diff --git a/extras/Projucer/Source/Wizards/jucer_TemplateThumbnailsComponent.h b/extras/Projucer/Source/Wizards/jucer_TemplateThumbnailsComponent.h index 393ca7d430..4cbdad09e6 100644 --- a/extras/Projucer/Source/Wizards/jucer_TemplateThumbnailsComponent.h +++ b/extras/Projucer/Source/Wizards/jucer_TemplateThumbnailsComponent.h @@ -107,7 +107,7 @@ public: void resized() override { - thumb->setBoundsToFit (0, 0, getWidth(), getHeight(), Justification::centred, false); + thumb->setBoundsToFit (getLocalBounds(), Justification::centred, false); } void setDescription (String descript) noexcept diff --git a/modules/juce_gui_basics/components/juce_Component.cpp b/modules/juce_gui_basics/components/juce_Component.cpp index 2e66c7daf0..3f1b39b0f5 100644 --- a/modules/juce_gui_basics/components/juce_Component.cpp +++ b/modules/juce_gui_basics/components/juce_Component.cpp @@ -255,6 +255,8 @@ struct ScalingHelpers static Rectangle subtractPosition (Rectangle p, const Component& c) noexcept { return p - c.getPosition().toFloat(); } }; +static const char colourPropertyPrefix[] = "jcclr_"; + //============================================================================== struct Component::ComponentHelpers { @@ -265,30 +267,26 @@ struct Component::ComponentHelpers } #endif - static Identifier getColourPropertyId (int colourId) + static Identifier getColourPropertyID (int colourID) { - char reversedHex[32]; - char* t = reversedHex; + char buffer[32]; + auto* end = buffer + numElementsInArray (buffer) - 1; + auto* t = end; + *t = 0; - for (unsigned int v = (unsigned int) colourId;;) + for (auto v = (uint32) colourID;;) { - *t++ = "0123456789abcdef" [(int) (v & 15)]; + *--t = "0123456789abcdef" [v & 15]; v >>= 4; if (v == 0) break; } - char destBuffer[32]; - char* dest = destBuffer; - memcpy (dest, "jcclr_", 6); - dest += 6; - - while (t > reversedHex) - *dest++ = *--t; + for (int i = (int) sizeof (colourPropertyPrefix) - 1; --i >= 0;) + *--t = colourPropertyPrefix[i]; - *dest++ = 0; - return destBuffer; + return t; } //============================================================================== @@ -672,6 +670,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo) peer->setVisible (isVisible()); peer = ComponentPeer::getPeerFor (this); + if (peer == nullptr) return; @@ -768,9 +767,8 @@ bool Component::isOpaque() const noexcept } //============================================================================== -class StandardCachedComponentImage : public CachedComponentImage +struct StandardCachedComponentImage : public CachedComponentImage { -public: StandardCachedComponentImage (Component& c) noexcept : owner (c), scale (1.0f) {} void paint (Graphics& g) override @@ -938,7 +936,7 @@ void Component::toBehind (Component* other) if (index >= 0 && childList [index + 1] != other) { - int otherIndex = childList.indexOf (other); + auto otherIndex = childList.indexOf (other); if (otherIndex >= 0) { @@ -1046,46 +1044,23 @@ int Component::getParentHeight() const noexcept : getParentMonitorArea().getHeight(); } -int Component::getScreenX() const { return getScreenPosition().x; } -int Component::getScreenY() const { return getScreenPosition().y; } - -Point Component::getScreenPosition() const { return localPointToGlobal (Point()); } -Rectangle Component::getScreenBounds() const { return localAreaToGlobal (getLocalBounds()); } - Rectangle Component::getParentMonitorArea() const { return Desktop::getInstance().getDisplays().getDisplayContaining (getScreenBounds().getCentre()).userArea; } -Point Component::getLocalPoint (const Component* source, Point point) const -{ - return ComponentHelpers::convertCoordinate (this, source, point); -} +int Component::getScreenX() const { return getScreenPosition().x; } +int Component::getScreenY() const { return getScreenPosition().y; } +Point Component::getScreenPosition() const { return localPointToGlobal (Point()); } +Rectangle Component::getScreenBounds() const { return localAreaToGlobal (getLocalBounds()); } -Point Component::getLocalPoint (const Component* source, Point point) const -{ - return ComponentHelpers::convertCoordinate (this, source, point); -} - -Rectangle Component::getLocalArea (const Component* source, Rectangle area) const -{ - return ComponentHelpers::convertCoordinate (this, source, area); -} +Point Component::getLocalPoint (const Component* source, Point point) const { return ComponentHelpers::convertCoordinate (this, source, point); } +Point Component::getLocalPoint (const Component* source, Point point) const { return ComponentHelpers::convertCoordinate (this, source, point); } +Rectangle Component::getLocalArea (const Component* source, Rectangle area) const { return ComponentHelpers::convertCoordinate (this, source, area); } -Point Component::localPointToGlobal (Point point) const -{ - return ComponentHelpers::convertCoordinate (nullptr, this, point); -} - -Point Component::localPointToGlobal (Point point) const -{ - return ComponentHelpers::convertCoordinate (nullptr, this, point); -} - -Rectangle Component::localAreaToGlobal (Rectangle area) const -{ - return ComponentHelpers::convertCoordinate (nullptr, this, area); -} +Point Component::localPointToGlobal (Point point) const { return ComponentHelpers::convertCoordinate (nullptr, this, point); } +Point Component::localPointToGlobal (Point point) const { return ComponentHelpers::convertCoordinate (nullptr, this, point); } +Rectangle Component::localAreaToGlobal (Rectangle area) const { return ComponentHelpers::convertCoordinate (nullptr, this, area); } //============================================================================== void Component::setBounds (int x, int y, int w, int h) @@ -1194,55 +1169,38 @@ void Component::sendMovedResizedMessages (bool wasMoved, bool wasResized) componentListeners.callChecked (checker, [=] (ComponentListener& l) { l.componentMovedOrResized (*this, wasMoved, wasResized); }); } -void Component::setSize (int w, int h) -{ - setBounds (getX(), getY(), w, h); -} +void Component::setSize (int w, int h) { setBounds (getX(), getY(), w, h); } -void Component::setTopLeftPosition (int x, int y) -{ - setBounds (x, y, getWidth(), getHeight()); -} +void Component::setTopLeftPosition (int x, int y) { setTopLeftPosition ({ x, y }); } +void Component::setTopLeftPosition (Point pos) { setBounds (pos.x, pos.y, getWidth(), getHeight()); } -void Component::setTopLeftPosition (Point pos) -{ - setBounds (pos.x, pos.y, getWidth(), getHeight()); -} +void Component::setTopRightPosition (int x, int y) { setTopLeftPosition (x - getWidth(), y); } +void Component::setBounds (Rectangle r) { setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight()); } -void Component::setTopRightPosition (int x, int y) -{ - setTopLeftPosition (x - getWidth(), y); -} +void Component::setCentrePosition (Point p) { setBounds (getBounds().withCentre (p.transformedBy (getTransform().inverted()))); } +void Component::setCentrePosition (int x, int y) { setCentrePosition ({ x, y }); } -void Component::setBounds (Rectangle r) +void Component::setCentreRelative (float x, float y) { - setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight()); + setCentrePosition (roundToInt (getParentWidth() * x), + roundToInt (getParentHeight() * y)); } -void Component::setBoundsRelative (float x, float y, float w, float h) +void Component::setBoundsRelative (Rectangle target) { - auto pw = getParentWidth(); - auto ph = getParentHeight(); - - setBounds (roundToInt (x * pw), - roundToInt (y * ph), - roundToInt (w * pw), - roundToInt (h * ph)); + setBounds ((target * Point ((float) getParentWidth(), + (float) getParentHeight())).toNearestInt()); } -void Component::setCentrePosition (Point p) { setBounds (getBounds().withCentre (p.transformedBy (getTransform().inverted()))); } -void Component::setCentrePosition (int x, int y) { setCentrePosition ({x, y}); } - -void Component::setCentreRelative (float x, float y) +void Component::setBoundsRelative (float x, float y, float w, float h) { - setCentrePosition (roundToInt (getParentWidth() * x), - roundToInt (getParentHeight() * y)); + setBoundsRelative ({ x, y, w, h }); } void Component::centreWithSize (int width, int height) { auto parentArea = ComponentHelpers::getParentOrMainMonitorBounds (*this) - .transformedBy (getTransform().inverted()); + .transformedBy (getTransform().inverted()); setBounds (parentArea.getCentreX() - width / 2, parentArea.getCentreY() - height / 2, @@ -1254,44 +1212,39 @@ void Component::setBoundsInset (BorderSize borders) setBounds (borders.subtractedFrom (ComponentHelpers::getParentOrMainMonitorBounds (*this))); } -void Component::setBoundsToFit (int x, int y, int width, int height, - Justification justification, bool onlyReduceInSize) +void Component::setBoundsToFit (Rectangle targetArea, Justification justification, bool onlyReduceInSize) { - // it's no good calling this method unless both the component and - // target rectangle have a finite size. - jassert (getWidth() > 0 && getHeight() > 0 && width > 0 && height > 0); - - if (getWidth() > 0 && getHeight() > 0 - && width > 0 && height > 0) + if (getLocalBounds().isEmpty() || targetArea.isEmpty()) { - int newW, newH; + // it's no good calling this method unless both the component and + // target rectangle have a finite size. + jassertfalse; + return; + } - if (onlyReduceInSize && getWidth() <= width && getHeight() <= height) - { - newW = getWidth(); - newH = getHeight(); - } - else - { - const double imageRatio = getHeight() / (double) getWidth(); - const double targetRatio = height / (double) width; + auto sourceArea = targetArea.withZeroOrigin(); - if (imageRatio <= targetRatio) - { - newW = width; - newH = jmin (height, roundToInt (newW * imageRatio)); - } - else - { - newH = height; - newW = jmin (width, roundToInt (newH / imageRatio)); - } - } + if (onlyReduceInSize + && getWidth() <= targetArea.getWidth() + && getHeight() <= targetArea.getHeight()) + { + sourceArea = getLocalBounds(); + } + else + { + auto sourceRatio = getHeight() / (double) getWidth(); + auto targetRatio = targetArea.getHeight() / (double) targetArea.getWidth(); - if (newW > 0 && newH > 0) - setBounds (justification.appliedToRectangle (Rectangle (newW, newH), - Rectangle (x, y, width, height))); + if (sourceRatio <= targetRatio) + sourceArea.setHeight (jmin (targetArea.getHeight(), + roundToInt (targetArea.getWidth() * sourceRatio))); + else + sourceArea.setWidth (jmin (targetArea.getWidth(), + roundToInt (targetArea.getHeight() / sourceRatio))); } + + if (! sourceArea.isEmpty()) + setBounds (justification.appliedToRectangle (sourceArea, targetArea)); } //============================================================================== @@ -1308,7 +1261,6 @@ void Component::setTransform (const AffineTransform& newTransform) repaint(); affineTransform.reset(); repaint(); - sendMovedResizedMessages (false, false); } } @@ -1559,13 +1511,13 @@ Component* Component::removeChildComponent (int index, bool sendParentEvents, bo //============================================================================== void Component::removeAllChildren() { - while (childComponentList.size() > 0) + while (! childComponentList.isEmpty()) removeChildComponent (childComponentList.size() - 1); } void Component::deleteAllChildren() { - while (childComponentList.size() > 0) + while (! childComponentList.isEmpty()) delete (removeChildComponent (childComponentList.size() - 1)); } @@ -1742,13 +1694,10 @@ void Component::exitModalState (int returnValue) bool Component::isCurrentlyModal (bool onlyConsiderForemostModalComponent) const noexcept { - const int n = onlyConsiderForemostModalComponent ? 1 : getNumCurrentlyModalComponents(); - - for (int i = 0; i < n; ++i) - if (getCurrentlyModalComponent(i) == this) - return true; + auto& mcm = *ModalComponentManager::getInstance(); - return false; + return onlyConsiderForemostModalComponent ? mcm.isFrontModalComponent (this) + : mcm.isModal (this); } bool Component::isCurrentlyBlockedByAnotherModalComponent() const @@ -2069,7 +2018,7 @@ Image Component::createComponentSnapshot (Rectangle areaToGrab, r = r.getIntersection (getLocalBounds()); if (r.isEmpty()) - return Image(); + return {}; auto w = roundToInt (scaleFactor * r.getWidth()); auto h = roundToInt (scaleFactor * r.getHeight()); @@ -2144,32 +2093,32 @@ void Component::sendLookAndFeelChange() } } -Colour Component::findColour (int colourId, bool inheritFromParent) const +Colour Component::findColour (int colourID, bool inheritFromParent) const { - if (auto* v = properties.getVarPointer (ComponentHelpers::getColourPropertyId (colourId))) + if (auto* v = properties.getVarPointer (ComponentHelpers::getColourPropertyID (colourID))) return Colour ((uint32) static_cast (*v)); if (inheritFromParent && parentComponent != nullptr - && (lookAndFeel == nullptr || ! lookAndFeel->isColourSpecified (colourId))) - return parentComponent->findColour (colourId, true); + && (lookAndFeel == nullptr || ! lookAndFeel->isColourSpecified (colourID))) + return parentComponent->findColour (colourID, true); - return getLookAndFeel().findColour (colourId); + return getLookAndFeel().findColour (colourID); } -bool Component::isColourSpecified (int colourId) const +bool Component::isColourSpecified (int colourID) const { - return properties.contains (ComponentHelpers::getColourPropertyId (colourId)); + return properties.contains (ComponentHelpers::getColourPropertyID (colourID)); } -void Component::removeColour (int colourId) +void Component::removeColour (int colourID) { - if (properties.remove (ComponentHelpers::getColourPropertyId (colourId))) + if (properties.remove (ComponentHelpers::getColourPropertyID (colourID))) colourChanged(); } -void Component::setColour (int colourId, Colour colour) +void Component::setColour (int colourID, Colour colour) { - if (properties.set (ComponentHelpers::getColourPropertyId (colourId), (int) colour.getARGB())) + if (properties.set (ComponentHelpers::getColourPropertyID (colourID), (int) colour.getARGB())) colourChanged(); } @@ -2181,7 +2130,7 @@ void Component::copyAllExplicitColoursTo (Component& target) const { auto name = properties.getName(i); - if (name.toString().startsWith ("jcclr_")) + if (name.toString().startsWith (colourPropertyPrefix)) if (target.properties.set (name, properties [name])) changed = true; } diff --git a/modules/juce_gui_basics/components/juce_Component.h b/modules/juce_gui_basics/components/juce_Component.h index 131678e105..188c0bf528 100644 --- a/modules/juce_gui_basics/components/juce_Component.h +++ b/modules/juce_gui_basics/components/juce_Component.h @@ -485,6 +485,17 @@ public: void setBoundsRelative (float proportionalX, float proportionalY, float proportionalWidth, float proportionalHeight); + /** 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 + setBoundsRelative ({ 0.2f, 0.2f, 0.5f, 0.5f }) would give it half the + width and height of the parent, with its top-left position 20% of + the way across and down the parent. + + @see setBounds + */ + void setBoundsRelative (Rectangle proportionalArea); + /** Changes the component's position and size based on the amount of space to leave around it. This will position the component within its parent, leaving the specified number of @@ -508,7 +519,7 @@ public: @see setBounds */ - void setBoundsToFit (int x, int y, int width, int height, + void setBoundsToFit (Rectangle targetArea, Justification justification, bool onlyReduceInSize); @@ -2060,7 +2071,7 @@ public: @see setColour, isColourSpecified, colourChanged, LookAndFeel::findColour, LookAndFeel::setColour */ - Colour findColour (int colourId, bool inheritFromParent = false) const; + Colour findColour (int colourID, bool inheritFromParent = false) const; /** Registers a colour to be used for a particular purpose. @@ -2072,17 +2083,17 @@ public: @see findColour, isColourSpecified, colourChanged, LookAndFeel::findColour, LookAndFeel::setColour */ - void setColour (int colourId, Colour newColour); + void setColour (int colourID, Colour newColour); /** If a colour has been set with setColour(), this will remove it. This allows you to make a colour revert to its default state. */ - void removeColour (int colourId); + void removeColour (int colourID); /** Returns true if the specified colour ID has been explicitly set for this component using the setColour() method. */ - bool isColourSpecified (int colourId) const; + bool isColourSpecified (int colourID) const; /** This looks for any colours that have been specified for this component, and copies them to the specified target component. diff --git a/modules/juce_gui_basics/components/juce_ModalComponentManager.cpp b/modules/juce_gui_basics/components/juce_ModalComponentManager.cpp index 44019820fd..4dc9a3cddc 100644 --- a/modules/juce_gui_basics/components/juce_ModalComponentManager.cpp +++ b/modules/juce_gui_basics/components/juce_ModalComponentManager.cpp @@ -172,7 +172,7 @@ Component* ModalComponentManager::getModalComponent (int index) const return nullptr; } -bool ModalComponentManager::isModal (Component* comp) const +bool ModalComponentManager::isModal (const Component* comp) const { for (auto* item : stack) if (item->isActive && item->component == comp) @@ -181,7 +181,7 @@ bool ModalComponentManager::isModal (Component* comp) const return false; } -bool ModalComponentManager::isFrontModalComponent (Component* comp) const +bool ModalComponentManager::isFrontModalComponent (const Component* comp) const { return comp == getModalComponent (0); } diff --git a/modules/juce_gui_basics/components/juce_ModalComponentManager.h b/modules/juce_gui_basics/components/juce_ModalComponentManager.h index f5bd1ca7e5..55115987a6 100644 --- a/modules/juce_gui_basics/components/juce_ModalComponentManager.h +++ b/modules/juce_gui_basics/components/juce_ModalComponentManager.h @@ -90,10 +90,10 @@ public: Component* getModalComponent (int index) const; /** Returns true if the specified component is in a modal state. */ - bool isModal (Component* component) const; + bool isModal (const Component* component) const; /** Returns true if the specified component is currently the topmost modal component. */ - bool isFrontModalComponent (Component* component) const; + bool isFrontModalComponent (const Component* component) const; /** Adds a new callback that will be called when the specified modal component is dismissed.