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.

376 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 drawTexturedBackground (Graphics& g);
  35. void showUTF8ToolWindow();
  36. bool cancelAnyModalComponents();
  37. bool reinvokeCommandAfterCancellingModalComps (const ApplicationCommandTarget::InvocationInfo&);
  38. //==============================================================================
  39. struct Icon
  40. {
  41. Icon() : path (nullptr) {}
  42. Icon (const Path& p, const Colour& c) : path (&p), colour (c) {}
  43. Icon (const Path* p, const Colour& c) : path (p), colour (c) {}
  44. void draw (Graphics& g, const Rectangle<float>& area) const
  45. {
  46. if (path != nullptr)
  47. {
  48. g.setColour (colour);
  49. const RectanglePlacement placement (RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize);
  50. g.fillPath (*path, placement.getTransformToFit (path->getBounds(), area));
  51. }
  52. }
  53. Icon withContrastingColourTo (const Colour& background) const
  54. {
  55. return Icon (path, background.contrasting (colour, 0.6f));
  56. }
  57. const Path* path;
  58. Colour colour;
  59. };
  60. //==============================================================================
  61. class RolloverHelpComp : public Component,
  62. private Timer
  63. {
  64. public:
  65. RolloverHelpComp();
  66. void paint (Graphics& g);
  67. void timerCallback();
  68. private:
  69. Component* lastComp;
  70. String lastTip;
  71. static String findTip (Component*);
  72. };
  73. //==============================================================================
  74. class PropertyListBuilder
  75. {
  76. public:
  77. PropertyListBuilder() {}
  78. void add (PropertyComponent* propertyComp)
  79. {
  80. components.add (propertyComp);
  81. }
  82. void add (PropertyComponent* propertyComp, const String& tooltip)
  83. {
  84. propertyComp->setTooltip (tooltip);
  85. add (propertyComp);
  86. }
  87. void addSearchPathProperty (const Value& value, const String& name, const String& mainHelpText)
  88. {
  89. add (new TextPropertyComponent (value, name, 16384, true),
  90. mainHelpText + " Use semi-colons or new-lines to separate multiple paths.");
  91. }
  92. void setPreferredHeight (int height)
  93. {
  94. for (int j = components.size(); --j >= 0;)
  95. components.getUnchecked(j)->setPreferredHeight (height);
  96. }
  97. Array <PropertyComponent*> components;
  98. private:
  99. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyListBuilder);
  100. };
  101. //==============================================================================
  102. class FloatingLabelComponent : public Component
  103. {
  104. public:
  105. FloatingLabelComponent();
  106. void remove();
  107. void update (Component* parent, const String& text, const Colour& textColour,
  108. int x, int y, bool toRight, bool below);
  109. void paint (Graphics& g);
  110. private:
  111. Font font;
  112. Colour colour;
  113. GlyphArrangement glyphs;
  114. };
  115. //==============================================================================
  116. // A ValueSource which takes an input source, and forwards any changes in it.
  117. // This class is a handy way to create sources which re-map a value.
  118. class ValueSourceFilter : public Value::ValueSource,
  119. public Value::Listener
  120. {
  121. public:
  122. ValueSourceFilter (const Value& source) : sourceValue (source)
  123. {
  124. sourceValue.addListener (this);
  125. }
  126. void valueChanged (Value&) { sendChangeMessage (true); }
  127. protected:
  128. Value sourceValue;
  129. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueSourceFilter);
  130. };
  131. //==============================================================================
  132. class PopupColourSelector : public Component,
  133. public ChangeListener,
  134. public Value::Listener,
  135. public ButtonListener
  136. {
  137. public:
  138. PopupColourSelector (const Value& colourValue_,
  139. const Colour& defaultColour_,
  140. const bool canResetToDefault)
  141. : defaultButton ("Reset to Default"),
  142. colourValue (colourValue_),
  143. defaultColour (defaultColour_)
  144. {
  145. addAndMakeVisible (&selector);
  146. selector.setName ("Colour");
  147. selector.setCurrentColour (getColour());
  148. selector.addChangeListener (this);
  149. if (canResetToDefault)
  150. {
  151. addAndMakeVisible (&defaultButton);
  152. defaultButton.addListener (this);
  153. }
  154. colourValue.addListener (this);
  155. setSize (300, 400);
  156. }
  157. void resized()
  158. {
  159. if (defaultButton.isVisible())
  160. {
  161. selector.setBounds (0, 0, getWidth(), getHeight() - 30);
  162. defaultButton.changeWidthToFitText (22);
  163. defaultButton.setTopLeftPosition (10, getHeight() - 26);
  164. }
  165. else
  166. {
  167. selector.setBounds (0, 0, getWidth(), getHeight());
  168. }
  169. }
  170. Colour getColour() const
  171. {
  172. if (colourValue.toString().isEmpty())
  173. return defaultColour;
  174. return Colour::fromString (colourValue.toString());
  175. }
  176. void setColour (const Colour& newColour)
  177. {
  178. if (getColour() != newColour)
  179. {
  180. if (newColour == defaultColour && defaultButton.isVisible())
  181. colourValue = var::null;
  182. else
  183. colourValue = newColour.toDisplayString (true);
  184. }
  185. }
  186. void buttonClicked (Button*)
  187. {
  188. setColour (defaultColour);
  189. selector.setCurrentColour (defaultColour);
  190. }
  191. void changeListenerCallback (ChangeBroadcaster*)
  192. {
  193. if (selector.getCurrentColour() != getColour())
  194. setColour (selector.getCurrentColour());
  195. }
  196. void valueChanged (Value&)
  197. {
  198. selector.setCurrentColour (getColour());
  199. }
  200. private:
  201. StoredSettings::ColourSelectorWithSwatches selector;
  202. TextButton defaultButton;
  203. Value colourValue;
  204. Colour defaultColour;
  205. };
  206. //==============================================================================
  207. /**
  208. A component that shows a colour swatch with hex ARGB value, and which pops up
  209. a colour selector when you click it.
  210. */
  211. class ColourEditorComponent : public Component,
  212. public Value::Listener
  213. {
  214. public:
  215. ColourEditorComponent (UndoManager* undoManager_, const Value& colourValue_,
  216. const Colour& defaultColour_, const bool canResetToDefault_)
  217. : undoManager (undoManager_), colourValue (colourValue_), defaultColour (defaultColour_),
  218. canResetToDefault (canResetToDefault_)
  219. {
  220. colourValue.addListener (this);
  221. }
  222. void paint (Graphics& g)
  223. {
  224. const Colour colour (getColour());
  225. g.fillAll (Colours::grey);
  226. g.fillCheckerBoard (getLocalBounds().reduced (2, 2),
  227. 10, 10,
  228. Colour (0xffdddddd).overlaidWith (colour),
  229. Colour (0xffffffff).overlaidWith (colour));
  230. g.setColour (Colours::white.overlaidWith (colour).contrasting());
  231. g.setFont (Font (getHeight() * 0.6f, Font::bold));
  232. g.drawFittedText (colour.toDisplayString (true), getLocalBounds().reduced (2, 1),
  233. Justification::centred, 1);
  234. }
  235. Colour getColour() const
  236. {
  237. if (colourValue.toString().isEmpty())
  238. return defaultColour;
  239. return Colour::fromString (colourValue.toString());
  240. }
  241. void setColour (const Colour& newColour)
  242. {
  243. if (getColour() != newColour)
  244. {
  245. if (newColour == defaultColour && canResetToDefault)
  246. colourValue = var::null;
  247. else
  248. colourValue = newColour.toDisplayString (true);
  249. }
  250. }
  251. void resetToDefault()
  252. {
  253. setColour (defaultColour);
  254. }
  255. void refresh()
  256. {
  257. const Colour col (getColour());
  258. if (col != lastColour)
  259. {
  260. lastColour = col;
  261. repaint();
  262. }
  263. }
  264. void mouseDown (const MouseEvent&)
  265. {
  266. if (undoManager != nullptr)
  267. undoManager->beginNewTransaction();
  268. CallOutBox::launchAsynchronously (*this, new PopupColourSelector (colourValue,
  269. defaultColour,
  270. canResetToDefault), nullptr);
  271. }
  272. void valueChanged (Value&)
  273. {
  274. refresh();
  275. }
  276. private:
  277. UndoManager* undoManager;
  278. Value colourValue;
  279. Colour lastColour;
  280. const Colour defaultColour;
  281. const bool canResetToDefault;
  282. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ColourEditorComponent);
  283. };
  284. //==============================================================================
  285. class ColourPropertyComponent : public PropertyComponent
  286. {
  287. public:
  288. ColourPropertyComponent (UndoManager* undoManager, const String& name, const Value& colour,
  289. const Colour& defaultColour, bool canResetToDefault)
  290. : PropertyComponent (name),
  291. colourEditor (undoManager, colour, defaultColour, canResetToDefault)
  292. {
  293. addAndMakeVisible (&colourEditor);
  294. }
  295. void resized()
  296. {
  297. colourEditor.setBounds (getLookAndFeel().getPropertyComponentContentPosition (*this));
  298. }
  299. void refresh() {}
  300. protected:
  301. ColourEditorComponent colourEditor;
  302. };