git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
284
deps/juce/modules/juce_gui_basics/positioning/juce_MarkerList.cpp
vendored
Normal file
284
deps/juce/modules/juce_gui_basics/positioning/juce_MarkerList.cpp
vendored
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
MarkerList::MarkerList()
|
||||
{
|
||||
}
|
||||
|
||||
MarkerList::MarkerList (const MarkerList& other)
|
||||
{
|
||||
operator= (other);
|
||||
}
|
||||
|
||||
MarkerList& MarkerList::operator= (const MarkerList& other)
|
||||
{
|
||||
if (other != *this)
|
||||
{
|
||||
markers.clear();
|
||||
markers.addCopiesOf (other.markers);
|
||||
markersHaveChanged();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
MarkerList::~MarkerList()
|
||||
{
|
||||
listeners.call ([this] (Listener& l) { l.markerListBeingDeleted (this); });
|
||||
}
|
||||
|
||||
bool MarkerList::operator== (const MarkerList& other) const noexcept
|
||||
{
|
||||
if (other.markers.size() != markers.size())
|
||||
return false;
|
||||
|
||||
for (int i = markers.size(); --i >= 0;)
|
||||
{
|
||||
const Marker* const m1 = markers.getUnchecked(i);
|
||||
jassert (m1 != nullptr);
|
||||
|
||||
const Marker* const m2 = other.getMarker (m1->name);
|
||||
|
||||
if (m2 == nullptr || *m1 != *m2)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MarkerList::operator!= (const MarkerList& other) const noexcept
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
int MarkerList::getNumMarkers() const noexcept
|
||||
{
|
||||
return markers.size();
|
||||
}
|
||||
|
||||
const MarkerList::Marker* MarkerList::getMarker (const int index) const noexcept
|
||||
{
|
||||
return markers [index];
|
||||
}
|
||||
|
||||
const MarkerList::Marker* MarkerList::getMarker (const String& name) const noexcept
|
||||
{
|
||||
return getMarkerByName (name);
|
||||
}
|
||||
|
||||
MarkerList::Marker* MarkerList::getMarkerByName (const String& name) const noexcept
|
||||
{
|
||||
for (int i = 0; i < markers.size(); ++i)
|
||||
{
|
||||
Marker* const m = markers.getUnchecked(i);
|
||||
|
||||
if (m->name == name)
|
||||
return m;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MarkerList::setMarker (const String& name, const RelativeCoordinate& position)
|
||||
{
|
||||
if (Marker* const m = getMarkerByName (name))
|
||||
{
|
||||
if (m->position != position)
|
||||
{
|
||||
m->position = position;
|
||||
markersHaveChanged();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
markers.add (new Marker (name, position));
|
||||
markersHaveChanged();
|
||||
}
|
||||
|
||||
void MarkerList::removeMarker (const int index)
|
||||
{
|
||||
if (isPositiveAndBelow (index, markers.size()))
|
||||
{
|
||||
markers.remove (index);
|
||||
markersHaveChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void MarkerList::removeMarker (const String& name)
|
||||
{
|
||||
for (int i = 0; i < markers.size(); ++i)
|
||||
{
|
||||
const Marker* const m = markers.getUnchecked(i);
|
||||
|
||||
if (m->name == name)
|
||||
{
|
||||
markers.remove (i);
|
||||
markersHaveChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MarkerList::markersHaveChanged()
|
||||
{
|
||||
listeners.call ([this] (Listener& l) { l.markersChanged (this); });
|
||||
}
|
||||
|
||||
void MarkerList::Listener::markerListBeingDeleted (MarkerList*)
|
||||
{
|
||||
}
|
||||
|
||||
void MarkerList::addListener (Listener* listener)
|
||||
{
|
||||
listeners.add (listener);
|
||||
}
|
||||
|
||||
void MarkerList::removeListener (Listener* listener)
|
||||
{
|
||||
listeners.remove (listener);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
MarkerList::Marker::Marker (const Marker& other)
|
||||
: name (other.name), position (other.position)
|
||||
{
|
||||
}
|
||||
|
||||
MarkerList::Marker::Marker (const String& name_, const RelativeCoordinate& position_)
|
||||
: name (name_), position (position_)
|
||||
{
|
||||
}
|
||||
|
||||
bool MarkerList::Marker::operator== (const Marker& other) const noexcept
|
||||
{
|
||||
return name == other.name && position == other.position;
|
||||
}
|
||||
|
||||
bool MarkerList::Marker::operator!= (const Marker& other) const noexcept
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const Identifier MarkerList::ValueTreeWrapper::markerTag ("Marker");
|
||||
const Identifier MarkerList::ValueTreeWrapper::nameProperty ("name");
|
||||
const Identifier MarkerList::ValueTreeWrapper::posProperty ("position");
|
||||
|
||||
MarkerList::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_)
|
||||
: state (state_)
|
||||
{
|
||||
}
|
||||
|
||||
int MarkerList::ValueTreeWrapper::getNumMarkers() const
|
||||
{
|
||||
return state.getNumChildren();
|
||||
}
|
||||
|
||||
ValueTree MarkerList::ValueTreeWrapper::getMarkerState (int index) const
|
||||
{
|
||||
return state.getChild (index);
|
||||
}
|
||||
|
||||
ValueTree MarkerList::ValueTreeWrapper::getMarkerState (const String& name) const
|
||||
{
|
||||
return state.getChildWithProperty (nameProperty, name);
|
||||
}
|
||||
|
||||
bool MarkerList::ValueTreeWrapper::containsMarker (const ValueTree& marker) const
|
||||
{
|
||||
return marker.isAChildOf (state);
|
||||
}
|
||||
|
||||
MarkerList::Marker MarkerList::ValueTreeWrapper::getMarker (const ValueTree& marker) const
|
||||
{
|
||||
jassert (containsMarker (marker));
|
||||
|
||||
return MarkerList::Marker (marker [nameProperty], RelativeCoordinate (marker [posProperty].toString()));
|
||||
}
|
||||
|
||||
void MarkerList::ValueTreeWrapper::setMarker (const MarkerList::Marker& m, UndoManager* undoManager)
|
||||
{
|
||||
ValueTree marker (state.getChildWithProperty (nameProperty, m.name));
|
||||
|
||||
if (marker.isValid())
|
||||
{
|
||||
marker.setProperty (posProperty, m.position.toString(), undoManager);
|
||||
}
|
||||
else
|
||||
{
|
||||
marker = ValueTree (markerTag);
|
||||
marker.setProperty (nameProperty, m.name, nullptr);
|
||||
marker.setProperty (posProperty, m.position.toString(), nullptr);
|
||||
state.appendChild (marker, undoManager);
|
||||
}
|
||||
}
|
||||
|
||||
void MarkerList::ValueTreeWrapper::removeMarker (const ValueTree& marker, UndoManager* undoManager)
|
||||
{
|
||||
state.removeChild (marker, undoManager);
|
||||
}
|
||||
|
||||
double MarkerList::getMarkerPosition (const Marker& marker, Component* parentComponent) const
|
||||
{
|
||||
if (parentComponent == nullptr)
|
||||
return marker.position.resolve (nullptr);
|
||||
|
||||
RelativeCoordinatePositionerBase::ComponentScope scope (*parentComponent);
|
||||
return marker.position.resolve (&scope);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MarkerList::ValueTreeWrapper::applyTo (MarkerList& markerList)
|
||||
{
|
||||
const int numMarkers = getNumMarkers();
|
||||
|
||||
StringArray updatedMarkers;
|
||||
|
||||
for (int i = 0; i < numMarkers; ++i)
|
||||
{
|
||||
const ValueTree marker (state.getChild (i));
|
||||
const String name (marker [nameProperty].toString());
|
||||
markerList.setMarker (name, RelativeCoordinate (marker [posProperty].toString()));
|
||||
updatedMarkers.add (name);
|
||||
}
|
||||
|
||||
for (int i = markerList.getNumMarkers(); --i >= 0;)
|
||||
if (! updatedMarkers.contains (markerList.getMarker (i)->name))
|
||||
markerList.removeMarker (i);
|
||||
}
|
||||
|
||||
void MarkerList::ValueTreeWrapper::readFrom (const MarkerList& markerList, UndoManager* undoManager)
|
||||
{
|
||||
state.removeAllChildren (undoManager);
|
||||
|
||||
for (int i = 0; i < markerList.getNumMarkers(); ++i)
|
||||
setMarker (*markerList.getMarker(i), undoManager);
|
||||
}
|
||||
|
||||
} // namespace juce
|
195
deps/juce/modules/juce_gui_basics/positioning/juce_MarkerList.h
vendored
Normal file
195
deps/juce/modules/juce_gui_basics/positioning/juce_MarkerList.h
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
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().
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API MarkerList
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an empty marker list. */
|
||||
MarkerList();
|
||||
/** Creates a copy of another marker list. */
|
||||
MarkerList (const MarkerList&);
|
||||
/** Copies another marker list to this one. */
|
||||
MarkerList& operator= (const MarkerList&);
|
||||
/** Destructor. */
|
||||
~MarkerList();
|
||||
|
||||
//==============================================================================
|
||||
/** Represents a marker in a MarkerList. */
|
||||
class JUCE_API Marker
|
||||
{
|
||||
public:
|
||||
/** Creates a copy of another Marker. */
|
||||
Marker (const Marker&);
|
||||
/** 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.
|
||||
|
||||
The expression used to define the coordinate may use the names of other
|
||||
markers, so that markers can be linked in arbitrary ways, but be careful
|
||||
not to create recursive loops of markers whose positions are based on each
|
||||
other! It can also refer to "parent.right" and "parent.bottom" so that you
|
||||
can set markers which are relative to the size of the component that contains
|
||||
them.
|
||||
|
||||
To resolve the coordinate, you can use the MarkerList::getMarkerPosition() method.
|
||||
*/
|
||||
RelativeCoordinate position;
|
||||
|
||||
/** Returns true if both the names and positions of these two markers match. */
|
||||
bool operator== (const Marker&) const noexcept;
|
||||
/** Returns true if either the name or position of these two markers differ. */
|
||||
bool operator!= (const Marker&) const noexcept;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the number of markers in the list. */
|
||||
int getNumMarkers() const noexcept;
|
||||
|
||||
/** Returns one of the markers in the list, by its index. */
|
||||
const Marker* getMarker (int index) const noexcept;
|
||||
|
||||
/** Returns a named marker, or nullptr if no such name is found.
|
||||
Note that name comparisons are case-sensitive.
|
||||
*/
|
||||
const Marker* getMarker (const String& name) const noexcept;
|
||||
|
||||
/** Evaluates the given marker and returns its absolute position.
|
||||
The parent component must be supplied in case the marker's expression refers to
|
||||
the size of its parent component.
|
||||
*/
|
||||
double getMarkerPosition (const Marker& marker, Component* parentComponent) const;
|
||||
|
||||
/** 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&) const noexcept;
|
||||
/** Returns true if not all the markers in these two lists match exactly. */
|
||||
bool operator!= (const MarkerList&) const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
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() = default;
|
||||
|
||||
/** 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();
|
||||
|
||||
//==============================================================================
|
||||
/** A base class for objects that want to provide a MarkerList. */
|
||||
struct MarkerListHolder
|
||||
{
|
||||
virtual ~MarkerListHolder() = default;
|
||||
|
||||
/** Objects can implement this method to provide a MarkerList. */
|
||||
virtual MarkerList* getMarkers (bool xAxis) = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Forms a wrapper around a ValueTree that can be used for storing a MarkerList. */
|
||||
class ValueTreeWrapper
|
||||
{
|
||||
public:
|
||||
ValueTreeWrapper (const ValueTree& state);
|
||||
|
||||
ValueTree& getState() noexcept { return state; }
|
||||
int getNumMarkers() const;
|
||||
ValueTree getMarkerState (int index) const;
|
||||
ValueTree getMarkerState (const String& name) const;
|
||||
bool containsMarker (const ValueTree& state) 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;
|
||||
|
||||
Marker* getMarkerByName (const String& name) const noexcept;
|
||||
|
||||
JUCE_LEAK_DETECTOR (MarkerList)
|
||||
};
|
||||
|
||||
} // namespace juce
|
153
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.cpp
vendored
Normal file
153
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.cpp
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
const String RelativeCoordinate::Strings::parent ("parent");
|
||||
const String RelativeCoordinate::Strings::left ("left");
|
||||
const String RelativeCoordinate::Strings::right ("right");
|
||||
const String RelativeCoordinate::Strings::top ("top");
|
||||
const String RelativeCoordinate::Strings::bottom ("bottom");
|
||||
const String RelativeCoordinate::Strings::x ("x");
|
||||
const String RelativeCoordinate::Strings::y ("y");
|
||||
const String RelativeCoordinate::Strings::width ("width");
|
||||
const String RelativeCoordinate::Strings::height ("height");
|
||||
|
||||
RelativeCoordinate::StandardStrings::Type RelativeCoordinate::StandardStrings::getTypeOf (const String& s) noexcept
|
||||
{
|
||||
if (s == Strings::left) return left;
|
||||
if (s == Strings::right) return right;
|
||||
if (s == Strings::top) return top;
|
||||
if (s == Strings::bottom) return bottom;
|
||||
if (s == Strings::x) return x;
|
||||
if (s == Strings::y) return y;
|
||||
if (s == Strings::width) return width;
|
||||
if (s == Strings::height) return height;
|
||||
if (s == Strings::parent) return parent;
|
||||
return unknown;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
RelativeCoordinate::RelativeCoordinate()
|
||||
{
|
||||
}
|
||||
|
||||
RelativeCoordinate::RelativeCoordinate (const Expression& term_)
|
||||
: term (term_)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeCoordinate::RelativeCoordinate (const RelativeCoordinate& other)
|
||||
: term (other.term)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeCoordinate& RelativeCoordinate::operator= (const RelativeCoordinate& other)
|
||||
{
|
||||
term = other.term;
|
||||
return *this;
|
||||
}
|
||||
|
||||
RelativeCoordinate::RelativeCoordinate (RelativeCoordinate&& other) noexcept
|
||||
: term (std::move (other.term))
|
||||
{
|
||||
}
|
||||
|
||||
RelativeCoordinate& RelativeCoordinate::operator= (RelativeCoordinate&& other) noexcept
|
||||
{
|
||||
term = std::move (other.term);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RelativeCoordinate::RelativeCoordinate (const double absoluteDistanceFromOrigin)
|
||||
: term (absoluteDistanceFromOrigin)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeCoordinate::RelativeCoordinate (const String& s)
|
||||
{
|
||||
String error;
|
||||
term = Expression (s, error);
|
||||
}
|
||||
|
||||
RelativeCoordinate::~RelativeCoordinate()
|
||||
{
|
||||
}
|
||||
|
||||
bool RelativeCoordinate::operator== (const RelativeCoordinate& other) const noexcept
|
||||
{
|
||||
return term.toString() == other.term.toString();
|
||||
}
|
||||
|
||||
bool RelativeCoordinate::operator!= (const RelativeCoordinate& other) const noexcept
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
double RelativeCoordinate::resolve (const Expression::Scope* scope) const
|
||||
{
|
||||
if (scope != nullptr)
|
||||
return term.evaluate (*scope);
|
||||
|
||||
return term.evaluate();
|
||||
}
|
||||
|
||||
bool RelativeCoordinate::isRecursive (const Expression::Scope* scope) const
|
||||
{
|
||||
String error;
|
||||
|
||||
if (scope != nullptr)
|
||||
term.evaluate (*scope, error);
|
||||
else
|
||||
term.evaluate (Expression::Scope(), error);
|
||||
|
||||
return error.isNotEmpty();
|
||||
}
|
||||
|
||||
void RelativeCoordinate::moveToAbsolute (double newPos, const Expression::Scope* scope)
|
||||
{
|
||||
if (scope != nullptr)
|
||||
{
|
||||
term = term.adjustedToGiveNewResult (newPos, *scope);
|
||||
}
|
||||
else
|
||||
{
|
||||
Expression::Scope defaultScope;
|
||||
term = term.adjustedToGiveNewResult (newPos, defaultScope);
|
||||
}
|
||||
}
|
||||
|
||||
bool RelativeCoordinate::isDynamic() const
|
||||
{
|
||||
return term.usesAnySymbols();
|
||||
}
|
||||
|
||||
String RelativeCoordinate::toString() const
|
||||
{
|
||||
return term.toString();
|
||||
}
|
||||
|
||||
} // namespace juce
|
181
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.h
vendored
Normal file
181
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.h
vendored
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Expresses a coordinate as a dynamically evaluated expression.
|
||||
|
||||
When using relative coordinates to position components, the following symbols are available:
|
||||
- "left", "right", "top", "bottom" refer to the position of those edges in this component, so
|
||||
e.g. for a component whose width is always 100, you might set the right edge to the "left + 100".
|
||||
- "[id].left", "[id].right", "[id].top", "[id].bottom", "[id].width", "[id].height", where [id] is
|
||||
the identifier of one of this component's siblings. A component's identifier is set with
|
||||
Component::setComponentID(). So for example if you want your component to always be 50 pixels to the
|
||||
right of the one called "xyz", you could set your left edge to be "xyz.right + 50".
|
||||
- Instead of an [id], you can use the name "parent" to refer to this component's parent. Like
|
||||
any other component, these values are relative to their component's parent, so "parent.right" won't be
|
||||
very useful for positioning a component because it refers to a position with the parent's parent.. but
|
||||
"parent.width" can be used for setting positions relative to the parent's size. E.g. to make a 10x10
|
||||
component which remains 1 pixel away from its parent's bottom-right, you could use
|
||||
"right - 10, bottom - 10, parent.width - 1, parent.height - 1".
|
||||
- The name of one of the parent component's markers can also be used as a symbol. For markers to be
|
||||
used, the parent component must implement its Component::getMarkers() method, and return at least one
|
||||
valid MarkerList. So if you want your component's top edge to be 10 pixels below the
|
||||
marker called "foobar", you'd set it to "foobar + 10".
|
||||
|
||||
See the Expression class for details about the operators that are supported, but for example
|
||||
if you wanted to make your component remains centred within its parent with a size of 100, 100,
|
||||
you could express it as:
|
||||
@code myComp.setBounds (RelativeBounds ("parent.width / 2 - 50, parent.height / 2 - 50, left + 100, top + 100"));
|
||||
@endcode
|
||||
..or an alternative way to achieve the same thing:
|
||||
@code myComp.setBounds (RelativeBounds ("right - 100, bottom - 100, parent.width / 2 + 50, parent.height / 2 + 50"));
|
||||
@endcode
|
||||
|
||||
Or if you wanted a 100x100 component whose top edge is lined up to a marker called "topMarker" and
|
||||
which is positioned 50 pixels to the right of another component called "otherComp", you could write:
|
||||
@code myComp.setBounds (RelativeBounds ("otherComp.right + 50, topMarker, left + 100, top + 100"));
|
||||
@endcode
|
||||
|
||||
Be careful not to make your coordinate expressions recursive, though, or exceptions and assertions will
|
||||
be thrown!
|
||||
|
||||
@see RelativePoint, RelativeRectangle
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API RelativeCoordinate
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a zero coordinate. */
|
||||
RelativeCoordinate();
|
||||
RelativeCoordinate (const Expression& expression);
|
||||
RelativeCoordinate (const RelativeCoordinate&);
|
||||
RelativeCoordinate& operator= (const RelativeCoordinate&);
|
||||
RelativeCoordinate (RelativeCoordinate&&) noexcept;
|
||||
RelativeCoordinate& operator= (RelativeCoordinate&&) noexcept;
|
||||
|
||||
/** Creates an absolute position from the parent origin on either the X or Y axis.
|
||||
|
||||
@param absoluteDistanceFromOrigin the distance from the origin
|
||||
*/
|
||||
RelativeCoordinate (double absoluteDistanceFromOrigin);
|
||||
|
||||
/** Recreates a coordinate from a string description.
|
||||
The string will be parsed by ExpressionParser::parse().
|
||||
@param stringVersion the expression to use
|
||||
@see toString
|
||||
*/
|
||||
RelativeCoordinate (const String& stringVersion);
|
||||
|
||||
/** Destructor. */
|
||||
~RelativeCoordinate();
|
||||
|
||||
bool operator== (const RelativeCoordinate&) const noexcept;
|
||||
bool operator!= (const RelativeCoordinate&) const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Calculates the absolute position of this coordinate.
|
||||
|
||||
You'll need to provide a suitable Expression::Scope for looking up any coordinates that may
|
||||
be needed to calculate the result.
|
||||
*/
|
||||
double resolve (const Expression::Scope* evaluationScope) const;
|
||||
|
||||
/** Returns true if this coordinate uses the specified coord name at any level in its evaluation.
|
||||
This will recursively check any coordinates upon which this one depends.
|
||||
*/
|
||||
bool references (const String& coordName, const Expression::Scope* evaluationScope) const;
|
||||
|
||||
/** Returns true if there's a recursive loop when trying to resolve this coordinate's position. */
|
||||
bool isRecursive (const Expression::Scope* evaluationScope) const;
|
||||
|
||||
/** Returns true if this coordinate depends on any other coordinates for its position. */
|
||||
bool isDynamic() const;
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the value of this coord to make it resolve to the specified position.
|
||||
|
||||
Calling this will leave the anchor points unchanged, but will set this coordinate's absolute
|
||||
or relative position to whatever value is necessary to make its resultant position
|
||||
match the position that is provided.
|
||||
*/
|
||||
void moveToAbsolute (double absoluteTargetPosition, const Expression::Scope* evaluationScope);
|
||||
|
||||
/** Returns the expression that defines this coordinate. */
|
||||
const Expression& getExpression() const { return term; }
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a string which represents this coordinate.
|
||||
For details of the string syntax, see the constructor notes.
|
||||
*/
|
||||
String toString() const;
|
||||
|
||||
//==============================================================================
|
||||
/** A set of static strings that are commonly used by the RelativeCoordinate class.
|
||||
|
||||
As well as avoiding using string literals in your code, using these preset values
|
||||
has the advantage that all instances of the same string will share the same, reference-counted
|
||||
String object, so if you have thousands of points which all refer to the same
|
||||
anchor points, this can save a significant amount of memory allocation.
|
||||
*/
|
||||
struct Strings
|
||||
{
|
||||
static const String parent; /**< "parent" */
|
||||
static const String left; /**< "left" */
|
||||
static const String right; /**< "right" */
|
||||
static const String top; /**< "top" */
|
||||
static const String bottom; /**< "bottom" */
|
||||
static const String x; /**< "x" */
|
||||
static const String y; /**< "y" */
|
||||
static const String width; /**< "width" */
|
||||
static const String height; /**< "height" */
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
struct StandardStrings
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
left, right, top, bottom,
|
||||
x, y, width, height,
|
||||
parent,
|
||||
unknown
|
||||
};
|
||||
|
||||
static Type getTypeOf (const String& s) noexcept;
|
||||
};
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
Expression term;
|
||||
};
|
||||
|
||||
} // namespace juce
|
335
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.cpp
vendored
Normal file
335
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.cpp
vendored
Normal file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
struct MarkerListScope : public Expression::Scope
|
||||
{
|
||||
MarkerListScope (Component& comp) : component (comp) {}
|
||||
|
||||
Expression getSymbolValue (const String& symbol) const override
|
||||
{
|
||||
auto type = RelativeCoordinate::StandardStrings::getTypeOf (symbol);
|
||||
|
||||
if (type == RelativeCoordinate::StandardStrings::width) return Expression ((double) component.getWidth());
|
||||
if (type == RelativeCoordinate::StandardStrings::height) return Expression ((double) component.getHeight());
|
||||
|
||||
MarkerList* list;
|
||||
|
||||
if (auto* marker = findMarker (component, symbol, list))
|
||||
return Expression (marker->position.getExpression().evaluate (*this));
|
||||
|
||||
return Expression::Scope::getSymbolValue (symbol);
|
||||
}
|
||||
|
||||
void visitRelativeScope (const String& scopeName, Visitor& visitor) const override
|
||||
{
|
||||
if (scopeName == RelativeCoordinate::Strings::parent)
|
||||
{
|
||||
if (auto* parent = component.getParentComponent())
|
||||
{
|
||||
visitor.visit (MarkerListScope (*parent));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Expression::Scope::visitRelativeScope (scopeName, visitor);
|
||||
}
|
||||
|
||||
String getScopeUID() const override
|
||||
{
|
||||
return String::toHexString ((pointer_sized_int) (void*) &component) + "m";
|
||||
}
|
||||
|
||||
static const MarkerList::Marker* findMarker (Component& component, const String& name, MarkerList*& list)
|
||||
{
|
||||
const MarkerList::Marker* marker = nullptr;
|
||||
|
||||
auto* mlh = dynamic_cast<MarkerList::MarkerListHolder*> (&component);
|
||||
|
||||
if (mlh != nullptr)
|
||||
{
|
||||
list = mlh->getMarkers (true);
|
||||
|
||||
if (list != nullptr)
|
||||
marker = list->getMarker (name);
|
||||
}
|
||||
|
||||
if (marker == nullptr)
|
||||
{
|
||||
if (mlh != nullptr)
|
||||
{
|
||||
list = mlh->getMarkers (false);
|
||||
|
||||
if (list != nullptr)
|
||||
marker = list->getMarker (name);
|
||||
}
|
||||
}
|
||||
|
||||
return marker;
|
||||
}
|
||||
|
||||
Component& component;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
RelativeCoordinatePositionerBase::ComponentScope::ComponentScope (Component& comp)
|
||||
: component (comp)
|
||||
{
|
||||
}
|
||||
|
||||
Expression RelativeCoordinatePositionerBase::ComponentScope::getSymbolValue (const String& symbol) const
|
||||
{
|
||||
switch (RelativeCoordinate::StandardStrings::getTypeOf (symbol))
|
||||
{
|
||||
case RelativeCoordinate::StandardStrings::x:
|
||||
case RelativeCoordinate::StandardStrings::left: return Expression ((double) component.getX());
|
||||
case RelativeCoordinate::StandardStrings::y:
|
||||
case RelativeCoordinate::StandardStrings::top: return Expression ((double) component.getY());
|
||||
case RelativeCoordinate::StandardStrings::width: return Expression ((double) component.getWidth());
|
||||
case RelativeCoordinate::StandardStrings::height: return Expression ((double) component.getHeight());
|
||||
case RelativeCoordinate::StandardStrings::right: return Expression ((double) component.getRight());
|
||||
case RelativeCoordinate::StandardStrings::bottom: return Expression ((double) component.getBottom());
|
||||
case RelativeCoordinate::StandardStrings::parent:
|
||||
case RelativeCoordinate::StandardStrings::unknown:
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (Component* const parent = component.getParentComponent())
|
||||
{
|
||||
MarkerList* list;
|
||||
|
||||
if (auto* marker = MarkerListScope::findMarker (*parent, symbol, list))
|
||||
{
|
||||
MarkerListScope scope (*parent);
|
||||
return Expression (marker->position.getExpression().evaluate (scope));
|
||||
}
|
||||
}
|
||||
|
||||
return Expression::Scope::getSymbolValue (symbol);
|
||||
}
|
||||
|
||||
void RelativeCoordinatePositionerBase::ComponentScope::visitRelativeScope (const String& scopeName, Visitor& visitor) const
|
||||
{
|
||||
if (auto* targetComp = (scopeName == RelativeCoordinate::Strings::parent)
|
||||
? component.getParentComponent()
|
||||
: findSiblingComponent (scopeName))
|
||||
visitor.visit (ComponentScope (*targetComp));
|
||||
else
|
||||
Expression::Scope::visitRelativeScope (scopeName, visitor);
|
||||
}
|
||||
|
||||
String RelativeCoordinatePositionerBase::ComponentScope::getScopeUID() const
|
||||
{
|
||||
return String::toHexString ((pointer_sized_int) (void*) &component);
|
||||
}
|
||||
|
||||
Component* RelativeCoordinatePositionerBase::ComponentScope::findSiblingComponent (const String& componentID) const
|
||||
{
|
||||
if (Component* const parent = component.getParentComponent())
|
||||
return parent->findChildWithID (componentID);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class RelativeCoordinatePositionerBase::DependencyFinderScope : public ComponentScope
|
||||
{
|
||||
public:
|
||||
DependencyFinderScope (Component& comp, RelativeCoordinatePositionerBase& p, bool& result)
|
||||
: ComponentScope (comp), positioner (p), ok (result)
|
||||
{
|
||||
}
|
||||
|
||||
Expression getSymbolValue (const String& symbol) const override
|
||||
{
|
||||
switch (RelativeCoordinate::StandardStrings::getTypeOf (symbol))
|
||||
{
|
||||
case RelativeCoordinate::StandardStrings::x:
|
||||
case RelativeCoordinate::StandardStrings::left:
|
||||
case RelativeCoordinate::StandardStrings::y:
|
||||
case RelativeCoordinate::StandardStrings::top:
|
||||
case RelativeCoordinate::StandardStrings::width:
|
||||
case RelativeCoordinate::StandardStrings::height:
|
||||
case RelativeCoordinate::StandardStrings::right:
|
||||
case RelativeCoordinate::StandardStrings::bottom:
|
||||
positioner.registerComponentListener (component);
|
||||
break;
|
||||
|
||||
case RelativeCoordinate::StandardStrings::parent:
|
||||
case RelativeCoordinate::StandardStrings::unknown:
|
||||
default:
|
||||
if (auto* parent = component.getParentComponent())
|
||||
{
|
||||
MarkerList* list;
|
||||
|
||||
if (MarkerListScope::findMarker (*parent, symbol, list) != nullptr)
|
||||
{
|
||||
positioner.registerMarkerListListener (list);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The marker we want doesn't exist, so watch all lists in case they change and the marker appears later..
|
||||
if (auto* mlh = dynamic_cast<MarkerList::MarkerListHolder*> (parent))
|
||||
{
|
||||
positioner.registerMarkerListListener (mlh->getMarkers (true));
|
||||
positioner.registerMarkerListListener (mlh->getMarkers (false));
|
||||
}
|
||||
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ComponentScope::getSymbolValue (symbol);
|
||||
}
|
||||
|
||||
void visitRelativeScope (const String& scopeName, Visitor& visitor) const override
|
||||
{
|
||||
if (Component* const targetComp = (scopeName == RelativeCoordinate::Strings::parent)
|
||||
? component.getParentComponent()
|
||||
: findSiblingComponent (scopeName))
|
||||
{
|
||||
visitor.visit (DependencyFinderScope (*targetComp, positioner, ok));
|
||||
}
|
||||
else
|
||||
{
|
||||
// The named component doesn't exist, so we'll watch the parent for changes in case it appears later..
|
||||
if (Component* const parent = component.getParentComponent())
|
||||
positioner.registerComponentListener (*parent);
|
||||
|
||||
positioner.registerComponentListener (component);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RelativeCoordinatePositionerBase& positioner;
|
||||
bool& ok;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
RelativeCoordinatePositionerBase::RelativeCoordinatePositionerBase (Component& comp)
|
||||
: Component::Positioner (comp), registeredOk (false)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeCoordinatePositionerBase::~RelativeCoordinatePositionerBase()
|
||||
{
|
||||
unregisterListeners();
|
||||
}
|
||||
|
||||
void RelativeCoordinatePositionerBase::componentMovedOrResized (Component&, bool /*wasMoved*/, bool /*wasResized*/)
|
||||
{
|
||||
apply();
|
||||
}
|
||||
|
||||
void RelativeCoordinatePositionerBase::componentParentHierarchyChanged (Component&)
|
||||
{
|
||||
apply();
|
||||
}
|
||||
|
||||
void RelativeCoordinatePositionerBase::componentChildrenChanged (Component& changed)
|
||||
{
|
||||
if (getComponent().getParentComponent() == &changed && ! registeredOk)
|
||||
apply();
|
||||
}
|
||||
|
||||
void RelativeCoordinatePositionerBase::componentBeingDeleted (Component& comp)
|
||||
{
|
||||
jassert (sourceComponents.contains (&comp));
|
||||
sourceComponents.removeFirstMatchingValue (&comp);
|
||||
registeredOk = false;
|
||||
}
|
||||
|
||||
void RelativeCoordinatePositionerBase::markersChanged (MarkerList*)
|
||||
{
|
||||
apply();
|
||||
}
|
||||
|
||||
void RelativeCoordinatePositionerBase::markerListBeingDeleted (MarkerList* markerList)
|
||||
{
|
||||
jassert (sourceMarkerLists.contains (markerList));
|
||||
sourceMarkerLists.removeFirstMatchingValue (markerList);
|
||||
}
|
||||
|
||||
void RelativeCoordinatePositionerBase::apply()
|
||||
{
|
||||
if (! registeredOk)
|
||||
{
|
||||
unregisterListeners();
|
||||
registeredOk = registerCoordinates();
|
||||
}
|
||||
|
||||
applyToComponentBounds();
|
||||
}
|
||||
|
||||
bool RelativeCoordinatePositionerBase::addCoordinate (const RelativeCoordinate& coord)
|
||||
{
|
||||
bool ok = true;
|
||||
DependencyFinderScope finderScope (getComponent(), *this, ok);
|
||||
coord.getExpression().evaluate (finderScope);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool RelativeCoordinatePositionerBase::addPoint (const RelativePoint& point)
|
||||
{
|
||||
const bool ok = addCoordinate (point.x);
|
||||
return addCoordinate (point.y) && ok;
|
||||
}
|
||||
|
||||
void RelativeCoordinatePositionerBase::registerComponentListener (Component& comp)
|
||||
{
|
||||
if (! sourceComponents.contains (&comp))
|
||||
{
|
||||
comp.addComponentListener (this);
|
||||
sourceComponents.add (&comp);
|
||||
}
|
||||
}
|
||||
|
||||
void RelativeCoordinatePositionerBase::registerMarkerListListener (MarkerList* const list)
|
||||
{
|
||||
if (list != nullptr && ! sourceMarkerLists.contains (list))
|
||||
{
|
||||
list->addListener (this);
|
||||
sourceMarkerLists.add (list);
|
||||
}
|
||||
}
|
||||
|
||||
void RelativeCoordinatePositionerBase::unregisterListeners()
|
||||
{
|
||||
for (int i = sourceComponents.size(); --i >= 0;)
|
||||
sourceComponents.getUnchecked(i)->removeComponentListener (this);
|
||||
|
||||
for (int i = sourceMarkerLists.size(); --i >= 0;)
|
||||
sourceMarkerLists.getUnchecked(i)->removeListener (this);
|
||||
|
||||
sourceComponents.clear();
|
||||
sourceMarkerLists.clear();
|
||||
}
|
||||
|
||||
} // namespace juce
|
90
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.h
vendored
Normal file
90
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.h
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Base class for Component::Positioners that are based upon relative coordinates.
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API RelativeCoordinatePositionerBase : public Component::Positioner,
|
||||
public ComponentListener,
|
||||
public MarkerList::Listener
|
||||
{
|
||||
public:
|
||||
RelativeCoordinatePositionerBase (Component&);
|
||||
~RelativeCoordinatePositionerBase() override;
|
||||
|
||||
void componentMovedOrResized (Component&, bool, bool) override;
|
||||
void componentParentHierarchyChanged (Component&) override;
|
||||
void componentChildrenChanged (Component&) override;
|
||||
void componentBeingDeleted (Component&) override;
|
||||
void markersChanged (MarkerList*) override;
|
||||
void markerListBeingDeleted (MarkerList*) override;
|
||||
|
||||
void apply();
|
||||
|
||||
bool addCoordinate (const RelativeCoordinate&);
|
||||
bool addPoint (const RelativePoint&);
|
||||
|
||||
//==============================================================================
|
||||
/** Used for resolving a RelativeCoordinate expression in the context of a component. */
|
||||
class ComponentScope : public Expression::Scope
|
||||
{
|
||||
public:
|
||||
ComponentScope (Component&);
|
||||
|
||||
Expression getSymbolValue (const String& symbol) const override;
|
||||
void visitRelativeScope (const String& scopeName, Visitor&) const override;
|
||||
String getScopeUID() const override;
|
||||
|
||||
protected:
|
||||
Component& component;
|
||||
|
||||
Component* findSiblingComponent (const String& componentID) const;
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual bool registerCoordinates() = 0;
|
||||
virtual void applyToComponentBounds() = 0;
|
||||
|
||||
private:
|
||||
class DependencyFinderScope;
|
||||
friend class DependencyFinderScope;
|
||||
Array<Component*> sourceComponents;
|
||||
Array<MarkerList*> sourceMarkerLists;
|
||||
bool registeredOk;
|
||||
|
||||
void registerComponentListener (Component&);
|
||||
void registerMarkerListListener (MarkerList*);
|
||||
void unregisterListeners();
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativeCoordinatePositionerBase)
|
||||
};
|
||||
|
||||
} // namespace juce
|
140
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.cpp
vendored
Normal file
140
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.cpp
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
RelativeParallelogram::RelativeParallelogram()
|
||||
{
|
||||
}
|
||||
|
||||
RelativeParallelogram::RelativeParallelogram (const Rectangle<float>& r)
|
||||
: topLeft (r.getTopLeft()), topRight (r.getTopRight()), bottomLeft (r.getBottomLeft())
|
||||
{
|
||||
}
|
||||
|
||||
RelativeParallelogram::RelativeParallelogram (const RelativePoint& topLeft_, const RelativePoint& topRight_, const RelativePoint& bottomLeft_)
|
||||
: topLeft (topLeft_), topRight (topRight_), bottomLeft (bottomLeft_)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeParallelogram::RelativeParallelogram (const String& topLeft_, const String& topRight_, const String& bottomLeft_)
|
||||
: topLeft (topLeft_), topRight (topRight_), bottomLeft (bottomLeft_)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeParallelogram::~RelativeParallelogram()
|
||||
{
|
||||
}
|
||||
|
||||
void RelativeParallelogram::resolveThreePoints (Point<float>* points, Expression::Scope* const scope) const
|
||||
{
|
||||
points[0] = topLeft.resolve (scope);
|
||||
points[1] = topRight.resolve (scope);
|
||||
points[2] = bottomLeft.resolve (scope);
|
||||
}
|
||||
|
||||
void RelativeParallelogram::resolveFourCorners (Point<float>* points, Expression::Scope* const scope) const
|
||||
{
|
||||
resolveThreePoints (points, scope);
|
||||
points[3] = points[1] + (points[2] - points[0]);
|
||||
}
|
||||
|
||||
const Rectangle<float> RelativeParallelogram::getBounds (Expression::Scope* const scope) const
|
||||
{
|
||||
Point<float> points[4];
|
||||
resolveFourCorners (points, scope);
|
||||
return Rectangle<float>::findAreaContainingPoints (points, 4);
|
||||
}
|
||||
|
||||
void RelativeParallelogram::getPath (Path& path, Expression::Scope* const scope) const
|
||||
{
|
||||
Point<float> points[4];
|
||||
resolveFourCorners (points, scope);
|
||||
|
||||
path.startNewSubPath (points[0]);
|
||||
path.lineTo (points[1]);
|
||||
path.lineTo (points[3]);
|
||||
path.lineTo (points[2]);
|
||||
path.closeSubPath();
|
||||
}
|
||||
|
||||
AffineTransform RelativeParallelogram::resetToPerpendicular (Expression::Scope* const scope)
|
||||
{
|
||||
Point<float> corners[3];
|
||||
resolveThreePoints (corners, scope);
|
||||
|
||||
const Line<float> top (corners[0], corners[1]);
|
||||
const Line<float> left (corners[0], corners[2]);
|
||||
const Point<float> newTopRight (corners[0] + Point<float> (top.getLength(), 0.0f));
|
||||
const Point<float> newBottomLeft (corners[0] + Point<float> (0.0f, left.getLength()));
|
||||
|
||||
topRight.moveToAbsolute (newTopRight, scope);
|
||||
bottomLeft.moveToAbsolute (newBottomLeft, scope);
|
||||
|
||||
return AffineTransform::fromTargetPoints (corners[0], corners[0],
|
||||
corners[1], newTopRight,
|
||||
corners[2], newBottomLeft);
|
||||
}
|
||||
|
||||
bool RelativeParallelogram::isDynamic() const
|
||||
{
|
||||
return topLeft.isDynamic() || topRight.isDynamic() || bottomLeft.isDynamic();
|
||||
}
|
||||
|
||||
bool RelativeParallelogram::operator== (const RelativeParallelogram& other) const noexcept
|
||||
{
|
||||
return topLeft == other.topLeft && topRight == other.topRight && bottomLeft == other.bottomLeft;
|
||||
}
|
||||
|
||||
bool RelativeParallelogram::operator!= (const RelativeParallelogram& other) const noexcept
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
Point<float> RelativeParallelogram::getInternalCoordForPoint (const Point<float>* const corners, Point<float> target) noexcept
|
||||
{
|
||||
const Point<float> tr (corners[1] - corners[0]);
|
||||
const Point<float> bl (corners[2] - corners[0]);
|
||||
target -= corners[0];
|
||||
|
||||
return Point<float> (Line<float> (Point<float>(), tr).getIntersection (Line<float> (target, target - bl)).getDistanceFromOrigin(),
|
||||
Line<float> (Point<float>(), bl).getIntersection (Line<float> (target, target - tr)).getDistanceFromOrigin());
|
||||
}
|
||||
|
||||
Point<float> RelativeParallelogram::getPointForInternalCoord (const Point<float>* const corners, const Point<float> point) noexcept
|
||||
{
|
||||
return corners[0]
|
||||
+ Line<float> (Point<float>(), corners[1] - corners[0]).getPointAlongLine (point.x)
|
||||
+ Line<float> (Point<float>(), corners[2] - corners[0]).getPointAlongLine (point.y);
|
||||
}
|
||||
|
||||
Rectangle<float> RelativeParallelogram::getBoundingBox (const Point<float>* const p) noexcept
|
||||
{
|
||||
const Point<float> points[] = { p[0], p[1], p[2], p[1] + (p[2] - p[0]) };
|
||||
return Rectangle<float>::findAreaContainingPoints (points, 4);
|
||||
}
|
||||
|
||||
} // namespace juce
|
66
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.h
vendored
Normal file
66
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.h
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A parallelogram defined by three RelativePoint positions.
|
||||
|
||||
@see RelativePoint, RelativeCoordinate
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API RelativeParallelogram
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
RelativeParallelogram();
|
||||
RelativeParallelogram (const Rectangle<float>& simpleRectangle);
|
||||
RelativeParallelogram (const RelativePoint& topLeft, const RelativePoint& topRight, const RelativePoint& bottomLeft);
|
||||
RelativeParallelogram (const String& topLeft, const String& topRight, const String& bottomLeft);
|
||||
~RelativeParallelogram();
|
||||
|
||||
//==============================================================================
|
||||
void resolveThreePoints (Point<float>* points, Expression::Scope* scope) const;
|
||||
void resolveFourCorners (Point<float>* points, Expression::Scope* scope) const;
|
||||
const Rectangle<float> getBounds (Expression::Scope* scope) const;
|
||||
void getPath (Path& path, Expression::Scope* scope) const;
|
||||
AffineTransform resetToPerpendicular (Expression::Scope* scope);
|
||||
bool isDynamic() const;
|
||||
|
||||
bool operator== (const RelativeParallelogram&) const noexcept;
|
||||
bool operator!= (const RelativeParallelogram&) const noexcept;
|
||||
|
||||
static Point<float> getInternalCoordForPoint (const Point<float>* parallelogramCorners, Point<float> point) noexcept;
|
||||
static Point<float> getPointForInternalCoord (const Point<float>* parallelogramCorners, Point<float> internalPoint) noexcept;
|
||||
static Rectangle<float> getBoundingBox (const Point<float>* parallelogramCorners) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
RelativePoint topLeft, topRight, bottomLeft;
|
||||
};
|
||||
|
||||
} // namespace juce
|
101
deps/juce/modules/juce_gui_basics/positioning/juce_RelativePoint.cpp
vendored
Normal file
101
deps/juce/modules/juce_gui_basics/positioning/juce_RelativePoint.cpp
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
namespace RelativePointHelpers
|
||||
{
|
||||
inline void skipComma (String::CharPointerType& s)
|
||||
{
|
||||
s.incrementToEndOfWhitespace();
|
||||
|
||||
if (*s == ',')
|
||||
++s;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
RelativePoint::RelativePoint()
|
||||
{
|
||||
}
|
||||
|
||||
RelativePoint::RelativePoint (Point<float> absolutePoint)
|
||||
: x (absolutePoint.x), y (absolutePoint.y)
|
||||
{
|
||||
}
|
||||
|
||||
RelativePoint::RelativePoint (const float x_, const float y_)
|
||||
: x (x_), y (y_)
|
||||
{
|
||||
}
|
||||
|
||||
RelativePoint::RelativePoint (const RelativeCoordinate& x_, const RelativeCoordinate& y_)
|
||||
: x (x_), y (y_)
|
||||
{
|
||||
}
|
||||
|
||||
RelativePoint::RelativePoint (const String& s)
|
||||
{
|
||||
String error;
|
||||
String::CharPointerType text (s.getCharPointer());
|
||||
x = RelativeCoordinate (Expression::parse (text, error));
|
||||
RelativePointHelpers::skipComma (text);
|
||||
y = RelativeCoordinate (Expression::parse (text, error));
|
||||
}
|
||||
|
||||
bool RelativePoint::operator== (const RelativePoint& other) const noexcept
|
||||
{
|
||||
return x == other.x && y == other.y;
|
||||
}
|
||||
|
||||
bool RelativePoint::operator!= (const RelativePoint& other) const noexcept
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
Point<float> RelativePoint::resolve (const Expression::Scope* scope) const
|
||||
{
|
||||
return Point<float> ((float) x.resolve (scope),
|
||||
(float) y.resolve (scope));
|
||||
}
|
||||
|
||||
void RelativePoint::moveToAbsolute (Point<float> newPos, const Expression::Scope* scope)
|
||||
{
|
||||
x.moveToAbsolute (newPos.x, scope);
|
||||
y.moveToAbsolute (newPos.y, scope);
|
||||
}
|
||||
|
||||
String RelativePoint::toString() const
|
||||
{
|
||||
return x.toString() + ", " + y.toString();
|
||||
}
|
||||
|
||||
bool RelativePoint::isDynamic() const
|
||||
{
|
||||
return x.isDynamic() || y.isDynamic();
|
||||
}
|
||||
|
||||
} // namespace juce
|
91
deps/juce/modules/juce_gui_basics/positioning/juce_RelativePoint.h
vendored
Normal file
91
deps/juce/modules/juce_gui_basics/positioning/juce_RelativePoint.h
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An X-Y position stored as a pair of RelativeCoordinate values.
|
||||
|
||||
@see RelativeCoordinate, RelativeRectangle
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API RelativePoint
|
||||
{
|
||||
public:
|
||||
/** Creates a point at the origin. */
|
||||
RelativePoint();
|
||||
|
||||
/** Creates an absolute point, relative to the origin. */
|
||||
RelativePoint (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&) const noexcept;
|
||||
bool operator!= (const RelativePoint&) const noexcept;
|
||||
|
||||
/** Calculates the absolute position of this point.
|
||||
|
||||
You'll need to provide a suitable Expression::Scope for looking up any coordinates that may
|
||||
be needed to calculate the result.
|
||||
*/
|
||||
Point<float> resolve (const Expression::Scope* 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 (Point<float> newPos, const Expression::Scope* 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.
|
||||
*/
|
||||
String toString() const;
|
||||
|
||||
/** 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;
|
||||
};
|
||||
|
||||
} // namespace juce
|
262
deps/juce/modules/juce_gui_basics/positioning/juce_RelativePointPath.cpp
vendored
Normal file
262
deps/juce/modules/juce_gui_basics/positioning/juce_RelativePointPath.cpp
vendored
Normal file
@ -0,0 +1,262 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
RelativePointPath::RelativePointPath()
|
||||
: usesNonZeroWinding (true),
|
||||
containsDynamicPoints (false)
|
||||
{
|
||||
}
|
||||
|
||||
RelativePointPath::RelativePointPath (const RelativePointPath& other)
|
||||
: usesNonZeroWinding (true),
|
||||
containsDynamicPoints (false)
|
||||
{
|
||||
for (int i = 0; i < other.elements.size(); ++i)
|
||||
elements.add (other.elements.getUnchecked(i)->clone());
|
||||
}
|
||||
|
||||
RelativePointPath::RelativePointPath (const Path& path)
|
||||
: usesNonZeroWinding (path.isUsingNonZeroWinding()),
|
||||
containsDynamicPoints (false)
|
||||
{
|
||||
for (Path::Iterator i (path); i.next();)
|
||||
{
|
||||
switch (i.elementType)
|
||||
{
|
||||
case Path::Iterator::startNewSubPath: elements.add (new StartSubPath (RelativePoint (i.x1, i.y1))); break;
|
||||
case Path::Iterator::lineTo: elements.add (new LineTo (RelativePoint (i.x1, i.y1))); break;
|
||||
case Path::Iterator::quadraticTo: elements.add (new QuadraticTo (RelativePoint (i.x1, i.y1), RelativePoint (i.x2, i.y2))); break;
|
||||
case Path::Iterator::cubicTo: elements.add (new CubicTo (RelativePoint (i.x1, i.y1), RelativePoint (i.x2, i.y2), RelativePoint (i.x3, i.y3))); break;
|
||||
case Path::Iterator::closePath: elements.add (new CloseSubPath()); break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RelativePointPath::~RelativePointPath()
|
||||
{
|
||||
}
|
||||
|
||||
bool RelativePointPath::operator== (const RelativePointPath& other) const noexcept
|
||||
{
|
||||
if (elements.size() != other.elements.size()
|
||||
|| usesNonZeroWinding != other.usesNonZeroWinding
|
||||
|| containsDynamicPoints != other.containsDynamicPoints)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < elements.size(); ++i)
|
||||
{
|
||||
ElementBase* const e1 = elements.getUnchecked(i);
|
||||
ElementBase* const e2 = other.elements.getUnchecked(i);
|
||||
|
||||
if (e1->type != e2->type)
|
||||
return false;
|
||||
|
||||
int numPoints1, numPoints2;
|
||||
const RelativePoint* const points1 = e1->getControlPoints (numPoints1);
|
||||
const RelativePoint* const points2 = e2->getControlPoints (numPoints2);
|
||||
|
||||
jassert (numPoints1 == numPoints2);
|
||||
|
||||
for (int j = numPoints1; --j >= 0;)
|
||||
if (points1[j] != points2[j])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RelativePointPath::operator!= (const RelativePointPath& other) const noexcept
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
void RelativePointPath::swapWith (RelativePointPath& other) noexcept
|
||||
{
|
||||
elements.swapWith (other.elements);
|
||||
std::swap (usesNonZeroWinding, other.usesNonZeroWinding);
|
||||
std::swap (containsDynamicPoints, other.containsDynamicPoints);
|
||||
}
|
||||
|
||||
void RelativePointPath::createPath (Path& path, Expression::Scope* scope) const
|
||||
{
|
||||
for (int i = 0; i < elements.size(); ++i)
|
||||
elements.getUnchecked(i)->addToPath (path, scope);
|
||||
}
|
||||
|
||||
bool RelativePointPath::containsAnyDynamicPoints() const
|
||||
{
|
||||
return containsDynamicPoints;
|
||||
}
|
||||
|
||||
void RelativePointPath::addElement (ElementBase* newElement)
|
||||
{
|
||||
if (newElement != nullptr)
|
||||
{
|
||||
elements.add (newElement);
|
||||
containsDynamicPoints = containsDynamicPoints || newElement->isDynamic();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
RelativePointPath::ElementBase::ElementBase (const ElementType type_) : type (type_)
|
||||
{
|
||||
}
|
||||
|
||||
bool RelativePointPath::ElementBase::isDynamic()
|
||||
{
|
||||
int numPoints;
|
||||
const RelativePoint* const points = getControlPoints (numPoints);
|
||||
|
||||
for (int i = numPoints; --i >= 0;)
|
||||
if (points[i].isDynamic())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
RelativePointPath::StartSubPath::StartSubPath (const RelativePoint& pos)
|
||||
: ElementBase (startSubPathElement), startPos (pos)
|
||||
{
|
||||
}
|
||||
|
||||
void RelativePointPath::StartSubPath::addToPath (Path& path, Expression::Scope* scope) const
|
||||
{
|
||||
path.startNewSubPath (startPos.resolve (scope));
|
||||
}
|
||||
|
||||
RelativePoint* RelativePointPath::StartSubPath::getControlPoints (int& numPoints)
|
||||
{
|
||||
numPoints = 1;
|
||||
return &startPos;
|
||||
}
|
||||
|
||||
RelativePointPath::ElementBase* RelativePointPath::StartSubPath::clone() const
|
||||
{
|
||||
return new StartSubPath (startPos);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
RelativePointPath::CloseSubPath::CloseSubPath()
|
||||
: ElementBase (closeSubPathElement)
|
||||
{
|
||||
}
|
||||
|
||||
void RelativePointPath::CloseSubPath::addToPath (Path& path, Expression::Scope*) const
|
||||
{
|
||||
path.closeSubPath();
|
||||
}
|
||||
|
||||
RelativePoint* RelativePointPath::CloseSubPath::getControlPoints (int& numPoints)
|
||||
{
|
||||
numPoints = 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RelativePointPath::ElementBase* RelativePointPath::CloseSubPath::clone() const
|
||||
{
|
||||
return new CloseSubPath();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
RelativePointPath::LineTo::LineTo (const RelativePoint& endPoint_)
|
||||
: ElementBase (lineToElement), endPoint (endPoint_)
|
||||
{
|
||||
}
|
||||
|
||||
void RelativePointPath::LineTo::addToPath (Path& path, Expression::Scope* scope) const
|
||||
{
|
||||
path.lineTo (endPoint.resolve (scope));
|
||||
}
|
||||
|
||||
RelativePoint* RelativePointPath::LineTo::getControlPoints (int& numPoints)
|
||||
{
|
||||
numPoints = 1;
|
||||
return &endPoint;
|
||||
}
|
||||
|
||||
RelativePointPath::ElementBase* RelativePointPath::LineTo::clone() const
|
||||
{
|
||||
return new LineTo (endPoint);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
RelativePointPath::QuadraticTo::QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint)
|
||||
: ElementBase (quadraticToElement)
|
||||
{
|
||||
controlPoints[0] = controlPoint;
|
||||
controlPoints[1] = endPoint;
|
||||
}
|
||||
|
||||
void RelativePointPath::QuadraticTo::addToPath (Path& path, Expression::Scope* scope) const
|
||||
{
|
||||
path.quadraticTo (controlPoints[0].resolve (scope),
|
||||
controlPoints[1].resolve (scope));
|
||||
}
|
||||
|
||||
RelativePoint* RelativePointPath::QuadraticTo::getControlPoints (int& numPoints)
|
||||
{
|
||||
numPoints = 2;
|
||||
return controlPoints;
|
||||
}
|
||||
|
||||
RelativePointPath::ElementBase* RelativePointPath::QuadraticTo::clone() const
|
||||
{
|
||||
return new QuadraticTo (controlPoints[0], controlPoints[1]);
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
RelativePointPath::CubicTo::CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint)
|
||||
: ElementBase (cubicToElement)
|
||||
{
|
||||
controlPoints[0] = controlPoint1;
|
||||
controlPoints[1] = controlPoint2;
|
||||
controlPoints[2] = endPoint;
|
||||
}
|
||||
|
||||
void RelativePointPath::CubicTo::addToPath (Path& path, Expression::Scope* scope) const
|
||||
{
|
||||
path.cubicTo (controlPoints[0].resolve (scope),
|
||||
controlPoints[1].resolve (scope),
|
||||
controlPoints[2].resolve (scope));
|
||||
}
|
||||
|
||||
RelativePoint* RelativePointPath::CubicTo::getControlPoints (int& numPoints)
|
||||
{
|
||||
numPoints = 3;
|
||||
return controlPoints;
|
||||
}
|
||||
|
||||
RelativePointPath::ElementBase* RelativePointPath::CubicTo::clone() const
|
||||
{
|
||||
return new CubicTo (controlPoints[0], controlPoints[1], controlPoints[2]);
|
||||
}
|
||||
|
||||
} // namespace juce
|
193
deps/juce/modules/juce_gui_basics/positioning/juce_RelativePointPath.h
vendored
Normal file
193
deps/juce/modules/juce_gui_basics/positioning/juce_RelativePointPath.h
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A path object that consists of RelativePoint coordinates rather than the normal fixed ones.
|
||||
|
||||
One of these paths can be converted into a Path object for drawing and manipulation, but
|
||||
unlike a Path, its points can be dynamic instead of just fixed.
|
||||
|
||||
@see RelativePoint, RelativeCoordinate
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API RelativePointPath
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
RelativePointPath();
|
||||
RelativePointPath (const RelativePointPath&);
|
||||
explicit RelativePointPath (const Path& path);
|
||||
~RelativePointPath();
|
||||
|
||||
bool operator== (const RelativePointPath&) const noexcept;
|
||||
bool operator!= (const RelativePointPath&) const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Resolves this points in this path and adds them to a normal Path object. */
|
||||
void createPath (Path& path, Expression::Scope* scope) const;
|
||||
|
||||
/** Returns true if the path contains any non-fixed points. */
|
||||
bool containsAnyDynamicPoints() const;
|
||||
|
||||
/** Quickly swaps the contents of this path with another. */
|
||||
void swapWith (RelativePointPath&) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** The types of element that may be contained in this path.
|
||||
@see RelativePointPath::ElementBase
|
||||
*/
|
||||
enum ElementType
|
||||
{
|
||||
nullElement,
|
||||
startSubPathElement,
|
||||
closeSubPathElement,
|
||||
lineToElement,
|
||||
quadraticToElement,
|
||||
cubicToElement
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Base class for the elements that make up a RelativePointPath.
|
||||
*/
|
||||
class JUCE_API ElementBase
|
||||
{
|
||||
public:
|
||||
ElementBase (ElementType type);
|
||||
virtual ~ElementBase() = default;
|
||||
virtual void addToPath (Path& path, Expression::Scope*) const = 0;
|
||||
virtual RelativePoint* getControlPoints (int& numPoints) = 0;
|
||||
virtual ElementBase* clone() const = 0;
|
||||
bool isDynamic();
|
||||
|
||||
const ElementType type;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE (ElementBase)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Class for the start sub path element */
|
||||
class JUCE_API StartSubPath : public ElementBase
|
||||
{
|
||||
public:
|
||||
StartSubPath (const RelativePoint& pos);
|
||||
void addToPath (Path& path, Expression::Scope*) const override;
|
||||
RelativePoint* getControlPoints (int& numPoints) override;
|
||||
ElementBase* clone() const override;
|
||||
|
||||
RelativePoint startPos;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE (StartSubPath)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Class for the close sub path element */
|
||||
class JUCE_API CloseSubPath : public ElementBase
|
||||
{
|
||||
public:
|
||||
CloseSubPath();
|
||||
void addToPath (Path& path, Expression::Scope*) const override;
|
||||
RelativePoint* getControlPoints (int& numPoints) override;
|
||||
ElementBase* clone() const override;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE (CloseSubPath)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Class for the line to element */
|
||||
class JUCE_API LineTo : public ElementBase
|
||||
{
|
||||
public:
|
||||
LineTo (const RelativePoint& endPoint);
|
||||
void addToPath (Path& path, Expression::Scope*) const override;
|
||||
RelativePoint* getControlPoints (int& numPoints) override;
|
||||
ElementBase* clone() const override;
|
||||
|
||||
RelativePoint endPoint;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE (LineTo)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Class for the quadratic to element */
|
||||
class JUCE_API QuadraticTo : public ElementBase
|
||||
{
|
||||
public:
|
||||
QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint);
|
||||
ValueTree createTree() const;
|
||||
void addToPath (Path& path, Expression::Scope*) const override;
|
||||
RelativePoint* getControlPoints (int& numPoints) override;
|
||||
ElementBase* clone() const override;
|
||||
|
||||
RelativePoint controlPoints[2];
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE (QuadraticTo)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Class for the cubic to element */
|
||||
class JUCE_API CubicTo : public ElementBase
|
||||
{
|
||||
public:
|
||||
CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint);
|
||||
ValueTree createTree() const;
|
||||
void addToPath (Path& path, Expression::Scope*) const override;
|
||||
RelativePoint* getControlPoints (int& numPoints) override;
|
||||
ElementBase* clone() const override;
|
||||
|
||||
RelativePoint controlPoints[3];
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE (CubicTo)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
void addElement (ElementBase* newElement);
|
||||
|
||||
//==============================================================================
|
||||
OwnedArray<ElementBase> elements;
|
||||
bool usesNonZeroWinding;
|
||||
|
||||
private:
|
||||
class Positioner;
|
||||
friend class Positioner;
|
||||
bool containsDynamicPoints;
|
||||
|
||||
void applyTo (DrawablePath& path) const;
|
||||
|
||||
RelativePointPath& operator= (const RelativePointPath&);
|
||||
JUCE_LEAK_DETECTOR (RelativePointPath)
|
||||
};
|
||||
|
||||
} // namespace juce
|
277
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeRectangle.cpp
vendored
Normal file
277
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeRectangle.cpp
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
namespace RelativeRectangleHelpers
|
||||
{
|
||||
inline void skipComma (String::CharPointerType& s)
|
||||
{
|
||||
s.incrementToEndOfWhitespace();
|
||||
|
||||
if (*s == ',')
|
||||
++s;
|
||||
}
|
||||
|
||||
static bool dependsOnSymbolsOtherThanThis (const Expression& e)
|
||||
{
|
||||
if (e.getType() == Expression::operatorType && e.getSymbolOrFunction() == ".")
|
||||
return true;
|
||||
|
||||
if (e.getType() == Expression::symbolType)
|
||||
{
|
||||
switch (RelativeCoordinate::StandardStrings::getTypeOf (e.getSymbolOrFunction()))
|
||||
{
|
||||
case RelativeCoordinate::StandardStrings::x:
|
||||
case RelativeCoordinate::StandardStrings::y:
|
||||
case RelativeCoordinate::StandardStrings::left:
|
||||
case RelativeCoordinate::StandardStrings::right:
|
||||
case RelativeCoordinate::StandardStrings::top:
|
||||
case RelativeCoordinate::StandardStrings::bottom: return false;
|
||||
case RelativeCoordinate::StandardStrings::width:
|
||||
case RelativeCoordinate::StandardStrings::height:
|
||||
case RelativeCoordinate::StandardStrings::parent:
|
||||
case RelativeCoordinate::StandardStrings::unknown:
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = e.getNumInputs(); --i >= 0;)
|
||||
if (dependsOnSymbolsOtherThanThis (e.getInput(i)))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
RelativeRectangle::RelativeRectangle()
|
||||
{
|
||||
}
|
||||
|
||||
RelativeRectangle::RelativeRectangle (const RelativeCoordinate& left_, const RelativeCoordinate& right_,
|
||||
const RelativeCoordinate& top_, const RelativeCoordinate& bottom_)
|
||||
: left (left_), right (right_), top (top_), bottom (bottom_)
|
||||
{
|
||||
}
|
||||
|
||||
RelativeRectangle::RelativeRectangle (const Rectangle<float>& rect)
|
||||
: left (rect.getX()),
|
||||
right (Expression::symbol (RelativeCoordinate::Strings::left) + Expression ((double) rect.getWidth())),
|
||||
top (rect.getY()),
|
||||
bottom (Expression::symbol (RelativeCoordinate::Strings::top) + Expression ((double) rect.getHeight()))
|
||||
{
|
||||
}
|
||||
|
||||
RelativeRectangle::RelativeRectangle (const String& s)
|
||||
{
|
||||
String error;
|
||||
String::CharPointerType text (s.getCharPointer());
|
||||
left = RelativeCoordinate (Expression::parse (text, error));
|
||||
RelativeRectangleHelpers::skipComma (text);
|
||||
top = RelativeCoordinate (Expression::parse (text, error));
|
||||
RelativeRectangleHelpers::skipComma (text);
|
||||
right = RelativeCoordinate (Expression::parse (text, error));
|
||||
RelativeRectangleHelpers::skipComma (text);
|
||||
bottom = RelativeCoordinate (Expression::parse (text, error));
|
||||
}
|
||||
|
||||
bool RelativeRectangle::operator== (const RelativeRectangle& other) const noexcept
|
||||
{
|
||||
return left == other.left && top == other.top && right == other.right && bottom == other.bottom;
|
||||
}
|
||||
|
||||
bool RelativeRectangle::operator!= (const RelativeRectangle& other) const noexcept
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// An expression context that can evaluate expressions using "this"
|
||||
class RelativeRectangleLocalScope : public Expression::Scope
|
||||
{
|
||||
public:
|
||||
RelativeRectangleLocalScope (const RelativeRectangle& rect_) : rect (rect_) {}
|
||||
|
||||
Expression getSymbolValue (const String& symbol) const
|
||||
{
|
||||
switch (RelativeCoordinate::StandardStrings::getTypeOf (symbol))
|
||||
{
|
||||
case RelativeCoordinate::StandardStrings::x:
|
||||
case RelativeCoordinate::StandardStrings::left: return rect.left.getExpression();
|
||||
case RelativeCoordinate::StandardStrings::y:
|
||||
case RelativeCoordinate::StandardStrings::top: return rect.top.getExpression();
|
||||
case RelativeCoordinate::StandardStrings::right: return rect.right.getExpression();
|
||||
case RelativeCoordinate::StandardStrings::bottom: return rect.bottom.getExpression();
|
||||
case RelativeCoordinate::StandardStrings::width:
|
||||
case RelativeCoordinate::StandardStrings::height:
|
||||
case RelativeCoordinate::StandardStrings::parent:
|
||||
case RelativeCoordinate::StandardStrings::unknown:
|
||||
default: break;
|
||||
}
|
||||
|
||||
return Expression::Scope::getSymbolValue (symbol);
|
||||
}
|
||||
|
||||
private:
|
||||
const RelativeRectangle& rect;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (RelativeRectangleLocalScope)
|
||||
};
|
||||
|
||||
const Rectangle<float> RelativeRectangle::resolve (const Expression::Scope* scope) const
|
||||
{
|
||||
if (scope == nullptr)
|
||||
{
|
||||
RelativeRectangleLocalScope defaultScope (*this);
|
||||
return resolve (&defaultScope);
|
||||
}
|
||||
else
|
||||
{
|
||||
const double l = left.resolve (scope);
|
||||
const double r = right.resolve (scope);
|
||||
const double t = top.resolve (scope);
|
||||
const double b = bottom.resolve (scope);
|
||||
|
||||
return Rectangle<float> ((float) l, (float) t, (float) jmax (0.0, r - l), (float) jmax (0.0, b - t));
|
||||
}
|
||||
}
|
||||
|
||||
void RelativeRectangle::moveToAbsolute (const Rectangle<float>& newPos, const Expression::Scope* scope)
|
||||
{
|
||||
left.moveToAbsolute (newPos.getX(), scope);
|
||||
right.moveToAbsolute (newPos.getRight(), scope);
|
||||
top.moveToAbsolute (newPos.getY(), scope);
|
||||
bottom.moveToAbsolute (newPos.getBottom(), scope);
|
||||
}
|
||||
|
||||
bool RelativeRectangle::isDynamic() const
|
||||
{
|
||||
using namespace RelativeRectangleHelpers;
|
||||
|
||||
return dependsOnSymbolsOtherThanThis (left.getExpression())
|
||||
|| dependsOnSymbolsOtherThanThis (right.getExpression())
|
||||
|| dependsOnSymbolsOtherThanThis (top.getExpression())
|
||||
|| dependsOnSymbolsOtherThanThis (bottom.getExpression());
|
||||
}
|
||||
|
||||
String RelativeRectangle::toString() const
|
||||
{
|
||||
return left.toString() + ", " + top.toString() + ", " + right.toString() + ", " + bottom.toString();
|
||||
}
|
||||
|
||||
void RelativeRectangle::renameSymbol (const Expression::Symbol& oldSymbol, const String& newName, const Expression::Scope& scope)
|
||||
{
|
||||
left = left.getExpression().withRenamedSymbol (oldSymbol, newName, scope);
|
||||
right = right.getExpression().withRenamedSymbol (oldSymbol, newName, scope);
|
||||
top = top.getExpression().withRenamedSymbol (oldSymbol, newName, scope);
|
||||
bottom = bottom.getExpression().withRenamedSymbol (oldSymbol, newName, scope);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class RelativeRectangleComponentPositioner : public RelativeCoordinatePositionerBase
|
||||
{
|
||||
public:
|
||||
RelativeRectangleComponentPositioner (Component& comp, const RelativeRectangle& r)
|
||||
: RelativeCoordinatePositionerBase (comp),
|
||||
rectangle (r)
|
||||
{
|
||||
}
|
||||
|
||||
bool registerCoordinates() override
|
||||
{
|
||||
bool ok = addCoordinate (rectangle.left);
|
||||
ok = addCoordinate (rectangle.right) && ok;
|
||||
ok = addCoordinate (rectangle.top) && ok;
|
||||
ok = addCoordinate (rectangle.bottom) && ok;
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool isUsingRectangle (const RelativeRectangle& other) const noexcept
|
||||
{
|
||||
return rectangle == other;
|
||||
}
|
||||
|
||||
void applyToComponentBounds() override
|
||||
{
|
||||
for (int i = 32; --i >= 0;)
|
||||
{
|
||||
ComponentScope scope (getComponent());
|
||||
const Rectangle<int> newBounds (rectangle.resolve (&scope).getSmallestIntegerContainer());
|
||||
|
||||
if (newBounds == getComponent().getBounds())
|
||||
return;
|
||||
|
||||
getComponent().setBounds (newBounds);
|
||||
}
|
||||
|
||||
jassertfalse; // Seems to be a recursive reference!
|
||||
}
|
||||
|
||||
void applyNewBounds (const Rectangle<int>& newBounds) override
|
||||
{
|
||||
if (newBounds != getComponent().getBounds())
|
||||
{
|
||||
ComponentScope scope (getComponent());
|
||||
rectangle.moveToAbsolute (newBounds.toFloat(), &scope);
|
||||
|
||||
applyToComponentBounds();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RelativeRectangle rectangle;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativeRectangleComponentPositioner)
|
||||
};
|
||||
|
||||
void RelativeRectangle::applyToComponent (Component& component) const
|
||||
{
|
||||
if (isDynamic())
|
||||
{
|
||||
RelativeRectangleComponentPositioner* current = dynamic_cast<RelativeRectangleComponentPositioner*> (component.getPositioner());
|
||||
|
||||
if (current == nullptr || ! current->isUsingRectangle (*this))
|
||||
{
|
||||
RelativeRectangleComponentPositioner* p = new RelativeRectangleComponentPositioner (component, *this);
|
||||
|
||||
component.setPositioner (p);
|
||||
p->apply();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
component.setPositioner (nullptr);
|
||||
component.setBounds (resolve (nullptr).getSmallestIntegerContainer());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace juce
|
108
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeRectangle.h
vendored
Normal file
108
deps/juce/modules/juce_gui_basics/positioning/juce_RelativeRectangle.h
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A rectangle stored as a set of RelativeCoordinate values.
|
||||
|
||||
The rectangle's top, left, bottom and right edge positions are each stored as a RelativeCoordinate.
|
||||
|
||||
@see RelativeCoordinate, RelativePoint
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API RelativeRectangle
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a zero-size rectangle at the origin. */
|
||||
RelativeRectangle();
|
||||
|
||||
/** Creates an absolute rectangle, relative to the origin. */
|
||||
explicit RelativeRectangle (const Rectangle<float>& rect);
|
||||
|
||||
/** Creates a rectangle from four coordinates. */
|
||||
RelativeRectangle (const RelativeCoordinate& left, const RelativeCoordinate& right,
|
||||
const RelativeCoordinate& top, const RelativeCoordinate& bottom);
|
||||
|
||||
/** Creates a rectangle from a stringified representation.
|
||||
The string must contain a sequence of 4 coordinates, separated by commas, in the order
|
||||
left, top, right, bottom. The syntax for the coordinate strings is explained in the
|
||||
RelativeCoordinate class.
|
||||
@see toString
|
||||
*/
|
||||
explicit RelativeRectangle (const String& stringVersion);
|
||||
|
||||
bool operator== (const RelativeRectangle&) const noexcept;
|
||||
bool operator!= (const RelativeRectangle&) const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Calculates the absolute position of this rectangle.
|
||||
|
||||
You'll need to provide a suitable Expression::Scope for looking up any coordinates that may
|
||||
be needed to calculate the result.
|
||||
*/
|
||||
const Rectangle<float> resolve (const Expression::Scope* scope) const;
|
||||
|
||||
/** Changes the values of this rectangle'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 Rectangle<float>& newPos, const Expression::Scope* scope);
|
||||
|
||||
/** Returns true if this rectangle depends on any external symbols for its position.
|
||||
Coordinates that refer to symbols based on "this" are assumed not to be dynamic.
|
||||
*/
|
||||
bool isDynamic() const;
|
||||
|
||||
/** Returns a string which represents this point.
|
||||
This returns a comma-separated list of coordinates, in the order left, top, right, bottom.
|
||||
If you're using this to position a Component, then see the notes for
|
||||
Component::setBounds (const RelativeRectangle&) for details of the syntax used.
|
||||
The string that is returned can be passed to the RelativeRectangle constructor to recreate the rectangle.
|
||||
*/
|
||||
String toString() const;
|
||||
|
||||
/** Renames a symbol if it is used by any of the coordinates.
|
||||
This calls Expression::withRenamedSymbol() on the rectangle's coordinates.
|
||||
*/
|
||||
void renameSymbol (const Expression::Symbol& oldSymbol, const String& newName, const Expression::Scope& scope);
|
||||
|
||||
/** Creates and sets an appropriate Component::Positioner object for the given component, which will
|
||||
keep it positioned with this rectangle.
|
||||
*/
|
||||
void applyToComponent (Component& component) const;
|
||||
|
||||
//==============================================================================
|
||||
// The actual rectangle coords...
|
||||
RelativeCoordinate left, right, top, bottom;
|
||||
};
|
||||
|
||||
} // namespace juce
|
Reference in New Issue
Block a user