|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2022 - 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 7 End-User License
- Agreement and JUCE Privacy Policy.
-
- End User License Agreement: www.juce.com/juce-7-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
|