|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- /*
- ==============================================================================
-
- 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
|