LMMS
Loading...
Searching...
No Matches
juce_TextEditor.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
29// a word or space that can't be broken down any further
31{
32 //==============================================================================
34 float width;
36
37 //==============================================================================
39 bool isNewLine() const noexcept { return atomText[0] == '\r' || atomText[0] == '\n'; }
40
41 String getText (juce_wchar passwordCharacter) const
42 {
43 if (passwordCharacter == 0)
44 return atomText;
45
46 return String::repeatedString (String::charToString (passwordCharacter),
47 atomText.length());
48 }
49
50 String getTrimmedText (const juce_wchar passwordCharacter) const
51 {
52 if (passwordCharacter == 0)
53 return atomText.substring (0, numChars);
54
55 if (isNewLine())
56 return {};
57
58 return String::repeatedString (String::charToString (passwordCharacter), numChars);
59 }
60
62};
63
64//==============================================================================
65// a run of text with a single font and colour
67{
68public:
69 UniformTextSection (const String& text, const Font& f, Colour col, juce_wchar passwordCharToUse)
70 : font (f), colour (col), passwordChar (passwordCharToUse)
71 {
73 }
74
77
78 UniformTextSection& operator= (const UniformTextSection&) = delete;
79
81 {
82 if (! other.atoms.isEmpty())
83 {
84 int i = 0;
85
86 if (! atoms.isEmpty())
87 {
88 auto& lastAtom = atoms.getReference (atoms.size() - 1);
89
90 if (! CharacterFunctions::isWhitespace (lastAtom.atomText.getLastCharacter()))
91 {
92 auto& first = other.atoms.getReference(0);
93
94 if (! CharacterFunctions::isWhitespace (first.atomText[0]))
95 {
96 lastAtom.atomText += first.atomText;
97 lastAtom.numChars = (uint16) (lastAtom.numChars + first.numChars);
98 lastAtom.width = font.getStringWidthFloat (lastAtom.getText (passwordChar));
99 ++i;
100 }
101 }
102 }
103
104 atoms.ensureStorageAllocated (atoms.size() + other.atoms.size() - i);
105
106 while (i < other.atoms.size())
107 {
108 atoms.add (other.atoms.getReference(i));
109 ++i;
110 }
111 }
112 }
113
114 UniformTextSection* split (int indexToBreakAt)
115 {
116 auto* section2 = new UniformTextSection ({}, font, colour, passwordChar);
117 int index = 0;
118
119 for (int i = 0; i < atoms.size(); ++i)
120 {
121 auto& atom = atoms.getReference(i);
122 auto nextIndex = index + atom.numChars;
123
124 if (index == indexToBreakAt)
125 {
126 for (int j = i; j < atoms.size(); ++j)
127 section2->atoms.add (atoms.getUnchecked (j));
128
129 atoms.removeRange (i, atoms.size());
130 break;
131 }
132
133 if (indexToBreakAt >= index && indexToBreakAt < nextIndex)
134 {
135 TextAtom secondAtom;
136 secondAtom.atomText = atom.atomText.substring (indexToBreakAt - index);
137 secondAtom.width = font.getStringWidthFloat (secondAtom.getText (passwordChar));
138 secondAtom.numChars = (uint16) secondAtom.atomText.length();
139
140 section2->atoms.add (secondAtom);
141
142 atom.atomText = atom.atomText.substring (0, indexToBreakAt - index);
143 atom.width = font.getStringWidthFloat (atom.getText (passwordChar));
144 atom.numChars = (uint16) (indexToBreakAt - index);
145
146 for (int j = i + 1; j < atoms.size(); ++j)
147 section2->atoms.add (atoms.getUnchecked (j));
148
149 atoms.removeRange (i + 1, atoms.size());
150 break;
151 }
152
153 index = nextIndex;
154 }
155
156 return section2;
157 }
158
160 {
161 for (auto& atom : atoms)
162 mo << atom.atomText;
163 }
164
166 {
167 int index = 0;
168
169 for (auto& atom : atoms)
170 {
171 auto nextIndex = index + atom.numChars;
172
173 if (range.getStart() < nextIndex)
174 {
175 if (range.getEnd() <= index)
176 break;
177
178 auto r = (range - index).getIntersectionWith ({ 0, (int) atom.numChars });
179
180 if (! r.isEmpty())
181 mo << atom.atomText.substring (r.getStart(), r.getEnd());
182 }
183
184 index = nextIndex;
185 }
186 }
187
189 {
190 int total = 0;
191
192 for (auto& atom : atoms)
193 total += atom.numChars;
194
195 return total;
196 }
197
198 void setFont (const Font& newFont, const juce_wchar passwordCharToUse)
199 {
200 if (font != newFont || passwordChar != passwordCharToUse)
201 {
202 font = newFont;
203 passwordChar = passwordCharToUse;
204
205 for (auto& atom : atoms)
206 atom.width = newFont.getStringWidthFloat (atom.getText (passwordChar));
207 }
208 }
209
210 //==============================================================================
215
216private:
217 void initialiseAtoms (const String& textToParse)
218 {
219 auto text = textToParse.getCharPointer();
220
221 while (! text.isEmpty())
222 {
223 size_t numChars = 0;
224 auto start = text;
225
226 // create a whitespace atom unless it starts with non-ws
227 if (text.isWhitespace() && *text != '\r' && *text != '\n')
228 {
229 do
230 {
231 ++text;
232 ++numChars;
233 }
234 while (text.isWhitespace() && *text != '\r' && *text != '\n');
235 }
236 else
237 {
238 if (*text == '\r')
239 {
240 ++text;
241 ++numChars;
242
243 if (*text == '\n')
244 {
245 ++start;
246 ++text;
247 }
248 }
249 else if (*text == '\n')
250 {
251 ++text;
252 ++numChars;
253 }
254 else
255 {
256 while (! (text.isEmpty() || text.isWhitespace()))
257 {
258 ++text;
259 ++numChars;
260 }
261 }
262 }
263
264 TextAtom atom;
265 atom.atomText = String (start, numChars);
266 atom.width = (atom.isNewLine() ? 0.0f : font.getStringWidthFloat (atom.getText (passwordChar)));
267 atom.numChars = (uint16) numChars;
268 atoms.add (atom);
269 }
270 }
271
273};
274
275//==============================================================================
277{
279 : sections (ed.sections),
281 bottomRight ((float) ed.getMaximumTextWidth(), (float) ed.getMaximumTextHeight()),
282 wordWrapWidth ((float) ed.getWordWrapWidth()),
286 {
288
289 if (! sections.isEmpty())
290 {
291 currentSection = sections.getUnchecked (sectionIndex);
292
293 if (currentSection != nullptr)
294 beginNewLine();
295 }
296
298 }
299
300 Iterator (const Iterator&) = default;
301 Iterator& operator= (const Iterator&) = delete;
302
303 //==============================================================================
304 bool next()
305 {
306 if (atom == &longAtom && chunkLongAtom (true))
307 return true;
308
309 if (sectionIndex >= sections.size())
310 {
312 return false;
313 }
314
315 bool forceNewLine = false;
316
317 if (atomIndex >= currentSection->atoms.size() - 1)
318 {
319 if (atomIndex >= currentSection->atoms.size())
320 {
321 if (++sectionIndex >= sections.size())
322 {
324 return false;
325 }
326
327 atomIndex = 0;
328 currentSection = sections.getUnchecked (sectionIndex);
329 }
330 else
331 {
332 auto& lastAtom = currentSection->atoms.getReference (atomIndex);
333
334 if (! lastAtom.isWhitespace())
335 {
336 // handle the case where the last atom in a section is actually part of the same
337 // word as the first atom of the next section...
338 float right = atomRight + lastAtom.width;
339 float lineHeight2 = lineHeight;
340 float maxDescent2 = maxDescent;
341
342 for (int section = sectionIndex + 1; section < sections.size(); ++section)
343 {
344 auto* s = sections.getUnchecked (section);
345
346 if (s->atoms.size() == 0)
347 break;
348
349 auto& nextAtom = s->atoms.getReference (0);
350
351 if (nextAtom.isWhitespace())
352 break;
353
354 right += nextAtom.width;
355
356 lineHeight2 = jmax (lineHeight2, s->font.getHeight());
357 maxDescent2 = jmax (maxDescent2, s->font.getDescent());
358
359 if (shouldWrap (right))
360 {
361 lineHeight = lineHeight2;
362 maxDescent = maxDescent2;
363
364 forceNewLine = true;
365 break;
366 }
367
368 if (s->atoms.size() > 1)
369 break;
370 }
371 }
372 }
373 }
374
375 bool isInPreviousAtom = false;
376
377 if (atom != nullptr)
378 {
380 indexInText += atom->numChars;
381
382 if (atom->isNewLine())
383 beginNewLine();
384 else
385 isInPreviousAtom = true;
386 }
387
388 atom = &(currentSection->atoms.getReference (atomIndex));
389 atomRight = atomX + atom->width;
390 ++atomIndex;
391
392 if (shouldWrap (atomRight) || forceNewLine)
393 {
394 if (atom->isWhitespace())
395 {
396 // leave whitespace at the end of a line, but truncate it to avoid scrolling
398 }
399 else if (shouldWrap (atom->width)) // atom too big to fit on a line, so break it up..
400 {
401 longAtom = *atom;
402 longAtom.numChars = 0;
403 atom = &longAtom;
404 chunkLongAtom (isInPreviousAtom);
405 }
406 else
407 {
408 beginNewLine();
409 atomRight = atomX + atom->width;
410 }
411 }
412
413 return true;
414 }
415
417 {
419 float lineWidth = 0;
420
421 auto tempSectionIndex = sectionIndex;
422 auto tempAtomIndex = atomIndex;
423 auto* section = sections.getUnchecked (tempSectionIndex);
424
425 lineHeight = section->font.getHeight();
426 maxDescent = section->font.getDescent();
427
428 float nextLineWidth = (atom != nullptr) ? atom->width : 0.0f;
429
430 while (! shouldWrap (nextLineWidth))
431 {
432 lineWidth = nextLineWidth;
433
434 if (tempSectionIndex >= sections.size())
435 break;
436
437 bool checkSize = false;
438
439 if (tempAtomIndex >= section->atoms.size())
440 {
441 if (++tempSectionIndex >= sections.size())
442 break;
443
444 tempAtomIndex = 0;
445 section = sections.getUnchecked (tempSectionIndex);
446 checkSize = true;
447 }
448
449 if (! isPositiveAndBelow (tempAtomIndex, section->atoms.size()))
450 break;
451
452 auto& nextAtom = section->atoms.getReference (tempAtomIndex);
453 nextLineWidth += nextAtom.width;
454
455 if (shouldWrap (nextLineWidth) || nextAtom.isNewLine())
456 break;
457
458 if (checkSize)
459 {
460 lineHeight = jmax (lineHeight, section->font.getHeight());
461 maxDescent = jmax (maxDescent, section->font.getDescent());
462 }
463
464 ++tempAtomIndex;
465 }
466
467 atomX = getJustificationOffsetX (lineWidth);
468 }
469
470 float getJustificationOffsetX (float lineWidth) const
471 {
472 if (justification.testFlags (Justification::horizontallyCentred)) return jmax (0.0f, (bottomRight.x - lineWidth) * 0.5f);
473 if (justification.testFlags (Justification::right)) return jmax (0.0f, bottomRight.x - lineWidth);
474
475 return 0;
476 }
477
478 //==============================================================================
479 void draw (Graphics& g, const UniformTextSection*& lastSection, AffineTransform transform) const
480 {
481 if (atom == nullptr)
482 return;
483
484 if (passwordCharacter != 0 || (underlineWhitespace || ! atom->isWhitespace()))
485 {
486 if (lastSection != currentSection)
487 {
488 lastSection = currentSection;
489 g.setColour (currentSection->colour);
490 g.setFont (currentSection->font);
491 }
492
493 jassert (atom->getTrimmedText (passwordCharacter).isNotEmpty());
494
497 atom->getTrimmedText (passwordCharacter),
499 ga.draw (g, transform);
500 }
501 }
502
503 void drawUnderline (Graphics& g, Range<int> underline, Colour colour, AffineTransform transform) const
504 {
505 auto startX = roundToInt (indexToX (underline.getStart()));
506 auto endX = roundToInt (indexToX (underline.getEnd()));
507 auto baselineY = roundToInt (lineY + currentSection->font.getAscent() + 0.5f);
508
510 g.addTransform (transform);
511 g.reduceClipRegion ({ startX, baselineY, endX - startX, 1 });
512 g.fillCheckerBoard ({ (float) endX, (float) baselineY + 1.0f }, 3.0f, 1.0f, colour, Colours::transparentBlack);
513 }
514
515 void drawSelectedText (Graphics& g, Range<int> selected, Colour selectedTextColour, AffineTransform transform) const
516 {
517 if (atom == nullptr)
518 return;
519
520 if (passwordCharacter != 0 || ! atom->isWhitespace())
521 {
524 atom->getTrimmedText (passwordCharacter),
526
527 if (selected.getEnd() < indexInText + atom->numChars)
528 {
529 GlyphArrangement ga2 (ga);
530 ga2.removeRangeOfGlyphs (0, selected.getEnd() - indexInText);
531 ga.removeRangeOfGlyphs (selected.getEnd() - indexInText, -1);
532
533 g.setColour (currentSection->colour);
534 ga2.draw (g, transform);
535 }
536
537 if (selected.getStart() > indexInText)
538 {
539 GlyphArrangement ga2 (ga);
540 ga2.removeRangeOfGlyphs (selected.getStart() - indexInText, -1);
541 ga.removeRangeOfGlyphs (0, selected.getStart() - indexInText);
542
543 g.setColour (currentSection->colour);
544 ga2.draw (g, transform);
545 }
546
547 g.setColour (selectedTextColour);
548 ga.draw (g, transform);
549 }
550 }
551
552 //==============================================================================
553 float indexToX (int indexToFind) const
554 {
555 if (indexToFind <= indexInText || atom == nullptr)
556 return atomX;
557
558 if (indexToFind >= indexInText + atom->numChars)
559 return atomRight;
560
562 g.addLineOfText (currentSection->font,
563 atom->getText (passwordCharacter),
564 atomX, 0.0f);
565
566 if (indexToFind - indexInText >= g.getNumGlyphs())
567 return atomRight;
568
569 return jmin (atomRight, g.getGlyph (indexToFind - indexInText).getLeft());
570 }
571
572 int xToIndex (float xToFind) const
573 {
574 if (xToFind <= atomX || atom == nullptr || atom->isNewLine())
575 return indexInText;
576
577 if (xToFind >= atomRight)
578 return indexInText + atom->numChars;
579
581 g.addLineOfText (currentSection->font,
582 atom->getText (passwordCharacter),
583 atomX, 0.0f);
584
585 auto numGlyphs = g.getNumGlyphs();
586
587 int j;
588 for (j = 0; j < numGlyphs; ++j)
589 {
590 auto& pg = g.getGlyph(j);
591
592 if ((pg.getLeft() + pg.getRight()) / 2 > xToFind)
593 break;
594 }
595
596 return indexInText + j;
597 }
598
599 //==============================================================================
600 bool getCharPosition (int index, Point<float>& anchor, float& lineHeightFound)
601 {
602 while (next())
603 {
604 if (indexInText + atom->numChars > index)
605 {
606 anchor = { indexToX (index), lineY };
607 lineHeightFound = lineHeight;
608 return true;
609 }
610 }
611
612 anchor = { atomX, lineY };
613 lineHeightFound = lineHeight;
614 return false;
615 }
616
618 {
619 if (justification.testFlags (Justification::top) || lineY >= bottomRight.y)
620 return 0;
621
622 while (next())
623 {
624 if (lineY >= bottomRight.y)
625 return 0;
626 }
627
628 auto bottom = jmax (0.0f, bottomRight.y - lineY - lineHeight);
629
630 if (justification.testFlags (Justification::bottom))
631 return bottom;
632
633 return bottom * 0.5f;
634 }
635
637 {
638 while (next()) {}
639
640 auto height = lineY + lineHeight + getYOffset();
641
642 if (atom != nullptr && atom->isNewLine())
644
645 return roundToInt (height);
646 }
647
649 {
650 float maxWidth = 0.0f;
651
652 while (next())
653 maxWidth = jmax (maxWidth, atomRight);
654
655 return roundToInt (maxWidth);
656 }
657
659 {
660 auto startX = indexToX (range.getStart());
661 auto endX = indexToX (range.getEnd());
662
663 return Rectangle<float> (startX, lineY, endX - startX, lineHeight * lineSpacing).getSmallestIntegerContainer();
664 }
665
666 //==============================================================================
667 int indexInText = 0;
668 float lineY = 0, lineHeight = 0, maxDescent = 0;
669 float atomX = 0, atomRight = 0;
670 const TextAtom* atom = nullptr;
671
672private:
678 const float wordWrapWidth;
680 const float lineSpacing;
683
684 bool chunkLongAtom (bool shouldStartNewLine)
685 {
686 const auto numRemaining = longAtom.atomText.length() - longAtom.numChars;
687
688 if (numRemaining <= 0)
689 return false;
690
691 longAtom.atomText = longAtom.atomText.substring (longAtom.numChars);
692 indexInText += longAtom.numChars;
693
695 g.addLineOfText (currentSection->font, atom->getText (passwordCharacter), 0.0f, 0.0f);
696
697 int split;
698 for (split = 0; split < g.getNumGlyphs(); ++split)
699 if (shouldWrap (g.getGlyph (split).getRight()))
700 break;
701
702 const auto numChars = jmax (1, split);
703 longAtom.numChars = (uint16) numChars;
704 longAtom.width = g.getGlyph (numChars - 1).getRight();
705
707
708 if (shouldStartNewLine)
709 {
710 if (split == numRemaining)
711 beginNewLine();
712 else
714 }
715
716 atomRight = atomX + longAtom.width;
717 return true;
718 }
719
721 {
722 if (atom != nullptr)
723 {
725
726 if (atom->isNewLine())
727 {
730 }
731 }
732 }
733
734 bool shouldWrap (const float x) const noexcept
735 {
736 return (x - 0.0001f) >= wordWrapWidth;
737 }
738
740};
741
742
743//==============================================================================
745{
746 InsertAction (TextEditor& ed, const String& newText, int insertPos,
747 const Font& newFont, Colour newColour, int oldCaret, int newCaret)
748 : owner (ed),
749 text (newText),
750 insertIndex (insertPos),
751 oldCaretPos (oldCaret),
752 newCaretPos (newCaret),
753 font (newFont),
754 colour (newColour)
755 {
756 }
757
758 bool perform() override
759 {
760 owner.insert (text, insertIndex, font, colour, nullptr, newCaretPos);
761 return true;
762 }
763
764 bool undo() override
765 {
766 owner.remove ({ insertIndex, insertIndex + text.length() }, nullptr, oldCaretPos);
767 return true;
768 }
769
770 int getSizeInUnits() override
771 {
772 return text.length() + 16;
773 }
774
775private:
779 const Font font;
781
783};
784
785//==============================================================================
787{
788 RemoveAction (TextEditor& ed, Range<int> rangeToRemove, int oldCaret, int newCaret,
789 const Array<UniformTextSection*>& oldSections)
790 : owner (ed),
791 range (rangeToRemove),
792 oldCaretPos (oldCaret),
793 newCaretPos (newCaret)
794 {
795 removedSections.addArray (oldSections);
796 }
797
798 bool perform() override
799 {
800 owner.remove (range, nullptr, newCaretPos);
801 return true;
802 }
803
804 bool undo() override
805 {
806 owner.reinsert (range.getStart(), removedSections);
807 owner.moveCaretTo (oldCaretPos, false);
808 return true;
809 }
810
811 int getSizeInUnits() override
812 {
813 int n = 16;
814
815 for (auto* s : removedSections)
816 n += s->getTotalLength();
817
818 return n;
819 }
820
821private:
826
828};
829
830//==============================================================================
832 public Timer,
833 public Value::Listener
834{
836 {
837 setWantsKeyboardFocus (false);
838 setInterceptsMouseClicks (false, true);
840
841 owner.getTextValue().addListener (this);
842 }
843
845 {
846 owner.getTextValue().removeListener (this);
847 }
848
849 void paint (Graphics& g) override
850 {
851 owner.drawContent (g);
852 }
853
855 {
856 startTimer (350);
857 }
858
859 void timerCallback() override
860 {
861 owner.timerCallbackInt();
862 }
863
864 void valueChanged (Value&) override
865 {
866 owner.textWasChangedByValue();
867 }
868
870
871private:
872 std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
873 {
875 }
876
878};
879
880//==============================================================================
882{
884
885 void visibleAreaChanged (const Rectangle<int>&) override
886 {
887 if (! reentrant) // it's rare, but possible to get into a feedback loop as the viewport's scrollbars
888 // appear and disappear, causing the wrap width to change.
889 {
890 auto wordWrapWidth = owner.getWordWrapWidth();
891
892 if (wordWrapWidth != lastWordWrapWidth)
893 {
894 lastWordWrapWidth = wordWrapWidth;
895
897 owner.checkLayout();
898 }
899 }
900 }
901
902private:
903 std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
904 {
906 }
907
910 bool reentrant = false;
911
913};
914
915//==============================================================================
917{
918 const int textChangeMessageId = 0x10003001;
919 const int returnKeyMessageId = 0x10003002;
920 const int escapeKeyMessageId = 0x10003003;
921 const int focusLossMessageId = 0x10003004;
922
924
925 static int getCharacterCategory (juce_wchar character) noexcept
926 {
927 return CharacterFunctions::isLetterOrDigit (character)
928 ? 2 : (CharacterFunctions::isWhitespace (character) ? 0 : 1);
929 }
930}
931
932//==============================================================================
934 : Component (name),
935 passwordCharacter (passwordChar)
936{
938
939 viewport.reset (new TextEditorViewport (*this));
941 viewport->setViewedComponent (textHolder = new TextHolderComponent (*this));
942 viewport->setWantsKeyboardFocus (false);
943 viewport->setScrollBarsShown (false, false);
944
947
948 juce::Desktop::getInstance().addGlobalMouseListener (this);
949}
950
952{
953 juce::Desktop::getInstance().removeGlobalMouseListener (this);
954
955 textValue.removeListener (textHolder);
956 textValue.referTo (Value());
957
958 viewport.reset();
959 textHolder = nullptr;
960}
961
962//==============================================================================
968
969bool TextEditor::undoOrRedo (const bool shouldUndo)
970{
971 if (! isReadOnly())
972 {
974
975 if (shouldUndo ? undoManager.undo()
976 : undoManager.redo())
977 {
978 repaint();
979 textChanged();
981
982 return true;
983 }
984 }
985
986 return false;
987}
988
989bool TextEditor::undo() { return undoOrRedo (true); }
990bool TextEditor::redo() { return undoOrRedo (false); }
991
992//==============================================================================
993void TextEditor::setMultiLine (const bool shouldBeMultiLine,
994 const bool shouldWordWrap)
995{
996 if (multiline != shouldBeMultiLine
997 || wordWrap != (shouldWordWrap && shouldBeMultiLine))
998 {
999 multiline = shouldBeMultiLine;
1000 wordWrap = shouldWordWrap && shouldBeMultiLine;
1001
1002 checkLayout();
1003
1004 viewport->setViewPosition (0, 0);
1005 resized();
1007 }
1008}
1009
1011{
1012 return multiline;
1013}
1014
1016{
1017 if (scrollbarVisible != shown)
1018 {
1019 scrollbarVisible = shown;
1020 checkLayout();
1021 }
1022}
1023
1024void TextEditor::setReadOnly (bool shouldBeReadOnly)
1025{
1026 if (readOnly != shouldBeReadOnly)
1027 {
1028 readOnly = shouldBeReadOnly;
1031
1032 if (auto* peer = getPeer())
1033 peer->refreshTextInputTarget();
1034 }
1035}
1036
1041
1043{
1044 return readOnly || ! isEnabled();
1045}
1046
1051
1052void TextEditor::setReturnKeyStartsNewLine (bool shouldStartNewLine)
1053{
1054 returnKeyStartsNewLine = shouldStartNewLine;
1055}
1056
1057void TextEditor::setTabKeyUsedAsCharacter (bool shouldTabKeyBeUsed)
1058{
1059 tabKeyUsed = shouldTabKeyBeUsed;
1060}
1061
1063{
1065}
1066
1071
1073{
1074 if (justification != j)
1075 {
1076 justification = j;
1077
1078 resized();
1079 repaint();
1080 }
1081}
1082
1083//==============================================================================
1084void TextEditor::setFont (const Font& newFont)
1085{
1086 currentFont = newFont;
1088}
1089
1090void TextEditor::applyFontToAllText (const Font& newFont, bool changeCurrentFont)
1091{
1092 if (changeCurrentFont)
1093 currentFont = newFont;
1094
1095 auto overallColour = findColour (textColourId);
1096
1097 for (auto* uts : sections)
1098 {
1099 uts->setFont (newFont, passwordCharacter);
1100 uts->colour = overallColour;
1101 }
1102
1104 checkLayout();
1106 repaint();
1107}
1108
1109void TextEditor::applyColourToAllText (const Colour& newColour, bool changeCurrentTextColour)
1110{
1111 for (auto* uts : sections)
1112 uts->colour = newColour;
1113
1114 if (changeCurrentTextColour)
1116 else
1117 repaint();
1118}
1119
1121{
1122 caret.reset();
1123 recreateCaret();
1124 repaint();
1125}
1126
1131
1133{
1134 recreateCaret();
1135 repaint();
1136}
1137
1138void TextEditor::setCaretVisible (bool shouldCaretBeVisible)
1139{
1140 if (caretVisible != shouldCaretBeVisible)
1141 {
1142 caretVisible = shouldCaretBeVisible;
1143 recreateCaret();
1144 }
1145}
1146
1148{
1149 if (isCaretVisible())
1150 {
1151 if (caret == nullptr)
1152 {
1153 caret.reset (getLookAndFeel().createCaretComponent (this));
1154 textHolder->addChildComponent (caret.get());
1156 }
1157 }
1158 else
1159 {
1160 caret.reset();
1161 }
1162}
1163
1165{
1166 if (caret != nullptr
1167 && getWidth() > 0 && getHeight() > 0)
1168 {
1169 Iterator i (*this);
1170 caret->setCaretPosition (getCaretRectangle().translated (leftIndent,
1171 topIndent + roundToInt (i.getYOffset())));
1172
1173 if (auto* handler = getAccessibilityHandler())
1174 handler->notifyAccessibilityEvent (AccessibilityEvent::textSelectionChanged);
1175 }
1176}
1177
1182
1184{
1185 String t (newInput);
1186
1187 if (allowedCharacters.isNotEmpty())
1188 t = t.retainCharacters (allowedCharacters);
1189
1190 if (maxLength > 0)
1191 t = t.substring (0, maxLength - (ed.getTotalNumChars() - ed.getHighlightedRegion().getLength()));
1192
1193 return t;
1194}
1195
1196void TextEditor::setInputFilter (InputFilter* newFilter, bool takeOwnership)
1197{
1198 inputFilter.set (newFilter, takeOwnership);
1199}
1200
1201void TextEditor::setInputRestrictions (int maxLen, const String& chars)
1202{
1203 setInputFilter (new LengthAndCharacterRestriction (maxLen, chars), true);
1204}
1205
1207{
1209 colourForTextWhenEmpty = colourToUse;
1210}
1211
1213{
1214 if (passwordCharacter != newPasswordCharacter)
1215 {
1216 passwordCharacter = newPasswordCharacter;
1218 }
1219}
1220
1221void TextEditor::setScrollBarThickness (int newThicknessPixels)
1222{
1223 viewport->setScrollBarThickness (newThicknessPixels);
1224}
1225
1226//==============================================================================
1228{
1229 clearInternal (nullptr);
1230 checkLayout();
1231 undoManager.clearUndoHistory();
1232}
1233
1234void TextEditor::setText (const String& newText, bool sendTextChangeMessage)
1235{
1236 auto newLength = newText.length();
1237
1238 if (newLength != getTotalNumChars() || getText() != newText)
1239 {
1240 if (! sendTextChangeMessage)
1241 textValue.removeListener (textHolder);
1242
1243 textValue = newText;
1244
1245 auto oldCursorPos = caretPosition;
1246 bool cursorWasAtEnd = oldCursorPos >= getTotalNumChars();
1247
1248 clearInternal (nullptr);
1249 insert (newText, 0, currentFont, findColour (textColourId), nullptr, caretPosition);
1250
1251 // if you're adding text with line-feeds to a single-line text editor, it
1252 // ain't gonna look right!
1253 jassert (multiline || ! newText.containsAnyOf ("\r\n"));
1254
1255 if (cursorWasAtEnd && ! isMultiLine())
1256 oldCursorPos = getTotalNumChars();
1257
1258 moveCaretTo (oldCursorPos, false);
1259
1260 if (sendTextChangeMessage)
1261 textChanged();
1262 else
1263 textValue.addListener (textHolder);
1264
1265 checkLayout();
1267 undoManager.clearUndoHistory();
1268
1269 repaint();
1270 }
1271}
1272
1273//==============================================================================
1275{
1277 {
1278 valueTextNeedsUpdating = false;
1279 textValue = getText();
1280 }
1281}
1282
1288
1290{
1291 if (textValue.getValueSource().getReferenceCount() > 1)
1292 setText (textValue.getValue());
1293}
1294
1295//==============================================================================
1297{
1298 checkLayout();
1299
1300 if (listeners.size() != 0 || onTextChange != nullptr)
1302
1303 if (textValue.getValueSource().getReferenceCount() > 1)
1304 {
1305 valueTextNeedsUpdating = false;
1306 textValue = getText();
1307 }
1308
1309 if (auto* handler = getAccessibilityHandler())
1310 handler->notifyAccessibilityEvent (AccessibilityEvent::textChanged);
1311}
1312
1313void TextEditor::setSelection (Range<int> newSelection) noexcept
1314{
1315 if (newSelection != selection)
1316 {
1317 selection = newSelection;
1318
1319 if (auto* handler = getAccessibilityHandler())
1320 handler->notifyAccessibilityEvent (AccessibilityEvent::textSelectionChanged);
1321 }
1322}
1323
1326
1329
1330//==============================================================================
1332{
1333 checkFocus();
1334
1336
1337 if (now > lastTransactionTime + 200)
1339}
1340
1346
1348{
1349 if (! range.isEmpty())
1350 {
1351 if (range.getEnd() >= getTotalNumChars())
1352 {
1353 textHolder->repaint();
1354 return;
1355 }
1356
1357 Iterator i (*this);
1358
1359 Point<float> anchor;
1360 auto lh = currentFont.getHeight();
1361 i.getCharPosition (range.getStart(), anchor, lh);
1362
1363 auto y1 = std::trunc (anchor.y);
1364 int y2 = 0;
1365
1366 if (range.getEnd() >= getTotalNumChars())
1367 {
1368 y2 = textHolder->getHeight();
1369 }
1370 else
1371 {
1372 i.getCharPosition (range.getEnd(), anchor, lh);
1373 y2 = (int) (anchor.y + lh * 2.0f);
1374 }
1375
1376 auto offset = i.getYOffset();
1377 textHolder->repaint (0, roundToInt (y1 + offset), textHolder->getWidth(), roundToInt ((float) y2 - y1 + offset));
1378 }
1379}
1380
1381//==============================================================================
1382void TextEditor::moveCaret (int newCaretPos)
1383{
1384 if (newCaretPos < 0)
1385 newCaretPos = 0;
1386 else
1387 newCaretPos = jmin (newCaretPos, getTotalNumChars());
1388
1389 if (newCaretPos != getCaretPosition())
1390 {
1391 caretPosition = newCaretPos;
1392
1393 if (hasKeyboardFocus (false))
1394 textHolder->restartTimer();
1395
1398
1399 if (auto* handler = getAccessibilityHandler())
1400 handler->notifyAccessibilityEvent (AccessibilityEvent::textChanged);
1401 }
1402}
1403
1405{
1406 return caretPosition;
1407}
1408
1409void TextEditor::setCaretPosition (const int newIndex)
1410{
1411 moveCaretTo (newIndex, false);
1412}
1413
1415{
1416 setCaretPosition (std::numeric_limits<int>::max());
1417}
1418
1419void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX,
1420 const int desiredCaretY)
1421
1422{
1424 auto caretRect = getCaretRectangle().translated (leftIndent, topIndent);
1425
1426 auto vx = caretRect.getX() - desiredCaretX;
1427 auto vy = caretRect.getY() - desiredCaretY;
1428
1429 if (desiredCaretX < jmax (1, proportionOfWidth (0.05f)))
1430 vx += desiredCaretX - proportionOfWidth (0.2f);
1431 else if (desiredCaretX > jmax (0, viewport->getMaximumVisibleWidth() - (wordWrap ? 2 : 10)))
1432 vx += desiredCaretX + (isMultiLine() ? proportionOfWidth (0.2f) : 10) - viewport->getMaximumVisibleWidth();
1433
1434 vx = jlimit (0, jmax (0, textHolder->getWidth() + 8 - viewport->getMaximumVisibleWidth()), vx);
1435
1436 if (! isMultiLine())
1437 {
1438 vy = viewport->getViewPositionY();
1439 }
1440 else
1441 {
1442 vy = jlimit (0, jmax (0, textHolder->getHeight() - viewport->getMaximumVisibleHeight()), vy);
1443
1444 if (desiredCaretY < 0)
1445 vy = jmax (0, desiredCaretY + vy);
1446 else if (desiredCaretY > jmax (0, viewport->getMaximumVisibleHeight() - caretRect.getHeight()))
1447 vy += desiredCaretY + 2 + caretRect.getHeight() - viewport->getMaximumVisibleHeight();
1448 }
1449
1450 viewport->setViewPosition (vx, vy);
1451}
1452
1454{
1455 return getCaretRectangleFloat().getSmallestIntegerContainer();
1456}
1457
1459{
1460 Point<float> anchor;
1461 auto cursorHeight = currentFont.getHeight(); // (in case the text is empty and the call below doesn't set this value)
1462 getCharPosition (caretPosition, anchor, cursorHeight);
1463
1464 return { anchor.x, anchor.y, 2.0f, cursorHeight };
1465}
1466
1468{
1469 Iterator i (*this);
1470 auto yOffset = i.getYOffset();
1471
1472 return { getLeftIndent() + borderSize.getLeft() - viewport->getViewPositionX(),
1473 roundToInt ((float) getTopIndent() + (float) borderSize.getTop() + yOffset) - viewport->getViewPositionY() };
1474}
1475
1477{
1478 RectangleList<int> boundingBox;
1479 Iterator i (*this);
1480
1481 while (i.next())
1482 {
1483 if (textRange.intersects ({ i.indexInText,
1484 i.indexInText + i.atom->numChars }))
1485 {
1486 boundingBox.add (i.getTextBounds (textRange));
1487 }
1488 }
1489
1490 boundingBox.offsetAll (getTextOffset());
1491 return boundingBox;
1492}
1493
1494//==============================================================================
1495// Extra space for the cursor at the right-hand-edge
1496constexpr int rightEdgeSpace = 2;
1497
1499{
1500 return wordWrap ? getMaximumTextWidth()
1501 : std::numeric_limits<int>::max();
1502}
1503
1505{
1506 return jmax (1, viewport->getMaximumVisibleWidth() - leftIndent - rightEdgeSpace);
1507}
1508
1510{
1511 return jmax (1, viewport->getMaximumVisibleHeight() - topIndent);
1512}
1513
1515{
1516 if (getWordWrapWidth() > 0)
1517 {
1518 const auto textBottom = Iterator (*this).getTotalTextHeight() + topIndent;
1519 const auto textRight = jmax (viewport->getMaximumVisibleWidth(),
1521
1522 textHolder->setSize (textRight, textBottom);
1523 viewport->setScrollBarsShown (scrollbarVisible && multiline && textBottom > viewport->getMaximumVisibleHeight(),
1524 scrollbarVisible && multiline && ! wordWrap && textRight > viewport->getMaximumVisibleWidth());
1525 }
1526}
1527
1528int TextEditor::getTextWidth() const { return textHolder->getWidth(); }
1529int TextEditor::getTextHeight() const { return textHolder->getHeight(); }
1530
1531void TextEditor::setIndents (int newLeftIndent, int newTopIndent)
1532{
1533 if (leftIndent != newLeftIndent || topIndent != newTopIndent)
1534 {
1535 leftIndent = newLeftIndent;
1536 topIndent = newTopIndent;
1537
1538 resized();
1539 repaint();
1540 }
1541}
1542
1548
1550{
1551 return borderSize;
1552}
1553
1554void TextEditor::setScrollToShowCursor (const bool shouldScrollToShowCursor)
1555{
1556 keepCaretOnScreen = shouldScrollToShowCursor;
1557}
1558
1560{
1562
1564 {
1565 auto viewPos = viewport->getViewPosition();
1566 auto caretRect = getCaretRectangle().translated (leftIndent, topIndent);
1567 auto relativeCursor = caretRect.getPosition() - viewPos;
1568
1569 if (relativeCursor.x < jmax (1, proportionOfWidth (0.05f)))
1570 {
1571 viewPos.x += relativeCursor.x - proportionOfWidth (0.2f);
1572 }
1573 else if (relativeCursor.x > jmax (0, viewport->getMaximumVisibleWidth() - (wordWrap ? 2 : 10)))
1574 {
1575 viewPos.x += relativeCursor.x + (isMultiLine() ? proportionOfWidth (0.2f) : 10) - viewport->getMaximumVisibleWidth();
1576 }
1577
1578 viewPos.x = jlimit (0, jmax (0, textHolder->getWidth() + 8 - viewport->getMaximumVisibleWidth()), viewPos.x);
1579
1580 if (! isMultiLine())
1581 {
1582 viewPos.y = (getHeight() - textHolder->getHeight() - topIndent) / -2;
1583 }
1584 else if (relativeCursor.y < 0)
1585 {
1586 viewPos.y = jmax (0, relativeCursor.y + viewPos.y);
1587 }
1588 else if (relativeCursor.y > jmax (0, viewport->getMaximumVisibleHeight() - caretRect.getHeight()))
1589 {
1590 viewPos.y += relativeCursor.y + 2 + caretRect.getHeight() - viewport->getMaximumVisibleHeight();
1591 }
1592
1593 viewport->setViewPosition (viewPos);
1594 }
1595}
1596
1597void TextEditor::moveCaretTo (const int newPosition, const bool isSelecting)
1598{
1599 if (isSelecting)
1600 {
1601 moveCaret (newPosition);
1602
1603 auto oldSelection = selection;
1604
1605 if (dragType == notDragging)
1606 {
1607 if (std::abs (getCaretPosition() - selection.getStart()) < std::abs (getCaretPosition() - selection.getEnd()))
1609 else
1611 }
1612
1614 {
1615 if (getCaretPosition() >= selection.getEnd())
1617
1619 }
1620 else
1621 {
1622 if (getCaretPosition() < selection.getStart())
1624
1626 }
1627
1628 repaintText (selection.getUnionWith (oldSelection));
1629 }
1630 else
1631 {
1633
1635
1636 moveCaret (newPosition);
1638 }
1639}
1640
1641int TextEditor::getTextIndexAt (const int x, const int y) const
1642{
1643 const auto offset = getTextOffset();
1644
1645 return indexAtPosition ((float) (x - offset.x),
1646 (float) (y - offset.y));
1647}
1648
1650{
1651 String newText (inputFilter != nullptr ? inputFilter->filterNewText (*this, t) : t);
1652
1653 if (isMultiLine())
1654 newText = newText.replace ("\r\n", "\n");
1655 else
1656 newText = newText.replaceCharacters ("\r\n", " ");
1657
1658 const int insertIndex = selection.getStart();
1659 const int newCaretPos = insertIndex + newText.length();
1660
1662 newText.isNotEmpty() ? newCaretPos - 1 : newCaretPos);
1663
1664 insert (newText, insertIndex, currentFont, findColour (textColourId),
1665 getUndoManager(), newCaretPos);
1666
1667 textChanged();
1668}
1669
1671{
1672 moveCaretTo (newSelection.getStart(), false);
1673 moveCaretTo (newSelection.getEnd(), true);
1674}
1675
1676//==============================================================================
1678{
1679 if (passwordCharacter == 0)
1680 {
1681 auto selectedText = getHighlightedText();
1682
1683 if (selectedText.isNotEmpty())
1685 }
1686}
1687
1689{
1690 if (! isReadOnly())
1691 {
1693
1694 if (clip.isNotEmpty())
1695 insertTextAtCaret (clip);
1696 }
1697}
1698
1700{
1701 if (! isReadOnly())
1702 {
1703 moveCaret (selection.getEnd());
1705 }
1706}
1707
1708//==============================================================================
1710{
1711 if (getWordWrapWidth() > 0)
1712 {
1713 g.setOrigin (leftIndent, topIndent);
1714 auto clip = g.getClipBounds();
1715
1716 auto yOffset = Iterator (*this).getYOffset();
1717
1718 AffineTransform transform;
1719
1720 if (yOffset > 0)
1721 {
1722 transform = AffineTransform::translation (0.0f, yOffset);
1723 clip.setY (roundToInt ((float) clip.getY() - yOffset));
1724 }
1725
1726 Iterator i (*this);
1727 Colour selectedTextColour;
1728
1729 if (! selection.isEmpty())
1730 {
1731 selectedTextColour = findColour (highlightedTextColourId);
1732
1733 g.setColour (findColour (highlightColourId).withMultipliedAlpha (hasKeyboardFocus (true) ? 1.0f : 0.5f));
1734
1735 auto boundingBox = getTextBounds (selection);
1736 boundingBox.offsetAll (-getTextOffset());
1737
1738 g.fillPath (boundingBox.toPath(), transform);
1739 }
1740
1741 const UniformTextSection* lastSection = nullptr;
1742
1743 while (i.next() && i.lineY < (float) clip.getBottom())
1744 {
1745 if (i.lineY + i.lineHeight >= (float) clip.getY())
1746 {
1747 if (selection.intersects ({ i.indexInText, i.indexInText + i.atom->numChars }))
1748 {
1749 i.drawSelectedText (g, selection, selectedTextColour, transform);
1750 lastSection = nullptr;
1751 }
1752 else
1753 {
1754 i.draw (g, lastSection, transform);
1755 }
1756 }
1757 }
1758
1759 for (auto& underlinedSection : underlinedSections)
1760 {
1761 Iterator i2 (*this);
1762
1763 while (i2.next() && i2.lineY < (float) clip.getBottom())
1764 {
1765 if (i2.lineY + i2.lineHeight >= (float) clip.getY()
1766 && underlinedSection.intersects ({ i2.indexInText, i2.indexInText + i2.atom->numChars }))
1767 {
1768 i2.drawUnderline (g, underlinedSection, findColour (textColourId), transform);
1769 }
1770 }
1771 }
1772 }
1773}
1774
1776{
1777 getLookAndFeel().fillTextEditorBackground (g, getWidth(), getHeight(), *this);
1778}
1779
1781{
1782 if (textToShowWhenEmpty.isNotEmpty()
1783 && (! hasKeyboardFocus (false))
1784 && getTotalNumChars() == 0)
1785 {
1786 g.setColour (colourForTextWhenEmpty);
1787 g.setFont (getFont());
1788
1789 Rectangle<int> textBounds (leftIndent,
1790 topIndent,
1791 viewport->getWidth() - leftIndent,
1792 getHeight() - topIndent);
1793
1794 if (! textBounds.isEmpty())
1795 g.drawText (textToShowWhenEmpty, textBounds, justification, true);
1796 }
1797
1798 getLookAndFeel().drawTextEditorOutline (g, getWidth(), getHeight(), *this);
1799}
1800
1801//==============================================================================
1803{
1804 const bool writable = ! isReadOnly();
1805
1806 if (passwordCharacter == 0)
1807 {
1808 m.addItem (StandardApplicationCommandIDs::cut, TRANS("Cut"), writable);
1809 m.addItem (StandardApplicationCommandIDs::copy, TRANS("Copy"), ! selection.isEmpty());
1810 }
1811
1812 m.addItem (StandardApplicationCommandIDs::paste, TRANS("Paste"), writable);
1813 m.addItem (StandardApplicationCommandIDs::del, TRANS("Delete"), writable);
1814 m.addSeparator();
1815 m.addItem (StandardApplicationCommandIDs::selectAll, TRANS("Select All"));
1816 m.addSeparator();
1817
1818 if (getUndoManager() != nullptr)
1819 {
1820 m.addItem (StandardApplicationCommandIDs::undo, TRANS("Undo"), undoManager.canUndo());
1821 m.addItem (StandardApplicationCommandIDs::redo, TRANS("Redo"), undoManager.canRedo());
1822 }
1823}
1824
1825void TextEditor::performPopupMenuAction (const int menuItemID)
1826{
1827 switch (menuItemID)
1828 {
1836 default: break;
1837 }
1838}
1839
1840//==============================================================================
1842{
1843 mouseDownInEditor = e.originalComponent == this;
1844
1845 if (! mouseDownInEditor)
1846 return;
1847
1848 beginDragAutoRepeat (100);
1850
1852 {
1853 if (! (popupMenuEnabled && e.mods.isPopupMenu()))
1854 {
1855 moveCaretTo (getTextIndexAt (e.x, e.y),
1856 e.mods.isShiftDown());
1857
1858 if (auto* peer = getPeer())
1859 peer->closeInputMethodContext();
1860 }
1861 else
1862 {
1863 PopupMenu m;
1864 m.setLookAndFeel (&getLookAndFeel());
1865 addPopupMenuItems (m, &e);
1866
1867 menuActive = true;
1868
1869 m.showMenuAsync (PopupMenu::Options(),
1870 [safeThis = SafePointer<TextEditor> { this }] (int menuResult)
1871 {
1872 if (auto* editor = safeThis.getComponent())
1873 {
1874 editor->menuActive = false;
1875
1876 if (menuResult != 0)
1877 editor->performPopupMenuAction (menuResult);
1878 }
1879 });
1880 }
1881 }
1882}
1883
1885{
1886 if (! mouseDownInEditor)
1887 return;
1888
1890 if (! (popupMenuEnabled && e.mods.isPopupMenu()))
1891 moveCaretTo (getTextIndexAt (e.x, e.y), true);
1892}
1893
1895{
1896 if (! mouseDownInEditor)
1897 return;
1898
1900 textHolder->restartTimer();
1901
1903 if (e.mouseWasClicked() && ! (popupMenuEnabled && e.mods.isPopupMenu()))
1904 moveCaret (getTextIndexAt (e.x, e.y));
1905
1906 wasFocused = true;
1907}
1908
1910{
1911 if (! mouseDownInEditor)
1912 return;
1913
1914 int tokenEnd = getTextIndexAt (e.x, e.y);
1915 int tokenStart = 0;
1916
1917 if (e.getNumberOfClicks() > 3)
1918 {
1919 tokenEnd = getTotalNumChars();
1920 }
1921 else
1922 {
1923 auto t = getText();
1924 auto totalLength = getTotalNumChars();
1925
1926 while (tokenEnd < totalLength)
1927 {
1928 auto c = t[tokenEnd];
1929
1930 // (note the slight bodge here - it's because iswalnum only checks for alphabetic chars in the current locale)
1932 ++tokenEnd;
1933 else
1934 break;
1935 }
1936
1937 tokenStart = tokenEnd;
1938
1939 while (tokenStart > 0)
1940 {
1941 auto c = t[tokenStart - 1];
1942
1943 // (note the slight bodge here - it's because iswalnum only checks for alphabetic chars in the current locale)
1945 --tokenStart;
1946 else
1947 break;
1948 }
1949
1950 if (e.getNumberOfClicks() > 2)
1951 {
1952 while (tokenEnd < totalLength)
1953 {
1954 auto c = t[tokenEnd];
1955
1956 if (c != '\r' && c != '\n')
1957 ++tokenEnd;
1958 else
1959 break;
1960 }
1961
1962 while (tokenStart > 0)
1963 {
1964 auto c = t[tokenStart - 1];
1965
1966 if (c != '\r' && c != '\n')
1967 --tokenStart;
1968 else
1969 break;
1970 }
1971 }
1972 }
1973
1974 moveCaretTo (tokenEnd, false);
1975 moveCaretTo (tokenStart, true);
1976}
1977
1979{
1980 if (! mouseDownInEditor)
1981 return;
1982
1983 if (! viewport->useMouseWheelMoveIfNeeded (e, wheel))
1985}
1986
1987//==============================================================================
1988bool TextEditor::moveCaretWithTransaction (const int newPos, const bool selecting)
1989{
1991 moveCaretTo (newPos, selecting);
1992
1993 if (auto* peer = getPeer())
1994 peer->closeInputMethodContext();
1995
1996 return true;
1997}
1998
1999bool TextEditor::moveCaretLeft (bool moveInWholeWordSteps, bool selecting)
2000{
2001 auto pos = getCaretPosition();
2002
2003 if (moveInWholeWordSteps)
2004 pos = findWordBreakBefore (pos);
2005 else
2006 --pos;
2007
2008 return moveCaretWithTransaction (pos, selecting);
2009}
2010
2011bool TextEditor::moveCaretRight (bool moveInWholeWordSteps, bool selecting)
2012{
2013 auto pos = getCaretPosition();
2014
2015 if (moveInWholeWordSteps)
2016 pos = findWordBreakAfter (pos);
2017 else
2018 ++pos;
2019
2020 return moveCaretWithTransaction (pos, selecting);
2021}
2022
2023bool TextEditor::moveCaretUp (bool selecting)
2024{
2025 if (! isMultiLine())
2026 return moveCaretToStartOfLine (selecting);
2027
2028 auto caretPos = getCaretRectangleFloat();
2029 return moveCaretWithTransaction (indexAtPosition (caretPos.getX(), caretPos.getY() - 1.0f), selecting);
2030}
2031
2032bool TextEditor::moveCaretDown (bool selecting)
2033{
2034 if (! isMultiLine())
2035 return moveCaretToEndOfLine (selecting);
2036
2037 auto caretPos = getCaretRectangleFloat();
2038 return moveCaretWithTransaction (indexAtPosition (caretPos.getX(), caretPos.getBottom() + 1.0f), selecting);
2039}
2040
2041bool TextEditor::pageUp (bool selecting)
2042{
2043 if (! isMultiLine())
2044 return moveCaretToStartOfLine (selecting);
2045
2046 auto caretPos = getCaretRectangleFloat();
2047 return moveCaretWithTransaction (indexAtPosition (caretPos.getX(), caretPos.getY() - (float) viewport->getViewHeight()), selecting);
2048}
2049
2050bool TextEditor::pageDown (bool selecting)
2051{
2052 if (! isMultiLine())
2053 return moveCaretToEndOfLine (selecting);
2054
2055 auto caretPos = getCaretRectangleFloat();
2056 return moveCaretWithTransaction (indexAtPosition (caretPos.getX(), caretPos.getBottom() + (float) viewport->getViewHeight()), selecting);
2057}
2058
2059void TextEditor::scrollByLines (int deltaLines)
2060{
2061 viewport->getVerticalScrollBar().moveScrollbarInSteps (deltaLines);
2062}
2063
2065{
2066 scrollByLines (-1);
2067 return true;
2068}
2069
2071{
2072 scrollByLines (1);
2073 return true;
2074}
2075
2076bool TextEditor::moveCaretToTop (bool selecting)
2077{
2078 return moveCaretWithTransaction (0, selecting);
2079}
2080
2082{
2083 auto caretPos = getCaretRectangleFloat();
2084 return moveCaretWithTransaction (indexAtPosition (0.0f, caretPos.getY()), selecting);
2085}
2086
2087bool TextEditor::moveCaretToEnd (bool selecting)
2088{
2089 return moveCaretWithTransaction (getTotalNumChars(), selecting);
2090}
2091
2093{
2094 auto caretPos = getCaretRectangleFloat();
2095 return moveCaretWithTransaction (indexAtPosition ((float) textHolder->getWidth(), caretPos.getY()), selecting);
2096}
2097
2098bool TextEditor::deleteBackwards (bool moveInWholeWordSteps)
2099{
2100 if (moveInWholeWordSteps)
2102 else if (selection.isEmpty() && selection.getStart() > 0)
2103 setSelection ({ selection.getEnd() - 1, selection.getEnd() });
2104
2105 cut();
2106 return true;
2107}
2108
2109bool TextEditor::deleteForwards (bool /*moveInWholeWordSteps*/)
2110{
2111 if (selection.isEmpty() && selection.getStart() < getTotalNumChars())
2112 setSelection ({ selection.getStart(), selection.getStart() + 1 });
2113
2114 cut();
2115 return true;
2116}
2117
2119{
2121 copy();
2122 return true;
2123}
2124
2126{
2128 copy();
2129 cut();
2130 return true;
2131}
2132
2134{
2136 paste();
2137 return true;
2138}
2139
2141{
2143 moveCaretTo (getTotalNumChars(), false);
2144 moveCaretTo (0, true);
2145 return true;
2146}
2147
2148//==============================================================================
2149void TextEditor::setEscapeAndReturnKeysConsumed (bool shouldBeConsumed) noexcept
2150{
2151 consumeEscAndReturnKeys = shouldBeConsumed;
2152}
2153
2155{
2158 return false;
2159
2161 {
2162 if (key == KeyPress::returnKey)
2163 {
2165
2167 {
2168 insertTextAtCaret ("\n");
2169 }
2170 else
2171 {
2172 returnPressed();
2174 }
2175 }
2176 else if (key.isKeyCode (KeyPress::escapeKey))
2177 {
2179 moveCaretTo (getCaretPosition(), false);
2180 escapePressed();
2182 }
2183 else if (key.getTextCharacter() >= ' '
2184 || (tabKeyUsed && (key.getTextCharacter() == '\t')))
2185 {
2186 insertTextAtCaret (String::charToString (key.getTextCharacter()));
2187
2189 }
2190 else
2191 {
2192 return false;
2193 }
2194 }
2195
2196 return true;
2197}
2198
2199bool TextEditor::keyStateChanged (const bool isKeyDown)
2200{
2201 if (! isKeyDown)
2202 return false;
2203
2204 #if JUCE_WINDOWS
2205 if (KeyPress (KeyPress::F4Key, ModifierKeys::altModifier, 0).isCurrentlyDown())
2206 return false; // We need to explicitly allow alt-F4 to pass through on Windows
2207 #endif
2208
2210 && (KeyPress (KeyPress::escapeKey).isCurrentlyDown()
2211 || KeyPress (KeyPress::returnKey).isCurrentlyDown()))
2212 return false;
2213
2214 // (overridden to avoid forwarding key events to the parent)
2215 return ! ModifierKeys::currentModifiers.isCommandDown();
2216}
2217
2218//==============================================================================
2220{
2222
2224 {
2225 moveCaretTo (0, false);
2226 moveCaretTo (getTotalNumChars(), true);
2227 }
2228
2229 checkFocus();
2230
2232 wasFocused = false;
2233
2234 repaint();
2236}
2237
2239{
2241
2242 wasFocused = false;
2243 textHolder->stopTimer();
2244
2245 underlinedSections.clear();
2246
2248
2250 repaint();
2251}
2252
2253//==============================================================================
2255{
2256 viewport->setBoundsInset (borderSize);
2257 viewport->setSingleStepSizes (16, roundToInt (currentFont.getHeight()));
2258
2259 checkLayout();
2260
2261 if (isMultiLine())
2263 else
2265}
2266
2267void TextEditor::handleCommandMessage (const int commandId)
2268{
2269 Component::BailOutChecker checker (this);
2270
2271 switch (commandId)
2272 {
2274 listeners.callChecked (checker, [this] (Listener& l) { l.textEditorTextChanged (*this); });
2275
2276 if (! checker.shouldBailOut() && onTextChange != nullptr)
2277 onTextChange();
2278
2279 break;
2280
2282 listeners.callChecked (checker, [this] (Listener& l) { l.textEditorReturnKeyPressed (*this); });
2283
2284 if (! checker.shouldBailOut() && onReturnKey != nullptr)
2285 onReturnKey();
2286
2287 break;
2288
2290 listeners.callChecked (checker, [this] (Listener& l) { l.textEditorEscapeKeyPressed (*this); });
2291
2292 if (! checker.shouldBailOut() && onEscapeKey != nullptr)
2293 onEscapeKey();
2294
2295 break;
2296
2299 listeners.callChecked (checker, [this] (Listener& l) { l.textEditorFocusLost (*this); });
2300
2301 if (! checker.shouldBailOut() && onFocusLost != nullptr)
2302 onFocusLost();
2303
2304 break;
2305
2306 default:
2308 break;
2309 }
2310}
2311
2312void TextEditor::setTemporaryUnderlining (const Array<Range<int>>& newUnderlinedSections)
2313{
2314 underlinedSections = newUnderlinedSections;
2315 repaint();
2316}
2317
2318//==============================================================================
2323
2325{
2326 remove ({ 0, getTotalNumChars() }, um, caretPosition);
2327}
2328
2329void TextEditor::insert (const String& text, int insertIndex, const Font& font,
2330 Colour colour, UndoManager* um, int caretPositionToMoveTo)
2331{
2332 if (text.isNotEmpty())
2333 {
2334 if (um != nullptr)
2335 {
2338
2339 um->perform (new InsertAction (*this, text, insertIndex, font, colour,
2340 caretPosition, caretPositionToMoveTo));
2341 }
2342 else
2343 {
2344 repaintText ({ insertIndex, getTotalNumChars() }); // must do this before and after changing the data, in case
2345 // a line gets moved due to word wrap
2346
2347 int index = 0;
2348 int nextIndex = 0;
2349
2350 for (int i = 0; i < sections.size(); ++i)
2351 {
2352 nextIndex = index + sections.getUnchecked (i)->getTotalLength();
2353
2354 if (insertIndex == index)
2355 {
2356 sections.insert (i, new UniformTextSection (text, font, colour, passwordCharacter));
2357 break;
2358 }
2359
2360 if (insertIndex > index && insertIndex < nextIndex)
2361 {
2362 splitSection (i, insertIndex - index);
2363 sections.insert (i + 1, new UniformTextSection (text, font, colour, passwordCharacter));
2364 break;
2365 }
2366
2367 index = nextIndex;
2368 }
2369
2370 if (nextIndex == insertIndex)
2371 sections.add (new UniformTextSection (text, font, colour, passwordCharacter));
2372
2374 totalNumChars = -1;
2376
2377 checkLayout();
2378 moveCaretTo (caretPositionToMoveTo, false);
2379
2380 repaintText ({ insertIndex, getTotalNumChars() });
2381 }
2382 }
2383}
2384
2385void TextEditor::reinsert (int insertIndex, const OwnedArray<UniformTextSection>& sectionsToInsert)
2386{
2387 int index = 0;
2388 int nextIndex = 0;
2389
2390 for (int i = 0; i < sections.size(); ++i)
2391 {
2392 nextIndex = index + sections.getUnchecked (i)->getTotalLength();
2393
2394 if (insertIndex == index)
2395 {
2396 for (int j = sectionsToInsert.size(); --j >= 0;)
2397 sections.insert (i, new UniformTextSection (*sectionsToInsert.getUnchecked(j)));
2398
2399 break;
2400 }
2401
2402 if (insertIndex > index && insertIndex < nextIndex)
2403 {
2404 splitSection (i, insertIndex - index);
2405
2406 for (int j = sectionsToInsert.size(); --j >= 0;)
2407 sections.insert (i + 1, new UniformTextSection (*sectionsToInsert.getUnchecked(j)));
2408
2409 break;
2410 }
2411
2412 index = nextIndex;
2413 }
2414
2415 if (nextIndex == insertIndex)
2416 for (auto* s : sectionsToInsert)
2417 sections.add (new UniformTextSection (*s));
2418
2420 totalNumChars = -1;
2422}
2423
2424void TextEditor::remove (Range<int> range, UndoManager* const um, const int caretPositionToMoveTo)
2425{
2426 if (! range.isEmpty())
2427 {
2428 int index = 0;
2429
2430 for (int i = 0; i < sections.size(); ++i)
2431 {
2432 auto nextIndex = index + sections.getUnchecked(i)->getTotalLength();
2433
2434 if (range.getStart() > index && range.getStart() < nextIndex)
2435 {
2436 splitSection (i, range.getStart() - index);
2437 --i;
2438 }
2439 else if (range.getEnd() > index && range.getEnd() < nextIndex)
2440 {
2441 splitSection (i, range.getEnd() - index);
2442 --i;
2443 }
2444 else
2445 {
2446 index = nextIndex;
2447
2448 if (index > range.getEnd())
2449 break;
2450 }
2451 }
2452
2453 index = 0;
2454
2455 if (um != nullptr)
2456 {
2457 Array<UniformTextSection*> removedSections;
2458
2459 for (auto* section : sections)
2460 {
2461 if (range.getEnd() <= range.getStart())
2462 break;
2463
2464 auto nextIndex = index + section->getTotalLength();
2465
2466 if (range.getStart() <= index && range.getEnd() >= nextIndex)
2467 removedSections.add (new UniformTextSection (*section));
2468
2469 index = nextIndex;
2470 }
2471
2474
2475 um->perform (new RemoveAction (*this, range, caretPosition,
2476 caretPositionToMoveTo, removedSections));
2477 }
2478 else
2479 {
2480 auto remainingRange = range;
2481
2482 for (int i = 0; i < sections.size(); ++i)
2483 {
2484 auto* section = sections.getUnchecked (i);
2485 auto nextIndex = index + section->getTotalLength();
2486
2487 if (remainingRange.getStart() <= index && remainingRange.getEnd() >= nextIndex)
2488 {
2489 sections.remove (i);
2490 remainingRange.setEnd (remainingRange.getEnd() - (nextIndex - index));
2491
2492 if (remainingRange.isEmpty())
2493 break;
2494
2495 --i;
2496 }
2497 else
2498 {
2499 index = nextIndex;
2500 }
2501 }
2502
2504 totalNumChars = -1;
2506
2507 checkLayout();
2508 moveCaretTo (caretPositionToMoveTo, false);
2509
2510 repaintText ({ range.getStart(), getTotalNumChars() });
2511 }
2512 }
2513}
2514
2515//==============================================================================
2517{
2519 mo.preallocate ((size_t) getTotalNumChars());
2520
2521 for (auto* s : sections)
2522 s->appendAllText (mo);
2523
2524 return mo.toUTF8();
2525}
2526
2528{
2529 if (range.isEmpty())
2530 return {};
2531
2533 mo.preallocate ((size_t) jmin (getTotalNumChars(), range.getLength()));
2534
2535 int index = 0;
2536
2537 for (auto* s : sections)
2538 {
2539 auto nextIndex = index + s->getTotalLength();
2540
2541 if (range.getStart() < nextIndex)
2542 {
2543 if (range.getEnd() <= index)
2544 break;
2545
2546 s->appendSubstring (mo, range - index);
2547 }
2548
2549 index = nextIndex;
2550 }
2551
2552 return mo.toUTF8();
2553}
2554
2559
2561{
2562 if (totalNumChars < 0)
2563 {
2564 totalNumChars = 0;
2565
2566 for (auto* s : sections)
2567 totalNumChars += s->getTotalLength();
2568 }
2569
2570 return totalNumChars;
2571}
2572
2574{
2575 return getTotalNumChars() == 0;
2576}
2577
2578void TextEditor::getCharPosition (int index, Point<float>& anchor, float& lineHeight) const
2579{
2580 if (getWordWrapWidth() <= 0)
2581 {
2582 anchor = {};
2583 lineHeight = currentFont.getHeight();
2584 }
2585 else
2586 {
2587 Iterator i (*this);
2588
2589 if (sections.isEmpty())
2590 {
2591 anchor = { i.getJustificationOffsetX (0), 0 };
2592 lineHeight = currentFont.getHeight();
2593 }
2594 else
2595 {
2596 i.getCharPosition (index, anchor, lineHeight);
2597 }
2598 }
2599}
2600
2601int TextEditor::indexAtPosition (const float x, const float y) const
2602{
2603 if (getWordWrapWidth() > 0)
2604 {
2605 for (Iterator i (*this); i.next();)
2606 {
2607 if (y < i.lineY + i.lineHeight)
2608 {
2609 if (y < i.lineY)
2610 return jmax (0, i.indexInText - 1);
2611
2612 if (x <= i.atomX || i.atom->isNewLine())
2613 return i.indexInText;
2614
2615 if (x < i.atomRight)
2616 return i.xToIndex (x);
2617 }
2618 }
2619 }
2620
2621 return getTotalNumChars();
2622}
2623
2624//==============================================================================
2625int TextEditor::findWordBreakAfter (const int position) const
2626{
2627 auto t = getTextInRange ({ position, position + 512 });
2628 auto totalLength = t.length();
2629 int i = 0;
2630
2631 while (i < totalLength && CharacterFunctions::isWhitespace (t[i]))
2632 ++i;
2633
2635
2636 while (i < totalLength && type == TextEditorDefs::getCharacterCategory (t[i]))
2637 ++i;
2638
2639 while (i < totalLength && CharacterFunctions::isWhitespace (t[i]))
2640 ++i;
2641
2642 return position + i;
2643}
2644
2645int TextEditor::findWordBreakBefore (const int position) const
2646{
2647 if (position <= 0)
2648 return 0;
2649
2650 auto startOfBuffer = jmax (0, position - 512);
2651 auto t = getTextInRange ({ startOfBuffer, position });
2652
2653 int i = position - startOfBuffer;
2654
2655 while (i > 0 && CharacterFunctions::isWhitespace (t [i - 1]))
2656 --i;
2657
2658 if (i > 0)
2659 {
2661
2662 while (i > 0 && type == TextEditorDefs::getCharacterCategory (t [i - 1]))
2663 --i;
2664 }
2665
2666 jassert (startOfBuffer + i >= 0);
2667 return startOfBuffer + i;
2668}
2669
2670
2671//==============================================================================
2672void TextEditor::splitSection (const int sectionIndex, const int charToSplitAt)
2673{
2674 jassert (sections[sectionIndex] != nullptr);
2675
2676 sections.insert (sectionIndex + 1,
2677 sections.getUnchecked (sectionIndex)->split (charToSplitAt));
2678}
2679
2681{
2682 for (int i = 0; i < sections.size() - 1; ++i)
2683 {
2684 auto* s1 = sections.getUnchecked (i);
2685 auto* s2 = sections.getUnchecked (i + 1);
2686
2687 if (s1->font == s2->font
2688 && s1->colour == s2->colour)
2689 {
2690 s1->append (*s2);
2691 sections.remove (i + 1);
2692 --i;
2693 }
2694 }
2695}
2696
2697//==============================================================================
2699{
2700public:
2701 explicit EditorAccessibilityHandler (TextEditor& textEditorToWrap)
2702 : AccessibilityHandler (textEditorToWrap,
2704 {},
2705 { std::make_unique<TextEditorTextInterface> (textEditorToWrap) }),
2706 textEditor (textEditorToWrap)
2707 {
2708 }
2709
2710 String getHelp() const override { return textEditor.getTooltip(); }
2711
2712private:
2714 {
2715 public:
2717 : textEditor (editor)
2718 {
2719 }
2720
2721 bool isDisplayingProtectedText() const override { return textEditor.getPasswordCharacter() != 0; }
2722 bool isReadOnly() const override { return textEditor.isReadOnly(); }
2723
2724 int getTotalNumCharacters() const override { return textEditor.getText().length(); }
2725 Range<int> getSelection() const override { return textEditor.getHighlightedRegion(); }
2726
2727 void setSelection (Range<int> r) override
2728 {
2729 if (r == textEditor.getHighlightedRegion())
2730 return;
2731
2732 if (r.isEmpty())
2733 {
2734 textEditor.setCaretPosition (r.getStart());
2735 }
2736 else
2737 {
2738 const auto cursorAtStart = r.getEnd() == textEditor.getHighlightedRegion().getStart()
2739 || r.getEnd() == textEditor.getHighlightedRegion().getEnd();
2740 textEditor.moveCaretTo (cursorAtStart ? r.getEnd() : r.getStart(), false);
2741 textEditor.moveCaretTo (cursorAtStart ? r.getStart() : r.getEnd(), true);
2742 }
2743 }
2744
2745 String getText (Range<int> r) const override
2746 {
2748 return String::repeatedString (String::charToString (textEditor.getPasswordCharacter()),
2750
2751 return textEditor.getTextInRange (r);
2752 }
2753
2754 void setText (const String& newText) override
2755 {
2756 textEditor.setText (newText);
2757 }
2758
2759 int getTextInsertionOffset() const override { return textEditor.getCaretPosition(); }
2760
2762 {
2763 auto localRects = textEditor.getTextBounds (textRange);
2764 RectangleList<int> globalRects;
2765
2766 std::for_each (localRects.begin(), localRects.end(),
2767 [&] (const Rectangle<int>& r) { globalRects.add (textEditor.localAreaToGlobal (r)); });
2768
2769 return globalRects;
2770 }
2771
2772 int getOffsetAtPoint (Point<int> point) const override
2773 {
2774 auto localPoint = textEditor.getLocalPoint (nullptr, point);
2775 return textEditor.getTextIndexAt (localPoint.x, localPoint.y);
2776 }
2777
2778 private:
2780
2781 //==============================================================================
2783 };
2784
2786
2787 //==============================================================================
2789};
2790
2791std::unique_ptr<AccessibilityHandler> TextEditor::createAccessibilityHandler()
2792{
2793 return std::make_unique<EditorAccessibilityHandler> (*this);
2794}
2795
2796} // namespace juce
#define copy(x)
Definition ADnoteParameters.cpp:1011
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
#define noexcept
Definition DistrhoDefines.h:72
#define nullptr
Definition DistrhoDefines.h:75
CAdPlugDatabase::CRecord::RecordType type
Definition adplugdb.cpp:93
static String repeatedString(StringRef stringToRepeat, int numberOfTimesToRepeat)
Definition String.cpp:1028
AccessibilityHandler(Component &componentToWrap, AccessibilityRole accessibilityRole, AccessibilityActions actions={}, Interfaces interfaces={})
Definition juce_AccessibilityHandler.cpp:55
Definition juce_AccessibilityTextInterface.h:39
Definition juce_AffineTransform.h:43
static AffineTransform translation(float deltaX, float deltaY) noexcept
Definition juce_AffineTransform.cpp:81
Definition juce_Array.h:56
void add(const ElementType &newElement)
Definition juce_Array.h:418
Definition juce_BorderSize.h:42
static bool isWhitespace(char character) noexcept
Definition juce_CharacterFunctions.cpp:59
static bool isLetterOrDigit(char character) noexcept
Definition juce_CharacterFunctions.cpp:90
Definition juce_Colour.h:38
Definition juce_Component.h:2331
bool shouldBailOut() const noexcept
Definition juce_Component.cpp:3252
Definition juce_Component.h:2287
int proportionOfWidth(float proportion) const noexcept
Definition juce_Component.cpp:1111
void setInterceptsMouseClicks(bool allowClicksOnThisComponent, bool allowClicksOnChildComponents) noexcept
Definition juce_Component.cpp:1420
int getHeight() const noexcept
Definition juce_Component.h:274
void addAndMakeVisible(Component *child, int zOrder=-1)
Definition juce_Component.cpp:1554
FocusChangeType
Definition juce_Component.h:1890
@ focusChangedByMouseClick
Definition juce_Component.h:1891
bool hasKeyboardFocus(bool trueIfChildIsFocused) const
Definition juce_Component.cpp:3086
bool isCurrentlyBlockedByAnotherModalComponent() const
Definition juce_Component.cpp:1832
AccessibilityHandler * getAccessibilityHandler()
Definition juce_Component.cpp:3302
void setMouseCursor(const MouseCursor &cursorType)
Definition juce_Component.cpp:1859
void postCommandMessage(int commandId)
Definition juce_Component.cpp:2361
void repaint()
Definition juce_Component.cpp:1917
Component() noexcept
Definition juce_Component.cpp:517
void setColour(int colourID, Colour newColour)
Definition juce_Component.cpp:2242
void setWantsKeyboardFocus(bool wantsFocus) noexcept
Definition juce_Component.cpp:2842
Colour findColour(int colourID, bool inheritFromParent=false) const
Definition juce_Component.cpp:2219
static std::unique_ptr< AccessibilityHandler > createIgnoredAccessibilityHandler(Component &)
Definition juce_Component.cpp:3292
int getWidth() const noexcept
Definition juce_Component.h:271
void mouseWheelMove(const MouseEvent &event, const MouseWheelDetails &wheel) override
Definition juce_Component.cpp:2303
static void JUCE_CALLTYPE beginDragAutoRepeat(int millisecondsBetweenCallbacks)
Definition juce_Component.cpp:2745
bool isEnabled() const noexcept
Definition juce_Component.cpp:3104
ComponentPeer * getPeer() const
Definition juce_Component.cpp:801
LookAndFeel & getLookAndFeel() const noexcept
Definition juce_Component.cpp:2173
void invalidateAccessibilityHandler()
Definition juce_Component.cpp:3297
void addGlobalMouseListener(MouseListener *listener)
Definition juce_Desktop.cpp:245
void removeGlobalMouseListener(MouseListener *listener)
Definition juce_Desktop.cpp:252
Definition juce_Font.h:42
float getHeight() const noexcept
Definition juce_Font.cpp:735
float getStringWidthFloat(const String &text) const
Definition juce_Font.cpp:747
Definition juce_GlyphArrangement.h:117
void addLineOfText(const Font &font, const String &text, float x, float y)
Definition juce_GlyphArrangement.cpp:144
void draw(const Graphics &) const
Definition juce_GlyphArrangement.cpp:706
void removeRangeOfGlyphs(int startIndex, int numGlyphs)
Definition juce_GlyphArrangement.cpp:138
Definition juce_GraphicsContext.h:660
Definition juce_GraphicsContext.h:45
Definition juce_Justification.h:41
@ horizontallyCentred
Definition juce_Justification.h:115
@ bottom
Definition juce_Justification.h:122
@ top
Definition juce_Justification.h:119
@ right
Definition juce_Justification.h:111
Definition juce_KeyPress.h:40
static const int F4Key
Definition juce_KeyPress.h:210
static const int escapeKey
Definition juce_KeyPress.h:190
static const int returnKey
Definition juce_KeyPress.h:191
Definition juce_MemoryOutputStream.h:36
static ModifierKeys currentModifiers
Definition juce_ModifierKeys.h:189
@ commandModifier
Definition juce_ModifierKeys.h:147
@ altModifier
Definition juce_ModifierKeys.h:127
@ IBeamCursor
Definition juce_MouseCursor.h:51
@ ParentCursor
Definition juce_MouseCursor.h:45
Definition juce_MouseEvent.h:39
Definition juce_OwnedArray.h:51
int size() const noexcept
Definition juce_OwnedArray.h:130
ObjectClass * getUnchecked(int index) const noexcept
Definition juce_OwnedArray.h:160
Definition juce_Point.h:42
ValueType y
Definition juce_Point.h:247
ValueType x
Definition juce_Point.h:246
Definition juce_PopupMenu.h:457
Definition juce_PopupMenu.h:80
Definition juce_Range.h:40
constexpr ValueType getStart() const noexcept
Definition juce_Range.h:80
constexpr bool isEmpty() const noexcept
Definition juce_Range.h:89
constexpr bool intersects(Range other) const noexcept
Definition juce_Range.h:227
constexpr ValueType getEnd() const noexcept
Definition juce_Range.h:86
JUCE_NODISCARD static constexpr Range emptyRange(const ValueType start) noexcept
Definition juce_Range.h:73
static constexpr Range between(const ValueType position1, const ValueType position2) noexcept
Definition juce_Range.h:59
constexpr ValueType getLength() const noexcept
Definition juce_Range.h:83
Definition juce_Rectangle.h:67
Rectangle< int > getSmallestIntegerContainer() const noexcept
Definition juce_Rectangle.h:840
bool isEmpty() const noexcept
Definition juce_Rectangle.h:121
Definition juce_RectangleList.h:43
void offsetAll(Point< ValueType > offset) noexcept
Definition juce_RectangleList.h:589
void add(RectangleType rect)
Definition juce_RectangleList.h:110
Definition juce_ScopedValueSetter.h:55
Definition juce_String.h:53
CharPointerType getCharPointer() const noexcept
Definition juce_String.h:1153
int length() const noexcept
Definition juce_String.cpp:511
String replace(StringRef stringToReplace, StringRef stringToInsertInstead, bool ignoreCase=false) const
Definition juce_String.cpp:1279
String replaceCharacters(StringRef charactersToReplace, StringRef charactersToInsertInstead) const
Definition juce_String.cpp:1367
static String charToString(juce_wchar character)
Definition juce_String.cpp:359
String substring(int startIndex, int endIndex) const
Definition juce_String.cpp:1498
bool containsAnyOf(StringRef charactersItMightContain) const noexcept
Definition juce_String.cpp:1805
bool isNotEmpty() const noexcept
Definition juce_String.h:316
static String getTextFromClipboard()
Definition juce_linux_Windowing.cpp:798
static void copyTextToClipboard(const String &text)
Definition juce_linux_Windowing.cpp:793
int getTotalNumCharacters() const override
Definition juce_TextEditor.cpp:2724
TextEditorTextInterface(TextEditor &editor)
Definition juce_TextEditor.cpp:2716
void setText(const String &newText) override
Definition juce_TextEditor.cpp:2754
bool isDisplayingProtectedText() const override
Definition juce_TextEditor.cpp:2721
int getOffsetAtPoint(Point< int > point) const override
Definition juce_TextEditor.cpp:2772
bool isReadOnly() const override
Definition juce_TextEditor.cpp:2722
RectangleList< int > getTextBounds(Range< int > textRange) const override
Definition juce_TextEditor.cpp:2761
void setSelection(Range< int > r) override
Definition juce_TextEditor.cpp:2727
Range< int > getSelection() const override
Definition juce_TextEditor.cpp:2725
int getTextInsertionOffset() const override
Definition juce_TextEditor.cpp:2759
TextEditor & textEditor
Definition juce_TextEditor.cpp:2779
String getText(Range< int > r) const override
Definition juce_TextEditor.cpp:2745
Definition juce_TextEditor.cpp:2699
TextEditor & textEditor
Definition juce_TextEditor.cpp:2785
String getHelp() const override
Definition juce_TextEditor.cpp:2710
EditorAccessibilityHandler(TextEditor &textEditorToWrap)
Definition juce_TextEditor.cpp:2701
Definition juce_TextEditor.h:611
Definition juce_TextEditor.h:627
LengthAndCharacterRestriction(int maxNumChars, const String &allowedCharacters)
Definition juce_TextEditor.cpp:1178
int maxLength
Definition juce_TextEditor.h:641
String filterNewText(TextEditor &, const String &) override
Definition juce_TextEditor.cpp:1183
String allowedCharacters
Definition juce_TextEditor.h:640
Definition juce_TextEditor.h:315
Definition juce_TextEditor.cpp:67
void initialiseAtoms(const String &textToParse)
Definition juce_TextEditor.cpp:217
void setFont(const Font &newFont, const juce_wchar passwordCharToUse)
Definition juce_TextEditor.cpp:198
UniformTextSection * split(int indexToBreakAt)
Definition juce_TextEditor.cpp:114
juce_wchar passwordChar
Definition juce_TextEditor.cpp:214
void append(UniformTextSection &other)
Definition juce_TextEditor.cpp:80
void appendSubstring(MemoryOutputStream &mo, Range< int > range) const
Definition juce_TextEditor.cpp:165
UniformTextSection(const UniformTextSection &)=default
void appendAllText(MemoryOutputStream &mo) const
Definition juce_TextEditor.cpp:159
Font font
Definition juce_TextEditor.cpp:211
UniformTextSection(UniformTextSection &&)=default
Array< TextAtom > atoms
Definition juce_TextEditor.cpp:213
Colour colour
Definition juce_TextEditor.cpp:212
int getTotalLength() const noexcept
Definition juce_TextEditor.cpp:188
UniformTextSection(const String &text, const Font &f, Colour col, juce_wchar passwordCharToUse)
Definition juce_TextEditor.cpp:69
void paint(Graphics &) override
Definition juce_TextEditor.cpp:1775
int findWordBreakBefore(int position) const
Definition juce_TextEditor.cpp:2645
void scrollEditorToPositionCaret(int desiredCaretX, int desiredCaretY)
Definition juce_TextEditor.cpp:1419
int getMaximumTextHeight() const
Definition juce_TextEditor.cpp:1509
int getMaximumTextWidth() const
Definition juce_TextEditor.cpp:1504
RectangleList< int > getTextBounds(Range< int > textRange)
Definition juce_TextEditor.cpp:1476
void handleCommandMessage(int) override
Definition juce_TextEditor.cpp:2267
DragType dragType
Definition juce_TextEditor.h:812
void clearInternal(UndoManager *)
Definition juce_TextEditor.cpp:2324
void repaintText(Range< int >)
Definition juce_TextEditor.cpp:1347
bool isTextInputActive() const override
Definition juce_TextEditor.cpp:1047
bool selectAllTextWhenFocused
Definition juce_TextEditor.h:776
void setScrollbarsShown(bool shouldBeEnabled)
Definition juce_TextEditor.cpp:1015
Range< int > selection
Definition juce_TextEditor.h:790
void setMultiLine(bool shouldBeMultiLine, bool shouldWordWrap=true)
Definition juce_TextEditor.cpp:993
@ highlightColourId
Definition juce_TextEditor.h:217
@ textColourId
Definition juce_TextEditor.h:212
@ highlightedTextColourId
Definition juce_TextEditor.h:221
bool moveCaretLeft(bool moveInWholeWordSteps, bool selecting)
Definition juce_TextEditor.cpp:1999
void setCaretPosition(int newIndex)
Definition juce_TextEditor.cpp:1409
int getCaretPosition() const
Definition juce_TextEditor.cpp:1404
bool isEmpty() const
Definition juce_TextEditor.cpp:2573
bool keyStateChanged(bool) override
Definition juce_TextEditor.cpp:2199
int leftIndent
Definition juce_TextEditor.h:791
Array< Range< int > > underlinedSections
Definition juce_TextEditor.h:815
Colour colourForTextWhenEmpty
Definition juce_TextEditor.h:798
bool tabKeyUsed
Definition juce_TextEditor.h:780
OptionalScopedPointer< InputFilter > inputFilter
Definition juce_TextEditor.h:800
UndoManager * getUndoManager() noexcept
Definition juce_TextEditor.cpp:2319
void setBorder(BorderSize< int > border)
Definition juce_TextEditor.cpp:1543
int findWordBreakAfter(int position) const
Definition juce_TextEditor.cpp:2625
void moveCaret(int newCaretPos)
Definition juce_TextEditor.cpp:1382
void reinsert(int insertIndex, const OwnedArray< UniformTextSection > &)
Definition juce_TextEditor.cpp:2385
void mouseWheelMove(const MouseEvent &, const MouseWheelDetails &) override
Definition juce_TextEditor.cpp:1978
void applyColourToAllText(const Colour &newColour, bool changeCurrentTextColour=true)
Definition juce_TextEditor.cpp:1109
Rectangle< int > getCaretRectangle() override
Definition juce_TextEditor.cpp:1453
int getTextWidth() const
Definition juce_TextEditor.cpp:1528
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Definition juce_TextEditor.cpp:2791
bool clicksOutsideDismissVirtualKeyboard
Definition juce_TextEditor.h:786
String textToShowWhenEmpty
Definition juce_TextEditor.h:797
bool undoOrRedo(bool shouldUndo)
Definition juce_TextEditor.cpp:969
void setIndents(int newLeftIndent, int newTopIndent)
Definition juce_TextEditor.cpp:1531
void insertTextAtCaret(const String &textToInsert) override
Definition juce_TextEditor.cpp:1649
bool returnKeyStartsNewLine
Definition juce_TextEditor.h:774
bool pasteFromClipboard()
Definition juce_TextEditor.cpp:2133
virtual void escapePressed()
Definition juce_TextEditor.cpp:1325
void mouseDown(const MouseEvent &) override
Definition juce_TextEditor.cpp:1841
std::unique_ptr< CaretComponent > caret
Definition juce_TextEditor.h:789
~TextEditor() override
Definition juce_TextEditor.cpp:951
void setPasswordCharacter(juce_wchar passwordCharacter)
Definition juce_TextEditor.cpp:1212
int getTotalNumChars() const
Definition juce_TextEditor.cpp:2560
void newTransaction()
Definition juce_TextEditor.cpp:963
void setSelection(Range< int >) noexcept
Definition juce_TextEditor.cpp:1313
bool deleteBackwards(bool moveInWholeWordSteps)
Definition juce_TextEditor.cpp:2098
std::unique_ptr< Viewport > viewport
Definition juce_TextEditor.h:765
bool scrollDown()
Definition juce_TextEditor.cpp:2064
bool isReadOnly() const noexcept
Definition juce_TextEditor.cpp:1042
void setTemporaryUnderlining(const Array< Range< int > > &) override
Definition juce_TextEditor.cpp:2312
bool wasFocused
Definition juce_TextEditor.h:778
const Font & getFont() const noexcept
Definition juce_TextEditor.h:257
std::function< void()> onFocusLost
Definition juce_TextEditor.h:354
std::function< void()> onEscapeKey
Definition juce_TextEditor.h:351
bool keepCaretOnScreen
Definition juce_TextEditor.h:779
void drawContent(Graphics &)
Definition juce_TextEditor.cpp:1709
bool undo()
Definition juce_TextEditor.cpp:989
void insert(const String &, int insertIndex, const Font &, Colour, UndoManager *, int newCaretPos)
Definition juce_TextEditor.cpp:2329
void setFont(const Font &newFont)
Definition juce_TextEditor.cpp:1084
void remove(Range< int >, UndoManager *, int caretPositionToMoveTo)
Definition juce_TextEditor.cpp:2424
void focusGained(FocusChangeType) override
Definition juce_TextEditor.cpp:2219
Point< int > getTextOffset() const noexcept
Definition juce_TextEditor.cpp:1467
bool wordWrap
Definition juce_TextEditor.h:773
void clear()
Definition juce_TextEditor.cpp:1227
bool moveCaretRight(bool moveInWholeWordSteps, bool selecting)
Definition juce_TextEditor.cpp:2011
void copy()
Definition juce_TextEditor.cpp:1677
bool scrollUp()
Definition juce_TextEditor.cpp:2070
void updateCaretPosition()
Definition juce_TextEditor.cpp:1164
void recreateCaret()
Definition juce_TextEditor.cpp:1147
bool copyToClipboard()
Definition juce_TextEditor.cpp:2118
String getHighlightedText() const
Definition juce_TextEditor.cpp:2555
bool cutToClipboard()
Definition juce_TextEditor.cpp:2125
@ draggingSelectionStart
Definition juce_TextEditor.h:808
@ draggingSelectionEnd
Definition juce_TextEditor.h:809
@ notDragging
Definition juce_TextEditor.h:807
void enablementChanged() override
Definition juce_TextEditor.cpp:1132
std::function< void()> onReturnKey
Definition juce_TextEditor.h:348
bool moveCaretToTop(bool selecting)
Definition juce_TextEditor.cpp:2076
bool moveCaretDown(bool selecting)
Definition juce_TextEditor.cpp:2032
void checkFocus()
Definition juce_TextEditor.cpp:1341
int getLeftIndent() const noexcept
Definition juce_TextEditor.h:504
bool caretVisible
Definition juce_TextEditor.h:771
int totalNumChars
Definition juce_TextEditor.h:794
void setText(const String &newText, bool sendTextChangeMessage=true)
Definition juce_TextEditor.cpp:1234
bool pageDown(bool selecting)
Definition juce_TextEditor.cpp:2050
int getTextHeight() const
Definition juce_TextEditor.cpp:1529
bool moveCaretToEndOfLine(bool selecting)
Definition juce_TextEditor.cpp:2092
void paintOverChildren(Graphics &) override
Definition juce_TextEditor.cpp:1780
bool mouseDownInEditor
Definition juce_TextEditor.h:785
void addListener(Listener *newListener)
Definition juce_TextEditor.cpp:1327
void textWasChangedByValue()
Definition juce_TextEditor.cpp:1289
void mouseDrag(const MouseEvent &) override
Definition juce_TextEditor.cpp:1884
int caretPosition
Definition juce_TextEditor.h:795
void setReadOnly(bool shouldBeReadOnly)
Definition juce_TextEditor.cpp:1024
juce_wchar passwordCharacter
Definition juce_TextEditor.h:799
void moveCaretTo(int newPosition, bool isSelecting)
Definition juce_TextEditor.cpp:1597
int getTextIndexAt(int x, int y) const
Definition juce_TextEditor.cpp:1641
void setEscapeAndReturnKeysConsumed(bool shouldBeConsumed) noexcept
Definition juce_TextEditor.cpp:2149
void coalesceSimilarSections()
Definition juce_TextEditor.cpp:2680
bool popupMenuEnabled
Definition juce_TextEditor.h:775
void setClicksOutsideDismissVirtualKeyboard(bool)
Definition juce_TextEditor.cpp:1037
String getTextInRange(const Range< int > &textRange) const override
Definition juce_TextEditor.cpp:2527
int indexAtPosition(float x, float y) const
Definition juce_TextEditor.cpp:2601
int getTopIndent() const noexcept
Definition juce_TextEditor.h:499
void lookAndFeelChanged() override
Definition juce_TextEditor.cpp:1120
virtual void addPopupMenuItems(PopupMenu &menuToAddTo, const MouseEvent *mouseClickEvent)
Definition juce_TextEditor.cpp:1802
void moveCaretToEnd()
Definition juce_TextEditor.cpp:1414
void checkLayout()
Definition juce_TextEditor.cpp:1514
unsigned int lastTransactionTime
Definition juce_TextEditor.h:792
Range< int > getHighlightedRegion() const override
Definition juce_TextEditor.h:460
virtual void returnPressed()
Definition juce_TextEditor.cpp:1324
void resized() override
Definition juce_TextEditor.cpp:2254
void setJustification(Justification newJustification)
Definition juce_TextEditor.cpp:1072
bool consumeEscAndReturnKeys
Definition juce_TextEditor.h:783
void scrollToMakeSureCursorIsVisible()
Definition juce_TextEditor.cpp:1559
void mouseDoubleClick(const MouseEvent &) override
Definition juce_TextEditor.cpp:1909
void textChanged()
Definition juce_TextEditor.cpp:1296
void setTextToShowWhenEmpty(const String &text, Colour colourToUse)
Definition juce_TextEditor.cpp:1206
bool menuActive
Definition juce_TextEditor.h:781
void setInputFilter(InputFilter *newFilter, bool takeOwnership)
Definition juce_TextEditor.cpp:1196
virtual void performPopupMenuAction(int menuItemID)
Definition juce_TextEditor.cpp:1825
void focusLost(FocusChangeType) override
Definition juce_TextEditor.cpp:2238
bool redo()
Definition juce_TextEditor.cpp:990
void scrollByLines(int deltaLines)
Definition juce_TextEditor.cpp:2059
void setInputRestrictions(int maxTextLength, const String &allowedCharacters=String())
Definition juce_TextEditor.cpp:1201
bool selectAll()
Definition juce_TextEditor.cpp:2140
BorderSize< int > borderSize
Definition juce_TextEditor.h:767
void getCharPosition(int index, Point< float > &, float &lineHeight) const
Definition juce_TextEditor.cpp:2578
bool moveCaretToStartOfLine(bool selecting)
Definition juce_TextEditor.cpp:2081
bool multiline
Definition juce_TextEditor.h:772
Value & getTextValue()
Definition juce_TextEditor.cpp:1283
bool valueTextNeedsUpdating
Definition juce_TextEditor.h:782
bool isCaretVisible() const noexcept
Definition juce_TextEditor.h:145
void setHighlightedRegion(const Range< int > &newSelection) override
Definition juce_TextEditor.cpp:1670
std::function< void()> onTextChange
Definition juce_TextEditor.h:345
void setCaretVisible(bool shouldBeVisible)
Definition juce_TextEditor.cpp:1138
TextHolderComponent * textHolder
Definition juce_TextEditor.h:766
ListenerList< Listener > listeners
Definition juce_TextEditor.h:814
bool readOnly
Definition juce_TextEditor.h:770
void setPopupMenuEnabled(bool menuEnabled)
Definition juce_TextEditor.cpp:1062
TextEditor(const String &componentName=String(), juce_wchar passwordCharacter=0)
Definition juce_TextEditor.cpp:933
void cut()
Definition juce_TextEditor.cpp:1699
void setTabKeyUsedAsCharacter(bool shouldTabKeyBeUsed)
Definition juce_TextEditor.cpp:1057
bool keyPressed(const KeyPress &) override
Definition juce_TextEditor.cpp:2154
void setReturnKeyStartsNewLine(bool shouldStartNewLine)
Definition juce_TextEditor.cpp:1052
void mouseUp(const MouseEvent &) override
Definition juce_TextEditor.cpp:1894
int topIndent
Definition juce_TextEditor.h:791
bool isMultiLine() const
Definition juce_TextEditor.cpp:1010
bool moveCaretWithTransaction(int newPos, bool selecting)
Definition juce_TextEditor.cpp:1988
OwnedArray< UniformTextSection > sections
Definition juce_TextEditor.h:796
bool pageUp(bool selecting)
Definition juce_TextEditor.cpp:2041
UndoManager undoManager
Definition juce_TextEditor.h:788
bool scrollbarVisible
Definition juce_TextEditor.h:777
String getText() const
Definition juce_TextEditor.cpp:2516
void parentHierarchyChanged() override
Definition juce_TextEditor.cpp:1127
BorderSize< int > getBorder() const
Definition juce_TextEditor.cpp:1549
bool moveCaretUp(bool selecting)
Definition juce_TextEditor.cpp:2023
Rectangle< float > getCaretRectangleFloat() const
Definition juce_TextEditor.cpp:1458
void updateValueFromText()
Definition juce_TextEditor.cpp:1274
void splitSection(int sectionIndex, int charToSplitAt)
Definition juce_TextEditor.cpp:2672
void removeListener(Listener *listenerToRemove)
Definition juce_TextEditor.cpp:1328
void paste()
Definition juce_TextEditor.cpp:1688
Font currentFont
Definition juce_TextEditor.h:793
bool deleteForwards(bool moveInWholeWordSteps)
Definition juce_TextEditor.cpp:2109
void setSelectAllWhenFocused(bool shouldSelectAll)
Definition juce_TextEditor.cpp:1067
void applyFontToAllText(const Font &newFont, bool changeCurrentFont=true)
Definition juce_TextEditor.cpp:1090
void setScrollBarThickness(int newThicknessPixels)
Definition juce_TextEditor.cpp:1221
void setScrollToShowCursor(bool shouldScrollToShowCaret)
Definition juce_TextEditor.cpp:1554
Justification justification
Definition juce_TextEditor.h:768
Value textValue
Definition juce_TextEditor.h:801
int getWordWrapWidth() const
Definition juce_TextEditor.cpp:1498
void timerCallbackInt()
Definition juce_TextEditor.cpp:1331
static uint32 getApproximateMillisecondCounter() noexcept
Definition juce_Time.cpp:261
Timer() noexcept
Definition juce_Timer.cpp:316
void startTimer(int intervalInMilliseconds) noexcept
Definition juce_Timer.cpp:332
Definition juce_UndoManager.h:52
bool perform(UndoableAction *action)
Definition juce_UndoManager.cpp:111
int getNumActionsInCurrentTransaction() const
Definition juce_UndoManager.cpp:360
UndoableAction()=default
Definition juce_Value.h:139
Definition juce_Value.h:51
Viewport(const String &componentName=String())
Definition juce_Viewport.cpp:160
* e
Definition inflate.c:1404
int * l
Definition inflate.c:1579
unsigned * m
Definition inflate.c:1559
struct huft * t
Definition inflate.c:943
register unsigned j
Definition inflate.c:1576
int y
Definition inflate.c:1588
int g
Definition inflate.c:1573
register unsigned i
Definition inflate.c:1575
static ZCONST unsigned border[]
Definition inflate.c:749
unsigned s
Definition inflate.c:1555
unsigned x[BMAX+1]
Definition inflate.c:1586
unsigned f
Definition inflate.c:1572
struct @113205115357366127300225113341150224053346037032::@137033172036070230260373056156374243321245367362 right
static const char * name
Definition pugl.h:1582
static int int height
Definition pugl.h:1594
virtual ASIOError start()=0
#define JUCE_LEAK_DETECTOR(OwnerClass)
Definition juce_LeakedObjectDetector.h:138
#define TRANS(stringLiteral)
Definition juce_LocalisedStrings.h:208
#define jassert(expression)
#define JUCE_DECLARE_NON_COPYABLE(className)
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
#define jassertfalse
const Colour transparentBlack
Definition juce_Colours.h:40
@ paste
Definition juce_ApplicationCommandID.h:74
@ del
Definition juce_ApplicationCommandID.h:65
@ redo
Definition juce_ApplicationCommandID.h:86
@ undo
Definition juce_ApplicationCommandID.h:83
@ cut
Definition juce_ApplicationCommandID.h:68
@ copy
Definition juce_ApplicationCommandID.h:71
@ selectAll
Definition juce_ApplicationCommandID.h:77
Definition juce_TextEditor.cpp:917
const int escapeKeyMessageId
Definition juce_TextEditor.cpp:920
const int textChangeMessageId
Definition juce_TextEditor.cpp:918
const int returnKeyMessageId
Definition juce_TextEditor.cpp:919
const int focusLossMessageId
Definition juce_TextEditor.cpp:921
const int maxActionsPerTransaction
Definition juce_TextEditor.cpp:923
static int getCharacterCategory(juce_wchar character) noexcept
Definition juce_TextEditor.cpp:925
Definition carla_juce.cpp:31
unsigned short uint16
Definition juce_MathsFunctions.h:41
constexpr Type jmin(Type a, Type b)
Definition juce_MathsFunctions.h:106
constexpr Type jmax(Type a, Type b)
Definition juce_MathsFunctions.h:94
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Definition juce_MathsFunctions.h:262
@ textChanged
Definition juce_AccessibilityEvent.h:71
@ textSelectionChanged
Definition juce_AccessibilityEvent.h:64
wchar_t juce_wchar
Definition juce_CharacterFunctions.h:42
constexpr int rightEdgeSpace
Definition juce_TextEditor.cpp:1496
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Definition juce_MathsFunctions.h:279
int roundToInt(const FloatType value) noexcept
Definition juce_MathsFunctions.h:465
AccessibilityRole
Definition juce_AccessibilityRole.h:37
@ staticText
Definition juce_AccessibilityRole.h:45
@ editableText
Definition juce_AccessibilityRole.h:46
Definition juce_MouseEvent.h:392
Definition juce_TextEditor.cpp:31
String atomText
Definition juce_TextEditor.cpp:33
String getTrimmedText(const juce_wchar passwordCharacter) const
Definition juce_TextEditor.cpp:50
bool isNewLine() const noexcept
Definition juce_TextEditor.cpp:39
bool isWhitespace() const noexcept
Definition juce_TextEditor.cpp:38
String getText(juce_wchar passwordCharacter) const
Definition juce_TextEditor.cpp:41
int numChars
Definition juce_TextEditor.cpp:35
float width
Definition juce_TextEditor.cpp:34
Definition juce_TextEditor.cpp:745
InsertAction(TextEditor &ed, const String &newText, int insertPos, const Font &newFont, Colour newColour, int oldCaret, int newCaret)
Definition juce_TextEditor.cpp:746
const String text
Definition juce_TextEditor.cpp:777
int getSizeInUnits() override
Definition juce_TextEditor.cpp:770
const Colour colour
Definition juce_TextEditor.cpp:780
const Font font
Definition juce_TextEditor.cpp:779
bool undo() override
Definition juce_TextEditor.cpp:764
TextEditor & owner
Definition juce_TextEditor.cpp:776
const int oldCaretPos
Definition juce_TextEditor.cpp:778
const int insertIndex
Definition juce_TextEditor.cpp:778
bool perform() override
Definition juce_TextEditor.cpp:758
const int newCaretPos
Definition juce_TextEditor.cpp:778
Definition juce_TextEditor.cpp:277
int indexInText
Definition juce_TextEditor.cpp:667
const float wordWrapWidth
Definition juce_TextEditor.cpp:678
const juce_wchar passwordCharacter
Definition juce_TextEditor.cpp:679
float atomX
Definition juce_TextEditor.cpp:669
void drawSelectedText(Graphics &g, Range< int > selected, Colour selectedTextColour, AffineTransform transform) const
Definition juce_TextEditor.cpp:515
float lineY
Definition juce_TextEditor.cpp:668
float maxDescent
Definition juce_TextEditor.cpp:668
Iterator(const TextEditor &ed)
Definition juce_TextEditor.cpp:278
void moveToEndOfLastAtom()
Definition juce_TextEditor.cpp:720
float getJustificationOffsetX(float lineWidth) const
Definition juce_TextEditor.cpp:470
Iterator(const Iterator &)=default
const float lineSpacing
Definition juce_TextEditor.cpp:680
const TextAtom * atom
Definition juce_TextEditor.cpp:670
const Point< float > bottomRight
Definition juce_TextEditor.cpp:677
TextAtom longAtom
Definition juce_TextEditor.cpp:682
bool chunkLongAtom(bool shouldStartNewLine)
Definition juce_TextEditor.cpp:684
const OwnedArray< UniformTextSection > & sections
Definition juce_TextEditor.cpp:673
int atomIndex
Definition juce_TextEditor.cpp:675
Rectangle< int > getTextBounds(Range< int > range) const
Definition juce_TextEditor.cpp:658
int getTotalTextHeight()
Definition juce_TextEditor.cpp:636
float atomRight
Definition juce_TextEditor.cpp:669
float getYOffset()
Definition juce_TextEditor.cpp:617
void draw(Graphics &g, const UniformTextSection *&lastSection, AffineTransform transform) const
Definition juce_TextEditor.cpp:479
int sectionIndex
Definition juce_TextEditor.cpp:675
void drawUnderline(Graphics &g, Range< int > underline, Colour colour, AffineTransform transform) const
Definition juce_TextEditor.cpp:503
void beginNewLine()
Definition juce_TextEditor.cpp:416
float lineHeight
Definition juce_TextEditor.cpp:668
bool shouldWrap(const float x) const noexcept
Definition juce_TextEditor.cpp:734
float indexToX(int indexToFind) const
Definition juce_TextEditor.cpp:553
bool getCharPosition(int index, Point< float > &anchor, float &lineHeightFound)
Definition juce_TextEditor.cpp:600
int getTextRight()
Definition juce_TextEditor.cpp:648
int xToIndex(float xToFind) const
Definition juce_TextEditor.cpp:572
bool next()
Definition juce_TextEditor.cpp:304
Justification justification
Definition juce_TextEditor.cpp:676
const UniformTextSection * currentSection
Definition juce_TextEditor.cpp:674
const bool underlineWhitespace
Definition juce_TextEditor.cpp:681
Definition juce_TextEditor.cpp:787
RemoveAction(TextEditor &ed, Range< int > rangeToRemove, int oldCaret, int newCaret, const Array< UniformTextSection * > &oldSections)
Definition juce_TextEditor.cpp:788
const int newCaretPos
Definition juce_TextEditor.cpp:824
OwnedArray< UniformTextSection > removedSections
Definition juce_TextEditor.cpp:825
bool perform() override
Definition juce_TextEditor.cpp:798
const int oldCaretPos
Definition juce_TextEditor.cpp:824
int getSizeInUnits() override
Definition juce_TextEditor.cpp:811
const Range< int > range
Definition juce_TextEditor.cpp:823
bool undo() override
Definition juce_TextEditor.cpp:804
TextEditor & owner
Definition juce_TextEditor.cpp:822
Definition juce_TextEditor.cpp:882
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Definition juce_TextEditor.cpp:903
int lastWordWrapWidth
Definition juce_TextEditor.cpp:909
TextEditor & owner
Definition juce_TextEditor.cpp:908
bool reentrant
Definition juce_TextEditor.cpp:910
TextEditorViewport(TextEditor &ed)
Definition juce_TextEditor.cpp:883
void visibleAreaChanged(const Rectangle< int > &) override
Definition juce_TextEditor.cpp:885
Definition juce_TextEditor.cpp:834
TextEditor & owner
Definition juce_TextEditor.cpp:869
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Definition juce_TextEditor.cpp:872
TextHolderComponent(TextEditor &ed)
Definition juce_TextEditor.cpp:835
~TextHolderComponent() override
Definition juce_TextEditor.cpp:844
void paint(Graphics &g) override
Definition juce_TextEditor.cpp:849
void restartTimer()
Definition juce_TextEditor.cpp:854
void timerCallback() override
Definition juce_TextEditor.cpp:859
void valueChanged(Value &) override
Definition juce_TextEditor.cpp:864
static bool invokeKeyFunction(CallbackClass &target, const KeyPress &key)
Definition juce_TextEditorKeyMapper.h:43
const char * text
Definition swell-functions.h:167
int n
Definition crypt.c:458
return c
Definition crypt.c:175
ZCONST char * key
Definition crypt.c:587
int r
Definition crypt.c:458
b
Definition crypt.c:628
void handler(int signal)
Definition fileio.c:1632
typedef int(UZ_EXP MsgFn)()
mo
Definition zipinfo.c:2287
#define const
Definition zconf.h:137