Browse Source

New Component::setBounds() method using a RelativeRectangle.

Added Justification::appliedToRectangle() and RectanglePlacement::appliedTo(). Removed a behavioural oddity from TopLevelWindow which brought them to the front when made visible. More RelativeRectangle development. AU wrapper now detects app shutdown and closes its UI.
tags/2021-05-28
Julian Storer 15 years ago
parent
commit
c1d8ac22df
26 changed files with 526 additions and 267 deletions
  1. +10
    -18
      extras/Jucer (experimental)/Source/Project/jucer_ProjectInformationComponent.cpp
  2. +1
    -1
      extras/Jucer (experimental)/Source/Project/jucer_ProjectInformationComponent.h
  3. +5
    -0
      extras/Jucer (experimental)/Source/Utility/jucer_CodeHelpers.cpp
  4. +1
    -0
      extras/Jucer (experimental)/Source/Utility/jucer_CodeHelpers.h
  5. +0
    -49
      extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.h
  6. +20
    -2
      extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm
  7. +128
    -89
      juce_amalgamated.cpp
  8. +114
    -9
      juce_amalgamated.h
  9. +1
    -1
      src/audio/audio_sources/juce_ResamplingAudioSource.cpp
  10. +1
    -1
      src/core/juce_StandardHeader.h
  11. +9
    -11
      src/gui/components/juce_Component.cpp
  12. +48
    -1
      src/gui/components/juce_Component.h
  13. +42
    -1
      src/gui/components/positioning/juce_MarkerList.cpp
  14. +19
    -2
      src/gui/components/positioning/juce_MarkerList.h
  15. +1
    -1
      src/gui/components/positioning/juce_RelativeCoordinatePositioner.cpp
  16. +59
    -5
      src/gui/components/positioning/juce_RelativeRectangle.cpp
  17. +4
    -2
      src/gui/components/positioning/juce_RelativeRectangle.h
  18. +0
    -6
      src/gui/components/windows/juce_TopLevelWindow.cpp
  19. +0
    -2
      src/gui/components/windows/juce_TopLevelWindow.h
  20. +0
    -19
      src/gui/graphics/contexts/juce_Justification.cpp
  21. +25
    -2
      src/gui/graphics/contexts/juce_Justification.h
  22. +15
    -0
      src/gui/graphics/contexts/juce_RectanglePlacement.h
  23. +3
    -0
      src/gui/graphics/geometry/juce_Rectangle.h
  24. +14
    -15
      src/maths/juce_Expression.cpp
  25. +3
    -15
      src/native/mac/juce_mac_QuickTimeMovieComponent.mm
  26. +3
    -15
      src/native/windows/juce_win32_QuickTimeMovieComponent.cpp

+ 10
- 18
extras/Jucer (experimental)/Source/Project/jucer_ProjectInformationComponent.cpp View File

@@ -7,7 +7,7 @@
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created for JUCE version: JUCE v1.52.97
Created for JUCE version: JUCE v1.53.8
------------------------------------------------------------------------------
@@ -32,10 +32,6 @@ public:
{
}
~PropertiesWithHelpComponent()
{
}
void rebuildProperties()
{
getPanel().clear();
@@ -108,16 +104,21 @@ ProjectInformationComponent::ProjectInformationComponent (Project& project_)
configTabBox (TabbedButtonBar::TabsAtTop)
{
addAndMakeVisible (&configTabBox);
configTabBox.setBounds (RelativeRectangle ("8, 0, this.left + parent.right - 16, this.top + parent.bottom - 36"));
addAndMakeVisible (&editConfigsButton);
editConfigsButton.setBounds (RelativeRectangle ("8, parent.bottom - 30, this.left + 192, this.top + 22"));
editConfigsButton.setButtonText ("Add/Remove Configurations...");
editConfigsButton.addListener (this);
addAndMakeVisible (&openProjectButton);
openProjectButton.setBounds (RelativeRectangle ("608, parent.bottom - 30, this.left + 208, this.top + 22"));
openProjectButton.setButtonText ("Open Project in ");
openProjectButton.addListener (this);
addAndMakeVisible (&editExportersButton);
editExportersButton.setBounds (RelativeRectangle ("208, parent.bottom - 30, this.left + 160, this.top + 22"));
editExportersButton.setButtonText ("Add/Remove Exporters...");
editExportersButton.addListener (this);
addAndMakeVisible (&saveAndOpenButton);
saveAndOpenButton.setBounds (RelativeRectangle ("391, parent.bottom - 30, this.left + 208, this.top + 22"));
saveAndOpenButton.setButtonText ("Save And Open in");
saveAndOpenButton.addListener (this);
@@ -136,7 +137,7 @@ ProjectInformationComponent::ProjectInformationComponent (Project& project_)
#endif
//[/UserPreSize]
setSize (859, 479);
setSize (836, 427);
//[Constructor] You can add your own custom stuff here..
configTabBox.setOutline (1);
@@ -166,16 +167,7 @@ void ProjectInformationComponent::resized()
//[Userresized_Pre]
//[/Userresized_Pre]
configTabBox.setBounds (Rectangle<int>::leftTopRightBottom (8, 0, (int) ((8.0 + getWidth()) - 16.0),
(int) ((0.0 + getHeight()) - 36.0)));
editConfigsButton.setBounds (Rectangle<int>::leftTopRightBottom (8, (int) (getHeight() - 30.0), (int) (8.0 + 192.0),
(int) (getHeight() - 30.0 + 22.0)));
openProjectButton.setBounds (Rectangle<int>::leftTopRightBottom (608, (int) (getHeight() - 30.0), (int) (608.0 + 208.0),
(int) (getHeight() - 30.0 + 22.0)));
editExportersButton.setBounds (Rectangle<int>::leftTopRightBottom (208, (int) (getHeight() - 30.0),
(int) (208.0 + 160.0), (int) (getHeight() - 30.0 + 22.0)));
saveAndOpenButton.setBounds (Rectangle<int>::leftTopRightBottom (391, (int) (getHeight() - 30.0), (int) (391.0 + 208.0),
(int) (getHeight() - 30.0 + 22.0)));
//[Userresized_Post]
//[/Userresized_Post]
@@ -357,8 +349,8 @@ void ProjectInformationComponent::changeListenerCallback (ChangeBroadcaster*)
JUCER_COMPONENT_METADATA_START
<COMPONENT id="tO9EG1a" className="ProjectInformationComponent" width="859"
height="479" background="f6f9ff" parentClasses="public Component, public ChangeListener"
<COMPONENT id="tO9EG1a" className="ProjectInformationComponent" width="836"
height="427" background="f6f9ff" parentClasses="public Component, public ChangeListener"
constructorParams="Project&amp; project_" memberInitialisers="project (project_)">
<COMPONENTS>
<TABBEDCOMPONENT id="962c1575c4142253" memberName="configTabBox" focusOrder="0"


+ 1
- 1
extras/Jucer (experimental)/Source/Project/jucer_ProjectInformationComponent.h View File

@@ -7,7 +7,7 @@
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created for JUCE version: JUCE v1.52.97
Created for JUCE version: JUCE v1.53.8
------------------------------------------------------------------------------


+ 5
- 0
extras/Jucer (experimental)/Source/Utility/jucer_CodeHelpers.cpp View File

@@ -195,6 +195,11 @@ namespace CodeHelpers
return CodeHelpers::addEscapeChars (text).quoted();
}
const String stringLiteralIfNotEmpty (const String& text)
{
return text.isNotEmpty() ? stringLiteral (text) : String::empty;
}
const String boolLiteral (const bool b)
{
return b ? "true" : "false";


+ 1
- 0
extras/Jucer (experimental)/Source/Utility/jucer_CodeHelpers.h View File

@@ -37,6 +37,7 @@ namespace CodeHelpers
const String makeHeaderGuardName (const File& file);
const String stringLiteral (const String& text);
const String stringLiteralIfNotEmpty (const String& text); // if the string's empty, this returns an empty string
const String boolLiteral (bool b);
const String floatLiteral (float v);
const String doubleLiteral (double v);


+ 0
- 49
extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.h View File

@@ -84,52 +84,3 @@ private:
Colour colour;
GlyphArrangement glyphs;
};
//==============================================================================
class JucerToolbarButton : public ToolbarItemComponent
{
public:
//==============================================================================
JucerToolbarButton (int itemId_, const String& labelText)
: ToolbarItemComponent (itemId_, labelText, true)
{
setClickingTogglesState (false);
}
//==============================================================================
bool getToolbarItemSizes (int toolbarDepth, bool isToolbarVertical, int& preferredSize, int& minSize, int& maxSize)
{
preferredSize = minSize = maxSize = 50;
return true;
}
void paintButton (Graphics& g, bool over, bool down)
{
Path p;
p.addRoundedRectangle (1.5f, 2.5f, getWidth() - 3.0f, getHeight() - 5.0f, 3.0f);
if (getToggleState())
{
g.setColour (Colours::grey.withAlpha (0.5f));
g.fillPath (p);
}
g.setColour (Colours::darkgrey.withAlpha (0.3f));
g.strokePath (p, PathStrokeType (1.0f));
g.setFont (11.0f);
g.setColour (Colours::black.withAlpha ((over || down) ? 1.0f : 0.7f));
g.drawFittedText (getButtonText(), 2, 2, getWidth() - 4, getHeight() - 4, Justification::centred, 2);
}
void paintButtonArea (Graphics& g, int width, int height, bool isMouseOver, bool isMouseDown)
{
}
void contentAreaChanged (const Rectangle<int>& newBounds)
{
}
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JucerToolbarButton);
};

