| @@ -1338,27 +1338,10 @@ private: | |||
| return getIvar<NSViewComponentPeer*> (self, "owner"); | |||
| } | |||
| //============================================================================== | |||
| 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) | |||
| static void mouseDown (id self, SEL s, NSEvent* ev) | |||
| { | |||
| if (JUCEApplication::isStandaloneApp()) | |||
| [self performSelector: @selector (asyncMouseDown:) | |||
| withObject: ev]; | |||
| asyncMouseDown (self, s, ev); | |||
| else | |||
| // 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 | |||
| @@ -1368,19 +1351,10 @@ private: | |||
| waitUntilDone: NO]; | |||
| } | |||
| static void asyncMouseDown (id self, SEL, NSEvent* ev) | |||
| { | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| if (owner != nullptr) | |||
| owner->redirectMouseDown (ev); | |||
| } | |||
| static void mouseUp (id self, SEL, NSEvent* ev) | |||
| static void mouseUp (id self, SEL s, NSEvent* ev) | |||
| { | |||
| if (! JUCEApplication::isStandaloneApp()) | |||
| [self performSelector: @selector (asyncMouseUp:) | |||
| withObject: ev]; | |||
| asyncMouseUp (self, s, ev); | |||
| else | |||
| // 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 | |||
| @@ -1390,55 +1364,51 @@ private: | |||
| waitUntilDone: NO]; | |||
| } | |||
| static void asyncMouseUp (id self, SEL, NSEvent* ev) { NSViewComponentPeer* const owner = getOwner (self); if (owner != nullptr) owner->redirectMouseUp (ev); } | |||
| static void mouseDragged (id self, SEL, NSEvent* ev) { NSViewComponentPeer* const owner = getOwner (self); if (owner != nullptr) owner->redirectMouseDrag (ev); } | |||
| static void mouseMoved (id self, SEL, NSEvent* ev) { NSViewComponentPeer* const owner = getOwner (self); if (owner != nullptr) owner->redirectMouseMove (ev); } | |||
| static void mouseEntered (id self, SEL, NSEvent* ev) { NSViewComponentPeer* const owner = getOwner (self); if (owner != nullptr) owner->redirectMouseEnter (ev); } | |||
| static void mouseExited (id self, SEL, NSEvent* ev) { NSViewComponentPeer* const owner = getOwner (self); if (owner != nullptr) owner->redirectMouseExit (ev); } | |||
| static void scrollWheel (id self, SEL, NSEvent* ev) { NSViewComponentPeer* const owner = getOwner (self); if (owner != nullptr) owner->redirectMouseWheel (ev); } | |||
| static void rightMouseDown (id self, SEL, NSEvent* ev) { [(NSView*) self mouseDown: ev]; } | |||
| static void rightMouseDragged (id self, SEL, NSEvent* ev) { [(NSView*) self mouseDragged: ev]; } | |||
| static void rightMouseUp (id self, SEL, NSEvent* ev) { [(NSView*) self mouseUp: ev]; } | |||
| static void otherMouseDown (id self, SEL, NSEvent* ev) { [(NSView*) self mouseDown: ev]; } | |||
| static void otherMouseDragged (id self, SEL, NSEvent* ev) { [(NSView*) self mouseDragged: ev]; } | |||
| static void otherMouseUp (id self, SEL, NSEvent* ev) { [(NSView*) self mouseUp: ev]; } | |||
| static void asyncMouseDown (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseDown (ev); } | |||
| static void asyncMouseUp (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseUp (ev); } | |||
| static void mouseDragged (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseDrag (ev); } | |||
| static void mouseMoved (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseMove (ev); } | |||
| static void mouseEntered (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseEnter (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 BOOL acceptsFirstMouse (id, SEL, NSEvent*) { return YES; } | |||
| static void rightMouseDown (id self, SEL s, NSEvent* ev) { mouseDown (self, s, ev); } | |||
| static void otherMouseDown (id self, SEL s, NSEvent* ev) { mouseDown (self, s, ev); } | |||
| static void rightMouseDragged (id self, SEL s, NSEvent* ev) { mouseDragged (self, s, ev); } | |||
| static void otherMouseDragged (id self, SEL s, NSEvent* ev) { mouseDragged (self, s, ev); } | |||
| static void rightMouseUp (id self, SEL s, NSEvent* ev) { mouseUp (self, s, ev); } | |||
| static void otherMouseUp (id self, SEL s, NSEvent* ev) { mouseUp (self, s, ev); } | |||
| static void frameChanged (id self, SEL, NSNotification*) | |||
| { | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| static BOOL acceptsFirstMouse (id, SEL, NSEvent*) { return YES; } | |||
| if (owner != nullptr) | |||
| owner->redirectMovedOrResized(); | |||
| } | |||
| 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 void viewDidMoveToWindow (id self, SEL) | |||
| static BOOL isOpaque (id self, SEL) | |||
| { | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| if (owner != nullptr) | |||
| owner->viewMovedToWindow(); | |||
| return owner == nullptr || owner->isOpaque(); | |||
| } | |||
| //============================================================================== | |||
| static void keyDown (id self, SEL, NSEvent* ev) | |||
| { | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| TextInputTarget* const target = owner->findCurrentTextInputTarget(); | |||
| owner->textWasInserted = false; | |||
| 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 (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); | |||
| 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) | |||
| { | |||
| // This commits multi-byte text when return is pressed, or after every keypress for western keyboards | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| NSString* newText = [aString isKindOfClass: [NSAttributedString class]] ? [aString string] : aString; | |||
| if ([newText length] > 0) | |||
| if (NSViewComponentPeer* const owner = getOwner (self)) | |||
| { | |||
| 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)); | |||
| owner->textWasInserted = true; | |||
| if (TextInputTarget* const target = owner->findCurrentTextInputTarget()) | |||
| { | |||
| target->insertTextAtCaret (nsStringToJuce (newText)); | |||
| 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) | |||
| { | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| owner->stringBeingComposed = nsStringToJuce ([aString isKindOfClass: [NSAttributedString class]] | |||
| ? [aString string] : aString); | |||
| TextInputTarget* const target = owner->findCurrentTextInputTarget(); | |||
| if (target != nullptr) | |||
| if (NSViewComponentPeer* const owner = getOwner (self)) | |||
| { | |||
| const Range<int> currentHighlight (target->getHighlightedRegion()); | |||
| target->insertTextAtCaret (owner->stringBeingComposed); | |||
| target->setHighlightedRegion (currentHighlight.withLength (owner->stringBeingComposed.length())); | |||
| owner->textWasInserted = true; | |||
| 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) | |||
| { | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| if (owner->stringBeingComposed.isNotEmpty()) | |||
| if (NSViewComponentPeer* const owner = getOwner (self)) | |||
| { | |||
| TextInputTarget* const target = owner->findCurrentTextInputTarget(); | |||
| if (target != nullptr) | |||
| if (owner->stringBeingComposed.isNotEmpty()) | |||
| { | |||
| target->insertTextAtCaret (owner->stringBeingComposed); | |||
| owner->textWasInserted = true; | |||
| } | |||
| if (TextInputTarget* const target = owner->findCurrentTextInputTarget()) | |||
| { | |||
| target->insertTextAtCaret (owner->stringBeingComposed); | |||
| owner->textWasInserted = true; | |||
| } | |||
| owner->stringBeingComposed = String::empty; | |||
| owner->stringBeingComposed = String::empty; | |||
| } | |||
| } | |||
| } | |||
| 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) | |||
| @@ -1525,15 +1493,15 @@ private: | |||
| static NSAttributedString* attributedSubstringFromRange (id self, SEL, NSRange theRange) | |||
| { | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| TextInputTarget* const target = owner->findCurrentTextInputTarget(); | |||
| if (target != nullptr) | |||
| if (NSViewComponentPeer* const owner = getOwner (self)) | |||
| { | |||
| const Range<int> r ((int) theRange.location, | |||
| (int) (theRange.location + theRange.length)); | |||
| if (TextInputTarget* const target = owner->findCurrentTextInputTarget()) | |||
| { | |||
| 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; | |||
| @@ -1548,15 +1516,15 @@ private: | |||
| static NSRange selectedRange (id self, SEL) | |||
| { | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| TextInputTarget* const target = owner->findCurrentTextInputTarget(); | |||
| if (target != nullptr) | |||
| if (NSViewComponentPeer* const owner = getOwner (self)) | |||
| { | |||
| const Range<int> highlight (target->getHighlightedRegion()); | |||
| if (TextInputTarget* const target = owner->findCurrentTextInputTarget()) | |||
| { | |||
| const Range<int> highlight (target->getHighlightedRegion()); | |||
| if (! highlight.isEmpty()) | |||
| return NSMakeRange (highlight.getStart(), highlight.getLength()); | |||
| if (! highlight.isEmpty()) | |||
| return NSMakeRange (highlight.getStart(), highlight.getLength()); | |||
| } | |||
| } | |||
| return NSMakeRange (NSNotFound, 0); | |||
| @@ -1564,18 +1532,20 @@ private: | |||
| static NSRect firstRectForCharacterRange (id self, SEL, NSRange) | |||
| { | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| Component* const comp = dynamic_cast <Component*> (owner->findCurrentTextInputTarget()); | |||
| if (comp == nullptr) | |||
| return NSMakeRect (0, 0, 0, 0); | |||
| if (NSViewComponentPeer* const owner = getOwner (self)) | |||
| { | |||
| if (Component* const comp = dynamic_cast <Component*> (owner->findCurrentTextInputTarget())) | |||
| { | |||
| const Rectangle<int> bounds (comp->getScreenBounds()); | |||
| const Rectangle<int> bounds (comp->getScreenBounds()); | |||
| return NSMakeRect (bounds.getX(), | |||
| [[[NSScreen screens] objectAtIndex: 0] frame].size.height - bounds.getY(), | |||
| bounds.getWidth(), | |||
| bounds.getHeight()); | |||
| } | |||
| } | |||
| return NSMakeRect (bounds.getX(), | |||
| [[[NSScreen screens] objectAtIndex: 0] frame].size.height - bounds.getY(), | |||
| bounds.getWidth(), | |||
| bounds.getHeight()); | |||
| return NSZeroRect; | |||
| } | |||
| static NSUInteger characterIndexForPoint (id, SEL, NSPoint) { return NSNotFound; } | |||
| @@ -1584,9 +1554,7 @@ private: | |||
| //============================================================================== | |||
| static void flagsChanged (id self, SEL, NSEvent* ev) | |||
| { | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| if (owner != nullptr) | |||
| if (NSViewComponentPeer* const owner = getOwner (self)) | |||
| owner->redirectModKeyChange (ev); | |||
| } | |||
| @@ -1605,8 +1573,7 @@ private: | |||
| static BOOL becomeFirstResponder (id self, SEL) | |||
| { | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| if (owner != nullptr) | |||
| if (NSViewComponentPeer* const owner = getOwner (self)) | |||
| owner->viewFocusGain(); | |||
| return YES; | |||
| @@ -1614,8 +1581,7 @@ private: | |||
| static BOOL resignFirstResponder (id self, SEL) | |||
| { | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| if (owner != nullptr) | |||
| if (NSViewComponentPeer* const owner = getOwner (self)) | |||
| owner->viewFocusLoss(); | |||
| 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); | |||
| if (owner != nullptr && owner->sendDragCallback (0, sender)) | |||
| return NSDragOperationCopy | NSDragOperationMove | NSDragOperationGeneric; | |||
| else | |||
| return NSDragOperationNone; | |||
| return draggingUpdated (self, s, sender); | |||
| } | |||
| static NSDragOperation draggingUpdated (id self, SEL, id <NSDraggingInfo> sender) | |||
| @@ -1648,19 +1609,14 @@ private: | |||
| 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); | |||
| if (owner != nullptr) | |||
| owner->sendDragCallback (1, sender); | |||
| draggingExited (self, s, sender); | |||
| } | |||
| static void draggingExited (id self, SEL, id <NSDraggingInfo> sender) | |||
| { | |||
| NSViewComponentPeer* const owner = getOwner (self); | |||
| if (owner != nullptr) | |||
| if (NSViewComponentPeer* const owner = getOwner (self)) | |||
| owner->sendDragCallback (1, sender); | |||
| } | |||
| @@ -32,8 +32,8 @@ struct TextAtom | |||
| int numChars; | |||
| //============================================================================== | |||
| bool isWhitespace() const { return CharacterFunctions::isWhitespace (atomText[0]); } | |||
| bool isNewLine() const { return atomText[0] == '\r' || atomText[0] == '\n'; } | |||
| bool isWhitespace() const noexcept { return CharacterFunctions::isWhitespace (atomText[0]); } | |||
| bool isNewLine() const noexcept { return atomText[0] == '\r' || atomText[0] == '\n'; } | |||
| String getText (const juce_wchar passwordCharacter) const | |||
| { | |||
| @@ -60,7 +60,6 @@ struct TextAtom | |||
| class TextEditor::UniformTextSection | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| UniformTextSection (const String& text, | |||
| const Font& font_, | |||
| const Colour& colour_, | |||
| @@ -321,7 +320,6 @@ private: | |||
| class TextEditor::Iterator | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| Iterator (const Array <UniformTextSection*>& sections_, | |||
| const float wordWrapWidth_, | |||
| const juce_wchar passwordCharacter_) | |||
| @@ -751,14 +749,14 @@ private: | |||
| class TextEditor::InsertAction : public UndoableAction | |||
| { | |||
| public: | |||
| InsertAction (TextEditor& owner_, | |||
| InsertAction (TextEditor& ed, | |||
| const String& text_, | |||
| const int insertIndex_, | |||
| const Font& font_, | |||
| const Colour& colour_, | |||
| const int oldCaretPos_, | |||
| const int newCaretPos_) | |||
| : owner (owner_), | |||
| : owner (ed), | |||
| text (text_), | |||
| insertIndex (insertIndex_), | |||
| oldCaretPos (oldCaretPos_), | |||
| @@ -799,12 +797,12 @@ private: | |||
| class TextEditor::RemoveAction : public UndoableAction | |||
| { | |||
| public: | |||
| RemoveAction (TextEditor& owner_, | |||
| RemoveAction (TextEditor& ed, | |||
| const Range<int> range_, | |||
| const int oldCaretPos_, | |||
| const int newCaretPos_, | |||
| const Array <UniformTextSection*>& removedSections_) | |||
| : owner (owner_), | |||
| : owner (ed), | |||
| range (range_), | |||
| oldCaretPos (oldCaretPos_), | |||
| newCaretPos (newCaretPos_), | |||
| @@ -860,8 +858,7 @@ class TextEditor::TextHolderComponent : public Component, | |||
| private ValueListener | |||
| { | |||
| public: | |||
| TextHolderComponent (TextEditor& owner_) | |||
| : owner (owner_) | |||
| TextHolderComponent (TextEditor& ed) : owner (ed) | |||
| { | |||
| setWantsKeyboardFocus (false); | |||
| setInterceptsMouseClicks (false, true); | |||
| @@ -905,8 +902,8 @@ private: | |||
| class TextEditorViewport : public Viewport | |||
| { | |||
| public: | |||
| TextEditorViewport (TextEditor& owner_) | |||
| : owner (owner_), lastWordWrapWidth (0), rentrant (false) | |||
| TextEditorViewport (TextEditor& ed) | |||
| : owner (ed), lastWordWrapWidth (0), rentrant (false) | |||
| { | |||
| } | |||
| @@ -970,6 +967,7 @@ TextEditor::TextEditor (const String& name, | |||
| tabKeyUsed (false), | |||
| menuActive (false), | |||
| valueTextNeedsUpdating (false), | |||
| consumeEscAndReturnKeys (true), | |||
| maxTextLength (0), | |||
| leftIndent (4), | |||
| topIndent (4), | |||
| @@ -2062,6 +2060,11 @@ bool TextEditor::selectAll() | |||
| } | |||
| //============================================================================== | |||
| void TextEditor::setEscapeAndReturnKeysConsumed (bool shouldBeConsumed) noexcept | |||
| { | |||
| consumeEscAndReturnKeys = shouldBeConsumed; | |||
| } | |||
| bool TextEditor::keyPressed (const KeyPress& key) | |||
| { | |||
| if (isReadOnly() && key != KeyPress ('c', ModifierKeys::commandModifier, 0)) | |||
| @@ -2076,13 +2079,17 @@ bool TextEditor::keyPressed (const KeyPress& key) | |||
| if (returnKeyStartsNewLine) | |||
| insertTextAtCaret ("\n"); | |||
| else | |||
| { | |||
| returnPressed(); | |||
| return consumeEscAndReturnKeys; | |||
| } | |||
| } | |||
| else if (key.isKeyCode (KeyPress::escapeKey)) | |||
| { | |||
| newTransaction(); | |||
| moveCaretTo (getCaretPosition(), false); | |||
| escapePressed(); | |||
| return consumeEscAndReturnKeys; | |||
| } | |||
| else if (key.getTextCharacter() >= ' ' | |||
| || (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 | |||
| #endif | |||
| if ((! consumeEscAndReturnKeys) | |||
| && (KeyPress (KeyPress::escapeKey).isCurrentlyDown() | |||
| || KeyPress (KeyPress::returnKey).isCurrentlyDown())) | |||
| return false; | |||
| // (overridden to avoid forwarding key events to the parent) | |||
| return ! ModifierKeys::getCurrentModifiers().isCommandDown(); | |||
| } | |||
| @@ -2213,7 +2225,7 @@ void TextEditor::setTemporaryUnderlining (const Array <Range<int> >& newUnderlin | |||
| //============================================================================== | |||
| UndoManager* TextEditor::getUndoManager() noexcept | |||
| { | |||
| return isReadOnly() ? 0 : &undoManager; | |||
| return readOnly ? nullptr : &undoManager; | |||
| } | |||
| void TextEditor::clearInternal (UndoManager* const um) | |||
| @@ -2252,17 +2264,13 @@ void TextEditor::insert (const String& text, | |||
| if (insertIndex == index) | |||
| { | |||
| sections.insert (i, new UniformTextSection (text, | |||
| font, colour, | |||
| passwordCharacter)); | |||
| sections.insert (i, new UniformTextSection (text, font, colour, passwordCharacter)); | |||
| break; | |||
| } | |||
| else if (insertIndex > index && insertIndex < nextIndex) | |||
| { | |||
| splitSection (i, insertIndex - index); | |||
| sections.insert (i + 1, new UniformTextSection (text, | |||
| font, colour, | |||
| passwordCharacter)); | |||
| sections.insert (i + 1, new UniformTextSection (text, font, colour, passwordCharacter)); | |||
| break; | |||
| } | |||
| @@ -2270,9 +2278,7 @@ void TextEditor::insert (const String& text, | |||
| } | |||
| if (nextIndex == insertIndex) | |||
| sections.add (new UniformTextSection (text, | |||
| font, colour, | |||
| passwordCharacter)); | |||
| sections.add (new UniformTextSection (text, font, colour, passwordCharacter)); | |||
| coalesceSimilarSections(); | |||
| totalNumChars = -1; | |||
| @@ -109,6 +109,14 @@ public: | |||
| */ | |||
| 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. | |||
| @@ -390,11 +398,6 @@ public: | |||
| */ | |||
| 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 | |||
| a specified position. | |||
| @@ -476,6 +479,7 @@ public: | |||
| void setScrollToShowCursor (bool shouldScrollToShowCaret); | |||
| //============================================================================== | |||
| void moveCaretToEnd(); | |||
| bool moveCaretLeft (bool moveInWholeWordSteps, bool selecting); | |||
| bool moveCaretRight (bool moveInWholeWordSteps, bool selecting); | |||
| bool moveCaretUp (bool selecting); | |||
| @@ -536,21 +540,21 @@ public: | |||
| //============================================================================== | |||
| /** @internal */ | |||
| void paint (Graphics& g); | |||
| void paint (Graphics&); | |||
| /** @internal */ | |||
| void paintOverChildren (Graphics& g); | |||
| void paintOverChildren (Graphics&); | |||
| /** @internal */ | |||
| void mouseDown (const MouseEvent& e); | |||
| void mouseDown (const MouseEvent&); | |||
| /** @internal */ | |||
| void mouseUp (const MouseEvent& e); | |||
| void mouseUp (const MouseEvent&); | |||
| /** @internal */ | |||
| void mouseDrag (const MouseEvent& e); | |||
| void mouseDrag (const MouseEvent&); | |||
| /** @internal */ | |||
| void mouseDoubleClick (const MouseEvent& e); | |||
| void mouseDoubleClick (const MouseEvent&); | |||
| /** @internal */ | |||
| void mouseWheelMove (const MouseEvent&, const MouseWheelDetails&); | |||
| /** @internal */ | |||
| bool keyPressed (const KeyPress& key); | |||
| bool keyPressed (const KeyPress&); | |||
| /** @internal */ | |||
| bool keyStateChanged (bool isKeyDown); | |||
| /** @internal */ | |||
| @@ -575,30 +579,18 @@ protected: | |||
| /** Scrolls the minimum distance needed to get the caret into view. */ | |||
| void scrollToMakeSureCursorIsVisible(); | |||
| /** @internal */ | |||
| void moveCaret (int newCaretPos); | |||
| /** @internal */ | |||
| void moveCaretTo (int newPosition, bool isSelecting); | |||
| /** Used internally to dispatch a text-change message. */ | |||
| void textChanged(); | |||
| /** Begins a new transaction in the UndoManager. */ | |||
| void newTransaction(); | |||
| /** Used internally to trigger an undo or redo. */ | |||
| void doUndoRedo (bool isRedo); | |||
| /** Can be overridden to intercept return key presses directly */ | |||
| virtual void returnPressed(); | |||
| /** Can be overridden to intercept escape key presses directly */ | |||
| virtual void escapePressed(); | |||
| /** @internal */ | |||
| void handleCommandMessage (int commandId); | |||
| private: | |||
| //============================================================================== | |||
| class Iterator; | |||
| @@ -625,6 +617,7 @@ private: | |||
| bool tabKeyUsed : 1; | |||
| bool menuActive : 1; | |||
| bool valueTextNeedsUpdating : 1; | |||
| bool consumeEscAndReturnKeys : 1; | |||
| UndoManager undoManager; | |||
| ScopedPointer<CaretComponent> caret; | |||
| @@ -652,13 +645,15 @@ private: | |||
| ListenerList <Listener> listeners; | |||
| Array <Range<int> > underlinedSections; | |||
| void moveCaret (int newCaretPos); | |||
| void moveCaretTo (int newPosition, bool isSelecting); | |||
| void handleCommandMessage (int); | |||
| void coalesceSimilarSections(); | |||
| void splitSection (int sectionIndex, int charToSplitAt); | |||
| void clearInternal (UndoManager* um); | |||
| void insert (const String& text, int insertIndex, const Font& font, | |||
| const Colour& colour, UndoManager* um, int caretPositionToMoveTo); | |||
| void reinsert (int insertIndex, const Array <UniformTextSection*>& sections); | |||
| void remove (const Range<int>& range, UndoManager* um, int caretPositionToMoveTo); | |||
| void clearInternal (UndoManager*); | |||
| void insert (const String&, int insertIndex, const Font&, const Colour&, UndoManager*, int newCaretPos); | |||
| void reinsert (int insertIndex, const Array <UniformTextSection*>&); | |||
| void remove (const Range<int>& range, UndoManager*, int caretPositionToMoveTo); | |||
| void getCharPosition (int index, float& x, float& y, float& lineHeight) const; | |||
| void updateCaretPosition(); | |||
| void updateValueFromText(); | |||
| @@ -669,11 +664,11 @@ private: | |||
| bool moveCaretWithTransation (int newPos, bool selecting); | |||
| friend class TextHolderComponent; | |||
| friend class TextEditorViewport; | |||
| void drawContent (Graphics& g); | |||
| void drawContent (Graphics&); | |||
| void updateTextHolderSize(); | |||
| float getWordWrapWidth() const; | |||
| void timerCallbackInt(); | |||
| void repaintText (const Range<int>& range); | |||
| void repaintText (const Range<int>&); | |||
| void scrollByLines (int deltaLines); | |||
| bool undoOrRedo (bool shouldUndo); | |||
| UndoManager* getUndoManager() noexcept; | |||
| @@ -23,49 +23,23 @@ | |||
| ============================================================================== | |||
| */ | |||
| class AlertWindowTextEditor : public TextEditor | |||
| static juce_wchar getDefaultPasswordChar() noexcept | |||
| { | |||
| public: | |||
| AlertWindowTextEditor (const String& name, const bool isPasswordBox) | |||
| : TextEditor (name, isPasswordBox ? getDefaultPasswordChar() : 0) | |||
| { | |||
| setSelectAllWhenFocused (true); | |||
| } | |||
| 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 | |||
| } | |||
| }; | |||
| #if JUCE_LINUX | |||
| return 0x2022; | |||
| #else | |||
| return 0x25cf; | |||
| #endif | |||
| } | |||
| //============================================================================== | |||
| AlertWindow::AlertWindow (const String& title, | |||
| const String& message, | |||
| AlertIconType iconType, | |||
| Component* associatedComponent_) | |||
| Component* comp) | |||
| : TopLevelWindow (title, true), | |||
| alertIconType (iconType), | |||
| associatedComponent (associatedComponent_), | |||
| associatedComponent (comp), | |||
| escapeKeyCancels (true) | |||
| { | |||
| if (message.isEmpty()) | |||
| @@ -175,15 +149,17 @@ void AlertWindow::addTextEditor (const String& name, | |||
| const String& onScreenLabel, | |||
| const bool isPasswordBox) | |||
| { | |||
| AlertWindowTextEditor* const tc = new AlertWindowTextEditor (name, isPasswordBox); | |||
| textBoxes.add (tc); | |||
| allComps.add (tc); | |||
| tc->setColour (TextEditor::outlineColourId, findColour (ComboBox::outlineColourId)); | |||
| tc->setFont (getLookAndFeel().getAlertWindowMessageFont()); | |||
| tc->setText (initialContents); | |||
| tc->setCaretPosition (initialContents.length()); | |||
| addAndMakeVisible (tc); | |||
| TextEditor* ed = new TextEditor (name, isPasswordBox ? getDefaultPasswordChar() : 0); | |||
| ed->setSelectAllWhenFocused (true); | |||
| ed->setEscapeAndReturnKeysConsumed (false); | |||
| textBoxes.add (ed); | |||
| allComps.add (ed); | |||
| ed->setColour (TextEditor::outlineColourId, findColour (ComboBox::outlineColourId)); | |||
| ed->setFont (getLookAndFeel().getAlertWindowMessageFont()); | |||
| ed->setText (initialContents); | |||
| ed->setCaretPosition (initialContents.length()); | |||
| addAndMakeVisible (ed); | |||
| textboxNames.add (onScreenLabel); | |||
| updateLayout (false); | |||
| @@ -343,8 +319,7 @@ void AlertWindow::paint (Graphics& g) | |||
| g.setColour (findColour (textColourId)); | |||
| g.setFont (getLookAndFeel().getAlertWindowFont()); | |||
| int i; | |||
| for (i = textBoxes.size(); --i >= 0;) | |||
| for (int i = textBoxes.size(); --i >= 0;) | |||
| { | |||
| const TextEditor* const te = textBoxes.getUnchecked(i); | |||
| @@ -354,7 +329,7 @@ void AlertWindow::paint (Graphics& g) | |||
| Justification::centredLeft, 1); | |||
| } | |||
| for (i = comboBoxNames.size(); --i >= 0;) | |||
| for (int i = comboBoxNames.size(); --i >= 0;) | |||
| { | |||
| const ComboBox* const cb = comboBoxes.getUnchecked(i); | |||
| @@ -364,7 +339,7 @@ void AlertWindow::paint (Graphics& g) | |||
| Justification::centredLeft, 1); | |||
| } | |||
| for (i = customComps.size(); --i >= 0;) | |||
| for (int i = customComps.size(); --i >= 0;) | |||
| { | |||
| const Component* const c = customComps.getUnchecked(i); | |||
| @@ -419,8 +394,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||
| int h = textBottom; | |||
| int buttonW = 40; | |||
| int i; | |||
| for (i = 0; i < buttons.size(); ++i) | |||
| for (int i = 0; i < buttons.size(); ++i) | |||
| buttonW += 16 + buttons.getUnchecked(i)->getWidth(); | |||
| w = jmax (buttonW, w); | |||
| @@ -430,7 +404,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||
| if (buttons.size() > 0) | |||
| h += 20 + buttons.getUnchecked(0)->getHeight(); | |||
| for (i = customComps.size(); --i >= 0;) | |||
| for (int i = customComps.size(); --i >= 0;) | |||
| { | |||
| Component* c = customComps.getUnchecked(i); | |||
| w = jmax (w, (c->getWidth() * 100) / 80); | |||
| @@ -440,7 +414,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||
| 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)); | |||
| w = jmax (w, ac->getPreferredWidth()); | |||
| @@ -448,7 +422,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||
| 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)); | |||
| ac->updateLayout ((int) (w * 0.8f)); | |||
| @@ -482,13 +456,13 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||
| const int spacer = 16; | |||
| int totalWidth = -spacer; | |||
| for (i = buttons.size(); --i >= 0;) | |||
| for (int i = buttons.size(); --i >= 0;) | |||
| totalWidth += buttons.getUnchecked(i)->getWidth() + spacer; | |||
| int x = (w - totalWidth) / 2; | |||
| 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); | |||
| int ny = proportionOfHeight (0.95f) - c->getHeight(); | |||
| @@ -503,7 +477,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||
| y = textBottom; | |||
| for (i = 0; i < allComps.size(); ++i) | |||
| for (int i = 0; i < allComps.size(); ++i) | |||
| { | |||
| Component* const c = allComps.getUnchecked(i); | |||
| h = 22; | |||