git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce

subrepo:
  subdir:   "deps/juce"
  merged:   "b13f9084e"
upstream:
  origin:   "https://github.com/essej/JUCE.git"
  branch:   "sono6good"
  commit:   "b13f9084e"
git-subrepo:
  version:  "0.4.3"
  origin:   "https://github.com/ingydotnet/git-subrepo.git"
  commit:   "2f68596"
This commit is contained in:
essej
2022-04-18 17:51:22 -04:00
parent 63e175fee6
commit 25bd5d8adb
3210 changed files with 1045392 additions and 0 deletions

View File

@ -0,0 +1,64 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
CaretComponent::CaretComponent (Component* const keyFocusOwner)
: owner (keyFocusOwner)
{
setPaintingIsUnclipped (true);
setInterceptsMouseClicks (false, false);
}
CaretComponent::~CaretComponent()
{
}
void CaretComponent::paint (Graphics& g)
{
g.setColour (findColour (caretColourId, true));
g.fillRect (getLocalBounds());
}
void CaretComponent::timerCallback()
{
setVisible (shouldBeShown() && ! isVisible());
}
void CaretComponent::setCaretPosition (const Rectangle<int>& characterArea)
{
startTimer (380);
setVisible (shouldBeShown());
setBounds (characterArea.withWidth (2));
}
bool CaretComponent::shouldBeShown() const
{
return owner == nullptr || (owner->hasKeyboardFocus (false)
&& ! owner->isCurrentlyBlockedByAnotherModalComponent());
}
} // namespace juce

View File

@ -0,0 +1,81 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
@tags{GUI}
*/
class JUCE_API CaretComponent : public Component,
private Timer
{
public:
//==============================================================================
/** Creates the caret component.
The keyFocusOwner is an optional component which the caret will check, making
itself visible only when the keyFocusOwner has keyboard focus.
*/
CaretComponent (Component* keyFocusOwner);
/** Destructor. */
~CaretComponent() override;
//==============================================================================
/** Sets the caret's position to place it next to the given character.
The area is the rectangle containing the entire character that the caret is
positioned on, so by default a vertical-line caret may choose to just show itself
at the left of this area. You can override this method to customise its size.
This method will also force the caret to reset its timer and become visible (if
appropriate), so that as it moves, you can see where it is.
*/
virtual void setCaretPosition (const Rectangle<int>& characterArea);
/** A set of colour IDs to use to change the colour of various aspects of the caret.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
caretColourId = 0x1000204, /**< The colour with which to draw the caret. */
};
//==============================================================================
/** @internal */
void paint (Graphics&) override;
private:
Component* owner;
bool shouldBeShown() const;
void timerCallback() override;
JUCE_DECLARE_NON_COPYABLE (CaretComponent)
};
} // namespace juce

View File

@ -0,0 +1,34 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
bool KeyListener::keyStateChanged (const bool, Component*)
{
return false;
}
} // namespace juce

View File

@ -0,0 +1,77 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
Receives callbacks when keys are pressed.
You can add a key listener to a component to be informed when that component
gets key events. See the Component::addListener method for more details.
@see KeyPress, Component::addKeyListener, KeyPressMappingSet
@tags{GUI}
*/
class JUCE_API KeyListener
{
public:
/** Destructor. */
virtual ~KeyListener() = default;
//==============================================================================
/** Called to indicate that a key has been pressed.
If your implementation returns true, then the key event is considered to have
been consumed, and will not be passed on to any other components. If it returns
false, then the key will be passed to other components that might want to use it.
@param key the keystroke, including modifier keys
@param originatingComponent the component that received the key event
@see keyStateChanged, Component::keyPressed
*/
virtual bool keyPressed (const KeyPress& key,
Component* originatingComponent) = 0;
/** Called when any key is pressed or released.
When this is called, classes that might be interested in
the state of one or more keys can use KeyPress::isKeyCurrentlyDown() to
check whether their key has changed.
If your implementation returns true, then the key event is considered to have
been consumed, and will not be passed on to any other components. If it returns
false, then the key will be passed to other components that might want to use it.
@param originatingComponent the component that received the key event
@param isKeyDown true if a key is being pressed, false if one is being released
@see KeyPress, Component::keyStateChanged
*/
virtual bool keyStateChanged (bool isKeyDown, Component* originatingComponent);
};
} // namespace juce

View File

