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.

244 lines
7.8KB

  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. #include "../../Application/jucer_Headers.h"
  19. #include "jucer_EditingPanelBase.h"
  20. #include "jucer_JucerDocumentEditor.h"
  21. //==============================================================================
  22. class EditingPanelBase::MagnifierComponent : public Component
  23. {
  24. public:
  25. explicit MagnifierComponent (Component* c) : content (c)
  26. {
  27. addAndMakeVisible (content.get());
  28. childBoundsChanged (content.get());
  29. }
  30. void childBoundsChanged (Component* child)
  31. {
  32. auto childArea = getLocalArea (child, child->getLocalBounds());
  33. setSize (childArea.getWidth(), childArea.getHeight());
  34. }
  35. double getScaleFactor() const { return scaleFactor; }
  36. void setScaleFactor (double newScale)
  37. {
  38. scaleFactor = newScale;
  39. content->setTransform (AffineTransform::scale ((float) scaleFactor));
  40. }
  41. private:
  42. double scaleFactor = 1.0;
  43. std::unique_ptr<Component> content;
  44. };
  45. //==============================================================================
  46. class ZoomingViewport : public Viewport
  47. {
  48. public:
  49. explicit ZoomingViewport (EditingPanelBase* p) : panel (p)
  50. {
  51. }
  52. void mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& wheel)
  53. {
  54. if (e.mods.isCtrlDown() || e.mods.isAltDown() || e.mods.isCommandDown())
  55. mouseMagnify (e, 1.0f / (1.0f - wheel.deltaY));
  56. else
  57. Viewport::mouseWheelMove (e, wheel);
  58. }
  59. void mouseMagnify (const MouseEvent& e, float factor)
  60. {
  61. panel->setZoom (panel->getZoom() * factor, e.x, e.y);
  62. }
  63. void dragKeyHeldDown (const bool isKeyDown)
  64. {
  65. if (isSpaceDown != isKeyDown)
  66. {
  67. isSpaceDown = isKeyDown;
  68. if (isSpaceDown)
  69. {
  70. auto dc = new DraggerOverlayComp();
  71. addAndMakeVisible (dc);
  72. dc->setBounds (getLocalBounds());
  73. }
  74. else
  75. {
  76. for (int i = getNumChildComponents(); --i >= 0;)
  77. std::unique_ptr<DraggerOverlayComp> deleter (dynamic_cast<DraggerOverlayComp*> (getChildComponent (i)));
  78. }
  79. }
  80. }
  81. private:
  82. EditingPanelBase* const panel;
  83. bool isSpaceDown = false;
  84. //==============================================================================
  85. class DraggerOverlayComp : public Component
  86. {
  87. public:
  88. DraggerOverlayComp()
  89. {
  90. setMouseCursor (MouseCursor::DraggingHandCursor);
  91. setAlwaysOnTop (true);
  92. }
  93. void mouseDown (const MouseEvent&)
  94. {
  95. if (Viewport* viewport = findParentComponentOfClass<Viewport>())
  96. {
  97. startX = viewport->getViewPositionX();
  98. startY = viewport->getViewPositionY();
  99. }
  100. }
  101. void mouseDrag (const MouseEvent& e)
  102. {
  103. if (Viewport* viewport = findParentComponentOfClass<Viewport>())
  104. viewport->setViewPosition (jlimit (0, jmax (0, viewport->getViewedComponent()->getWidth() - viewport->getViewWidth()),
  105. startX - e.getDistanceFromDragStartX()),
  106. jlimit (0, jmax (0, viewport->getViewedComponent()->getHeight() - viewport->getViewHeight()),
  107. startY - e.getDistanceFromDragStartY()));
  108. }
  109. private:
  110. int startX, startY;
  111. };
  112. };
  113. //==============================================================================
  114. EditingPanelBase::EditingPanelBase (JucerDocument& doc, Component* props, Component* editorComp)
  115. : document (doc),
  116. editor (editorComp),
  117. propsPanel (props)
  118. {
  119. addAndMakeVisible (viewport = new ZoomingViewport (this));
  120. addAndMakeVisible (propsPanel);
  121. viewport->setViewedComponent (magnifier = new MagnifierComponent (editor));
  122. }
  123. EditingPanelBase::~EditingPanelBase()
  124. {
  125. deleteAllChildren();
  126. }
  127. void EditingPanelBase::resized()
  128. {
  129. const int contentW = jmax (1, getWidth() - 260);
  130. propsPanel->setBounds (contentW + 4, 4, jmax (100, getWidth() - contentW - 8), getHeight() - 8);
  131. viewport->setBounds (4, 4, contentW - 8, getHeight() - 8);
  132. if (document.isFixedSize())
  133. editor->setSize (jmax (document.getInitialWidth(),
  134. roundToInt ((viewport->getWidth() - viewport->getScrollBarThickness()) / getZoom())),
  135. jmax (document.getInitialHeight(),
  136. roundToInt ((viewport->getHeight() - viewport->getScrollBarThickness()) / getZoom())));
  137. else
  138. editor->setSize (viewport->getWidth(),
  139. viewport->getHeight());
  140. }
  141. void EditingPanelBase::paint (Graphics& g)
  142. {
  143. g.fillAll (findColour (secondaryBackgroundColourId));
  144. }
  145. void EditingPanelBase::visibilityChanged()
  146. {
  147. if (isVisible())
  148. {
  149. updatePropertiesList();
  150. if (Component* p = getParentComponent())
  151. {
  152. resized();
  153. if (JucerDocumentEditor* const cdh = dynamic_cast<JucerDocumentEditor*> (p->getParentComponent()))
  154. cdh->setViewportToLastPos (viewport, *this);
  155. resized();
  156. }
  157. }
  158. else
  159. {
  160. if (Component* p = getParentComponent())
  161. if (JucerDocumentEditor* const cdh = dynamic_cast<JucerDocumentEditor*> (p->getParentComponent()))
  162. cdh->storeLastViewportPos (viewport, *this);
  163. }
  164. editor->setVisible (isVisible());
  165. }
  166. double EditingPanelBase::getZoom() const
  167. {
  168. return magnifier->getScaleFactor();
  169. }
  170. void EditingPanelBase::setZoom (double newScale)
  171. {
  172. setZoom (jlimit (1.0 / 8.0, 16.0, newScale),
  173. viewport->getWidth() / 2,
  174. viewport->getHeight() / 2);
  175. }
  176. void EditingPanelBase::setZoom (double newScale, int anchorX, int anchorY)
  177. {
  178. Point<int> anchor (editor->getLocalPoint (viewport, Point<int> (anchorX, anchorY)));
  179. magnifier->setScaleFactor (newScale);
  180. resized();
  181. jassert (viewport != nullptr);
  182. anchor = viewport->getLocalPoint (editor, anchor);
  183. viewport->setViewPosition (jlimit (0, jmax (0, viewport->getViewedComponent()->getWidth() - viewport->getViewWidth()),
  184. viewport->getViewPositionX() + anchor.getX() - anchorX),
  185. jlimit (0, jmax (0, viewport->getViewedComponent()->getHeight() - viewport->getViewHeight()),
  186. viewport->getViewPositionY() + anchor.getY() - anchorY));
  187. }
  188. void EditingPanelBase::xyToTargetXY (int& x, int& y) const
  189. {
  190. Point<int> pos (editor->getLocalPoint (this, Point<int> (x, y)));
  191. x = pos.getX();
  192. y = pos.getY();
  193. }
  194. void EditingPanelBase::dragKeyHeldDown (bool isKeyDown)
  195. {
  196. ((ZoomingViewport*) viewport)->dragKeyHeldDown (isKeyDown);
  197. }