Browse Source

Added method TextEditor::setEscapeAndReturnKeysConsumed().

tags/2021-05-28
jules 13 years ago
parent
commit
9281759612
4 changed files with 186 additions and 255 deletions
  1. +102
    -146
      modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm
  2. +28
    -22
      modules/juce_gui_basics/widgets/juce_TextEditor.cpp
  3. +26
    -31
      modules/juce_gui_basics/widgets/juce_TextEditor.h
  4. +30
    -56
      modules/juce_gui_basics/windows/juce_AlertWindow.cpp

+ 102
- 146
modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm View File

@@ -1338,27 +1338,10 @@ private:
return getIvar<NSViewComponentPeer*> (self, "owner"); 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()) if (JUCEApplication::isStandaloneApp())
[self performSelector: @selector (asyncMouseDown:)
withObject: ev];
asyncMouseDown (self, s, 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)
{
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()) if (! JUCEApplication::isStandaloneApp())
[self performSelector: @selector (asyncMouseUp:)
withObject: ev];
asyncMouseUp (self, s, 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 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); NSViewComponentPeer* const owner = getOwner (self);
if (owner != nullptr)
owner->viewMovedToWindow();
return owner == nullptr || owner->isOpaque();
} }
//============================================================================== //==============================================================================
static void keyDown (id self, SEL, NSEvent* ev) 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) 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);
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 doCommandBySelector (id, SEL, SEL) {}
static void setMarkedText (id self, SEL, id aString, NSRange) 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) 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) 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);
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; return nil;
@@ -1548,15 +1516,15 @@ private:
static NSRange selectedRange (id self, SEL) 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); 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);
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; } 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 (owner != nullptr)
if (NSViewComponentPeer* const owner = getOwner (self))
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 (owner != nullptr)
if (NSViewComponentPeer* const owner = getOwner (self))
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 (owner != nullptr)
if (NSViewComponentPeer* const owner = getOwner (self))
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);
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) 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);
if (owner != nullptr)
owner->sendDragCallback (1, sender);
draggingExited (self, s, 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 (owner != nullptr)
if (NSViewComponentPeer* const owner = getOwner (self))
owner->sendDragCallback (1, sender); owner->sendDragCallback (1, sender);
} }


+ 28
- 22
modules/juce_gui_basics/widgets/juce_TextEditor.cpp View File

@@ -32,8 +32,8 @@ struct TextAtom
int numChars; 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 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_)
: owner (owner_)
TextHolderComponent (TextEditor& ed) : owner (ed)
{ {
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_)
: 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), 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,
font, colour,
passwordCharacter));
sections.insert (i, new UniformTextSection (text, 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,
font, colour,
passwordCharacter));
sections.insert (i + 1, new UniformTextSection (text, 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,
font, colour,
passwordCharacter));
sections.add (new UniformTextSection (text, font, colour, passwordCharacter));
coalesceSimilarSections(); coalesceSimilarSections();
totalNumChars = -1; totalNumChars = -1;


+ 26
- 31
modules/juce_gui_basics/widgets/juce_TextEditor.h 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 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 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;


+ 30
- 56
modules/juce_gui_basics/windows/juce_AlertWindow.cpp View File

@@ -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, 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);
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); 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 (i = textBoxes.size(); --i >= 0;)
for (int 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 (i = 0; i < buttons.size(); ++i)
for (int 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;


Loading…
Cancel
Save