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.

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