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.

174 lines
5.4KB

  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. #include "jucer_ColouredElement.h"
  20. //==============================================================================
  21. class PaintElementEllipse : public ColouredElement
  22. {
  23. public:
  24. PaintElementEllipse (PaintRoutine* pr)
  25. : ColouredElement (pr, "Ellipse", true, false)
  26. {
  27. }
  28. void draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea) override
  29. {
  30. fillType.setFillType (g, getDocument(), parentArea);
  31. Rectangle<int> r (position.getRectangle (parentArea, layout));
  32. g.fillEllipse ((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight());
  33. if (isStrokePresent)
  34. {
  35. strokeType.fill.setFillType (g, getDocument(), parentArea);
  36. g.drawEllipse ((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight(),
  37. getStrokeType().stroke.getStrokeThickness());
  38. }
  39. }
  40. void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected) override
  41. {
  42. ColouredElement::getEditableProperties (props, multipleSelected);
  43. props.add (new ShapeToPathProperty (this));
  44. }
  45. void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override
  46. {
  47. if (fillType.isInvisible() && (strokeType.isInvisible() || ! isStrokePresent))
  48. return;
  49. String x, y, w, h, s;
  50. positionToCode (position, code.document->getComponentLayout(), x, y, w, h);
  51. s << "{\n"
  52. << " float x = " << castToFloat (x) << ", y = " << castToFloat (y) << ", "
  53. << "width = " << castToFloat (w) << ", height = " << castToFloat (h) << ";\n";
  54. if (! fillType.isInvisible())
  55. s << " " << fillType.generateVariablesCode ("fill");
  56. if (isStrokePresent && ! strokeType.isInvisible())
  57. s << " " << strokeType.fill.generateVariablesCode ("stroke");
  58. s << " //[UserPaintCustomArguments] Customize the painting arguments here..\n"
  59. << customPaintCode
  60. << " //[/UserPaintCustomArguments]\n";
  61. if (! fillType.isInvisible())
  62. {
  63. s << " ";
  64. fillType.fillInGeneratedCode ("fill", position, code, s);
  65. s << " g.fillEllipse (x, y, width, height);\n";
  66. }
  67. if (isStrokePresent && ! strokeType.isInvisible())
  68. {
  69. s << " ";
  70. strokeType.fill.fillInGeneratedCode ("stroke", position, code, s);
  71. s << " g.drawEllipse (x, y, width, height, " << CodeHelpers::floatLiteral (strokeType.stroke.getStrokeThickness(), 3) << ");\n";
  72. }
  73. s << "}\n\n";
  74. paintMethodCode += s;
  75. }
  76. void applyCustomPaintSnippets (StringArray& snippets) override
  77. {
  78. customPaintCode.clear();
  79. if (! snippets.isEmpty() && (! fillType.isInvisible() || (isStrokePresent && ! strokeType.isInvisible())))
  80. {
  81. customPaintCode = snippets[0];
  82. snippets.remove (0);
  83. }
  84. }
  85. static const char* getTagName() noexcept { return "ELLIPSE"; }
  86. XmlElement* createXml() const override
  87. {
  88. XmlElement* e = new XmlElement (getTagName());
  89. position.applyToXml (*e);
  90. addColourAttributes (e);
  91. return e;
  92. }
  93. bool loadFromXml (const XmlElement& xml) override
  94. {
  95. if (xml.hasTagName (getTagName()))
  96. {
  97. position.restoreFromXml (xml, position);
  98. loadColourAttributes (xml);
  99. return true;
  100. }
  101. jassertfalse;
  102. return false;
  103. }
  104. void convertToPath()
  105. {
  106. double x, y, w, h;
  107. getCurrentAbsoluteBoundsDouble (x, y, w, h);
  108. Path path;
  109. path.addEllipse ((float) x, (float) y, (float) w, (float) h);
  110. convertToNewPathElement (path);
  111. }
  112. private:
  113. String customPaintCode;
  114. //==============================================================================
  115. struct ShapeToPathProperty : public ButtonPropertyComponent
  116. {
  117. ShapeToPathProperty (PaintElementEllipse* const e)
  118. : ButtonPropertyComponent ("path", false),
  119. element (e)
  120. {
  121. }
  122. void buttonClicked()
  123. {
  124. element->convertToPath();
  125. }
  126. String getButtonText() const
  127. {
  128. return "convert to a path";
  129. }
  130. PaintElementEllipse* element;
  131. };
  132. };