diff --git a/modules/juce_gui_basics/widgets/juce_TextEditor.cpp b/modules/juce_gui_basics/widgets/juce_TextEditor.cpp index 413ac80b1a..c0a0775c72 100644 --- a/modules/juce_gui_basics/widgets/juce_TextEditor.cpp +++ b/modules/juce_gui_basics/widgets/juce_TextEditor.cpp @@ -278,21 +278,11 @@ class TextEditor::Iterator { public: Iterator (const OwnedArray& sectionList, - const float wrapWidth, - const juce_wchar passwordChar) - : indexInText (0), - lineY (0), - lineHeight (0), - maxDescent (0), - atomX (0), - atomRight (0), - atom (0), - currentSection (nullptr), - sections (sectionList), - sectionIndex (0), - atomIndex (0), + float wrapWidth, juce_wchar passwordChar, float spacing) + : sections (sectionList), wordWrapWidth (wrapWidth), - passwordCharacter (passwordChar) + passwordCharacter (passwordChar), + lineSpacing (spacing) { jassert (wordWrapWidth > 0); @@ -319,6 +309,7 @@ public: atomIndex (other.atomIndex), wordWrapWidth (other.wordWrapWidth), passwordCharacter (other.passwordCharacter), + lineSpacing (other.lineSpacing), tempAtom (other.tempAtom) { } @@ -337,7 +328,7 @@ public: atomX = 0; if (tempAtom.numChars > 0) - lineY += lineHeight; + lineY += lineHeight * lineSpacing; indexInText += tempAtom.numChars; @@ -472,7 +463,7 @@ public: void beginNewLine() { atomX = 0; - lineY += lineHeight; + lineY += lineHeight * lineSpacing; int tempSectionIndex = sectionIndex; int tempAtomIndex = atomIndex; @@ -547,7 +538,7 @@ public: const float startX = indexToX (selected.getStart()); const float endX = indexToX (selected.getEnd()); - area.add (startX, lineY, endX - startX, lineHeight); + area.add (startX, lineY, endX - startX, lineHeight * lineSpacing); } void drawUnderline (Graphics& g, const Range underline, const Colour colour) const @@ -664,20 +655,21 @@ public: } //============================================================================== - int indexInText; - float lineY, lineHeight, maxDescent; - float atomX, atomRight; - const TextAtom* atom; - const UniformTextSection* currentSection; + int indexInText = 0; + float lineY = 0, lineHeight = 0, maxDescent = 0; + float atomX = 0, atomRight = 0; + const TextAtom* atom = nullptr; + const UniformTextSection* currentSection = nullptr; private: const OwnedArray& sections; - int sectionIndex, atomIndex; + int sectionIndex = 0, atomIndex = 0; const float wordWrapWidth; const juce_wchar passwordCharacter; + const float lineSpacing; TextAtom tempAtom; - Iterator& operator= (const Iterator&); + Iterator& operator= (const Iterator&) = delete; void moveToEndOfLastAtom() { @@ -688,7 +680,7 @@ private: if (atom->isNewLine()) { atomX = 0.0f; - lineY += lineHeight; + lineY += lineHeight * lineSpacing; } } } @@ -900,28 +892,6 @@ namespace TextEditorDefs TextEditor::TextEditor (const String& name, const juce_wchar passwordChar) : Component (name), - borderSize (1, 1, 1, 3), - readOnly (false), - caretVisible (true), - multiline (false), - wordWrap (false), - returnKeyStartsNewLine (false), - popupMenuEnabled (true), - selectAllTextWhenFocused (false), - scrollbarVisible (true), - wasFocused (false), - keepCaretOnScreen (true), - tabKeyUsed (false), - menuActive (false), - valueTextNeedsUpdating (false), - consumeEscAndReturnKeys (true), - styleChanged (false), - leftIndent (4), - topIndent (4), - lastTransactionTime (0), - currentFont (14.0f), - totalNumChars (0), - caretPosition (0), passwordCharacter (passwordChar), keyboardType (TextInputTarget::textKeyboard), dragType (notDragging) @@ -1292,7 +1262,7 @@ void TextEditor::repaintText (const Range range) if (wordWrapWidth > 0) { - Iterator i (sections, wordWrapWidth, passwordCharacter); + Iterator i (sections, wordWrapWidth, passwordCharacter, lineSpacing); i.getCharPosition (range.getStart(), x, y, lh); @@ -1407,7 +1377,7 @@ void TextEditor::updateTextHolderSize() { float maxWidth = 0.0f; - Iterator i (sections, wordWrapWidth, passwordCharacter); + Iterator i (sections, wordWrapWidth, passwordCharacter, lineSpacing); while (i.next()) maxWidth = jmax (maxWidth, i.atomRight); @@ -1604,7 +1574,7 @@ void TextEditor::drawContent (Graphics& g) const Rectangle clip (g.getClipBounds()); Colour selectedTextColour; - Iterator i (sections, wordWrapWidth, passwordCharacter); + Iterator i (sections, wordWrapWidth, passwordCharacter, lineSpacing); if (! selection.isEmpty()) { @@ -1648,7 +1618,7 @@ void TextEditor::drawContent (Graphics& g) { const Range underlinedSection = underlinedSections.getReference (j); - Iterator i2 (sections, wordWrapWidth, passwordCharacter); + Iterator i2 (sections, wordWrapWidth, passwordCharacter, lineSpacing); while (i2.next() && i2.lineY < clip.getBottom()) { @@ -2429,7 +2399,7 @@ void TextEditor::getCharPosition (const int index, float& cx, float& cy, float& if (wordWrapWidth > 0 && sections.size() > 0) { - Iterator i (sections, wordWrapWidth, passwordCharacter); + Iterator i (sections, wordWrapWidth, passwordCharacter, lineSpacing); i.getCharPosition (index, cx, cy, lineHeight); } @@ -2446,7 +2416,7 @@ int TextEditor::indexAtPosition (const float x, const float y) if (wordWrapWidth > 0) { - Iterator i (sections, wordWrapWidth, passwordCharacter); + Iterator i (sections, wordWrapWidth, passwordCharacter, lineSpacing); while (i.next()) { diff --git a/modules/juce_gui_basics/widgets/juce_TextEditor.h b/modules/juce_gui_basics/widgets/juce_TextEditor.h index ef0fa060cb..00e6393a4d 100644 --- a/modules/juce_gui_basics/widgets/juce_TextEditor.h +++ b/modules/juce_gui_basics/widgets/juce_TextEditor.h @@ -462,6 +462,16 @@ public: */ void setScrollToShowCursor (bool shouldScrollToShowCaret); + /** Sets the line spacing of the TextEditor. + + The default (and minimum) value is 1.0 and values > 1.0 will increase the line spacing as a + multiple of the line height e.g. for double-spacing call this method with an argument of 2.0. + */ + void setLineSpacing (float newLineSpacing) noexcept { lineSpacing = jmax (1.0f, newLineSpacing); } + + /** Returns the current line spacing of the TextEditor. */ + float getLineSpacing() const noexcept { return lineSpacing; } + //============================================================================== void moveCaretToEnd(); bool moveCaretLeft (bool moveInWholeWordSteps, bool selecting); @@ -669,32 +679,32 @@ private: ScopedPointer viewport; TextHolderComponent* textHolder; - BorderSize borderSize; - - bool readOnly; - bool caretVisible; - bool multiline; - bool wordWrap; - bool returnKeyStartsNewLine; - bool popupMenuEnabled; - bool selectAllTextWhenFocused; - bool scrollbarVisible; - bool wasFocused; - bool keepCaretOnScreen; - bool tabKeyUsed; - bool menuActive; - bool valueTextNeedsUpdating; - bool consumeEscAndReturnKeys; - bool styleChanged; + BorderSize borderSize { 1, 1, 1, 3 }; + + bool readOnly = false; + bool caretVisible = true; + bool multiline = false; + bool wordWrap = false; + bool returnKeyStartsNewLine = false; + bool popupMenuEnabled = true; + bool selectAllTextWhenFocused = false; + bool scrollbarVisible = true; + bool wasFocused = false; + bool keepCaretOnScreen = true; + bool tabKeyUsed = false; + bool menuActive = false; + bool valueTextNeedsUpdating = false; + bool consumeEscAndReturnKeys = true; + bool styleChanged = false; UndoManager undoManager; ScopedPointer caret; Range selection; - int leftIndent, topIndent; - unsigned int lastTransactionTime; - Font currentFont; - mutable int totalNumChars; - int caretPosition; + int leftIndent = 4, topIndent = 4; + unsigned int lastTransactionTime = 0; + Font currentFont { 14.0f }; + mutable int totalNumChars = 0; + int caretPosition = 0; OwnedArray sections; String textToShowWhenEmpty; Colour colourForTextWhenEmpty; @@ -702,6 +712,7 @@ private: OptionalScopedPointer inputFilter; Value textValue; VirtualKeyboardType keyboardType; + float lineSpacing = 1.0f; enum {