1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Added method TextEditor::setEscapeAndReturnKeysConsumed().

This commit is contained in:
jules 2012-08-29 19:02:57 +01:00
parent 8e0d120421
commit 9281759612
4 changed files with 201 additions and 270 deletions

View file

@ -1338,27 +1338,10 @@ private:
return getIvar<NSViewComponentPeer*> (self, "owner"); return getIvar<NSViewComponentPeer*> (self, "owner");
} }
//============================================================================== static void mouseDown (id self, SEL s, NSEvent* ev)
static void drawRect (id self, SEL, NSRect r)
{
NSViewComponentPeer* const owner = getOwner (self);
if (owner != nullptr)
owner->drawRect (r);
}
static BOOL isOpaque (id self, SEL)
{
NSViewComponentPeer* const owner = getOwner (self);
return owner == nullptr || owner->isOpaque();
}
//==============================================================================
static void mouseDown (id self, SEL, NSEvent* ev)
{ {
if (JUCEApplication::isStandaloneApp()) if (JUCEApplication::isStandaloneApp())
[self performSelector: @selector (asyncMouseDown:) asyncMouseDown (self, s, ev);
withObject: ev];
else else
// In some host situations, the host will stop modal loops from working // In some host situations, the host will stop modal loops from working
// correctly if they're called from a mouse event, so we'll trigger // correctly if they're called from a mouse event, so we'll trigger
@ -1368,19 +1351,10 @@ private:
waitUntilDone: NO]; waitUntilDone: NO];
} }
static void asyncMouseDown (id self, SEL, NSEvent* ev) static void mouseUp (id self, SEL s, NSEvent* ev)
{
NSViewComponentPeer* const owner = getOwner (self);
if (owner != nullptr)
owner->redirectMouseDown (ev);
}
static void mouseUp (id self, SEL, NSEvent* ev)
{ {
if (! JUCEApplication::isStandaloneApp()) if (! JUCEApplication::isStandaloneApp())
[self performSelector: @selector (asyncMouseUp:) asyncMouseUp (self, s, ev);
withObject: ev];
else else
// In some host situations, the host will stop modal loops from working // In some host situations, the host will stop modal loops from working
// correctly if they're called from a mouse event, so we'll trigger // correctly if they're called from a mouse event, so we'll trigger
@ -1390,55 +1364,51 @@ private:
waitUntilDone: NO]; waitUntilDone: NO];
} }
static void asyncMouseUp (id self, SEL, NSEvent* ev) { NSViewComponentPeer* const owner = getOwner (self); if (owner != nullptr) owner->redirectMouseUp (ev); } static void asyncMouseDown (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseDown (ev); }
static void mouseDragged (id self, SEL, NSEvent* ev) { NSViewComponentPeer* const owner = getOwner (self); if (owner != nullptr) owner->redirectMouseDrag (ev); } static void asyncMouseUp (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseUp (ev); }
static void mouseMoved (id self, SEL, NSEvent* ev) { NSViewComponentPeer* const owner = getOwner (self); if (owner != nullptr) owner->redirectMouseMove (ev); } static void mouseDragged (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseDrag (ev); }
static void mouseEntered (id self, SEL, NSEvent* ev) { NSViewComponentPeer* const owner = getOwner (self); if (owner != nullptr) owner->redirectMouseEnter (ev); } static void mouseMoved (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseMove (ev); }
static void mouseExited (id self, SEL, NSEvent* ev) { NSViewComponentPeer* const owner = getOwner (self); if (owner != nullptr) owner->redirectMouseExit (ev); } static void mouseEntered (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseEnter (ev); }
static void scrollWheel (id self, SEL, NSEvent* ev) { NSViewComponentPeer* const owner = getOwner (self); if (owner != nullptr) owner->redirectMouseWheel (ev); } static void mouseExited (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseExit (ev); }
static void scrollWheel (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseWheel (ev); }
static void rightMouseDown (id self, SEL, NSEvent* ev) { [(NSView*) self mouseDown: ev]; } static void rightMouseDown (id self, SEL s, NSEvent* ev) { mouseDown (self, s, ev); }
static void rightMouseDragged (id self, SEL, NSEvent* ev) { [(NSView*) self mouseDragged: ev]; } static void otherMouseDown (id self, SEL s, NSEvent* ev) { mouseDown (self, s, ev); }
static void rightMouseUp (id self, SEL, NSEvent* ev) { [(NSView*) self mouseUp: ev]; } static void rightMouseDragged (id self, SEL s, NSEvent* ev) { mouseDragged (self, s, ev); }
static void otherMouseDown (id self, SEL, NSEvent* ev) { [(NSView*) self mouseDown: ev]; } static void otherMouseDragged (id self, SEL s, NSEvent* ev) { mouseDragged (self, s, ev); }
static void otherMouseDragged (id self, SEL, NSEvent* ev) { [(NSView*) self mouseDragged: ev]; } static void rightMouseUp (id self, SEL s, NSEvent* ev) { mouseUp (self, s, ev); }
static void otherMouseUp (id self, SEL, NSEvent* ev) { [(NSView*) self mouseUp: ev]; } static void otherMouseUp (id self, SEL s, NSEvent* ev) { mouseUp (self, s, ev); }
static BOOL acceptsFirstMouse (id, SEL, NSEvent*) { return YES; } static BOOL acceptsFirstMouse (id, SEL, NSEvent*) { return YES; }
static void frameChanged (id self, SEL, NSNotification*) static void drawRect (id self, SEL, NSRect r) { if (NSViewComponentPeer* const p = getOwner (self)) p->drawRect (r); }
static void frameChanged (id self, SEL, NSNotification*) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMovedOrResized(); }
static void viewDidMoveToWindow (id self, SEL) { if (NSViewComponentPeer* const p = getOwner (self)) p->viewMovedToWindow(); }
static BOOL isOpaque (id self, SEL)
{ {
NSViewComponentPeer* const owner = getOwner (self); NSViewComponentPeer* const owner = getOwner (self);
return owner == nullptr || owner->isOpaque();
if (owner != nullptr)
owner->redirectMovedOrResized();
}
static void viewDidMoveToWindow (id self, SEL)
{
NSViewComponentPeer* const owner = getOwner (self);
if (owner != nullptr)
owner->viewMovedToWindow();
} }
//============================================================================== //==============================================================================
static void keyDown (id self, SEL, NSEvent* ev) static void keyDown (id self, SEL, NSEvent* ev)
{ {
NSViewComponentPeer* const owner = getOwner (self); if (NSViewComponentPeer* const owner = getOwner (self))
TextInputTarget* const target = owner->findCurrentTextInputTarget();
owner->textWasInserted = false;
if (target != nullptr)
[(NSView*) self interpretKeyEvents: [NSArray arrayWithObject: ev]];
else
owner->stringBeingComposed = String::empty;
if ((! owner->textWasInserted) && (owner == nullptr || ! owner->redirectKeyDown (ev)))
{ {
objc_super s = { self, [NSView class] }; TextInputTarget* const target = owner->findCurrentTextInputTarget();
objc_msgSendSuper (&s, @selector (keyDown:), ev); owner->textWasInserted = false;
if (target != nullptr)
[(NSView*) self interpretKeyEvents: [NSArray arrayWithObject: ev]];
else
owner->stringBeingComposed = String::empty;
if ((! owner->textWasInserted) && (owner == nullptr || ! owner->redirectKeyDown (ev)))
{
objc_super s = { self, [NSView class] };
objc_msgSendSuper (&s, @selector (keyDown:), ev);
}
} }
} }
@ -1457,65 +1427,63 @@ private:
static void insertText (id self, SEL, id aString) static void insertText (id self, SEL, id aString)
{ {
// This commits multi-byte text when return is pressed, or after every keypress for western keyboards // This commits multi-byte text when return is pressed, or after every keypress for western keyboards
NSViewComponentPeer* const owner = getOwner (self); if (NSViewComponentPeer* const owner = getOwner (self))
NSString* newText = [aString isKindOfClass: [NSAttributedString class]] ? [aString string] : aString;
if ([newText length] > 0)
{ {
TextInputTarget* const target = owner->findCurrentTextInputTarget(); NSString* newText = [aString isKindOfClass: [NSAttributedString class]] ? [aString string] : aString;
if (target != nullptr) if ([newText length] > 0)
{ {
target->insertTextAtCaret (nsStringToJuce (newText)); if (TextInputTarget* const target = owner->findCurrentTextInputTarget())
owner->textWasInserted = true; {
} target->insertTextAtCaret (nsStringToJuce (newText));
} owner->textWasInserted = true;
}
owner->stringBeingComposed = String::empty;
}
static void doCommandBySelector (id, SEL, SEL) {}
static void setMarkedText (id self, SEL, id aString, NSRange)
{
NSViewComponentPeer* const owner = getOwner (self);
owner->stringBeingComposed = nsStringToJuce ([aString isKindOfClass: [NSAttributedString class]]
? [aString string] : aString);
TextInputTarget* const target = owner->findCurrentTextInputTarget();
if (target != nullptr)
{
const Range<int> currentHighlight (target->getHighlightedRegion());
target->insertTextAtCaret (owner->stringBeingComposed);
target->setHighlightedRegion (currentHighlight.withLength (owner->stringBeingComposed.length()));
owner->textWasInserted = true;
}
}
static void unmarkText (id self, SEL)
{
NSViewComponentPeer* const owner = getOwner (self);
if (owner->stringBeingComposed.isNotEmpty())
{
TextInputTarget* const target = owner->findCurrentTextInputTarget();
if (target != nullptr)
{
target->insertTextAtCaret (owner->stringBeingComposed);
owner->textWasInserted = true;
} }
owner->stringBeingComposed = String::empty; owner->stringBeingComposed = String::empty;
} }
} }
static void doCommandBySelector (id, SEL, SEL) {}
static void setMarkedText (id self, SEL, id aString, NSRange)
{
if (NSViewComponentPeer* const owner = getOwner (self))
{
owner->stringBeingComposed = nsStringToJuce ([aString isKindOfClass: [NSAttributedString class]]
? [aString string] : aString);
if (TextInputTarget* const target = owner->findCurrentTextInputTarget())
{
const Range<int> currentHighlight (target->getHighlightedRegion());
target->insertTextAtCaret (owner->stringBeingComposed);
target->setHighlightedRegion (currentHighlight.withLength (owner->stringBeingComposed.length()));
owner->textWasInserted = true;
}
}
}
static void unmarkText (id self, SEL)
{
if (NSViewComponentPeer* const owner = getOwner (self))
{
if (owner->stringBeingComposed.isNotEmpty())
{
if (TextInputTarget* const target = owner->findCurrentTextInputTarget())
{
target->insertTextAtCaret (owner->stringBeingComposed);
owner->textWasInserted = true;
}
owner->stringBeingComposed = String::empty;
}
}
}
static BOOL hasMarkedText (id self, SEL) static BOOL hasMarkedText (id self, SEL)
{ {
return getOwner (self)->stringBeingComposed.isNotEmpty(); NSViewComponentPeer* const owner = getOwner (self);
return owner != nullptr && owner->stringBeingComposed.isNotEmpty();
} }
static long conversationIdentifier (id self, SEL) static long conversationIdentifier (id self, SEL)
@ -1525,15 +1493,15 @@ private:
static NSAttributedString* attributedSubstringFromRange (id self, SEL, NSRange theRange) static NSAttributedString* attributedSubstringFromRange (id self, SEL, NSRange theRange)
{ {
NSViewComponentPeer* const owner = getOwner (self); if (NSViewComponentPeer* const owner = getOwner (self))
TextInputTarget* const target = owner->findCurrentTextInputTarget();
if (target != nullptr)
{ {
const Range<int> r ((int) theRange.location, if (TextInputTarget* const target = owner->findCurrentTextInputTarget())
(int) (theRange.location + theRange.length)); {
const Range<int> r ((int) theRange.location,
(int) (theRange.location + theRange.length));
return [[[NSAttributedString alloc] initWithString: juceStringToNS (target->getTextInRange (r))] autorelease]; return [[[NSAttributedString alloc] initWithString: juceStringToNS (target->getTextInRange (r))] autorelease];
}
} }
return nil; return nil;
@ -1548,15 +1516,15 @@ private:
static NSRange selectedRange (id self, SEL) static NSRange selectedRange (id self, SEL)
{ {
NSViewComponentPeer* const owner = getOwner (self); if (NSViewComponentPeer* const owner = getOwner (self))
TextInputTarget* const target = owner->findCurrentTextInputTarget();
if (target != nullptr)
{ {
const Range<int> highlight (target->getHighlightedRegion()); if (TextInputTarget* const target = owner->findCurrentTextInputTarget())
{
const Range<int> highlight (target->getHighlightedRegion());
if (! highlight.isEmpty()) if (! highlight.isEmpty())
return NSMakeRange (highlight.getStart(), highlight.getLength()); return NSMakeRange (highlight.getStart(), highlight.getLength());
}
} }
return NSMakeRange (NSNotFound, 0); return NSMakeRange (NSNotFound, 0);
@ -1564,18 +1532,20 @@ private:
static NSRect firstRectForCharacterRange (id self, SEL, NSRange) static NSRect firstRectForCharacterRange (id self, SEL, NSRange)
{ {
NSViewComponentPeer* const owner = getOwner (self); if (NSViewComponentPeer* const owner = getOwner (self))
Component* const comp = dynamic_cast <Component*> (owner->findCurrentTextInputTarget()); {
if (Component* const comp = dynamic_cast <Component*> (owner->findCurrentTextInputTarget()))
{
const Rectangle<int> bounds (comp->getScreenBounds());
if (comp == nullptr) return NSMakeRect (bounds.getX(),
return NSMakeRect (0, 0, 0, 0); [[[NSScreen screens] objectAtIndex: 0] frame].size.height - bounds.getY(),
bounds.getWidth(),
bounds.getHeight());
}
}
const Rectangle<int> bounds (comp->getScreenBounds()); return NSZeroRect;
return NSMakeRect (bounds.getX(),
[[[NSScreen screens] objectAtIndex: 0] frame].size.height - bounds.getY(),
bounds.getWidth(),
bounds.getHeight());
} }
static NSUInteger characterIndexForPoint (id, SEL, NSPoint) { return NSNotFound; } static NSUInteger characterIndexForPoint (id, SEL, NSPoint) { return NSNotFound; }
@ -1584,9 +1554,7 @@ private:
//============================================================================== //==============================================================================
static void flagsChanged (id self, SEL, NSEvent* ev) static void flagsChanged (id self, SEL, NSEvent* ev)
{ {
NSViewComponentPeer* const owner = getOwner (self); if (NSViewComponentPeer* const owner = getOwner (self))
if (owner != nullptr)
owner->redirectModKeyChange (ev); owner->redirectModKeyChange (ev);
} }
@ -1605,8 +1573,7 @@ private:
static BOOL becomeFirstResponder (id self, SEL) static BOOL becomeFirstResponder (id self, SEL)
{ {
NSViewComponentPeer* const owner = getOwner (self); if (NSViewComponentPeer* const owner = getOwner (self))
if (owner != nullptr)
owner->viewFocusGain(); owner->viewFocusGain();
return YES; return YES;
@ -1614,8 +1581,7 @@ private:
static BOOL resignFirstResponder (id self, SEL) static BOOL resignFirstResponder (id self, SEL)
{ {
NSViewComponentPeer* const owner = getOwner (self); if (NSViewComponentPeer* const owner = getOwner (self))
if (owner != nullptr)
owner->viewFocusLoss(); owner->viewFocusLoss();
return YES; return YES;
@ -1628,14 +1594,9 @@ private:
} }
//============================================================================== //==============================================================================
static NSDragOperation draggingEntered (id self, SEL, id <NSDraggingInfo> sender) static NSDragOperation draggingEntered (id self, SEL s, id <NSDraggingInfo> sender)
{ {
NSViewComponentPeer* const owner = getOwner (self); return draggingUpdated (self, s, sender);
if (owner != nullptr && owner->sendDragCallback (0, sender))
return NSDragOperationCopy | NSDragOperationMove | NSDragOperationGeneric;
else
return NSDragOperationNone;
} }
static NSDragOperation draggingUpdated (id self, SEL, id <NSDraggingInfo> sender) static NSDragOperation draggingUpdated (id self, SEL, id <NSDraggingInfo> sender)
@ -1648,19 +1609,14 @@ private:
return NSDragOperationNone; return NSDragOperationNone;
} }
static void draggingEnded (id self, SEL, id <NSDraggingInfo> sender) static void draggingEnded (id self, SEL s, id <NSDraggingInfo> sender)
{ {
NSViewComponentPeer* const owner = getOwner (self); draggingExited (self, s, sender);
if (owner != nullptr)
owner->sendDragCallback (1, sender);
} }
static void draggingExited (id self, SEL, id <NSDraggingInfo> sender) static void draggingExited (id self, SEL, id <NSDraggingInfo> sender)
{ {
NSViewComponentPeer* const owner = getOwner (self); if (NSViewComponentPeer* const owner = getOwner (self))
if (owner != nullptr)
owner->sendDragCallback (1, sender); owner->sendDragCallback (1, sender);
} }

View file

@ -32,8 +32,8 @@ struct TextAtom
int numChars; int numChars;
//============================================================================== //==============================================================================
bool isWhitespace() const { return CharacterFunctions::isWhitespace (atomText[0]); } bool isWhitespace() const noexcept { return CharacterFunctions::isWhitespace (atomText[0]); }
bool isNewLine() const { return atomText[0] == '\r' || atomText[0] == '\n'; } bool isNewLine() const noexcept { return atomText[0] == '\r' || atomText[0] == '\n'; }
String getText (const juce_wchar passwordCharacter) const String getText (const juce_wchar passwordCharacter) const
{ {
@ -60,7 +60,6 @@ struct TextAtom
class TextEditor::UniformTextSection class TextEditor::UniformTextSection
{ {
public: public:
//==============================================================================
UniformTextSection (const String& text, UniformTextSection (const String& text,
const Font& font_, const Font& font_,
const Colour& colour_, const Colour& colour_,
@ -321,7 +320,6 @@ private:
class TextEditor::Iterator class TextEditor::Iterator
{ {
public: public:
//==============================================================================
Iterator (const Array <UniformTextSection*>& sections_, Iterator (const Array <UniformTextSection*>& sections_,
const float wordWrapWidth_, const float wordWrapWidth_,
const juce_wchar passwordCharacter_) const juce_wchar passwordCharacter_)
@ -751,14 +749,14 @@ private:
class TextEditor::InsertAction : public UndoableAction class TextEditor::InsertAction : public UndoableAction
{ {
public: public:
InsertAction (TextEditor& owner_, InsertAction (TextEditor& ed,
const String& text_, const String& text_,
const int insertIndex_, const int insertIndex_,
const Font& font_, const Font& font_,
const Colour& colour_, const Colour& colour_,
const int oldCaretPos_, const int oldCaretPos_,
const int newCaretPos_) const int newCaretPos_)
: owner (owner_), : owner (ed),
text (text_), text (text_),
insertIndex (insertIndex_), insertIndex (insertIndex_),
oldCaretPos (oldCaretPos_), oldCaretPos (oldCaretPos_),
@ -799,12 +797,12 @@ private:
class TextEditor::RemoveAction : public UndoableAction class TextEditor::RemoveAction : public UndoableAction
{ {
public: public:
RemoveAction (TextEditor& owner_, RemoveAction (TextEditor& ed,
const Range<int> range_, const Range<int> range_,
const int oldCaretPos_, const int oldCaretPos_,
const int newCaretPos_, const int newCaretPos_,
const Array <UniformTextSection*>& removedSections_) const Array <UniformTextSection*>& removedSections_)
: owner (owner_), : owner (ed),
range (range_), range (range_),
oldCaretPos (oldCaretPos_), oldCaretPos (oldCaretPos_),
newCaretPos (newCaretPos_), newCaretPos (newCaretPos_),
@ -860,8 +858,7 @@ class TextEditor::TextHolderComponent : public Component,
private ValueListener private ValueListener
{ {
public: public:
TextHolderComponent (TextEditor& owner_) TextHolderComponent (TextEditor& ed) : owner (ed)
: owner (owner_)
{ {
setWantsKeyboardFocus (false); setWantsKeyboardFocus (false);
setInterceptsMouseClicks (false, true); setInterceptsMouseClicks (false, true);
@ -905,8 +902,8 @@ private:
class TextEditorViewport : public Viewport class TextEditorViewport : public Viewport
{ {
public: public:
TextEditorViewport (TextEditor& owner_) TextEditorViewport (TextEditor& ed)
: owner (owner_), lastWordWrapWidth (0), rentrant (false) : owner (ed), lastWordWrapWidth (0), rentrant (false)
{ {
} }
@ -970,6 +967,7 @@ TextEditor::TextEditor (const String& name,
tabKeyUsed (false), tabKeyUsed (false),
menuActive (false), menuActive (false),
valueTextNeedsUpdating (false), valueTextNeedsUpdating (false),
consumeEscAndReturnKeys (true),
maxTextLength (0), maxTextLength (0),
leftIndent (4), leftIndent (4),
topIndent (4), topIndent (4),
@ -2062,6 +2060,11 @@ bool TextEditor::selectAll()
} }
//============================================================================== //==============================================================================
void TextEditor::setEscapeAndReturnKeysConsumed (bool shouldBeConsumed) noexcept
{
consumeEscAndReturnKeys = shouldBeConsumed;
}
bool TextEditor::keyPressed (const KeyPress& key) bool TextEditor::keyPressed (const KeyPress& key)
{ {
if (isReadOnly() && key != KeyPress ('c', ModifierKeys::commandModifier, 0)) if (isReadOnly() && key != KeyPress ('c', ModifierKeys::commandModifier, 0))
@ -2076,13 +2079,17 @@ bool TextEditor::keyPressed (const KeyPress& key)
if (returnKeyStartsNewLine) if (returnKeyStartsNewLine)
insertTextAtCaret ("\n"); insertTextAtCaret ("\n");
else else
{
returnPressed(); returnPressed();
return consumeEscAndReturnKeys;
}
} }
else if (key.isKeyCode (KeyPress::escapeKey)) else if (key.isKeyCode (KeyPress::escapeKey))
{ {
newTransaction(); newTransaction();
moveCaretTo (getCaretPosition(), false); moveCaretTo (getCaretPosition(), false);
escapePressed(); escapePressed();
return consumeEscAndReturnKeys;
} }
else if (key.getTextCharacter() >= ' ' else if (key.getTextCharacter() >= ' '
|| (tabKeyUsed && (key.getTextCharacter() == '\t'))) || (tabKeyUsed && (key.getTextCharacter() == '\t')))
@ -2110,6 +2117,11 @@ bool TextEditor::keyStateChanged (const bool isKeyDown)
return false; // We need to explicitly allow alt-F4 to pass through on Windows return false; // We need to explicitly allow alt-F4 to pass through on Windows
#endif #endif
if ((! consumeEscAndReturnKeys)
&& (KeyPress (KeyPress::escapeKey).isCurrentlyDown()
|| KeyPress (KeyPress::returnKey).isCurrentlyDown()))
return false;
// (overridden to avoid forwarding key events to the parent) // (overridden to avoid forwarding key events to the parent)
return ! ModifierKeys::getCurrentModifiers().isCommandDown(); return ! ModifierKeys::getCurrentModifiers().isCommandDown();
} }
@ -2213,7 +2225,7 @@ void TextEditor::setTemporaryUnderlining (const Array <Range<int> >& newUnderlin
//============================================================================== //==============================================================================
UndoManager* TextEditor::getUndoManager() noexcept UndoManager* TextEditor::getUndoManager() noexcept
{ {
return isReadOnly() ? 0 : &undoManager; return readOnly ? nullptr : &undoManager;
} }
void TextEditor::clearInternal (UndoManager* const um) void TextEditor::clearInternal (UndoManager* const um)
@ -2252,17 +2264,13 @@ void TextEditor::insert (const String& text,
if (insertIndex == index) if (insertIndex == index)
{ {
sections.insert (i, new UniformTextSection (text, sections.insert (i, new UniformTextSection (text, font, colour, passwordCharacter));
font, colour,
passwordCharacter));
break; break;
} }
else if (insertIndex > index && insertIndex < nextIndex) else if (insertIndex > index && insertIndex < nextIndex)
{ {
splitSection (i, insertIndex - index); splitSection (i, insertIndex - index);
sections.insert (i + 1, new UniformTextSection (text, sections.insert (i + 1, new UniformTextSection (text, font, colour, passwordCharacter));
font, colour,
passwordCharacter));
break; break;
} }
@ -2270,9 +2278,7 @@ void TextEditor::insert (const String& text,
} }
if (nextIndex == insertIndex) if (nextIndex == insertIndex)
sections.add (new UniformTextSection (text, sections.add (new UniformTextSection (text, font, colour, passwordCharacter));
font, colour,
passwordCharacter));
coalesceSimilarSections(); coalesceSimilarSections();
totalNumChars = -1; totalNumChars = -1;

View file

@ -109,6 +109,14 @@ public:
*/ */
bool isTabKeyUsedAsCharacter() const { return tabKeyUsed; } bool isTabKeyUsedAsCharacter() const { return tabKeyUsed; }
/** This can be used to change whether escape and return keypress events are
propagated up to the parent component.
The default here is true, meaning that these events are not allowed to reach the
parent, but you may want to allow them through so that they can trigger other
actions, e.g. closing a dialog box, etc.
*/
void setEscapeAndReturnKeysConsumed (bool shouldBeConsumed) noexcept;
//============================================================================== //==============================================================================
/** Changes the editor to read-only mode. /** Changes the editor to read-only mode.
@ -390,11 +398,6 @@ public:
*/ */
void setCaretPosition (int newIndex); void setCaretPosition (int newIndex);
/** Moves the caret to be the end of all the text.
@see setCaretPosition
*/
void moveCaretToEnd();
/** Attempts to scroll the text editor so that the caret ends up at /** Attempts to scroll the text editor so that the caret ends up at
a specified position. a specified position.
@ -476,6 +479,7 @@ public:
void setScrollToShowCursor (bool shouldScrollToShowCaret); void setScrollToShowCursor (bool shouldScrollToShowCaret);
//============================================================================== //==============================================================================
void moveCaretToEnd();
bool moveCaretLeft (bool moveInWholeWordSteps, bool selecting); bool moveCaretLeft (bool moveInWholeWordSteps, bool selecting);
bool moveCaretRight (bool moveInWholeWordSteps, bool selecting); bool moveCaretRight (bool moveInWholeWordSteps, bool selecting);
bool moveCaretUp (bool selecting); bool moveCaretUp (bool selecting);
@ -536,21 +540,21 @@ public:
//============================================================================== //==============================================================================
/** @internal */ /** @internal */
void paint (Graphics& g); void paint (Graphics&);
/** @internal */ /** @internal */
void paintOverChildren (Graphics& g); void paintOverChildren (Graphics&);
/** @internal */ /** @internal */
void mouseDown (const MouseEvent& e); void mouseDown (const MouseEvent&);
/** @internal */ /** @internal */
void mouseUp (const MouseEvent& e); void mouseUp (const MouseEvent&);
/** @internal */ /** @internal */
void mouseDrag (const MouseEvent& e); void mouseDrag (const MouseEvent&);
/** @internal */ /** @internal */
void mouseDoubleClick (const MouseEvent& e); void mouseDoubleClick (const MouseEvent&);
/** @internal */ /** @internal */
void mouseWheelMove (const MouseEvent&, const MouseWheelDetails&); void mouseWheelMove (const MouseEvent&, const MouseWheelDetails&);
/** @internal */ /** @internal */
bool keyPressed (const KeyPress& key); bool keyPressed (const KeyPress&);
/** @internal */ /** @internal */
bool keyStateChanged (bool isKeyDown); bool keyStateChanged (bool isKeyDown);
/** @internal */ /** @internal */
@ -575,30 +579,18 @@ protected:
/** Scrolls the minimum distance needed to get the caret into view. */ /** Scrolls the minimum distance needed to get the caret into view. */
void scrollToMakeSureCursorIsVisible(); void scrollToMakeSureCursorIsVisible();
/** @internal */
void moveCaret (int newCaretPos);
/** @internal */
void moveCaretTo (int newPosition, bool isSelecting);
/** Used internally to dispatch a text-change message. */ /** Used internally to dispatch a text-change message. */
void textChanged(); void textChanged();
/** Begins a new transaction in the UndoManager. */ /** Begins a new transaction in the UndoManager. */
void newTransaction(); void newTransaction();
/** Used internally to trigger an undo or redo. */
void doUndoRedo (bool isRedo);
/** Can be overridden to intercept return key presses directly */ /** Can be overridden to intercept return key presses directly */
virtual void returnPressed(); virtual void returnPressed();
/** Can be overridden to intercept escape key presses directly */ /** Can be overridden to intercept escape key presses directly */
virtual void escapePressed(); virtual void escapePressed();
/** @internal */
void handleCommandMessage (int commandId);
private: private:
//============================================================================== //==============================================================================
class Iterator; class Iterator;
@ -625,6 +617,7 @@ private:
bool tabKeyUsed : 1; bool tabKeyUsed : 1;
bool menuActive : 1; bool menuActive : 1;
bool valueTextNeedsUpdating : 1; bool valueTextNeedsUpdating : 1;
bool consumeEscAndReturnKeys : 1;
UndoManager undoManager; UndoManager undoManager;
ScopedPointer<CaretComponent> caret; ScopedPointer<CaretComponent> caret;
@ -652,13 +645,15 @@ private:
ListenerList <Listener> listeners; ListenerList <Listener> listeners;
Array <Range<int> > underlinedSections; Array <Range<int> > underlinedSections;
void moveCaret (int newCaretPos);
void moveCaretTo (int newPosition, bool isSelecting);
void handleCommandMessage (int);
void coalesceSimilarSections(); void coalesceSimilarSections();
void splitSection (int sectionIndex, int charToSplitAt); void splitSection (int sectionIndex, int charToSplitAt);
void clearInternal (UndoManager* um); void clearInternal (UndoManager*);
void insert (const String& text, int insertIndex, const Font& font, void insert (const String&, int insertIndex, const Font&, const Colour&, UndoManager*, int newCaretPos);
const Colour& colour, UndoManager* um, int caretPositionToMoveTo); void reinsert (int insertIndex, const Array <UniformTextSection*>&);
void reinsert (int insertIndex, const Array <UniformTextSection*>& sections); void remove (const Range<int>& range, UndoManager*, int caretPositionToMoveTo);
void remove (const Range<int>& range, UndoManager* um, int caretPositionToMoveTo);
void getCharPosition (int index, float& x, float& y, float& lineHeight) const; void getCharPosition (int index, float& x, float& y, float& lineHeight) const;
void updateCaretPosition(); void updateCaretPosition();
void updateValueFromText(); void updateValueFromText();
@ -669,11 +664,11 @@ private:
bool moveCaretWithTransation (int newPos, bool selecting); bool moveCaretWithTransation (int newPos, bool selecting);
friend class TextHolderComponent; friend class TextHolderComponent;
friend class TextEditorViewport; friend class TextEditorViewport;
void drawContent (Graphics& g); void drawContent (Graphics&);
void updateTextHolderSize(); void updateTextHolderSize();
float getWordWrapWidth() const; float getWordWrapWidth() const;
void timerCallbackInt(); void timerCallbackInt();
void repaintText (const Range<int>& range); void repaintText (const Range<int>&);
void scrollByLines (int deltaLines); void scrollByLines (int deltaLines);
bool undoOrRedo (bool shouldUndo); bool undoOrRedo (bool shouldUndo);
UndoManager* getUndoManager() noexcept; UndoManager* getUndoManager() noexcept;

View file

@ -23,49 +23,23 @@
============================================================================== ==============================================================================
*/ */
class AlertWindowTextEditor : public TextEditor static juce_wchar getDefaultPasswordChar() noexcept
{ {
public: #if JUCE_LINUX
AlertWindowTextEditor (const String& name, const bool isPasswordBox) return 0x2022;
: TextEditor (name, isPasswordBox ? getDefaultPasswordChar() : 0) #else
{ return 0x25cf;
setSelectAllWhenFocused (true); #endif
} }
void returnPressed()
{
// pass these up the component hierarchy to be trigger the buttons
getParentComponent()->keyPressed (KeyPress (KeyPress::returnKey, 0, '\n'));
}
void escapePressed()
{
// pass these up the component hierarchy to be trigger the buttons
getParentComponent()->keyPressed (KeyPress (KeyPress::escapeKey, 0, 0));
}
private:
JUCE_DECLARE_NON_COPYABLE (AlertWindowTextEditor);
static juce_wchar getDefaultPasswordChar() noexcept
{
#if JUCE_LINUX
return 0x2022;
#else
return 0x25cf;
#endif
}
};
//============================================================================== //==============================================================================
AlertWindow::AlertWindow (const String& title, AlertWindow::AlertWindow (const String& title,
const String& message, const String& message,
AlertIconType iconType, AlertIconType iconType,
Component* associatedComponent_) Component* comp)
: TopLevelWindow (title, true), : TopLevelWindow (title, true),
alertIconType (iconType), alertIconType (iconType),
associatedComponent (associatedComponent_), associatedComponent (comp),
escapeKeyCancels (true) escapeKeyCancels (true)
{ {
if (message.isEmpty()) if (message.isEmpty())
@ -175,15 +149,17 @@ void AlertWindow::addTextEditor (const String& name,
const String& onScreenLabel, const String& onScreenLabel,
const bool isPasswordBox) const bool isPasswordBox)
{ {
AlertWindowTextEditor* const tc = new AlertWindowTextEditor (name, isPasswordBox); TextEditor* ed = new TextEditor (name, isPasswordBox ? getDefaultPasswordChar() : 0);
textBoxes.add (tc); ed->setSelectAllWhenFocused (true);
allComps.add (tc); ed->setEscapeAndReturnKeysConsumed (false);
textBoxes.add (ed);
allComps.add (ed);
tc->setColour (TextEditor::outlineColourId, findColour (ComboBox::outlineColourId)); ed->setColour (TextEditor::outlineColourId, findColour (ComboBox::outlineColourId));
tc->setFont (getLookAndFeel().getAlertWindowMessageFont()); ed->setFont (getLookAndFeel().getAlertWindowMessageFont());
tc->setText (initialContents); ed->setText (initialContents);
tc->setCaretPosition (initialContents.length()); ed->setCaretPosition (initialContents.length());
addAndMakeVisible (tc); addAndMakeVisible (ed);
textboxNames.add (onScreenLabel); textboxNames.add (onScreenLabel);
updateLayout (false); updateLayout (false);
@ -343,8 +319,7 @@ void AlertWindow::paint (Graphics& g)
g.setColour (findColour (textColourId)); g.setColour (findColour (textColourId));
g.setFont (getLookAndFeel().getAlertWindowFont()); g.setFont (getLookAndFeel().getAlertWindowFont());
int i; for (int i = textBoxes.size(); --i >= 0;)
for (i = textBoxes.size(); --i >= 0;)
{ {
const TextEditor* const te = textBoxes.getUnchecked(i); const TextEditor* const te = textBoxes.getUnchecked(i);
@ -354,7 +329,7 @@ void AlertWindow::paint (Graphics& g)
Justification::centredLeft, 1); Justification::centredLeft, 1);
} }
for (i = comboBoxNames.size(); --i >= 0;) for (int i = comboBoxNames.size(); --i >= 0;)
{ {
const ComboBox* const cb = comboBoxes.getUnchecked(i); const ComboBox* const cb = comboBoxes.getUnchecked(i);
@ -364,7 +339,7 @@ void AlertWindow::paint (Graphics& g)
Justification::centredLeft, 1); Justification::centredLeft, 1);
} }
for (i = customComps.size(); --i >= 0;) for (int i = customComps.size(); --i >= 0;)
{ {
const Component* const c = customComps.getUnchecked(i); const Component* const c = customComps.getUnchecked(i);
@ -419,8 +394,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
int h = textBottom; int h = textBottom;
int buttonW = 40; int buttonW = 40;
int i; for (int i = 0; i < buttons.size(); ++i)
for (i = 0; i < buttons.size(); ++i)
buttonW += 16 + buttons.getUnchecked(i)->getWidth(); buttonW += 16 + buttons.getUnchecked(i)->getWidth();
w = jmax (buttonW, w); w = jmax (buttonW, w);
@ -430,7 +404,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
if (buttons.size() > 0) if (buttons.size() > 0)
h += 20 + buttons.getUnchecked(0)->getHeight(); h += 20 + buttons.getUnchecked(0)->getHeight();
for (i = customComps.size(); --i >= 0;) for (int i = customComps.size(); --i >= 0;)
{ {
Component* c = customComps.getUnchecked(i); Component* c = customComps.getUnchecked(i);
w = jmax (w, (c->getWidth() * 100) / 80); w = jmax (w, (c->getWidth() * 100) / 80);
@ -440,7 +414,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
h += labelHeight; h += labelHeight;
} }
for (i = textBlocks.size(); --i >= 0;) for (int i = textBlocks.size(); --i >= 0;)
{ {
const AlertTextComp* const ac = static_cast <const AlertTextComp*> (textBlocks.getUnchecked(i)); const AlertTextComp* const ac = static_cast <const AlertTextComp*> (textBlocks.getUnchecked(i));
w = jmax (w, ac->getPreferredWidth()); w = jmax (w, ac->getPreferredWidth());
@ -448,7 +422,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
w = jmin (w, (int) (getParentWidth() * 0.7f)); w = jmin (w, (int) (getParentWidth() * 0.7f));
for (i = textBlocks.size(); --i >= 0;) for (int i = textBlocks.size(); --i >= 0;)
{ {
AlertTextComp* const ac = static_cast <AlertTextComp*> (textBlocks.getUnchecked(i)); AlertTextComp* const ac = static_cast <AlertTextComp*> (textBlocks.getUnchecked(i));
ac->updateLayout ((int) (w * 0.8f)); ac->updateLayout ((int) (w * 0.8f));
@ -482,13 +456,13 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
const int spacer = 16; const int spacer = 16;
int totalWidth = -spacer; int totalWidth = -spacer;
for (i = buttons.size(); --i >= 0;) for (int i = buttons.size(); --i >= 0;)
totalWidth += buttons.getUnchecked(i)->getWidth() + spacer; totalWidth += buttons.getUnchecked(i)->getWidth() + spacer;
int x = (w - totalWidth) / 2; int x = (w - totalWidth) / 2;
int y = (int) (getHeight() * 0.95f); int y = (int) (getHeight() * 0.95f);
for (i = 0; i < buttons.size(); ++i) for (int i = 0; i < buttons.size(); ++i)
{ {
TextButton* const c = buttons.getUnchecked(i); TextButton* const c = buttons.getUnchecked(i);
int ny = proportionOfHeight (0.95f) - c->getHeight(); int ny = proportionOfHeight (0.95f) - c->getHeight();
@ -503,7 +477,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
y = textBottom; y = textBottom;
for (i = 0; i < allComps.size(); ++i) for (int i = 0; i < allComps.size(); ++i)
{ {
Component* const c = allComps.getUnchecked(i); Component* const c = allComps.getUnchecked(i);
h = 22; h = 22;