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.

711 lines
27KB

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