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.

378 lines
12KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. //==============================================================================
  19. String hexString8Digits (int value);
  20. String createAlphaNumericUID();
  21. String createGUID (const String& seed); // Turns a seed into a windows GUID
  22. String escapeSpaces (const String& text); // replaces spaces with blackslash-space
  23. String addQuotesIfContainsSpaces (const String& text);
  24. StringPairArray parsePreprocessorDefs (const String& defs);
  25. StringPairArray mergePreprocessorDefs (StringPairArray inheritedDefs, const StringPairArray& overridingDefs);
  26. String createGCCPreprocessorFlags (const StringPairArray& defs);
  27. String replacePreprocessorDefs (const StringPairArray& definitions, String sourceString);
  28. StringArray getSearchPathsFromString (const String& searchPath);
  29. void setValueIfVoid (Value value, const var& defaultValue);
  30. //==============================================================================
  31. int indexOfLineStartingWith (const StringArray& lines, const String& text, int startIndex);
  32. void autoScrollForMouseEvent (const MouseEvent& e, bool scrollX = true, bool scrollY = true);
  33. void drawComponentPlaceholder (Graphics& g, int w, int h, const String& text);
  34. void drawRecessedShadows (Graphics& g, int w, int h, int shadowSize);
  35. void showUTF8ToolWindow();
  36. // Start a callout modally, which will delete the content comp when it's dismissed.
  37. void launchAsyncCallOutBox (Component& attachTo, Component* content);
  38. bool cancelAnyModalComponents();
  39. bool reinvokeCommandAfterCancellingModalComps (const ApplicationCommandTarget::InvocationInfo&);
  40. //==============================================================================
  41. struct Icon
  42. {
  43. Icon() : path (nullptr) {}
  44. Icon (const Path& p, const Colour& c) : path (&p), colour (c) {}
  45. Icon (const Path* p, const Colour& c) : path (p), colour (c) {}
  46. void draw (Graphics& g, const Rectangle<float>& area) const
  47. {
  48. if (path != nullptr)
  49. {
  50. g.setColour (colour);
  51. const RectanglePlacement placement (RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize);
  52. g.fillPath (*path, placement.getTransformToFit (path->getBounds(), area));
  53. }
  54. }
  55. Icon withContrastingColourTo (const Colour& background) const
  56. {
  57. return Icon (path, background.contrasting (colour, 0.6f));
  58. }
  59. const Path* path;
  60. Colour colour;
  61. };
  62. //==============================================================================
  63. class RolloverHelpComp : public Component,
  64. private Timer
  65. {
  66. public:
  67. RolloverHelpComp();
  68. void paint (Graphics& g);
  69. void timerCallback();
  70. private:
  71. Component* lastComp;
  72. String lastTip;
  73. static String findTip (Component*);
  74. };
  75. //==============================================================================
  76. class PropertyListBuilder
  77. {
  78. public:
  79. PropertyListBuilder() {}
  80. void add (PropertyComponent* propertyComp)
  81. {
  82. components.add (propertyComp);
  83. }
  84. void add (PropertyComponent* propertyComp, const String& tooltip)
  85. {
  86. propertyComp->setTooltip (tooltip);
  87. add (propertyComp);
  88. }
  89. void addSearchPathProperty (const Value& value, const String& name, const String& mainHelpText)
  90. {
  91. add (new TextPropertyComponent (value, name, 16384, true),
  92. mainHelpText + " Use semi-colons or new-lines to separate multiple paths.");
  93. }
  94. void setPreferredHeight (int height)
  95. {
  96. for (int j = components.size(); --j >= 0;)
  97. components.getUnchecked(j)->setPreferredHeight (height);
  98. }
  99. Array <PropertyComponent*> components;
  100. private:
  101. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyListBuilder);
  102. };
  103. //==============================================================================
  104. class FloatingLabelComponent : public Component
  105. {
  106. public:
  107. FloatingLabelComponent();
  108. void remove();
  109. void update (Component* parent, const String& text, const Colour& textColour,
  110. int x, int y, bool toRight, bool below);
  111. void paint (Graphics& g);
  112. private:
  113. Font font;
  114. Colour colour;
  115. GlyphArrangement glyphs;
  116. };
  117. //==============================================================================
  118. // A ValueSource which takes an input source, and forwards any changes in it.
  119. // This class is a handy way to create sources which re-map a value.
  120. class ValueSourceFilter : public Value::ValueSource,
  121. public Value::Listener
  122. {
  123. public:
  124. ValueSourceFilter (const Value& source) : sourceValue (source)
  125. {
  126. sourceValue.addListener (this);
  127. }
  128. void valueChanged (Value&) { sendChangeMessage (true); }
  129. protected:
  130. Value sourceValue;
  131. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueSourceFilter);
  132. };
  133. //==============================================================================
  134. class PopupColourSelector : public Component,
  135. public ChangeListener,
  136. public Value::Listener,
  137. public ButtonListener
  138. {
  139. public:
  140. PopupColourSelector (const Value& colourValue_,
  141. const Colour& defaultColour_,
  142. const bool canResetToDefault)
  143. : defaultButton ("Reset to Default"),
  144. colourValue (colourValue_),
  145. defaultColour (defaultColour_)
  146. {
  147. addAndMakeVisible (&selector);
  148. selector.setName ("Colour");
  149. selector.setCurrentColour (getColour());
  150. selector.addChangeListener (this);
  151. if (canResetToDefault)
  152. {
  153. addAndMakeVisible (&defaultButton);
  154. defaultButton.addListener (this);
  155. }
  156. colourValue.addListener (this);
  157. setSize (300, 400);
  158. }
  159. void resized()
  160. {
  161. if (defaultButton.isVisible())
  162. {
  163. selector.setBounds (0, 0, getWidth(), getHeight() - 30);
  164. defaultButton.changeWidthToFitText (22);
  165. defaultButton.setTopLeftPosition (10, getHeight() - 26);
  166. }
  167. else
  168. {
  169. selector.setBounds (0, 0, getWidth(), getHeight());
  170. }
  171. }
  172. Colour getColour() const
  173. {
  174. if (colourValue.toString().isEmpty())
  175. return defaultColour;
  176. return Colour::fromString (colourValue.toString());
  177. }
  178. void setColour (const Colour& newColour)
  179. {
  180. if (getColour() != newColour)
  181. {
  182. if (newColour == defaultColour && defaultButton.isVisible())
  183. colourValue = var::null;
  184. else
  185. colourValue = newColour.toDisplayString (true);
  186. }
  187. }
  188. void buttonClicked (Button*)
  189. {
  190. setColour (defaultColour);
  191. selector.setCurrentColour (defaultColour);
  192. }
  193. void changeListenerCallback (ChangeBroadcaster*)
  194. {
  195. if (selector.getCurrentColour() != getColour())
  196. setColour (selector.getCurrentColour());
  197. }
  198. void valueChanged (Value&)
  199. {
  200. selector.setCurrentColour (getColour());
  201. }
  202. private:
  203. StoredSettings::ColourSelectorWithSwatches selector;
  204. TextButton defaultButton;
  205. Value colourValue;
  206. Colour defaultColour;
  207. };
  208. //==============================================================================
  209. /**
  210. A component that shows a colour swatch with hex ARGB value, and which pops up
  211. a colour selector when you click it.
  212. */
  213. class ColourEditorComponent : public Component,
  214. public Value::Listener
  215. {
  216. public:
  217. ColourEditorComponent (UndoManager* undoManager_, const Value& colourValue_,
  218. const Colour& defaultColour_, const bool canResetToDefault_)
  219. : undoManager (undoManager_), colourValue (colourValue_), defaultColour (defaultColour_),
  220. canResetToDefault (canResetToDefault_)
  221. {
  222. colourValue.addListener (this);
  223. }
  224. void paint (Graphics& g)
  225. {
  226. const Colour colour (getColour());
  227. g.fillAll (Colours::grey);
  228. g.fillCheckerBoard (getLocalBounds().reduced (2, 2),
  229. 10, 10,
  230. Colour (0xffdddddd).overlaidWith (colour),
  231. Colour (0xffffffff).overlaidWith (colour));
  232. g.setColour (Colours::white.overlaidWith (colour).contrasting());
  233. g.setFont (Font (getHeight() * 0.6f, Font::bold));
  234. g.drawFittedText (colour.toDisplayString (true),
  235. 2, 1, getWidth() - 4, getHeight() - 1,
  236. Justification::centred, 1);
  237. }
  238. Colour getColour() const
  239. {
  240. if (colourValue.toString().isEmpty())
  241. return defaultColour;
  242. return Colour::fromString (colourValue.toString());
  243. }
  244. void setColour (const Colour& newColour)
  245. {
  246. if (getColour() != newColour)
  247. {
  248. if (newColour == defaultColour && canResetToDefault)
  249. colourValue = var::null;
  250. else
  251. colourValue = newColour.toDisplayString (true);
  252. }
  253. }
  254. void resetToDefault()
  255. {
  256. setColour (defaultColour);
  257. }
  258. void refresh()
  259. {
  260. const Colour col (getColour());
  261. if (col != lastColour)
  262. {
  263. lastColour = col;
  264. repaint();
  265. }
  266. }
  267. void mouseDown (const MouseEvent&)
  268. {
  269. if (undoManager != nullptr)
  270. undoManager->beginNewTransaction();
  271. launchAsyncCallOutBox (*this, new PopupColourSelector (colourValue, defaultColour, canResetToDefault));
  272. }
  273. void valueChanged (Value&)
  274. {
  275. refresh();
  276. }
  277. private:
  278. UndoManager* undoManager;
  279. Value colourValue;
  280. Colour lastColour;
  281. const Colour defaultColour;
  282. const bool canResetToDefault;
  283. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ColourEditorComponent);
  284. };
  285. //==============================================================================
  286. class ColourPropertyComponent : public PropertyComponent
  287. {
  288. public:
  289. ColourPropertyComponent (UndoManager* undoManager, const String& name, const Value& colour,
  290. const Colour& defaultColour, bool canResetToDefault)
  291. : PropertyComponent (name),
  292. colourEditor (undoManager, colour, defaultColour, canResetToDefault)
  293. {
  294. addAndMakeVisible (&colourEditor);
  295. }
  296. void resized()
  297. {
  298. colourEditor.setBounds (getLookAndFeel().getPropertyComponentContentPosition (*this));
  299. }
  300. void refresh() {}
  301. protected:
  302. ColourEditorComponent colourEditor;
  303. };