@ -0,0 +1,289 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
KeyPress::KeyPress (int code, ModifierKeys m, juce_wchar textChar) noexcept
: keyCode (code), mods (m), textCharacter (textChar)
{
}
KeyPress::KeyPress (const int code) noexcept : keyCode (code)
{
}
bool KeyPress::operator== (int otherKeyCode) const noexcept
{
return keyCode == otherKeyCode && ! mods.isAnyModifierKeyDown();
}
bool KeyPress::operator== (const KeyPress& other) const noexcept
{
return mods.getRawFlags() == other.mods.getRawFlags()
&& (textCharacter == other.textCharacter
|| textCharacter == 0
|| other.textCharacter == 0)
&& (keyCode == other.keyCode
|| (keyCode < 256
&& other.keyCode < 256
&& CharacterFunctions::toLowerCase ((juce_wchar) keyCode)
== CharacterFunctions::toLowerCase ((juce_wchar) other.keyCode)));
}
bool KeyPress::operator!= (const KeyPress& other) const noexcept { return ! operator== (other); }
bool KeyPress::operator!= (int otherKeyCode) const noexcept { return ! operator== (otherKeyCode); }
bool KeyPress::isCurrentlyDown() const
{
return isKeyCurrentlyDown (keyCode)
&& (ModifierKeys::currentModifiers.getRawFlags() & ModifierKeys::allKeyboardModifiers)
== (mods.getRawFlags() & ModifierKeys::allKeyboardModifiers);
}
//==============================================================================
namespace KeyPressHelpers
{
struct KeyNameAndCode
{
const char* name;
int code;
};
const KeyNameAndCode translations[] =
{
{ "spacebar", KeyPress::spaceKey },
{ "return", KeyPress::returnKey },
{ "escape", KeyPress::escapeKey },
{ "backspace", KeyPress::backspaceKey },
{ "cursor left", KeyPress::leftKey },
{ "cursor right", KeyPress::rightKey },
{ "cursor up", KeyPress::upKey },
{ "cursor down", KeyPress::downKey },
{ "page up", KeyPress::pageUpKey },
{ "page down", KeyPress::pageDownKey },
{ "home", KeyPress::homeKey },
{ "end", KeyPress::endKey },
{ "delete", KeyPress::deleteKey },
{ "insert", KeyPress::insertKey },
{ "tab", KeyPress::tabKey },
{ "play", KeyPress::playKey },
{ "stop", KeyPress::stopKey },
{ "fast forward", KeyPress::fastForwardKey },
{ "rewind", KeyPress::rewindKey }
};
struct ModifierDescription
{
const char* name;
int flag;
};
static const ModifierDescription modifierNames[] =
{
{ "ctrl", ModifierKeys::ctrlModifier },
{ "control", ModifierKeys::ctrlModifier },
{ "ctl", ModifierKeys::ctrlModifier },
{ "shift", ModifierKeys::shiftModifier },
{ "shft", ModifierKeys::shiftModifier },
{ "alt", ModifierKeys::altModifier },
{ "option", ModifierKeys::altModifier },
{ "command", ModifierKeys::commandModifier },
{ "cmd", ModifierKeys::commandModifier }
};
static const char* numberPadPrefix() noexcept { return "numpad "; }
static int getNumpadKeyCode (const String& desc)
{
if (desc.containsIgnoreCase (numberPadPrefix()))
{
auto lastChar = desc.trimEnd().getLastCharacter();
switch (lastChar)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return (int) (KeyPress::numberPad0 + (int) lastChar - '0');
case '+': return KeyPress::numberPadAdd;
case '-': return KeyPress::numberPadSubtract;
case '*': return KeyPress::numberPadMultiply;
case '/': return KeyPress::numberPadDivide;
case '.': return KeyPress::numberPadDecimalPoint;
case '=': return KeyPress::numberPadEquals;
default: break;
}
if (desc.endsWith ("separator")) return KeyPress::numberPadSeparator;
if (desc.endsWith ("delete")) return KeyPress::numberPadDelete;
}
return 0;
}
#if JUCE_MAC || JUCE_IOS
struct OSXSymbolReplacement
{
const char* text;
juce_wchar symbol;
};
const OSXSymbolReplacement osxSymbols[] =
{
{ "shift + ", 0x21e7 },
{ "command + ", 0x2318 },
{ "option + ", 0x2325 },
{ "ctrl + ", 0x2303 },
{ "return", 0x21b5 },
{ "cursor left", 0x2190 },
{ "cursor right", 0x2192 },
{ "cursor up", 0x2191 },
{ "cursor down", 0x2193 },
{ "backspace", 0x232b },
{ "delete", 0x2326 },
{ "spacebar", 0x2423 }
};
#endif
}
//==============================================================================
KeyPress KeyPress::createFromDescription (const String& desc)
{
int modifiers = 0;
for (int i = 0; i < numElementsInArray (KeyPressHelpers::modifierNames); ++i)
if (desc.containsWholeWordIgnoreCase (KeyPressHelpers::modifierNames[i].name))
modifiers |= KeyPressHelpers::modifierNames[i].flag;
int key = 0;
for (int i = 0; i < numElementsInArray (KeyPressHelpers::translations); ++i)
{
if (desc.containsWholeWordIgnoreCase (String (KeyPressHelpers::translations[i].name)))
{
key = KeyPressHelpers::translations[i].code;
break;
}
}
if (key == 0)
key = KeyPressHelpers::getNumpadKeyCode (desc);
if (key == 0)
{
// see if it's a function key..
if (! desc.containsChar ('#')) // avoid mistaking hex-codes like "#f1"
{
for (int i = 1; i <= 35; ++i)
{
if (desc.containsWholeWordIgnoreCase ("f" + String (i)))
{
if (i <= 16) key = F1Key + i - 1;
else if (i <= 24) key = F17Key + i - 17;
else if (i <= 35) key = F25Key + i - 25;
}
}
}
if (key == 0)
{
// give up and use the hex code..
auto hexCode = desc.fromFirstOccurrenceOf ("#", false, false)
.retainCharacters ("0123456789abcdefABCDEF")
.getHexValue32();
if (hexCode > 0)
key = hexCode;
else
key = (int) CharacterFunctions::toUpperCase (desc.getLastCharacter());
}
}
return KeyPress (key, ModifierKeys (modifiers), 0);
}
String KeyPress::getTextDescription() const
{
String desc;
if (keyCode > 0)
{
// some keyboard layouts use a shift-key to get the slash, but in those cases, we
// want to store it as being a slash, not shift+whatever.
if (textCharacter == '/' && keyCode != numberPadDivide)
return "/";
if (mods.isCtrlDown()) desc << "ctrl + ";
if (mods.isShiftDown()) desc << "shift + ";
#if JUCE_MAC || JUCE_IOS
if (mods.isAltDown()) desc << "option + ";
if (mods.isCommandDown()) desc << "command + ";
#else
if (mods.isAltDown()) desc << "alt + ";
#endif
for (int i = 0; i < numElementsInArray (KeyPressHelpers::translations); ++i)
if (keyCode == KeyPressHelpers::translations[i].code)
return desc + KeyPressHelpers::translations[i].name;
// not all F keys have consecutive key codes on all platforms
if (keyCode >= F1Key && keyCode <= F16Key) desc << 'F' << (1 + keyCode - F1Key);
else if (keyCode >= F17Key && keyCode <= F24Key) desc << 'F' << (17 + keyCode - F17Key);
else if (keyCode >= F25Key && keyCode <= F35Key) desc << 'F' << (25 + keyCode - F25Key);
else if (keyCode >= numberPad0 && keyCode <= numberPad9) desc << KeyPressHelpers::numberPadPrefix() << (keyCode - numberPad0);
else if (keyCode >= 33 && keyCode < 176) desc += CharacterFunctions::toUpperCase ((juce_wchar) keyCode);
else if (keyCode == numberPadAdd) desc << KeyPressHelpers::numberPadPrefix() << '+';
else if (keyCode == numberPadSubtract) desc << KeyPressHelpers::numberPadPrefix() << '-';
else if (keyCode == numberPadMultiply) desc << KeyPressHelpers::numberPadPrefix() << '*';
else if (keyCode == numberPadDivide) desc << KeyPressHelpers::numberPadPrefix() << '/';
else if (keyCode == numberPadSeparator) desc << KeyPressHelpers::numberPadPrefix() << "separator";
else if (keyCode == numberPadDecimalPoint) desc << KeyPressHelpers::numberPadPrefix() << '.';
else if (keyCode == numberPadEquals) desc << KeyPressHelpers::numberPadPrefix() << '=';
else if (keyCode == numberPadDelete) desc << KeyPressHelpers::numberPadPrefix() << "delete";
else desc << '#' << String::toHexString (keyCode);
}
return desc;
}
String KeyPress::getTextDescriptionWithIcons() const
{
#if JUCE_MAC || JUCE_IOS
auto s = getTextDescription();
for (int i = 0; i < numElementsInArray (KeyPressHelpers::osxSymbols); ++i)
s = s.replace (KeyPressHelpers::osxSymbols[i].text,
String::charToString (KeyPressHelpers::osxSymbols[i].symbol));
return s;
#else
return getTextDescription();
#endif
}
} // namespace juce

