mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-21 01:24:21 +00:00
win32 font fix. Tidied up warnings in plugin host. More drawable refactoring. TabbedComponent fix.
This commit is contained in:
parent
e5c4ecc670
commit
7478c7f9ab
27 changed files with 1798 additions and 1479 deletions
|
|
@ -231,7 +231,7 @@ public:
|
|||
|
||||
void mouseDown (const MouseEvent& e)
|
||||
{
|
||||
originalPos = relativePositionToGlobal (Point<int>());
|
||||
originalPos = localPointToGlobal (Point<int>());
|
||||
|
||||
toFront (true);
|
||||
|
||||
|
|
@ -277,7 +277,7 @@ public:
|
|||
Point<int> pos (originalPos + Point<int> (e.getDistanceFromDragStartX(), e.getDistanceFromDragStartY()));
|
||||
|
||||
if (getParentComponent() != 0)
|
||||
pos = getParentComponent()->globalPositionToRelative (pos);
|
||||
pos = getParentComponent()->getLocalPoint (0, pos);
|
||||
|
||||
graph.setNodePosition (filterID,
|
||||
(pos.getX() + getWidth() / 2) / (double) getParentWidth(),
|
||||
|
|
|
|||
|
|
@ -498,7 +498,7 @@ void MainHostWindow::filesDropped (const StringArray& files, int x, int y)
|
|||
|
||||
Point<int> pos (x, y);
|
||||
if (graphEditor != 0)
|
||||
pos = relativePositionToOtherComponent (graphEditor, pos);
|
||||
pos = graphEditor->getLocalPoint (this, pos);
|
||||
|
||||
for (int i = 0; i < jmin (5, typesFound.size()); ++i)
|
||||
createPlugin (typesFound.getUnchecked(i), pos.getX(), pos.getY());
|
||||
|
|
|
|||
1195
juce_amalgamated.cpp
1195
juce_amalgamated.cpp
File diff suppressed because it is too large
Load diff
|
|
@ -73,7 +73,7 @@ namespace JuceDummyNamespace {}
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 53
|
||||
#define JUCE_BUILDNUMBER 6
|
||||
#define JUCE_BUILDNUMBER 7
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
@ -45451,6 +45451,273 @@ private:
|
|||
/*** End of inlined file: juce_RelativeCoordinate.h ***/
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_RelativeCoordinatePositioner.h ***/
|
||||
#ifndef __JUCE_RELATIVECOORDINATEPOSITIONER_JUCEHEADER__
|
||||
#define __JUCE_RELATIVECOORDINATEPOSITIONER_JUCEHEADER__
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_RelativePoint.h ***/
|
||||
#ifndef __JUCE_RELATIVEPOINT_JUCEHEADER__
|
||||
#define __JUCE_RELATIVEPOINT_JUCEHEADER__
|
||||
|
||||
/**
|
||||
An X-Y position stored as a pair of RelativeCoordinate values.
|
||||
|
||||
@see RelativeCoordinate, RelativeRectangle
|
||||
*/
|
||||
class JUCE_API RelativePoint
|
||||
{
|
||||
public:
|
||||
/** Creates a point at the origin. */
|
||||
RelativePoint();
|
||||
|
||||
/** Creates an absolute point, relative to the origin. */
|
||||
RelativePoint (const Point<float>& absolutePoint);
|
||||
|
||||
/** Creates an absolute point, relative to the origin. */
|
||||
RelativePoint (float absoluteX, float absoluteY);
|
||||
|
||||
/** Creates an absolute point from two coordinates. */
|
||||
RelativePoint (const RelativeCoordinate& x, const RelativeCoordinate& y);
|
||||
|
||||
/** Creates a point from a stringified representation.
|
||||
The string must contain a pair of coordinates, separated by space or a comma. The syntax for the coordinate
|
||||
strings is explained in the RelativeCoordinate class.
|
||||
@see toString
|
||||
*/
|
||||
RelativePoint (const String& stringVersion);
|
||||
|
||||
bool operator== (const RelativePoint& other) const throw();
|
||||
bool operator!= (const RelativePoint& other) const throw();
|
||||
|
||||
/** Calculates the absolute position of this point.
|
||||
|
||||
You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
|
||||
be needed to calculate the result.
|
||||
*/
|
||||
const Point<float> resolve (const Expression::EvaluationContext* evaluationContext) const;
|
||||
|
||||
/** Changes the values of this point's coordinates to make it resolve to the specified position.
|
||||
|
||||
Calling this will leave any anchor points unchanged, but will set any absolute
|
||||
or relative positions to whatever values are necessary to make the resultant position
|
||||
match the position that is provided.
|
||||
*/
|
||||
void moveToAbsolute (const Point<float>& newPos, const Expression::EvaluationContext* evaluationContext);
|
||||
|
||||
/** Returns a string which represents this point.
|
||||
This returns a comma-separated pair of coordinates. For details of the string syntax used by the
|
||||
coordinates, see the RelativeCoordinate constructor notes.
|
||||
The string that is returned can be passed to the RelativePoint constructor to recreate the point.
|
||||
*/
|
||||
const String toString() const;
|
||||
|
||||
/** Renames a symbol if it is used by any of the coordinates.
|
||||
This calls RelativeCoordinate::renameAnchorIfUsed() on its X and Y coordinates.
|
||||
*/
|
||||
void renameSymbolIfUsed (const String& oldName, const String& newName);
|
||||
|
||||
/** Returns true if this point depends on any other coordinates for its position. */
|
||||
bool isDynamic() const;
|
||||
|
||||
// The actual X and Y coords...
|
||||
RelativeCoordinate x, y;
|
||||
};
|
||||
|
||||
#endif // __JUCE_RELATIVEPOINT_JUCEHEADER__
|
||||
/*** End of inlined file: juce_RelativePoint.h ***/
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_MarkerList.h ***/
|
||||
#ifndef __JUCE_MARKERLIST_JUCEHEADER__
|
||||
#define __JUCE_MARKERLIST_JUCEHEADER__
|
||||
|
||||
/**
|
||||
Holds a set of named marker points along a one-dimensional axis.
|
||||
|
||||
This class is used to store sets of X and Y marker points in components.
|
||||
@see Component::getMarkers().
|
||||
*/
|
||||
class JUCE_API MarkerList
|
||||
{
|
||||
public:
|
||||
|
||||
/** Creates an empty marker list. */
|
||||
MarkerList();
|
||||
/** Creates a copy of another marker list. */
|
||||
MarkerList (const MarkerList& other);
|
||||
/** Copies another marker list to this one. */
|
||||
MarkerList& operator= (const MarkerList& other);
|
||||
/** Destructor. */
|
||||
~MarkerList();
|
||||
|
||||
/** Represents a marker in a MarkerList. */
|
||||
class JUCE_API Marker
|
||||
{
|
||||
public:
|
||||
/** Creates a copy of another Marker. */
|
||||
Marker (const Marker& other);
|
||||
/** Creates a Marker with a given name and position. */
|
||||
Marker (const String& name, const RelativeCoordinate& position);
|
||||
|
||||
/** The marker's name. */
|
||||
String name;
|
||||
|
||||
/** The marker's position. */
|
||||
RelativeCoordinate position;
|
||||
|
||||
/** Returns true if both the names and positions of these two markers match. */
|
||||
bool operator== (const Marker&) const throw();
|
||||
/** Returns true if either the name or position of these two markers differ. */
|
||||
bool operator!= (const Marker&) const throw();
|
||||
};
|
||||
|
||||
/** Returns the number of markers in the list. */
|
||||
int getNumMarkers() const throw();
|
||||
|
||||
/** Returns one of the markers in the list, by its index. */
|
||||
const Marker* getMarker (int index) const throw();
|
||||
|
||||
/** Returns a named marker, or 0 if no such name is found.
|
||||
Note that name comparisons are case-sensitive.
|
||||
*/
|
||||
const Marker* getMarker (const String& name) const throw();
|
||||
|
||||
/** Sets the position of a marker.
|
||||
|
||||
If the name already exists, then the existing marker is moved; if it doesn't exist, then a
|
||||
new marker is added.
|
||||
*/
|
||||
void setMarker (const String& name, const RelativeCoordinate& position);
|
||||
|
||||
/** Deletes the marker at the given list index. */
|
||||
void removeMarker (int index);
|
||||
|
||||
/** Deletes the marker with the given name. */
|
||||
void removeMarker (const String& name);
|
||||
|
||||
/** Returns true if all the markers in these two lists match exactly. */
|
||||
bool operator== (const MarkerList& other) const throw();
|
||||
/** Returns true if not all the markers in these two lists match exactly. */
|
||||
bool operator!= (const MarkerList& other) const throw();
|
||||
|
||||
/**
|
||||
A class for receiving events when changes are made to a MarkerList.
|
||||
|
||||
You can register a MarkerList::Listener with a MarkerList using the MarkerList::addListener()
|
||||
method, and it will be called when markers are moved, added, or deleted.
|
||||
|
||||
@see MarkerList::addListener, MarkerList::removeListener
|
||||
*/
|
||||
class JUCE_API Listener
|
||||
{
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~Listener() {}
|
||||
|
||||
/** Called when something in the given marker list changes. */
|
||||
virtual void markersChanged (MarkerList* markerList) = 0;
|
||||
|
||||
/** Called when the given marker list is being deleted. */
|
||||
virtual void markerListBeingDeleted (MarkerList* markerList);
|
||||
};
|
||||
|
||||
/** Registers a listener that will be called when the markers are changed. */
|
||||
void addListener (Listener* listener);
|
||||
|
||||
/** Deregisters a previously-registered listener. */
|
||||
void removeListener (Listener* listener);
|
||||
|
||||
/** Synchronously calls markersChanged() on all the registered listeners. */
|
||||
void markersHaveChanged();
|
||||
|
||||
/** Forms a wrapper around a ValueTree that can be used for storing a MarkerList. */
|
||||
class ValueTreeWrapper
|
||||
{
|
||||
public:
|
||||
ValueTreeWrapper (const ValueTree& state);
|
||||
|
||||
ValueTree& getState() throw() { return state; }
|
||||
int getNumMarkers() const;
|
||||
const ValueTree getMarkerState (int index) const;
|
||||
const ValueTree getMarkerState (const String& name) const;
|
||||
bool containsMarker (const ValueTree& state) const;
|
||||
const MarkerList::Marker getMarker (const ValueTree& state) const;
|
||||
void setMarker (const MarkerList::Marker& marker, UndoManager* undoManager);
|
||||
void removeMarker (const ValueTree& state, UndoManager* undoManager);
|
||||
|
||||
void applyTo (MarkerList& markerList);
|
||||
void readFrom (const MarkerList& markerList, UndoManager* undoManager);
|
||||
|
||||
static const Identifier markerTag, nameProperty, posProperty;
|
||||
|
||||
private:
|
||||
ValueTree state;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
OwnedArray<Marker> markers;
|
||||
ListenerList <Listener> listeners;
|
||||
|
||||
JUCE_LEAK_DETECTOR (MarkerList);
|
||||
};
|
||||
|
||||
#endif // __JUCE_MARKERLIST_JUCEHEADER__
|
||||
/*** End of inlined file: juce_MarkerList.h ***/
|
||||
|
||||
/**
|
||||
Base class for Component::Positioners that are based upon relative coordinates.
|
||||
*/
|
||||
class JUCE_API RelativeCoordinatePositionerBase : public Component::Positioner,
|
||||
public ComponentListener,
|
||||
public MarkerList::Listener,
|
||||
public Expression::EvaluationContext
|
||||
{
|
||||
public:
|
||||
RelativeCoordinatePositionerBase (Component& component_);
|
||||
~RelativeCoordinatePositionerBase();
|
||||
|
||||
const Expression getSymbolValue (const String& objectName, const String& member) const;
|
||||
|
||||
void componentMovedOrResized (Component&, bool, bool);
|
||||
void componentParentHierarchyChanged (Component&);
|
||||
void componentBeingDeleted (Component& component);
|
||||
void markersChanged (MarkerList*);
|
||||
void markerListBeingDeleted (MarkerList* markerList);
|
||||
|
||||
void apply();
|
||||
|
||||
bool addCoordinate (const RelativeCoordinate& coord);
|
||||
bool addPoint (const RelativePoint& point);
|
||||
|
||||
protected:
|
||||
virtual bool registerCoordinates() = 0;
|
||||
virtual void applyToComponentBounds() = 0;
|
||||
|
||||
private:
|
||||
Array <Component*> sourceComponents;
|
||||
Array <MarkerList*> sourceMarkerLists;
|
||||
bool registeredOk;
|
||||
|
||||
bool registerListeners (const Expression& e);
|
||||
bool registerComponent (const String& componentID);
|
||||
bool registerMarker (const String markerName);
|
||||
void registerComponentListener (Component* const comp);
|
||||
void registerMarkerListListener (MarkerList* const list);
|
||||
void unregisterListeners();
|
||||
Component* findComponent (const String& componentID) const;
|
||||
Component* getSourceComponent (const String& objectName) const;
|
||||
const Expression xToExpression (const Component* const source, const int x) const;
|
||||
const Expression yToExpression (const Component* const source, const int y) const;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativeCoordinatePositionerBase);
|
||||
};
|
||||
|
||||
#endif // __JUCE_RELATIVECOORDINATEPOSITIONER_JUCEHEADER__
|
||||
/*** End of inlined file: juce_RelativeCoordinatePositioner.h ***/
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_ComponentBuilder.h ***/
|
||||
#ifndef __JUCE_COMPONENTBUILDER_JUCEHEADER__
|
||||
#define __JUCE_COMPONENTBUILDER_JUCEHEADER__
|
||||
|
|
@ -45841,6 +46108,27 @@ protected:
|
|||
|
||||
Point<int> originRelativeToComponent;
|
||||
|
||||
#ifndef DOXYGEN
|
||||
/** Internal utility class used by Drawables. */
|
||||
template <class DrawableType>
|
||||
class Positioner : public RelativeCoordinatePositionerBase
|
||||
{
|
||||
public:
|
||||
Positioner (DrawableType& component_)
|
||||
: RelativeCoordinatePositionerBase (component_),
|
||||
owner (component_)
|
||||
{}
|
||||
|
||||
bool registerCoordinates() { return owner.registerCoordinates (*this); }
|
||||
void applyToComponentBounds() { owner.recalculateCoordinates (this); }
|
||||
|
||||
private:
|
||||
DrawableType& owner;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Positioner);
|
||||
};
|
||||
#endif
|
||||
|
||||
private:
|
||||
void nonConstDraw (Graphics& g, float opacity, const AffineTransform& transform);
|
||||
|
||||
|
|
@ -54179,8 +54467,6 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
ScopedPointer<TabbedButtonBar> tabs;
|
||||
|
||||
/** This creates one of the tab buttons.
|
||||
|
||||
If you need to use custom tab components, you can override this method and
|
||||
|
|
@ -54188,15 +54474,18 @@ protected:
|
|||
*/
|
||||
virtual TabBarButton* createTabButton (const String& tabName, int tabIndex);
|
||||
|
||||
/** @internal */
|
||||
ScopedPointer<TabbedButtonBar> tabs;
|
||||
|
||||
private:
|
||||
|
||||
OwnedArray <WeakReference<Component> > contentComponents;
|
||||
Array <WeakReference<Component> > contentComponents;
|
||||
WeakReference<Component> panelComponent;
|
||||
int tabDepth;
|
||||
int outlineThickness, edgeIndent;
|
||||
static const Identifier deleteComponentId;
|
||||
|
||||
friend class TabCompButtonBar;
|
||||
class ButtonBar;
|
||||
friend class ButtonBar;
|
||||
void changeCallback (int newCurrentTabIndex, const String& newTabName);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TabbedComponent);
|
||||
|
|
@ -57419,206 +57708,12 @@ private:
|
|||
#endif
|
||||
#ifndef __JUCE_MARKERLIST_JUCEHEADER__
|
||||
|
||||
/*** Start of inlined file: juce_MarkerList.h ***/
|
||||
#ifndef __JUCE_MARKERLIST_JUCEHEADER__
|
||||
#define __JUCE_MARKERLIST_JUCEHEADER__
|
||||
|
||||
/**
|
||||
Holds a set of named marker points along a one-dimensional axis.
|
||||
|
||||
This class is used to store sets of X and Y marker points in components.
|
||||
@see Component::getMarkers().
|
||||
*/
|
||||
class JUCE_API MarkerList
|
||||
{
|
||||
public:
|
||||
|
||||
/** Creates an empty marker list. */
|
||||
MarkerList();
|
||||
/** Creates a copy of another marker list. */
|
||||
MarkerList (const MarkerList& other);
|
||||
/** Copies another marker list to this one. */
|
||||
MarkerList& operator= (const MarkerList& other);
|
||||
/** Destructor. */
|
||||
~MarkerList();
|
||||
|
||||
/** Represents a marker in a MarkerList. */
|
||||
class JUCE_API Marker
|
||||
{
|
||||
public:
|
||||
/** Creates a copy of another Marker. */
|
||||
Marker (const Marker& other);
|
||||
/** Creates a Marker with a given name and position. */
|
||||
Marker (const String& name, const RelativeCoordinate& position);
|
||||
|
||||
/** The marker's name. */
|
||||
String name;
|
||||
|
||||
/** The marker's position. */
|
||||
RelativeCoordinate position;
|
||||
|
||||
/** Returns true if both the names and positions of these two markers match. */
|
||||
bool operator== (const Marker&) const throw();
|
||||
/** Returns true if either the name or position of these two markers differ. */
|
||||
bool operator!= (const Marker&) const throw();
|
||||
};
|
||||
|
||||
/** Returns the number of markers in the list. */
|
||||
int getNumMarkers() const throw();
|
||||
|
||||
/** Returns one of the markers in the list, by its index. */
|
||||
const Marker* getMarker (int index) const throw();
|
||||
|
||||
/** Returns a named marker, or 0 if no such name is found.
|
||||
Note that name comparisons are case-sensitive.
|
||||
*/
|
||||
const Marker* getMarker (const String& name) const throw();
|
||||
|
||||
/** Sets the position of a marker.
|
||||
|
||||
If the name already exists, then the existing marker is moved; if it doesn't exist, then a
|
||||
new marker is added.
|
||||
*/
|
||||
void setMarker (const String& name, const RelativeCoordinate& position);
|
||||
|
||||
/** Deletes the marker at the given list index. */
|
||||
void removeMarker (int index);
|
||||
|
||||
/** Deletes the marker with the given name. */
|
||||
void removeMarker (const String& name);
|
||||
|
||||
/** Returns true if all the markers in these two lists match exactly. */
|
||||
bool operator== (const MarkerList& other) const throw();
|
||||
/** Returns true if not all the markers in these two lists match exactly. */
|
||||
bool operator!= (const MarkerList& other) const throw();
|
||||
|
||||
/**
|
||||
A class for receiving events when changes are made to a MarkerList.
|
||||
|
||||
You can register a MarkerList::Listener with a MarkerList using the MarkerList::addListener()
|
||||
method, and it will be called when markers are moved, added, or deleted.
|
||||
|
||||
@see MarkerList::addListener, MarkerList::removeListener
|
||||
*/
|
||||
class JUCE_API Listener
|
||||
{
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~Listener() {}
|
||||
|
||||
/** Called when something in the given marker list changes. */
|
||||
virtual void markersChanged (MarkerList* markerList) = 0;
|
||||
|
||||
/** Called when the given marker list is being deleted. */
|
||||
virtual void markerListBeingDeleted (MarkerList* markerList);
|
||||
};
|
||||
|
||||
/** Registers a listener that will be called when the markers are changed. */
|
||||
void addListener (Listener* listener);
|
||||
|
||||
/** Deregisters a previously-registered listener. */
|
||||
void removeListener (Listener* listener);
|
||||
|
||||
/** Synchronously calls markersChanged() on all the registered listeners. */
|
||||
void markersHaveChanged();
|
||||
|
||||
/** Forms a wrapper around a ValueTree that can be used for storing a MarkerList. */
|
||||
class ValueTreeWrapper
|
||||
{
|
||||
public:
|
||||
ValueTreeWrapper (const ValueTree& state);
|
||||
|
||||
ValueTree& getState() throw() { return state; }
|
||||
int getNumMarkers() const;
|
||||
const ValueTree getMarkerState (int index) const;
|
||||
const ValueTree getMarkerState (const String& name) const;
|
||||
bool containsMarker (const ValueTree& state) const;
|
||||
const MarkerList::Marker getMarker (const ValueTree& state) const;
|
||||
void setMarker (const MarkerList::Marker& marker, UndoManager* undoManager);
|
||||
void removeMarker (const ValueTree& state, UndoManager* undoManager);
|
||||
|
||||
void applyTo (MarkerList& markerList);
|
||||
void readFrom (const MarkerList& markerList, UndoManager* undoManager);
|
||||
|
||||
static const Identifier markerTag, nameProperty, posProperty;
|
||||
|
||||
private:
|
||||
ValueTree state;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
OwnedArray<Marker> markers;
|
||||
ListenerList <Listener> listeners;
|
||||
|
||||
JUCE_LEAK_DETECTOR (MarkerList);
|
||||
};
|
||||
|
||||
#endif // __JUCE_MARKERLIST_JUCEHEADER__
|
||||
/*** End of inlined file: juce_MarkerList.h ***/
|
||||
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_RELATIVECOORDINATE_JUCEHEADER__
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_RELATIVECOORDINATEPOSITIONER_JUCEHEADER__
|
||||
|
||||
/*** Start of inlined file: juce_RelativeCoordinatePositioner.h ***/
|
||||
#ifndef __JUCE_RELATIVECOORDINATEPOSITIONER_JUCEHEADER__
|
||||
#define __JUCE_RELATIVECOORDINATEPOSITIONER_JUCEHEADER__
|
||||
|
||||
/**
|
||||
Base class for Component::Positioners that are based upon relative coordinates.
|
||||
*/
|
||||
class JUCE_API RelativeCoordinatePositionerBase : public Component::Positioner,
|
||||
public ComponentListener,
|
||||
public MarkerList::Listener,
|
||||
public Expression::EvaluationContext
|
||||
{
|
||||
public:
|
||||
RelativeCoordinatePositionerBase (Component& component_);
|
||||
~RelativeCoordinatePositionerBase();
|
||||
|
||||
const Expression getSymbolValue (const String& objectName, const String& member) const;
|
||||
|
||||
void componentMovedOrResized (Component&, bool, bool);
|
||||
void componentParentHierarchyChanged (Component&);
|
||||
void componentBeingDeleted (Component& component);
|
||||
void markersChanged (MarkerList*);
|
||||
void markerListBeingDeleted (MarkerList* markerList);
|
||||
|
||||
void apply();
|
||||
|
||||
protected:
|
||||
bool addCoordinate (const RelativeCoordinate& coord);
|
||||
|
||||
virtual bool registerCoordinates() = 0;
|
||||
virtual void applyToComponentBounds() = 0;
|
||||
|
||||
private:
|
||||
Array <Component*> sourceComponents;
|
||||
Array <MarkerList*> sourceMarkerLists;
|
||||
bool registeredOk;
|
||||
|
||||
bool registerListeners (const Expression& e);
|
||||
bool registerComponent (const String& componentID);
|
||||
bool registerMarker (const String markerName);
|
||||
void registerComponentListener (Component* const comp);
|
||||
void registerMarkerListListener (MarkerList* const list);
|
||||
void unregisterListeners();
|
||||
Component* findComponent (const String& componentID) const;
|
||||
Component* getSourceComponent (const String& objectName) const;
|
||||
const Expression xToExpression (const Component* const source, const int x) const;
|
||||
const Expression yToExpression (const Component* const source, const int y) const;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativeCoordinatePositionerBase);
|
||||
};
|
||||
|
||||
#endif // __JUCE_RELATIVECOORDINATEPOSITIONER_JUCEHEADER__
|
||||
/*** End of inlined file: juce_RelativeCoordinatePositioner.h ***/
|
||||
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_RELATIVEPARALLELOGRAM_JUCEHEADER__
|
||||
|
||||
|
|
@ -57626,78 +57721,6 @@ private:
|
|||
#ifndef __JUCE_RELATIVEPARALLELOGRAM_JUCEHEADER__
|
||||
#define __JUCE_RELATIVEPARALLELOGRAM_JUCEHEADER__
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_RelativePoint.h ***/
|
||||
#ifndef __JUCE_RELATIVEPOINT_JUCEHEADER__
|
||||
#define __JUCE_RELATIVEPOINT_JUCEHEADER__
|
||||
|
||||
/**
|
||||
An X-Y position stored as a pair of RelativeCoordinate values.
|
||||
|
||||
@see RelativeCoordinate, RelativeRectangle
|
||||
*/
|
||||
class JUCE_API RelativePoint
|
||||
{
|
||||
public:
|
||||
/** Creates a point at the origin. */
|
||||
RelativePoint();
|
||||
|
||||
/** Creates an absolute point, relative to the origin. */
|
||||
RelativePoint (const Point<float>& absolutePoint);
|
||||
|
||||
/** Creates an absolute point, relative to the origin. */
|
||||
RelativePoint (float absoluteX, float absoluteY);
|
||||
|
||||
/** Creates an absolute point from two coordinates. */
|
||||
RelativePoint (const RelativeCoordinate& x, const RelativeCoordinate& y);
|
||||
|
||||
/** Creates a point from a stringified representation.
|
||||
The string must contain a pair of coordinates, separated by space or a comma. The syntax for the coordinate
|
||||
strings is explained in the RelativeCoordinate class.
|
||||
@see toString
|
||||
*/
|
||||
RelativePoint (const String& stringVersion);
|
||||
|
||||
bool operator== (const RelativePoint& other) const throw();
|
||||
bool operator!= (const RelativePoint& other) const throw();
|
||||
|
||||
/** Calculates the absolute position of this point.
|
||||
|
||||
You'll need to provide a suitable Expression::EvaluationContext for looking up any coordinates that may
|
||||
be needed to calculate the result.
|
||||
*/
|
||||
const Point<float> resolve (const Expression::EvaluationContext* evaluationContext) const;
|
||||
|
||||
/** Changes the values of this point's coordinates to make it resolve to the specified position.
|
||||
|
||||
Calling this will leave any anchor points unchanged, but will set any absolute
|
||||
or relative positions to whatever values are necessary to make the resultant position
|
||||
match the position that is provided.
|
||||
*/
|
||||
void moveToAbsolute (const Point<float>& newPos, const Expression::EvaluationContext* evaluationContext);
|
||||
|
||||
/** Returns a string which represents this point.
|
||||
This returns a comma-separated pair of coordinates. For details of the string syntax used by the
|
||||
coordinates, see the RelativeCoordinate constructor notes.
|
||||
The string that is returned can be passed to the RelativePoint constructor to recreate the point.
|
||||
*/
|
||||
const String toString() const;
|
||||
|
||||
/** Renames a symbol if it is used by any of the coordinates.
|
||||
This calls RelativeCoordinate::renameAnchorIfUsed() on its X and Y coordinates.
|
||||
*/
|
||||
void renameSymbolIfUsed (const String& oldName, const String& newName);
|
||||
|
||||
/** Returns true if this point depends on any other coordinates for its position. */
|
||||
bool isDynamic() const;
|
||||
|
||||
// The actual X and Y coords...
|
||||
RelativeCoordinate x, y;
|
||||
};
|
||||
|
||||
#endif // __JUCE_RELATIVEPOINT_JUCEHEADER__
|
||||
/*** End of inlined file: juce_RelativePoint.h ***/
|
||||
|
||||
/**
|
||||
A parallelogram defined by three RelativePoint positions.
|
||||
|
||||
|
|
@ -57718,12 +57741,14 @@ public:
|
|||
const Rectangle<float> getBounds (Expression::EvaluationContext* coordFinder) const;
|
||||
void getPath (Path& path, Expression::EvaluationContext* coordFinder) const;
|
||||
const AffineTransform resetToPerpendicular (Expression::EvaluationContext* coordFinder);
|
||||
bool isDynamic() const;
|
||||
|
||||
bool operator== (const RelativeParallelogram& other) const throw();
|
||||
bool operator!= (const RelativeParallelogram& other) const throw();
|
||||
|
||||
static const Point<float> getInternalCoordForPoint (const Point<float>* parallelogramCorners, Point<float> point) throw();
|
||||
static const Point<float> getPointForInternalCoord (const Point<float>* parallelogramCorners, const Point<float>& internalPoint) throw();
|
||||
static const Rectangle<float> getBoundingBox (const Point<float>* parallelogramCorners) throw();
|
||||
|
||||
RelativePoint topLeft, topRight, bottomLeft;
|
||||
};
|
||||
|
|
@ -61744,8 +61769,8 @@ protected:
|
|||
|
||||
@see Drawable
|
||||
*/
|
||||
class JUCE_API DrawableComposite : public Drawable,
|
||||
public Expression::EvaluationContext
|
||||
class JUCE_API DrawableComposite : public Drawable//,
|
||||
// public Expression::EvaluationContext
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
@ -61810,8 +61835,6 @@ public:
|
|||
/** @internal */
|
||||
static const Identifier valueTreeType;
|
||||
/** @internal */
|
||||
const Expression getSymbolValue (const String& symbol, const String& member) const;
|
||||
/** @internal */
|
||||
const Rectangle<float> getDrawableBounds() const;
|
||||
/** @internal */
|
||||
void childBoundsChanged (Component*);
|
||||
|
|
@ -61853,7 +61876,10 @@ private:
|
|||
MarkerList markersX, markersY;
|
||||
bool updateBoundsReentrant;
|
||||
|
||||
void refreshTransformFromBounds();
|
||||
friend class Drawable::Positioner<DrawableComposite>;
|
||||
bool registerCoordinates (RelativeCoordinatePositionerBase&);
|
||||
void recalculateCoordinates (Expression::EvaluationContext*);
|
||||
|
||||
void updateBoundsToFitChildren();
|
||||
|
||||
DrawableComposite& operator= (const DrawableComposite&);
|
||||
|
|
@ -61967,7 +61993,9 @@ private:
|
|||
Colour overlayColour;
|
||||
RelativeParallelogram bounds;
|
||||
|
||||
void refreshTransformFromBounds();
|
||||
friend class Drawable::Positioner<DrawableImage>;
|
||||
bool registerCoordinates (RelativeCoordinatePositionerBase&);
|
||||
void recalculateCoordinates (Expression::EvaluationContext*);
|
||||
|
||||
DrawableImage& operator= (const DrawableImage&);
|
||||
JUCE_LEAK_DETECTOR (DrawableImage);
|
||||
|
|
@ -62006,6 +62034,29 @@ public:
|
|||
/** Destructor. */
|
||||
~DrawableShape();
|
||||
|
||||
/** A FillType wrapper that allows the gradient coordinates to be implemented using RelativePoint.
|
||||
*/
|
||||
class RelativeFillType
|
||||
{
|
||||
public:
|
||||
RelativeFillType();
|
||||
RelativeFillType (const FillType& fill);
|
||||
RelativeFillType (const RelativeFillType&);
|
||||
RelativeFillType& operator= (const RelativeFillType&);
|
||||
|
||||
bool operator== (const RelativeFillType&) const;
|
||||
bool operator!= (const RelativeFillType&) const;
|
||||
|
||||
bool isDynamic() const;
|
||||
bool recalculateCoords (Expression::EvaluationContext* context);
|
||||
|
||||
void writeTo (ValueTree& v, ComponentBuilder::ImageProvider*, UndoManager*) const;
|
||||
bool readFrom (const ValueTree& v, ComponentBuilder::ImageProvider*);
|
||||
|
||||
FillType fill;
|
||||
RelativePoint gradientPoint1, gradientPoint2, gradientPoint3;
|
||||
};
|
||||
|
||||
/** Sets a fill type for the path.
|
||||
This colour is used to fill the path - if you don't want the path to be
|
||||
filled (e.g. if you're just drawing an outline), set this to a transparent
|
||||
|
|
@ -62015,20 +62066,34 @@ public:
|
|||
*/
|
||||
void setFill (const FillType& newFill);
|
||||
|
||||
/** Sets a fill type for the path.
|
||||
This colour is used to fill the path - if you don't want the path to be
|
||||
filled (e.g. if you're just drawing an outline), set this to a transparent
|
||||
colour.
|
||||
|
||||
@see setPath, setStrokeFill
|
||||
*/
|
||||
void setFill (const RelativeFillType& newFill);
|
||||
|
||||
/** Returns the current fill type.
|
||||
@see setFill
|
||||
*/
|
||||
const FillType& getFill() const throw() { return mainFill; }
|
||||
const RelativeFillType& getFill() const throw() { return mainFill; }
|
||||
|
||||
/** Sets the fill type with which the outline will be drawn.
|
||||
@see setFill
|
||||
*/
|
||||
void setStrokeFill (const FillType& newStrokeFill);
|
||||
|
||||
/** Sets the fill type with which the outline will be drawn.
|
||||
@see setFill
|
||||
*/
|
||||
void setStrokeFill (const RelativeFillType& newStrokeFill);
|
||||
|
||||
/** Returns the current stroke fill.
|
||||
@see setStrokeFill
|
||||
*/
|
||||
const FillType& getStrokeFill() const throw() { return strokeFill; }
|
||||
const RelativeFillType& getStrokeFill() const throw() { return strokeFill; }
|
||||
|
||||
/** Changes the properties of the outline that will be drawn around the path.
|
||||
If the stroke has 0 thickness, no stroke will be drawn.
|
||||
|
|
@ -62042,7 +62107,7 @@ public:
|
|||
void setStrokeThickness (float newThickness);
|
||||
|
||||
/** Returns the current outline style. */
|
||||
const PathStrokeType& getStrokeType() const throw() { return strokeType; }
|
||||
const PathStrokeType& getStrokeType() const throw() { return strokeType; }
|
||||
|
||||
/** @internal */
|
||||
class FillAndStrokeState : public Drawable::ValueTreeWrapperBase
|
||||
|
|
@ -62050,32 +62115,13 @@ public:
|
|||
public:
|
||||
FillAndStrokeState (const ValueTree& state);
|
||||
|
||||
const FillType getMainFill (Expression::EvaluationContext* nameFinder,
|
||||
ComponentBuilder::ImageProvider* imageProvider) const;
|
||||
ValueTree getMainFillState();
|
||||
void setMainFill (const FillType& newFill, const RelativePoint* gradientPoint1,
|
||||
const RelativePoint* gradientPoint2, const RelativePoint* gradientPoint3,
|
||||
ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager);
|
||||
|
||||
const FillType getStrokeFill (Expression::EvaluationContext* nameFinder,
|
||||
ComponentBuilder::ImageProvider* imageProvider) const;
|
||||
ValueTree getStrokeFillState();
|
||||
void setStrokeFill (const FillType& newFill, const RelativePoint* gradientPoint1,
|
||||
const RelativePoint* gradientPoint2, const RelativePoint* gradientPoint3,
|
||||
ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager);
|
||||
ValueTree getFillState (const Identifier& fillOrStrokeType);
|
||||
const RelativeFillType getFill (const Identifier& fillOrStrokeType, ComponentBuilder::ImageProvider*) const;
|
||||
void setFill (const Identifier& fillOrStrokeType, const RelativeFillType& newFill,
|
||||
ComponentBuilder::ImageProvider*, UndoManager*);
|
||||
|
||||
const PathStrokeType getStrokeType() const;
|
||||
void setStrokeType (const PathStrokeType& newStrokeType, UndoManager* undoManager);
|
||||
|
||||
static const FillType readFillType (const ValueTree& v, RelativePoint* gradientPoint1,
|
||||
RelativePoint* gradientPoint2, RelativePoint* gradientPoint3,
|
||||
Expression::EvaluationContext* nameFinder,
|
||||
ComponentBuilder::ImageProvider* imageProvider);
|
||||
|
||||
static void writeFillType (ValueTree& v, const FillType& fillType,
|
||||
const RelativePoint* gradientPoint1, const RelativePoint* gradientPoint2,
|
||||
const RelativePoint* gradientPoint3, ComponentBuilder::ImageProvider* imageProvider,
|
||||
UndoManager* undoManager);
|
||||
void setStrokeType (const PathStrokeType& newStrokeType, UndoManager*);
|
||||
|
||||
static const Identifier type, colour, colours, fill, stroke, path, jointStyle, capStyle, strokeWidth,
|
||||
gradientPoint1, gradientPoint2, gradientPoint3, radial, imageId, imageOpacity;
|
||||
|
|
@ -62094,26 +62140,23 @@ protected:
|
|||
void pathChanged();
|
||||
/** Called when the cached stroke should be updated. */
|
||||
void strokeChanged();
|
||||
|
||||
/** Implemented by subclasses to regenerate the path. */
|
||||
virtual bool rebuildPath (Path& path) const = 0;
|
||||
|
||||
/** True if there's a stroke with a non-zero thickness and non-transparent colour. */
|
||||
bool isStrokeVisible() const throw();
|
||||
|
||||
/** Updates the details from a FillAndStrokeState object, returning true if something changed. */
|
||||
bool refreshFillTypes (const FillAndStrokeState& newState,
|
||||
Expression::EvaluationContext* nameFinder,
|
||||
ComponentBuilder::ImageProvider* imageProvider);
|
||||
|
||||
void refreshFillTypes (const FillAndStrokeState& newState, ComponentBuilder::ImageProvider*);
|
||||
/** Writes the stroke and fill details to a FillAndStrokeState object. */
|
||||
void writeTo (FillAndStrokeState& state, ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager) const;
|
||||
void writeTo (FillAndStrokeState& state, ComponentBuilder::ImageProvider*, UndoManager*) const;
|
||||
|
||||
PathStrokeType strokeType;
|
||||
Path path, strokePath;
|
||||
|
||||
private:
|
||||
FillType mainFill, strokeFill;
|
||||
class RelativePositioner;
|
||||
RelativeFillType mainFill, strokeFill;
|
||||
ScopedPointer<RelativeCoordinatePositionerBase> mainFillPositioner, strokeFillPositioner;
|
||||
|
||||
void setFillInternal (RelativeFillType& fill, const RelativeFillType& newFill,
|
||||
ScopedPointer<RelativeCoordinatePositionerBase>& positioner);
|
||||
|
||||
DrawableShape& operator= (const DrawableShape&);
|
||||
};
|
||||
|
|
@ -62184,24 +62227,24 @@ public:
|
|||
int getNumControlPoints() const throw();
|
||||
|
||||
const RelativePoint getControlPoint (int index) const;
|
||||
Value getControlPointValue (int index, UndoManager* undoManager) const;
|
||||
Value getControlPointValue (int index, UndoManager*) const;
|
||||
const RelativePoint getStartPoint() const;
|
||||
const RelativePoint getEndPoint() const;
|
||||
void setControlPoint (int index, const RelativePoint& point, UndoManager* undoManager);
|
||||
float getLength (Expression::EvaluationContext* nameFinder) const;
|
||||
void setControlPoint (int index, const RelativePoint& point, UndoManager*);
|
||||
float getLength (Expression::EvaluationContext*) const;
|
||||
|
||||
ValueTreeWrapper getParent() const;
|
||||
Element getPreviousElement() const;
|
||||
|
||||
const String getModeOfEndPoint() const;
|
||||
void setModeOfEndPoint (const String& newMode, UndoManager* undoManager);
|
||||
void setModeOfEndPoint (const String& newMode, UndoManager*);
|
||||
|
||||
void convertToLine (UndoManager* undoManager);
|
||||
void convertToCubic (Expression::EvaluationContext* nameFinder, UndoManager* undoManager);
|
||||
void convertToLine (UndoManager*);
|
||||
void convertToCubic (Expression::EvaluationContext*, UndoManager*);
|
||||
void convertToPathBreak (UndoManager* undoManager);
|
||||
ValueTree insertPoint (const Point<float>& targetPoint, Expression::EvaluationContext* nameFinder, UndoManager* undoManager);
|
||||
ValueTree insertPoint (const Point<float>& targetPoint, Expression::EvaluationContext*, UndoManager*);
|
||||
void removePoint (UndoManager* undoManager);
|
||||
float findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext* nameFinder) const;
|
||||
float findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext*) const;
|
||||
|
||||
static const Identifier mode, startSubPathElement, closeSubPathElement,
|
||||
lineToElement, quadraticToElement, cubicToElement;
|
||||
|
|
@ -62220,15 +62263,13 @@ public:
|
|||
static const Identifier nonZeroWinding, point1, point2, point3;
|
||||
};
|
||||
|
||||
protected:
|
||||
bool rebuildPath (Path& path) const;
|
||||
|
||||
private:
|
||||
|
||||
ScopedPointer<RelativePointPath> relativePath;
|
||||
|
||||
class RelativePositioner;
|
||||
friend class RelativePositioner;
|
||||
void applyRelativePath (const RelativePointPath& newPath);
|
||||
const RelativePointPath* getRelativePath() const;
|
||||
void applyRelativePath (const RelativePointPath&, Expression::EvaluationContext*);
|
||||
|
||||
DrawablePath& operator= (const DrawablePath&);
|
||||
JUCE_LEAK_DETECTOR (DrawablePath);
|
||||
|
|
@ -62290,24 +62331,24 @@ public:
|
|||
ValueTreeWrapper (const ValueTree& state);
|
||||
|
||||
const RelativeParallelogram getRectangle() const;
|
||||
void setRectangle (const RelativeParallelogram& newBounds, UndoManager* undoManager);
|
||||
void setRectangle (const RelativeParallelogram& newBounds, UndoManager*);
|
||||
|
||||
void setCornerSize (const RelativePoint& cornerSize, UndoManager* undoManager);
|
||||
void setCornerSize (const RelativePoint& cornerSize, UndoManager*);
|
||||
const RelativePoint getCornerSize() const;
|
||||
Value getCornerSizeValue (UndoManager* undoManager) const;
|
||||
Value getCornerSizeValue (UndoManager*) const;
|
||||
|
||||
static const Identifier topLeft, topRight, bottomLeft, cornerSize;
|
||||
};
|
||||
|
||||
protected:
|
||||
/** @internal */
|
||||
bool rebuildPath (Path& path) const;
|
||||
|
||||
private:
|
||||
friend class Drawable::Positioner<DrawableRectangle>;
|
||||
|
||||
RelativeParallelogram bounds;
|
||||
RelativePoint cornerSize;
|
||||
|
||||
const AffineTransform calculateTransform() const;
|
||||
void rebuildPath();
|
||||
bool registerCoordinates (RelativeCoordinatePositionerBase&);
|
||||
void recalculateCoordinates (Expression::EvaluationContext*);
|
||||
|
||||
DrawableRectangle& operator= (const DrawableRectangle&);
|
||||
JUCE_LEAK_DETECTOR (DrawableRectangle);
|
||||
|
|
@ -62425,12 +62466,17 @@ private:
|
|||
|
||||
RelativeParallelogram bounds;
|
||||
RelativePoint fontSizeControlPoint;
|
||||
Font font;
|
||||
Point<float> resolvedPoints[3];
|
||||
Font font, scaledFont;
|
||||
String text;
|
||||
Colour colour;
|
||||
Justification justification;
|
||||
|
||||
friend class Drawable::Positioner<DrawableText>;
|
||||
bool registerCoordinates (RelativeCoordinatePositionerBase&);
|
||||
void recalculateCoordinates (Expression::EvaluationContext*);
|
||||
void refreshBounds();
|
||||
const AffineTransform getArrangementAndTransform (GlyphArrangement& glyphs) const;
|
||||
|
||||
DrawableText& operator= (const DrawableText&);
|
||||
JUCE_LEAK_DETECTOR (DrawableText);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 53
|
||||
#define JUCE_BUILDNUMBER 6
|
||||
#define JUCE_BUILDNUMBER 7
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
|
|||
|
|
@ -86,8 +86,9 @@ namespace ComponentBuilderHelpers
|
|||
if (topLevelComp != 0)
|
||||
{
|
||||
ComponentBuilder::TypeHandler* const type = builder.getHandlerForState (state);
|
||||
const String uid (getStateId (state));
|
||||
|
||||
if (type == 0)
|
||||
if (type == 0 || uid.isEmpty())
|
||||
{
|
||||
// ..handle the case where a child of the actual state node has changed.
|
||||
if (state.getParent().isValid())
|
||||
|
|
@ -95,21 +96,20 @@ namespace ComponentBuilderHelpers
|
|||
}
|
||||
else
|
||||
{
|
||||
Component* const changedComp = findComponentWithID (topLevelComp, getStateId (state));
|
||||
Component* const changedComp = findComponentWithID (topLevelComp, uid);
|
||||
|
||||
if (changedComp != 0)
|
||||
type->updateComponentFromState (changedComp, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
const Identifier ComponentBuilder::idProperty ("id");
|
||||
|
||||
ComponentBuilder::ComponentBuilder (const ValueTree& state_)
|
||||
: state (state_)
|
||||
: state (state_), imageProvider (0)
|
||||
{
|
||||
state.addListener (this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,17 +32,39 @@ BEGIN_JUCE_NAMESPACE
|
|||
|
||||
|
||||
//==============================================================================
|
||||
class TabCompButtonBar : public TabbedButtonBar
|
||||
namespace TabbedComponentHelpers
|
||||
{
|
||||
public:
|
||||
TabCompButtonBar (TabbedComponent& owner_,
|
||||
const TabbedButtonBar::Orientation orientation_)
|
||||
: TabbedButtonBar (orientation_),
|
||||
owner (owner_)
|
||||
const Identifier deleteComponentId ("deleteByTabComp_");
|
||||
|
||||
void deleteIfNecessary (Component* const comp)
|
||||
{
|
||||
if (comp != 0 && (bool) comp->getProperties() [deleteComponentId])
|
||||
delete comp;
|
||||
}
|
||||
|
||||
~TabCompButtonBar()
|
||||
const Rectangle<int> getTabArea (Rectangle<int>& content, BorderSize& outline,
|
||||
const TabbedButtonBar::Orientation orientation, const int tabDepth)
|
||||
{
|
||||
switch (orientation)
|
||||
{
|
||||
case TabbedButtonBar::TabsAtTop: outline.setTop (0); return content.removeFromTop (tabDepth);
|
||||
case TabbedButtonBar::TabsAtBottom: outline.setBottom (0); return content.removeFromBottom (tabDepth);
|
||||
case TabbedButtonBar::TabsAtLeft: outline.setLeft (0); return content.removeFromLeft (tabDepth);
|
||||
case TabbedButtonBar::TabsAtRight: outline.setRight (0); return content.removeFromRight (tabDepth);
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
return Rectangle<int>();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class TabbedComponent::ButtonBar : public TabbedButtonBar
|
||||
{
|
||||
public:
|
||||
ButtonBar (TabbedComponent& owner_, const TabbedButtonBar::Orientation orientation_)
|
||||
: TabbedButtonBar (orientation_),
|
||||
owner (owner_)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -69,16 +91,17 @@ public:
|
|||
private:
|
||||
TabbedComponent& owner;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TabCompButtonBar);
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonBar);
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
TabbedComponent::TabbedComponent (const TabbedButtonBar::Orientation orientation)
|
||||
: tabDepth (30),
|
||||
outlineThickness (1),
|
||||
edgeIndent (0)
|
||||
{
|
||||
addAndMakeVisible (tabs = new TabCompButtonBar (*this, orientation));
|
||||
addAndMakeVisible (tabs = new ButtonBar (*this, orientation));
|
||||
}
|
||||
|
||||
TabbedComponent::~TabbedComponent()
|
||||
|
|
@ -114,8 +137,6 @@ TabBarButton* TabbedComponent::createTabButton (const String& tabName, const int
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
const Identifier TabbedComponent::deleteComponentId ("deleteByTabComp_");
|
||||
|
||||
void TabbedComponent::clearTabs()
|
||||
{
|
||||
if (panelComponent != 0)
|
||||
|
|
@ -128,12 +149,7 @@ void TabbedComponent::clearTabs()
|
|||
tabs->clearTabs();
|
||||
|
||||
for (int i = contentComponents.size(); --i >= 0;)
|
||||
{
|
||||
WeakReference<Component>& c = *contentComponents.getUnchecked (i);
|
||||
|
||||
if (c != 0 && (bool) c->getProperties() [deleteComponentId])
|
||||
delete c.get();
|
||||
}
|
||||
TabbedComponentHelpers::deleteIfNecessary (contentComponents.getReference (i));
|
||||
|
||||
contentComponents.clear();
|
||||
}
|
||||
|
|
@ -144,10 +160,10 @@ void TabbedComponent::addTab (const String& tabName,
|
|||
const bool deleteComponentWhenNotNeeded,
|
||||
const int insertIndex)
|
||||
{
|
||||
contentComponents.insert (insertIndex, new WeakReference<Component> (contentComponent));
|
||||
contentComponents.insert (insertIndex, WeakReference<Component> (contentComponent));
|
||||
|
||||
if (contentComponent != 0)
|
||||
contentComponent->getProperties().set (deleteComponentId, deleteComponentWhenNotNeeded);
|
||||
if (deleteComponentWhenNotNeeded && contentComponent != 0)
|
||||
contentComponent->getProperties().set (TabbedComponentHelpers::deleteComponentId, true);
|
||||
|
||||
tabs->addTab (tabName, tabBackgroundColour, insertIndex);
|
||||
}
|
||||
|
|
@ -159,13 +175,9 @@ void TabbedComponent::setTabName (const int tabIndex, const String& newName)
|
|||
|
||||
void TabbedComponent::removeTab (const int tabIndex)
|
||||
{
|
||||
WeakReference<Component>* c = contentComponents [tabIndex];
|
||||
|
||||
if (c != 0)
|
||||
if (isPositiveAndBelow (tabIndex, contentComponents.size()))
|
||||
{
|
||||
if ((bool) ((*c)->getProperties() [deleteComponentId]))
|
||||
delete c->get();
|
||||
|
||||
TabbedComponentHelpers::deleteIfNecessary (contentComponents.getReference (tabIndex));
|
||||
contentComponents.remove (tabIndex);
|
||||
tabs->removeTab (tabIndex);
|
||||
}
|
||||
|
|
@ -183,8 +195,7 @@ const StringArray TabbedComponent::getTabNames() const
|
|||
|
||||
Component* TabbedComponent::getTabContentComponent (const int tabIndex) const throw()
|
||||
{
|
||||
WeakReference<Component>* const c = contentComponents [tabIndex];
|
||||
return c != 0 ? *c : 0;
|
||||
return contentComponents [tabIndex];
|
||||
}
|
||||
|
||||
const Colour TabbedComponent::getTabBackgroundColour (const int tabIndex) const throw()
|
||||
|
|
@ -215,99 +226,62 @@ const String TabbedComponent::getCurrentTabName() const
|
|||
return tabs->getCurrentTabName();
|
||||
}
|
||||
|
||||
void TabbedComponent::setOutline (int thickness)
|
||||
void TabbedComponent::setOutline (const int thickness)
|
||||
{
|
||||
outlineThickness = thickness;
|
||||
resized();
|
||||
repaint();
|
||||
}
|
||||
|
||||
void TabbedComponent::setIndent (const int indentThickness)
|
||||
{
|
||||
edgeIndent = indentThickness;
|
||||
resized();
|
||||
repaint();
|
||||
}
|
||||
|
||||
void TabbedComponent::paint (Graphics& g)
|
||||
{
|
||||
g.fillAll (findColour (backgroundColourId));
|
||||
|
||||
const TabbedButtonBar::Orientation o = getOrientation();
|
||||
Rectangle<int> content (getLocalBounds());
|
||||
BorderSize outline (outlineThickness);
|
||||
TabbedComponentHelpers::getTabArea (content, outline, getOrientation(), tabDepth);
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int r = getWidth();
|
||||
int b = getHeight();
|
||||
|
||||
if (o == TabbedButtonBar::TabsAtTop)
|
||||
y += tabDepth;
|
||||
else if (o == TabbedButtonBar::TabsAtBottom)
|
||||
b -= tabDepth;
|
||||
else if (o == TabbedButtonBar::TabsAtLeft)
|
||||
x += tabDepth;
|
||||
else if (o == TabbedButtonBar::TabsAtRight)
|
||||
r -= tabDepth;
|
||||
|
||||
g.reduceClipRegion (x, y, r - x, b - y);
|
||||
g.reduceClipRegion (content);
|
||||
g.fillAll (tabs->getTabBackgroundColour (getCurrentTabIndex()));
|
||||
|
||||
if (outlineThickness > 0)
|
||||
{
|
||||
if (o == TabbedButtonBar::TabsAtTop)
|
||||
--y;
|
||||
else if (o == TabbedButtonBar::TabsAtBottom)
|
||||
++b;
|
||||
else if (o == TabbedButtonBar::TabsAtLeft)
|
||||
--x;
|
||||
else if (o == TabbedButtonBar::TabsAtRight)
|
||||
++r;
|
||||
RectangleList rl (content);
|
||||
rl.subtract (outline.subtractedFrom (content));
|
||||
|
||||
g.setColour (findColour (outlineColourId));
|
||||
g.drawRect (x, y, r - x, b - y, outlineThickness);
|
||||
g.reduceClipRegion (rl);
|
||||
g.fillAll (findColour (outlineColourId));
|
||||
}
|
||||
}
|
||||
|
||||
void TabbedComponent::resized()
|
||||
{
|
||||
const TabbedButtonBar::Orientation o = getOrientation();
|
||||
const int indent = edgeIndent + outlineThickness;
|
||||
BorderSize indents (indent);
|
||||
Rectangle<int> content (getLocalBounds());
|
||||
BorderSize outline (outlineThickness);
|
||||
|
||||
if (o == TabbedButtonBar::TabsAtTop)
|
||||
{
|
||||
tabs->setBounds (0, 0, getWidth(), tabDepth);
|
||||
indents.setTop (tabDepth + edgeIndent);
|
||||
}
|
||||
else if (o == TabbedButtonBar::TabsAtBottom)
|
||||
{
|
||||
tabs->setBounds (0, getHeight() - tabDepth, getWidth(), tabDepth);
|
||||
indents.setBottom (tabDepth + edgeIndent);
|
||||
}
|
||||
else if (o == TabbedButtonBar::TabsAtLeft)
|
||||
{
|
||||
tabs->setBounds (0, 0, tabDepth, getHeight());
|
||||
indents.setLeft (tabDepth + edgeIndent);
|
||||
}
|
||||
else if (o == TabbedButtonBar::TabsAtRight)
|
||||
{
|
||||
tabs->setBounds (getWidth() - tabDepth, 0, tabDepth, getHeight());
|
||||
indents.setRight (tabDepth + edgeIndent);
|
||||
}
|
||||
|
||||
const Rectangle<int> bounds (indents.subtractedFrom (getLocalBounds()));
|
||||
tabs->setBounds (TabbedComponentHelpers::getTabArea (content, outline, getOrientation(), tabDepth));
|
||||
content = BorderSize (edgeIndent).subtractedFrom (outline.subtractedFrom (content));
|
||||
|
||||
for (int i = contentComponents.size(); --i >= 0;)
|
||||
if (*contentComponents.getUnchecked (i) != 0)
|
||||
(*contentComponents.getUnchecked (i))->setBounds (bounds);
|
||||
if (contentComponents.getReference (i) != 0)
|
||||
contentComponents.getReference (i)->setBounds (content);
|
||||
}
|
||||
|
||||
void TabbedComponent::lookAndFeelChanged()
|
||||
{
|
||||
for (int i = contentComponents.size(); --i >= 0;)
|
||||
if (*contentComponents.getUnchecked (i) != 0)
|
||||
(*contentComponents.getUnchecked (i))->lookAndFeelChanged();
|
||||
if (contentComponents.getReference (i) != 0)
|
||||
contentComponents.getReference (i)->lookAndFeelChanged();
|
||||
}
|
||||
|
||||
void TabbedComponent::changeCallback (const int newCurrentTabIndex,
|
||||
const String& newTabName)
|
||||
void TabbedComponent::changeCallback (const int newCurrentTabIndex, const String& newTabName)
|
||||
{
|
||||
if (panelComponent != 0)
|
||||
{
|
||||
|
|
@ -337,12 +311,8 @@ void TabbedComponent::changeCallback (const int newCurrentTabIndex,
|
|||
currentTabChanged (newCurrentTabIndex, newTabName);
|
||||
}
|
||||
|
||||
void TabbedComponent::currentTabChanged (const int, const String&)
|
||||
{
|
||||
}
|
||||
void TabbedComponent::currentTabChanged (const int, const String&) {}
|
||||
void TabbedComponent::popupMenuClickOnTab (const int, const String&) {}
|
||||
|
||||
void TabbedComponent::popupMenuClickOnTab (const int, const String&)
|
||||
{
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -214,8 +214,6 @@ public:
|
|||
|
||||
protected:
|
||||
//==============================================================================
|
||||
ScopedPointer<TabbedButtonBar> tabs;
|
||||
|
||||
/** This creates one of the tab buttons.
|
||||
|
||||
If you need to use custom tab components, you can override this method and
|
||||
|
|
@ -223,15 +221,18 @@ protected:
|
|||
*/
|
||||
virtual TabBarButton* createTabButton (const String& tabName, int tabIndex);
|
||||
|
||||
/** @internal */
|
||||
ScopedPointer<TabbedButtonBar> tabs;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
OwnedArray <WeakReference<Component> > contentComponents;
|
||||
Array <WeakReference<Component> > contentComponents;
|
||||
WeakReference<Component> panelComponent;
|
||||
int tabDepth;
|
||||
int outlineThickness, edgeIndent;
|
||||
static const Identifier deleteComponentId;
|
||||
|
||||
friend class TabCompButtonBar;
|
||||
class ButtonBar;
|
||||
friend class ButtonBar;
|
||||
void changeCallback (int newCurrentTabIndex, const String& newTabName);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TabbedComponent);
|
||||
|
|
|
|||
|
|
@ -121,6 +121,12 @@ bool RelativeCoordinatePositionerBase::addCoordinate (const RelativeCoordinate&
|
|||
return registerListeners (coord.getExpression());
|
||||
}
|
||||
|
||||
bool RelativeCoordinatePositionerBase::addPoint (const RelativePoint& point)
|
||||
{
|
||||
const bool ok = addCoordinate (point.x);
|
||||
return addCoordinate (point.y) && ok;
|
||||
}
|
||||
|
||||
bool RelativeCoordinatePositionerBase::registerListeners (const Expression& e)
|
||||
{
|
||||
bool ok = true;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#ifndef __JUCE_RELATIVECOORDINATEPOSITIONER_JUCEHEADER__
|
||||
#define __JUCE_RELATIVECOORDINATEPOSITIONER_JUCEHEADER__
|
||||
|
||||
#include "juce_RelativeCoordinate.h"
|
||||
#include "juce_RelativePoint.h"
|
||||
#include "juce_MarkerList.h"
|
||||
#include "../juce_Component.h"
|
||||
|
||||
|
|
@ -54,9 +54,10 @@ public:
|
|||
|
||||
void apply();
|
||||
|
||||
protected:
|
||||
bool addCoordinate (const RelativeCoordinate& coord);
|
||||
bool addPoint (const RelativePoint& point);
|
||||
|
||||
protected:
|
||||
virtual bool registerCoordinates() = 0;
|
||||
virtual void applyToComponentBounds() = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,11 @@ const AffineTransform RelativeParallelogram::resetToPerpendicular (Expression::E
|
|||
corners[2].getX(), corners[2].getY(), newBottomLeft.getX(), newBottomLeft.getY());
|
||||
}
|
||||
|
||||
bool RelativeParallelogram::isDynamic() const
|
||||
{
|
||||
return topLeft.isDynamic() || topRight.isDynamic() || bottomLeft.isDynamic();
|
||||
}
|
||||
|
||||
bool RelativeParallelogram::operator== (const RelativeParallelogram& other) const throw()
|
||||
{
|
||||
return topLeft == other.topLeft && topRight == other.topRight && bottomLeft == other.bottomLeft;
|
||||
|
|
@ -130,4 +135,11 @@ const Point<float> RelativeParallelogram::getPointForInternalCoord (const Point<
|
|||
+ Line<float> (Point<float>(), corners[2] - corners[0]).getPointAlongLine (point.getY());
|
||||
}
|
||||
|
||||
const Rectangle<float> RelativeParallelogram::getBoundingBox (const Point<float>* const p) throw()
|
||||
{
|
||||
const Point<float> points[] = { p[0], p[1], p[2], p[1] + (p[2] - p[0]) };
|
||||
return Rectangle<float>::findAreaContainingPoints (points, 4);
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -51,12 +51,14 @@ public:
|
|||
const Rectangle<float> getBounds (Expression::EvaluationContext* coordFinder) const;
|
||||
void getPath (Path& path, Expression::EvaluationContext* coordFinder) const;
|
||||
const AffineTransform resetToPerpendicular (Expression::EvaluationContext* coordFinder);
|
||||
bool isDynamic() const;
|
||||
|
||||
bool operator== (const RelativeParallelogram& other) const throw();
|
||||
bool operator!= (const RelativeParallelogram& other) const throw();
|
||||
|
||||
static const Point<float> getInternalCoordForPoint (const Point<float>* parallelogramCorners, Point<float> point) throw();
|
||||
static const Point<float> getPointForInternalCoord (const Point<float>* parallelogramCorners, const Point<float>& internalPoint) throw();
|
||||
static const Rectangle<float> getBoundingBox (const Point<float>* parallelogramCorners) throw();
|
||||
|
||||
//==============================================================================
|
||||
RelativePoint topLeft, topRight, bottomLeft;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "../../components/juce_Component.h"
|
||||
#include "../../components/positioning/juce_RelativeCoordinate.h"
|
||||
#include "../../components/positioning/juce_RelativeCoordinatePositioner.h"
|
||||
#include "../../../containers/juce_ValueTree.h"
|
||||
#include "../../components/layout/juce_ComponentBuilder.h"
|
||||
class DrawableComposite;
|
||||
|
|
@ -215,6 +216,27 @@ protected:
|
|||
|
||||
Point<int> originRelativeToComponent;
|
||||
|
||||
#ifndef DOXYGEN
|
||||
/** Internal utility class used by Drawables. */
|
||||
template <class DrawableType>
|
||||
class Positioner : public RelativeCoordinatePositionerBase
|
||||
{
|
||||
public:
|
||||
Positioner (DrawableType& component_)
|
||||
: RelativeCoordinatePositionerBase (component_),
|
||||
owner (component_)
|
||||
{}
|
||||
|
||||
bool registerCoordinates() { return owner.registerCoordinates (*this); }
|
||||
void applyToComponentBounds() { owner.recalculateCoordinates (this); }
|
||||
|
||||
private:
|
||||
DrawableType& owner;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Positioner);
|
||||
};
|
||||
#endif
|
||||
|
||||
private:
|
||||
void nonConstDraw (Graphics& g, float opacity, const AffineTransform& transform);
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,11 @@ DrawableComposite::~DrawableComposite()
|
|||
deleteAllChildren();
|
||||
}
|
||||
|
||||
Drawable* DrawableComposite::createCopy() const
|
||||
{
|
||||
return new DrawableComposite (*this);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const Rectangle<float> DrawableComposite::getDrawableBounds() const
|
||||
{
|
||||
|
|
@ -98,13 +103,26 @@ void DrawableComposite::setContentArea (const RelativeRectangle& newArea)
|
|||
markersX.setMarker (contentRightMarkerName, newArea.right);
|
||||
markersY.setMarker (contentTopMarkerName, newArea.top);
|
||||
markersY.setMarker (contentBottomMarkerName, newArea.bottom);
|
||||
refreshTransformFromBounds();
|
||||
}
|
||||
|
||||
void DrawableComposite::setBoundingBox (const RelativeParallelogram& newBoundingBox)
|
||||
void DrawableComposite::setBoundingBox (const RelativeParallelogram& newBounds)
|
||||
{
|
||||
bounds = newBoundingBox;
|
||||
refreshTransformFromBounds();
|
||||
if (bounds != newBounds)
|
||||
{
|
||||
bounds = newBounds;
|
||||
|
||||
if (bounds.isDynamic())
|
||||
{
|
||||
Drawable::Positioner<DrawableComposite>* const p = new Drawable::Positioner<DrawableComposite> (*this);
|
||||
setPositioner (p);
|
||||
p->apply();
|
||||
}
|
||||
else
|
||||
{
|
||||
setPositioner (0);
|
||||
recalculateCoordinates (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableComposite::resetBoundingBoxToContentArea()
|
||||
|
|
@ -127,12 +145,19 @@ void DrawableComposite::resetContentAreaAndBoundingBoxToFitChildren()
|
|||
resetBoundingBoxToContentArea();
|
||||
}
|
||||
|
||||
void DrawableComposite::refreshTransformFromBounds()
|
||||
bool DrawableComposite::registerCoordinates (RelativeCoordinatePositionerBase& positioner)
|
||||
{
|
||||
bool ok = positioner.addPoint (bounds.topLeft);
|
||||
ok = positioner.addPoint (bounds.topRight) && ok;
|
||||
return positioner.addPoint (bounds.bottomLeft) && ok;
|
||||
}
|
||||
|
||||
void DrawableComposite::recalculateCoordinates (Expression::EvaluationContext* context)
|
||||
{
|
||||
Point<float> resolved[3];
|
||||
bounds.resolveThreePoints (resolved, getParent());
|
||||
bounds.resolveThreePoints (resolved, context);
|
||||
|
||||
const Rectangle<float> content (getContentArea().resolve (getParent()));
|
||||
const Rectangle<float> content (getContentArea().resolve (context));
|
||||
|
||||
AffineTransform t (AffineTransform::fromTargetPoints (content.getX(), content.getY(), resolved[0].getX(), resolved[0].getY(),
|
||||
content.getRight(), content.getY(), resolved[1].getX(), resolved[1].getY(),
|
||||
|
|
@ -212,27 +237,6 @@ const char* const DrawableComposite::contentRightMarkerName = "right";
|
|||
const char* const DrawableComposite::contentTopMarkerName = "top";
|
||||
const char* const DrawableComposite::contentBottomMarkerName = "bottom";
|
||||
|
||||
//==============================================================================
|
||||
const Expression DrawableComposite::getSymbolValue (const String& symbol, const String& member) const
|
||||
{
|
||||
jassert (member.isEmpty()) // the only symbols available in a Drawable are markers.
|
||||
|
||||
const MarkerList::Marker* m = markersX.getMarker (symbol);
|
||||
|
||||
if (m == 0)
|
||||
m = markersY.getMarker (symbol);
|
||||
|
||||
if (m != 0)
|
||||
return m->position.getExpression();
|
||||
|
||||
throw Expression::EvaluationError (symbol, member);
|
||||
}
|
||||
|
||||
Drawable* DrawableComposite::createCopy() const
|
||||
{
|
||||
return new DrawableComposite (*this);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const Identifier DrawableComposite::valueTreeType ("Group");
|
||||
|
||||
|
|
@ -321,16 +325,12 @@ void DrawableComposite::refreshFromValueTree (const ValueTree& tree, ComponentBu
|
|||
const ValueTreeWrapper wrapper (tree);
|
||||
setComponentID (wrapper.getID());
|
||||
|
||||
const RelativeParallelogram newBounds (wrapper.getBoundingBox());
|
||||
if (bounds != newBounds)
|
||||
bounds = newBounds;
|
||||
|
||||
wrapper.getMarkerList (true).applyTo (markersX);
|
||||
wrapper.getMarkerList (false).applyTo (markersY);
|
||||
|
||||
builder.updateChildComponents (*this, wrapper.getChildList());
|
||||
setBoundingBox (wrapper.getBoundingBox());
|
||||
|
||||
refreshTransformFromBounds();
|
||||
builder.updateChildComponents (*this, wrapper.getChildList());
|
||||
}
|
||||
|
||||
const ValueTree DrawableComposite::createValueTree (ComponentBuilder::ImageProvider* imageProvider) const
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@
|
|||
|
||||
@see Drawable
|
||||
*/
|
||||
class JUCE_API DrawableComposite : public Drawable,
|
||||
public Expression::EvaluationContext
|
||||
class JUCE_API DrawableComposite : public Drawable//,
|
||||
// public Expression::EvaluationContext
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
|
|
@ -107,8 +107,6 @@ public:
|
|||
/** @internal */
|
||||
static const Identifier valueTreeType;
|
||||
/** @internal */
|
||||
const Expression getSymbolValue (const String& symbol, const String& member) const;
|
||||
/** @internal */
|
||||
const Rectangle<float> getDrawableBounds() const;
|
||||
/** @internal */
|
||||
void childBoundsChanged (Component*);
|
||||
|
|
@ -151,7 +149,10 @@ private:
|
|||
MarkerList markersX, markersY;
|
||||
bool updateBoundsReentrant;
|
||||
|
||||
void refreshTransformFromBounds();
|
||||
friend class Drawable::Positioner<DrawableComposite>;
|
||||
bool registerCoordinates (RelativeCoordinatePositionerBase&);
|
||||
void recalculateCoordinates (Expression::EvaluationContext*);
|
||||
|
||||
void updateBoundsToFitChildren();
|
||||
|
||||
DrawableComposite& operator= (const DrawableComposite&);
|
||||
|
|
|
|||
|
|
@ -58,17 +58,14 @@ DrawableImage::~DrawableImage()
|
|||
void DrawableImage::setImage (const Image& imageToUse)
|
||||
{
|
||||
image = imageToUse;
|
||||
|
||||
setBounds (imageToUse.getBounds());
|
||||
|
||||
if (image.isValid())
|
||||
{
|
||||
bounds.topLeft = RelativePoint (Point<float> (0.0f, 0.0f));
|
||||
bounds.topRight = RelativePoint (Point<float> ((float) image.getWidth(), 0.0f));
|
||||
bounds.bottomLeft = RelativePoint (Point<float> (0.0f, (float) image.getHeight()));
|
||||
}
|
||||
bounds.topLeft = RelativePoint (Point<float> (0.0f, 0.0f));
|
||||
bounds.topRight = RelativePoint (Point<float> ((float) image.getWidth(), 0.0f));
|
||||
bounds.bottomLeft = RelativePoint (Point<float> (0.0f, (float) image.getHeight()));
|
||||
recalculateCoordinates (0);
|
||||
|
||||
refreshTransformFromBounds();
|
||||
repaint();
|
||||
}
|
||||
|
||||
void DrawableImage::setOpacity (const float newOpacity)
|
||||
|
|
@ -83,17 +80,38 @@ void DrawableImage::setOverlayColour (const Colour& newOverlayColour)
|
|||
|
||||
void DrawableImage::setBoundingBox (const RelativeParallelogram& newBounds)
|
||||
{
|
||||
bounds = newBounds;
|
||||
refreshTransformFromBounds();
|
||||
if (bounds != newBounds)
|
||||
{
|
||||
bounds = newBounds;
|
||||
|
||||
if (bounds.isDynamic())
|
||||
{
|
||||
Drawable::Positioner<DrawableImage>* const p = new Drawable::Positioner<DrawableImage> (*this);
|
||||
setPositioner (p);
|
||||
p->apply();
|
||||
}
|
||||
else
|
||||
{
|
||||
setPositioner (0);
|
||||
recalculateCoordinates (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void DrawableImage::refreshTransformFromBounds()
|
||||
bool DrawableImage::registerCoordinates (RelativeCoordinatePositionerBase& positioner)
|
||||
{
|
||||
if (! image.isNull())
|
||||
bool ok = positioner.addPoint (bounds.topLeft);
|
||||
ok = positioner.addPoint (bounds.topRight) && ok;
|
||||
return positioner.addPoint (bounds.bottomLeft) && ok;
|
||||
}
|
||||
|
||||
void DrawableImage::recalculateCoordinates (Expression::EvaluationContext* context)
|
||||
{
|
||||
if (image.isValid())
|
||||
{
|
||||
Point<float> resolved[3];
|
||||
bounds.resolveThreePoints (resolved, getParent());
|
||||
bounds.resolveThreePoints (resolved, context);
|
||||
|
||||
const Point<float> tr (resolved[0] + (resolved[1] - resolved[0]) / (float) image.getWidth());
|
||||
const Point<float> bl (resolved[0] + (resolved[2] - resolved[0]) / (float) image.getHeight());
|
||||
|
|
@ -102,8 +120,10 @@ void DrawableImage::refreshTransformFromBounds()
|
|||
tr.getX(), tr.getY(),
|
||||
bl.getX(), bl.getY()));
|
||||
|
||||
if (! t.isSingularity())
|
||||
setTransform (t);
|
||||
if (t.isSingularity())
|
||||
t = AffineTransform::identity;
|
||||
|
||||
setTransform (t);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -251,12 +271,11 @@ void DrawableImage::refreshFromValueTree (const ValueTree& tree, ComponentBuilde
|
|||
repaint();
|
||||
opacity = newOpacity;
|
||||
overlayColour = newOverlayColour;
|
||||
bounds = newBounds;
|
||||
|
||||
if (image != newImage)
|
||||
setImage (newImage);
|
||||
else
|
||||
refreshTransformFromBounds();
|
||||
|
||||
setBoundingBox (newBounds);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,9 @@ private:
|
|||
Colour overlayColour;
|
||||
RelativeParallelogram bounds;
|
||||
|
||||
void refreshTransformFromBounds();
|
||||
friend class Drawable::Positioner<DrawableImage>;
|
||||
bool registerCoordinates (RelativeCoordinatePositionerBase&);
|
||||
void recalculateCoordinates (Expression::EvaluationContext*);
|
||||
|
||||
DrawableImage& operator= (const DrawableImage&);
|
||||
JUCE_LEAK_DETECTOR (DrawableImage);
|
||||
|
|
|
|||
|
|
@ -40,10 +40,8 @@ DrawablePath::DrawablePath()
|
|||
DrawablePath::DrawablePath (const DrawablePath& other)
|
||||
: DrawableShape (other)
|
||||
{
|
||||
const RelativePointPath* const relativePath = other.getRelativePath();
|
||||
|
||||
if (relativePath != 0)
|
||||
setPath (*relativePath);
|
||||
if (other.relativePath != 0)
|
||||
setPath (*other.relativePath);
|
||||
else
|
||||
setPath (other.path);
|
||||
}
|
||||
|
|
@ -74,15 +72,10 @@ const Path& DrawablePath::getStrokePath() const
|
|||
return strokePath;
|
||||
}
|
||||
|
||||
bool DrawablePath::rebuildPath (Path&) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void DrawablePath::applyRelativePath (const RelativePointPath& relativePath)
|
||||
void DrawablePath::applyRelativePath (const RelativePointPath& newRelativePath, Expression::EvaluationContext* context)
|
||||
{
|
||||
Path newPath;
|
||||
relativePath.createPath (newPath, 0);
|
||||
newRelativePath.createPath (newPath, context);
|
||||
|
||||
if (path != newPath)
|
||||
{
|
||||
|
|
@ -95,9 +88,8 @@ void DrawablePath::applyRelativePath (const RelativePointPath& relativePath)
|
|||
class DrawablePath::RelativePositioner : public RelativeCoordinatePositionerBase
|
||||
{
|
||||
public:
|
||||
RelativePositioner (DrawablePath& component_, const RelativePointPath& path_)
|
||||
RelativePositioner (DrawablePath& component_)
|
||||
: RelativeCoordinatePositionerBase (component_),
|
||||
path (path_),
|
||||
owner (component_)
|
||||
{
|
||||
}
|
||||
|
|
@ -106,6 +98,9 @@ public:
|
|||
{
|
||||
bool ok = true;
|
||||
|
||||
jassert (owner.relativePath != 0);
|
||||
const RelativePointPath& path = *owner.relativePath;
|
||||
|
||||
for (int i = 0; i < path.elements.size(); ++i)
|
||||
{
|
||||
RelativePointPath::ElementBase* const e = path.elements.getUnchecked(i);
|
||||
|
|
@ -114,10 +109,7 @@ public:
|
|||
RelativePoint* const points = e->getControlPoints (numPoints);
|
||||
|
||||
for (int j = numPoints; --j >= 0;)
|
||||
{
|
||||
ok = addCoordinate (points[j].x) && ok;
|
||||
ok = addCoordinate (points[j].y) && ok;
|
||||
}
|
||||
ok = addPoint (points[j]) && ok;
|
||||
}
|
||||
|
||||
return ok;
|
||||
|
|
@ -125,39 +117,33 @@ public:
|
|||
|
||||
void applyToComponentBounds()
|
||||
{
|
||||
owner.applyRelativePath (path);
|
||||
jassert (owner.relativePath != 0);
|
||||
owner.applyRelativePath (*owner.relativePath, this);
|
||||
}
|
||||
|
||||
const RelativePointPath path;
|
||||
|
||||
private:
|
||||
DrawablePath& owner;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativePositioner);
|
||||
};
|
||||
|
||||
const RelativePointPath* DrawablePath::getRelativePath() const
|
||||
{
|
||||
RelativePositioner* current = dynamic_cast <RelativePositioner*> (getPositioner());
|
||||
return current != 0 ? &(current->path) : 0;
|
||||
}
|
||||
|
||||
void DrawablePath::setPath (const RelativePointPath& newRelativePath)
|
||||
{
|
||||
if (newRelativePath.containsAnyDynamicPoints())
|
||||
{
|
||||
const RelativePointPath* current = getRelativePath();
|
||||
|
||||
if (current == 0 || newRelativePath != *current)
|
||||
if (relativePath == 0 || newRelativePath != *relativePath)
|
||||
{
|
||||
RelativePositioner* const p = new RelativePositioner (*this, newRelativePath);
|
||||
relativePath = new RelativePointPath (newRelativePath);
|
||||
|
||||
RelativePositioner* const p = new RelativePositioner (*this);
|
||||
setPositioner (p);
|
||||
p->apply();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
applyRelativePath (newRelativePath);
|
||||
relativePath = 0;
|
||||
applyRelativePath (newRelativePath, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -313,26 +299,26 @@ const RelativePoint DrawablePath::ValueTreeWrapper::Element::getEndPoint() const
|
|||
return RelativePoint();
|
||||
}
|
||||
|
||||
float DrawablePath::ValueTreeWrapper::Element::getLength (Expression::EvaluationContext* nameFinder) const
|
||||
float DrawablePath::ValueTreeWrapper::Element::getLength (Expression::EvaluationContext* context) const
|
||||
{
|
||||
const Identifier i (state.getType());
|
||||
|
||||
if (i == lineToElement || i == closeSubPathElement)
|
||||
return getEndPoint().resolve (nameFinder).getDistanceFrom (getStartPoint().resolve (nameFinder));
|
||||
return getEndPoint().resolve (context).getDistanceFrom (getStartPoint().resolve (context));
|
||||
|
||||
if (i == cubicToElement)
|
||||
{
|
||||
Path p;
|
||||
p.startNewSubPath (getStartPoint().resolve (nameFinder));
|
||||
p.cubicTo (getControlPoint (0).resolve (nameFinder), getControlPoint (1).resolve (nameFinder), getControlPoint (2).resolve (nameFinder));
|
||||
p.startNewSubPath (getStartPoint().resolve (context));
|
||||
p.cubicTo (getControlPoint (0).resolve (context), getControlPoint (1).resolve (context), getControlPoint (2).resolve (context));
|
||||
return p.getLength();
|
||||
}
|
||||
|
||||
if (i == quadraticToElement)
|
||||
{
|
||||
Path p;
|
||||
p.startNewSubPath (getStartPoint().resolve (nameFinder));
|
||||
p.quadraticTo (getControlPoint (0).resolve (nameFinder), getControlPoint (1).resolve (nameFinder));
|
||||
p.startNewSubPath (getStartPoint().resolve (context));
|
||||
p.quadraticTo (getControlPoint (0).resolve (context), getControlPoint (1).resolve (context));
|
||||
return p.getLength();
|
||||
}
|
||||
|
||||
|
|
@ -364,7 +350,7 @@ void DrawablePath::ValueTreeWrapper::Element::convertToLine (UndoManager* undoMa
|
|||
}
|
||||
}
|
||||
|
||||
void DrawablePath::ValueTreeWrapper::Element::convertToCubic (Expression::EvaluationContext* nameFinder, UndoManager* undoManager)
|
||||
void DrawablePath::ValueTreeWrapper::Element::convertToCubic (Expression::EvaluationContext* context, UndoManager* undoManager)
|
||||
{
|
||||
const Identifier i (state.getType());
|
||||
|
||||
|
|
@ -375,8 +361,8 @@ void DrawablePath::ValueTreeWrapper::Element::convertToCubic (Expression::Evalua
|
|||
|
||||
const RelativePoint start (getStartPoint());
|
||||
const RelativePoint end (getEndPoint());
|
||||
const Point<float> startResolved (start.resolve (nameFinder));
|
||||
const Point<float> endResolved (end.resolve (nameFinder));
|
||||
const Point<float> startResolved (start.resolve (context));
|
||||
const Point<float> endResolved (end.resolve (context));
|
||||
e.setControlPoint (0, startResolved + (endResolved - startResolved) * 0.3f, undoManager);
|
||||
e.setControlPoint (1, startResolved + (endResolved - startResolved) * 0.7f, undoManager);
|
||||
e.setControlPoint (2, end, undoManager);
|
||||
|
|
@ -421,7 +407,7 @@ namespace DrawablePathHelpers
|
|||
}
|
||||
}
|
||||
|
||||
float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext* nameFinder) const
|
||||
float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext* context) const
|
||||
{
|
||||
using namespace DrawablePathHelpers;
|
||||
const Identifier type (state.getType());
|
||||
|
|
@ -431,7 +417,7 @@ float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Po
|
|||
{
|
||||
RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getControlPoint (1)), rp4 (getEndPoint());
|
||||
|
||||
const Point<float> points[] = { rp1.resolve (nameFinder), rp2.resolve (nameFinder), rp3.resolve (nameFinder), rp4.resolve (nameFinder) };
|
||||
const Point<float> points[] = { rp1.resolve (context), rp2.resolve (context), rp3.resolve (context), rp4.resolve (context) };
|
||||
|
||||
float bestDistance = std::numeric_limits<float>::max();
|
||||
|
||||
|
|
@ -451,7 +437,7 @@ float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Po
|
|||
else if (type == quadraticToElement)
|
||||
{
|
||||
RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getEndPoint());
|
||||
const Point<float> points[] = { rp1.resolve (nameFinder), rp2.resolve (nameFinder), rp3.resolve (nameFinder) };
|
||||
const Point<float> points[] = { rp1.resolve (context), rp2.resolve (context), rp3.resolve (context) };
|
||||
|
||||
float bestDistance = std::numeric_limits<float>::max();
|
||||
|
||||
|
|
@ -471,24 +457,24 @@ float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Po
|
|||
else if (type == lineToElement)
|
||||
{
|
||||
RelativePoint rp1 (getStartPoint()), rp2 (getEndPoint());
|
||||
const Line<float> line (rp1.resolve (nameFinder), rp2.resolve (nameFinder));
|
||||
const Line<float> line (rp1.resolve (context), rp2.resolve (context));
|
||||
bestProp = line.findNearestProportionalPositionTo (targetPoint);
|
||||
}
|
||||
|
||||
return bestProp;
|
||||
}
|
||||
|
||||
ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<float>& targetPoint, Expression::EvaluationContext* nameFinder, UndoManager* undoManager)
|
||||
ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<float>& targetPoint, Expression::EvaluationContext* context, UndoManager* undoManager)
|
||||
{
|
||||
ValueTree newTree;
|
||||
const Identifier type (state.getType());
|
||||
|
||||
if (type == cubicToElement)
|
||||
{
|
||||
float bestProp = findProportionAlongLine (targetPoint, nameFinder);
|
||||
float bestProp = findProportionAlongLine (targetPoint, context);
|
||||
|
||||
RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getControlPoint (1)), rp4 (getEndPoint());
|
||||
const Point<float> points[] = { rp1.resolve (nameFinder), rp2.resolve (nameFinder), rp3.resolve (nameFinder), rp4.resolve (nameFinder) };
|
||||
const Point<float> points[] = { rp1.resolve (context), rp2.resolve (context), rp3.resolve (context), rp4.resolve (context) };
|
||||
|
||||
const Point<float> mid1 (points[0] + (points[1] - points[0]) * bestProp),
|
||||
mid2 (points[1] + (points[2] - points[1]) * bestProp),
|
||||
|
|
@ -513,10 +499,10 @@ ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<floa
|
|||
}
|
||||
else if (type == quadraticToElement)
|
||||
{
|
||||
float bestProp = findProportionAlongLine (targetPoint, nameFinder);
|
||||
float bestProp = findProportionAlongLine (targetPoint, context);
|
||||
|
||||
RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getEndPoint());
|
||||
const Point<float> points[] = { rp1.resolve (nameFinder), rp2.resolve (nameFinder), rp3.resolve (nameFinder) };
|
||||
const Point<float> points[] = { rp1.resolve (context), rp2.resolve (context), rp3.resolve (context) };
|
||||
|
||||
const Point<float> mid1 (points[0] + (points[1] - points[0]) * bestProp),
|
||||
mid2 (points[1] + (points[2] - points[1]) * bestProp);
|
||||
|
|
@ -536,7 +522,7 @@ ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<floa
|
|||
else if (type == lineToElement)
|
||||
{
|
||||
RelativePoint rp1 (getStartPoint()), rp2 (getEndPoint());
|
||||
const Line<float> line (rp1.resolve (nameFinder), rp2.resolve (nameFinder));
|
||||
const Line<float> line (rp1.resolve (context), rp2.resolve (context));
|
||||
const Point<float> newPoint (line.findNearestPointTo (targetPoint));
|
||||
|
||||
setControlPoint (0, newPoint, undoManager);
|
||||
|
|
@ -564,15 +550,8 @@ void DrawablePath::refreshFromValueTree (const ValueTree& tree, ComponentBuilder
|
|||
ValueTreeWrapper v (tree);
|
||||
setComponentID (v.getID());
|
||||
|
||||
if (refreshFillTypes (v, getParent(), builder.getImageProvider()))
|
||||
repaint();
|
||||
|
||||
const PathStrokeType newStroke (v.getStrokeType());
|
||||
if (strokeType != newStroke)
|
||||
{
|
||||
strokeType = newStroke;
|
||||
strokeChanged();
|
||||
}
|
||||
refreshFillTypes (v, builder.getImageProvider());
|
||||
setStrokeType (v.getStrokeType());
|
||||
|
||||
RelativePointPath newRelativePath;
|
||||
v.writeTo (newRelativePath);
|
||||
|
|
@ -587,17 +566,10 @@ const ValueTree DrawablePath::createValueTree (ComponentBuilder::ImageProvider*
|
|||
v.setID (getComponentID());
|
||||
writeTo (v, imageProvider, 0);
|
||||
|
||||
const RelativePointPath* const relativePath = getRelativePath();
|
||||
|
||||
if (relativePath != 0)
|
||||
{
|
||||
v.readFrom (*relativePath, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
RelativePointPath rp (path);
|
||||
v.readFrom (rp, 0);
|
||||
}
|
||||
v.readFrom (RelativePointPath (path), 0);
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,24 +97,24 @@ public:
|
|||
int getNumControlPoints() const throw();
|
||||
|
||||
const RelativePoint getControlPoint (int index) const;
|
||||
Value getControlPointValue (int index, UndoManager* undoManager) const;
|
||||
Value getControlPointValue (int index, UndoManager*) const;
|
||||
const RelativePoint getStartPoint() const;
|
||||
const RelativePoint getEndPoint() const;
|
||||
void setControlPoint (int index, const RelativePoint& point, UndoManager* undoManager);
|
||||
float getLength (Expression::EvaluationContext* nameFinder) const;
|
||||
void setControlPoint (int index, const RelativePoint& point, UndoManager*);
|
||||
float getLength (Expression::EvaluationContext*) const;
|
||||
|
||||
ValueTreeWrapper getParent() const;
|
||||
Element getPreviousElement() const;
|
||||
|
||||
const String getModeOfEndPoint() const;
|
||||
void setModeOfEndPoint (const String& newMode, UndoManager* undoManager);
|
||||
void setModeOfEndPoint (const String& newMode, UndoManager*);
|
||||
|
||||
void convertToLine (UndoManager* undoManager);
|
||||
void convertToCubic (Expression::EvaluationContext* nameFinder, UndoManager* undoManager);
|
||||
void convertToLine (UndoManager*);
|
||||
void convertToCubic (Expression::EvaluationContext*, UndoManager*);
|
||||
void convertToPathBreak (UndoManager* undoManager);
|
||||
ValueTree insertPoint (const Point<float>& targetPoint, Expression::EvaluationContext* nameFinder, UndoManager* undoManager);
|
||||
ValueTree insertPoint (const Point<float>& targetPoint, Expression::EvaluationContext*, UndoManager*);
|
||||
void removePoint (UndoManager* undoManager);
|
||||
float findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext* nameFinder) const;
|
||||
float findProportionAlongLine (const Point<float>& targetPoint, Expression::EvaluationContext*) const;
|
||||
|
||||
static const Identifier mode, startSubPathElement, closeSubPathElement,
|
||||
lineToElement, quadraticToElement, cubicToElement;
|
||||
|
|
@ -133,15 +133,13 @@ public:
|
|||
static const Identifier nonZeroWinding, point1, point2, point3;
|
||||
};
|
||||
|
||||
protected:
|
||||
bool rebuildPath (Path& path) const;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
ScopedPointer<RelativePointPath> relativePath;
|
||||
|
||||
class RelativePositioner;
|
||||
friend class RelativePositioner;
|
||||
void applyRelativePath (const RelativePointPath& newPath);
|
||||
const RelativePointPath* getRelativePath() const;
|
||||
void applyRelativePath (const RelativePointPath&, Expression::EvaluationContext*);
|
||||
|
||||
DrawablePath& operator= (const DrawablePath&);
|
||||
JUCE_LEAK_DETECTOR (DrawablePath);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ BEGIN_JUCE_NAMESPACE
|
|||
|
||||
#include "juce_DrawableRectangle.h"
|
||||
#include "juce_DrawableComposite.h"
|
||||
#include "../../components/positioning/juce_RelativeCoordinatePositioner.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
DrawableRectangle::DrawableRectangle()
|
||||
|
|
@ -36,7 +38,9 @@ DrawableRectangle::DrawableRectangle()
|
|||
}
|
||||
|
||||
DrawableRectangle::DrawableRectangle (const DrawableRectangle& other)
|
||||
: DrawableShape (other)
|
||||
: DrawableShape (other),
|
||||
bounds (other.bounds),
|
||||
cornerSize (other.cornerSize)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -52,51 +56,72 @@ Drawable* DrawableRectangle::createCopy() const
|
|||
//==============================================================================
|
||||
void DrawableRectangle::setRectangle (const RelativeParallelogram& newBounds)
|
||||
{
|
||||
bounds = newBounds;
|
||||
pathChanged();
|
||||
strokeChanged();
|
||||
if (bounds != newBounds)
|
||||
{
|
||||
bounds = newBounds;
|
||||
rebuildPath();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableRectangle::setCornerSize (const RelativePoint& newSize)
|
||||
{
|
||||
cornerSize = newSize;
|
||||
pathChanged();
|
||||
strokeChanged();
|
||||
if (cornerSize != newSize)
|
||||
{
|
||||
cornerSize = newSize;
|
||||
rebuildPath();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool DrawableRectangle::rebuildPath (Path& path) const
|
||||
void DrawableRectangle::rebuildPath()
|
||||
{
|
||||
if (bounds.isDynamic() || cornerSize.isDynamic())
|
||||
{
|
||||
Drawable::Positioner<DrawableRectangle>* const p = new Drawable::Positioner<DrawableRectangle> (*this);
|
||||
setPositioner (p);
|
||||
p->apply();
|
||||
}
|
||||
else
|
||||
{
|
||||
setPositioner (0);
|
||||
recalculateCoordinates (0);
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawableRectangle::registerCoordinates (RelativeCoordinatePositionerBase& positioner)
|
||||
{
|
||||
bool ok = positioner.addPoint (bounds.topLeft);
|
||||
ok = positioner.addPoint (bounds.topRight) && ok;
|
||||
ok = positioner.addPoint (bounds.bottomLeft) && ok;
|
||||
return positioner.addPoint (cornerSize) && ok;
|
||||
}
|
||||
|
||||
void DrawableRectangle::recalculateCoordinates (Expression::EvaluationContext* context)
|
||||
{
|
||||
Point<float> points[3];
|
||||
bounds.resolveThreePoints (points, getParent());
|
||||
bounds.resolveThreePoints (points, context);
|
||||
|
||||
const float cornerSizeX = (float) cornerSize.x.resolve (context);
|
||||
const float cornerSizeY = (float) cornerSize.y.resolve (context);
|
||||
|
||||
const float w = Line<float> (points[0], points[1]).getLength();
|
||||
const float h = Line<float> (points[0], points[2]).getLength();
|
||||
|
||||
const float cornerSizeX = (float) cornerSize.x.resolve (getParent());
|
||||
const float cornerSizeY = (float) cornerSize.y.resolve (getParent());
|
||||
|
||||
path.clear();
|
||||
Path newPath;
|
||||
|
||||
if (cornerSizeX > 0 && cornerSizeY > 0)
|
||||
path.addRoundedRectangle (0, 0, w, h, cornerSizeX, cornerSizeY);
|
||||
newPath.addRoundedRectangle (0, 0, w, h, cornerSizeX, cornerSizeY);
|
||||
else
|
||||
path.addRectangle (0, 0, w, h);
|
||||
newPath.addRectangle (0, 0, w, h);
|
||||
|
||||
path.applyTransform (AffineTransform::fromTargetPoints (0, 0, points[0].getX(), points[0].getY(),
|
||||
w, 0, points[1].getX(), points[1].getY(),
|
||||
0, h, points[2].getX(), points[2].getY()));
|
||||
return true;
|
||||
}
|
||||
newPath.applyTransform (AffineTransform::fromTargetPoints (0, 0, points[0].getX(), points[0].getY(),
|
||||
w, 0, points[1].getX(), points[1].getY(),
|
||||
0, h, points[2].getX(), points[2].getY()));
|
||||
|
||||
const AffineTransform DrawableRectangle::calculateTransform() const
|
||||
{
|
||||
Point<float> resolved[3];
|
||||
bounds.resolveThreePoints (resolved, getParent());
|
||||
|
||||
return AffineTransform::fromTargetPoints (resolved[0].getX(), resolved[0].getY(),
|
||||
resolved[1].getX(), resolved[1].getY(),
|
||||
resolved[2].getX(), resolved[2].getY());
|
||||
if (path != newPath)
|
||||
{
|
||||
path.swapWithPath (newPath);
|
||||
pathChanged();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -148,22 +173,10 @@ void DrawableRectangle::refreshFromValueTree (const ValueTree& tree, ComponentBu
|
|||
ValueTreeWrapper v (tree);
|
||||
setComponentID (v.getID());
|
||||
|
||||
if (refreshFillTypes (v, getParent(), builder.getImageProvider()))
|
||||
repaint();
|
||||
|
||||
RelativeParallelogram newBounds (v.getRectangle());
|
||||
|
||||
const PathStrokeType newStroke (v.getStrokeType());
|
||||
const RelativePoint newCornerSize (v.getCornerSize());
|
||||
|
||||
if (strokeType != newStroke || newBounds != bounds || newCornerSize != cornerSize)
|
||||
{
|
||||
repaint();
|
||||
bounds = newBounds;
|
||||
strokeType = newStroke;
|
||||
cornerSize = newCornerSize;
|
||||
pathChanged();
|
||||
}
|
||||
refreshFillTypes (v, builder.getImageProvider());
|
||||
setStrokeType (v.getStrokeType());
|
||||
setRectangle (v.getRectangle());
|
||||
setCornerSize (v.getCornerSize());
|
||||
}
|
||||
|
||||
const ValueTree DrawableRectangle::createValueTree (ComponentBuilder::ImageProvider* imageProvider) const
|
||||
|
|
|
|||
|
|
@ -79,25 +79,25 @@ public:
|
|||
ValueTreeWrapper (const ValueTree& state);
|
||||
|
||||
const RelativeParallelogram getRectangle() const;
|
||||
void setRectangle (const RelativeParallelogram& newBounds, UndoManager* undoManager);
|
||||
void setRectangle (const RelativeParallelogram& newBounds, UndoManager*);
|
||||
|
||||
void setCornerSize (const RelativePoint& cornerSize, UndoManager* undoManager);
|
||||
void setCornerSize (const RelativePoint& cornerSize, UndoManager*);
|
||||
const RelativePoint getCornerSize() const;
|
||||
Value getCornerSizeValue (UndoManager* undoManager) const;
|
||||
Value getCornerSizeValue (UndoManager*) const;
|
||||
|
||||
static const Identifier topLeft, topRight, bottomLeft, cornerSize;
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
/** @internal */
|
||||
bool rebuildPath (Path& path) const;
|
||||
|
||||
private:
|
||||
friend class Drawable::Positioner<DrawableRectangle>;
|
||||
|
||||
RelativeParallelogram bounds;
|
||||
RelativePoint cornerSize;
|
||||
|
||||
const AffineTransform calculateTransform() const;
|
||||
void rebuildPath();
|
||||
bool registerCoordinates (RelativeCoordinatePositionerBase&);
|
||||
void recalculateCoordinates (Expression::EvaluationContext*);
|
||||
|
||||
DrawableRectangle& operator= (const DrawableRectangle&);
|
||||
JUCE_LEAK_DETECTOR (DrawableRectangle);
|
||||
|
|
|
|||
|
|
@ -50,20 +50,89 @@ DrawableShape::~DrawableShape()
|
|||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class DrawableShape::RelativePositioner : public RelativeCoordinatePositionerBase
|
||||
{
|
||||
public:
|
||||
RelativePositioner (DrawableShape& component_, const DrawableShape::RelativeFillType& fill_, bool isMainFill_)
|
||||
: RelativeCoordinatePositionerBase (component_),
|
||||
owner (component_),
|
||||
fill (fill_),
|
||||
isMainFill (isMainFill_)
|
||||
{
|
||||
}
|
||||
|
||||
bool registerCoordinates()
|
||||
{
|
||||
bool ok = addPoint (fill.gradientPoint1);
|
||||
ok = addPoint (fill.gradientPoint2) && ok;
|
||||
return addPoint (fill.gradientPoint3) && ok;
|
||||
}
|
||||
|
||||
void applyToComponentBounds()
|
||||
{
|
||||
if (isMainFill ? owner.mainFill.recalculateCoords (this)
|
||||
: owner.strokeFill.recalculateCoords (this))
|
||||
owner.repaint();
|
||||
}
|
||||
|
||||
private:
|
||||
DrawableShape& owner;
|
||||
const DrawableShape::RelativeFillType fill;
|
||||
const bool isMainFill;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativePositioner);
|
||||
};
|
||||
|
||||
void DrawableShape::setFill (const FillType& newFill)
|
||||
{
|
||||
mainFill = newFill;
|
||||
setFill (RelativeFillType (newFill));
|
||||
}
|
||||
|
||||
void DrawableShape::setStrokeFill (const FillType& newFill)
|
||||
{
|
||||
strokeFill = newFill;
|
||||
setStrokeFill (RelativeFillType (newFill));
|
||||
}
|
||||
|
||||
void DrawableShape::setFillInternal (RelativeFillType& fill, const RelativeFillType& newFill,
|
||||
ScopedPointer<RelativeCoordinatePositionerBase>& positioner)
|
||||
{
|
||||
if (fill != newFill)
|
||||
{
|
||||
fill = newFill;
|
||||
positioner = 0;
|
||||
|
||||
if (fill.isDynamic())
|
||||
{
|
||||
positioner = new RelativePositioner (*this, fill, true);
|
||||
positioner->apply();
|
||||
}
|
||||
else
|
||||
{
|
||||
fill.recalculateCoords (0);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
strokeType = newStrokeType;
|
||||
strokeChanged();
|
||||
if (strokeType != newStrokeType)
|
||||
{
|
||||
strokeType = newStrokeType;
|
||||
strokeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableShape::setStrokeThickness (const float newThickness)
|
||||
|
|
@ -73,42 +142,19 @@ void DrawableShape::setStrokeThickness (const float newThickness)
|
|||
|
||||
bool DrawableShape::isStrokeVisible() const throw()
|
||||
{
|
||||
return strokeType.getStrokeThickness() > 0.0f && ! strokeFill.isInvisible();
|
||||
return strokeType.getStrokeThickness() > 0.0f && ! strokeFill.fill.isInvisible();
|
||||
}
|
||||
|
||||
bool DrawableShape::refreshFillTypes (const FillAndStrokeState& newState,
|
||||
Expression::EvaluationContext* /*nameFinder*/,
|
||||
ComponentBuilder::ImageProvider* imageProvider)
|
||||
void DrawableShape::refreshFillTypes (const FillAndStrokeState& newState, ComponentBuilder::ImageProvider* imageProvider)
|
||||
{
|
||||
bool hasChanged = false;
|
||||
|
||||
{
|
||||
const FillType f (newState.getMainFill (getParent(), imageProvider));
|
||||
|
||||
if (mainFill != f)
|
||||
{
|
||||
hasChanged = true;
|
||||
mainFill = f;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const FillType f (newState.getStrokeFill (getParent(), imageProvider));
|
||||
|
||||
if (strokeFill != f)
|
||||
{
|
||||
hasChanged = true;
|
||||
strokeFill = f;
|
||||
}
|
||||
}
|
||||
|
||||
return hasChanged;
|
||||
setFill (newState.getFill (FillAndStrokeState::fill, imageProvider));
|
||||
setStrokeFill (newState.getFill (FillAndStrokeState::stroke, imageProvider));
|
||||
}
|
||||
|
||||
void DrawableShape::writeTo (FillAndStrokeState& state, ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager) const
|
||||
{
|
||||
state.setMainFill (mainFill, 0, 0, 0, imageProvider, undoManager);
|
||||
state.setStrokeFill (strokeFill, 0, 0, 0, imageProvider, undoManager);
|
||||
state.setFill (FillAndStrokeState::fill, mainFill, imageProvider, undoManager);
|
||||
state.setFill (FillAndStrokeState::stroke, strokeFill, imageProvider, undoManager);
|
||||
state.setStrokeType (strokeType, undoManager);
|
||||
}
|
||||
|
||||
|
|
@ -117,19 +163,18 @@ void DrawableShape::paint (Graphics& g)
|
|||
{
|
||||
transformContextToCorrectOrigin (g);
|
||||
|
||||
g.setFillType (mainFill);
|
||||
g.setFillType (mainFill.fill);
|
||||
g.fillPath (path);
|
||||
|
||||
if (isStrokeVisible())
|
||||
{
|
||||
g.setFillType (strokeFill);
|
||||
g.setFillType (strokeFill.fill);
|
||||
g.fillPath (strokePath);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableShape::pathChanged()
|
||||
{
|
||||
rebuildPath (path);
|
||||
strokeChanged();
|
||||
}
|
||||
|
||||
|
|
@ -159,6 +204,183 @@ bool DrawableShape::hitTest (int x, int y) const
|
|||
|| (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.getX() + g.point2.getY() - g.point1.getY(),
|
||||
g.point1.getY() + g.point1.getX() - g.point2.getX())
|
||||
.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::EvaluationContext* context)
|
||||
{
|
||||
if (fill.isGradient())
|
||||
{
|
||||
const Point<float> g1 (gradientPoint1.resolve (context));
|
||||
const Point<float> g2 (gradientPoint2.resolve (context));
|
||||
AffineTransform t;
|
||||
|
||||
ColourGradient& g = *fill.gradient;
|
||||
|
||||
if (g.isRadial)
|
||||
{
|
||||
const Point<float> g3 (gradientPoint3.resolve (context));
|
||||
const Point<float> g3Source (g1.getX() + g2.getY() - g1.getY(),
|
||||
g1.getY() + g1.getX() - g2.getX());
|
||||
|
||||
t = AffineTransform::fromTargetPoints (g1.getX(), g1.getY(), g1.getX(), g1.getY(),
|
||||
g2.getX(), g2.getY(), g2.getX(), g2.getY(),
|
||||
g3Source.getX(), g3Source.getY(), g3.getX(), g3.getY());
|
||||
}
|
||||
|
||||
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 != 0)
|
||||
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 (Colour (colourString.isEmpty() ? (uint32) 0xff000000
|
||||
: (uint32) colourString.getHexValue32()));
|
||||
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 ((uint32) colourSteps[i * 2 + 1].getHexValue32()));
|
||||
|
||||
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 != 0)
|
||||
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");
|
||||
|
|
@ -181,50 +403,28 @@ DrawableShape::FillAndStrokeState::FillAndStrokeState (const ValueTree& state_)
|
|||
{
|
||||
}
|
||||
|
||||
const FillType DrawableShape::FillAndStrokeState::getMainFill (Expression::EvaluationContext* nameFinder,
|
||||
ComponentBuilder::ImageProvider* imageProvider) const
|
||||
const DrawableShape::RelativeFillType DrawableShape::FillAndStrokeState::getFill (const Identifier& fillOrStrokeType, ComponentBuilder::ImageProvider* imageProvider) const
|
||||
{
|
||||
return readFillType (state.getChildWithName (fill), 0, 0, 0, nameFinder, imageProvider);
|
||||
DrawableShape::RelativeFillType f;
|
||||
f.readFrom (state.getChildWithName (fillOrStrokeType), imageProvider);
|
||||
return f;
|
||||
}
|
||||
|
||||
ValueTree DrawableShape::FillAndStrokeState::getMainFillState()
|
||||
ValueTree DrawableShape::FillAndStrokeState::getFillState (const Identifier& fillOrStrokeType)
|
||||
{
|
||||
ValueTree v (state.getChildWithName (fill));
|
||||
ValueTree v (state.getChildWithName (fillOrStrokeType));
|
||||
if (v.isValid())
|
||||
return v;
|
||||
|
||||
setMainFill (Colours::black, 0, 0, 0, 0, 0);
|
||||
return getMainFillState();
|
||||
setFill (fillOrStrokeType, FillType (Colours::black), 0, 0);
|
||||
return getFillState (fillOrStrokeType);
|
||||
}
|
||||
|
||||
void DrawableShape::FillAndStrokeState::setMainFill (const FillType& newFill, const RelativePoint* gp1, const RelativePoint* gp2,
|
||||
const RelativePoint* gp3, ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager)
|
||||
void DrawableShape::FillAndStrokeState::setFill (const Identifier& fillOrStrokeType, const RelativeFillType& newFill,
|
||||
ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager)
|
||||
{
|
||||
ValueTree v (state.getOrCreateChildWithName (fill, undoManager));
|
||||
writeFillType (v, newFill, gp1, gp2, gp3, imageProvider, undoManager);
|
||||
}
|
||||
|
||||
const FillType DrawableShape::FillAndStrokeState::getStrokeFill (Expression::EvaluationContext* nameFinder,
|
||||
ComponentBuilder::ImageProvider* imageProvider) const
|
||||
{
|
||||
return readFillType (state.getChildWithName (stroke), 0, 0, 0, nameFinder, imageProvider);
|
||||
}
|
||||
|
||||
ValueTree DrawableShape::FillAndStrokeState::getStrokeFillState()
|
||||
{
|
||||
ValueTree v (state.getChildWithName (stroke));
|
||||
if (v.isValid())
|
||||
return v;
|
||||
|
||||
setStrokeFill (Colours::black, 0, 0, 0, 0, 0);
|
||||
return getStrokeFillState();
|
||||
}
|
||||
|
||||
void DrawableShape::FillAndStrokeState::setStrokeFill (const FillType& newFill, const RelativePoint* gp1, const RelativePoint* gp2,
|
||||
const RelativePoint* gp3, ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager)
|
||||
{
|
||||
ValueTree v (state.getOrCreateChildWithName (stroke, undoManager));
|
||||
writeFillType (v, newFill, gp1, gp2, gp3, imageProvider, undoManager);
|
||||
ValueTree v (state.getOrCreateChildWithName (fillOrStrokeType, undoManager));
|
||||
newFill.writeTo (v, imageProvider, undoManager);
|
||||
}
|
||||
|
||||
const PathStrokeType DrawableShape::FillAndStrokeState::getStrokeType() const
|
||||
|
|
@ -250,121 +450,4 @@ void DrawableShape::FillAndStrokeState::setStrokeType (const PathStrokeType& new
|
|||
? "butt" : (newStrokeType.getEndStyle() == PathStrokeType::square ? "square" : "round"), undoManager);
|
||||
}
|
||||
|
||||
const FillType DrawableShape::FillAndStrokeState::readFillType (const ValueTree& v, RelativePoint* const gp1, RelativePoint* const gp2, RelativePoint* const gp3,
|
||||
Expression::EvaluationContext* const nameFinder, ComponentBuilder::ImageProvider* imageProvider)
|
||||
{
|
||||
const String newType (v[type].toString());
|
||||
|
||||
if (newType == "solid")
|
||||
{
|
||||
const String colourString (v [colour].toString());
|
||||
return FillType (Colour (colourString.isEmpty() ? (uint32) 0xff000000
|
||||
: (uint32) colourString.getHexValue32()));
|
||||
}
|
||||
else if (newType == "gradient")
|
||||
{
|
||||
RelativePoint p1 (v [gradientPoint1]), p2 (v [gradientPoint2]), p3 (v [gradientPoint3]);
|
||||
|
||||
ColourGradient g;
|
||||
|
||||
if (gp1 != 0) *gp1 = p1;
|
||||
if (gp2 != 0) *gp2 = p2;
|
||||
if (gp3 != 0) *gp3 = p3;
|
||||
|
||||
g.point1 = p1.resolve (nameFinder);
|
||||
g.point2 = p2.resolve (nameFinder);
|
||||
g.isRadial = v[radial];
|
||||
|
||||
StringArray colourSteps;
|
||||
colourSteps.addTokens (v[colours].toString(), false);
|
||||
|
||||
for (int i = 0; i < colourSteps.size() / 2; ++i)
|
||||
g.addColour (colourSteps[i * 2].getDoubleValue(),
|
||||
Colour ((uint32) colourSteps[i * 2 + 1].getHexValue32()));
|
||||
|
||||
FillType fillType (g);
|
||||
|
||||
if (g.isRadial)
|
||||
{
|
||||
const Point<float> point3 (p3.resolve (nameFinder));
|
||||
const Point<float> point3Source (g.point1.getX() + g.point2.getY() - g.point1.getY(),
|
||||
g.point1.getY() + g.point1.getX() - g.point2.getX());
|
||||
|
||||
fillType.transform = AffineTransform::fromTargetPoints (g.point1.getX(), g.point1.getY(), g.point1.getX(), g.point1.getY(),
|
||||
g.point2.getX(), g.point2.getY(), g.point2.getX(), g.point2.getY(),
|
||||
point3Source.getX(), point3Source.getY(), point3.getX(), point3.getY());
|
||||
}
|
||||
|
||||
return fillType;
|
||||
}
|
||||
else if (newType == "image")
|
||||
{
|
||||
Image im;
|
||||
if (imageProvider != 0)
|
||||
im = imageProvider->getImageForIdentifier (v[imageId]);
|
||||
|
||||
FillType f (im, AffineTransform::identity);
|
||||
f.setOpacity ((float) v.getProperty (imageOpacity, 1.0f));
|
||||
return f;
|
||||
}
|
||||
|
||||
jassert (! v.isValid());
|
||||
return FillType();
|
||||
}
|
||||
|
||||
namespace DrawableShapeHelpers
|
||||
{
|
||||
const Point<float> calcThirdGradientPoint (const FillType& fillType)
|
||||
{
|
||||
const ColourGradient& g = *fillType.gradient;
|
||||
const Point<float> point3Source (g.point1.getX() + g.point2.getY() - g.point1.getY(),
|
||||
g.point1.getY() + g.point1.getX() - g.point2.getX());
|
||||
|
||||
return point3Source.transformedBy (fillType.transform);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableShape::FillAndStrokeState::writeFillType (ValueTree& v, const FillType& fillType,
|
||||
const RelativePoint* const gp1, const RelativePoint* const gp2, const RelativePoint* gp3,
|
||||
ComponentBuilder::ImageProvider* imageProvider, UndoManager* const undoManager)
|
||||
{
|
||||
if (fillType.isColour())
|
||||
{
|
||||
v.setProperty (type, "solid", undoManager);
|
||||
v.setProperty (colour, String::toHexString ((int) fillType.colour.getARGB()), undoManager);
|
||||
}
|
||||
else if (fillType.isGradient())
|
||||
{
|
||||
v.setProperty (type, "gradient", undoManager);
|
||||
v.setProperty (gradientPoint1, gp1 != 0 ? gp1->toString() : fillType.gradient->point1.toString(), undoManager);
|
||||
v.setProperty (gradientPoint2, gp2 != 0 ? gp2->toString() : fillType.gradient->point2.toString(), undoManager);
|
||||
v.setProperty (gradientPoint3, gp3 != 0 ? gp3->toString() : DrawableShapeHelpers::calcThirdGradientPoint (fillType).toString(), undoManager);
|
||||
|
||||
v.setProperty (radial, fillType.gradient->isRadial, undoManager);
|
||||
|
||||
String s;
|
||||
for (int i = 0; i < fillType.gradient->getNumColours(); ++i)
|
||||
s << ' ' << fillType.gradient->getColourPosition (i)
|
||||
<< ' ' << String::toHexString ((int) fillType.gradient->getColour(i).getARGB());
|
||||
|
||||
v.setProperty (colours, s.trimStart(), undoManager);
|
||||
}
|
||||
else if (fillType.isTiledImage())
|
||||
{
|
||||
v.setProperty (type, "image", undoManager);
|
||||
|
||||
if (imageProvider != 0)
|
||||
v.setProperty (imageId, imageProvider->getIdentifierForImage (fillType.image), undoManager);
|
||||
|
||||
if (fillType.getOpacity() < 1.0f)
|
||||
v.setProperty (imageOpacity, fillType.getOpacity(), undoManager);
|
||||
else
|
||||
v.removeProperty (imageOpacity, undoManager);
|
||||
}
|
||||
else
|
||||
{
|
||||
jassertfalse;
|
||||
}
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "juce_Drawable.h"
|
||||
#include "../contexts/juce_FillType.h"
|
||||
#include "../colour/juce_ColourGradient.h"
|
||||
#include "../../components/positioning/juce_RelativePoint.h"
|
||||
#include "../../components/positioning/juce_RelativeCoordinatePositioner.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -50,6 +50,31 @@ public:
|
|||
/** Destructor. */
|
||||
~DrawableShape();
|
||||
|
||||
//==============================================================================
|
||||
/** A FillType wrapper that allows the gradient coordinates to be implemented using RelativePoint.
|
||||
*/
|
||||
class RelativeFillType
|
||||
{
|
||||
public:
|
||||
RelativeFillType();
|
||||
RelativeFillType (const FillType& fill);
|
||||
RelativeFillType (const RelativeFillType&);
|
||||
RelativeFillType& operator= (const RelativeFillType&);
|
||||
|
||||
bool operator== (const RelativeFillType&) const;
|
||||
bool operator!= (const RelativeFillType&) const;
|
||||
|
||||
bool isDynamic() const;
|
||||
bool recalculateCoords (Expression::EvaluationContext* context);
|
||||
|
||||
void writeTo (ValueTree& v, ComponentBuilder::ImageProvider*, UndoManager*) const;
|
||||
bool readFrom (const ValueTree& v, ComponentBuilder::ImageProvider*);
|
||||
|
||||
//==============================================================================
|
||||
FillType fill;
|
||||
RelativePoint gradientPoint1, gradientPoint2, gradientPoint3;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Sets a fill type for the path.
|
||||
This colour is used to fill the path - if you don't want the path to be
|
||||
|
|
@ -60,20 +85,34 @@ public:
|
|||
*/
|
||||
void setFill (const FillType& newFill);
|
||||
|
||||
/** Sets a fill type for the path.
|
||||
This colour is used to fill the path - if you don't want the path to be
|
||||
filled (e.g. if you're just drawing an outline), set this to a transparent
|
||||
colour.
|
||||
|
||||
@see setPath, setStrokeFill
|
||||
*/
|
||||
void setFill (const RelativeFillType& newFill);
|
||||
|
||||
/** Returns the current fill type.
|
||||
@see setFill
|
||||
*/
|
||||
const FillType& getFill() const throw() { return mainFill; }
|
||||
const RelativeFillType& getFill() const throw() { return mainFill; }
|
||||
|
||||
/** Sets the fill type with which the outline will be drawn.
|
||||
@see setFill
|
||||
*/
|
||||
void setStrokeFill (const FillType& newStrokeFill);
|
||||
|
||||
/** Sets the fill type with which the outline will be drawn.
|
||||
@see setFill
|
||||
*/
|
||||
void setStrokeFill (const RelativeFillType& newStrokeFill);
|
||||
|
||||
/** Returns the current stroke fill.
|
||||
@see setStrokeFill
|
||||
*/
|
||||
const FillType& getStrokeFill() const throw() { return strokeFill; }
|
||||
const RelativeFillType& getStrokeFill() const throw() { return strokeFill; }
|
||||
|
||||
/** Changes the properties of the outline that will be drawn around the path.
|
||||
If the stroke has 0 thickness, no stroke will be drawn.
|
||||
|
|
@ -87,7 +126,7 @@ public:
|
|||
void setStrokeThickness (float newThickness);
|
||||
|
||||
/** Returns the current outline style. */
|
||||
const PathStrokeType& getStrokeType() const throw() { return strokeType; }
|
||||
const PathStrokeType& getStrokeType() const throw() { return strokeType; }
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
|
|
@ -96,32 +135,13 @@ public:
|
|||
public:
|
||||
FillAndStrokeState (const ValueTree& state);
|
||||
|
||||
const FillType getMainFill (Expression::EvaluationContext* nameFinder,
|
||||
ComponentBuilder::ImageProvider* imageProvider) const;
|
||||
ValueTree getMainFillState();
|
||||
void setMainFill (const FillType& newFill, const RelativePoint* gradientPoint1,
|
||||
const RelativePoint* gradientPoint2, const RelativePoint* gradientPoint3,
|
||||
ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager);
|
||||
|
||||
const FillType getStrokeFill (Expression::EvaluationContext* nameFinder,
|
||||
ComponentBuilder::ImageProvider* imageProvider) const;
|
||||
ValueTree getStrokeFillState();
|
||||
void setStrokeFill (const FillType& newFill, const RelativePoint* gradientPoint1,
|
||||
const RelativePoint* gradientPoint2, const RelativePoint* gradientPoint3,
|
||||
ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager);
|
||||
ValueTree getFillState (const Identifier& fillOrStrokeType);
|
||||
const RelativeFillType getFill (const Identifier& fillOrStrokeType, ComponentBuilder::ImageProvider*) const;
|
||||
void setFill (const Identifier& fillOrStrokeType, const RelativeFillType& newFill,
|
||||
ComponentBuilder::ImageProvider*, UndoManager*);
|
||||
|
||||
const PathStrokeType getStrokeType() const;
|
||||
void setStrokeType (const PathStrokeType& newStrokeType, UndoManager* undoManager);
|
||||
|
||||
static const FillType readFillType (const ValueTree& v, RelativePoint* gradientPoint1,
|
||||
RelativePoint* gradientPoint2, RelativePoint* gradientPoint3,
|
||||
Expression::EvaluationContext* nameFinder,
|
||||
ComponentBuilder::ImageProvider* imageProvider);
|
||||
|
||||
static void writeFillType (ValueTree& v, const FillType& fillType,
|
||||
const RelativePoint* gradientPoint1, const RelativePoint* gradientPoint2,
|
||||
const RelativePoint* gradientPoint3, ComponentBuilder::ImageProvider* imageProvider,
|
||||
UndoManager* undoManager);
|
||||
void setStrokeType (const PathStrokeType& newStrokeType, UndoManager*);
|
||||
|
||||
static const Identifier type, colour, colours, fill, stroke, path, jointStyle, capStyle, strokeWidth,
|
||||
gradientPoint1, gradientPoint2, gradientPoint3, radial, imageId, imageOpacity;
|
||||
|
|
@ -140,28 +160,24 @@ protected:
|
|||
void pathChanged();
|
||||
/** Called when the cached stroke should be updated. */
|
||||
void strokeChanged();
|
||||
|
||||
/** Implemented by subclasses to regenerate the path. */
|
||||
virtual bool rebuildPath (Path& path) const = 0;
|
||||
|
||||
/** True if there's a stroke with a non-zero thickness and non-transparent colour. */
|
||||
bool isStrokeVisible() const throw();
|
||||
|
||||
/** Updates the details from a FillAndStrokeState object, returning true if something changed. */
|
||||
bool refreshFillTypes (const FillAndStrokeState& newState,
|
||||
Expression::EvaluationContext* nameFinder,
|
||||
ComponentBuilder::ImageProvider* imageProvider);
|
||||
|
||||
void refreshFillTypes (const FillAndStrokeState& newState, ComponentBuilder::ImageProvider*);
|
||||
/** Writes the stroke and fill details to a FillAndStrokeState object. */
|
||||
void writeTo (FillAndStrokeState& state, ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager) const;
|
||||
|
||||
void writeTo (FillAndStrokeState& state, ComponentBuilder::ImageProvider*, UndoManager*) const;
|
||||
|
||||
//==============================================================================
|
||||
PathStrokeType strokeType;
|
||||
Path path, strokePath;
|
||||
|
||||
private:
|
||||
FillType mainFill, strokeFill;
|
||||
class RelativePositioner;
|
||||
RelativeFillType mainFill, strokeFill;
|
||||
ScopedPointer<RelativeCoordinatePositionerBase> mainFillPositioner, strokeFillPositioner;
|
||||
|
||||
void setFillInternal (RelativeFillType& fill, const RelativeFillType& newFill,
|
||||
ScopedPointer<RelativeCoordinatePositionerBase>& positioner);
|
||||
|
||||
DrawableShape& operator= (const DrawableShape&);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -57,38 +57,38 @@ DrawableText::~DrawableText()
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
void DrawableText::refreshBounds()
|
||||
{
|
||||
setBoundsToEnclose (getDrawableBounds());
|
||||
repaint();
|
||||
}
|
||||
|
||||
void DrawableText::setText (const String& newText)
|
||||
{
|
||||
text = newText;
|
||||
refreshBounds();
|
||||
if (text != newText)
|
||||
{
|
||||
text = newText;
|
||||
refreshBounds();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableText::setColour (const Colour& newColour)
|
||||
{
|
||||
colour = newColour;
|
||||
repaint();
|
||||
if (colour != newColour)
|
||||
{
|
||||
colour = newColour;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableText::setFont (const Font& newFont, bool applySizeAndScale)
|
||||
{
|
||||
font = newFont;
|
||||
|
||||
if (applySizeAndScale)
|
||||
if (font != newFont)
|
||||
{
|
||||
Point<float> corners[3];
|
||||
bounds.resolveThreePoints (corners, getParent());
|
||||
font = newFont;
|
||||
|
||||
setFontSizeControlPoint (RelativePoint (RelativeParallelogram::getPointForInternalCoord (corners,
|
||||
Point<float> (font.getHorizontalScale() * font.getHeight(), font.getHeight()))));
|
||||
if (applySizeAndScale)
|
||||
{
|
||||
setFontSizeControlPoint (RelativePoint (RelativeParallelogram::getPointForInternalCoord (resolvedPoints,
|
||||
Point<float> (font.getHorizontalScale() * font.getHeight(), font.getHeight()))));
|
||||
}
|
||||
|
||||
refreshBounds();
|
||||
}
|
||||
|
||||
refreshBounds();
|
||||
}
|
||||
|
||||
void DrawableText::setJustification (const Justification& newJustification)
|
||||
|
|
@ -99,14 +99,74 @@ void DrawableText::setJustification (const Justification& newJustification)
|
|||
|
||||
void DrawableText::setBoundingBox (const RelativeParallelogram& newBounds)
|
||||
{
|
||||
bounds = newBounds;
|
||||
refreshBounds();
|
||||
if (bounds != newBounds)
|
||||
{
|
||||
bounds = newBounds;
|
||||
refreshBounds();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableText::setFontSizeControlPoint (const RelativePoint& newPoint)
|
||||
{
|
||||
fontSizeControlPoint = newPoint;
|
||||
refreshBounds();
|
||||
if (fontSizeControlPoint != newPoint)
|
||||
{
|
||||
fontSizeControlPoint = newPoint;
|
||||
refreshBounds();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableText::refreshBounds()
|
||||
{
|
||||
if (bounds.isDynamic() || fontSizeControlPoint.isDynamic())
|
||||
{
|
||||
Drawable::Positioner<DrawableText>* const p = new Drawable::Positioner<DrawableText> (*this);
|
||||
setPositioner (p);
|
||||
p->apply();
|
||||
}
|
||||
else
|
||||
{
|
||||
setPositioner (0);
|
||||
recalculateCoordinates (0);
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawableText::registerCoordinates (RelativeCoordinatePositionerBase& positioner)
|
||||
{
|
||||
bool ok = positioner.addPoint (bounds.topLeft);
|
||||
ok = positioner.addPoint (bounds.topRight) && ok;
|
||||
ok = positioner.addPoint (bounds.bottomLeft) && ok;
|
||||
return positioner.addPoint (fontSizeControlPoint) && ok;
|
||||
}
|
||||
|
||||
void DrawableText::recalculateCoordinates (Expression::EvaluationContext* context)
|
||||
{
|
||||
bounds.resolveThreePoints (resolvedPoints, context);
|
||||
|
||||
const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength();
|
||||
const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength();
|
||||
|
||||
const Point<float> fontCoords (RelativeParallelogram::getInternalCoordForPoint (resolvedPoints, fontSizeControlPoint.resolve (context)));
|
||||
const float fontHeight = jlimit (0.01f, jmax (0.01f, h), fontCoords.getY());
|
||||
const float fontWidth = jlimit (0.01f, jmax (0.01f, w), fontCoords.getX());
|
||||
|
||||
scaledFont = font;
|
||||
scaledFont.setHeight (fontHeight);
|
||||
scaledFont.setHorizontalScale (fontWidth / fontHeight);
|
||||
|
||||
setBoundsToEnclose (getDrawableBounds());
|
||||
repaint();
|
||||
}
|
||||
|
||||
const AffineTransform DrawableText::getArrangementAndTransform (GlyphArrangement& glyphs) const
|
||||
{
|
||||
const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength();
|
||||
const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength();
|
||||
|
||||
glyphs.addFittedText (scaledFont, text, 0, 0, w, h, justification, 0x100000);
|
||||
|
||||
return AffineTransform::fromTargetPoints (0, 0, resolvedPoints[0].getX(), resolvedPoints[0].getY(),
|
||||
w, 0, resolvedPoints[1].getX(), resolvedPoints[1].getY(),
|
||||
0, h, resolvedPoints[2].getX(), resolvedPoints[2].getY());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -114,32 +174,16 @@ void DrawableText::paint (Graphics& g)
|
|||
{
|
||||
transformContextToCorrectOrigin (g);
|
||||
|
||||
Point<float> points[3];
|
||||
bounds.resolveThreePoints (points, getParent());
|
||||
|
||||
const float w = Line<float> (points[0], points[1]).getLength();
|
||||
const float h = Line<float> (points[0], points[2]).getLength();
|
||||
|
||||
const Point<float> fontCoords (bounds.getInternalCoordForPoint (points, fontSizeControlPoint.resolve (getParent())));
|
||||
const float fontHeight = jlimit (0.01f, jmax (0.01f, h), fontCoords.getY());
|
||||
const float fontWidth = jlimit (0.01f, jmax (0.01f, w), fontCoords.getX());
|
||||
|
||||
Font f (font);
|
||||
f.setHeight (fontHeight);
|
||||
f.setHorizontalScale (fontWidth / fontHeight);
|
||||
|
||||
g.setColour (colour);
|
||||
|
||||
GlyphArrangement ga;
|
||||
ga.addFittedText (f, text, 0, 0, w, h, justification, 0x100000);
|
||||
ga.draw (g, AffineTransform::fromTargetPoints (0, 0, points[0].getX(), points[0].getY(),
|
||||
w, 0, points[1].getX(), points[1].getY(),
|
||||
0, h, points[2].getX(), points[2].getY()));
|
||||
const AffineTransform transform (getArrangementAndTransform (ga));
|
||||
ga.draw (g, transform);
|
||||
}
|
||||
|
||||
const Rectangle<float> DrawableText::getDrawableBounds() const
|
||||
{
|
||||
return bounds.getBounds (getParent());
|
||||
return RelativeParallelogram::getBoundingBox (resolvedPoints);
|
||||
}
|
||||
|
||||
Drawable* DrawableText::createCopy() const
|
||||
|
|
@ -254,7 +298,6 @@ void DrawableText::refreshFromValueTree (const ValueTree& tree, ComponentBuilder
|
|||
if (text != newText || font != newFont || justification != newJustification
|
||||
|| colour != newColour || bounds != newBounds || newFontPoint != fontSizeControlPoint)
|
||||
{
|
||||
repaint();
|
||||
setBoundingBox (newBounds);
|
||||
setFontSizeControlPoint (newFontPoint);
|
||||
setColour (newColour);
|
||||
|
|
|
|||
|
|
@ -134,12 +134,17 @@ private:
|
|||
//==============================================================================
|
||||
RelativeParallelogram bounds;
|
||||
RelativePoint fontSizeControlPoint;
|
||||
Font font;
|
||||
Point<float> resolvedPoints[3];
|
||||
Font font, scaledFont;
|
||||
String text;
|
||||
Colour colour;
|
||||
Justification justification;
|
||||
|
||||
friend class Drawable::Positioner<DrawableText>;
|
||||
bool registerCoordinates (RelativeCoordinatePositionerBase&);
|
||||
void recalculateCoordinates (Expression::EvaluationContext*);
|
||||
void refreshBounds();
|
||||
const AffineTransform getArrangementAndTransform (GlyphArrangement& glyphs) const;
|
||||
|
||||
DrawableText& operator= (const DrawableText&);
|
||||
JUCE_LEAK_DETECTOR (DrawableText);
|
||||
|
|
|
|||
|
|
@ -72,10 +72,6 @@ public:
|
|||
|
||||
const Typeface::Ptr findTypefaceFor (const Font& font)
|
||||
{
|
||||
// (can't initialise defaultFace in the constructor or in getDefaultTypeface() because of recursion).
|
||||
if (defaultFace == 0)
|
||||
defaultFace = LookAndFeel::getDefaultLookAndFeel().getTypefaceForFont (Font());
|
||||
|
||||
const int flags = font.getStyleFlags() & (Font::bold | Font::italic);
|
||||
const String faceName (font.getTypefaceName());
|
||||
|
||||
|
|
@ -114,6 +110,9 @@ public:
|
|||
face.typeface = LookAndFeel::getDefaultLookAndFeel().getTypefaceForFont (font);
|
||||
jassert (face.typeface != 0); // the look and feel must return a typeface!
|
||||
|
||||
if (defaultFace == 0 && font == Font())
|
||||
defaultFace = face.typeface;
|
||||
|
||||
return face.typeface;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
#if JUCE_MAC
|
||||
#if JUCE_MAC
|
||||
static NSImage* createNSImage (const Image& image)
|
||||
{
|
||||
const ScopedAutoReleasePool pool;
|
||||
|
|
@ -111,7 +111,7 @@ public:
|
|||
|
||||
return im;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
CGContextRef context;
|
||||
|
|
@ -120,11 +120,11 @@ public:
|
|||
private:
|
||||
static CGBitmapInfo getCGImageFlags (const Image::PixelFormat& format)
|
||||
{
|
||||
#if JUCE_BIG_ENDIAN
|
||||
#if JUCE_BIG_ENDIAN
|
||||
return format == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) : kCGBitmapByteOrderDefault;
|
||||
#else
|
||||
#else
|
||||
return format == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little) : kCGBitmapByteOrderDefault;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CoreGraphicsImage);
|
||||
|
|
@ -132,11 +132,11 @@ private:
|
|||
|
||||
Image::SharedImage* Image::SharedImage::createNativeImage (PixelFormat format, int width, int height, bool clearImage)
|
||||
{
|
||||
#if USE_COREGRAPHICS_RENDERING
|
||||
#if USE_COREGRAPHICS_RENDERING
|
||||
return new CoreGraphicsImage (format == RGB ? ARGB : format, width, height, clearImage);
|
||||
#else
|
||||
#else
|
||||
return createSoftwareImage (format, width, height, clearImage);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -382,16 +382,16 @@ public:
|
|||
{
|
||||
if (replaceExistingContents)
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
|
||||
CGContextClearRect (context, cgRect);
|
||||
#else
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
|
||||
#else
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
|
||||
if (CGContextDrawLinearGradient == 0) // (just a way of checking whether we're running in 10.5 or later)
|
||||
CGContextClearRect (context, cgRect);
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
CGContextSetBlendMode (context, kCGBlendModeCopy);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
fillCGRect (cgRect, false);
|
||||
CGContextSetBlendMode (context, kCGBlendModeNormal);
|
||||
|
|
@ -467,16 +467,16 @@ public:
|
|||
|
||||
if (fillEntireClipAsTiles)
|
||||
{
|
||||
#if JUCE_IOS
|
||||
#if JUCE_IOS
|
||||
CGContextDrawTiledImage (context, imageRect, image);
|
||||
#else
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
||||
#else
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
||||
// There's a bug in CGContextDrawTiledImage that makes it incredibly slow
|
||||
// if it's doing a transformation - it's quicker to just draw lots of images manually
|
||||
if (CGContextDrawTiledImage != 0 && transform.isOnlyTranslation())
|
||||
CGContextDrawTiledImage (context, imageRect, image);
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
// Fallback to manually doing a tiled fill on 10.4
|
||||
CGRect clip = CGRectIntegral (CGContextGetClipBoundingBox (context));
|
||||
|
|
@ -496,7 +496,7 @@ public:
|
|||
y += ih;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -681,8 +681,7 @@ private:
|
|||
|
||||
CGShadingRef createGradient (const AffineTransform& transform, ColourGradient gradient)
|
||||
{
|
||||
numGradientLookupEntries = gradient.createLookupTable (transform, gradientLookupTable);
|
||||
--numGradientLookupEntries;
|
||||
numGradientLookupEntries = gradient.createLookupTable (transform, gradientLookupTable) - 1;
|
||||
|
||||
CGShadingRef result = 0;
|
||||
CGFunctionRef function = CGFunctionCreate (this, 1, 0, 4, 0, &gradientCallbacks);
|
||||
|
|
@ -803,7 +802,7 @@ const Image juce_loadWithCoreImage (InputStream& input)
|
|||
MemoryBlock data;
|
||||
input.readIntoMemoryBlock (data, -1);
|
||||
|
||||
#if JUCE_IOS
|
||||
#if JUCE_IOS
|
||||
JUCE_AUTORELEASEPOOL
|
||||
UIImage* image = [UIImage imageWithData: [NSData dataWithBytesNoCopy: data.getData()
|
||||
length: data.getSize()
|
||||
|
|
@ -813,7 +812,7 @@ const Image juce_loadWithCoreImage (InputStream& input)
|
|||
{
|
||||
CGImageRef loadedImage = image.CGImage;
|
||||
|
||||
#else
|
||||
#else
|
||||
CGDataProviderRef provider = CGDataProviderCreateWithData (0, data.getData(), data.getSize(), 0);
|
||||
CGImageSourceRef imageSource = CGImageSourceCreateWithDataProvider (provider, 0);
|
||||
CGDataProviderRelease (provider);
|
||||
|
|
@ -822,7 +821,7 @@ const Image juce_loadWithCoreImage (InputStream& input)
|
|||
{
|
||||
CGImageRef loadedImage = CGImageSourceCreateImageAtIndex (imageSource, 0, 0);
|
||||
CFRelease (imageSource);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (loadedImage != 0)
|
||||
{
|
||||
|
|
@ -841,9 +840,9 @@ const Image juce_loadWithCoreImage (InputStream& input)
|
|||
CGContextDrawImage (cgImage->context, CGRectMake (0, 0, image.getWidth(), image.getHeight()), loadedImage);
|
||||
CGContextFlush (cgImage->context);
|
||||
|
||||
#if ! JUCE_IOS
|
||||
#if ! JUCE_IOS
|
||||
CFRelease (loadedImage);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Because it's impossible to create a truly 24-bit CG image, this flag allows a user
|
||||
// to find out whether the file they just loaded the image from had an alpha channel or not.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue