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.

241 lines
7.7KB

  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. Drawable::Drawable()
  19. {
  20. setInterceptsMouseClicks (false, false);
  21. setPaintingIsUnclipped (true);
  22. }
  23. Drawable::Drawable (const Drawable& other)
  24. {
  25. setName (other.getName());
  26. setComponentID (other.getComponentID());
  27. }
  28. Drawable::~Drawable()
  29. {
  30. }
  31. //==============================================================================
  32. void Drawable::draw (Graphics& g, float opacity, const AffineTransform& transform) const
  33. {
  34. const_cast <Drawable*> (this)->nonConstDraw (g, opacity, transform);
  35. }
  36. void Drawable::nonConstDraw (Graphics& g, float opacity, const AffineTransform& transform)
  37. {
  38. Graphics::ScopedSaveState ss (g);
  39. g.addTransform (AffineTransform::translation ((float) -(originRelativeToComponent.x),
  40. (float) -(originRelativeToComponent.y))
  41. .followedBy (getTransform())
  42. .followedBy (transform));
  43. if (! g.isClipEmpty())
  44. {
  45. if (opacity < 1.0f)
  46. {
  47. g.beginTransparencyLayer (opacity);
  48. paintEntireComponent (g, true);
  49. g.endTransparencyLayer();
  50. }
  51. else
  52. {
  53. paintEntireComponent (g, true);
  54. }
  55. }
  56. }
  57. void Drawable::drawAt (Graphics& g, float x, float y, float opacity) const
  58. {
  59. draw (g, opacity, AffineTransform::translation (x, y));
  60. }
  61. void Drawable::drawWithin (Graphics& g, const Rectangle<float>& destArea, const RectanglePlacement& placement, float opacity) const
  62. {
  63. draw (g, opacity, placement.getTransformToFit (getDrawableBounds(), destArea));
  64. }
  65. //==============================================================================
  66. DrawableComposite* Drawable::getParent() const
  67. {
  68. return dynamic_cast <DrawableComposite*> (getParentComponent());
  69. }
  70. void Drawable::transformContextToCorrectOrigin (Graphics& g)
  71. {
  72. g.setOrigin (originRelativeToComponent.x,
  73. originRelativeToComponent.y);
  74. }
  75. void Drawable::parentHierarchyChanged()
  76. {
  77. setBoundsToEnclose (getDrawableBounds());
  78. }
  79. void Drawable::setBoundsToEnclose (const Rectangle<float>& area)
  80. {
  81. Drawable* const parent = getParent();
  82. Point<int> parentOrigin;
  83. if (parent != nullptr)
  84. parentOrigin = parent->originRelativeToComponent;
  85. const Rectangle<int> newBounds (area.getSmallestIntegerContainer() + parentOrigin);
  86. originRelativeToComponent = parentOrigin - newBounds.getPosition();
  87. setBounds (newBounds);
  88. }
  89. //==============================================================================
  90. void Drawable::setOriginWithOriginalSize (const Point<float>& originWithinParent)
  91. {
  92. setTransform (AffineTransform::translation (originWithinParent.x, originWithinParent.y));
  93. }
  94. void Drawable::setTransformToFit (const Rectangle<float>& area, const RectanglePlacement& placement)
  95. {
  96. if (! area.isEmpty())
  97. setTransform (placement.getTransformToFit (getDrawableBounds(), area));
  98. }
  99. //==============================================================================
  100. Drawable* Drawable::createFromImageData (const void* data, const size_t numBytes)
  101. {
  102. Drawable* result = nullptr;
  103. Image image (ImageFileFormat::loadFrom (data, numBytes));
  104. if (image.isValid())
  105. {
  106. DrawableImage* const di = new DrawableImage();
  107. di->setImage (image);
  108. result = di;
  109. }
  110. else
  111. {
  112. const String asString (String::createStringFromData (data, (int) numBytes));
  113. XmlDocument doc (asString);
  114. ScopedPointer <XmlElement> outer (doc.getDocumentElement (true));
  115. if (outer != nullptr && outer->hasTagName ("svg"))
  116. {
  117. ScopedPointer <XmlElement> svg (doc.getDocumentElement());
  118. if (svg != nullptr)
  119. result = Drawable::createFromSVG (*svg);
  120. }
  121. }
  122. return result;
  123. }
  124. Drawable* Drawable::createFromImageDataStream (InputStream& dataSource)
  125. {
  126. MemoryOutputStream mo;
  127. mo << dataSource;
  128. return createFromImageData (mo.getData(), mo.getDataSize());
  129. }
  130. Drawable* Drawable::createFromImageFile (const File& file)
  131. {
  132. FileInputStream fin (file);
  133. return fin.openedOk() ? createFromImageDataStream (fin) : nullptr;
  134. }
  135. //==============================================================================
  136. template <class DrawableClass>
  137. class DrawableTypeHandler : public ComponentBuilder::TypeHandler
  138. {
  139. public:
  140. DrawableTypeHandler()
  141. : ComponentBuilder::TypeHandler (DrawableClass::valueTreeType)
  142. {
  143. }
  144. Component* addNewComponentFromState (const ValueTree& state, Component* parent)
  145. {
  146. DrawableClass* const d = new DrawableClass();
  147. if (parent != nullptr)
  148. parent->addAndMakeVisible (d);
  149. updateComponentFromState (d, state);
  150. return d;
  151. }
  152. void updateComponentFromState (Component* component, const ValueTree& state)
  153. {
  154. DrawableClass* const d = dynamic_cast <DrawableClass*> (component);
  155. jassert (d != nullptr);
  156. d->refreshFromValueTree (state, *this->getBuilder());
  157. }
  158. };
  159. void Drawable::registerDrawableTypeHandlers (ComponentBuilder& builder)
  160. {
  161. builder.registerTypeHandler (new DrawableTypeHandler <DrawablePath>());
  162. builder.registerTypeHandler (new DrawableTypeHandler <DrawableComposite>());
  163. builder.registerTypeHandler (new DrawableTypeHandler <DrawableRectangle>());
  164. builder.registerTypeHandler (new DrawableTypeHandler <DrawableImage>());
  165. builder.registerTypeHandler (new DrawableTypeHandler <DrawableText>());
  166. }
  167. Drawable* Drawable::createFromValueTree (const ValueTree& tree, ComponentBuilder::ImageProvider* imageProvider)
  168. {
  169. ComponentBuilder builder (tree);
  170. builder.setImageProvider (imageProvider);
  171. registerDrawableTypeHandlers (builder);
  172. ScopedPointer<Component> comp (builder.createComponent());
  173. Drawable* const d = dynamic_cast<Drawable*> (static_cast <Component*> (comp));
  174. if (d != nullptr)
  175. comp.release();
  176. return d;
  177. }
  178. //==============================================================================
  179. Drawable::ValueTreeWrapperBase::ValueTreeWrapperBase (const ValueTree& state_)
  180. : state (state_)
  181. {
  182. }
  183. String Drawable::ValueTreeWrapperBase::getID() const
  184. {
  185. return state [ComponentBuilder::idProperty];
  186. }
  187. void Drawable::ValueTreeWrapperBase::setID (const String& newID)
  188. {
  189. if (newID.isEmpty())
  190. state.removeProperty (ComponentBuilder::idProperty, nullptr);
  191. else
  192. state.setProperty (ComponentBuilder::idProperty, newID, nullptr);
  193. }