+ 20
- 2
extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm View File

@@ -109,6 +109,8 @@ class EditorCompHolder;
withAU: (JuceAU*) au
withComponent: (AudioProcessorEditor*) editorComp;
- (void) dealloc;
- (void) shutdown;
- (void) applicationWillTerminate: (NSNotification*) aNotification;
- (void) viewDidMoveToWindow;
- (BOOL) mouseDownCanMoveWindow;
- (void) filterBeingDeleted: (JuceAU*) au_;
@@ -1010,6 +1012,10 @@ public:
[self setHidden: NO];
[self setPostsFrameChangedNotifications: YES];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector (applicationWillTerminate:)
name: NSApplicationWillTerminateNotification
object: nil];
activeUIs.add (self);
editorComp->addToDesktop (0, (void*) self);
@@ -1019,6 +1025,20 @@ public:
}
- (void) dealloc
{
if (activeUIs.contains (self))
[self shutdown];
[super dealloc];
}
- (void) applicationWillTerminate: (NSNotification*) aNotification
{
(void) aNotification;
[self shutdown];
}
- (void) shutdown
{
// there's some kind of component currently modal, but the host
// is trying to delete our plugin..
@@ -1030,8 +1050,6 @@ public:
activeUIs.removeValue (self);
if (activePlugins.size() + activeUIs.size() == 0)
shutdownJuce_GUI();
[super dealloc];
}
- (void) viewDidMoveToWindow


+ 128
- 89
juce_amalgamated.cpp View File

@@ -4812,7 +4812,7 @@ public:
class Negate : public Term
{
public:
Negate (const TermPtr& input_) : input (input_)
explicit Negate (const TermPtr& input_) : input (input_)
{
jassert (input_ != 0);
}
@@ -4872,7 +4872,6 @@ public:
}

Type getType() const throw() { return operatorType; }

int getNumInputs() const { return 2; }
Term* getInput (int index) const { return index == 0 ? static_cast<Term*> (left) : (index == 1 ? static_cast<Term*> (right) : 0); }

@@ -5026,7 +5025,7 @@ public:

