Add remaining files
[juce-lv2.git] / juce / source / src / gui / components / positioning / juce_RelativeRectangle.cpp
blob3ed7cb575dadf26bd5dbf05a2cd6964dc70d64f1
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../../core/juce_StandardHeader.h"
28 BEGIN_JUCE_NAMESPACE
30 #include "juce_RelativeRectangle.h"
31 #include "juce_RelativeCoordinatePositioner.h"
34 //==============================================================================
35 namespace RelativeRectangleHelpers
37 inline void skipComma (String::CharPointerType& s)
39 s = s.findEndOfWhitespace();
41 if (*s == ',')
42 ++s;
45 bool dependsOnSymbolsOtherThanThis (const Expression& e)
47 if (e.getType() == Expression::operatorType && e.getSymbolOrFunction() == ".")
48 return true;
50 if (e.getType() == Expression::symbolType)
52 switch (RelativeCoordinate::StandardStrings::getTypeOf (e.getSymbolOrFunction()))
54 case RelativeCoordinate::StandardStrings::x:
55 case RelativeCoordinate::StandardStrings::y:
56 case RelativeCoordinate::StandardStrings::left:
57 case RelativeCoordinate::StandardStrings::right:
58 case RelativeCoordinate::StandardStrings::top:
59 case RelativeCoordinate::StandardStrings::bottom: return false;
60 default: break;
63 return true;
65 else
67 for (int i = e.getNumInputs(); --i >= 0;)
68 if (dependsOnSymbolsOtherThanThis (e.getInput(i)))
69 return true;
72 return false;
76 //==============================================================================
77 RelativeRectangle::RelativeRectangle()
81 RelativeRectangle::RelativeRectangle (const RelativeCoordinate& left_, const RelativeCoordinate& right_,
82 const RelativeCoordinate& top_, const RelativeCoordinate& bottom_)
83 : left (left_), right (right_), top (top_), bottom (bottom_)
87 RelativeRectangle::RelativeRectangle (const Rectangle<float>& rect)
88 : left (rect.getX()),
89 right (Expression::symbol (RelativeCoordinate::Strings::left) + Expression ((double) rect.getWidth())),
90 top (rect.getY()),
91 bottom (Expression::symbol (RelativeCoordinate::Strings::top) + Expression ((double) rect.getHeight()))
95 RelativeRectangle::RelativeRectangle (const String& s)
97 String::CharPointerType text (s.getCharPointer());
98 left = RelativeCoordinate (Expression::parse (text));
99 RelativeRectangleHelpers::skipComma (text);
100 top = RelativeCoordinate (Expression::parse (text));
101 RelativeRectangleHelpers::skipComma (text);
102 right = RelativeCoordinate (Expression::parse (text));
103 RelativeRectangleHelpers::skipComma (text);
104 bottom = RelativeCoordinate (Expression::parse (text));
107 bool RelativeRectangle::operator== (const RelativeRectangle& other) const noexcept
109 return left == other.left && top == other.top && right == other.right && bottom == other.bottom;
112 bool RelativeRectangle::operator!= (const RelativeRectangle& other) const noexcept
114 return ! operator== (other);
117 //==============================================================================
118 // An expression context that can evaluate expressions using "this"
119 class RelativeRectangleLocalScope : public Expression::Scope
121 public:
122 RelativeRectangleLocalScope (const RelativeRectangle& rect_) : rect (rect_) {}
124 Expression getSymbolValue (const String& symbol) const
126 switch (RelativeCoordinate::StandardStrings::getTypeOf (symbol))
128 case RelativeCoordinate::StandardStrings::x:
129 case RelativeCoordinate::StandardStrings::left: return rect.left.getExpression();
130 case RelativeCoordinate::StandardStrings::y:
131 case RelativeCoordinate::StandardStrings::top: return rect.top.getExpression();
132 case RelativeCoordinate::StandardStrings::right: return rect.right.getExpression();
133 case RelativeCoordinate::StandardStrings::bottom: return rect.bottom.getExpression();
134 default: break;
137 return Expression::Scope::getSymbolValue (symbol);
140 private:
141 const RelativeRectangle& rect;
143 JUCE_DECLARE_NON_COPYABLE (RelativeRectangleLocalScope);
146 const Rectangle<float> RelativeRectangle::resolve (const Expression::Scope* scope) const
148 if (scope == nullptr)
150 RelativeRectangleLocalScope defaultScope (*this);
151 return resolve (&defaultScope);
153 else
155 const double l = left.resolve (scope);
156 const double r = right.resolve (scope);
157 const double t = top.resolve (scope);
158 const double b = bottom.resolve (scope);
160 return Rectangle<float> ((float) l, (float) t, (float) jmax (0.0, r - l), (float) jmax (0.0, b - t));
164 void RelativeRectangle::moveToAbsolute (const Rectangle<float>& newPos, const Expression::Scope* scope)
166 left.moveToAbsolute (newPos.getX(), scope);
167 right.moveToAbsolute (newPos.getRight(), scope);
168 top.moveToAbsolute (newPos.getY(), scope);
169 bottom.moveToAbsolute (newPos.getBottom(), scope);
172 bool RelativeRectangle::isDynamic() const
174 using namespace RelativeRectangleHelpers;
176 return dependsOnSymbolsOtherThanThis (left.getExpression())
177 || dependsOnSymbolsOtherThanThis (right.getExpression())
178 || dependsOnSymbolsOtherThanThis (top.getExpression())
179 || dependsOnSymbolsOtherThanThis (bottom.getExpression());
182 String RelativeRectangle::toString() const
184 return left.toString() + ", " + top.toString() + ", " + right.toString() + ", " + bottom.toString();
187 void RelativeRectangle::renameSymbol (const Expression::Symbol& oldSymbol, const String& newName, const Expression::Scope& scope)
189 left = left.getExpression().withRenamedSymbol (oldSymbol, newName, scope);
190 right = right.getExpression().withRenamedSymbol (oldSymbol, newName, scope);
191 top = top.getExpression().withRenamedSymbol (oldSymbol, newName, scope);
192 bottom = bottom.getExpression().withRenamedSymbol (oldSymbol, newName, scope);
195 //==============================================================================
196 class RelativeRectangleComponentPositioner : public RelativeCoordinatePositionerBase
198 public:
199 RelativeRectangleComponentPositioner (Component& component_, const RelativeRectangle& rectangle_)
200 : RelativeCoordinatePositionerBase (component_),
201 rectangle (rectangle_)
205 bool registerCoordinates()
207 bool ok = addCoordinate (rectangle.left);
208 ok = addCoordinate (rectangle.right) && ok;
209 ok = addCoordinate (rectangle.top) && ok;
210 ok = addCoordinate (rectangle.bottom) && ok;
211 return ok;
214 bool isUsingRectangle (const RelativeRectangle& other) const noexcept
216 return rectangle == other;
219 void applyToComponentBounds()
221 for (int i = 4; --i >= 0;)
223 ComponentScope scope (getComponent());
224 const Rectangle<int> newBounds (rectangle.resolve (&scope).getSmallestIntegerContainer());
226 if (newBounds == getComponent().getBounds())
227 return;
229 getComponent().setBounds (newBounds);
232 jassertfalse; // must be a recursive reference!
235 void applyNewBounds (const Rectangle<int>& newBounds)
237 if (newBounds != getComponent().getBounds())
239 ComponentScope scope (getComponent());
240 rectangle.moveToAbsolute (newBounds.toFloat(), &scope);
242 applyToComponentBounds();
246 private:
247 RelativeRectangle rectangle;
249 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativeRectangleComponentPositioner);
252 void RelativeRectangle::applyToComponent (Component& component) const
254 if (isDynamic())
256 RelativeRectangleComponentPositioner* current = dynamic_cast <RelativeRectangleComponentPositioner*> (component.getPositioner());
258 if (current == nullptr || ! current->isUsingRectangle (*this))
260 RelativeRectangleComponentPositioner* p = new RelativeRectangleComponentPositioner (component, *this);
262 component.setPositioner (p);
263 p->apply();
266 else
268 component.setPositioner (nullptr);
269 component.setBounds (resolve (nullptr).getSmallestIntegerContainer());
274 END_JUCE_NAMESPACE