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.

225 lines
7.3KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. #pragma once
  19. //==============================================================================
  20. struct ColourPropertyComponent final : public PropertyComponent
  21. {
  22. ColourPropertyComponent (UndoManager* undoManager, const String& name, const Value& colour,
  23. Colour defaultColour, bool canResetToDefault)
  24. : PropertyComponent (name),
  25. colourEditor (undoManager, colour, defaultColour, canResetToDefault)
  26. {
  27. addAndMakeVisible (colourEditor);
  28. }
  29. void resized() override
  30. {
  31. colourEditor.setBounds (getLookAndFeel().getPropertyComponentContentPosition (*this));
  32. }
  33. void refresh() override {}
  34. private:
  35. /**
  36. A component that shows a colour swatch with hex ARGB value, and which pops up
  37. a colour selector when you click it.
  38. */
  39. struct ColourEditorComponent final : public Component,
  40. private Value::Listener
  41. {
  42. ColourEditorComponent (UndoManager* um, const Value& colour,
  43. Colour defaultCol, const bool canReset)
  44. : undoManager (um), colourValue (colour), defaultColour (defaultCol),
  45. canResetToDefault (canReset)
  46. {
  47. colourValue.addListener (this);
  48. }
  49. void paint (Graphics& g) override
  50. {
  51. const Colour colour (getColour());
  52. g.fillAll (Colours::grey);
  53. g.fillCheckerBoard (getLocalBounds().reduced (2).toFloat(),
  54. 10.0f, 10.0f,
  55. Colour (0xffdddddd).overlaidWith (colour),
  56. Colour (0xffffffff).overlaidWith (colour));
  57. g.setColour (Colours::white.overlaidWith (colour).contrasting());
  58. g.setFont (Font ((float) getHeight() * 0.6f, Font::bold));
  59. g.drawFittedText (colour.toDisplayString (true), getLocalBounds().reduced (2, 1),
  60. Justification::centred, 1);
  61. }
  62. Colour getColour() const
  63. {
  64. if (colourValue.toString().isEmpty())
  65. return defaultColour;
  66. return Colour::fromString (colourValue.toString());
  67. }
  68. void setColour (Colour newColour)
  69. {
  70. if (getColour() != newColour)
  71. {
  72. if (newColour == defaultColour && canResetToDefault)
  73. colourValue = var();
  74. else
  75. colourValue = newColour.toDisplayString (true);
  76. }
  77. }
  78. void resetToDefault()
  79. {
  80. setColour (defaultColour);
  81. }
  82. void refresh()
  83. {
  84. const Colour col (getColour());
  85. if (col != lastColour)
  86. {
  87. lastColour = col;
  88. repaint();
  89. }
  90. }
  91. void mouseDown (const MouseEvent&) override
  92. {
  93. if (undoManager != nullptr)
  94. undoManager->beginNewTransaction();
  95. CallOutBox::launchAsynchronously (std::make_unique<PopupColourSelector> (colourValue,
  96. defaultColour,
  97. canResetToDefault),
  98. getScreenBounds(),
  99. nullptr);
  100. }
  101. private:
  102. void valueChanged (Value&) override
  103. {
  104. refresh();
  105. }
  106. UndoManager* undoManager;
  107. Value colourValue;
  108. Colour lastColour;
  109. const Colour defaultColour;
  110. const bool canResetToDefault;
  111. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ColourEditorComponent)
  112. };
  113. //==============================================================================
  114. struct PopupColourSelector final : public Component,
  115. private ChangeListener,
  116. private Value::Listener
  117. {
  118. PopupColourSelector (const Value& colour,
  119. Colour defaultCol,
  120. const bool canResetToDefault)
  121. : defaultButton ("Reset to Default"),
  122. colourValue (colour),
  123. defaultColour (defaultCol)
  124. {
  125. addAndMakeVisible (selector);
  126. selector.setName ("Colour");
  127. selector.setCurrentColour (getColour());
  128. selector.addChangeListener (this);
  129. if (canResetToDefault)
  130. {
  131. addAndMakeVisible (defaultButton);
  132. defaultButton.onClick = [this]
  133. {
  134. setColour (defaultColour);
  135. selector.setCurrentColour (defaultColour);
  136. };
  137. }
  138. colourValue.addListener (this);
  139. setSize (300, 400);
  140. }
  141. void resized() override
  142. {
  143. if (defaultButton.isVisible())
  144. {
  145. selector.setBounds (0, 0, getWidth(), getHeight() - 30);
  146. defaultButton.changeWidthToFitText (22);
  147. defaultButton.setTopLeftPosition (10, getHeight() - 26);
  148. }
  149. else
  150. {
  151. selector.setBounds (getLocalBounds());
  152. }
  153. }
  154. Colour getColour() const
  155. {
  156. if (colourValue.toString().isEmpty())
  157. return defaultColour;
  158. return Colour::fromString (colourValue.toString());
  159. }
  160. void setColour (Colour newColour)
  161. {
  162. if (getColour() != newColour)
  163. {
  164. if (newColour == defaultColour && defaultButton.isVisible())
  165. colourValue = var();
  166. else
  167. colourValue = newColour.toDisplayString (true);
  168. }
  169. }
  170. private:
  171. void changeListenerCallback (ChangeBroadcaster*) override
  172. {
  173. if (selector.getCurrentColour() != getColour())
  174. setColour (selector.getCurrentColour());
  175. }
  176. void valueChanged (Value&) override
  177. {
  178. selector.setCurrentColour (getColour());
  179. }
  180. StoredSettings::ColourSelectorWithSwatches selector;
  181. TextButton defaultButton;
  182. Value colourValue;
  183. Colour defaultColour;
  184. };
  185. ColourEditorComponent colourEditor;
  186. };