Browse Source

Added a class TextEditor::InputFilter to perform custom filters on text input.

tags/2021-05-28
jules 12 years ago
parent
commit
a180c6c358
2 changed files with 171 additions and 178 deletions
  1. +105
    -160
      modules/juce_gui_basics/widgets/juce_TextEditor.cpp
  2. +66
    -18
      modules/juce_gui_basics/widgets/juce_TextEditor.h

+ 105
- 160
modules/juce_gui_basics/widgets/juce_TextEditor.cpp View File

@@ -67,7 +67,7 @@ public:
}
UniformTextSection (const UniformTextSection& other)
: font (other.font), colour (other.colour)
: font (other.font), colour (other.colour)
{
atoms.ensureStorageAllocated (other.atoms.size());
@@ -80,39 +80,28 @@ public:
void clear()
{
for (int i = atoms.size(); --i >= 0;)
delete getAtom(i);
delete atoms.getUnchecked (i);
atoms.clear();
}
int getNumAtoms() const
{
return atoms.size();
}
TextAtom* getAtom (const int index) const noexcept
{
return atoms.getUnchecked (index);
}
void append (const UniformTextSection& other, const juce_wchar passwordCharacter)
void append (const UniformTextSection& other, const juce_wchar passwordChar)
{
if (other.atoms.size() > 0)
{
TextAtom* const lastAtom = atoms.getLast();
int i = 0;
if (lastAtom != nullptr)
if (TextAtom* const lastAtom = atoms.getLast())
{
if (! CharacterFunctions::isWhitespace (lastAtom->atomText.getLastCharacter()))
{
TextAtom* const first = other.getAtom(0);
TextAtom* const first = other.atoms.getUnchecked(0);
if (! CharacterFunctions::isWhitespace (first->atomText[0]))
{
lastAtom->atomText += first->atomText;
lastAtom->numChars = (uint16) (lastAtom->numChars + first->numChars);
lastAtom->width = font.getStringWidthFloat (lastAtom->getText (passwordCharacter));
lastAtom->width = font.getStringWidthFloat (lastAtom->getText (passwordChar));
delete first;
++i;
}
@@ -123,30 +112,27 @@ public:
while (i < other.atoms.size())
{
atoms.add (other.getAtom(i));
atoms.add (other.atoms.getUnchecked(i));
++i;
}
}
}
UniformTextSection* split (const int indexToBreakAt,
const juce_wchar passwordCharacter)
UniformTextSection* split (const int indexToBreakAt, const juce_wchar passwordChar)
{
UniformTextSection* const section2 = new UniformTextSection (String::empty,
font, colour,
passwordCharacter);
UniformTextSection* const section2 = new UniformTextSection (String::empty, font, colour, passwordChar);
int index = 0;
for (int i = 0; i < atoms.size(); ++i)
{
TextAtom* const atom = getAtom(i);
TextAtom* const atom = atoms.getUnchecked(i);
const int nextIndex = index + atom->numChars;
if (index == indexToBreakAt)
{
for (int j = i; j < atoms.size(); ++j)
section2->atoms.add (getAtom (j));
section2->atoms.add (atoms.getUnchecked (j));
for (int j = atoms.size(); --j >= i;)
atoms.remove (j);
@@ -158,17 +144,17 @@ public:
TextAtom* const secondAtom = new TextAtom();
secondAtom->atomText = atom->atomText.substring (indexToBreakAt - index);
secondAtom->width = font.getStringWidthFloat (secondAtom->getText (passwordCharacter));
secondAtom->width = font.getStringWidthFloat (secondAtom->getText (passwordChar));
secondAtom->numChars = (uint16) secondAtom->atomText.length();
section2->atoms.add (secondAtom);
atom->atomText = atom->atomText.substring (0, indexToBreakAt - index);
atom->width = font.getStringWidthFloat (atom->getText (passwordCharacter));
atom->width = font.getStringWidthFloat (atom->getText (passwordChar));
atom->numChars = (uint16) (indexToBreakAt - index);
for (int j = i + 1; j < atoms.size(); ++j)
section2->atoms.add (getAtom (j));
section2->atoms.add (atoms.getUnchecked (j));
for (int j = atoms.size(); --j > i;)
atoms.remove (j);
@@ -185,7 +171,7 @@ public:
void appendAllText (MemoryOutputStream& mo) const
{
for (int i = 0; i < atoms.size(); ++i)
mo << getAtom(i)->atomText;
mo << atoms.getUnchecked(i)->atomText;
}
void appendSubstring (MemoryOutputStream& mo, const Range<int>& range) const
@@ -193,7 +179,7 @@ public:
int index = 0;
for (int i = 0; i < atoms.size(); ++i)
{
const TextAtom* const atom = getAtom (i);
const TextAtom* const atom = atoms.getUnchecked (i);
const int nextIndex = index + atom->numChars;
if (range.getStart() < nextIndex)
@@ -211,18 +197,17 @@ public:
}
}
int getTotalLength() const
int getTotalLength() const noexcept
{
int total = 0;
for (int i = atoms.size(); --i >= 0;)
total += getAtom(i)->numChars;
total += atoms.getUnchecked(i)->numChars;
return total;
}
void setFont (const Font& newFont,
const juce_wchar passwordCharacter)
void setFont (const Font& newFont, const juce_wchar passwordChar)
{
if (font != newFont)
{
@@ -231,7 +216,7 @@ public:
for (int i = atoms.size(); --i >= 0;)
{
TextAtom* const atom = atoms.getUnchecked(i);
atom->width = newFont.getStringWidthFloat (atom->getText (passwordCharacter));
atom->width = newFont.getStringWidthFloat (atom->getText (passwordChar));
}
}
}
@@ -239,13 +224,10 @@ public:
//==============================================================================
Font font;
Colour colour;
private:
Array <TextAtom*> atoms;
//==============================================================================
void initialiseAtoms (const String& textToParse,
const juce_wchar passwordCharacter)
private:
void initialiseAtoms (const String& textToParse, const juce_wchar passwordChar)
{
String::CharPointerType text (textToParse.getCharPointer());
@@ -294,8 +276,7 @@ private:
TextAtom* const atom = new TextAtom();
atom->atomText = String (start, numChars);
atom->width = font.getStringWidthFloat (atom->getText (passwordCharacter));
atom->width = font.getStringWidthFloat (atom->getText (passwordChar));
atom->numChars = (uint16) numChars;
atoms.add (atom);
@@ -399,9 +380,9 @@ public:
moveToEndOfLastAtom();
return false;
}
else if (atomIndex >= currentSection->getNumAtoms() - 1)
else if (atomIndex >= currentSection->atoms.size() - 1)
{
if (atomIndex >= currentSection->getNumAtoms())
if (atomIndex >= currentSection->atoms.size())
{
if (++sectionIndex >= sections.size())
{
@@ -414,7 +395,7 @@ public:
}
else
{
const TextAtom* const lastAtom = currentSection->getAtom (atomIndex);
const TextAtom* const lastAtom = currentSection->atoms.getUnchecked (atomIndex);
if (! lastAtom->isWhitespace())
{
@@ -428,10 +409,10 @@ public:
{
const UniformTextSection* const s = sections.getUnchecked (section);
if (s->getNumAtoms() == 0)
if (s->atoms.size() == 0)
break;
const TextAtom* const nextAtom = s->getAtom (0);
const TextAtom* const nextAtom = s->atoms.getUnchecked (0);
if (nextAtom->isWhitespace())
break;
@@ -450,7 +431,7 @@ public:
break;
}
if (s->getNumAtoms() > 1)
if (s->atoms.size() > 1)
break;
}
}
@@ -466,7 +447,7 @@ public:
beginNewLine();
}
atom = currentSection->getAtom (atomIndex);
atom = currentSection->atoms.getUnchecked (atomIndex);
atomRight = atomX + atom->width;
++atomIndex;
@@ -523,7 +504,7 @@ public:
bool checkSize = false;
if (tempAtomIndex >= section->getNumAtoms())
if (tempAtomIndex >= section->atoms.size())
{
if (++tempSectionIndex >= sections.size())
break;
@@ -533,7 +514,7 @@ public:
checkSize = true;
}
const TextAtom* const nextAtom = section->getAtom (tempAtomIndex);
const TextAtom* const nextAtom = section->atoms.getUnchecked (tempAtomIndex);
if (nextAtom == nullptr)
break;
@@ -570,16 +551,15 @@ public:
GlyphArrangement ga;
ga.addLineOfText (currentSection->font,
atom->getTrimmedText (passwordCharacter),
atomX,
(float) roundToInt (lineY + lineHeight - maxDescent));
atomX, (float) roundToInt (lineY + lineHeight - maxDescent));
ga.draw (g);
}
}
void drawSelection (Graphics& g, const Range<int>& selection) const
void drawSelection (Graphics& g, const Range<int>& selected) const
{
const int startX = roundToInt (indexToX (selection.getStart()));
const int endX = roundToInt (indexToX (selection.getEnd()));
const int startX = roundToInt (indexToX (selected.getStart()));
const int endX = roundToInt (indexToX (selected.getEnd()));
const int y = roundToInt (lineY);
const int nextY = roundToInt (lineY + lineHeight);
@@ -599,7 +579,7 @@ public:
}
void drawSelectedText (Graphics& g,
const Range<int>& selection,
const Range<int>& selected,
const Colour& selectedTextColour) const
{
if (passwordCharacter != 0 || ! atom->isWhitespace())
@@ -607,24 +587,23 @@ public:
GlyphArrangement ga;
ga.addLineOfText (currentSection->font,
atom->getTrimmedText (passwordCharacter),
atomX,
(float) roundToInt (lineY + lineHeight - maxDescent));
atomX, (float) roundToInt (lineY + lineHeight - maxDescent));
if (selection.getEnd() < indexInText + atom->numChars)
if (selected.getEnd() < indexInText + atom->numChars)
{
GlyphArrangement ga2 (ga);
ga2.removeRangeOfGlyphs (0, selection.getEnd() - indexInText);
ga.removeRangeOfGlyphs (selection.getEnd() - indexInText, -1);
ga2.removeRangeOfGlyphs (0, selected.getEnd() - indexInText);
ga.removeRangeOfGlyphs (selected.getEnd() - indexInText, -1);
g.setColour (currentSection->colour);
ga2.draw (g);
}
if (selection.getStart() > indexInText)
if (selected.getStart() > indexInText)
{
GlyphArrangement ga2 (ga);
ga2.removeRangeOfGlyphs (selection.getStart() - indexInText, -1);
ga.removeRangeOfGlyphs (0, selection.getStart() - indexInText);
ga2.removeRangeOfGlyphs (selected.getStart() - indexInText, -1);
ga.removeRangeOfGlyphs (0, selected.getStart() - indexInText);
g.setColour (currentSection->colour);
ga2.draw (g);
@@ -726,7 +705,7 @@ private:
}
}
bool shouldWrap (const float x) const
bool shouldWrap (const float x) const noexcept
{
return (x - 0.0001f) >= wordWrapWidth;
}
@@ -824,12 +803,11 @@ public:
int getSizeInUnits()
{
int n = 0;
int n = 16;
for (int i = removedSections.size(); --i >= 0;)
n += removedSections.getUnchecked (i)->getTotalLength();
return n + 16;
return n;
}
private:
@@ -957,7 +935,6 @@ TextEditor::TextEditor (const String& name,
menuActive (false),
valueTextNeedsUpdating (false),
consumeEscAndReturnKeys (true),
maxTextLength (0),
leftIndent (4),
topIndent (4),
lastTransactionTime (0),
@@ -982,11 +959,8 @@ TextEditor::TextEditor (const String& name,
TextEditor::~TextEditor()
{
if (wasFocused)
{
ComponentPeer* const peer = getPeer();
if (peer != nullptr)
if (ComponentPeer* const peer = getPeer())
peer->dismissPendingTextInput();
}
textValue.referTo (Value());
clearInternal (0);
@@ -1105,7 +1079,6 @@ void TextEditor::setFont (const Font& newFont)
void TextEditor::applyFontToAllText (const Font& newFont)
{
currentFont = newFont;
const Colour overallColour (findColour (textColourId));
for (int i = sections.size(); --i >= 0;)
@@ -1155,11 +1128,32 @@ void TextEditor::updateCaretPosition()
caret->setCaretPosition (getCaretRectangle().translated (leftIndent, topIndent));
}
TextEditor::LengthAndCharacterRestriction::LengthAndCharacterRestriction (int maxLen, const String& chars)
: allowedCharacters (chars), maxLength (maxLen)
{}
String TextEditor::LengthAndCharacterRestriction::filterNewText (TextEditor& ed, const String& newInput)
{
String t (newInput);
if (allowedCharacters.isNotEmpty())
t = t.retainCharacters (allowedCharacters);
if (maxLength > 0)
t = t.substring (0, maxLength - (ed.getTotalNumChars() - ed.getHighlightedRegion().getLength()));
return t;
}
void TextEditor::setInputFilter (InputFilter* newFilter, bool takeOwnership)
{
inputFilter.set (newFilter, takeOwnership);
}
void TextEditor::setInputRestrictions (const int maxLen,
const String& chars)
{
maxTextLength = jmax (0, maxLen);
allowedCharacters = chars;
setInputFilter (new LengthAndCharacterRestriction (maxLen, chars), true);
}
void TextEditor::setTextToShowWhenEmpty (const String& text, const Colour& colourToUse)
@@ -1262,25 +1256,11 @@ void TextEditor::textChanged()
}
}
void TextEditor::returnPressed()
{
postCommandMessage (TextEditorDefs::returnKeyMessageId);
}
void TextEditor::escapePressed()
{
postCommandMessage (TextEditorDefs::escapeKeyMessageId);
}
void TextEditor::addListener (TextEditorListener* const newListener)
{
listeners.add (newListener);
}
void TextEditor::returnPressed() { postCommandMessage (TextEditorDefs::returnKeyMessageId); }
void TextEditor::escapePressed() { postCommandMessage (TextEditorDefs::escapeKeyMessageId); }
void TextEditor::removeListener (TextEditorListener* const listenerToRemove)
{
listeners.remove (listenerToRemove);
}
void TextEditor::addListener (TextEditorListener* const l) { listeners.add (l); }
void TextEditor::removeListener (TextEditorListener* const l) { listeners.remove (l); }
//==============================================================================
void TextEditor::timerCallbackInt()
@@ -1430,21 +1410,13 @@ void TextEditor::updateTextHolderSize()
}
}
int TextEditor::getTextWidth() const
{
return textHolder->getWidth();
}
int TextEditor::getTextHeight() const
{
return textHolder->getHeight();
}
int TextEditor::getTextWidth() const { return textHolder->getWidth(); }
int TextEditor::getTextHeight() const { return textHolder->getHeight(); }
void TextEditor::setIndents (const int newLeftIndent,
const int newTopIndent)
void TextEditor::setIndents (const int newLeftIndent, const int newTopIndent)
{
leftIndent = newLeftIndent;
topIndent = newTopIndent;
topIndent = newTopIndent;
}
void TextEditor::setBorder (const BorderSize<int>& border)
@@ -1561,32 +1533,21 @@ int TextEditor::getTextIndexAt (const int x, const int y)
void TextEditor::insertTextAtCaret (const String& t)
{
String newText (t);
if (allowedCharacters.isNotEmpty())
newText = newText.retainCharacters (allowedCharacters);
String newText (inputFilter != nullptr ? inputFilter->filterNewText (*this, t) : t);
if (! isMultiLine())
newText = newText.replaceCharacters ("\r\n", " ");
else
if (isMultiLine())
newText = newText.replace ("\r\n", "\n");
else
newText = newText.replaceCharacters ("\r\n", " ");
const int newCaretPos = selection.getStart() + newText.length();
const int insertIndex = selection.getStart();
const int newCaretPos = insertIndex + newText.length();
remove (selection, getUndoManager(),
newText.isNotEmpty() ? newCaretPos - 1 : newCaretPos);
if (maxTextLength > 0)
newText = newText.substring (0, maxTextLength - getTotalNumChars());
if (newText.isNotEmpty())
insert (newText,
insertIndex,
currentFont,
findColour (textColourId),
getUndoManager(),
newCaretPos);
insert (newText, insertIndex, currentFont, findColour (textColourId),
getUndoManager(), newCaretPos);
textChanged();
}
@@ -1714,16 +1675,12 @@ void TextEditor::paintOverChildren (Graphics& g)
g.setFont (getFont());
if (isMultiLine())
{
g.drawText (textToShowWhenEmpty, getLocalBounds(),
Justification::centred, true);
}
else
{
g.drawText (textToShowWhenEmpty,
leftIndent, 0, viewport->getWidth() - leftIndent, getHeight(),
Justification::centredLeft, true);
}
}
getLookAndFeel().drawTextEditorOutline (g, getWidth(), getHeight(), *this);
@@ -1888,7 +1845,7 @@ void TextEditor::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& w
}
//==============================================================================
bool TextEditor::moveCaretWithTransation (const int newPos, const bool selecting)
bool TextEditor::moveCaretWithTransaction (const int newPos, const bool selecting)
{
newTransaction();
moveCaretTo (newPos, selecting);
@@ -1904,7 +1861,7 @@ bool TextEditor::moveCaretLeft (bool moveInWholeWordSteps, bool selecting)
else
--pos;
return moveCaretWithTransation (pos, selecting);
return moveCaretWithTransaction (pos, selecting);
}
bool TextEditor::moveCaretRight (bool moveInWholeWordSteps, bool selecting)
@@ -1916,7 +1873,7 @@ bool TextEditor::moveCaretRight (bool moveInWholeWordSteps, bool selecting)
else
++pos;
return moveCaretWithTransation (pos, selecting);
return moveCaretWithTransaction (pos, selecting);
}
bool TextEditor::moveCaretUp (bool selecting)
@@ -1925,7 +1882,7 @@ bool TextEditor::moveCaretUp (bool selecting)
return moveCaretToStartOfLine (selecting);
const Rectangle<float> caretPos (getCaretRectangle().toFloat());
return moveCaretWithTransation (indexAtPosition (caretPos.getX(), caretPos.getY() - 1.0f), selecting);
return moveCaretWithTransaction (indexAtPosition (caretPos.getX(), caretPos.getY() - 1.0f), selecting);
}
bool TextEditor::moveCaretDown (bool selecting)
@@ -1934,7 +1891,7 @@ bool TextEditor::moveCaretDown (bool selecting)
return moveCaretToEndOfLine (selecting);
const Rectangle<float> caretPos (getCaretRectangle().toFloat());
return moveCaretWithTransation (indexAtPosition (caretPos.getX(), caretPos.getBottom() + 1.0f), selecting);
return moveCaretWithTransaction (indexAtPosition (caretPos.getX(), caretPos.getBottom() + 1.0f), selecting);
}
bool TextEditor::pageUp (bool selecting)
@@ -1943,7 +1900,7 @@ bool TextEditor::pageUp (bool selecting)
return moveCaretToStartOfLine (selecting);
const Rectangle<float> caretPos (getCaretRectangle().toFloat());
return moveCaretWithTransation (indexAtPosition (caretPos.getX(), caretPos.getY() - viewport->getViewHeight()), selecting);
return moveCaretWithTransaction (indexAtPosition (caretPos.getX(), caretPos.getY() - viewport->getViewHeight()), selecting);
}
bool TextEditor::pageDown (bool selecting)
@@ -1952,14 +1909,12 @@ bool TextEditor::pageDown (bool selecting)
return moveCaretToEndOfLine (selecting);
const Rectangle<float> caretPos (getCaretRectangle().toFloat());
return moveCaretWithTransation (indexAtPosition (caretPos.getX(), caretPos.getBottom() + viewport->getViewHeight()), selecting);
return moveCaretWithTransaction (indexAtPosition (caretPos.getX(), caretPos.getBottom() + viewport->getViewHeight()), selecting);
}
void TextEditor::scrollByLines (int deltaLines)
{
ScrollBar* scrollbar = viewport->getVerticalScrollBar();
if (scrollbar != nullptr)
if (ScrollBar* scrollbar = viewport->getVerticalScrollBar())
scrollbar->moveScrollbarInSteps (deltaLines);
}
@@ -1977,24 +1932,24 @@ bool TextEditor::scrollUp()
bool TextEditor::moveCaretToTop (bool selecting)
{
return moveCaretWithTransation (0, selecting);
return moveCaretWithTransaction (0, selecting);
}
bool TextEditor::moveCaretToStartOfLine (bool selecting)
{
const Rectangle<float> caretPos (getCaretRectangle().toFloat());
return moveCaretWithTransation (indexAtPosition (0.0f, caretPos.getY()), selecting);
return moveCaretWithTransaction (indexAtPosition (0.0f, caretPos.getY()), selecting);
}
bool TextEditor::moveCaretToEnd (bool selecting)
{
return moveCaretWithTransation (getTotalNumChars(), selecting);
return moveCaretWithTransaction (getTotalNumChars(), selecting);
}
bool TextEditor::moveCaretToEndOfLine (bool selecting)
{
const Rectangle<float> caretPos (getCaretRectangle().toFloat());
return moveCaretWithTransation (indexAtPosition ((float) textHolder->getWidth(), caretPos.getY()), selecting);
return moveCaretWithTransaction (indexAtPosition ((float) textHolder->getWidth(), caretPos.getY()), selecting);
}
bool TextEditor::deleteBackwards (bool moveInWholeWordSteps)
@@ -2128,9 +2083,9 @@ void TextEditor::focusGained (FocusChangeType)
repaint();
updateCaretPosition();
ComponentPeer* const peer = getPeer();
if (peer != nullptr && ! isReadOnly())
peer->textInputRequired (getScreenPosition() - peer->getScreenPosition());
if (ComponentPeer* const peer = getPeer())
if (! isReadOnly())
peer->textInputRequired (getScreenPosition() - peer->getScreenPosition());
}
void TextEditor::focusLost (FocusChangeType)
@@ -2142,8 +2097,7 @@ void TextEditor::focusLost (FocusChangeType)
underlinedSections.clear();
ComponentPeer* const peer = getPeer();
if (peer != nullptr)
if (ComponentPeer* const peer = getPeer())
peer->dismissPendingTextInput();
updateCaretPosition();
@@ -2160,14 +2114,10 @@ void TextEditor::resized()
updateTextHolderSize();
if (! isMultiLine())
{
scrollToMakeSureCursorIsVisible();
}
else
{
if (isMultiLine())
updateCaretPosition();
}
else
scrollToMakeSureCursorIsVisible();
}
void TextEditor::handleCommandMessage (const int commandId)
@@ -2600,8 +2550,3 @@ void TextEditor::coalesceSimilarSections()
}
}
}
void TextEditor::Listener::textEditorTextChanged (TextEditor&) {}
void TextEditor::Listener::textEditorReturnKeyPressed (TextEditor&) {}
void TextEditor::Listener::textEditorEscapeKeyPressed (TextEditor&) {}
void TextEditor::Listener::textEditorFocusLost (TextEditor&) {}