View File

@ -0,0 +1,277 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
Represents a key press, including any modifier keys that are needed.
E.g. a KeyPress might represent CTRL+C, SHIFT+ALT+H, Spacebar, Escape, etc.
@see Component, KeyListener, KeyPressMappingSet, Button::addShortcut
@tags{GUI}
*/
class JUCE_API KeyPress
{
public:
//==============================================================================
/** Creates an (invalid) KeyPress.
@see isValid
*/
KeyPress() = default;
/** Destructor. */
~KeyPress() = default;
/** Creates a KeyPress for a key and some modifiers.
e.g.
CTRL+C would be: KeyPress ('c', ModifierKeys::ctrlModifier, 0)
SHIFT+Escape would be: KeyPress (KeyPress::escapeKey, ModifierKeys::shiftModifier, 0)
@param keyCode a code that represents the key - this value must be
one of special constants listed in this class, or an
8-bit character code such as a letter (case is ignored),
digit or a simple key like "," or ".". Note that this
isn't the same as the textCharacter parameter, so for example
a keyCode of 'a' and a shift-key modifier should have a
textCharacter value of 'A'.
@param modifiers the modifiers to associate with the keystroke
@param textCharacter the character that would be printed if someone typed
this keypress into a text editor. This value may be
null if the keypress is a non-printing character
@see getKeyCode, isKeyCode, getModifiers
*/
KeyPress (int keyCode,
ModifierKeys modifiers,
juce_wchar textCharacter) noexcept;
/** Creates a keypress with a keyCode but no modifiers or text character. */
explicit KeyPress (int keyCode) noexcept;
/** Creates a copy of another KeyPress. */
KeyPress (const KeyPress&) = default;
/** Copies this KeyPress from another one. */
KeyPress& operator= (const KeyPress&) = default;
/** Compares two KeyPress objects. */
bool operator== (const KeyPress& other) const noexcept;
/** Compares two KeyPress objects. */
bool operator!= (const KeyPress& other) const noexcept;
/** Returns true if this keypress is for the given keycode without any modifiers. */
bool operator== (int keyCode) const noexcept;
/** Returns true if this keypress is not for the given keycode without any modifiers. */
bool operator!= (int keyCode) const noexcept;
//==============================================================================
/** Returns true if this is a valid KeyPress.
A null keypress can be created by the default constructor, in case it's
needed.
*/
bool isValid() const noexcept { return keyCode != 0; }
/** Returns the key code itself.
This will either be one of the special constants defined in this class,
or an 8-bit character code.
*/
int getKeyCode() const noexcept { return keyCode; }
/** Returns the key modifiers.
@see ModifierKeys
*/
ModifierKeys getModifiers() const noexcept { return mods; }
/** Returns the character that is associated with this keypress.
This is the character that you'd expect to see printed if you press this
keypress in a text editor or similar component.
*/
juce_wchar getTextCharacter() const noexcept { return textCharacter; }
/** Checks whether the KeyPress's key is the same as the one provided, without checking
the modifiers.
The values for key codes can either be one of the special constants defined in
this class, or an 8-bit character code.
@see getKeyCode
*/
bool isKeyCode (int keyCodeToCompare) const noexcept { return keyCode == keyCodeToCompare; }
//==============================================================================
/** Converts a textual key description to a KeyPress.
This attempts to decode a textual version of a keypress, e.g. "ctrl + c" or "spacebar".
This isn't designed to cope with any kind of input, but should be given the
strings that are created by the getTextDescription() method.
If the string can't be parsed, the object returned will be invalid.
@see getTextDescription
*/
static KeyPress createFromDescription (const String& textVersion);
/** Creates a textual description of the key combination.
e.g. "ctrl + c" or "delete".
To store a keypress in a file, use this method, along with createFromDescription()
to retrieve it later.
*/
String getTextDescription() const;
/** Creates a textual description of the key combination, using unicode icon symbols if possible.
On OSX, this uses the Apple symbols for command, option, shift, etc, instead of the textual
modifier key descriptions that are returned by getTextDescription()
*/
String getTextDescriptionWithIcons() const;
//==============================================================================
/** Checks whether the user is currently holding down the keys that make up this
KeyPress.
Note that this will return false if any extra modifier keys are
down - e.g. if the keypress is CTRL+X and the user is actually holding CTRL+ALT+x
then it will be false.
*/
bool isCurrentlyDown() const;
/** Checks whether a particular key is held down, irrespective of modifiers.
The values for key codes can either be one of the special constants defined in
this class, or an 8-bit character code.
*/
static bool isKeyCurrentlyDown (int keyCode);
//==============================================================================
// Key codes
//
// Note that the actual values of these are platform-specific and may change
// without warning, so don't store them anywhere as constants. For persisting/retrieving
// KeyPress objects, use getTextDescription() and createFromDescription() instead.
//
static const int spaceKey; /**< key-code for the space bar */
static const int escapeKey; /**< key-code for the escape key */
static const int returnKey; /**< key-code for the return key*/
static const int tabKey; /**< key-code for the tab key*/
static const int deleteKey; /**< key-code for the delete key (not backspace) */
static const int backspaceKey; /**< key-code for the backspace key */
static const int insertKey; /**< key-code for the insert key */
static const int upKey; /**< key-code for the cursor-up key */
static const int downKey; /**< key-code for the cursor-down key */
static const int leftKey; /**< key-code for the cursor-left key */
static const int rightKey; /**< key-code for the cursor-right key */
static const int pageUpKey; /**< key-code for the page-up key */
static const int pageDownKey; /**< key-code for the page-down key */
static const int homeKey; /**< key-code for the home key */
static const int endKey; /**< key-code for the end key */
static const int F1Key; /**< key-code for the F1 key */
static const int F2Key; /**< key-code for the F2 key */
static const int F3Key; /**< key-code for the F3 key */
static const int F4Key; /**< key-code for the F4 key */
static const int F5Key; /**< key-code for the F5 key */
static const int F6Key; /**< key-code for the F6 key */
static const int F7Key; /**< key-code for the F7 key */
static const int F8Key; /**< key-code for the F8 key */
static const int F9Key; /**< key-code for the F9 key */
static const int F10Key; /**< key-code for the F10 key */
static const int F11Key; /**< key-code for the F11 key */
static const int F12Key; /**< key-code for the F12 key */
static const int F13Key; /**< key-code for the F13 key */
static const int F14Key; /**< key-code for the F14 key */
static const int F15Key; /**< key-code for the F15 key */
static const int F16Key; /**< key-code for the F16 key */
static const int F17Key; /**< key-code for the F17 key */
static const int F18Key; /**< key-code for the F18 key */
static const int F19Key; /**< key-code for the F19 key */
static const int F20Key; /**< key-code for the F20 key */
static const int F21Key; /**< key-code for the F21 key */
static const int F22Key; /**< key-code for the F22 key */
static const int F23Key; /**< key-code for the F23 key */
static const int F24Key; /**< key-code for the F24 key */
static const int F25Key; /**< key-code for the F25 key */
static const int F26Key; /**< key-code for the F26 key */
static const int F27Key; /**< key-code for the F27 key */
static const int F28Key; /**< key-code for the F28 key */
static const int F29Key; /**< key-code for the F29 key */
static const int F30Key; /**< key-code for the F30 key */
static const int F31Key; /**< key-code for the F31 key */
static const int F32Key; /**< key-code for the F32 key */
static const int F33Key; /**< key-code for the F33 key */
static const int F34Key; /**< key-code for the F34 key */
static const int F35Key; /**< key-code for the F35 key */
static const int numberPad0; /**< key-code for the 0 on the numeric keypad. */
static const int numberPad1; /**< key-code for the 1 on the numeric keypad. */
static const int numberPad2; /**< key-code for the 2 on the numeric keypad. */
static const int numberPad3; /**< key-code for the 3 on the numeric keypad. */
static const int numberPad4; /**< key-code for the 4 on the numeric keypad. */
static const int numberPad5; /**< key-code for the 5 on the numeric keypad. */
static const int numberPad6; /**< key-code for the 6 on the numeric keypad. */
static const int numberPad7; /**< key-code for the 7 on the numeric keypad. */
static const int numberPad8; /**< key-code for the 8 on the numeric keypad. */
static const int numberPad9; /**< key-code for the 9 on the numeric keypad. */
static const int numberPadAdd; /**< key-code for the add sign on the numeric keypad. */
static const int numberPadSubtract; /**< key-code for the subtract sign on the numeric keypad. */
static const int numberPadMultiply; /**< key-code for the multiply sign on the numeric keypad. */
static const int numberPadDivide; /**< key-code for the divide sign on the numeric keypad. */
static const int numberPadSeparator; /**< key-code for the comma on the numeric keypad. */
static const int numberPadDecimalPoint; /**< key-code for the decimal point sign on the numeric keypad. */
static const int numberPadEquals; /**< key-code for the equals key on the numeric keypad. */
static const int numberPadDelete; /**< key-code for the delete key on the numeric keypad. */
static const int playKey; /**< key-code for a multimedia 'play' key, (not all keyboards will have one) */
static const int stopKey; /**< key-code for a multimedia 'stop' key, (not all keyboards will have one) */
static const int fastForwardKey; /**< key-code for a multimedia 'fast-forward' key, (not all keyboards will have one) */
static const int rewindKey; /**< key-code for a multimedia 'rewind' key, (not all keyboards will have one) */
private:
//==============================================================================
int keyCode = 0;
ModifierKeys mods;
juce_wchar textCharacter = 0;
JUCE_LEAK_DETECTOR (KeyPress)
};
} // namespace juce

