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.

271 lines
8.2KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../../../core/juce_StandardHeader.h"
  19. BEGIN_JUCE_NAMESPACE
  20. #include "juce_Toolbar.h"
  21. #include "juce_ToolbarItemPalette.h"
  22. #include "juce_ToolbarItemFactory.h"
  23. #include "../menus/juce_PopupMenu.h"
  24. #include "../lookandfeel/juce_LookAndFeel.h"
  25. #include "../layout/juce_StretchableObjectResizer.h"
  26. //==============================================================================
  27. ToolbarItemFactory::ToolbarItemFactory()
  28. {
  29. }
  30. ToolbarItemFactory::~ToolbarItemFactory()
  31. {
  32. }
  33. //==============================================================================
  34. class ItemDragAndDropOverlayComponent : public Component
  35. {
  36. public:
  37. ItemDragAndDropOverlayComponent()
  38. : isDragging (false)
  39. {
  40. setAlwaysOnTop (true);
  41. setRepaintsOnMouseActivity (true);
  42. setMouseCursor (MouseCursor::DraggingHandCursor);
  43. }
  44. ~ItemDragAndDropOverlayComponent()
  45. {
  46. }
  47. void paint (Graphics& g)
  48. {
  49. ToolbarItemComponent* const tc = dynamic_cast <ToolbarItemComponent*> (getParentComponent());
  50. if (isMouseOverOrDragging()
  51. && tc != 0
  52. && tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar)
  53. {
  54. g.setColour (findColour (Toolbar::editingModeOutlineColourId, true));
  55. g.drawRect (0, 0, getWidth(), getHeight(),
  56. jmin (2, (getWidth() - 1) / 2, (getHeight() - 1) / 2));
  57. }
  58. }
  59. void mouseDown (const MouseEvent& e)
  60. {
  61. isDragging = false;
  62. ToolbarItemComponent* const tc = dynamic_cast <ToolbarItemComponent*> (getParentComponent());
  63. if (tc != 0)
  64. {
  65. tc->dragOffsetX = e.x;
  66. tc->dragOffsetY = e.y;
  67. }
  68. }
  69. void mouseDrag (const MouseEvent& e)
  70. {
  71. if (! (isDragging || e.mouseWasClicked()))
  72. {
  73. isDragging = true;
  74. DragAndDropContainer* const dnd = DragAndDropContainer::findParentDragContainerFor (this);
  75. if (dnd != 0)
  76. {
  77. dnd->startDragging (Toolbar::toolbarDragDescriptor, getParentComponent(), 0, true);
  78. ToolbarItemComponent* const tc = dynamic_cast <ToolbarItemComponent*> (getParentComponent());
  79. if (tc != 0)
  80. {
  81. tc->isBeingDragged = true;
  82. if (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar)
  83. tc->setVisible (false);
  84. }
  85. }
  86. }
  87. }
  88. void mouseUp (const MouseEvent&)
  89. {
  90. isDragging = false;
  91. ToolbarItemComponent* const tc = dynamic_cast <ToolbarItemComponent*> (getParentComponent());
  92. if (tc != 0)
  93. {
  94. tc->isBeingDragged = false;
  95. Toolbar* const tb = tc->getToolbar();
  96. if (tb != 0)
  97. tb->updateAllItemPositions (true);
  98. else if (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar)
  99. delete tc;
  100. }
  101. }
  102. void parentSizeChanged()
  103. {
  104. setBounds (0, 0, getParentWidth(), getParentHeight());
  105. }
  106. //==============================================================================
  107. juce_UseDebuggingNewOperator
  108. private:
  109. bool isDragging;
  110. ItemDragAndDropOverlayComponent (const ItemDragAndDropOverlayComponent&);
  111. const ItemDragAndDropOverlayComponent& operator= (const ItemDragAndDropOverlayComponent&);
  112. };
  113. //==============================================================================
  114. ToolbarItemComponent::ToolbarItemComponent (const int itemId_,
  115. const String& labelText,
  116. const bool isBeingUsedAsAButton_)
  117. : Button (labelText),
  118. itemId (itemId_),
  119. mode (normalMode),
  120. toolbarStyle (Toolbar::iconsOnly),
  121. dragOffsetX (0),
  122. dragOffsetY (0),
  123. isActive (true),
  124. isBeingDragged (false),
  125. isBeingUsedAsAButton (isBeingUsedAsAButton_)
  126. {
  127. // Your item ID can't be 0!
  128. jassert (itemId_ != 0);
  129. }
  130. ToolbarItemComponent::~ToolbarItemComponent()
  131. {
  132. jassert (overlayComp == 0 || overlayComp->isValidComponent());
  133. overlayComp = 0;
  134. }
  135. Toolbar* ToolbarItemComponent::getToolbar() const
  136. {
  137. return dynamic_cast <Toolbar*> (getParentComponent());
  138. }
  139. bool ToolbarItemComponent::isToolbarVertical() const
  140. {
  141. const Toolbar* const t = getToolbar();
  142. return t != 0 && t->isVertical();
  143. }
  144. void ToolbarItemComponent::setStyle (const Toolbar::ToolbarItemStyle& newStyle)
  145. {
  146. if (toolbarStyle != newStyle)
  147. {
  148. toolbarStyle = newStyle;
  149. repaint();
  150. resized();
  151. }
  152. }
  153. void ToolbarItemComponent::paintButton (Graphics& g, bool isMouseOver, bool isMouseDown)
  154. {
  155. if (isBeingUsedAsAButton)
  156. getLookAndFeel().paintToolbarButtonBackground (g, getWidth(), getHeight(),
  157. isMouseOver, isMouseDown, *this);
  158. if (toolbarStyle != Toolbar::iconsOnly)
  159. {
  160. const int indent = contentArea.getX();
  161. int y = indent;
  162. int h = getHeight() - indent * 2;
  163. if (toolbarStyle == Toolbar::iconsWithText)
  164. {
  165. y = contentArea.getBottom() + indent / 2;
  166. h -= contentArea.getHeight();
  167. }
  168. getLookAndFeel().paintToolbarButtonLabel (g, indent, y, getWidth() - indent * 2, h,
  169. getButtonText(), *this);
  170. }
  171. if (! contentArea.isEmpty())
  172. {
  173. g.saveState();
  174. g.setOrigin (contentArea.getX(), contentArea.getY());
  175. g.reduceClipRegion (0, 0, contentArea.getWidth(), contentArea.getHeight());
  176. paintButtonArea (g, contentArea.getWidth(), contentArea.getHeight(), isMouseOver, isMouseDown);
  177. g.restoreState();
  178. }
  179. }
  180. void ToolbarItemComponent::resized()
  181. {
  182. if (toolbarStyle != Toolbar::textOnly)
  183. {
  184. const int indent = jmin (proportionOfWidth (0.08f),
  185. proportionOfHeight (0.08f));
  186. contentArea = Rectangle (indent, indent,
  187. getWidth() - indent * 2,
  188. toolbarStyle == Toolbar::iconsWithText ? proportionOfHeight (0.55f)
  189. : (getHeight() - indent * 2));
  190. }
  191. else
  192. {
  193. contentArea = Rectangle();
  194. }
  195. contentAreaChanged (contentArea);
  196. }
  197. void ToolbarItemComponent::setEditingMode (const ToolbarEditingMode newMode)
  198. {
  199. if (mode != newMode)
  200. {
  201. mode = newMode;
  202. repaint();
  203. if (mode == normalMode)
  204. {
  205. jassert (overlayComp == 0 || overlayComp->isValidComponent());
  206. overlayComp = 0;
  207. }
  208. else if (overlayComp == 0)
  209. {
  210. addAndMakeVisible (overlayComp = new ItemDragAndDropOverlayComponent());
  211. overlayComp->parentSizeChanged();
  212. }
  213. resized();
  214. }
  215. }
  216. END_JUCE_NAMESPACE