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.

710 lines
27KB

  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. static const Slider::SliderStyle sliderStyleTypes[] =
  21. {
  22. Slider::LinearHorizontal,
  23. Slider::LinearVertical,
  24. Slider::LinearBar,
  25. Slider::LinearBarVertical,
  26. Slider::Rotary,
  27. Slider::RotaryHorizontalDrag,
  28. Slider::RotaryVerticalDrag,
  29. Slider::RotaryHorizontalVerticalDrag,
  30. Slider::IncDecButtons,
  31. Slider::TwoValueHorizontal,
  32. Slider::TwoValueVertical,
  33. Slider::ThreeValueHorizontal,
  34. Slider::ThreeValueVertical
  35. };
  36. static const Slider::TextEntryBoxPosition sliderTextBoxPositions[] =
  37. {
  38. Slider::NoTextBox,
  39. Slider::TextBoxLeft,
  40. Slider::TextBoxRight,
  41. Slider::TextBoxAbove,
  42. Slider::TextBoxBelow
  43. };
  44. struct SliderHandler : public ComponentTypeHandler
  45. {
  46. SliderHandler()
  47. : ComponentTypeHandler ("Slider", "juce::Slider", typeid (Slider), 150, 24)
  48. {
  49. registerColour (juce::Slider::backgroundColourId, "background", "bkgcol");
  50. registerColour (juce::Slider::thumbColourId, "thumb", "thumbcol");
  51. registerColour (juce::Slider::trackColourId, "track", "trackcol");
  52. registerColour (juce::Slider::rotarySliderFillColourId, "rotary fill", "rotarysliderfill");
  53. registerColour (juce::Slider::rotarySliderOutlineColourId, "rotary outln", "rotaryslideroutline");
  54. registerColour (juce::Slider::textBoxTextColourId, "textbox text", "textboxtext");
  55. registerColour (juce::Slider::textBoxBackgroundColourId, "textbox bkgd", "textboxbkgd");
  56. registerColour (juce::Slider::textBoxHighlightColourId, "textbox highlt", "textboxhighlight");
  57. registerColour (juce::Slider::textBoxOutlineColourId, "textbox outln", "textboxoutline");
  58. }
  59. Component* createNewComponent (JucerDocument*) override
  60. {
  61. return new Slider ("new slider");
  62. }
  63. XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
  64. {
  65. XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout);
  66. Slider* s = dynamic_cast<Slider*> (comp);
  67. e->setAttribute ("min", s->getMinimum());
  68. e->setAttribute ("max", s->getMaximum());
  69. e->setAttribute ("int", s->getInterval());
  70. e->setAttribute ("style", sliderStyleToString (s->getSliderStyle()));
  71. e->setAttribute ("textBoxPos", textBoxPosToString (s->getTextBoxPosition()));
  72. e->setAttribute ("textBoxEditable", s->isTextBoxEditable());
  73. e->setAttribute ("textBoxWidth", s->getTextBoxWidth());
  74. e->setAttribute ("textBoxHeight", s->getTextBoxHeight());
  75. e->setAttribute ("skewFactor", s->getSkewFactor());
  76. e->setAttribute ("needsCallback", needsSliderListener (s));
  77. return e;
  78. }
  79. bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout) override
  80. {
  81. if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
  82. return false;
  83. Slider* const s = dynamic_cast<Slider*> (comp);
  84. s->setRange (xml.getDoubleAttribute ("min", 0.0),
  85. xml.getDoubleAttribute ("max", 10.0),
  86. xml.getDoubleAttribute ("int", 0.0));
  87. s->setSliderStyle (sliderStringToStyle (xml.getStringAttribute ("style", "LinearHorizontal")));
  88. s->setTextBoxStyle (stringToTextBoxPos (xml.getStringAttribute ("textBoxPos", "TextBoxLeft")),
  89. ! xml.getBoolAttribute ("textBoxEditable", true),
  90. xml.getIntAttribute ("textBoxWidth", 80),
  91. xml.getIntAttribute ("textBoxHeight", 20));
  92. s->setSkewFactor (xml.getDoubleAttribute ("skewFactor", 1.0));
  93. setNeedsSliderListener (s, xml.getBoolAttribute ("needsCallback", true));
  94. return true;
  95. }
  96. String getCreationParameters (GeneratedCode&, Component* component) override
  97. {
  98. return quotedString (component->getName(), false);
  99. }
  100. void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
  101. {
  102. ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
  103. Slider* const s = dynamic_cast<Slider*> (component);
  104. String r;
  105. r << memberVariableName << "->setRange ("
  106. << s->getMinimum() << ", " << s->getMaximum() << ", " << s->getInterval()
  107. << ");\n"
  108. << memberVariableName << "->setSliderStyle (juce::Slider::"
  109. << sliderStyleToString (s->getSliderStyle()) << ");\n"
  110. << memberVariableName << "->setTextBoxStyle (juce::Slider::"
  111. << textBoxPosToString (s->getTextBoxPosition())
  112. << ", " << CodeHelpers::boolLiteral (! s->isTextBoxEditable())
  113. << ", " << s->getTextBoxWidth() << ", " << s->getTextBoxHeight() << ");\n"
  114. << getColourIntialisationCode (component, memberVariableName);
  115. if (needsSliderListener (component))
  116. r << memberVariableName << "->addListener (this);\n";
  117. if (! approximatelyEqual (s->getSkewFactor(), 1.0))
  118. r << memberVariableName << "->setSkewFactor (" << s->getSkewFactor() << ");\n";
  119. r << '\n';
  120. code.constructorCode += r;
  121. }
  122. void fillInGeneratedCode (Component* component, GeneratedCode& code) override
  123. {
  124. ComponentTypeHandler::fillInGeneratedCode (component, code);
  125. if (needsSliderListener (component))
  126. {
  127. String& callback = code.getCallbackCode ("public juce::Slider::Listener",
  128. "void",
  129. "sliderValueChanged (juce::Slider* sliderThatWasMoved)",
  130. true);
  131. if (callback.isNotEmpty())
  132. callback << "else ";
  133. const String memberVariableName (code.document->getComponentLayout()->getComponentMemberVariableName (component));
  134. const String userCodeComment ("UserSliderCode_" + memberVariableName);
  135. callback
  136. << "if (sliderThatWasMoved == " << memberVariableName << ".get())\n"
  137. << "{\n //[" << userCodeComment << "] -- add your slider handling code here..\n //[/" << userCodeComment << "]\n}\n";
  138. }
  139. }
  140. void getEditableProperties (Component* component, JucerDocument& document,
  141. Array<PropertyComponent*>& props, bool multipleSelected) override
  142. {
  143. ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
  144. if (multipleSelected)
  145. return;
  146. if (auto* s = dynamic_cast<Slider*> (component))
  147. {
  148. props.add (new SliderRangeProperty (s, document, "minimum", 0));
  149. props.add (new SliderRangeProperty (s, document, "maximum", 1));
  150. props.add (new SliderRangeProperty (s, document, "interval", 2));
  151. props.add (new SliderTypeProperty (s, document));
  152. props.add (new SliderTextboxProperty (s, document));
  153. props.add (new SliderTextboxEditableProperty (s, document));
  154. props.add (new SliderTextboxSizeProperty (s, document, true));
  155. props.add (new SliderTextboxSizeProperty (s, document, false));
  156. props.add (new SliderSkewProperty (s, document));
  157. props.add (new SliderCallbackProperty (s, document));
  158. }
  159. addColourProperties (component, document, props);
  160. }
  161. static bool needsSliderListener (Component* slider)
  162. {
  163. return slider->getProperties().getWithDefault ("generateListenerCallback", true);
  164. }
  165. static void setNeedsSliderListener (Component* slider, bool shouldDoCallback)
  166. {
  167. slider->getProperties().set ("generateListenerCallback", shouldDoCallback);
  168. }
  169. private:
  170. //==============================================================================
  171. struct SliderTypeProperty : public ComponentChoiceProperty<Slider>
  172. {
  173. SliderTypeProperty (Slider* slider, JucerDocument& doc)
  174. : ComponentChoiceProperty<Slider> ("type", slider, doc)
  175. {
  176. choices.add ("Linear Horizontal");
  177. choices.add ("Linear Vertical");
  178. choices.add ("Linear Bar Horizontal");
  179. choices.add ("Linear Bar Vertical");
  180. choices.add ("Rotary");
  181. choices.add ("Rotary HorizontalDrag");
  182. choices.add ("Rotary VerticalDrag");
  183. choices.add ("Rotary HorizontalVerticalDrag");
  184. choices.add ("Inc/Dec Buttons");
  185. choices.add ("Two Value Horizontal");
  186. choices.add ("Two Value Vertical");
  187. choices.add ("Three Value Horizontal");
  188. choices.add ("Three Value Vertical");
  189. }
  190. void setIndex (int newIndex) override
  191. {
  192. if (newIndex >= 0 && newIndex < numElementsInArray (sliderStyleTypes))
  193. document.perform (new SliderTypeChangeAction (component, *document.getComponentLayout(),
  194. sliderStyleTypes[newIndex]),
  195. "Change Slider style");
  196. }
  197. int getIndex() const override
  198. {
  199. for (int i = 0; i < numElementsInArray (sliderStyleTypes); ++i)
  200. if (sliderStyleTypes[i] == dynamic_cast<Slider*> (component)->getSliderStyle())
  201. return i;
  202. return -1;
  203. }
  204. private:
  205. struct SliderTypeChangeAction : public ComponentUndoableAction<Slider>
  206. {
  207. SliderTypeChangeAction (Slider* comp, ComponentLayout& l, Slider::SliderStyle newState_)
  208. : ComponentUndoableAction<Slider> (comp, l),
  209. newState (newState_)
  210. {
  211. oldState = comp->getSliderStyle();
  212. }
  213. bool perform() override
  214. {
  215. showCorrectTab();
  216. getComponent()->setSliderStyle (newState);
  217. changed();
  218. return true;
  219. }
  220. bool undo() override
  221. {
  222. showCorrectTab();
  223. getComponent()->setSliderStyle (oldState);
  224. changed();
  225. return true;
  226. }
  227. Slider::SliderStyle newState, oldState;
  228. };
  229. };
  230. //==============================================================================
  231. struct SliderTextboxProperty : public ComponentChoiceProperty<Slider>
  232. {
  233. SliderTextboxProperty (Slider* slider, JucerDocument& doc)
  234. : ComponentChoiceProperty<Slider> ("text position", slider, doc)
  235. {
  236. choices.add ("No text box");
  237. choices.add ("Text box on left");
  238. choices.add ("Text box on right");
  239. choices.add ("Text box above");
  240. choices.add ("Text box below");
  241. }
  242. void setIndex (int newIndex) override
  243. {
  244. if (newIndex >= 0 && newIndex < numElementsInArray (sliderTextBoxPositions))
  245. document.perform (new SliderTextBoxChangeAction (component, *document.getComponentLayout(),
  246. sliderTextBoxPositions[newIndex]),
  247. "Change Slider textbox");
  248. }
  249. int getIndex() const override
  250. {
  251. for (int i = 0; i < numElementsInArray (sliderTextBoxPositions); ++i)
  252. if (sliderTextBoxPositions[i] == component->getTextBoxPosition())
  253. return i;
  254. return -1;
  255. }
  256. private:
  257. struct SliderTextBoxChangeAction : public ComponentUndoableAction<Slider>
  258. {
  259. SliderTextBoxChangeAction (Slider* comp, ComponentLayout& l, Slider::TextEntryBoxPosition newState_)
  260. : ComponentUndoableAction<Slider> (comp, l),
  261. newState (newState_)
  262. {
  263. oldState = comp->getTextBoxPosition();
  264. }
  265. bool perform() override
  266. {
  267. showCorrectTab();
  268. getComponent()->setTextBoxStyle (newState,
  269. ! getComponent()->isTextBoxEditable(),
  270. getComponent()->getTextBoxWidth(),
  271. getComponent()->getTextBoxHeight());
  272. changed();
  273. return true;
  274. }
  275. bool undo() override
  276. {
  277. showCorrectTab();
  278. getComponent()->setTextBoxStyle (oldState,
  279. ! getComponent()->isTextBoxEditable(),
  280. getComponent()->getTextBoxWidth(),
  281. getComponent()->getTextBoxHeight());
  282. changed();
  283. return true;
  284. }
  285. Slider::TextEntryBoxPosition newState, oldState;
  286. };
  287. };
  288. //==============================================================================
  289. struct SliderTextboxEditableProperty : public ComponentBooleanProperty<Slider>
  290. {
  291. SliderTextboxEditableProperty (Slider* slider, JucerDocument& doc)
  292. : ComponentBooleanProperty<Slider> ("text box mode", "Editable", "Editable", slider, doc)
  293. {
  294. }
  295. void setState (bool newState) override
  296. {
  297. document.perform (new SliderEditableChangeAction (component, *document.getComponentLayout(), newState),
  298. "Change Slider editability");
  299. }
  300. bool getState() const override
  301. {
  302. return component->isTextBoxEditable();
  303. }
  304. private:
  305. struct SliderEditableChangeAction : public ComponentUndoableAction<Slider>
  306. {
  307. SliderEditableChangeAction (Slider* const comp, ComponentLayout& l, bool newState_)
  308. : ComponentUndoableAction<Slider> (comp, l),
  309. newState (newState_)
  310. {
  311. oldState = comp->isTextBoxEditable();
  312. }
  313. bool perform() override
  314. {
  315. showCorrectTab();
  316. getComponent()->setTextBoxIsEditable (newState);
  317. changed();
  318. return true;
  319. }
  320. bool undo() override
  321. {
  322. showCorrectTab();
  323. getComponent()->setTextBoxIsEditable (oldState);
  324. changed();
  325. return true;
  326. }
  327. bool newState, oldState;
  328. };
  329. };
  330. //==============================================================================
  331. struct SliderCallbackProperty : public ComponentBooleanProperty<Slider>
  332. {
  333. SliderCallbackProperty (Slider* s, JucerDocument& doc)
  334. : ComponentBooleanProperty<Slider> ("callback", "Generate SliderListener",
  335. "Generate SliderListener", s, doc)
  336. {
  337. }
  338. void setState (bool newState) override
  339. {
  340. document.perform (new SliderCallbackChangeAction (component, *document.getComponentLayout(), newState),
  341. "Change button callback");
  342. }
  343. bool getState() const override { return needsSliderListener (component); }
  344. struct SliderCallbackChangeAction : public ComponentUndoableAction<Slider>
  345. {
  346. SliderCallbackChangeAction (Slider* comp, ComponentLayout& l, bool newState_)
  347. : ComponentUndoableAction<Slider> (comp, l),
  348. newState (newState_)
  349. {
  350. oldState = needsSliderListener (comp);
  351. }
  352. bool perform() override
  353. {
  354. showCorrectTab();
  355. setNeedsSliderListener (getComponent(), newState);
  356. changed();
  357. return true;
  358. }
  359. bool undo() override
  360. {
  361. showCorrectTab();
  362. setNeedsSliderListener (getComponent(), oldState);
  363. changed();
  364. return true;
  365. }
  366. bool newState, oldState;
  367. };
  368. };
  369. //==============================================================================
  370. struct SliderTextboxSizeProperty : public ComponentTextProperty<Slider>
  371. {
  372. SliderTextboxSizeProperty (Slider* slider, JucerDocument& doc, bool isWidth_)
  373. : ComponentTextProperty<Slider> (isWidth_ ? "text box width" : "text box height",
  374. 12, false, slider, doc),
  375. isWidth (isWidth_)
  376. {
  377. }
  378. void setText (const String& newText) override
  379. {
  380. document.perform (new SliderBoxSizeChangeAction (component, *document.getComponentLayout(), isWidth, newText.getIntValue()),
  381. "Change Slider textbox size");
  382. }
  383. String getText() const override
  384. {
  385. return String (isWidth ? component->getTextBoxWidth()
  386. : component->getTextBoxHeight());
  387. }
  388. private:
  389. const bool isWidth;
  390. struct SliderBoxSizeChangeAction : public ComponentUndoableAction<Slider>
  391. {
  392. SliderBoxSizeChangeAction (Slider* const comp, ComponentLayout& l, bool isWidth_, int newSize_)
  393. : ComponentUndoableAction<Slider> (comp, l),
  394. isWidth (isWidth_),
  395. newSize (newSize_)
  396. {
  397. oldSize = isWidth ? comp->getTextBoxWidth()
  398. : comp->getTextBoxHeight();
  399. }
  400. bool perform() override
  401. {
  402. showCorrectTab();
  403. Slider& c = *getComponent();
  404. if (isWidth)
  405. c.setTextBoxStyle (c.getTextBoxPosition(),
  406. ! c.isTextBoxEditable(),
  407. newSize,
  408. c.getTextBoxHeight());
  409. else
  410. c.setTextBoxStyle (c.getTextBoxPosition(),
  411. ! c.isTextBoxEditable(),
  412. c.getTextBoxWidth(),
  413. newSize);
  414. changed();
  415. return true;
  416. }
  417. bool undo() override
  418. {
  419. showCorrectTab();
  420. Slider& c = *getComponent();
  421. if (isWidth)
  422. c.setTextBoxStyle (c.getTextBoxPosition(),
  423. ! c.isTextBoxEditable(),
  424. oldSize,
  425. c.getTextBoxHeight());
  426. else
  427. c.setTextBoxStyle (c.getTextBoxPosition(),
  428. ! c.isTextBoxEditable(),
  429. c.getTextBoxWidth(),
  430. oldSize);
  431. changed();
  432. return true;
  433. }
  434. bool isWidth;
  435. int newSize, oldSize;
  436. };
  437. };
  438. //==============================================================================
  439. struct SliderRangeProperty : public ComponentTextProperty<Slider>
  440. {
  441. SliderRangeProperty (Slider* slider, JucerDocument& doc,
  442. const String& name, int rangeParam_)
  443. : ComponentTextProperty<Slider> (name, 15, false, slider, doc),
  444. rangeParam (rangeParam_)
  445. {
  446. }
  447. void setText (const String& newText) override
  448. {
  449. double state [3];
  450. state [0] = component->getMinimum();
  451. state [1] = component->getMaximum();
  452. state [2] = component->getInterval();
  453. state [rangeParam] = newText.getDoubleValue();
  454. document.perform (new SliderRangeChangeAction (component, *document.getComponentLayout(), state),
  455. "Change Slider range");
  456. }
  457. String getText() const override
  458. {
  459. if (auto* s = dynamic_cast<Slider*> (component))
  460. {
  461. switch (rangeParam)
  462. {
  463. case 0: return String (s->getMinimum());
  464. case 1: return String (s->getMaximum());
  465. case 2: return String (s->getInterval());
  466. default: jassertfalse; break;
  467. }
  468. }
  469. return {};
  470. }
  471. private:
  472. const int rangeParam;
  473. struct SliderRangeChangeAction : public ComponentUndoableAction<Slider>
  474. {
  475. SliderRangeChangeAction (Slider* comp, ComponentLayout& l, const double newState_[3])
  476. : ComponentUndoableAction<Slider> (comp, l)
  477. {
  478. newState[0] = newState_ [0];
  479. newState[1] = newState_ [1];
  480. newState[2] = newState_ [2];
  481. oldState[0] = comp->getMinimum();
  482. oldState[1] = comp->getMaximum();
  483. oldState[2] = comp->getInterval();
  484. }
  485. bool perform() override
  486. {
  487. showCorrectTab();
  488. getComponent()->setRange (newState[0], newState[1], newState[2]);
  489. changed();
  490. return true;
  491. }
  492. bool undo() override
  493. {
  494. showCorrectTab();
  495. getComponent()->setRange (oldState[0], oldState[1], oldState[2]);
  496. changed();
  497. return true;
  498. }
  499. double newState[3], oldState[3];
  500. };
  501. };
  502. //==============================================================================
  503. struct SliderSkewProperty : public ComponentTextProperty<Slider>
  504. {
  505. SliderSkewProperty (Slider* slider, JucerDocument& doc)
  506. : ComponentTextProperty<Slider> ("skew factor", 12, false, slider, doc)
  507. {
  508. }
  509. void setText (const String& newText) override
  510. {
  511. const double skew = jlimit (0.001, 1000.0, newText.getDoubleValue());
  512. document.perform (new SliderSkewChangeAction (component, *document.getComponentLayout(), skew),
  513. "Change Slider skew");
  514. }
  515. String getText() const override
  516. {
  517. if (auto* s = dynamic_cast<Slider*> (component))
  518. return String (s->getSkewFactor());
  519. return {};
  520. }
  521. struct SliderSkewChangeAction : public ComponentUndoableAction<Slider>
  522. {
  523. SliderSkewChangeAction (Slider* comp, ComponentLayout& l, double newValue_)
  524. : ComponentUndoableAction<Slider> (comp, l)
  525. {
  526. newValue = newValue_;
  527. oldValue = comp->getSkewFactor();
  528. }
  529. bool perform() override
  530. {
  531. showCorrectTab();
  532. getComponent()->setSkewFactor (newValue);
  533. changed();
  534. return true;
  535. }
  536. bool undo() override
  537. {
  538. showCorrectTab();
  539. getComponent()->setSkewFactor (oldValue);
  540. changed();
  541. return true;
  542. }
  543. double newValue, oldValue;
  544. };
  545. };
  546. //==============================================================================
  547. static String sliderStyleToString (Slider::SliderStyle style)
  548. {
  549. switch (style)
  550. {
  551. case Slider::LinearHorizontal: return "LinearHorizontal";
  552. case Slider::LinearVertical: return "LinearVertical";
  553. case Slider::LinearBar: return "LinearBar";
  554. case Slider::LinearBarVertical: return "LinearBarVertical";
  555. case Slider::Rotary: return "Rotary";
  556. case Slider::RotaryHorizontalDrag: return "RotaryHorizontalDrag";
  557. case Slider::RotaryVerticalDrag: return "RotaryVerticalDrag";
  558. case Slider::RotaryHorizontalVerticalDrag: return "RotaryHorizontalVerticalDrag";
  559. case Slider::IncDecButtons: return "IncDecButtons";
  560. case Slider::TwoValueHorizontal: return "TwoValueHorizontal";
  561. case Slider::TwoValueVertical: return "TwoValueVertical";
  562. case Slider::ThreeValueHorizontal: return "ThreeValueHorizontal";
  563. case Slider::ThreeValueVertical: return "ThreeValueVertical";
  564. default: jassertfalse; break;
  565. }
  566. return {};
  567. }
  568. static Slider::SliderStyle sliderStringToStyle (const String& s)
  569. {
  570. for (int i = 0; i < numElementsInArray (sliderStyleTypes); ++i)
  571. if (s == sliderStyleToString (sliderStyleTypes[i]))
  572. return sliderStyleTypes[i];
  573. jassertfalse;
  574. return Slider::LinearHorizontal;
  575. }
  576. static String textBoxPosToString (const Slider::TextEntryBoxPosition pos)
  577. {
  578. switch (pos)
  579. {
  580. case Slider::NoTextBox: return "NoTextBox";
  581. case Slider::TextBoxLeft: return "TextBoxLeft";
  582. case Slider::TextBoxRight: return "TextBoxRight";
  583. case Slider::TextBoxAbove: return "TextBoxAbove";
  584. case Slider::TextBoxBelow: return "TextBoxBelow";
  585. default: jassertfalse; break;
  586. }
  587. return {};
  588. }
  589. static Slider::TextEntryBoxPosition stringToTextBoxPos (const String& s)
  590. {
  591. for (int i = 0; i < numElementsInArray (sliderTextBoxPositions); ++i)
  592. if (s == textBoxPosToString (sliderTextBoxPositions[i]))
  593. return sliderTextBoxPositions[i];
  594. jassertfalse;
  595. return Slider::TextBoxLeft;
  596. }
  597. };