juce_Drawable.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. Drawable::Drawable()
  18. {
  19. setInterceptsMouseClicks (false, false);
  20. setPaintingIsUnclipped (true);
  21. }
  22. Drawable::Drawable (const Drawable& other)
  23. : Component (other.getName())
  24. {
  25. setComponentID (other.getComponentID());
  26. setTransform (other.getTransform());
  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,
  62. RectanglePlacement placement, float opacity) const
  63. {
  64. draw (g, opacity, placement.getTransformToFit (getDrawableBounds(), destArea));
  65. }
  66. //==============================================================================
  67. DrawableComposite* Drawable::getParent() const
  68. {
  69. return dynamic_cast<DrawableComposite*> (getParentComponent());
  70. }
  71. void Drawable::transformContextToCorrectOrigin (Graphics& g)
  72. {
  73. g.setOrigin (originRelativeToComponent);
  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. bool Drawable::replaceColour (Colour original, Colour replacement)
  91. {
  92. bool changed = false;
  93. for (int i = getNumChildComponents(); --i >= 0;)
  94. if (Drawable* d = dynamic_cast<Drawable*> (getChildComponent(i)))
  95. changed = d->replaceColour (original, replacement) || changed;
  96. return changed;
  97. }
  98. //==============================================================================
  99. void Drawable::setOriginWithOriginalSize (Point<float> originWithinParent)
  100. {
  101. setTransform (AffineTransform::translation (originWithinParent.x, originWithinParent.y));
  102. }
  103. void Drawable::setTransformToFit (const Rectangle<float>& area, RectanglePlacement placement)
  104. {
  105. if (! area.isEmpty())
  106. setTransform (placement.getTransformToFit (getDrawableBounds(), area));
  107. }
  108. //==============================================================================
  109. Drawable* Drawable::createFromImageData (const void* data, const size_t numBytes)
  110. {
  111. Drawable* result = nullptr;
  112. Image image (ImageFileFormat::loadFrom (data, numBytes));
  113. if (image.isValid())
  114. {
  115. DrawableImage* const di = new DrawableImage();
  116. di->setImage (image);
  117. result = di;
  118. }
  119. else
  120. {
  121. const String asString (String::createStringFromData (data, (int) numBytes));
  122. XmlDocument doc (asString);
  123. ScopedPointer<XmlElement> outer (doc.getDocumentElement (true));
  124. if (outer != nullptr && outer->hasTagName ("svg"))
  125. {
  126. ScopedPointer<XmlElement> svg (doc.getDocumentElement());
  127. if (svg != nullptr)
  128. result = Drawable::createFromSVG (*svg);
  129. }
  130. }
  131. return result;
  132. }
  133. Drawable* Drawable::createFromImageDataStream (InputStream& dataSource)
  134. {
  135. MemoryOutputStream mo;
  136. mo << dataSource;
  137. return createFromImageData (mo.getData(), mo.getDataSize());
  138. }
  139. Drawable* Drawable::createFromImageFile (const File& file)
  140. {
  141. FileInputStream fin (file);
  142. return fin.openedOk() ? createFromImageDataStream (fin) : nullptr;
  143. }
  144. //==============================================================================
  145. template <class DrawableClass>
  146. class DrawableTypeHandler : public ComponentBuilder::TypeHandler
  147. {
  148. public:
  149. DrawableTypeHandler()
  150. : ComponentBuilder::TypeHandler (DrawableClass::valueTreeType)
  151. {
  152. }
  153. Component* addNewComponentFromState (const ValueTree& state, Component* parent)
  154. {
  155. DrawableClass* const d = new DrawableClass();
  156. if (parent != nullptr)
  157. parent->addAndMakeVisible (d);
  158. updateComponentFromState (d, state);
  159. return d;
  160. }
  161. void updateComponentFromState (Component* component, const ValueTree& state)
  162. {
  163. DrawableClass* const d = dynamic_cast<DrawableClass*> (component);
  164. jassert (d != nullptr);
  165. d->refreshFromValueTree (state, *this->getBuilder());
  166. }
  167. };
  168. void Drawable::registerDrawableTypeHandlers (ComponentBuilder& builder)
  169. {
  170. builder.registerTypeHandler (new DrawableTypeHandler <DrawablePath>());
  171. builder.registerTypeHandler (new DrawableTypeHandler <DrawableComposite>());
  172. builder.registerTypeHandler (new DrawableTypeHandler <DrawableRectangle>());
  173. builder.registerTypeHandler (new DrawableTypeHandler <DrawableImage>());
  174. builder.registerTypeHandler (new DrawableTypeHandler <DrawableText>());
  175. }
  176. Drawable* Drawable::createFromValueTree (const ValueTree& tree, ComponentBuilder::ImageProvider* imageProvider)
  177. {
  178. ComponentBuilder builder (tree);
  179. builder.setImageProvider (imageProvider);
  180. registerDrawableTypeHandlers (builder);
  181. ScopedPointer<Component> comp (builder.createComponent());
  182. Drawable* const d = dynamic_cast<Drawable*> (static_cast<Component*> (comp));
  183. if (d != nullptr)
  184. comp.release();
  185. return d;
  186. }
  187. //==============================================================================
  188. Drawable::ValueTreeWrapperBase::ValueTreeWrapperBase (const ValueTree& state_)
  189. : state (state_)
  190. {
  191. }
  192. String Drawable::ValueTreeWrapperBase::getID() const
  193. {
  194. return state [ComponentBuilder::idProperty];
  195. }
  196. void Drawable::ValueTreeWrapperBase::setID (const String& newID)
  197. {
  198. if (newID.isEmpty())
  199. state.removeProperty (ComponentBuilder::idProperty, nullptr);
  200. else
  201. state.setProperty (ComponentBuilder::idProperty, newID, nullptr);
  202. }