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.

303 lines
12KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  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 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. #include "../JuceDemoHeader.h"
  20. // these classes are C++11-only
  21. #if JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS
  22. struct DemoFlexPanel : public juce::Component
  23. {
  24. DemoFlexPanel (juce::Colour col, FlexItem& item) : flexItem (item), colour (col)
  25. {
  26. int x = 70;
  27. int y = 3;
  28. setupTextEditor (flexOrderEditor, { x, y, 20, 18 }, "0", [this] { flexItem.order = (int) flexOrderEditor.getText().getFloatValue(); });
  29. addLabel ("order", flexOrderEditor);
  30. y += 20;
  31. setupTextEditor (flexGrowEditor, { x, y, 20, 18 }, "0", [this] { flexItem.flexGrow = flexGrowEditor.getText().getFloatValue(); });
  32. addLabel ("flex-grow", flexGrowEditor);
  33. y += 20;
  34. setupTextEditor (flexShrinkEditor, { x, y, 20, 18 }, "1", [this] { flexItem.flexShrink = flexShrinkEditor.getText().getFloatValue(); });
  35. addLabel ("flex-shrink", flexShrinkEditor);
  36. y += 20;
  37. setupTextEditor (flexBasisEditor, { x, y, 33, 18 }, "100", [this] { flexItem.flexBasis = flexBasisEditor.getText().getFloatValue(); });
  38. addLabel ("flex-basis", flexBasisEditor);
  39. y += 20;
  40. alignSelfCombo.addItem ("auto", 1);
  41. alignSelfCombo.addItem ("flex-start", 2);
  42. alignSelfCombo.addItem ("flex-end", 3);
  43. alignSelfCombo.addItem ("center", 4);
  44. alignSelfCombo.addItem ("stretch", 5);
  45. alignSelfCombo.setBounds (x, y, 90, 18);
  46. alignSelfCombo.onChange = [this] { updateAssignSelf(); };
  47. alignSelfCombo.setSelectedId (5);
  48. alignSelfCombo.setColour (ComboBox::outlineColourId, Colours::transparentBlack);
  49. addAndMakeVisible (alignSelfCombo);
  50. addLabel ("align-self", alignSelfCombo);
  51. }
  52. void setupTextEditor (TextEditor& te, Rectangle<int> b, StringRef initialText, std::function<void()> updateFn)
  53. {
  54. te.setBounds (b);
  55. te.setText (initialText);
  56. te.onTextChange = [this, updateFn]
  57. {
  58. updateFn();
  59. refreshLayout();
  60. };
  61. addAndMakeVisible (te);
  62. }
  63. void addLabel (const String& name, Component& target)
  64. {
  65. auto label = new Label (name, name);
  66. label->attachToComponent (&target, true);
  67. labels.add (label);
  68. addAndMakeVisible (label);
  69. }
  70. void updateAssignSelf()
  71. {
  72. switch (alignSelfCombo.getSelectedId())
  73. {
  74. case 1: flexItem.alignSelf = FlexItem::AlignSelf::autoAlign; break;
  75. case 2: flexItem.alignSelf = FlexItem::AlignSelf::flexStart; break;
  76. case 3: flexItem.alignSelf = FlexItem::AlignSelf::flexEnd; break;
  77. case 4: flexItem.alignSelf = FlexItem::AlignSelf::center; break;
  78. case 5: flexItem.alignSelf = FlexItem::AlignSelf::stretch; break;
  79. }
  80. refreshLayout();
  81. }
  82. void refreshLayout()
  83. {
  84. if (auto parent = getParentComponent())
  85. parent->resized();
  86. }
  87. void paint (Graphics& g) override
  88. {
  89. auto r = getLocalBounds();
  90. g.setColour (colour);
  91. g.fillRect (r);
  92. g.setColour (Colours::black);
  93. g.drawFittedText ("w: " + String (r.getWidth()) + newLine + "h: " + String (r.getHeight()),
  94. r.reduced (4), Justification::bottomRight, 2);
  95. }
  96. void lookAndFeelChanged() override
  97. {
  98. flexOrderEditor.applyFontToAllText (flexOrderEditor.getFont());
  99. flexGrowEditor.applyFontToAllText (flexGrowEditor.getFont());
  100. flexShrinkEditor.applyFontToAllText (flexShrinkEditor.getFont());
  101. flexBasisEditor.applyFontToAllText (flexBasisEditor.getFont());
  102. }
  103. FlexItem& flexItem;
  104. TextEditor flexOrderEditor, flexGrowEditor, flexShrinkEditor, flexBasisEditor;
  105. ComboBox alignSelfCombo;
  106. juce::Colour colour;
  107. OwnedArray<Label> labels;
  108. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DemoFlexPanel)
  109. };
  110. //==============================================================================
  111. struct FlexBoxDemo : public juce::Component
  112. {
  113. FlexBoxDemo()
  114. {
  115. setupPropertiesPanel();
  116. setupFlexBoxItems();
  117. }
  118. void resized() override
  119. {
  120. flexBox.performLayout (getFlexBoxBounds());
  121. }
  122. Rectangle<float> getFlexBoxBounds() const
  123. {
  124. return getLocalBounds().withTrimmedLeft (300)
  125. .reduced (10)
  126. .toFloat();
  127. }
  128. void paint (Graphics& g) override
  129. {
  130. g.fillAll (getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::windowBackground,
  131. Colours::lightgrey));
  132. g.setColour (Colours::white);
  133. g.fillRect (getFlexBoxBounds());
  134. }
  135. void setupPropertiesPanel()
  136. {
  137. auto directionGroup = addControl (new GroupComponent ("direction", "flex-direction"));
  138. directionGroup->setBounds (10, 30, 140, 110);
  139. int i = 0;
  140. int groupID = 1234;
  141. int leftMargin = 15;
  142. int topMargin = 45;
  143. createToggleButton ("row", groupID, leftMargin, topMargin + i++ * 22, true, [this] { flexBox.flexDirection = FlexBox::Direction::row; }).setToggleState (true, dontSendNotification);
  144. createToggleButton ("row-reverse", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.flexDirection = FlexBox::Direction::rowReverse; });
  145. createToggleButton ("column", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.flexDirection = FlexBox::Direction::column; });
  146. createToggleButton ("column-reverse", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.flexDirection = FlexBox::Direction::columnReverse; });
  147. auto wrapGroup = addControl (new GroupComponent ("wrap", "flex-wrap"));
  148. wrapGroup->setBounds (160, 30, 140, 110);
  149. i = 0;
  150. ++groupID;
  151. leftMargin = 165;
  152. createToggleButton ("nowrap", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.flexWrap = FlexBox::Wrap::noWrap; });
  153. createToggleButton ("wrap", groupID, leftMargin, topMargin + i++ * 22, true, [this] { flexBox.flexWrap = FlexBox::Wrap::wrap; });
  154. createToggleButton ("wrap-reverse", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.flexWrap = FlexBox::Wrap::wrapReverse; });
  155. auto justifyGroup = addControl (new GroupComponent ("justify", "justify-content"));
  156. justifyGroup->setBounds (10, 150, 140, 140);
  157. i = 0;
  158. ++groupID;
  159. leftMargin = 15;
  160. topMargin = 165;
  161. createToggleButton ("flex-start", groupID, leftMargin, topMargin + i++ * 22, true, [this] { flexBox.justifyContent = FlexBox::JustifyContent::flexStart; });
  162. createToggleButton ("flex-end", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.justifyContent = FlexBox::JustifyContent::flexEnd; });
  163. createToggleButton ("center", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.justifyContent = FlexBox::JustifyContent::center; });
  164. createToggleButton ("space-between", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.justifyContent = FlexBox::JustifyContent::spaceBetween; });
  165. createToggleButton ("space-around", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.justifyContent = FlexBox::JustifyContent::spaceAround; });
  166. auto alignGroup = addControl (new GroupComponent ("align", "align-items"));
  167. alignGroup->setBounds (160, 150, 140, 140);
  168. i = 0;
  169. ++groupID;
  170. leftMargin = 165;
  171. topMargin = 165;
  172. createToggleButton ("stretch", groupID, leftMargin, topMargin + i++ * 22, true, [this] { flexBox.alignItems = FlexBox::AlignItems::stretch; });
  173. createToggleButton ("flex-start", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.alignItems = FlexBox::AlignItems::flexStart; });
  174. createToggleButton ("flex-end", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.alignItems = FlexBox::AlignItems::flexEnd; });
  175. createToggleButton ("center", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.alignItems = FlexBox::AlignItems::center; });
  176. auto alignContentGroup = addControl (new GroupComponent ("content", "align-content"));
  177. alignContentGroup->setBounds (10, 300, 140, 160);
  178. i = 0;
  179. ++groupID;
  180. leftMargin = 15;
  181. topMargin = 315;
  182. createToggleButton ("stretch", groupID, leftMargin, topMargin + i++ * 22, true, [this] { flexBox.alignContent = FlexBox::AlignContent::stretch; });
  183. createToggleButton ("flex-start", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.alignContent = FlexBox::AlignContent::flexStart; });
  184. createToggleButton ("flex-end", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.alignContent = FlexBox::AlignContent::flexEnd; });
  185. createToggleButton ("center", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.alignContent = FlexBox::AlignContent::center; });
  186. createToggleButton ("space-between", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.alignContent = FlexBox::AlignContent::spaceBetween; });
  187. createToggleButton ("space-around", groupID, leftMargin, topMargin + i++ * 22, false, [this] { flexBox.alignContent = FlexBox::AlignContent::spaceAround; });
  188. }
  189. void setupFlexBoxItems()
  190. {
  191. addItem (Colours::orange);
  192. addItem (Colours::aqua);
  193. addItem (Colours::lightcoral);
  194. addItem (Colours::aquamarine);
  195. addItem (Colours::forestgreen);
  196. }
  197. void addItem (Colour colour)
  198. {
  199. flexBox.items.add (FlexItem (100, 150)
  200. .withMargin (10)
  201. .withWidth (200));
  202. auto& flexItem = flexBox.items.getReference (flexBox.items.size() - 1);
  203. auto panel = panels.add (new DemoFlexPanel (colour, flexItem));
  204. flexItem.associatedComponent = panel;
  205. addAndMakeVisible (panel);
  206. }
  207. ToggleButton& createToggleButton (StringRef text, int groupID, int x, int y, bool toggleOn, std::function<void()> fn)
  208. {
  209. auto* tb = buttons.add (new ToggleButton());
  210. tb->setButtonText (text);
  211. tb->setRadioGroupId (groupID);
  212. tb->setToggleState (toggleOn, dontSendNotification);
  213. tb->onClick = [this, fn]
  214. {
  215. fn();
  216. resized();
  217. };
  218. tb->setBounds (x, y, 130, 22);
  219. addAndMakeVisible (tb);
  220. return *tb;
  221. }
  222. template <typename ComponentType>
  223. ComponentType* addControl (ComponentType* newControlComp)
  224. {
  225. controls.add (newControlComp);
  226. addAndMakeVisible (newControlComp);
  227. return newControlComp;
  228. }
  229. FlexBox flexBox;
  230. OwnedArray<DemoFlexPanel> panels;
  231. OwnedArray<Component> controls;
  232. OwnedArray<ToggleButton> buttons;
  233. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlexBoxDemo)
  234. };
  235. // This static object will register this demo type in a global list of demos..
  236. static JuceDemoType<FlexBoxDemo> demo ("10 Components: FlexBox");
  237. #endif