View File

@ -0,0 +1,274 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
namespace KeyboardFocusTraverserHelpers
{
static bool isKeyboardFocusable (const Component* comp, const Component* container)
{
return comp->getWantsKeyboardFocus() && container->isParentOf (comp);
}
static Component* traverse (Component* current, Component* container,
FocusHelpers::NavigationDirection direction)
{
if (auto* comp = FocusHelpers::navigateFocus (current, container, direction,
&Component::isKeyboardFocusContainer))
{
if (isKeyboardFocusable (comp, container))
return comp;
return traverse (comp, container, direction);
}
return nullptr;
}
}
Component* KeyboardFocusTraverser::getNextComponent (Component* current)
{
return KeyboardFocusTraverserHelpers::traverse (current, current->findKeyboardFocusContainer(),
FocusHelpers::NavigationDirection::forwards);
}
Component* KeyboardFocusTraverser::getPreviousComponent (Component* current)
{
return KeyboardFocusTraverserHelpers::traverse (current, current->findKeyboardFocusContainer(),
FocusHelpers::NavigationDirection::backwards);
}
Component* KeyboardFocusTraverser::getDefaultComponent (Component* parentComponent)
{
for (auto* comp : getAllComponents (parentComponent))
if (KeyboardFocusTraverserHelpers::isKeyboardFocusable (comp, parentComponent))
return comp;
return nullptr;
}
std::vector<Component*> KeyboardFocusTraverser::getAllComponents (Component* parentComponent)
{
std::vector<Component*> components;
FocusHelpers::findAllComponents (parentComponent,
components,
&Component::isKeyboardFocusContainer);
auto removePredicate = [parentComponent] (const Component* comp)
{
return ! KeyboardFocusTraverserHelpers::isKeyboardFocusable (comp, parentComponent);
};
components.erase (std::remove_if (std::begin (components), std::end (components), std::move (removePredicate)),
std::end (components));
return components;
}
//==============================================================================
//==============================================================================
#if JUCE_UNIT_TESTS
struct KeyboardFocusTraverserTests : public UnitTest
{
KeyboardFocusTraverserTests()
: UnitTest ("KeyboardFocusTraverser", UnitTestCategories::gui)
{}
void runTest() override
{
ScopedJuceInitialiser_GUI libraryInitialiser;
const MessageManagerLock mml;
beginTest ("No child wants keyboard focus");
{
TestComponent parent;
expect (traverser.getDefaultComponent (&parent) == nullptr);
expect (traverser.getAllComponents (&parent).empty());
}
beginTest ("Single child wants keyboard focus");
{
TestComponent parent;
parent.children[5].setWantsKeyboardFocus (true);
auto* defaultComponent = traverser.getDefaultComponent (&parent);
expect (defaultComponent == &parent.children[5]);
expect (defaultComponent->getWantsKeyboardFocus());
expect (traverser.getNextComponent (defaultComponent) == nullptr);
expect (traverser.getPreviousComponent (defaultComponent) == nullptr);
expect (traverser.getAllComponents (&parent).size() == 1);
}
beginTest ("Multiple children want keyboard focus");
{
TestComponent parent;
Component* focusChildren[]
{
&parent.children[1],
&parent.children[9],
&parent.children[3],
&parent.children[5],
&parent.children[8],
&parent.children[0]
};
for (auto* focusChild : focusChildren)
focusChild->setWantsKeyboardFocus (true);
auto allComponents = traverser.getAllComponents (&parent);
for (auto* focusChild : focusChildren)
expect (std::find (allComponents.cbegin(), allComponents.cend(), focusChild) != allComponents.cend());
auto* componentToTest = traverser.getDefaultComponent (&parent);
for (;;)
{
expect (componentToTest->getWantsKeyboardFocus());
expect (std::find (std::begin (focusChildren), std::end (focusChildren), componentToTest) != std::end (focusChildren));
componentToTest = traverser.getNextComponent (componentToTest);
if (componentToTest == nullptr)
break;
}
int focusOrder = 1;
for (auto* focusChild : focusChildren)
focusChild->setExplicitFocusOrder (focusOrder++);
componentToTest = traverser.getDefaultComponent (&parent);
for (auto* focusChild : focusChildren)
{
expect (componentToTest == focusChild);
expect (componentToTest->getWantsKeyboardFocus());
componentToTest = traverser.getNextComponent (componentToTest);
}
}
beginTest ("Single nested child wants keyboard focus");
{
TestComponent parent;
Component grandparent;
grandparent.addAndMakeVisible (parent);
auto& focusChild = parent.children[5];
focusChild.setWantsKeyboardFocus (true);
expect (traverser.getDefaultComponent (&grandparent) == &focusChild);
expect (traverser.getDefaultComponent (&parent) == &focusChild);
expect (traverser.getNextComponent (&focusChild) == nullptr);
expect (traverser.getPreviousComponent (&focusChild) == nullptr);
expect (traverser.getAllComponents (&parent).size() == 1);
}
beginTest ("Multiple nested children want keyboard focus");
{
TestComponent parent;
Component grandparent;
grandparent.addAndMakeVisible (parent);
Component* focusChildren[]
{
&parent.children[1],
&parent.children[4],
&parent.children[5]
};
for (auto* focusChild : focusChildren)
focusChild->setWantsKeyboardFocus (true);
auto allComponents = traverser.getAllComponents (&parent);
expect (std::equal (allComponents.cbegin(), allComponents.cend(), focusChildren,
[] (const Component* c1, const Component* c2) { return c1 == c2; }));
const auto front = *focusChildren;
const auto back = *std::prev (std::end (focusChildren));
expect (traverser.getDefaultComponent (&grandparent) == front);
expect (traverser.getDefaultComponent (&parent) == front);
expect (traverser.getNextComponent (front) == *std::next (std::begin (focusChildren)));
expect (traverser.getPreviousComponent (back) == *std::prev (std::end (focusChildren), 2));
std::array<Component, 3> otherParents;
for (auto& p : otherParents)
{
grandparent.addAndMakeVisible (p);
p.setWantsKeyboardFocus (true);
}
expect (traverser.getDefaultComponent (&grandparent) == front);
expect (traverser.getDefaultComponent (&parent) == front);
expect (traverser.getNextComponent (back) == &otherParents.front());
expect (traverser.getNextComponent (&otherParents.back()) == nullptr);
expect (traverser.getAllComponents (&grandparent).size() == numElementsInArray (focusChildren) + otherParents.size());
expect (traverser.getAllComponents (&parent).size() == (size_t) numElementsInArray (focusChildren));
for (auto* focusChild : focusChildren)
focusChild->setWantsKeyboardFocus (false);
expect (traverser.getDefaultComponent (&grandparent) == &otherParents.front());
expect (traverser.getDefaultComponent (&parent) == nullptr);
expect (traverser.getAllComponents (&grandparent).size() == otherParents.size());
expect (traverser.getAllComponents (&parent).empty());
}
}
private:
struct TestComponent : public Component
{
TestComponent()
{
for (auto& child : children)
addAndMakeVisible (child);
}
std::array<Component, 10> children;
};
KeyboardFocusTraverser traverser;
};
static KeyboardFocusTraverserTests keyboardFocusTraverserTests;
#endif
} // namespace juce

