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.

291 lines
9.6KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 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. DrawableImage::DrawableImage()
  19. : opacity (1.0f),
  20. overlayColour (0x00000000)
  21. {
  22. bounds.topRight = RelativePoint (Point<float> (1.0f, 0.0f));
  23. bounds.bottomLeft = RelativePoint (Point<float> (0.0f, 1.0f));
  24. }
  25. DrawableImage::DrawableImage (const DrawableImage& other)
  26. : Drawable (other),
  27. image (other.image),
  28. opacity (other.opacity),
  29. overlayColour (other.overlayColour),
  30. bounds (other.bounds)
  31. {
  32. }
  33. DrawableImage::~DrawableImage()
  34. {
  35. }
  36. //==============================================================================
  37. void DrawableImage::setImage (const Image& imageToUse)
  38. {
  39. image = imageToUse;
  40. setBounds (imageToUse.getBounds());
  41. bounds.topLeft = RelativePoint (Point<float> (0.0f, 0.0f));
  42. bounds.topRight = RelativePoint (Point<float> ((float) image.getWidth(), 0.0f));
  43. bounds.bottomLeft = RelativePoint (Point<float> (0.0f, (float) image.getHeight()));
  44. recalculateCoordinates (nullptr);
  45. repaint();
  46. }
  47. void DrawableImage::setOpacity (const float newOpacity)
  48. {
  49. opacity = newOpacity;
  50. }
  51. void DrawableImage::setOverlayColour (const Colour& newOverlayColour)
  52. {
  53. overlayColour = newOverlayColour;
  54. }
  55. void DrawableImage::setBoundingBox (const RelativeParallelogram& newBounds)
  56. {
  57. if (bounds != newBounds)
  58. {
  59. bounds = newBounds;
  60. if (bounds.isDynamic())
  61. {
  62. Drawable::Positioner<DrawableImage>* const p = new Drawable::Positioner<DrawableImage> (*this);
  63. setPositioner (p);
  64. p->apply();
  65. }
  66. else
  67. {
  68. setPositioner (nullptr);
  69. recalculateCoordinates (nullptr);
  70. }
  71. }
  72. }
  73. //==============================================================================
  74. bool DrawableImage::registerCoordinates (RelativeCoordinatePositionerBase& pos)
  75. {
  76. bool ok = pos.addPoint (bounds.topLeft);
  77. ok = pos.addPoint (bounds.topRight) && ok;
  78. return pos.addPoint (bounds.bottomLeft) && ok;
  79. }
  80. void DrawableImage::recalculateCoordinates (Expression::Scope* scope)
  81. {
  82. if (image.isValid())
  83. {
  84. Point<float> resolved[3];
  85. bounds.resolveThreePoints (resolved, scope);
  86. const Point<float> tr (resolved[0] + (resolved[1] - resolved[0]) / (float) image.getWidth());
  87. const Point<float> bl (resolved[0] + (resolved[2] - resolved[0]) / (float) image.getHeight());
  88. AffineTransform t (AffineTransform::fromTargetPoints (resolved[0].x, resolved[0].y,
  89. tr.x, tr.y,
  90. bl.x, bl.y));
  91. if (t.isSingularity())
  92. t = AffineTransform::identity;
  93. setTransform (t);
  94. }
  95. }
  96. //==============================================================================
  97. void DrawableImage::paint (Graphics& g)
  98. {
  99. if (image.isValid())
  100. {
  101. if (opacity > 0.0f && ! overlayColour.isOpaque())
  102. {
  103. g.setOpacity (opacity);
  104. g.drawImageAt (image, 0, 0, false);
  105. }
  106. if (! overlayColour.isTransparent())
  107. {
  108. g.setColour (overlayColour.withMultipliedAlpha (opacity));
  109. g.drawImageAt (image, 0, 0, true);
  110. }
  111. }
  112. }
  113. Rectangle<float> DrawableImage::getDrawableBounds() const
  114. {
  115. return image.getBounds().toFloat();
  116. }
  117. bool DrawableImage::hitTest (int x, int y)
  118. {
  119. return Drawable::hitTest (x, y) && image.isValid() && image.getPixelAt (x, y).getAlpha() >= 127;
  120. }
  121. Drawable* DrawableImage::createCopy() const
  122. {
  123. return new DrawableImage (*this);
  124. }
  125. //==============================================================================
  126. const Identifier DrawableImage::valueTreeType ("Image");
  127. const Identifier DrawableImage::ValueTreeWrapper::opacity ("opacity");
  128. const Identifier DrawableImage::ValueTreeWrapper::overlay ("overlay");
  129. const Identifier DrawableImage::ValueTreeWrapper::image ("image");
  130. const Identifier DrawableImage::ValueTreeWrapper::topLeft ("topLeft");
  131. const Identifier DrawableImage::ValueTreeWrapper::topRight ("topRight");
  132. const Identifier DrawableImage::ValueTreeWrapper::bottomLeft ("bottomLeft");
  133. //==============================================================================
  134. DrawableImage::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_)
  135. : ValueTreeWrapperBase (state_)
  136. {
  137. jassert (state.hasType (valueTreeType));
  138. }
  139. var DrawableImage::ValueTreeWrapper::getImageIdentifier() const
  140. {
  141. return state [image];
  142. }
  143. Value DrawableImage::ValueTreeWrapper::getImageIdentifierValue (UndoManager* undoManager)
  144. {
  145. return state.getPropertyAsValue (image, undoManager);
  146. }
  147. void DrawableImage::ValueTreeWrapper::setImageIdentifier (const var& newIdentifier, UndoManager* undoManager)
  148. {
  149. state.setProperty (image, newIdentifier, undoManager);
  150. }
  151. float DrawableImage::ValueTreeWrapper::getOpacity() const
  152. {
  153. return (float) state.getProperty (opacity, 1.0);
  154. }
  155. Value DrawableImage::ValueTreeWrapper::getOpacityValue (UndoManager* undoManager)
  156. {
  157. if (! state.hasProperty (opacity))
  158. state.setProperty (opacity, 1.0, undoManager);
  159. return state.getPropertyAsValue (opacity, undoManager);
  160. }
  161. void DrawableImage::ValueTreeWrapper::setOpacity (float newOpacity, UndoManager* undoManager)
  162. {
  163. state.setProperty (opacity, newOpacity, undoManager);
  164. }
  165. Colour DrawableImage::ValueTreeWrapper::getOverlayColour() const
  166. {
  167. return Colour::fromString (state [overlay].toString());
  168. }
  169. void DrawableImage::ValueTreeWrapper::setOverlayColour (const Colour& newColour, UndoManager* undoManager)
  170. {
  171. if (newColour.isTransparent())
  172. state.removeProperty (overlay, undoManager);
  173. else
  174. state.setProperty (overlay, String::toHexString ((int) newColour.getARGB()), undoManager);
  175. }
  176. Value DrawableImage::ValueTreeWrapper::getOverlayColourValue (UndoManager* undoManager)
  177. {
  178. return state.getPropertyAsValue (overlay, undoManager);
  179. }
  180. RelativeParallelogram DrawableImage::ValueTreeWrapper::getBoundingBox() const
  181. {
  182. return RelativeParallelogram (state.getProperty (topLeft, "0, 0"),
  183. state.getProperty (topRight, "100, 0"),
  184. state.getProperty (bottomLeft, "0, 100"));
  185. }
  186. void DrawableImage::ValueTreeWrapper::setBoundingBox (const RelativeParallelogram& newBounds, UndoManager* undoManager)
  187. {
  188. state.setProperty (topLeft, newBounds.topLeft.toString(), undoManager);
  189. state.setProperty (topRight, newBounds.topRight.toString(), undoManager);
  190. state.setProperty (bottomLeft, newBounds.bottomLeft.toString(), undoManager);
  191. }
  192. //==============================================================================
  193. void DrawableImage::refreshFromValueTree (const ValueTree& tree, ComponentBuilder& builder)
  194. {
  195. const ValueTreeWrapper controller (tree);
  196. setComponentID (controller.getID());
  197. const float newOpacity = controller.getOpacity();
  198. const Colour newOverlayColour (controller.getOverlayColour());
  199. Image newImage;
  200. const var imageIdentifier (controller.getImageIdentifier());
  201. jassert (builder.getImageProvider() != 0 || imageIdentifier.isVoid()); // if you're using images, you need to provide something that can load and save them!
  202. if (builder.getImageProvider() != nullptr)
  203. newImage = builder.getImageProvider()->getImageForIdentifier (imageIdentifier);
  204. const RelativeParallelogram newBounds (controller.getBoundingBox());
  205. if (bounds != newBounds || newOpacity != opacity
  206. || overlayColour != newOverlayColour || image != newImage)
  207. {
  208. repaint();
  209. opacity = newOpacity;
  210. overlayColour = newOverlayColour;
  211. if (image != newImage)
  212. setImage (newImage);
  213. setBoundingBox (newBounds);
  214. }
  215. }
  216. ValueTree DrawableImage::createValueTree (ComponentBuilder::ImageProvider* imageProvider) const
  217. {
  218. ValueTree tree (valueTreeType);
  219. ValueTreeWrapper v (tree);
  220. v.setID (getComponentID());
  221. v.setOpacity (opacity, nullptr);
  222. v.setOverlayColour (overlayColour, nullptr);
  223. v.setBoundingBox (bounds, nullptr);
  224. if (image.isValid())
  225. {
  226. jassert (imageProvider != nullptr); // if you're using images, you need to provide something that can load and save them!
  227. if (imageProvider != nullptr)
  228. v.setImageIdentifier (imageProvider->getIdentifierForImage (image), nullptr);
  229. }
  230. return tree;
  231. }