| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2013 - Raw Material Software Ltd.
 - 
 -    Permission is granted to use this software under the terms of either:
 -    a) the GPL v2 (or any later version)
 -    b) the Affero GPL v3
 - 
 -    Details of these licenses can be found at: www.gnu.org/licenses
 - 
 -    JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
 -    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 -    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 - 
 -    ------------------------------------------------------------------------------
 - 
 -    To release a closed-source product which uses JUCE, commercial licenses are
 -    available: visit www.juce.com for more information.
 - 
 -   ==============================================================================
 - */
 - 
 - DrawableShape::DrawableShape()
 -     : strokeType (0.0f),
 -       mainFill (Colours::black),
 -       strokeFill (Colours::black)
 - {
 - }
 - 
 - DrawableShape::DrawableShape (const DrawableShape& other)
 -     : Drawable (other),
 -       strokeType (other.strokeType),
 -       mainFill (other.mainFill),
 -       strokeFill (other.strokeFill)
 - {
 - }
 - 
 - DrawableShape::~DrawableShape()
 - {
 - }
 - 
 - //==============================================================================
 - class DrawableShape::RelativePositioner  : public RelativeCoordinatePositionerBase
 - {
 - public:
 -     RelativePositioner (DrawableShape& comp, const DrawableShape::RelativeFillType& f, bool isMain)
 -         : RelativeCoordinatePositionerBase (comp),
 -           owner (comp),
 -           fill (f),
 -           isMainFill (isMain)
 -     {
 -     }
 - 
 -     bool registerCoordinates()
 -     {
 -         bool ok = addPoint (fill.gradientPoint1);
 -         ok = addPoint (fill.gradientPoint2) && ok;
 -         return addPoint (fill.gradientPoint3) && ok;
 -     }
 - 
 -     void applyToComponentBounds()
 -     {
 -         ComponentScope scope (owner);
 -         if (isMainFill ? owner.mainFill.recalculateCoords (&scope)
 -                        : owner.strokeFill.recalculateCoords (&scope))
 -             owner.repaint();
 -     }
 - 
 -     void applyNewBounds (const Rectangle<int>&)
 -     {
 -         jassertfalse; // drawables can't be resized directly!
 -     }
 - 
 - private:
 -     DrawableShape& owner;
 -     const DrawableShape::RelativeFillType fill;
 -     const bool isMainFill;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativePositioner)
 - };
 - 
 - void DrawableShape::setFill (const FillType& newFill)
 - {
 -     setFill (RelativeFillType (newFill));
 - }
 - 
 - void DrawableShape::setStrokeFill (const FillType& newFill)
 - {
 -     setStrokeFill (RelativeFillType (newFill));
 - }
 - 
 - void DrawableShape::setFillInternal (RelativeFillType& fill, const RelativeFillType& newFill,
 -                                      ScopedPointer<RelativeCoordinatePositionerBase>& pos)
 - {
 -     if (fill != newFill)
 -     {
 -         fill = newFill;
 -         pos = nullptr;
 - 
 -         if (fill.isDynamic())
 -         {
 -             pos = new RelativePositioner (*this, fill, true);
 -             pos->apply();
 -         }
 -         else
 -         {
 -             fill.recalculateCoords (nullptr);
 -         }
 - 
 -         repaint();
 -     }
 - }
 - 
 - void DrawableShape::setFill (const RelativeFillType& newFill)
 - {
 -     setFillInternal (mainFill, newFill, mainFillPositioner);
 - }
 - 
 - void DrawableShape::setStrokeFill (const RelativeFillType& newFill)
 - {
 -     setFillInternal (strokeFill, newFill, strokeFillPositioner);
 - }
 - 
 - void DrawableShape::setStrokeType (const PathStrokeType& newStrokeType)
 - {
 -     if (strokeType != newStrokeType)
 -     {
 -         strokeType = newStrokeType;
 -         strokeChanged();
 -     }
 - }
 - 
 - void DrawableShape::setStrokeThickness (const float newThickness)
 - {
 -     setStrokeType (PathStrokeType (newThickness, strokeType.getJointStyle(), strokeType.getEndStyle()));
 - }
 - 
 - bool DrawableShape::isStrokeVisible() const noexcept
 - {
 -     return strokeType.getStrokeThickness() > 0.0f && ! strokeFill.fill.isInvisible();
 - }
 - 
 - void DrawableShape::refreshFillTypes (const FillAndStrokeState& newState, ComponentBuilder::ImageProvider* imageProvider)
 - {
 -     setFill (newState.getFill (FillAndStrokeState::fill, imageProvider));
 -     setStrokeFill (newState.getFill (FillAndStrokeState::stroke, imageProvider));
 - }
 - 
 - void DrawableShape::writeTo (FillAndStrokeState& state, ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager) const
 - {
 -     state.setFill (FillAndStrokeState::fill, mainFill, imageProvider, undoManager);
 -     state.setFill (FillAndStrokeState::stroke, strokeFill, imageProvider, undoManager);
 -     state.setStrokeType (strokeType, undoManager);
 - }
 - 
 - //==============================================================================
 - void DrawableShape::paint (Graphics& g)
 - {
 -     transformContextToCorrectOrigin (g);
 - 
 -     g.setFillType (mainFill.fill);
 -     g.fillPath (path);
 - 
 -     if (isStrokeVisible())
 -     {
 -         g.setFillType (strokeFill.fill);
 -         g.fillPath (strokePath);
 -     }
 - }
 - 
 - void DrawableShape::pathChanged()
 - {
 -     strokeChanged();
 - }
 - 
 - void DrawableShape::strokeChanged()
 - {
 -     strokePath.clear();
 -     strokeType.createStrokedPath (strokePath, path, AffineTransform::identity, 4.0f);
 - 
 -     setBoundsToEnclose (getDrawableBounds());
 -     repaint();
 - }
 - 
 - Rectangle<float> DrawableShape::getDrawableBounds() const
 - {
 -     if (isStrokeVisible())
 -         return strokePath.getBounds();
 - 
 -     return path.getBounds();
 - }
 - 
 - bool DrawableShape::hitTest (int x, int y)
 - {
 -     bool allowsClicksOnThisComponent, allowsClicksOnChildComponents;
 -     getInterceptsMouseClicks (allowsClicksOnThisComponent, allowsClicksOnChildComponents);
 - 
 -     if (! allowsClicksOnThisComponent)
 -         return false;
 - 
 -     const float globalX = (float) (x - originRelativeToComponent.x);
 -     const float globalY = (float) (y - originRelativeToComponent.y);
 - 
 -     return path.contains (globalX, globalY)
 -             || (isStrokeVisible() && strokePath.contains (globalX, globalY));
 - }
 - 
 - //==============================================================================
 - DrawableShape::RelativeFillType::RelativeFillType()
 - {
 - }
 - 
 - DrawableShape::RelativeFillType::RelativeFillType (const FillType& fill_)
 -     : fill (fill_)
 - {
 -     if (fill.isGradient())
 -     {
 -         const ColourGradient& g = *fill.gradient;
 - 
 -         gradientPoint1 = g.point1.transformedBy (fill.transform);
 -         gradientPoint2 = g.point2.transformedBy (fill.transform);
 -         gradientPoint3 = Point<float> (g.point1.x + g.point2.y - g.point1.y,
 -                                        g.point1.y + g.point1.x - g.point2.x)
 -                             .transformedBy (fill.transform);
 -         fill.transform = AffineTransform::identity;
 -     }
 - }
 - 
 - DrawableShape::RelativeFillType::RelativeFillType (const RelativeFillType& other)
 -     : fill (other.fill),
 -       gradientPoint1 (other.gradientPoint1),
 -       gradientPoint2 (other.gradientPoint2),
 -       gradientPoint3 (other.gradientPoint3)
 - {
 - }
 - 
 - DrawableShape::RelativeFillType& DrawableShape::RelativeFillType::operator= (const RelativeFillType& other)
 - {
 -     fill = other.fill;
 -     gradientPoint1 = other.gradientPoint1;
 -     gradientPoint2 = other.gradientPoint2;
 -     gradientPoint3 = other.gradientPoint3;
 -     return *this;
 - }
 - 
 - bool DrawableShape::RelativeFillType::operator== (const RelativeFillType& other) const
 - {
 -     return fill == other.fill
 -         && ((! fill.isGradient())
 -              || (gradientPoint1 == other.gradientPoint1
 -                  && gradientPoint2 == other.gradientPoint2
 -                  && gradientPoint3 == other.gradientPoint3));
 - }
 - 
 - bool DrawableShape::RelativeFillType::operator!= (const RelativeFillType& other) const
 - {
 -     return ! operator== (other);
 - }
 - 
 - bool DrawableShape::RelativeFillType::recalculateCoords (Expression::Scope* scope)
 - {
 -     if (fill.isGradient())
 -     {
 -         const Point<float> g1 (gradientPoint1.resolve (scope));
 -         const Point<float> g2 (gradientPoint2.resolve (scope));
 -         AffineTransform t;
 - 
 -         ColourGradient& g = *fill.gradient;
 - 
 -         if (g.isRadial)
 -         {
 -             const Point<float> g3 (gradientPoint3.resolve (scope));
 -             const Point<float> g3Source (g1.x + g2.y - g1.y,
 -                                          g1.y + g1.x - g2.x);
 - 
 -             t = AffineTransform::fromTargetPoints (g1.x, g1.y, g1.x, g1.y,
 -                                                    g2.x, g2.y, g2.x, g2.y,
 -                                                    g3Source.x, g3Source.y, g3.x, g3.y);
 -         }
 - 
 -         if (g.point1 != g1 || g.point2 != g2 || fill.transform != t)
 -         {
 -             g.point1 = g1;
 -             g.point2 = g2;
 -             fill.transform = t;
 -             return true;
 -         }
 -     }
 - 
 -     return false;
 - }
 - 
 - bool DrawableShape::RelativeFillType::isDynamic() const
 - {
 -     return gradientPoint1.isDynamic() || gradientPoint2.isDynamic() || gradientPoint3.isDynamic();
 - }
 - 
 - void DrawableShape::RelativeFillType::writeTo (ValueTree& v, ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager) const
 - {
 -     if (fill.isColour())
 -     {
 -         v.setProperty (FillAndStrokeState::type, "solid", undoManager);
 -         v.setProperty (FillAndStrokeState::colour, String::toHexString ((int) fill.colour.getARGB()), undoManager);
 -     }
 -     else if (fill.isGradient())
 -     {
 -         v.setProperty (FillAndStrokeState::type, "gradient", undoManager);
 -         v.setProperty (FillAndStrokeState::gradientPoint1, gradientPoint1.toString(), undoManager);
 -         v.setProperty (FillAndStrokeState::gradientPoint2, gradientPoint2.toString(), undoManager);
 -         v.setProperty (FillAndStrokeState::gradientPoint3, gradientPoint3.toString(), undoManager);
 - 
 -         const ColourGradient& cg = *fill.gradient;
 -         v.setProperty (FillAndStrokeState::radial, cg.isRadial, undoManager);
 - 
 -         String s;
 -         for (int i = 0; i < cg.getNumColours(); ++i)
 -             s << ' ' << cg.getColourPosition (i)
 -               << ' ' << String::toHexString ((int) cg.getColour(i).getARGB());
 - 
 -         v.setProperty (FillAndStrokeState::colours, s.trimStart(), undoManager);
 -     }
 -     else if (fill.isTiledImage())
 -     {
 -         v.setProperty (FillAndStrokeState::type, "image", undoManager);
 - 
 -         if (imageProvider != nullptr)
 -             v.setProperty (FillAndStrokeState::imageId, imageProvider->getIdentifierForImage (fill.image), undoManager);
 - 
 -         if (fill.getOpacity() < 1.0f)
 -             v.setProperty (FillAndStrokeState::imageOpacity, fill.getOpacity(), undoManager);
 -         else
 -             v.removeProperty (FillAndStrokeState::imageOpacity, undoManager);
 -     }
 -     else
 -     {
 -         jassertfalse;
 -     }
 - }
 - 
 - bool DrawableShape::RelativeFillType::readFrom (const ValueTree& v, ComponentBuilder::ImageProvider* imageProvider)
 - {
 -     const String newType (v [FillAndStrokeState::type].toString());
 - 
 -     if (newType == "solid")
 -     {
 -         const String colourString (v [FillAndStrokeState::colour].toString());
 -         fill.setColour (colourString.isEmpty() ? Colours::black
 -                                                : Colour::fromString (colourString));
 -         return true;
 -     }
 -     else if (newType == "gradient")
 -     {
 -         ColourGradient g;
 -         g.isRadial = v [FillAndStrokeState::radial];
 - 
 -         StringArray colourSteps;
 -         colourSteps.addTokens (v [FillAndStrokeState::colours].toString(), false);
 - 
 -         for (int i = 0; i < colourSteps.size() / 2; ++i)
 -             g.addColour (colourSteps[i * 2].getDoubleValue(),
 -                          Colour::fromString (colourSteps[i * 2 + 1]));
 - 
 -         fill.setGradient (g);
 - 
 -         gradientPoint1 = RelativePoint (v [FillAndStrokeState::gradientPoint1]);
 -         gradientPoint2 = RelativePoint (v [FillAndStrokeState::gradientPoint2]);
 -         gradientPoint3 = RelativePoint (v [FillAndStrokeState::gradientPoint3]);
 -         return true;
 -     }
 -     else if (newType == "image")
 -     {
 -         Image im;
 -         if (imageProvider != nullptr)
 -             im = imageProvider->getImageForIdentifier (v [FillAndStrokeState::imageId]);
 - 
 -         fill.setTiledImage (im, AffineTransform::identity);
 -         fill.setOpacity ((float) v.getProperty (FillAndStrokeState::imageOpacity, 1.0f));
 -         return true;
 -     }
 - 
 -     jassertfalse;
 -     return false;
 - }
 - 
 - //==============================================================================
 - const Identifier DrawableShape::FillAndStrokeState::type ("type");
 - const Identifier DrawableShape::FillAndStrokeState::colour ("colour");
 - const Identifier DrawableShape::FillAndStrokeState::colours ("colours");
 - const Identifier DrawableShape::FillAndStrokeState::fill ("Fill");
 - const Identifier DrawableShape::FillAndStrokeState::stroke ("Stroke");
 - const Identifier DrawableShape::FillAndStrokeState::path ("Path");
 - const Identifier DrawableShape::FillAndStrokeState::jointStyle ("jointStyle");
 - const Identifier DrawableShape::FillAndStrokeState::capStyle ("capStyle");
 - const Identifier DrawableShape::FillAndStrokeState::strokeWidth ("strokeWidth");
 - const Identifier DrawableShape::FillAndStrokeState::gradientPoint1 ("point1");
 - const Identifier DrawableShape::FillAndStrokeState::gradientPoint2 ("point2");
 - const Identifier DrawableShape::FillAndStrokeState::gradientPoint3 ("point3");
 - const Identifier DrawableShape::FillAndStrokeState::radial ("radial");
 - const Identifier DrawableShape::FillAndStrokeState::imageId ("imageId");
 - const Identifier DrawableShape::FillAndStrokeState::imageOpacity ("imageOpacity");
 - 
 - DrawableShape::FillAndStrokeState::FillAndStrokeState (const ValueTree& state_)
 -     : Drawable::ValueTreeWrapperBase (state_)
 - {
 - }
 - 
 - DrawableShape::RelativeFillType DrawableShape::FillAndStrokeState::getFill (const Identifier& fillOrStrokeType, ComponentBuilder::ImageProvider* imageProvider) const
 - {
 -     DrawableShape::RelativeFillType f;
 -     f.readFrom (state.getChildWithName (fillOrStrokeType), imageProvider);
 -     return f;
 - }
 - 
 - ValueTree DrawableShape::FillAndStrokeState::getFillState (const Identifier& fillOrStrokeType)
 - {
 -     ValueTree v (state.getChildWithName (fillOrStrokeType));
 -     if (v.isValid())
 -         return v;
 - 
 -     setFill (fillOrStrokeType, FillType (Colours::black), nullptr, nullptr);
 -     return getFillState (fillOrStrokeType);
 - }
 - 
 - void DrawableShape::FillAndStrokeState::setFill (const Identifier& fillOrStrokeType, const RelativeFillType& newFill,
 -                                                  ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager)
 - {
 -     ValueTree v (state.getOrCreateChildWithName (fillOrStrokeType, undoManager));
 -     newFill.writeTo (v, imageProvider, undoManager);
 - }
 - 
 - PathStrokeType DrawableShape::FillAndStrokeState::getStrokeType() const
 - {
 -     const String jointStyleString (state [jointStyle].toString());
 -     const String capStyleString (state [capStyle].toString());
 - 
 -     return PathStrokeType (state [strokeWidth],
 -                            jointStyleString == "curved" ? PathStrokeType::curved
 -                                                         : (jointStyleString == "bevel" ? PathStrokeType::beveled
 -                                                                                        : PathStrokeType::mitered),
 -                            capStyleString == "square" ? PathStrokeType::square
 -                                                       : (capStyleString == "round" ? PathStrokeType::rounded
 -                                                                                    : PathStrokeType::butt));
 - }
 - 
 - void DrawableShape::FillAndStrokeState::setStrokeType (const PathStrokeType& newStrokeType, UndoManager* undoManager)
 - {
 -     state.setProperty (strokeWidth, (double) newStrokeType.getStrokeThickness(), undoManager);
 -     state.setProperty (jointStyle, newStrokeType.getJointStyle() == PathStrokeType::mitered
 -                                      ? "miter" : (newStrokeType.getJointStyle() == PathStrokeType::curved ? "curved" : "bevel"), undoManager);
 -     state.setProperty (capStyle, newStrokeType.getEndStyle() == PathStrokeType::butt
 -                                      ? "butt" : (newStrokeType.getEndStyle() == PathStrokeType::square ? "square" : "round"), undoManager);
 - }
 
 
  |