View File

@ -0,0 +1,87 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
Controls the order in which keyboard focus moves between components.
The default behaviour of this class uses a FocusTraverser object internally to
determine the default/next/previous component until it finds one which wants
keyboard focus, as set by the Component::setWantsKeyboardFocus() method.
If you need keyboard focus traversal in a more customised way, you can create
a subclass of ComponentTraverser that uses your own algorithm, and use
Component::createKeyboardFocusTraverser() to create it.
@see FocusTraverser, ComponentTraverser, Component::createKeyboardFocusTraverser
@tags{GUI}
*/
class JUCE_API KeyboardFocusTraverser : public ComponentTraverser
{
public:
/** Destructor. */
~KeyboardFocusTraverser() override = default;
/** Returns the component that should receive keyboard focus by default within the
given parent component.
The default implementation will return the foremost focusable component (as
determined by FocusTraverser) that also wants keyboard focus, or nullptr if
there is no suitable component.
*/
Component* getDefaultComponent (Component* parentComponent) override;
/** Returns the component that should be given keyboard focus after the specified
one when moving "forwards".
The default implementation will return the next focusable component (as
determined by FocusTraverser) that also wants keyboard focus, or nullptr if
there is no suitable component.
*/
Component* getNextComponent (Component* current) override;
/** Returns the component that should be given keyboard focus after the specified
one when moving "backwards".
The default implementation will return the previous focusable component (as
determined by FocusTraverser) that also wants keyboard focus, or nullptr if
there is no suitable component.
*/
Component* getPreviousComponent (Component* current) override;
/** Returns all of the components that can receive keyboard focus within the given
parent component in traversal order.
The default implementation will return all focusable child components (as
determined by FocusTraverser) that also wants keyboard focus.
*/
std::vector<Component*> getAllComponents (Component* parentComponent) override;
};
} // namespace juce

