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.

229 lines
7.4KB

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