+ 66
- 18
modules/juce_gui_basics/widgets/juce_TextEditor.h View File

@@ -262,16 +262,6 @@ public:
*/
void setSelectAllWhenFocused (bool shouldSelectAll);
/** Sets limits on the characters that can be entered.
@param maxTextLength if this is > 0, it sets a maximum length limit; if 0, no
limit is set
@param allowedCharacters if this is non-empty, then only characters that occur in
this string are allowed to be entered into the editor.
*/
void setInputRestrictions (int maxTextLength,
const String& allowedCharacters = String::empty);
/** When the text editor is empty, it can be set to display a message.
This is handy for things like telling the user what to type in the box - the
@@ -292,23 +282,23 @@ public:
@see TextEditor::addListener
*/
class JUCE_API Listener
class Listener
{
public:
/** Destructor. */
virtual ~Listener() {}
/** Called when the user changes the text in some way. */
virtual void textEditorTextChanged (TextEditor& editor);
virtual void textEditorTextChanged (TextEditor&) {}
/** Called when the user presses the return key. */
virtual void textEditorReturnKeyPressed (TextEditor& editor);
virtual void textEditorReturnKeyPressed (TextEditor&) {}
/** Called when the user presses the escape key. */
virtual void textEditorEscapeKeyPressed (TextEditor& editor);
virtual void textEditorEscapeKeyPressed (TextEditor&) {}
/** Called when the text editor loses focus. */
virtual void textEditorFocusLost (TextEditor& editor);
virtual void textEditorFocusLost (TextEditor&) {}
};
/** Registers a listener to be told when things happen to the text.
@@ -538,6 +528,65 @@ public:
*/
virtual void performPopupMenuAction (int menuItemID);
//==============================================================================
/** Base class for input filters that can be applied to a TextEditor to restrict
the text that can be entered.
*/
class InputFilter
{
public:
InputFilter() {}
virtual ~InputFilter() {}
/** This method is called whenever text is entered into the editor.
An implementation of this class should should check the input string,
and return an edited version of it that should be used.
*/
virtual String filterNewText (TextEditor&, const String& newInput) = 0;
};
/** An input filter for a TextEditor that limits the length of text and/or the
characters that it may contain.
*/
class JUCE_API LengthAndCharacterRestriction : public InputFilter
{
public:
/** Creates a filter that limits the length of text, and/or the characters that it can contain.
@param maxTextLength if this is > 0, it sets a maximum length limit; if <= 0, no
limit is set
@param allowedCharacters if this is non-empty, then only characters that occur in
this string are allowed to be entered into the editor.
*/
LengthAndCharacterRestriction (int maxNumChars, const String& allowedCharacters);
private:
String allowedCharacters;
int maxLength;
String filterNewText (TextEditor&, const String&);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LengthAndCharacterRestriction);
};
/** Sets an input filter that should be applied to this editor.
The filter can be nullptr, to remove any existing filters.
If takeOwnership is true, then the filter will be owned and deleted by the editor
when no longer needed.
*/
void setInputFilter (InputFilter* newFilter, bool takeOwnership);
/** Sets limits on the characters that can be entered.
This is just a shortcut that passes an instance of the LengthAndCharacterRestriction
class to setInputFilter().
@param maxTextLength if this is > 0, it sets a maximum length limit; if 0, no
limit is set
@param allowedCharacters if this is non-empty, then only characters that occur in
this string are allowed to be entered into the editor.
*/
void setInputRestrictions (int maxTextLength,
const String& allowedCharacters = String::empty);
//==============================================================================
/** @internal */
void paint (Graphics&);
@@ -621,7 +670,6 @@ private:
UndoManager undoManager;
ScopedPointer<CaretComponent> caret;
int maxTextLength;
Range<int> selection;
int leftIndent, topIndent;
unsigned int lastTransactionTime;
@@ -632,6 +680,7 @@ private:
String textToShowWhenEmpty;
Colour colourForTextWhenEmpty;
juce_wchar passwordCharacter;
OptionalScopedPointer<InputFilter> inputFilter;
Value textValue;
enum
@@ -641,7 +690,6 @@ private:
draggingSelectionEnd
} dragType;
String allowedCharacters;
ListenerList <Listener> listeners;
Array <Range<int> > underlinedSections;
@@ -661,7 +709,7 @@ private:
int indexAtPosition (float x, float y);
int findWordBreakAfter (int position) const;
int findWordBreakBefore (int position) const;
bool moveCaretWithTransation (int newPos, bool selecting);
bool moveCaretWithTransaction (int newPos, bool selecting);
friend class TextHolderComponent;
friend class TextEditorViewport;
void drawContent (Graphics&);


Loading…
Cancel
Save