View File

@ -0,0 +1,49 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
ModifierKeys ModifierKeys::currentModifiers;
ModifierKeys::ModifierKeys (int rawFlags) noexcept : flags (rawFlags) {}
int ModifierKeys::getNumMouseButtonsDown() const noexcept
{
int num = 0;
if (isLeftButtonDown()) ++num;
if (isRightButtonDown()) ++num;
if (isMiddleButtonDown()) ++num;
return num;
}
ModifierKeys ModifierKeys::getCurrentModifiersRealtime() noexcept
{
return ComponentPeer::getCurrentModifiersRealtime();
}
} // namespace juce

View File

@ -0,0 +1,211 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
Represents the state of the mouse buttons and modifier keys.
This is used both by mouse events and by KeyPress objects to describe
the state of keys such as shift, control, alt, etc.
@see KeyPress, MouseEvent::mods
@tags{GUI}
*/
class JUCE_API ModifierKeys
{
public:
//==============================================================================
/** Creates a ModifierKeys object with no flags set. */
ModifierKeys() = default;
/** Creates a ModifierKeys object from a raw set of flags.
@param flags to represent the keys that are down
@see shiftModifier, ctrlModifier, altModifier, leftButtonModifier,
rightButtonModifier, commandModifier, popupMenuClickModifier
*/
ModifierKeys (int flags) noexcept;
/** Creates a copy of another object. */
ModifierKeys (const ModifierKeys&) = default;
/** Copies this object from another one. */
ModifierKeys& operator= (const ModifierKeys&) = default;
//==============================================================================
/** Checks whether the 'command' key flag is set (or 'ctrl' on Windows/Linux).
This is a platform-agnostic way of checking for the operating system's
preferred command-key modifier - so on the Mac it tests for the cmd key, on
Windows/Linux, it's actually checking for the CTRL key.
*/
inline bool isCommandDown() const noexcept { return testFlags (commandModifier); }
/** Checks whether the user is trying to launch a pop-up menu.
This checks for platform-specific modifiers that might indicate that the user
is following the operating system's normal method of showing a pop-up menu.
So on Windows/Linux, this method is really testing for a right-click.
On the Mac, it tests for either the CTRL key being down, or a right-click.
*/
inline bool isPopupMenu() const noexcept { return testFlags (popupMenuClickModifier); }
/** Checks whether the flag is set for the left mouse-button. */
inline bool isLeftButtonDown() const noexcept { return testFlags (leftButtonModifier); }
/** Checks whether the flag is set for the right mouse-button.
Note that for detecting popup-menu clicks, you should be using isPopupMenu() instead, as
this is platform-independent (and makes your code more explanatory too).
*/
inline bool isRightButtonDown() const noexcept { return testFlags (rightButtonModifier); }
inline bool isMiddleButtonDown() const noexcept { return testFlags (middleButtonModifier); }
/** Tests for any of the mouse-button flags. */
inline bool isAnyMouseButtonDown() const noexcept { return testFlags (allMouseButtonModifiers); }
/** Tests for any of the modifier key flags. */
inline bool isAnyModifierKeyDown() const noexcept { return testFlags ((shiftModifier | ctrlModifier | altModifier | commandModifier)); }
/** Checks whether the shift key's flag is set. */
inline bool isShiftDown() const noexcept { return testFlags (shiftModifier); }
/** Checks whether the CTRL key's flag is set.
Remember that it's better to use the platform-agnostic routines to test for command-key and
popup-menu modifiers.
@see isCommandDown, isPopupMenu
*/
inline bool isCtrlDown() const noexcept { return testFlags (ctrlModifier); }
/** Checks whether the ALT key's flag is set. */
inline bool isAltDown() const noexcept { return testFlags (altModifier); }
//==============================================================================
/** Flags that represent the different keys. */
enum Flags
{
/** Indicates no modifier keys. */
noModifiers = 0,
/** Shift key flag. */
shiftModifier = 1,
/** CTRL key flag. */
ctrlModifier = 2,
/** ALT key flag. */
altModifier = 4,
/** Left mouse button flag. */
leftButtonModifier = 16,
/** Right mouse button flag. */
rightButtonModifier = 32,
/** Middle mouse button flag. */
middleButtonModifier = 64,
#if JUCE_MAC || JUCE_IOS
/** Command key flag - on windows this is the same as the CTRL key flag. */
commandModifier = 8,
/** Popup menu flag - on windows this is the same as rightButtonModifier, on the
Mac it's the same as (rightButtonModifier | ctrlModifier). */
popupMenuClickModifier = rightButtonModifier | ctrlModifier,
#else
/** Command key flag - on windows this is the same as the CTRL key flag. */
commandModifier = ctrlModifier,
/** Popup menu flag - on windows this is the same as rightButtonModifier, on the
Mac it's the same as (rightButtonModifier | ctrlModifier). */
popupMenuClickModifier = rightButtonModifier,
#endif
/** Represents a combination of all the shift, alt, ctrl and command key modifiers. */
allKeyboardModifiers = shiftModifier | ctrlModifier | altModifier | commandModifier,
/** Represents a combination of all the mouse buttons at once. */
allMouseButtonModifiers = leftButtonModifier | rightButtonModifier | middleButtonModifier,
/** Represents a combination of all the alt, ctrl and command key modifiers. */
ctrlAltCommandModifiers = ctrlModifier | altModifier | commandModifier
};
//==============================================================================
/** Returns a copy of only the mouse-button flags */
ModifierKeys withOnlyMouseButtons() const noexcept { return ModifierKeys (flags & allMouseButtonModifiers); }
/** Returns a copy of only the non-mouse flags */
ModifierKeys withoutMouseButtons() const noexcept { return ModifierKeys (flags & ~allMouseButtonModifiers); }
bool operator== (const ModifierKeys other) const noexcept { return flags == other.flags; }
bool operator!= (const ModifierKeys other) const noexcept { return flags != other.flags; }
//==============================================================================
/** Returns the raw flags for direct testing. */
inline int getRawFlags() const noexcept { return flags; }
ModifierKeys withoutFlags (int rawFlagsToClear) const noexcept { return ModifierKeys (flags & ~rawFlagsToClear); }
ModifierKeys withFlags (int rawFlagsToSet) const noexcept { return ModifierKeys (flags | rawFlagsToSet); }
/** Tests a combination of flags and returns true if any of them are set. */
bool testFlags (int flagsToTest) const noexcept { return (flags & flagsToTest) != 0; }
/** Returns the total number of mouse buttons that are down. */
int getNumMouseButtonsDown() const noexcept;
//==============================================================================
/** This object represents the last-known state of the keyboard and mouse buttons. */
static ModifierKeys currentModifiers;
/** Creates a ModifierKeys object to represent the last-known state of the
keyboard and mouse buttons.
This method is here for backwards compatibility and there's no need to call it anymore,
you should use the public currentModifiers member directly.
*/
static ModifierKeys getCurrentModifiers() noexcept { return currentModifiers; }
/** Creates a ModifierKeys object to represent the current state of the
keyboard and mouse buttons.
This method is here for backwards compatibility and you should call ComponentPeer::getCurrentModifiersRealtime()
instead (which is what this method now does).
*/
static ModifierKeys getCurrentModifiersRealtime() noexcept;
private:
int flags = 0;
};
} // namespace juce