for (int i = topLevel->getNumInputs(); --i >= 0;)
{
Term* t = findDestinationFor (topLevel->getInput (i), inputTerm);
Term* const t = findDestinationFor (topLevel->getInput (i), inputTerm);

if (t != 0)
return t;
@@ -5038,7 +5037,7 @@ public:
static Constant* findTermToAdjust (Term* const term, const bool mustBeFlagged)
{
{
Constant* c = dynamic_cast<Constant*> (term);
Constant* const c = dynamic_cast<Constant*> (term);
if (c != 0 && (c->isResolutionTarget || ! mustBeFlagged))
return c;
}
@@ -5050,14 +5049,14 @@ public:
const int numIns = term->getNumInputs();
for (i = 0; i < numIns; ++i)
{
Constant* c = dynamic_cast<Constant*> (term->getInput (i));
Constant* const c = dynamic_cast<Constant*> (term->getInput (i));
if (c != 0 && (c->isResolutionTarget || ! mustBeFlagged))
return c;
}

for (i = 0; i < numIns; ++i)
{
Constant* c = findTermToAdjust (term->getInput (i), mustBeFlagged);
Constant* const c = findTermToAdjust (term->getInput (i), mustBeFlagged);
if (c != 0)
return c;
}
@@ -5067,7 +5066,7 @@ public:

static bool containsAnySymbols (const Term* const t)
{
if (dynamic_cast <const Symbol*> (t) != 0)
if (t->getType() == Expression::symbolType)
return true;

for (int i = t->getNumInputs(); --i >= 0;)
@@ -5079,7 +5078,7 @@ public:

static bool renameSymbol (Term* const t, const String& oldName, const String& newName)
{
Symbol* const sym = dynamic_cast <Symbol*> (t);
Symbol* const sym = dynamic_cast<Symbol*> (t);

if (sym != 0 && sym->mainSymbol == oldName)
{
@@ -5137,13 +5136,13 @@ public:
return c >= '0' && c <= '9';
}

void skipWhitespace (int& i)
void skipWhitespace (int& i) throw()
{
while (CharacterFunctions::isWhitespace (text [i]))
++i;
}

bool readChar (const juce_wchar required)
bool readChar (const juce_wchar required) throw()
{
if (text[textIndex] == required)
{
@@ -5154,7 +5153,7 @@ public:
return false;
}

bool readOperator (const char* ops, char* const opType = 0)
bool readOperator (const char* ops, char* const opType = 0) throw()
{
skipWhitespace (textIndex);

@@ -5174,7 +5173,7 @@ public:
return false;
}

bool readIdentifier (String& identifier)
bool readIdentifier (String& identifier) throw()
{
skipWhitespace (textIndex);
int i = textIndex;
@@ -5197,7 +5196,7 @@ public:
return false;
}

Term* readNumber()
Term* readNumber() throw()
{
skipWhitespace (textIndex);
int i = textIndex;
@@ -5321,7 +5320,7 @@ public:
{
if (readOperator ("(")) // method call...
{
Function* f = new Function (identifier, ReferenceCountedArray<Term>());
Function* const f = new Function (identifier, ReferenceCountedArray<Term>());
ScopedPointer<Term> func (f); // (can't use ScopedPointer<Function> in MSVC)

TermPtr param (readExpression());
@@ -5481,7 +5480,7 @@ const Expression Expression::adjustedToGiveNewResult (const double targetValue,

jassert (termToAdjust != 0);

const Term* parent = Helpers::findDestinationFor (newTerm, termToAdjust);
const Term* const parent = Helpers::findDestinationFor (newTerm, termToAdjust);

if (parent == 0)
{
@@ -24896,7 +24895,7 @@ void ResamplingAudioSource::releaseResources()

void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
float localRatio;
double localRatio;

{
const ScopedLock sl (ratioLock);
@@ -40595,10 +40594,12 @@ void Component::setTopRightPosition (const int x, const int y)

void Component::setBounds (const Rectangle<int>& r)
{
setBounds (r.getX(),
r.getY(),
r.getWidth(),
r.getHeight());
setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight());
}

void Component::setBounds (const RelativeRectangle& newBounds)
{
newBounds.applyToComponent (*this);
}

void Component::setBoundsRelative (const float x, const float y,
@@ -40675,13 +40676,8 @@ void Component::setBoundsToFit (int x, int y, int width, int height,
}

if (newW > 0 && newH > 0)
{
int newX, newY;
justification.applyToRectangle (newX, newY, newW, newH,
x, y, width, height);

setBounds (newX, newY, newW, newH);
}
setBounds (justification.appliedToRectangle (Rectangle<int> (0, 0, newW, newH),
Rectangle<int> (x, y, width, height)));
}
}

@@ -79265,12 +79261,6 @@ void TopLevelWindow::parentHierarchyChanged()
setDropShadowEnabled (useDropShadow);
}

void TopLevelWindow::visibilityChanged()
{
if (isShowing())
toFront (true);
}

int TopLevelWindow::getDesktopWindowStyleFlags() const
{
int styleFlags = ComponentPeer::windowAppearsOnTaskbar;
@@ -79642,6 +79632,45 @@ void MarkerList::ValueTreeWrapper::removeMarker (const ValueTree& marker, UndoMa
state.removeChild (marker, undoManager);
}

class MarkerListEvaluator : public Expression::EvaluationContext
{
public:
MarkerListEvaluator (const MarkerList& markerList_, Component* const parentComponent_)
: markerList (markerList_), parentComponent (parentComponent_)
{
}

const Expression getSymbolValue (const String& objectName, const String& member) const
{
if (member.isNotEmpty())
{
const MarkerList::Marker* const marker = markerList.getMarker (objectName);

if (marker != 0)
return Expression ((double) marker->position.resolve (this));
}
else if (parentComponent != 0 && objectName == RelativeCoordinate::Strings::parent)
{
if (member == RelativeCoordinate::Strings::right) return Expression ((double) parentComponent->getWidth());
if (member == RelativeCoordinate::Strings::bottom) return Expression ((double) parentComponent->getHeight());
}

return Expression::EvaluationContext::getSymbolValue (objectName, member);
}

private:
const MarkerList& markerList;
Component* parentComponent;

JUCE_DECLARE_NON_COPYABLE (MarkerListEvaluator);
};

double MarkerList::getMarkerPosition (const Marker& marker, Component* const parentComponent) const
{
MarkerListEvaluator context (*this, parentComponent);
return marker.position.resolve (&context);
}

void MarkerList::ValueTreeWrapper::applyTo (MarkerList& markerList)
{
const int numMarkers = getNumMarkers();
@@ -79918,6 +79947,26 @@ namespace RelativeRectangleHelpers
if (s[i] == ',')
++i;
}

bool dependsOnSymbolsOtherThanThis (const Expression& e)
{
if (e.getType() == Expression::symbolType)
{
String objectName, memberName;
e.getSymbolParts (objectName, memberName);

if (objectName != RelativeCoordinate::Strings::this_)
return true;
}
else
{
for (int i = e.getNumInputs(); --i >= 0;)
if (dependsOnSymbolsOtherThanThis (e.getInput(i)))
return true;
}

return false;
}
}

RelativeRectangle::RelativeRectangle()
@@ -79930,11 +79979,13 @@ RelativeRectangle::RelativeRectangle (const RelativeCoordinate& left_, const Rel
{
}

RelativeRectangle::RelativeRectangle (const Rectangle<float>& rect, const String& componentName)
RelativeRectangle::RelativeRectangle (const Rectangle<float>& rect)
: left (rect.getX()),
right (Expression::symbol (componentName + "." + RelativeCoordinate::Strings::left) + Expression ((double) rect.getWidth())),
right (Expression::symbol (RelativeCoordinate::Strings::this_ + "." + RelativeCoordinate::Strings::left)
+ Expression ((double) rect.getWidth())),
top (rect.getY()),
bottom (Expression::symbol (componentName + "." + RelativeCoordinate::Strings::top) + Expression ((double) rect.getHeight()))
bottom (Expression::symbol (RelativeCoordinate::Strings::this_ + "." + RelativeCoordinate::Strings::top)
+ Expression ((double) rect.getHeight()))
{
}

@@ -79980,7 +80031,12 @@ void RelativeRectangle::moveToAbsolute (const Rectangle<float>& newPos, const Ex

bool RelativeRectangle::isDynamic() const
{
return left.isDynamic() || right.isDynamic() || top.isDynamic() || bottom.isDynamic();
using namespace RelativeRectangleHelpers;

return dependsOnSymbolsOtherThanThis (left.getExpression())
|| dependsOnSymbolsOtherThanThis (right.getExpression())
|| dependsOnSymbolsOtherThanThis (top.getExpression())
|| dependsOnSymbolsOtherThanThis (bottom.getExpression());
}

const String RelativeRectangle::toString() const
@@ -80040,6 +80096,31 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativeRectangleComponentPositioner);
};

// An expression context that can evaluate expressions using "this"
class TemporaryRectangleContext : public Expression::EvaluationContext
{
public:
TemporaryRectangleContext (const RelativeRectangle& rect_) : rect (rect_) {}

const Expression getSymbolValue (const String& objectName, const String& edge) const
{
if (objectName == RelativeCoordinate::Strings::this_)
{
if (edge == RelativeCoordinate::Strings::left) return rect.left.getExpression();
if (edge == RelativeCoordinate::Strings::right) return rect.right.getExpression();
if (edge == RelativeCoordinate::Strings::top) return rect.top.getExpression();
if (edge == RelativeCoordinate::Strings::bottom) return rect.bottom.getExpression();
}

return Expression::EvaluationContext::getSymbolValue (objectName, edge);
}

private:
const RelativeRectangle& rect;

JUCE_DECLARE_NON_COPYABLE (TemporaryRectangleContext);
};

void RelativeRectangle::applyToComponent (Component& component) const
{
if (isDynamic())
@@ -80057,7 +80138,9 @@ void RelativeRectangle::applyToComponent (Component& component) const
else
{
component.setPositioner (0);
component.setBounds (resolve (0).getSmallestIntegerContainer());

TemporaryRectangleContext context (*this);
component.setBounds (resolve (&context).getSmallestIntegerContainer());
}
}

@@ -80496,7 +80579,7 @@ const Expression RelativeCoordinatePositionerBase::getSymbolValue (const String&
const MarkerList::Marker* const marker = markerList->getMarker (objectName);

if (marker != 0)
return marker->position.getExpression();
return Expression (markerList->getMarkerPosition (*marker, getComponent().getParentComponent()));
}

return Expression::EvaluationContext::getSymbolValue (objectName, member);
@@ -83256,26 +83339,6 @@ int Justification::getOnlyHorizontalFlags() const throw()
return flags & (left | right | horizontallyCentred | horizontallyJustified);
}

void Justification::applyToRectangle (int& x, int& y,
const int w, const int h,
const int spaceX, const int spaceY,
const int spaceW, const int spaceH) const throw()
{
if ((flags & horizontallyCentred) != 0)
x = spaceX + ((spaceW - w) >> 1);
else if ((flags & right) != 0)
x = spaceX + spaceW - w;
else
x = spaceX;

if ((flags & verticallyCentred) != 0)
y = spaceY + ((spaceH - h) >> 1);
else if ((flags & bottom) != 0)
y = spaceY + spaceH - h;
else
y = spaceY;
}

END_JUCE_NAMESPACE
/*** End of inlined file: juce_Justification.cpp ***/

@@ -246157,24 +246220,12 @@ void QuickTimeMovieComponent::setBoundsWithCorrectAspectRatio (const Rectangle<i
int normalWidth, normalHeight;
getMovieNormalSize (normalWidth, normalHeight);

if (normalWidth > 0 && normalHeight > 0 && ! spaceToFitWithin.isEmpty())
{
double x = 0.0, y = 0.0, w = normalWidth, h = normalHeight;

placement.applyTo (x, y, w, h,
spaceToFitWithin.getX(), spaceToFitWithin.getY(),
spaceToFitWithin.getWidth(), spaceToFitWithin.getHeight());
const Rectangle<int> normalSize (0, 0, normalWidth, normalHeight);

if (w > 0 && h > 0)
{
setBounds (roundToInt (x), roundToInt (y),
roundToInt (w), roundToInt (h));
}
}
if (! (spaceToFitWithin.isEmpty() || normalSize.isEmpty()))
setBounds (placement.appliedTo (normalSize, spaceToFitWithin));
else
{
setBounds (spaceToFitWithin);
}
}

#endif
@@ -275569,24 +275620,12 @@ void QuickTimeMovieComponent::setBoundsWithCorrectAspectRatio (const Rectangle<i
int normalWidth, normalHeight;
getMovieNormalSize (normalWidth, normalHeight);

if (normalWidth > 0 && normalHeight > 0 && ! spaceToFitWithin.isEmpty())
{
double x = 0.0, y = 0.0, w = normalWidth, h = normalHeight;
const Rectangle<int> normalSize (0, 0, normalWidth, normalHeight);

placement.applyTo (x, y, w, h,
spaceToFitWithin.getX(), spaceToFitWithin.getY(),
spaceToFitWithin.getWidth(), spaceToFitWithin.getHeight());

if (w > 0 && h > 0)
{
setBounds (roundToInt (x), roundToInt (y),
roundToInt (w), roundToInt (h));
}
}
if (! (spaceToFitWithin.isEmpty() || normalSize.isEmpty()))
setBounds (placement.appliedTo (normalSize, spaceToFitWithin));
else
{
setBounds (spaceToFitWithin);
}
}

#if ! (JUCE_MAC && JUCE_64BIT)


+ 114
- 9
juce_amalgamated.h View File

@@ -73,7 +73,7 @@ namespace JuceDummyNamespace {}
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53
#define JUCE_BUILDNUMBER 8
#define JUCE_BUILDNUMBER 9

/** Current Juce version number.

@@ -21954,6 +21954,9 @@ public:
/** Changes the position of the rectangle's top-left corner (leaving its size unchanged). */
void setPosition (const ValueType newX, const ValueType newY) throw() { x = newX; y = newY; }

/** Returns a rectangle with the same size as this one, but a new position. */
const Rectangle withPosition (const ValueType newX, const ValueType newY) const throw() { return Rectangle (newX, newY, w, h); }

/** Returns a rectangle with the same size as this one, but a new position. */
const Rectangle withPosition (const Point<ValueType>& newPos) const throw() { return Rectangle (newPos.getX(), newPos.getY(), w, h); }

@@ -22584,8 +22587,30 @@ public:
The (x, y) position of the rectangle will be updated to position it inside the
given space according to the justification flags.
*/
void applyToRectangle (int& x, int& y, int w, int h,
int spaceX, int spaceY, int spaceW, int spaceH) const throw();
template <typename ValueType>
void applyToRectangle (ValueType& x, ValueType& y, ValueType w, ValueType h,
ValueType spaceX, ValueType spaceY, ValueType spaceW, ValueType spaceH) const throw()
{
x = spaceX;
if ((flags & horizontallyCentred) != 0) x += (spaceW - w) / (ValueType) 2;
else if ((flags & right) != 0) x += spaceW - w;

y = spaceY;
if ((flags & verticallyCentred) != 0) y += (spaceH - h) / (ValueType) 2;
else if ((flags & bottom) != 0) y += spaceH - h;
}

/** Returns the new position of a rectangle that has been justified to fit within a given space.
*/
template <typename ValueType>
const Rectangle<ValueType> appliedToRectangle (const Rectangle<ValueType>& areaToAdjust,
const Rectangle<ValueType>& targetSpace) const throw()
{
ValueType x = areaToAdjust.getX(), y = areaToAdjust.getY();
applyToRectangle (x, y, areaToAdjust.getWidth(), areaToAdjust.getHeight(),
targetSpace.getX(), targetSpace.getY(), targetSpace.getWidth(), targetSpace.getHeight());
return areaToAdjust.withPosition (x, y);
}

/** Flag values that can be combined and used in the constructor. */
enum
@@ -25319,6 +25344,20 @@ public:
double destinationW,
double destinationH) const throw();

/** Returns the transform that should be applied to these source co-ordinates to fit them
into the destination rectangle using the current flags.
*/
template <typename ValueType>
const Rectangle<ValueType> appliedTo (const Rectangle<ValueType>& source,
const Rectangle<ValueType>& destination) const throw()
{
double x = source.getX(), y = source.getY(), w = source.getWidth(), h = source.getHeight();
applyTo (x, y, w, h, static_cast <double> (destination.getX()), static_cast <double> (destination.getY()),
static_cast <double> (destination.getWidth()), static_cast <double> (destination.getHeight()));
return Rectangle<ValueType> (static_cast <ValueType> (x), static_cast <ValueType> (y),
static_cast <ValueType> (w), static_cast <ValueType> (h));
}

/** Returns the transform that should be applied to these source co-ordinates to fit them
into the destination rectangle using the current flags.
*/
@@ -26895,6 +26934,7 @@ class MouseInputSource;
class MouseInputSourceInternal;
class ComponentPeer;
class MarkerList;
class RelativeRectangle;

/**
The base class for all JUCE user-interface objects.
@@ -27317,6 +27357,53 @@ public:
*/
void setBounds (const Rectangle<int>& newBounds);

/** Changes the component's position and size.

This is similar to the other setBounds() methods, but uses RelativeRectangle::applyToComponent()
to set the position, This uses a Component::Positioner to make sure that any dynamic
expressions are used in the RelativeRectangle will be automatically re-applied to the
component's bounds when the source values change. See RelativeRectangle::applyToComponent()
for more details.

When using relative expressions, the following symbols are available:
- "this.left", "this.right", "this.top", "this.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 "this.left + 100".
- "parent.left", "parent.right", "parent.top", "parent.bottom" refer to the parent component's
positions, in its own coordinate space, so "parent.left", "parent.right" are always 0, and
"parent.top", "parent.bottom" will actually be the width and height of the parent. So
for example to make your component's right-hand edge always 10 pixels away from its parent's
right-hand edge, you could set it to "parent.right - 10"
- "[id].left", "[id].right", "[id].top", "[id].bottom", 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"
- The name of a marker that is defined in the parent component. 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 remain centred within its parent with a size of 100, 100,
you could express it as:
@code myComp.setBounds (RelativeBounds ("parent.right / 2 - 50, parent.bottom / 2 - 50, this.left + 100, this.top + 100"));
@endcode
..or an alternative way to achieve the same thing:
@code myComp.setBounds (RelativeBounds ("this.right - 100, this.bottom - 100, parent.right / 2 + 50, parent.bottom / 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, this.left + 100, this.top + 100"));
@endcode

Be careful not to make your coordinate expressions recursive, though, or exceptions and assertions will
be thrown!

@see setBounds, RelativeRectangle::applyToComponent(), Expression
*/
void setBounds (const RelativeRectangle& newBounds);

/** Changes the component's position and size in terms of fractions of its parent's size.

The values are factors of the parent's size, so for example
@@ -45533,6 +45620,8 @@ public:
#ifndef __JUCE_MARKERLIST_JUCEHEADER__
#define __JUCE_MARKERLIST_JUCEHEADER__

class Component;

/**
Holds a set of named marker points along a one-dimensional axis.

@@ -45564,7 +45653,17 @@ public:
/** The marker's name. */
String name;

/** The marker's position. */
/** 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. */
@@ -45584,6 +45683,12 @@ public:
*/
const Marker* getMarker (const String& name) const throw();

/** 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
@@ -45659,7 +45764,7 @@ public:
private:

OwnedArray<Marker> markers;
ListenerList <Listener> listeners;
ListenerList<Listener> listeners;

JUCE_LEAK_DETECTOR (MarkerList);
};
@@ -51738,8 +51843,6 @@ protected:
/** @internal */
void parentHierarchyChanged();
/** @internal */
void visibilityChanged();
/** @internal */
virtual int getDesktopWindowStyleFlags() const;
/** @internal */
void recreateDesktopWindow();
@@ -57949,7 +58052,7 @@ public:
RelativeRectangle();

/** Creates an absolute rectangle, relative to the origin. */
explicit RelativeRectangle (const Rectangle<float>& rect, const String& componentName);
explicit RelativeRectangle (const Rectangle<float>& rect);

/** Creates a rectangle from four coordinates. */
RelativeRectangle (const RelativeCoordinate& left, const RelativeCoordinate& right,
@@ -57981,7 +58084,9 @@ public:
*/
void moveToAbsolute (const Rectangle<float>& newPos, const Expression::EvaluationContext* evaluationContext);

/** Returns true if this rectangle depends on any other coordinates for its position. */
/** 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.


+ 1
- 1
src/audio/audio_sources/juce_ResamplingAudioSource.cpp View File

@@ -88,7 +88,7 @@ void ResamplingAudioSource::releaseResources()
void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
float localRatio;
double localRatio;
{
const ScopedLock sl (ratioLock);


+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -33,7 +33,7 @@
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53
#define JUCE_BUILDNUMBER 8
#define JUCE_BUILDNUMBER 9
/** Current Juce version number.


+ 9
- 11
src/gui/components/juce_Component.cpp View File

@@ -41,6 +41,7 @@ BEGIN_JUCE_NAMESPACE
#include "../../core/juce_Time.h"
#include "../../core/juce_PlatformUtilities.h"
#include "mouse/juce_MouseInputSource.h"
#include "positioning/juce_RelativeRectangle.h"
//==============================================================================
@@ -1084,10 +1085,12 @@ void Component::setTopRightPosition (const int x, const int y)
void Component::setBounds (const Rectangle<int>& r)
{
setBounds (r.getX(),
r.getY(),
r.getWidth(),
r.getHeight());
setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
void Component::setBounds (const RelativeRectangle& newBounds)
{
newBounds.applyToComponent (*this);
}
void Component::setBoundsRelative (const float x, const float y,
@@ -1164,13 +1167,8 @@ void Component::setBoundsToFit (int x, int y, int width, int height,
}
if (newW > 0 && newH > 0)
{
int newX, newY;
justification.applyToRectangle (newX, newY, newW, newH,
x, y, width, height);
setBounds (newX, newY, newW, newH);
}
setBounds (justification.appliedToRectangle (Rectangle<int> (0, 0, newW, newH),
Rectangle<int> (x, y, width, height)));
}
}


+ 48
- 1
src/gui/components/juce_Component.h View File

@@ -48,7 +48,7 @@ class MouseInputSource;
class MouseInputSourceInternal;
class ComponentPeer;
class MarkerList;
class RelativeRectangle;
//==============================================================================
/**
@@ -479,6 +479,53 @@ public:
*/
void setBounds (const Rectangle<int>& newBounds);
/** Changes the component's position and size.
This is similar to the other setBounds() methods, but uses RelativeRectangle::applyToComponent()
to set the position, This uses a Component::Positioner to make sure that any dynamic
expressions are used in the RelativeRectangle will be automatically re-applied to the
component's bounds when the source values change. See RelativeRectangle::applyToComponent()
for more details.
When using relative expressions, the following symbols are available:
- "this.left", "this.right", "this.top", "this.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 "this.left + 100".
- "parent.left", "parent.right", "parent.top", "parent.bottom" refer to the parent component's
positions, in its own coordinate space, so "parent.left", "parent.right" are always 0, and
"parent.top", "parent.bottom" will actually be the width and height of the parent. So
for example to make your component's right-hand edge always 10 pixels away from its parent's
right-hand edge, you could set it to "parent.right - 10"
- "[id].left", "[id].right", "[id].top", "[id].bottom", 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"
- The name of a marker that is defined in the parent component. 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 remain centred within its parent with a size of 100, 100,
you could express it as:
@code myComp.setBounds (RelativeBounds ("parent.right / 2 - 50, parent.bottom / 2 - 50, this.left + 100, this.top + 100"));
@endcode
..or an alternative way to achieve the same thing:
@code myComp.setBounds (RelativeBounds ("this.right - 100, this.bottom - 100, parent.right / 2 + 50, parent.bottom / 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, this.left + 100, this.top + 100"));
@endcode
Be careful not to make your coordinate expressions recursive, though, or exceptions and assertions will
be thrown!
@see setBounds, RelativeRectangle::applyToComponent(), Expression
*/
void setBounds (const RelativeRectangle& newBounds);
/** Changes the component's position and size in terms of fractions of its parent's size.
The values are factors of the parent's size, so for example


+ 42
- 1
src/gui/components/positioning/juce_MarkerList.cpp View File

@@ -28,7 +28,7 @@
BEGIN_JUCE_NAMESPACE
#include "juce_MarkerList.h"
#include "../juce_Component.h"
//==============================================================================
MarkerList::MarkerList()
@@ -246,6 +246,47 @@ void MarkerList::ValueTreeWrapper::removeMarker (const ValueTree& marker, UndoMa
state.removeChild (marker, undoManager);
}
//==============================================================================
class MarkerListEvaluator : public Expression::EvaluationContext
{
public:
MarkerListEvaluator (const MarkerList& markerList_, Component* const parentComponent_)
: markerList (markerList_), parentComponent (parentComponent_)
{
}
const Expression getSymbolValue (const String& objectName, const String& member) const
{
if (member.isNotEmpty())
{
const MarkerList::Marker* const marker = markerList.getMarker (objectName);
if (marker != 0)
return Expression ((double) marker->position.resolve (this));
}
else if (parentComponent != 0 && objectName == RelativeCoordinate::Strings::parent)
{
if (member == RelativeCoordinate::Strings::right) return Expression ((double) parentComponent->getWidth());
if (member == RelativeCoordinate::Strings::bottom) return Expression ((double) parentComponent->getHeight());
}
return Expression::EvaluationContext::getSymbolValue (objectName, member);
}
private:
const MarkerList& markerList;
Component* parentComponent;
JUCE_DECLARE_NON_COPYABLE (MarkerListEvaluator);
};
double MarkerList::getMarkerPosition (const Marker& marker, Component* const parentComponent) const
{
MarkerListEvaluator context (*this, parentComponent);
return marker.position.resolve (&context);
}
//==============================================================================
void MarkerList::ValueTreeWrapper::applyTo (MarkerList& markerList)
{
const int numMarkers = getNumMarkers();


+ 19
- 2
src/gui/components/positioning/juce_MarkerList.h View File

@@ -28,6 +28,7 @@
#include "../../../containers/juce_ValueTree.h"
#include "../positioning/juce_RelativeCoordinate.h"
class Component;
//==============================================================================
@@ -63,7 +64,17 @@ public:
/** The marker's name. */
String name;
/** The marker's position. */
/** 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. */
@@ -84,6 +95,12 @@ public:
*/
const Marker* getMarker (const String& name) const throw();
/** 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
@@ -161,7 +178,7 @@ public:
private:
//==============================================================================
OwnedArray<Marker> markers;
ListenerList <Listener> listeners;
ListenerList<Listener> listeners;
JUCE_LEAK_DETECTOR (MarkerList);
};


+ 1
- 1
src/gui/components/positioning/juce_RelativeCoordinatePositioner.cpp View File

@@ -72,7 +72,7 @@ const Expression RelativeCoordinatePositionerBase::getSymbolValue (const String&
const MarkerList::Marker* const marker = markerList->getMarker (objectName);
if (marker != 0)
return marker->position.getExpression();
return Expression (markerList->getMarkerPosition (*marker, getComponent().getParentComponent()));
}
return Expression::EvaluationContext::getSymbolValue (objectName, member);


+ 59
- 5
src/gui/components/positioning/juce_RelativeRectangle.cpp View File

@@ -40,6 +40,26 @@ namespace RelativeRectangleHelpers
if (s[i] == ',')
++i;
}
bool dependsOnSymbolsOtherThanThis (const Expression& e)
{
if (e.getType() == Expression::symbolType)
{
String objectName, memberName;
e.getSymbolParts (objectName, memberName);
if (objectName != RelativeCoordinate::Strings::this_)
return true;
}
else
{
for (int i = e.getNumInputs(); --i >= 0;)
if (dependsOnSymbolsOtherThanThis (e.getInput(i)))
return true;
}
return false;
}
}
//==============================================================================
@@ -53,11 +73,13 @@ RelativeRectangle::RelativeRectangle (const RelativeCoordinate& left_, const Rel
{
}
RelativeRectangle::RelativeRectangle (const Rectangle<float>& rect, const String& componentName)
RelativeRectangle::RelativeRectangle (const Rectangle<float>& rect)
: left (rect.getX()),
right (Expression::symbol (componentName + "." + RelativeCoordinate::Strings::left) + Expression ((double) rect.getWidth())),
right (Expression::symbol (RelativeCoordinate::Strings::this_ + "." + RelativeCoordinate::Strings::left)
+ Expression ((double) rect.getWidth())),
top (rect.getY()),
bottom (Expression::symbol (componentName + "." + RelativeCoordinate::Strings::top) + Expression ((double) rect.getHeight()))
bottom (Expression::symbol (RelativeCoordinate::Strings::this_ + "." + RelativeCoordinate::Strings::top)
+ Expression ((double) rect.getHeight()))
{
}
@@ -103,7 +125,12 @@ void RelativeRectangle::moveToAbsolute (const Rectangle<float>& newPos, const Ex
bool RelativeRectangle::isDynamic() const
{
return left.isDynamic() || right.isDynamic() || top.isDynamic() || bottom.isDynamic();
using namespace RelativeRectangleHelpers;
return dependsOnSymbolsOtherThanThis (left.getExpression())
|| dependsOnSymbolsOtherThanThis (right.getExpression())
|| dependsOnSymbolsOtherThanThis (top.getExpression())
|| dependsOnSymbolsOtherThanThis (bottom.getExpression());
}
const String RelativeRectangle::toString() const
@@ -164,6 +191,31 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RelativeRectangleComponentPositioner);
};
// An expression context that can evaluate expressions using "this"
class TemporaryRectangleContext : public Expression::EvaluationContext
{
public:
TemporaryRectangleContext (const RelativeRectangle& rect_) : rect (rect_) {}
const Expression getSymbolValue (const String& objectName, const String& edge) const
{
if (objectName == RelativeCoordinate::Strings::this_)
{
if (edge == RelativeCoordinate::Strings::left) return rect.left.getExpression();
if (edge == RelativeCoordinate::Strings::right) return rect.right.getExpression();
if (edge == RelativeCoordinate::Strings::top) return rect.top.getExpression();
if (edge == RelativeCoordinate::Strings::bottom) return rect.bottom.getExpression();
}
return Expression::EvaluationContext::getSymbolValue (objectName, edge);
}
private:
const RelativeRectangle& rect;
JUCE_DECLARE_NON_COPYABLE (TemporaryRectangleContext);
};
void RelativeRectangle::applyToComponent (Component& component) const
{
if (isDynamic())
@@ -181,7 +233,9 @@ void RelativeRectangle::applyToComponent (Component& component) const
else
{
component.setPositioner (0);
component.setBounds (resolve (0).getSmallestIntegerContainer());
TemporaryRectangleContext context (*this);
component.setBounds (resolve (&context).getSmallestIntegerContainer());
}
}


+ 4
- 2
src/gui/components/positioning/juce_RelativeRectangle.h View File

@@ -45,7 +45,7 @@ public:
RelativeRectangle();
/** Creates an absolute rectangle, relative to the origin. */
explicit RelativeRectangle (const Rectangle<float>& rect, const String& componentName);
explicit RelativeRectangle (const Rectangle<float>& rect);
/** Creates a rectangle from four coordinates. */
RelativeRectangle (const RelativeCoordinate& left, const RelativeCoordinate& right,
@@ -78,7 +78,9 @@ public:
*/
void moveToAbsolute (const Rectangle<float>& newPos, const Expression::EvaluationContext* evaluationContext);
/** Returns true if this rectangle depends on any other coordinates for its position. */
/** 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.


+ 0
- 6
src/gui/components/windows/juce_TopLevelWindow.cpp View File

@@ -192,12 +192,6 @@ void TopLevelWindow::parentHierarchyChanged()
setDropShadowEnabled (useDropShadow);
}
void TopLevelWindow::visibilityChanged()
{
if (isShowing())
toFront (true);
}
int TopLevelWindow::getDesktopWindowStyleFlags() const
{
int styleFlags = ComponentPeer::windowAppearsOnTaskbar;


+ 0
- 2
src/gui/components/windows/juce_TopLevelWindow.h View File

@@ -148,8 +148,6 @@ protected:
/** @internal */
void parentHierarchyChanged();
/** @internal */
void visibilityChanged();
/** @internal */
virtual int getDesktopWindowStyleFlags() const;
/** @internal */
void recreateDesktopWindow();


+ 0
- 19
src/gui/graphics/contexts/juce_Justification.cpp View File

@@ -52,24 +52,5 @@ int Justification::getOnlyHorizontalFlags() const throw()
return flags & (left | right | horizontallyCentred | horizontallyJustified);
}
void Justification::applyToRectangle (int& x, int& y,
const int w, const int h,
const int spaceX, const int spaceY,
const int spaceW, const int spaceH) const throw()
{
if ((flags & horizontallyCentred) != 0)
x = spaceX + ((spaceW - w) >> 1);
else if ((flags & right) != 0)
x = spaceX + spaceW - w;
else
x = spaceX;
if ((flags & verticallyCentred) != 0)
y = spaceY + ((spaceH - h) >> 1);
else if ((flags & bottom) != 0)
y = spaceY + spaceH - h;
else
y = spaceY;
}
END_JUCE_NAMESPACE

+ 25
- 2
src/gui/graphics/contexts/juce_Justification.h View File

@@ -26,6 +26,8 @@
#ifndef __JUCE_JUSTIFICATION_JUCEHEADER__
#define __JUCE_JUSTIFICATION_JUCEHEADER__
#include "../geometry/juce_Rectangle.h"
//==============================================================================
/**
@@ -74,9 +76,30 @@ public:
The (x, y) position of the rectangle will be updated to position it inside the
given space according to the justification flags.
*/
void applyToRectangle (int& x, int& y, int w, int h,
int spaceX, int spaceY, int spaceW, int spaceH) const throw();
template <typename ValueType>
void applyToRectangle (ValueType& x, ValueType& y, ValueType w, ValueType h,
ValueType spaceX, ValueType spaceY, ValueType spaceW, ValueType spaceH) const throw()
{
x = spaceX;
if ((flags & horizontallyCentred) != 0) x += (spaceW - w) / (ValueType) 2;
else if ((flags & right) != 0) x += spaceW - w;
y = spaceY;
if ((flags & verticallyCentred) != 0) y += (spaceH - h) / (ValueType) 2;
else if ((flags & bottom) != 0) y += spaceH - h;
}
/** Returns the new position of a rectangle that has been justified to fit within a given space.
*/
template <typename ValueType>
const Rectangle<ValueType> appliedToRectangle (const Rectangle<ValueType>& areaToAdjust,
const Rectangle<ValueType>& targetSpace) const throw()
{
ValueType x = areaToAdjust.getX(), y = areaToAdjust.getY();
applyToRectangle (x, y, areaToAdjust.getWidth(), areaToAdjust.getHeight(),
targetSpace.getX(), targetSpace.getY(), targetSpace.getWidth(), targetSpace.getHeight());
return areaToAdjust.withPosition (x, y);
}
//==============================================================================
/** Flag values that can be combined and used in the constructor. */


+ 15
- 0
src/gui/graphics/contexts/juce_RectanglePlacement.h View File

@@ -141,12 +141,27 @@ public:
double destinationW,
double destinationH) const throw();
/** Returns the transform that should be applied to these source co-ordinates to fit them
into the destination rectangle using the current flags.
*/
template <typename ValueType>
const Rectangle<ValueType> appliedTo (const Rectangle<ValueType>& source,
const Rectangle<ValueType>& destination) const throw()
{
double x = source.getX(), y = source.getY(), w = source.getWidth(), h = source.getHeight();
applyTo (x, y, w, h, static_cast <double> (destination.getX()), static_cast <double> (destination.getY()),
static_cast <double> (destination.getWidth()), static_cast <double> (destination.getHeight()));
return Rectangle<ValueType> (static_cast <ValueType> (x), static_cast <ValueType> (y),
static_cast <ValueType> (w), static_cast <ValueType> (h));
}
/** Returns the transform that should be applied to these source co-ordinates to fit them
into the destination rectangle using the current flags.
*/
const AffineTransform getTransformToFit (const Rectangle<float>& source,
const Rectangle<float>& destination) const throw();
private:
//==============================================================================
int flags;


+ 3
- 0
src/gui/graphics/geometry/juce_Rectangle.h View File

@@ -149,6 +149,9 @@ public:
/** Changes the position of the rectangle's top-left corner (leaving its size unchanged). */
void setPosition (const ValueType newX, const ValueType newY) throw() { x = newX; y = newY; }
/** Returns a rectangle with the same size as this one, but a new position. */
const Rectangle withPosition (const ValueType newX, const ValueType newY) const throw() { return Rectangle (newX, newY, w, h); }
/** Returns a rectangle with the same size as this one, but a new position. */
const Rectangle withPosition (const Point<ValueType>& newPos) const throw() { return Rectangle (newPos.getX(), newPos.getY(), w, h); }


+ 14
- 15
src/maths/juce_Expression.cpp View File

@@ -196,7 +196,7 @@ public:
class Negate : public Term
{
public:
Negate (const TermPtr& input_) : input (input_)
explicit Negate (const TermPtr& input_) : input (input_)
{
jassert (input_ != 0);
}
@@ -257,7 +257,6 @@ public:
}
Type getType() const throw() { return operatorType; }
int getNumInputs() const { return 2; }
Term* getInput (int index) const { return index == 0 ? static_cast<Term*> (left) : (index == 1 ? static_cast<Term*> (right) : 0); }
@@ -416,7 +415,7 @@ public:
for (int i = topLevel->getNumInputs(); --i >= 0;)
{
Term* t = findDestinationFor (topLevel->getInput (i), inputTerm);
Term* const t = findDestinationFor (topLevel->getInput (i), inputTerm);
if (t != 0)
return t;
@@ -428,7 +427,7 @@ public:
static Constant* findTermToAdjust (Term* const term, const bool mustBeFlagged)
{
{
Constant* c = dynamic_cast<Constant*> (term);
Constant* const c = dynamic_cast<Constant*> (term);
if (c != 0 && (c->isResolutionTarget || ! mustBeFlagged))
return c;
}
@@ -440,14 +439,14 @@ public:
const int numIns = term->getNumInputs();
for (i = 0; i < numIns; ++i)
{
Constant* c = dynamic_cast<Constant*> (term->getInput (i));
Constant* const c = dynamic_cast<Constant*> (term->getInput (i));
if (c != 0 && (c->isResolutionTarget || ! mustBeFlagged))
return c;
}
for (i = 0; i < numIns; ++i)
{
Constant* c = findTermToAdjust (term->getInput (i), mustBeFlagged);
Constant* const c = findTermToAdjust (term->getInput (i), mustBeFlagged);
if (c != 0)
return c;
}
@@ -457,7 +456,7 @@ public:
static bool containsAnySymbols (const Term* const t)
{
if (dynamic_cast <const Symbol*> (t) != 0)
if (t->getType() == Expression::symbolType)
return true;
for (int i = t->getNumInputs(); --i >= 0;)
@@ -469,7 +468,7 @@ public:
static bool renameSymbol (Term* const t, const String& oldName, const String& newName)
{
Symbol* const sym = dynamic_cast <Symbol*> (t);
Symbol* const sym = dynamic_cast<Symbol*> (t);
if (sym != 0 && sym->mainSymbol == oldName)
{
@@ -529,13 +528,13 @@ public:
return c >= '0' && c <= '9';
}
void skipWhitespace (int& i)
void skipWhitespace (int& i) throw()
{
while (CharacterFunctions::isWhitespace (text [i]))
++i;
}
bool readChar (const juce_wchar required)
bool readChar (const juce_wchar required) throw()
{
if (text[textIndex] == required)
{
@@ -546,7 +545,7 @@ public:
return false;
}
bool readOperator (const char* ops, char* const opType = 0)
bool readOperator (const char* ops, char* const opType = 0) throw()
{
skipWhitespace (textIndex);
@@ -566,7 +565,7 @@ public:
return false;
}
bool readIdentifier (String& identifier)
bool readIdentifier (String& identifier) throw()
{
skipWhitespace (textIndex);
int i = textIndex;
@@ -589,7 +588,7 @@ public:
return false;
}
Term* readNumber()
Term* readNumber() throw()
{
skipWhitespace (textIndex);
int i = textIndex;
@@ -713,7 +712,7 @@ public:
{
if (readOperator ("(")) // method call...
{
Function* f = new Function (identifier, ReferenceCountedArray<Term>());
Function* const f = new Function (identifier, ReferenceCountedArray<Term>());
ScopedPointer<Term> func (f); // (can't use ScopedPointer<Function> in MSVC)
TermPtr param (readExpression());
@@ -874,7 +873,7 @@ const Expression Expression::adjustedToGiveNewResult (const double targetValue,
jassert (termToAdjust != 0);
const Term* parent = Helpers::findDestinationFor (newTerm, termToAdjust);
const Term* const parent = Helpers::findDestinationFor (newTerm, termToAdjust);
if (parent == 0)
{


+ 3
- 15
src/native/mac/juce_mac_QuickTimeMovieComponent.mm View File

@@ -324,24 +324,12 @@ void QuickTimeMovieComponent::setBoundsWithCorrectAspectRatio (const Rectangle<i
int normalWidth, normalHeight;
getMovieNormalSize (normalWidth, normalHeight);
if (normalWidth > 0 && normalHeight > 0 && ! spaceToFitWithin.isEmpty())
{
double x = 0.0, y = 0.0, w = normalWidth, h = normalHeight;
placement.applyTo (x, y, w, h,
spaceToFitWithin.getX(), spaceToFitWithin.getY(),
spaceToFitWithin.getWidth(), spaceToFitWithin.getHeight());
const Rectangle<int> normalSize (0, 0, normalWidth, normalHeight);
if (w > 0 && h > 0)
{
setBounds (roundToInt (x), roundToInt (y),
roundToInt (w), roundToInt (h));
}
}
if (! (spaceToFitWithin.isEmpty() || normalSize.isEmpty()))
setBounds (placement.appliedTo (normalSize, spaceToFitWithin));
else
{
setBounds (spaceToFitWithin);
}
}


+ 3
- 15
src/native/windows/juce_win32_QuickTimeMovieComponent.cpp View File

@@ -478,24 +478,12 @@ void QuickTimeMovieComponent::setBoundsWithCorrectAspectRatio (const Rectangle<i
int normalWidth, normalHeight;
getMovieNormalSize (normalWidth, normalHeight);
if (normalWidth > 0 && normalHeight > 0 && ! spaceToFitWithin.isEmpty())
{
double x = 0.0, y = 0.0, w = normalWidth, h = normalHeight;
placement.applyTo (x, y, w, h,
spaceToFitWithin.getX(), spaceToFitWithin.getY(),
spaceToFitWithin.getWidth(), spaceToFitWithin.getHeight());
const Rectangle<int> normalSize (0, 0, normalWidth, normalHeight);
if (w > 0 && h > 0)
{
setBounds (roundToInt (x), roundToInt (y),
roundToInt (w), roundToInt (h));
}
}
if (! (spaceToFitWithin.isEmpty() || normalSize.isEmpty()))
setBounds (placement.appliedTo (normalSize, spaceToFitWithin));
else
{
setBounds (spaceToFitWithin);
}
}
#endif

Loading…
Cancel
Save