The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
8.7KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. #include "../../../../juce_core/basics/juce_StandardHeader.h"
  24. BEGIN_JUCE_NAMESPACE
  25. #include "juce_KeyPress.h"
  26. #include "../juce_Component.h"
  27. //==============================================================================
  28. KeyPress::KeyPress() throw()
  29. : keyCode (0),
  30. mods (0),
  31. textCharacter (0)
  32. {
  33. }
  34. KeyPress::KeyPress (const int keyCode_,
  35. const ModifierKeys& mods_,
  36. const juce_wchar textCharacter_) throw()
  37. : keyCode (keyCode_),
  38. mods (mods_),
  39. textCharacter (textCharacter_)
  40. {
  41. }
  42. KeyPress::KeyPress (const int keyCode_) throw()
  43. : keyCode (keyCode_),
  44. textCharacter (0)
  45. {
  46. }
  47. KeyPress::KeyPress (const KeyPress& other) throw()
  48. : keyCode (other.keyCode),
  49. mods (other.mods),
  50. textCharacter (other.textCharacter)
  51. {
  52. }
  53. const KeyPress& KeyPress::operator= (const KeyPress& other) throw()
  54. {
  55. keyCode = other.keyCode;
  56. mods = other.mods;
  57. textCharacter = other.textCharacter;
  58. return *this;
  59. }
  60. bool KeyPress::operator== (const KeyPress& other) const throw()
  61. {
  62. return mods.getRawFlags() == other.mods.getRawFlags()
  63. && (textCharacter == other.textCharacter
  64. || textCharacter == 0
  65. || other.textCharacter == 0)
  66. && (keyCode == other.keyCode
  67. || (keyCode < 256
  68. && other.keyCode < 256
  69. && CharacterFunctions::toLowerCase ((tchar) keyCode)
  70. == CharacterFunctions::toLowerCase ((tchar) other.keyCode)));
  71. }
  72. bool KeyPress::operator!= (const KeyPress& other) const throw()
  73. {
  74. return ! operator== (other);
  75. }
  76. bool KeyPress::isCurrentlyDown() const
  77. {
  78. int modsMask = ModifierKeys::commandModifier | ModifierKeys::ctrlModifier | ModifierKeys::altModifier;
  79. if (keyCode == KeyPress::downKey
  80. || keyCode == KeyPress::upKey
  81. || keyCode == KeyPress::leftKey
  82. || keyCode == KeyPress::rightKey
  83. || keyCode == KeyPress::deleteKey
  84. || keyCode == KeyPress::backspaceKey
  85. || keyCode == KeyPress::returnKey
  86. || keyCode == KeyPress::escapeKey
  87. || keyCode == KeyPress::homeKey
  88. || keyCode == KeyPress::endKey
  89. || keyCode == KeyPress::pageUpKey
  90. || keyCode == KeyPress::pageDownKey
  91. || (keyCode >= KeyPress::F1Key && keyCode <= KeyPress::F16Key))
  92. {
  93. modsMask |= ModifierKeys::shiftModifier;
  94. }
  95. return isKeyCurrentlyDown (keyCode)
  96. && (ModifierKeys::getCurrentModifiers().getRawFlags() & modsMask)
  97. == (mods.getRawFlags() & modsMask);
  98. }
  99. //==============================================================================
  100. struct KeyNameAndCode
  101. {
  102. const char* name;
  103. int code;
  104. };
  105. static const KeyNameAndCode keyNameTranslations[] =
  106. {
  107. { "spacebar", KeyPress::spaceKey },
  108. { "return", KeyPress::returnKey },
  109. { "escape", KeyPress::escapeKey },
  110. { "backspace", KeyPress::backspaceKey },
  111. { "cursor left", KeyPress::leftKey },
  112. { "cursor right", KeyPress::rightKey },
  113. { "cursor up", KeyPress::upKey },
  114. { "cursor down", KeyPress::downKey },
  115. { "page up", KeyPress::pageUpKey },
  116. { "page down", KeyPress::pageDownKey },
  117. { "home", KeyPress::homeKey },
  118. { "end", KeyPress::endKey },
  119. { "delete", KeyPress::deleteKey },
  120. { "insert", KeyPress::insertKey },
  121. { "tab", KeyPress::tabKey },
  122. { "play", KeyPress::playKey },
  123. { "stop", KeyPress::stopKey },
  124. { "fast forward", KeyPress::fastForwardKey },
  125. { "rewind", KeyPress::rewindKey }
  126. };
  127. static const tchar* const numberPadPrefix = T("numpad ");
  128. //==============================================================================
  129. const KeyPress KeyPress::createFromDescription (const String& desc)
  130. {
  131. int modifiers = 0;
  132. if (desc.containsWholeWordIgnoreCase (T("ctrl"))
  133. || desc.containsWholeWordIgnoreCase (T("control"))
  134. || desc.containsWholeWordIgnoreCase (T("ctl")))
  135. modifiers |= ModifierKeys::ctrlModifier;
  136. if (desc.containsWholeWordIgnoreCase (T("shift"))
  137. || desc.containsWholeWordIgnoreCase (T("shft")))
  138. modifiers |= ModifierKeys::shiftModifier;
  139. if (desc.containsWholeWordIgnoreCase (T("alt"))
  140. || desc.containsWholeWordIgnoreCase (T("option")))
  141. modifiers |= ModifierKeys::altModifier;
  142. if (desc.containsWholeWordIgnoreCase (T("command"))
  143. || desc.containsWholeWordIgnoreCase (T("cmd")))
  144. modifiers |= ModifierKeys::commandModifier;
  145. int key = 0;
  146. for (int i = 0; i < numElementsInArray (keyNameTranslations); ++i)
  147. {
  148. if (desc.containsWholeWordIgnoreCase (String (keyNameTranslations[i].name)))
  149. {
  150. key = keyNameTranslations[i].code;
  151. break;
  152. }
  153. }
  154. if (key == 0)
  155. {
  156. // see if it's a numpad key..
  157. for (int i = 0; i < 10; ++i)
  158. if (desc.containsWholeWordIgnoreCase (numberPadPrefix + String (i)))
  159. key = numberPad0 + i;
  160. if (key == 0)
  161. {
  162. // see if it's a function key..
  163. for (int i = 1; i <= 12; ++i)
  164. if (desc.containsWholeWordIgnoreCase (T("f") + String (i)))
  165. key = F1Key + i - 1;
  166. if (key == 0)
  167. {
  168. // give up and use the hex code..
  169. const int hexCode = desc.fromFirstOccurrenceOf (T("#"), false, false)
  170. .toLowerCase()
  171. .retainCharacters (T("0123456789abcdef"))
  172. .getHexValue32();
  173. if (hexCode > 0)
  174. {
  175. key = hexCode;
  176. }
  177. else
  178. {
  179. key = CharacterFunctions::toUpperCase (desc.getLastCharacter());
  180. }
  181. }
  182. }
  183. }
  184. return KeyPress (key, ModifierKeys (modifiers), 0);
  185. }
  186. const String KeyPress::getTextDescription() const
  187. {
  188. String desc;
  189. if (keyCode > 0)
  190. {
  191. if (mods.isCtrlDown())
  192. desc << "ctrl + ";
  193. if (mods.isShiftDown())
  194. desc << "shift + ";
  195. #if JUCE_MAC
  196. // only do this on the mac, because on Windows ctrl and command are the same,
  197. // and this would get confusing
  198. if (mods.isCommandDown())
  199. desc << "command + ";
  200. if (mods.isAltDown())
  201. desc << "option + ";
  202. #else
  203. if (mods.isAltDown())
  204. desc << "alt + ";
  205. #endif
  206. for (int i = 0; i < numElementsInArray (keyNameTranslations); ++i)
  207. if (keyCode == keyNameTranslations[i].code)
  208. return desc + keyNameTranslations[i].name;
  209. if (keyCode >= F1Key && keyCode <= F16Key)
  210. desc << 'F' << (1 + keyCode - F1Key);
  211. else if (keyCode >= numberPad0 && keyCode <= numberPad9)
  212. desc << numberPadPrefix << (keyCode - numberPad0);
  213. else if (keyCode >= 33 && keyCode < 176)
  214. desc += CharacterFunctions::toUpperCase ((tchar) keyCode);
  215. else
  216. desc << '#' << String::toHexString (keyCode);
  217. }
  218. return desc;
  219. }
  220. END_JUCE_NAMESPACE