View File

@ -0,0 +1,49 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
Handles reading/writing to the system's clipboard.
@tags{GUI}
*/
class JUCE_API SystemClipboard
{
public:
/** Copies a string of text onto the clipboard */
static void copyTextToClipboard (const String& text);
/** Gets the current clipboard's contents.
Obviously this might have come from another app, so could contain
anything..
*/
static String getTextFromClipboard();
};
} // namespace juce

View File

@ -0,0 +1,123 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/** This class is used to invoke a range of text-editor navigation methods on
an object, based upon a keypress event.
It's currently used internally by the TextEditor and CodeEditorComponent.
@tags{GUI}
*/
template <class CallbackClass>
struct TextEditorKeyMapper
{
/** Checks the keypress and invokes one of a range of navigation functions that
the target class must implement, based on the key event.
*/
static bool invokeKeyFunction (CallbackClass& target, const KeyPress& key)
{
auto mods = key.getModifiers();
const bool isShiftDown = mods.isShiftDown();
const bool ctrlOrAltDown = mods.isCtrlDown() || mods.isAltDown();
int numCtrlAltCommandKeys = 0;
if (mods.isCtrlDown()) ++numCtrlAltCommandKeys;
if (mods.isAltDown()) ++numCtrlAltCommandKeys;
if (key == KeyPress (KeyPress::downKey, ModifierKeys::ctrlModifier, 0) && target.scrollUp()) return true;
if (key == KeyPress (KeyPress::upKey, ModifierKeys::ctrlModifier, 0) && target.scrollDown()) return true;
#if JUCE_MAC
if (mods.isCommandDown() && ! ctrlOrAltDown)
{
if (key.isKeyCode (KeyPress::upKey)) return target.moveCaretToTop (isShiftDown);
if (key.isKeyCode (KeyPress::downKey)) return target.moveCaretToEnd (isShiftDown);
if (key.isKeyCode (KeyPress::leftKey)) return target.moveCaretToStartOfLine (isShiftDown);
if (key.isKeyCode (KeyPress::rightKey)) return target.moveCaretToEndOfLine (isShiftDown);
}
if (mods.isCommandDown())
++numCtrlAltCommandKeys;
#endif
if (numCtrlAltCommandKeys < 2)
{
if (key.isKeyCode (KeyPress::leftKey)) return target.moveCaretLeft (ctrlOrAltDown, isShiftDown);
if (key.isKeyCode (KeyPress::rightKey)) return target.moveCaretRight (ctrlOrAltDown, isShiftDown);
if (key.isKeyCode (KeyPress::homeKey)) return ctrlOrAltDown ? target.moveCaretToTop (isShiftDown)
: target.moveCaretToStartOfLine (isShiftDown);
if (key.isKeyCode (KeyPress::endKey)) return ctrlOrAltDown ? target.moveCaretToEnd (isShiftDown)
: target.moveCaretToEndOfLine (isShiftDown);
}
if (numCtrlAltCommandKeys == 0)
{
if (key.isKeyCode (KeyPress::upKey)) return target.moveCaretUp (isShiftDown);
if (key.isKeyCode (KeyPress::downKey)) return target.moveCaretDown (isShiftDown);
if (key.isKeyCode (KeyPress::pageUpKey)) return target.pageUp (isShiftDown);
if (key.isKeyCode (KeyPress::pageDownKey)) return target.pageDown (isShiftDown);
}
if (key == KeyPress ('c', ModifierKeys::commandModifier, 0)
|| key == KeyPress (KeyPress::insertKey, ModifierKeys::ctrlModifier, 0))
return target.copyToClipboard();
if (key == KeyPress ('x', ModifierKeys::commandModifier, 0)
|| key == KeyPress (KeyPress::deleteKey, ModifierKeys::shiftModifier, 0))
return target.cutToClipboard();
if (key == KeyPress ('v', ModifierKeys::commandModifier, 0)
|| key == KeyPress (KeyPress::insertKey, ModifierKeys::shiftModifier, 0))
return target.pasteFromClipboard();
// NB: checking for delete must happen after the earlier check for shift + delete
if (numCtrlAltCommandKeys < 2)
{
if (key.isKeyCode (KeyPress::backspaceKey)) return target.deleteBackwards (ctrlOrAltDown);
if (key.isKeyCode (KeyPress::deleteKey)) return target.deleteForwards (ctrlOrAltDown);
}
if (key == KeyPress ('a', ModifierKeys::commandModifier, 0))
return target.selectAll();
if (key == KeyPress ('z', ModifierKeys::commandModifier, 0))
return target.undo();
if (key == KeyPress ('y', ModifierKeys::commandModifier, 0)
|| key == KeyPress ('z', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0))
return target.redo();
return false;
}
};
} // namespace juce

View File

@ -0,0 +1,96 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
An abstract base class which can be implemented by components that function as
text editors.
This class allows different types of text editor component to provide a uniform
interface, which can be used by things like OS-specific input methods, on-screen
keyboards, etc.
@tags{GUI}
*/
class JUCE_API TextInputTarget
{
public:
//==============================================================================
/** */
TextInputTarget() = default;
/** Destructor. */
virtual ~TextInputTarget() = default;
/** Returns true if this input target is currently accepting input.
For example, a text editor might return false if it's in read-only mode.
*/
virtual bool isTextInputActive() const = 0;
/** Returns the extents of the selected text region, or an empty range if
nothing is selected,
*/
virtual Range<int> getHighlightedRegion() const = 0;
/** Sets the currently-selected text region. */
virtual void setHighlightedRegion (const Range<int>& newRange) = 0;
/** Sets a number of temporarily underlined sections.
This is needed by MS Windows input method UI.
*/
virtual void setTemporaryUnderlining (const Array<Range<int>>& underlinedRegions) = 0;
/** Returns a specified sub-section of the text. */
virtual String getTextInRange (const Range<int>& range) const = 0;
/** Inserts some text, overwriting the selected text region, if there is one. */
virtual void insertTextAtCaret (const String& textToInsert) = 0;
/** Returns the position of the caret, relative to the component's origin. */
virtual Rectangle<int> getCaretRectangle() = 0;
/** A set of possible on-screen keyboard types, for use in the
getKeyboardType() method.
*/
enum VirtualKeyboardType
{
textKeyboard = 0,
numericKeyboard,
decimalKeyboard,
urlKeyboard,
emailAddressKeyboard,
phoneNumberKeyboard
};
/** Returns the target's preference for the type of keyboard that would be most appropriate.
This may be ignored, depending on the capabilities of the OS.
*/
virtual VirtualKeyboardType getKeyboardType() { return textKeyboard; }
};
} // namespace juce