| @@ -1088,7 +1088,8 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| class WidgetsDemo : public Component, | class WidgetsDemo : public Component, | ||||
| public ButtonListener | |||||
| public ButtonListener, | |||||
| public SliderListener | |||||
| { | { | ||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -1111,9 +1112,17 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| addAndMakeVisible (&enableButton); | addAndMakeVisible (&enableButton); | ||||
| enableButton.setBounds (230, 10, 180, 24); | enableButton.setBounds (230, 10, 180, 24); | ||||
| enableButton.setTooltip ("toggle button"); | |||||
| enableButton.setTooltip ("Enables/disables all the components"); | |||||
| enableButton.setToggleState (true, false); | enableButton.setToggleState (true, false); | ||||
| enableButton.addButtonListener (this); | enableButton.addButtonListener (this); | ||||
| addAndMakeVisible (&transformSlider); | |||||
| transformSlider.setSliderStyle (Slider::LinearBar); | |||||
| transformSlider.setTextValueSuffix (" degrees rotation"); | |||||
| transformSlider.setRange (-180.0, 180.0, 0.1); | |||||
| transformSlider.setBounds (440, 10, 180, 24); | |||||
| transformSlider.setTooltip ("Applies a transform to the components"); | |||||
| transformSlider.addListener (this); | |||||
| } | } | ||||
| ~WidgetsDemo() | ~WidgetsDemo() | ||||
| @@ -1397,9 +1406,17 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| void sliderValueChanged (Slider*) | |||||
| { | |||||
| // When you move the roation slider, we'll apply a rotaion transform to the whole tabs component.. | |||||
| tabs.setTransform (AffineTransform::rotation ((float) (transformSlider.getValue() / (180.0 / double_Pi)), | |||||
| getWidth() * 0.5f, getHeight() * 0.5f)); | |||||
| } | |||||
| private: | private: | ||||
| TextButton menuButton; | TextButton menuButton; | ||||
| ToggleButton enableButton; | ToggleButton enableButton; | ||||
| Slider transformSlider; | |||||
| DemoTabbedComponent tabs; | DemoTabbedComponent tabs; | ||||
| }; | }; | ||||
| @@ -39782,7 +39782,7 @@ END_JUCE_NAMESPACE | |||||
| /*** Start of inlined file: juce_Component.cpp ***/ | /*** Start of inlined file: juce_Component.cpp ***/ | ||||
| BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
| #define checkMessageManagerIsLocked jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||||
| #define CHECK_MESSAGE_MANAGER_IS_LOCKED jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||||
| Component* Component::currentlyFocusedComponent = 0; | Component* Component::currentlyFocusedComponent = 0; | ||||
| @@ -39982,22 +39982,34 @@ public: | |||||
| static const Point<int> convertFromParentSpace (const Component& comp, const Point<int>& pointInParentSpace) | static const Point<int> convertFromParentSpace (const Component& comp, const Point<int>& pointInParentSpace) | ||||
| { | { | ||||
| return pointInParentSpace - comp.getPosition(); | |||||
| if (comp.affineTransform_ == 0) | |||||
| return pointInParentSpace - comp.getPosition(); | |||||
| return pointInParentSpace.toFloat().transformedBy (comp.affineTransform_->inverted()).toInt() - comp.getPosition(); | |||||
| } | } | ||||
| static const Rectangle<int> convertFromParentSpace (const Component& comp, const Rectangle<int>& areaInParentSpace) | static const Rectangle<int> convertFromParentSpace (const Component& comp, const Rectangle<int>& areaInParentSpace) | ||||
| { | { | ||||
| return areaInParentSpace - comp.getPosition(); | |||||
| if (comp.affineTransform_ == 0) | |||||
| return areaInParentSpace - comp.getPosition(); | |||||
| return areaInParentSpace.toFloat().transformed (comp.affineTransform_->inverted()).getSmallestIntegerContainer() - comp.getPosition(); | |||||
| } | } | ||||
| static const Point<int> convertToParentSpace (const Component& comp, const Point<int>& pointInLocalSpace) | static const Point<int> convertToParentSpace (const Component& comp, const Point<int>& pointInLocalSpace) | ||||
| { | { | ||||
| return pointInLocalSpace + comp.getPosition(); | |||||
| if (comp.affineTransform_ == 0) | |||||
| return pointInLocalSpace + comp.getPosition(); | |||||
| return (pointInLocalSpace + comp.getPosition()).toFloat().transformedBy (*comp.affineTransform_).toInt(); | |||||
| } | } | ||||
| static const Rectangle<int> convertToParentSpace (const Component& comp, const Rectangle<int>& areaInLocalSpace) | static const Rectangle<int> convertToParentSpace (const Component& comp, const Rectangle<int>& areaInLocalSpace) | ||||
| { | { | ||||
| return areaInLocalSpace + comp.getPosition(); | |||||
| if (comp.affineTransform_ == 0) | |||||
| return areaInLocalSpace + comp.getPosition(); | |||||
| return (areaInLocalSpace + comp.getPosition()).toFloat().transformed (*comp.affineTransform_).getSmallestIntegerContainer(); | |||||
| } | } | ||||
| template <typename Type> | template <typename Type> | ||||
| @@ -40070,8 +40082,7 @@ public: | |||||
| { | { | ||||
| const Component& child = *comp.childComponentList_.getUnchecked(i); | const Component& child = *comp.childComponentList_.getUnchecked(i); | ||||
| //xxx if (child.isVisible() && ! child.isTransformed()) | |||||
| if (child.isVisible()) | |||||
| if (child.isVisible() && ! child.isTransformed()) | |||||
| { | { | ||||
| const Rectangle<int> newClip (clipRect.getIntersection (child.bounds_)); | const Rectangle<int> newClip (clipRect.getIntersection (child.bounds_)); | ||||
| @@ -40195,7 +40206,7 @@ void Component::setName (const String& name) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (componentName_ != name) | if (componentName_ != name) | ||||
| { | { | ||||
| @@ -40221,7 +40232,7 @@ void Component::setVisible (bool shouldBeVisible) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| SafePointer<Component> safePointer (this); | SafePointer<Component> safePointer (this); | ||||
| @@ -40309,7 +40320,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (isOpaque()) | if (isOpaque()) | ||||
| styleWanted &= ~ComponentPeer::windowIsSemiTransparent; | styleWanted &= ~ComponentPeer::windowIsSemiTransparent; | ||||
| @@ -40397,7 +40408,7 @@ void Component::removeFromDesktop() | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (flags.hasHeavyweightPeerFlag) | if (flags.hasHeavyweightPeerFlag) | ||||
| { | { | ||||
| @@ -40472,7 +40483,7 @@ void Component::toFront (const bool setAsForeground) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (flags.hasHeavyweightPeerFlag) | if (flags.hasHeavyweightPeerFlag) | ||||
| { | { | ||||
| @@ -40711,7 +40722,7 @@ void Component::setBounds (const int x, const int y, int w, int h) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (w < 0) w = 0; | if (w < 0) w = 0; | ||||
| if (h < 0) h = 0; | if (h < 0) h = 0; | ||||
| @@ -40899,6 +40910,41 @@ void Component::setBoundsToFit (int x, int y, int width, int height, | |||||
| } | } | ||||
| } | } | ||||
| bool Component::isTransformed() const throw() | |||||
| { | |||||
| return affineTransform_ != 0; | |||||
| } | |||||
| void Component::setTransform (const AffineTransform& newTransform) | |||||
| { | |||||
| if (newTransform.isIdentity()) | |||||
| { | |||||
| if (affineTransform_ != 0) | |||||
| { | |||||
| repaint(); | |||||
| affineTransform_ = 0; | |||||
| repaint(); | |||||
| } | |||||
| } | |||||
| else if (affineTransform_ == 0) | |||||
| { | |||||
| repaint(); | |||||
| affineTransform_ = new AffineTransform (newTransform); | |||||
| repaint(); | |||||
| } | |||||
| else if (*affineTransform_ != newTransform) | |||||
| { | |||||
| repaint(); | |||||
| *affineTransform_ = newTransform; | |||||
| repaint(); | |||||
| } | |||||
| } | |||||
| const AffineTransform Component::getTransform() const | |||||
| { | |||||
| return affineTransform_ != 0 ? *affineTransform_ : AffineTransform::identity; | |||||
| } | |||||
| bool Component::hitTest (int x, int y) | bool Component::hitTest (int x, int y) | ||||
| { | { | ||||
| if (! flags.ignoresMouseClicksFlag) | if (! flags.ignoresMouseClicksFlag) | ||||
| @@ -40953,15 +40999,13 @@ bool Component::contains (const Point<int>& point) | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool Component::reallyContains (const int x, const int y, const bool returnTrueIfWithinAChild) | |||||
| bool Component::reallyContains (const Point<int>& point, const bool returnTrueIfWithinAChild) | |||||
| { | { | ||||
| const Point<int> p (x, y); | |||||
| if (! contains (p)) | |||||
| if (! contains (point)) | |||||
| return false; | return false; | ||||
| Component* const top = getTopLevelComponent(); | Component* const top = getTopLevelComponent(); | ||||
| const Component* const compAtPosition = top->getComponentAt (top->getLocalPoint (this, p)); | |||||
| const Component* const compAtPosition = top->getComponentAt (top->getLocalPoint (this, point)); | |||||
| return (compAtPosition == this) || (returnTrueIfWithinAChild && isParentOf (compAtPosition)); | return (compAtPosition == this) || (returnTrueIfWithinAChild && isParentOf (compAtPosition)); | ||||
| } | } | ||||
| @@ -40994,7 +41038,7 @@ void Component::addChildComponent (Component* const child, int zOrder) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (child != 0 && child->parentComponent_ != this) | if (child != 0 && child->parentComponent_ != this) | ||||
| { | { | ||||
| @@ -41047,7 +41091,7 @@ Component* Component::removeChildComponent (const int index) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| Component* const child = childComponentList_ [index]; | Component* const child = childComponentList_ [index]; | ||||
| @@ -41215,7 +41259,7 @@ void Component::enterModalState (const bool takeKeyboardFocus_, ModalComponentMa | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| // Check for an attempt to make a component modal when it already is! | // Check for an attempt to make a component modal when it already is! | ||||
| // This can cause nasty problems.. | // This can cause nasty problems.. | ||||
| @@ -41385,7 +41429,7 @@ void Component::internalRepaint (int x, int y, int w, int h) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (x < 0) | if (x < 0) | ||||
| { | { | ||||
| @@ -41412,7 +41456,17 @@ void Component::internalRepaint (int x, int y, int w, int h) | |||||
| if (parentComponent_ != 0) | if (parentComponent_ != 0) | ||||
| { | { | ||||
| if (parentComponent_->flags.visibleFlag) | if (parentComponent_->flags.visibleFlag) | ||||
| parentComponent_->internalRepaint (x + getX(), y + getY(), w, h); | |||||
| { | |||||
| if (affineTransform_ == 0) | |||||
| { | |||||
| parentComponent_->internalRepaint (x + getX(), y + getY(), w, h); | |||||
| } | |||||
| else | |||||
| { | |||||
| const Rectangle<int> r (ComponentHelpers::convertToParentSpace (*this, Rectangle<int> (x, y, w, h))); | |||||
| parentComponent_->internalRepaint (r.getX(), r.getY(), r.getWidth(), r.getHeight()); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| else if (flags.hasHeavyweightPeerFlag) | else if (flags.hasHeavyweightPeerFlag) | ||||
| { | { | ||||
| @@ -41447,6 +41501,15 @@ void Component::paintComponent (Graphics& g) | |||||
| } | } | ||||
| } | } | ||||
| void Component::paintTransformedChild (Graphics& g) | |||||
| { | |||||
| if (affineTransform_ != 0) | |||||
| g.addTransform (*affineTransform_); | |||||
| g.setOrigin (getX(), getY()); | |||||
| paintEntireComponent (g, false); | |||||
| } | |||||
| void Component::paintComponentAndChildren (Graphics& g) | void Component::paintComponentAndChildren (Graphics& g) | ||||
| { | { | ||||
| const Rectangle<int> clipBounds (g.getClipBounds()); | const Rectangle<int> clipBounds (g.getClipBounds()); | ||||
| @@ -41476,8 +41539,7 @@ void Component::paintComponentAndChildren (Graphics& g) | |||||
| if (child->flags.dontClipGraphicsFlag) | if (child->flags.dontClipGraphicsFlag) | ||||
| { | { | ||||
| g.setOrigin (child->getX(), child->getY()); | |||||
| child->paintEntireComponent (g, false); | |||||
| child->paintTransformedChild (g); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -41497,10 +41559,7 @@ void Component::paintComponentAndChildren (Graphics& g) | |||||
| } | } | ||||
| if (nothingClipped || ! g.isClipEmpty()) | if (nothingClipped || ! g.isClipEmpty()) | ||||
| { | |||||
| g.setOrigin (child->getX(), child->getY()); | |||||
| child->paintEntireComponent (g, false); | |||||
| } | |||||
| child->paintTransformedChild (g); | |||||
| } | } | ||||
| } | } | ||||
| @@ -41860,7 +41919,7 @@ void Component::addMouseListener (MouseListener* const newListener, | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| // If you register a component as a mouselistener for itself, it'll receive all the events | // If you register a component as a mouselistener for itself, it'll receive all the events | ||||
| // twice - once via the direct callback that all components get anyway, and then again as a listener! | // twice - once via the direct callback that all components get anyway, and then again as a listener! | ||||
| @@ -41876,7 +41935,7 @@ void Component::removeMouseListener (MouseListener* const listenerToRemove) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (mouseListeners_ != 0) | if (mouseListeners_ != 0) | ||||
| mouseListeners_->removeListener (listenerToRemove); | mouseListeners_->removeListener (listenerToRemove); | ||||
| @@ -42131,7 +42190,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point<int>& r | |||||
| { | { | ||||
| Desktop& desktop = Desktop::getInstance(); | Desktop& desktop = Desktop::getInstance(); | ||||
| flags.mouseOverFlag = reallyContains (relativePos.getX(), relativePos.getY(), false); | |||||
| flags.mouseOverFlag = reallyContains (relativePos, false); | |||||
| BailOutChecker checker (this); | BailOutChecker checker (this); | ||||
| @@ -42499,7 +42558,7 @@ void Component::grabKeyboardFocus() | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| grabFocusInternal (focusChangedDirectly); | grabFocusInternal (focusChangedDirectly); | ||||
| } | } | ||||
| @@ -42508,7 +42567,7 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (parentComponent_ != 0) | if (parentComponent_ != 0) | ||||
| { | { | ||||
| @@ -42563,20 +42622,9 @@ void Component::giveAwayFocus() | |||||
| componentLosingFocus->internalFocusLoss (focusChangedDirectly); | componentLosingFocus->internalFocusLoss (focusChangedDirectly); | ||||
| } | } | ||||
| bool Component::isMouseOver() const throw() | |||||
| { | |||||
| return flags.mouseOverFlag; | |||||
| } | |||||
| bool Component::isMouseButtonDown() const throw() | |||||
| { | |||||
| return flags.mouseDownFlag; | |||||
| } | |||||
| bool Component::isMouseOverOrDragging() const throw() | |||||
| { | |||||
| return flags.mouseOverFlag || flags.mouseDownFlag; | |||||
| } | |||||
| bool Component::isMouseOver() const throw() { return flags.mouseOverFlag; } | |||||
| bool Component::isMouseButtonDown() const throw() { return flags.mouseDownFlag; } | |||||
| bool Component::isMouseOverOrDragging() const throw() { return flags.mouseOverFlag || flags.mouseDownFlag; } | |||||
| bool JUCE_CALLTYPE Component::isMouseButtonDownAnywhere() throw() | bool JUCE_CALLTYPE Component::isMouseButtonDownAnywhere() throw() | ||||
| { | { | ||||
| @@ -42590,8 +42638,7 @@ const Point<int> Component::getMouseXYRelative() const | |||||
| const Rectangle<int> Component::getParentMonitorArea() const | const Rectangle<int> Component::getParentMonitorArea() const | ||||
| { | { | ||||
| return Desktop::getInstance() | |||||
| .getMonitorAreaContaining (localPointToGlobal (getLocalBounds().getCentre())); | |||||
| return Desktop::getInstance().getMonitorAreaContaining (getScreenBounds().getCentre()); | |||||
| } | } | ||||
| void Component::addKeyListener (KeyListener* const newListener) | void Component::addKeyListener (KeyListener* const newListener) | ||||
| @@ -43515,34 +43562,29 @@ void Button::turnOffOtherButtonsInGroup (const bool sendChangeNotification) | |||||
| void Button::enablementChanged() | void Button::enablementChanged() | ||||
| { | { | ||||
| updateState (0); | |||||
| updateState(); | |||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| Button::ButtonState Button::updateState (const MouseEvent* const e) | |||||
| Button::ButtonState Button::updateState() | |||||
| { | |||||
| return updateState (reallyContains (getMouseXYRelative(), true), isMouseButtonDown()); | |||||
| } | |||||
| Button::ButtonState Button::updateState (const bool over, const bool down) | |||||
| { | { | ||||
| ButtonState state = buttonNormal; | |||||
| ButtonState newState = buttonNormal; | |||||
| if (isEnabled() && isVisible() && ! isCurrentlyBlockedByAnotherModalComponent()) | if (isEnabled() && isVisible() && ! isCurrentlyBlockedByAnotherModalComponent()) | ||||
| { | { | ||||
| Point<int> mousePos; | |||||
| if (e == 0) | |||||
| mousePos = getMouseXYRelative(); | |||||
| else | |||||
| mousePos = e->getEventRelativeTo (this).getPosition(); | |||||
| const bool over = reallyContains (mousePos.getX(), mousePos.getY(), true); | |||||
| const bool down = isMouseButtonDown(); | |||||
| if ((down && (over || (triggerOnMouseDown && buttonState == buttonDown))) || isKeyDown) | if ((down && (over || (triggerOnMouseDown && buttonState == buttonDown))) || isKeyDown) | ||||
| state = buttonDown; | |||||
| newState = buttonDown; | |||||
| else if (over) | else if (over) | ||||
| state = buttonOver; | |||||
| newState = buttonOver; | |||||
| } | } | ||||
| setState (state); | |||||
| return state; | |||||
| setState (newState); | |||||
| return newState; | |||||
| } | } | ||||
| void Button::setState (const ButtonState newState) | void Button::setState (const ButtonState newState) | ||||
| @@ -43687,19 +43729,19 @@ void Button::paint (Graphics& g) | |||||
| paintButton (g, isOver(), isDown()); | paintButton (g, isOver(), isDown()); | ||||
| } | } | ||||
| void Button::mouseEnter (const MouseEvent& e) | |||||
| void Button::mouseEnter (const MouseEvent&) | |||||
| { | { | ||||
| updateState (&e); | |||||
| updateState (true, false); | |||||
| } | } | ||||
| void Button::mouseExit (const MouseEvent& e) | |||||
| void Button::mouseExit (const MouseEvent&) | |||||
| { | { | ||||
| updateState (&e); | |||||
| updateState (false, false); | |||||
| } | } | ||||
| void Button::mouseDown (const MouseEvent& e) | void Button::mouseDown (const MouseEvent& e) | ||||
| { | { | ||||
| updateState (&e); | |||||
| updateState (true, true); | |||||
| if (isDown()) | if (isDown()) | ||||
| { | { | ||||
| @@ -43714,7 +43756,7 @@ void Button::mouseDown (const MouseEvent& e) | |||||
| void Button::mouseUp (const MouseEvent& e) | void Button::mouseUp (const MouseEvent& e) | ||||
| { | { | ||||
| const bool wasDown = isDown(); | const bool wasDown = isDown(); | ||||
| updateState (&e); | |||||
| updateState (isMouseOver(), false); | |||||
| if (wasDown && isOver() && ! triggerOnMouseDown) | if (wasDown && isOver() && ! triggerOnMouseDown) | ||||
| internalClickCallback (e.mods); | internalClickCallback (e.mods); | ||||
| @@ -43723,7 +43765,7 @@ void Button::mouseUp (const MouseEvent& e) | |||||
| void Button::mouseDrag (const MouseEvent& e) | void Button::mouseDrag (const MouseEvent& e) | ||||
| { | { | ||||
| const ButtonState oldState = buttonState; | const ButtonState oldState = buttonState; | ||||
| updateState (&e); | |||||
| updateState (isMouseOver(), true); | |||||
| if (autoRepeatDelay >= 0 && buttonState != oldState && isDown()) | if (autoRepeatDelay >= 0 && buttonState != oldState && isDown()) | ||||
| getRepeatTimer().startTimer (autoRepeatSpeed); | getRepeatTimer().startTimer (autoRepeatSpeed); | ||||
| @@ -43731,13 +43773,13 @@ void Button::mouseDrag (const MouseEvent& e) | |||||
| void Button::focusGained (FocusChangeType) | void Button::focusGained (FocusChangeType) | ||||
| { | { | ||||
| updateState (0); | |||||
| updateState(); | |||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| void Button::focusLost (FocusChangeType) | void Button::focusLost (FocusChangeType) | ||||
| { | { | ||||
| updateState (0); | |||||
| updateState(); | |||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| @@ -43750,7 +43792,7 @@ void Button::setVisible (bool shouldBeVisible) | |||||
| if (! shouldBeVisible) | if (! shouldBeVisible) | ||||
| needsToRelease = false; | needsToRelease = false; | ||||
| updateState (0); | |||||
| updateState(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -43878,7 +43920,7 @@ bool Button::keyStateChanged (const bool, Component*) | |||||
| if (autoRepeatDelay >= 0 && (isKeyDown && ! wasDown)) | if (autoRepeatDelay >= 0 && (isKeyDown && ! wasDown)) | ||||
| getRepeatTimer().startTimer (autoRepeatDelay); | getRepeatTimer().startTimer (autoRepeatDelay); | ||||
| updateState (0); | |||||
| updateState(); | |||||
| if (isEnabled() && wasDown && ! isKeyDown) | if (isEnabled() && wasDown && ! isKeyDown) | ||||
| { | { | ||||
| @@ -43922,10 +43964,10 @@ void Button::repeatTimerCallback() | |||||
| if (needsRepainting) | if (needsRepainting) | ||||
| { | { | ||||
| getRepeatTimer().stopTimer(); | getRepeatTimer().stopTimer(); | ||||
| updateState (0); | |||||
| updateState(); | |||||
| needsRepainting = false; | needsRepainting = false; | ||||
| } | } | ||||
| else if (autoRepeatSpeed > 0 && (isKeyDown || (updateState (0) == buttonDown))) | |||||
| else if (autoRepeatSpeed > 0 && (isKeyDown || (updateState() == buttonDown))) | |||||
| { | { | ||||
| int repeatSpeed = autoRepeatSpeed; | int repeatSpeed = autoRepeatSpeed; | ||||
| @@ -48020,7 +48062,7 @@ void ComboBox::mouseUp (const MouseEvent& e2) | |||||
| const MouseEvent e (e2.getEventRelativeTo (this)); | const MouseEvent e (e2.getEventRelativeTo (this)); | ||||
| if (reallyContains (e.x, e.y, true) | |||||
| if (reallyContains (e.getPosition(), true) | |||||
| && (e2.eventComponent == this || ! label->isEditable())) | && (e2.eventComponent == this || ! label->isEditable())) | ||||
| { | { | ||||
| showPopup(); | showPopup(); | ||||
| @@ -49804,6 +49846,10 @@ void Slider::lookAndFeelChanged() | |||||
| valueBox->setTooltip (getTooltip()); | valueBox->setTooltip (getTooltip()); | ||||
| } | } | ||||
| else | |||||
| { | |||||
| valueBox = 0; | |||||
| } | |||||
| if (style == IncDecButtons) | if (style == IncDecButtons) | ||||
| { | { | ||||
| @@ -51750,7 +51796,7 @@ int TableHeaderComponent::getResizeDraggerAt (const int mouseX) const | |||||
| void TableHeaderComponent::updateColumnUnderMouse (int x, int y) | void TableHeaderComponent::updateColumnUnderMouse (int x, int y) | ||||
| { | { | ||||
| const int newCol = (reallyContains (x, y, true) && getResizeDraggerAt (x) == 0) | |||||
| const int newCol = (reallyContains (Point<int> (x, y), true) && getResizeDraggerAt (x) == 0) | |||||
| ? getColumnIdAtX (x) : 0; | ? getColumnIdAtX (x) : 0; | ||||
| if (newCol != columnIdUnderMouse) | if (newCol != columnIdUnderMouse) | ||||
| @@ -68454,7 +68500,7 @@ int MenuBarComponent::getItemAt (const int x, const int y) | |||||
| { | { | ||||
| for (int i = 0; i < xPositions.size(); ++i) | for (int i = 0; i < xPositions.size(); ++i) | ||||
| if (x >= xPositions[i] && x < xPositions[i + 1]) | if (x >= xPositions[i] && x < xPositions[i + 1]) | ||||
| return reallyContains (x, y, true) ? i : -1; | |||||
| return reallyContains (Point<int> (x, y), true) ? i : -1; | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| @@ -69243,7 +69289,7 @@ public: | |||||
| // comp that we're attached to. | // comp that we're attached to. | ||||
| const Point<int> mousePos (componentAttachedTo->getMouseXYRelative()); | const Point<int> mousePos (componentAttachedTo->getMouseXYRelative()); | ||||
| if (componentAttachedTo->reallyContains (mousePos.getX(), mousePos.getY(), true)) | |||||
| if (componentAttachedTo->reallyContains (mousePos, true)) | |||||
| { | { | ||||
| postCommandMessage (PopupMenuSettings::dismissCommandId); // dismiss asynchrounously | postCommandMessage (PopupMenuSettings::dismissCommandId); // dismiss asynchrounously | ||||
| return; | return; | ||||
| @@ -69287,7 +69333,7 @@ public: | |||||
| const uint32 now = Time::getMillisecondCounter(); | const uint32 now = Time::getMillisecondCounter(); | ||||
| if (now > timeEnteredCurrentChildComp + 100 | if (now > timeEnteredCurrentChildComp + 100 | ||||
| && reallyContains (localMousePos.getX(), localMousePos.getY(), true) | |||||
| && reallyContains (localMousePos, true) | |||||
| && currentChild != 0 | && currentChild != 0 | ||||
| && (! disableMouseMoves) | && (! disableMouseMoves) | ||||
| && ! (activeSubMenu != 0 && activeSubMenu->isVisible())) | && ! (activeSubMenu != 0 && activeSubMenu->isVisible())) | ||||
| @@ -69379,7 +69425,7 @@ public: | |||||
| else if (wasDown && now > menuCreationTime + 250 | else if (wasDown && now > menuCreationTime + 250 | ||||
| && ! (isDown || overScrollArea)) | && ! (isDown || overScrollArea)) | ||||
| { | { | ||||
| isOver = reallyContains (localMousePos.getX(), localMousePos.getY(), true); | |||||
| isOver = reallyContains (localMousePos, true); | |||||
| if (isOver) | if (isOver) | ||||
| { | { | ||||
| @@ -69452,7 +69498,7 @@ private: | |||||
| void updateMouseOverStatus (const Point<int>& globalMousePos) | void updateMouseOverStatus (const Point<int>& globalMousePos) | ||||
| { | { | ||||
| const Point<int> relPos (getLocalPoint (0, globalMousePos)); | const Point<int> relPos (getLocalPoint (0, globalMousePos)); | ||||
| isOver = reallyContains (relPos.getX(), relPos.getY(), true); | |||||
| isOver = reallyContains (relPos, true); | |||||
| if (activeSubMenu != 0) | if (activeSubMenu != 0) | ||||
| activeSubMenu->updateMouseOverStatus (globalMousePos); | activeSubMenu->updateMouseOverStatus (globalMousePos); | ||||
| @@ -69798,7 +69844,7 @@ private: | |||||
| void highlightItemUnderMouse (const Point<int>& globalMousePos, const Point<int>& localMousePos) | void highlightItemUnderMouse (const Point<int>& globalMousePos, const Point<int>& localMousePos) | ||||
| { | { | ||||
| isOver = reallyContains (localMousePos.getX(), localMousePos.getY(), true); | |||||
| isOver = reallyContains (localMousePos, true); | |||||
| if (isOver) | if (isOver) | ||||
| hasBeenOver = true; | hasBeenOver = true; | ||||
| @@ -71732,7 +71778,7 @@ void MouseHoverDetector::hoverTimerCallback() | |||||
| { | { | ||||
| const Point<int> pos (source->getMouseXYRelative()); | const Point<int> pos (source->getMouseXYRelative()); | ||||
| if (source->reallyContains (pos.getX(), pos.getY(), false)) | |||||
| if (source->reallyContains (pos, false)) | |||||
| { | { | ||||
| hasJustHovered = true; | hasJustHovered = true; | ||||
| mouseHovered (pos.getX(), pos.getY()); | mouseHovered (pos.getX(), pos.getY()); | ||||
| @@ -75390,7 +75436,7 @@ const uint8 MidiKeyboardComponent::blackNotes[] = { 1, 3, 6, 8, 10 }; | |||||
| int MidiKeyboardComponent::xyToNote (const Point<int>& pos, float& mousePositionVelocity) | int MidiKeyboardComponent::xyToNote (const Point<int>& pos, float& mousePositionVelocity) | ||||
| { | { | ||||
| if (! reallyContains (pos.getX(), pos.getY(), false)) | |||||
| if (! reallyContains (pos, false)) | |||||
| return -1; | return -1; | ||||
| Point<int> p (pos); | Point<int> p (pos); | ||||
| @@ -64,7 +64,7 @@ | |||||
| */ | */ | ||||
| #define JUCE_MAJOR_VERSION 1 | #define JUCE_MAJOR_VERSION 1 | ||||
| #define JUCE_MINOR_VERSION 52 | #define JUCE_MINOR_VERSION 52 | ||||
| #define JUCE_BUILDNUMBER 94 | |||||
| #define JUCE_BUILDNUMBER 95 | |||||
| /** Current Juce version number. | /** Current Juce version number. | ||||
| @@ -26113,15 +26113,21 @@ public: | |||||
| */ | */ | ||||
| bool isAlwaysOnTop() const throw(); | bool isAlwaysOnTop() const throw(); | ||||
| /** Returns the x co-ordinate of the component's left edge. | |||||
| /** Returns the x coordinate of the component's left edge. | |||||
| This is a distance in pixels from the left edge of the component's parent. | This is a distance in pixels from the left edge of the component's parent. | ||||
| @see getScreenX | |||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to its bounding box. | |||||
| */ | */ | ||||
| inline int getX() const throw() { return bounds_.getX(); } | inline int getX() const throw() { return bounds_.getX(); } | ||||
| /** Returns the y co-ordinate of the top of this component. | |||||
| /** Returns the y coordinate of the top of this component. | |||||
| This is a distance in pixels from the top edge of the component's parent. | This is a distance in pixels from the top edge of the component's parent. | ||||
| @see getScreenY | |||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to its bounding box. | |||||
| */ | */ | ||||
| inline int getY() const throw() { return bounds_.getY(); } | inline int getY() const throw() { return bounds_.getY(); } | ||||
| @@ -26131,26 +26137,38 @@ public: | |||||
| /** Returns the component's height in pixels. */ | /** Returns the component's height in pixels. */ | ||||
| inline int getHeight() const throw() { return bounds_.getHeight(); } | inline int getHeight() const throw() { return bounds_.getHeight(); } | ||||
| /** Returns the x co-ordinate of the component's right-hand edge. | |||||
| /** Returns the x coordinate of the component's right-hand edge. | |||||
| This is a distance in pixels from the left edge of the component's parent. | This is a distance in pixels from the left edge of the component's parent. | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to its bounding box. | |||||
| */ | */ | ||||
| int getRight() const throw() { return bounds_.getRight(); } | int getRight() const throw() { return bounds_.getRight(); } | ||||
| /** Returns the component's top-left position as a Point. */ | /** Returns the component's top-left position as a Point. */ | ||||
| const Point<int> getPosition() const throw() { return bounds_.getPosition(); } | const Point<int> getPosition() const throw() { return bounds_.getPosition(); } | ||||
| /** Returns the y co-ordinate of the bottom edge of this component. | |||||
| /** Returns the y coordinate of the bottom edge of this component. | |||||
| This is a distance in pixels from the top edge of the component's parent. | This is a distance in pixels from the top edge of the component's parent. | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to its bounding box. | |||||
| */ | */ | ||||
| int getBottom() const throw() { return bounds_.getBottom(); } | int getBottom() const throw() { return bounds_.getBottom(); } | ||||
| /** Returns this component's bounding box. | /** Returns this component's bounding box. | ||||
| The rectangle returned is relative to the top-left of the component's parent. | The rectangle returned is relative to the top-left of the component's parent. | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to its bounding box. | |||||
| */ | */ | ||||
| const Rectangle<int>& getBounds() const throw() { return bounds_; } | const Rectangle<int>& getBounds() const throw() { return bounds_; } | ||||
| /** Returns the component's bounds, relative to its own origin. | /** Returns the component's bounds, relative to its own origin. | ||||
| This is like getBounds(), but returns the rectangle in local co-ordinates, In practice, it'll | |||||
| This is like getBounds(), but returns the rectangle in local coordinates, In practice, it'll | |||||
| return a rectangle with position (0, 0), and the same size as this component. | return a rectangle with position (0, 0), and the same size as this component. | ||||
| */ | */ | ||||
| const Rectangle<int> getLocalBounds() const throw(); | const Rectangle<int> getLocalBounds() const throw(); | ||||
| @@ -26166,12 +26184,12 @@ public: | |||||
| void getVisibleArea (RectangleList& result, | void getVisibleArea (RectangleList& result, | ||||
| bool includeSiblings) const; | bool includeSiblings) const; | ||||
| /** Returns this component's x co-ordinate relative the the screen's top-left origin. | |||||
| /** Returns this component's x coordinate relative the the screen's top-left origin. | |||||
| @see getX, localPointToGlobal | @see getX, localPointToGlobal | ||||
| */ | */ | ||||
| int getScreenX() const; | int getScreenX() const; | ||||
| /** Returns this component's y co-ordinate relative the the screen's top-left origin. | |||||
| /** Returns this component's y coordinate relative the the screen's top-left origin. | |||||
| @see getY, localPointToGlobal | @see getY, localPointToGlobal | ||||
| */ | */ | ||||
| int getScreenY() const; | int getScreenY() const; | ||||
| @@ -26200,6 +26218,10 @@ public: | |||||
| This takes a rectangle that is relative to a different component, and returns its position relative | This takes a rectangle that is relative to a different component, and returns its position relative | ||||
| to this component. If the sourceComponent parameter is null, the source rectangle is assumed to be | to this component. If the sourceComponent parameter is null, the source rectangle is assumed to be | ||||
| a screen coordinate. | a screen coordinate. | ||||
| If you've used setTransform() to apply one or more transforms to components, then the source rectangle | |||||
| may not actually be rectanglular when converted to the target space, so in that situation this will return | |||||
| the smallest rectangle that fully contains the transformed area. | |||||
| */ | */ | ||||
| const Rectangle<int> getLocalArea (const Component* sourceComponent, | const Rectangle<int> getLocalArea (const Component* sourceComponent, | ||||
| const Rectangle<int>& areaRelativeToSourceComponent) const; | const Rectangle<int>& areaRelativeToSourceComponent) const; | ||||
| @@ -26210,6 +26232,10 @@ public: | |||||
| const Point<int> localPointToGlobal (const Point<int>& localPoint) const; | const Point<int> localPointToGlobal (const Point<int>& localPoint) const; | ||||
| /** Converts a rectangle from this component's coordinate space to a screen coordinate. | /** Converts a rectangle from this component's coordinate space to a screen coordinate. | ||||
| If you've used setTransform() to apply one or more transforms to components, then the source rectangle | |||||
| may not actually be rectanglular when converted to the target space, so in that situation this will return | |||||
| the smallest rectangle that fully contains the transformed area. | |||||
| @see getLocalPoint, localPointToGlobal | @see getLocalPoint, localPointToGlobal | ||||
| */ | */ | ||||
| const Rectangle<int> localAreaToGlobal (const Rectangle<int>& localArea) const; | const Rectangle<int> localAreaToGlobal (const Rectangle<int>& localArea) const; | ||||
| @@ -26221,6 +26247,10 @@ public: | |||||
| If the component actually moves, this method will make a synchronous call to moved(). | If the component actually moves, this method will make a synchronous call to moved(). | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to whatever bounds you set for it. | |||||
| @see setBounds, ComponentListener::componentMovedOrResized | @see setBounds, ComponentListener::componentMovedOrResized | ||||
| */ | */ | ||||
| void setTopLeftPosition (int x, int y); | void setTopLeftPosition (int x, int y); | ||||
| @@ -26231,29 +26261,51 @@ public: | |||||
| The position is relative to the top-left of the component's parent. | The position is relative to the top-left of the component's parent. | ||||
| If the component actually moves, this method will make a synchronous call to moved(). | If the component actually moves, this method will make a synchronous call to moved(). | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to whatever bounds you set for it. | |||||
| */ | */ | ||||
| void setTopRightPosition (int x, int y); | void setTopRightPosition (int x, int y); | ||||
| /** Changes the size of the component. | /** Changes the size of the component. | ||||
| A synchronous call to resized() will be occur if the size actually changes. | A synchronous call to resized() will be occur if the size actually changes. | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to whatever bounds you set for it. | |||||
| */ | */ | ||||
| void setSize (int newWidth, int newHeight); | void setSize (int newWidth, int newHeight); | ||||
| /** Changes the component's position and size. | /** Changes the component's position and size. | ||||
| The co-ordinates are relative to the top-left of the component's parent, or relative | |||||
| The coordinates are relative to the top-left of the component's parent, or relative | |||||
| to the origin of the screen is the component is on the desktop. | to the origin of the screen is the component is on the desktop. | ||||
| If this method changes the component's top-left position, it will make a synchronous | If this method changes the component's top-left position, it will make a synchronous | ||||
| call to moved(). If it changes the size, it will also make a call to resized(). | call to moved(). If it changes the size, it will also make a call to resized(). | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to whatever bounds you set for it. | |||||
| @see setTopLeftPosition, setSize, ComponentListener::componentMovedOrResized | @see setTopLeftPosition, setSize, ComponentListener::componentMovedOrResized | ||||
| */ | */ | ||||
| void setBounds (int x, int y, int width, int height); | void setBounds (int x, int y, int width, int height); | ||||
| /** Changes the component's position and size. | /** Changes the component's position and size. | ||||
| The coordinates are relative to the top-left of the component's parent, or relative | |||||
| to the origin of the screen is the component is on the desktop. | |||||
| If this method changes the component's top-left position, it will make a synchronous | |||||
| call to moved(). If it changes the size, it will also make a call to resized(). | |||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to whatever bounds you set for it. | |||||
| @see setBounds | @see setBounds | ||||
| */ | */ | ||||
| void setBounds (const Rectangle<int>& newBounds); | void setBounds (const Rectangle<int>& newBounds); | ||||
| @@ -26264,6 +26316,8 @@ public: | |||||
| setBoundsRelative (0.2f, 0.2f, 0.5f, 0.5f) would give it half the | 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 | width and height of the parent, with its top-left position 20% of | ||||
| the way across and down the parent. | the way across and down the parent. | ||||
| @see setBounds | |||||
| */ | */ | ||||
| void setBoundsRelative (float proportionalX, float proportionalY, | void setBoundsRelative (float proportionalX, float proportionalY, | ||||
| float proportionalWidth, float proportionalHeight); | float proportionalWidth, float proportionalHeight); | ||||
| @@ -26272,6 +26326,8 @@ public: | |||||
| This will position the component within its parent, leaving the specified number of | This will position the component within its parent, leaving the specified number of | ||||
| pixels around each edge. | pixels around each edge. | ||||
| @see setBounds | |||||
| */ | */ | ||||
| void setBoundsInset (const BorderSize& borders); | void setBoundsInset (const BorderSize& borders); | ||||
| @@ -26286,6 +26342,8 @@ public: | |||||
| It will then be positioned within the rectangle according to the justification flags | It will then be positioned within the rectangle according to the justification flags | ||||
| specified. | specified. | ||||
| @see setBounds | |||||
| */ | */ | ||||
| void setBoundsToFit (int x, int y, int width, int height, | void setBoundsToFit (int x, int y, int width, int height, | ||||
| const Justification& justification, | const Justification& justification, | ||||
| @@ -26295,6 +26353,8 @@ public: | |||||
| Leaves the component's size unchanged, but sets the position of its centre | Leaves the component's size unchanged, but sets the position of its centre | ||||
| relative to its parent's top-left. | relative to its parent's top-left. | ||||
| @see setBounds | |||||
| */ | */ | ||||
| void setCentrePosition (int x, int y); | void setCentrePosition (int x, int y); | ||||
| @@ -26314,6 +26374,37 @@ public: | |||||
| */ | */ | ||||
| void centreWithSize (int width, int height); | void centreWithSize (int width, int height); | ||||
| /** Sets a transform matrix to be applied to this component. | |||||
| If you set a transform for a component, the component's position will be warped by it, relative to | |||||
| the component's parent's top-left origin. This means that the values you pass into setBounds() will no | |||||
| longer reflect the actual area within the parent that the component covers, as the bounds will be | |||||
| transformed and the component will probably end up actually appearing somewhere else within its parent. | |||||
| When using transforms you need to be extremely careful when converting coordinates between the | |||||
| coordinate spaces of different components or the screen - you should always use getLocalPoint(), | |||||
| getLocalArea(), etc to do this, and never just manually add a component's position to a point in order to | |||||
| convert it between different components (but I'm sure you would never have done that anyway...). | |||||
| Currently, transforms are not supported for desktop windows, so the transform will be ignored if you | |||||
| put a component on the desktop. | |||||
| To remove a component's transform, simply pass AffineTransform::identity as the parameter to this method. | |||||
| */ | |||||
| void setTransform (const AffineTransform& transform); | |||||
| /** Returns the transform that is currently being applied to this component. | |||||
| For more details about transforms, see setTransform(). | |||||
| @see setTransform | |||||
| */ | |||||
| const AffineTransform getTransform() const; | |||||
| /** Returns true if a non-identity transform is being applied to this component. | |||||
| For more details about transforms, see setTransform(). | |||||
| @see setTransform | |||||
| */ | |||||
| bool isTransformed() const throw(); | |||||
| /** Returns a proportion of the component's width. | /** Returns a proportion of the component's width. | ||||
| This is a handy equivalent of (getWidth() * proportion). | This is a handy equivalent of (getWidth() * proportion). | ||||
| @@ -26340,7 +26431,7 @@ public: | |||||
| */ | */ | ||||
| int getParentHeight() const throw(); | int getParentHeight() const throw(); | ||||
| /** Returns the screen co-ordinates of the monitor that contains this component. | |||||
| /** Returns the screen coordinates of the monitor that contains this component. | |||||
| If there's only one monitor, this will return its size - if there are multiple | If there's only one monitor, this will return its size - if there are multiple | ||||
| monitors, it will return the area of the monitor that contains the component's | monitors, it will return the area of the monitor that contains the component's | ||||
| @@ -26509,7 +26600,7 @@ public: | |||||
| Overriding this method allows you to create components which only intercept | Overriding this method allows you to create components which only intercept | ||||
| mouse-clicks within a user-defined area. | mouse-clicks within a user-defined area. | ||||
| This is called to find out whether a particular x, y co-ordinate is | |||||
| This is called to find out whether a particular x, y coordinate is | |||||
| considered to be inside the component or not, and is used by methods such | considered to be inside the component or not, and is used by methods such | ||||
| as contains() and getComponentAt() to work out which component | as contains() and getComponentAt() to work out which component | ||||
| the mouse is clicked on. | the mouse is clicked on. | ||||
| @@ -26531,10 +26622,10 @@ public: | |||||
| Note that for components on the desktop, this method will be ignored, because it's | Note that for components on the desktop, this method will be ignored, because it's | ||||
| not always possible to implement this behaviour on all platforms. | not always possible to implement this behaviour on all platforms. | ||||
| @param x the x co-ordinate to test, relative to the left hand edge of this | |||||
| @param x the x coordinate to test, relative to the left hand edge of this | |||||
| component. This value is guaranteed to be greater than or equal to | component. This value is guaranteed to be greater than or equal to | ||||
| zero, and less than the component's width | zero, and less than the component's width | ||||
| @param y the y co-ordinate to test, relative to the top edge of this | |||||
| @param y the y coordinate to test, relative to the top edge of this | |||||
| component. This value is guaranteed to be greater than or equal to | component. This value is guaranteed to be greater than or equal to | ||||
| zero, and less than the component's height | zero, and less than the component's height | ||||
| @returns true if the click is considered to be inside the component | @returns true if the click is considered to be inside the component | ||||
| @@ -26576,32 +26667,29 @@ public: | |||||
| Never override this method! Use hitTest to create custom hit regions. | Never override this method! Use hitTest to create custom hit regions. | ||||
| @param point the x co-ordinate to test, relative to this component's top-left. | |||||
| @param localPoint the coordinate to test, relative to this component's top-left. | |||||
| @returns true if the point is within the component's hit-test area, but only if | @returns true if the point is within the component's hit-test area, but only if | ||||
| that part of the component isn't clipped by its parent component. Note | that part of the component isn't clipped by its parent component. Note | ||||
| that this won't take into account any overlapping sibling components | that this won't take into account any overlapping sibling components | ||||
| which might be in the way - for that, see reallyContains() | which might be in the way - for that, see reallyContains() | ||||
| @see hitTest, reallyContains, getComponentAt | @see hitTest, reallyContains, getComponentAt | ||||
| */ | */ | ||||
| bool contains (const Point<int>& point); | |||||
| bool contains (const Point<int>& localPoint); | |||||
| /** Returns true if a given point lies in this component, taking any overlapping | /** Returns true if a given point lies in this component, taking any overlapping | ||||
| siblings into account. | siblings into account. | ||||
| @param x the x co-ordinate to test, relative to this component's left hand edge. | |||||
| @param y the y co-ordinate to test, relative to this component's top edge. | |||||
| @param returnTrueIfWithinAChild if the point actually lies within a child of this | |||||
| component, this determines the value that will | |||||
| be returned. | |||||
| @param localPoint the coordinate to test, relative to this component's top-left. | |||||
| @param returnTrueIfWithinAChild if the point actually lies within a child of this component, | |||||
| this determines whether that is counted as a hit. | |||||
| @see contains, getComponentAt | @see contains, getComponentAt | ||||
| */ | */ | ||||
| bool reallyContains (int x, int y, bool returnTrueIfWithinAChild); | |||||
| bool reallyContains (const Point<int>& localPoint, bool returnTrueIfWithinAChild); | |||||
| /** Returns the component at a certain point within this one. | /** Returns the component at a certain point within this one. | ||||
| @param x the x co-ordinate to test, relative to this component's left hand edge. | |||||
| @param y the y co-ordinate to test, relative to this component's top edge. | |||||
| @param x the x coordinate to test, relative to this component's left edge. | |||||
| @param y the y coordinate to test, relative to this component's top edge. | |||||
| @returns the component that is at this position - which may be 0, this component, | @returns the component that is at this position - which may be 0, this component, | ||||
| or one of its children. Note that overlapping siblings that might actually | or one of its children. Note that overlapping siblings that might actually | ||||
| be in the way are not taken into account by this method - to account for these, | be in the way are not taken into account by this method - to account for these, | ||||
| @@ -26612,7 +26700,7 @@ public: | |||||
| /** Returns the component at a certain point within this one. | /** Returns the component at a certain point within this one. | ||||
| @param position the co-ordinates to test, relative to this component's top-left. | |||||
| @param position the coordinate to test, relative to this component's top-left. | |||||
| @returns the component that is at this position - which may be 0, this component, | @returns the component that is at this position - which may be 0, this component, | ||||
| or one of its children. Note that overlapping siblings that might actually | or one of its children. Note that overlapping siblings that might actually | ||||
| be in the way are not taken into account by this method - to account for these, | be in the way are not taken into account by this method - to account for these, | ||||
| @@ -27442,8 +27530,7 @@ public: | |||||
| static bool JUCE_CALLTYPE isMouseButtonDownAnywhere() throw(); | static bool JUCE_CALLTYPE isMouseButtonDownAnywhere() throw(); | ||||
| /** Returns the mouse's current position, relative to this component. | /** Returns the mouse's current position, relative to this component. | ||||
| The co-ordinates are relative to the component's top-left corner. | |||||
| The return value is relative to the component's top-left corner. | |||||
| */ | */ | ||||
| const Point<int> getMouseXYRelative() const; | const Point<int> getMouseXYRelative() const; | ||||
| @@ -27849,6 +27936,7 @@ private: | |||||
| String componentName_; | String componentName_; | ||||
| Component* parentComponent_; | Component* parentComponent_; | ||||
| Rectangle<int> bounds_; | Rectangle<int> bounds_; | ||||
| ScopedPointer <AffineTransform> affineTransform_; | |||||
| Array <Component*> childComponentList_; | Array <Component*> childComponentList_; | ||||
| LookAndFeel* lookAndFeel_; | LookAndFeel* lookAndFeel_; | ||||
| MouseCursor cursor_; | MouseCursor cursor_; | ||||
| @@ -27914,6 +28002,7 @@ private: | |||||
| void internalHierarchyChanged(); | void internalHierarchyChanged(); | ||||
| void paintComponentAndChildren (Graphics& g); | void paintComponentAndChildren (Graphics& g); | ||||
| void paintComponent (Graphics& g); | void paintComponent (Graphics& g); | ||||
| void paintTransformedChild (Graphics& g); | |||||
| void sendMovedResizedMessages (bool wasMoved, bool wasResized); | void sendMovedResizedMessages (bool wasMoved, bool wasResized); | ||||
| void repaintParent(); | void repaintParent(); | ||||
| void sendFakeMouseMove() const; | void sendFakeMouseMove() const; | ||||
| @@ -36206,7 +36295,8 @@ private: | |||||
| void repeatTimerCallback(); | void repeatTimerCallback(); | ||||
| RepeatTimer& getRepeatTimer(); | RepeatTimer& getRepeatTimer(); | ||||
| ButtonState updateState (const MouseEvent*); | |||||
| ButtonState updateState(); | |||||
| ButtonState updateState (bool isOver, bool isDown); | |||||
| bool isShortcutPressed() const; | bool isShortcutPressed() const; | ||||
| void turnOffOtherButtonsInGroup (bool sendChangeNotification); | void turnOffOtherButtonsInGroup (bool sendChangeNotification); | ||||
| @@ -33,7 +33,7 @@ | |||||
| */ | */ | ||||
| #define JUCE_MAJOR_VERSION 1 | #define JUCE_MAJOR_VERSION 1 | ||||
| #define JUCE_MINOR_VERSION 52 | #define JUCE_MINOR_VERSION 52 | ||||
| #define JUCE_BUILDNUMBER 94 | |||||
| #define JUCE_BUILDNUMBER 95 | |||||
| /** Current Juce version number. | /** Current Juce version number. | ||||
| @@ -227,34 +227,29 @@ void Button::turnOffOtherButtonsInGroup (const bool sendChangeNotification) | |||||
| //============================================================================== | //============================================================================== | ||||
| void Button::enablementChanged() | void Button::enablementChanged() | ||||
| { | { | ||||
| updateState (0); | |||||
| updateState(); | |||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| Button::ButtonState Button::updateState (const MouseEvent* const e) | |||||
| Button::ButtonState Button::updateState() | |||||
| { | { | ||||
| ButtonState state = buttonNormal; | |||||
| return updateState (reallyContains (getMouseXYRelative(), true), isMouseButtonDown()); | |||||
| } | |||||
| Button::ButtonState Button::updateState (const bool over, const bool down) | |||||
| { | |||||
| ButtonState newState = buttonNormal; | |||||
| if (isEnabled() && isVisible() && ! isCurrentlyBlockedByAnotherModalComponent()) | if (isEnabled() && isVisible() && ! isCurrentlyBlockedByAnotherModalComponent()) | ||||
| { | { | ||||
| Point<int> mousePos; | |||||
| if (e == 0) | |||||
| mousePos = getMouseXYRelative(); | |||||
| else | |||||
| mousePos = e->getEventRelativeTo (this).getPosition(); | |||||
| const bool over = reallyContains (mousePos.getX(), mousePos.getY(), true); | |||||
| const bool down = isMouseButtonDown(); | |||||
| if ((down && (over || (triggerOnMouseDown && buttonState == buttonDown))) || isKeyDown) | if ((down && (over || (triggerOnMouseDown && buttonState == buttonDown))) || isKeyDown) | ||||
| state = buttonDown; | |||||
| newState = buttonDown; | |||||
| else if (over) | else if (over) | ||||
| state = buttonOver; | |||||
| newState = buttonOver; | |||||
| } | } | ||||
| setState (state); | |||||
| return state; | |||||
| setState (newState); | |||||
| return newState; | |||||
| } | } | ||||
| void Button::setState (const ButtonState newState) | void Button::setState (const ButtonState newState) | ||||
| @@ -403,19 +398,19 @@ void Button::paint (Graphics& g) | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void Button::mouseEnter (const MouseEvent& e) | |||||
| void Button::mouseEnter (const MouseEvent&) | |||||
| { | { | ||||
| updateState (&e); | |||||
| updateState (true, false); | |||||
| } | } | ||||
| void Button::mouseExit (const MouseEvent& e) | |||||
| void Button::mouseExit (const MouseEvent&) | |||||
| { | { | ||||
| updateState (&e); | |||||
| updateState (false, false); | |||||
| } | } | ||||
| void Button::mouseDown (const MouseEvent& e) | void Button::mouseDown (const MouseEvent& e) | ||||
| { | { | ||||
| updateState (&e); | |||||
| updateState (true, true); | |||||
| if (isDown()) | if (isDown()) | ||||
| { | { | ||||
| @@ -430,7 +425,7 @@ void Button::mouseDown (const MouseEvent& e) | |||||
| void Button::mouseUp (const MouseEvent& e) | void Button::mouseUp (const MouseEvent& e) | ||||
| { | { | ||||
| const bool wasDown = isDown(); | const bool wasDown = isDown(); | ||||
| updateState (&e); | |||||
| updateState (isMouseOver(), false); | |||||
| if (wasDown && isOver() && ! triggerOnMouseDown) | if (wasDown && isOver() && ! triggerOnMouseDown) | ||||
| internalClickCallback (e.mods); | internalClickCallback (e.mods); | ||||
| @@ -439,7 +434,7 @@ void Button::mouseUp (const MouseEvent& e) | |||||
| void Button::mouseDrag (const MouseEvent& e) | void Button::mouseDrag (const MouseEvent& e) | ||||
| { | { | ||||
| const ButtonState oldState = buttonState; | const ButtonState oldState = buttonState; | ||||
| updateState (&e); | |||||
| updateState (isMouseOver(), true); | |||||
| if (autoRepeatDelay >= 0 && buttonState != oldState && isDown()) | if (autoRepeatDelay >= 0 && buttonState != oldState && isDown()) | ||||
| getRepeatTimer().startTimer (autoRepeatSpeed); | getRepeatTimer().startTimer (autoRepeatSpeed); | ||||
| @@ -447,13 +442,13 @@ void Button::mouseDrag (const MouseEvent& e) | |||||
| void Button::focusGained (FocusChangeType) | void Button::focusGained (FocusChangeType) | ||||
| { | { | ||||
| updateState (0); | |||||
| updateState(); | |||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| void Button::focusLost (FocusChangeType) | void Button::focusLost (FocusChangeType) | ||||
| { | { | ||||
| updateState (0); | |||||
| updateState(); | |||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| @@ -467,7 +462,7 @@ void Button::setVisible (bool shouldBeVisible) | |||||
| if (! shouldBeVisible) | if (! shouldBeVisible) | ||||
| needsToRelease = false; | needsToRelease = false; | ||||
| updateState (0); | |||||
| updateState(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -597,7 +592,7 @@ bool Button::keyStateChanged (const bool, Component*) | |||||
| if (autoRepeatDelay >= 0 && (isKeyDown && ! wasDown)) | if (autoRepeatDelay >= 0 && (isKeyDown && ! wasDown)) | ||||
| getRepeatTimer().startTimer (autoRepeatDelay); | getRepeatTimer().startTimer (autoRepeatDelay); | ||||
| updateState (0); | |||||
| updateState(); | |||||
| if (isEnabled() && wasDown && ! isKeyDown) | if (isEnabled() && wasDown && ! isKeyDown) | ||||
| { | { | ||||
| @@ -642,10 +637,10 @@ void Button::repeatTimerCallback() | |||||
| if (needsRepainting) | if (needsRepainting) | ||||
| { | { | ||||
| getRepeatTimer().stopTimer(); | getRepeatTimer().stopTimer(); | ||||
| updateState (0); | |||||
| updateState(); | |||||
| needsRepainting = false; | needsRepainting = false; | ||||
| } | } | ||||
| else if (autoRepeatSpeed > 0 && (isKeyDown || (updateState (0) == buttonDown))) | |||||
| else if (autoRepeatSpeed > 0 && (isKeyDown || (updateState() == buttonDown))) | |||||
| { | { | ||||
| int repeatSpeed = autoRepeatSpeed; | int repeatSpeed = autoRepeatSpeed; | ||||
| @@ -495,7 +495,8 @@ private: | |||||
| void repeatTimerCallback(); | void repeatTimerCallback(); | ||||
| RepeatTimer& getRepeatTimer(); | RepeatTimer& getRepeatTimer(); | ||||
| ButtonState updateState (const MouseEvent*); | |||||
| ButtonState updateState(); | |||||
| ButtonState updateState (bool isOver, bool isDown); | |||||
| bool isShortcutPressed() const; | bool isShortcutPressed() const; | ||||
| void turnOffOtherButtonsInGroup (bool sendChangeNotification); | void turnOffOtherButtonsInGroup (bool sendChangeNotification); | ||||
| @@ -590,7 +590,7 @@ void ComboBox::mouseUp (const MouseEvent& e2) | |||||
| const MouseEvent e (e2.getEventRelativeTo (this)); | const MouseEvent e (e2.getEventRelativeTo (this)); | ||||
| if (reallyContains (e.x, e.y, true) | |||||
| if (reallyContains (e.getPosition(), true) | |||||
| && (e2.eventComponent == this || ! label->isEditable())) | && (e2.eventComponent == this || ! label->isEditable())) | ||||
| { | { | ||||
| showPopup(); | showPopup(); | ||||
| @@ -352,6 +352,10 @@ void Slider::lookAndFeelChanged() | |||||
| valueBox->setTooltip (getTooltip()); | valueBox->setTooltip (getTooltip()); | ||||
| } | } | ||||
| else | |||||
| { | |||||
| valueBox = 0; | |||||
| } | |||||
| if (style == IncDecButtons) | if (style == IncDecButtons) | ||||
| { | { | ||||
| @@ -909,7 +909,7 @@ int TableHeaderComponent::getResizeDraggerAt (const int mouseX) const | |||||
| void TableHeaderComponent::updateColumnUnderMouse (int x, int y) | void TableHeaderComponent::updateColumnUnderMouse (int x, int y) | ||||
| { | { | ||||
| const int newCol = (reallyContains (x, y, true) && getResizeDraggerAt (x) == 0) | |||||
| const int newCol = (reallyContains (Point<int> (x, y), true) && getResizeDraggerAt (x) == 0) | |||||
| ? getColumnIdAtX (x) : 0; | ? getColumnIdAtX (x) : 0; | ||||
| if (newCol != columnIdUnderMouse) | if (newCol != columnIdUnderMouse) | ||||
| @@ -44,7 +44,7 @@ BEGIN_JUCE_NAMESPACE | |||||
| //============================================================================== | //============================================================================== | ||||
| #define checkMessageManagerIsLocked jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||||
| #define CHECK_MESSAGE_MANAGER_IS_LOCKED jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||||
| Component* Component::currentlyFocusedComponent = 0; | Component* Component::currentlyFocusedComponent = 0; | ||||
| @@ -249,22 +249,34 @@ public: | |||||
| static const Point<int> convertFromParentSpace (const Component& comp, const Point<int>& pointInParentSpace) | static const Point<int> convertFromParentSpace (const Component& comp, const Point<int>& pointInParentSpace) | ||||
| { | { | ||||
| return pointInParentSpace - comp.getPosition(); | |||||
| if (comp.affineTransform_ == 0) | |||||
| return pointInParentSpace - comp.getPosition(); | |||||
| return pointInParentSpace.toFloat().transformedBy (comp.affineTransform_->inverted()).toInt() - comp.getPosition(); | |||||
| } | } | ||||
| static const Rectangle<int> convertFromParentSpace (const Component& comp, const Rectangle<int>& areaInParentSpace) | static const Rectangle<int> convertFromParentSpace (const Component& comp, const Rectangle<int>& areaInParentSpace) | ||||
| { | { | ||||
| return areaInParentSpace - comp.getPosition(); | |||||
| if (comp.affineTransform_ == 0) | |||||
| return areaInParentSpace - comp.getPosition(); | |||||
| return areaInParentSpace.toFloat().transformed (comp.affineTransform_->inverted()).getSmallestIntegerContainer() - comp.getPosition(); | |||||
| } | } | ||||
| static const Point<int> convertToParentSpace (const Component& comp, const Point<int>& pointInLocalSpace) | static const Point<int> convertToParentSpace (const Component& comp, const Point<int>& pointInLocalSpace) | ||||
| { | { | ||||
| return pointInLocalSpace + comp.getPosition(); | |||||
| if (comp.affineTransform_ == 0) | |||||
| return pointInLocalSpace + comp.getPosition(); | |||||
| return (pointInLocalSpace + comp.getPosition()).toFloat().transformedBy (*comp.affineTransform_).toInt(); | |||||
| } | } | ||||
| static const Rectangle<int> convertToParentSpace (const Component& comp, const Rectangle<int>& areaInLocalSpace) | static const Rectangle<int> convertToParentSpace (const Component& comp, const Rectangle<int>& areaInLocalSpace) | ||||
| { | { | ||||
| return areaInLocalSpace + comp.getPosition(); | |||||
| if (comp.affineTransform_ == 0) | |||||
| return areaInLocalSpace + comp.getPosition(); | |||||
| return (areaInLocalSpace + comp.getPosition()).toFloat().transformed (*comp.affineTransform_).getSmallestIntegerContainer(); | |||||
| } | } | ||||
| template <typename Type> | template <typename Type> | ||||
| @@ -337,8 +349,7 @@ public: | |||||
| { | { | ||||
| const Component& child = *comp.childComponentList_.getUnchecked(i); | const Component& child = *comp.childComponentList_.getUnchecked(i); | ||||
| //xxx if (child.isVisible() && ! child.isTransformed()) | |||||
| if (child.isVisible()) | |||||
| if (child.isVisible() && ! child.isTransformed()) | |||||
| { | { | ||||
| const Rectangle<int> newClip (clipRect.getIntersection (child.bounds_)); | const Rectangle<int> newClip (clipRect.getIntersection (child.bounds_)); | ||||
| @@ -465,7 +476,7 @@ void Component::setName (const String& name) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (componentName_ != name) | if (componentName_ != name) | ||||
| { | { | ||||
| @@ -491,7 +502,7 @@ void Component::setVisible (bool shouldBeVisible) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| SafePointer<Component> safePointer (this); | SafePointer<Component> safePointer (this); | ||||
| @@ -582,7 +593,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (isOpaque()) | if (isOpaque()) | ||||
| styleWanted &= ~ComponentPeer::windowIsSemiTransparent; | styleWanted &= ~ComponentPeer::windowIsSemiTransparent; | ||||
| @@ -670,7 +681,7 @@ void Component::removeFromDesktop() | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (flags.hasHeavyweightPeerFlag) | if (flags.hasHeavyweightPeerFlag) | ||||
| { | { | ||||
| @@ -748,7 +759,7 @@ void Component::toFront (const bool setAsForeground) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (flags.hasHeavyweightPeerFlag) | if (flags.hasHeavyweightPeerFlag) | ||||
| { | { | ||||
| @@ -990,7 +1001,7 @@ void Component::setBounds (const int x, const int y, int w, int h) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (w < 0) w = 0; | if (w < 0) w = 0; | ||||
| if (h < 0) h = 0; | if (h < 0) h = 0; | ||||
| @@ -1178,6 +1189,42 @@ void Component::setBoundsToFit (int x, int y, int width, int height, | |||||
| } | } | ||||
| } | } | ||||
| //============================================================================== | |||||
| bool Component::isTransformed() const throw() | |||||
| { | |||||
| return affineTransform_ != 0; | |||||
| } | |||||
| void Component::setTransform (const AffineTransform& newTransform) | |||||
| { | |||||
| if (newTransform.isIdentity()) | |||||
| { | |||||
| if (affineTransform_ != 0) | |||||
| { | |||||
| repaint(); | |||||
| affineTransform_ = 0; | |||||
| repaint(); | |||||
| } | |||||
| } | |||||
| else if (affineTransform_ == 0) | |||||
| { | |||||
| repaint(); | |||||
| affineTransform_ = new AffineTransform (newTransform); | |||||
| repaint(); | |||||
| } | |||||
| else if (*affineTransform_ != newTransform) | |||||
| { | |||||
| repaint(); | |||||
| *affineTransform_ = newTransform; | |||||
| repaint(); | |||||
| } | |||||
| } | |||||
| const AffineTransform Component::getTransform() const | |||||
| { | |||||
| return affineTransform_ != 0 ? *affineTransform_ : AffineTransform::identity; | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| bool Component::hitTest (int x, int y) | bool Component::hitTest (int x, int y) | ||||
| { | { | ||||
| @@ -1233,15 +1280,13 @@ bool Component::contains (const Point<int>& point) | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool Component::reallyContains (const int x, const int y, const bool returnTrueIfWithinAChild) | |||||
| bool Component::reallyContains (const Point<int>& point, const bool returnTrueIfWithinAChild) | |||||
| { | { | ||||
| const Point<int> p (x, y); | |||||
| if (! contains (p)) | |||||
| if (! contains (point)) | |||||
| return false; | return false; | ||||
| Component* const top = getTopLevelComponent(); | Component* const top = getTopLevelComponent(); | ||||
| const Component* const compAtPosition = top->getComponentAt (top->getLocalPoint (this, p)); | |||||
| const Component* const compAtPosition = top->getComponentAt (top->getLocalPoint (this, point)); | |||||
| return (compAtPosition == this) || (returnTrueIfWithinAChild && isParentOf (compAtPosition)); | return (compAtPosition == this) || (returnTrueIfWithinAChild && isParentOf (compAtPosition)); | ||||
| } | } | ||||
| @@ -1275,7 +1320,7 @@ void Component::addChildComponent (Component* const child, int zOrder) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (child != 0 && child->parentComponent_ != this) | if (child != 0 && child->parentComponent_ != this) | ||||
| { | { | ||||
| @@ -1328,7 +1373,7 @@ Component* Component::removeChildComponent (const int index) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| Component* const child = childComponentList_ [index]; | Component* const child = childComponentList_ [index]; | ||||
| @@ -1500,7 +1545,7 @@ void Component::enterModalState (const bool takeKeyboardFocus_, ModalComponentMa | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| // Check for an attempt to make a component modal when it already is! | // Check for an attempt to make a component modal when it already is! | ||||
| // This can cause nasty problems.. | // This can cause nasty problems.. | ||||
| @@ -1674,7 +1719,7 @@ void Component::internalRepaint (int x, int y, int w, int h) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (x < 0) | if (x < 0) | ||||
| { | { | ||||
| @@ -1701,7 +1746,17 @@ void Component::internalRepaint (int x, int y, int w, int h) | |||||
| if (parentComponent_ != 0) | if (parentComponent_ != 0) | ||||
| { | { | ||||
| if (parentComponent_->flags.visibleFlag) | if (parentComponent_->flags.visibleFlag) | ||||
| parentComponent_->internalRepaint (x + getX(), y + getY(), w, h); | |||||
| { | |||||
| if (affineTransform_ == 0) | |||||
| { | |||||
| parentComponent_->internalRepaint (x + getX(), y + getY(), w, h); | |||||
| } | |||||
| else | |||||
| { | |||||
| const Rectangle<int> r (ComponentHelpers::convertToParentSpace (*this, Rectangle<int> (x, y, w, h))); | |||||
| parentComponent_->internalRepaint (r.getX(), r.getY(), r.getWidth(), r.getHeight()); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| else if (flags.hasHeavyweightPeerFlag) | else if (flags.hasHeavyweightPeerFlag) | ||||
| { | { | ||||
| @@ -1737,6 +1792,15 @@ void Component::paintComponent (Graphics& g) | |||||
| } | } | ||||
| } | } | ||||
| void Component::paintTransformedChild (Graphics& g) | |||||
| { | |||||
| if (affineTransform_ != 0) | |||||
| g.addTransform (*affineTransform_); | |||||
| g.setOrigin (getX(), getY()); | |||||
| paintEntireComponent (g, false); | |||||
| } | |||||
| void Component::paintComponentAndChildren (Graphics& g) | void Component::paintComponentAndChildren (Graphics& g) | ||||
| { | { | ||||
| const Rectangle<int> clipBounds (g.getClipBounds()); | const Rectangle<int> clipBounds (g.getClipBounds()); | ||||
| @@ -1766,8 +1830,7 @@ void Component::paintComponentAndChildren (Graphics& g) | |||||
| if (child->flags.dontClipGraphicsFlag) | if (child->flags.dontClipGraphicsFlag) | ||||
| { | { | ||||
| g.setOrigin (child->getX(), child->getY()); | |||||
| child->paintEntireComponent (g, false); | |||||
| child->paintTransformedChild (g); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -1787,10 +1850,7 @@ void Component::paintComponentAndChildren (Graphics& g) | |||||
| } | } | ||||
| if (nothingClipped || ! g.isClipEmpty()) | if (nothingClipped || ! g.isClipEmpty()) | ||||
| { | |||||
| g.setOrigin (child->getX(), child->getY()); | |||||
| child->paintEntireComponent (g, false); | |||||
| } | |||||
| child->paintTransformedChild (g); | |||||
| } | } | ||||
| } | } | ||||
| @@ -2161,7 +2221,7 @@ void Component::addMouseListener (MouseListener* const newListener, | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| // If you register a component as a mouselistener for itself, it'll receive all the events | // If you register a component as a mouselistener for itself, it'll receive all the events | ||||
| // twice - once via the direct callback that all components get anyway, and then again as a listener! | // twice - once via the direct callback that all components get anyway, and then again as a listener! | ||||
| @@ -2177,7 +2237,7 @@ void Component::removeMouseListener (MouseListener* const listenerToRemove) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (mouseListeners_ != 0) | if (mouseListeners_ != 0) | ||||
| mouseListeners_->removeListener (listenerToRemove); | mouseListeners_->removeListener (listenerToRemove); | ||||
| @@ -2437,7 +2497,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point<int>& r | |||||
| { | { | ||||
| Desktop& desktop = Desktop::getInstance(); | Desktop& desktop = Desktop::getInstance(); | ||||
| flags.mouseOverFlag = reallyContains (relativePos.getX(), relativePos.getY(), false); | |||||
| flags.mouseOverFlag = reallyContains (relativePos, false); | |||||
| BailOutChecker checker (this); | BailOutChecker checker (this); | ||||
| @@ -2807,7 +2867,7 @@ void Component::grabKeyboardFocus() | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| grabFocusInternal (focusChangedDirectly); | grabFocusInternal (focusChangedDirectly); | ||||
| } | } | ||||
| @@ -2816,7 +2876,7 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext) | |||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | ||||
| checkMessageManagerIsLocked | |||||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||||
| if (parentComponent_ != 0) | if (parentComponent_ != 0) | ||||
| { | { | ||||
| @@ -2872,20 +2932,9 @@ void Component::giveAwayFocus() | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| bool Component::isMouseOver() const throw() | |||||
| { | |||||
| return flags.mouseOverFlag; | |||||
| } | |||||
| bool Component::isMouseButtonDown() const throw() | |||||
| { | |||||
| return flags.mouseDownFlag; | |||||
| } | |||||
| bool Component::isMouseOverOrDragging() const throw() | |||||
| { | |||||
| return flags.mouseOverFlag || flags.mouseDownFlag; | |||||
| } | |||||
| bool Component::isMouseOver() const throw() { return flags.mouseOverFlag; } | |||||
| bool Component::isMouseButtonDown() const throw() { return flags.mouseDownFlag; } | |||||
| bool Component::isMouseOverOrDragging() const throw() { return flags.mouseOverFlag || flags.mouseDownFlag; } | |||||
| bool JUCE_CALLTYPE Component::isMouseButtonDownAnywhere() throw() | bool JUCE_CALLTYPE Component::isMouseButtonDownAnywhere() throw() | ||||
| { | { | ||||
| @@ -2900,8 +2949,7 @@ const Point<int> Component::getMouseXYRelative() const | |||||
| //============================================================================== | //============================================================================== | ||||
| const Rectangle<int> Component::getParentMonitorArea() const | const Rectangle<int> Component::getParentMonitorArea() const | ||||
| { | { | ||||
| return Desktop::getInstance() | |||||
| .getMonitorAreaContaining (localPointToGlobal (getLocalBounds().getCentre())); | |||||
| return Desktop::getInstance().getMonitorAreaContaining (getScreenBounds().getCentre()); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -258,15 +258,21 @@ public: | |||||
| bool isAlwaysOnTop() const throw(); | bool isAlwaysOnTop() const throw(); | ||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns the x co-ordinate of the component's left edge. | |||||
| /** Returns the x coordinate of the component's left edge. | |||||
| This is a distance in pixels from the left edge of the component's parent. | This is a distance in pixels from the left edge of the component's parent. | ||||
| @see getScreenX | |||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to its bounding box. | |||||
| */ | */ | ||||
| inline int getX() const throw() { return bounds_.getX(); } | inline int getX() const throw() { return bounds_.getX(); } | ||||
| /** Returns the y co-ordinate of the top of this component. | |||||
| /** Returns the y coordinate of the top of this component. | |||||
| This is a distance in pixels from the top edge of the component's parent. | This is a distance in pixels from the top edge of the component's parent. | ||||
| @see getScreenY | |||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to its bounding box. | |||||
| */ | */ | ||||
| inline int getY() const throw() { return bounds_.getY(); } | inline int getY() const throw() { return bounds_.getY(); } | ||||
| @@ -276,26 +282,38 @@ public: | |||||
| /** Returns the component's height in pixels. */ | /** Returns the component's height in pixels. */ | ||||
| inline int getHeight() const throw() { return bounds_.getHeight(); } | inline int getHeight() const throw() { return bounds_.getHeight(); } | ||||
| /** Returns the x co-ordinate of the component's right-hand edge. | |||||
| /** Returns the x coordinate of the component's right-hand edge. | |||||
| This is a distance in pixels from the left edge of the component's parent. | This is a distance in pixels from the left edge of the component's parent. | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to its bounding box. | |||||
| */ | */ | ||||
| int getRight() const throw() { return bounds_.getRight(); } | int getRight() const throw() { return bounds_.getRight(); } | ||||
| /** Returns the component's top-left position as a Point. */ | /** Returns the component's top-left position as a Point. */ | ||||
| const Point<int> getPosition() const throw() { return bounds_.getPosition(); } | const Point<int> getPosition() const throw() { return bounds_.getPosition(); } | ||||
| /** Returns the y co-ordinate of the bottom edge of this component. | |||||
| /** Returns the y coordinate of the bottom edge of this component. | |||||
| This is a distance in pixels from the top edge of the component's parent. | This is a distance in pixels from the top edge of the component's parent. | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to its bounding box. | |||||
| */ | */ | ||||
| int getBottom() const throw() { return bounds_.getBottom(); } | int getBottom() const throw() { return bounds_.getBottom(); } | ||||
| /** Returns this component's bounding box. | /** Returns this component's bounding box. | ||||
| The rectangle returned is relative to the top-left of the component's parent. | The rectangle returned is relative to the top-left of the component's parent. | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to its bounding box. | |||||
| */ | */ | ||||
| const Rectangle<int>& getBounds() const throw() { return bounds_; } | const Rectangle<int>& getBounds() const throw() { return bounds_; } | ||||
| /** Returns the component's bounds, relative to its own origin. | /** Returns the component's bounds, relative to its own origin. | ||||
| This is like getBounds(), but returns the rectangle in local co-ordinates, In practice, it'll | |||||
| This is like getBounds(), but returns the rectangle in local coordinates, In practice, it'll | |||||
| return a rectangle with position (0, 0), and the same size as this component. | return a rectangle with position (0, 0), and the same size as this component. | ||||
| */ | */ | ||||
| const Rectangle<int> getLocalBounds() const throw(); | const Rectangle<int> getLocalBounds() const throw(); | ||||
| @@ -312,12 +330,12 @@ public: | |||||
| bool includeSiblings) const; | bool includeSiblings) const; | ||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns this component's x co-ordinate relative the the screen's top-left origin. | |||||
| /** Returns this component's x coordinate relative the the screen's top-left origin. | |||||
| @see getX, localPointToGlobal | @see getX, localPointToGlobal | ||||
| */ | */ | ||||
| int getScreenX() const; | int getScreenX() const; | ||||
| /** Returns this component's y co-ordinate relative the the screen's top-left origin. | |||||
| /** Returns this component's y coordinate relative the the screen's top-left origin. | |||||
| @see getY, localPointToGlobal | @see getY, localPointToGlobal | ||||
| */ | */ | ||||
| int getScreenY() const; | int getScreenY() const; | ||||
| @@ -346,6 +364,10 @@ public: | |||||
| This takes a rectangle that is relative to a different component, and returns its position relative | This takes a rectangle that is relative to a different component, and returns its position relative | ||||
| to this component. If the sourceComponent parameter is null, the source rectangle is assumed to be | to this component. If the sourceComponent parameter is null, the source rectangle is assumed to be | ||||
| a screen coordinate. | a screen coordinate. | ||||
| If you've used setTransform() to apply one or more transforms to components, then the source rectangle | |||||
| may not actually be rectanglular when converted to the target space, so in that situation this will return | |||||
| the smallest rectangle that fully contains the transformed area. | |||||
| */ | */ | ||||
| const Rectangle<int> getLocalArea (const Component* sourceComponent, | const Rectangle<int> getLocalArea (const Component* sourceComponent, | ||||
| const Rectangle<int>& areaRelativeToSourceComponent) const; | const Rectangle<int>& areaRelativeToSourceComponent) const; | ||||
| @@ -356,6 +378,10 @@ public: | |||||
| const Point<int> localPointToGlobal (const Point<int>& localPoint) const; | const Point<int> localPointToGlobal (const Point<int>& localPoint) const; | ||||
| /** Converts a rectangle from this component's coordinate space to a screen coordinate. | /** Converts a rectangle from this component's coordinate space to a screen coordinate. | ||||
| If you've used setTransform() to apply one or more transforms to components, then the source rectangle | |||||
| may not actually be rectanglular when converted to the target space, so in that situation this will return | |||||
| the smallest rectangle that fully contains the transformed area. | |||||
| @see getLocalPoint, localPointToGlobal | @see getLocalPoint, localPointToGlobal | ||||
| */ | */ | ||||
| const Rectangle<int> localAreaToGlobal (const Rectangle<int>& localArea) const; | const Rectangle<int> localAreaToGlobal (const Rectangle<int>& localArea) const; | ||||
| @@ -368,6 +394,10 @@ public: | |||||
| If the component actually moves, this method will make a synchronous call to moved(). | If the component actually moves, this method will make a synchronous call to moved(). | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to whatever bounds you set for it. | |||||
| @see setBounds, ComponentListener::componentMovedOrResized | @see setBounds, ComponentListener::componentMovedOrResized | ||||
| */ | */ | ||||
| void setTopLeftPosition (int x, int y); | void setTopLeftPosition (int x, int y); | ||||
| @@ -378,29 +408,51 @@ public: | |||||
| The position is relative to the top-left of the component's parent. | The position is relative to the top-left of the component's parent. | ||||
| If the component actually moves, this method will make a synchronous call to moved(). | If the component actually moves, this method will make a synchronous call to moved(). | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to whatever bounds you set for it. | |||||
| */ | */ | ||||
| void setTopRightPosition (int x, int y); | void setTopRightPosition (int x, int y); | ||||
| /** Changes the size of the component. | /** Changes the size of the component. | ||||
| A synchronous call to resized() will be occur if the size actually changes. | A synchronous call to resized() will be occur if the size actually changes. | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to whatever bounds you set for it. | |||||
| */ | */ | ||||
| void setSize (int newWidth, int newHeight); | void setSize (int newWidth, int newHeight); | ||||
| /** Changes the component's position and size. | /** Changes the component's position and size. | ||||
| The co-ordinates are relative to the top-left of the component's parent, or relative | |||||
| The coordinates are relative to the top-left of the component's parent, or relative | |||||
| to the origin of the screen is the component is on the desktop. | to the origin of the screen is the component is on the desktop. | ||||
| If this method changes the component's top-left position, it will make a synchronous | If this method changes the component's top-left position, it will make a synchronous | ||||
| call to moved(). If it changes the size, it will also make a call to resized(). | call to moved(). If it changes the size, it will also make a call to resized(). | ||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to whatever bounds you set for it. | |||||
| @see setTopLeftPosition, setSize, ComponentListener::componentMovedOrResized | @see setTopLeftPosition, setSize, ComponentListener::componentMovedOrResized | ||||
| */ | */ | ||||
| void setBounds (int x, int y, int width, int height); | void setBounds (int x, int y, int width, int height); | ||||
| /** Changes the component's position and size. | /** Changes the component's position and size. | ||||
| The coordinates are relative to the top-left of the component's parent, or relative | |||||
| to the origin of the screen is the component is on the desktop. | |||||
| If this method changes the component's top-left position, it will make a synchronous | |||||
| call to moved(). If it changes the size, it will also make a call to resized(). | |||||
| Note that if you've used setTransform() to apply a transform, then the component's | |||||
| bounds will no longer be a direct reflection of the position at which it appears within | |||||
| its parent, as the transform will be applied to whatever bounds you set for it. | |||||
| @see setBounds | @see setBounds | ||||
| */ | */ | ||||
| void setBounds (const Rectangle<int>& newBounds); | void setBounds (const Rectangle<int>& newBounds); | ||||
| @@ -411,6 +463,8 @@ public: | |||||
| setBoundsRelative (0.2f, 0.2f, 0.5f, 0.5f) would give it half the | 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 | width and height of the parent, with its top-left position 20% of | ||||
| the way across and down the parent. | the way across and down the parent. | ||||
| @see setBounds | |||||
| */ | */ | ||||
| void setBoundsRelative (float proportionalX, float proportionalY, | void setBoundsRelative (float proportionalX, float proportionalY, | ||||
| float proportionalWidth, float proportionalHeight); | float proportionalWidth, float proportionalHeight); | ||||
| @@ -419,6 +473,8 @@ public: | |||||
| This will position the component within its parent, leaving the specified number of | This will position the component within its parent, leaving the specified number of | ||||
| pixels around each edge. | pixels around each edge. | ||||
| @see setBounds | |||||
| */ | */ | ||||
| void setBoundsInset (const BorderSize& borders); | void setBoundsInset (const BorderSize& borders); | ||||
| @@ -433,6 +489,8 @@ public: | |||||
| It will then be positioned within the rectangle according to the justification flags | It will then be positioned within the rectangle according to the justification flags | ||||
| specified. | specified. | ||||
| @see setBounds | |||||
| */ | */ | ||||
| void setBoundsToFit (int x, int y, int width, int height, | void setBoundsToFit (int x, int y, int width, int height, | ||||
| const Justification& justification, | const Justification& justification, | ||||
| @@ -442,6 +500,8 @@ public: | |||||
| Leaves the component's size unchanged, but sets the position of its centre | Leaves the component's size unchanged, but sets the position of its centre | ||||
| relative to its parent's top-left. | relative to its parent's top-left. | ||||
| @see setBounds | |||||
| */ | */ | ||||
| void setCentrePosition (int x, int y); | void setCentrePosition (int x, int y); | ||||
| @@ -461,6 +521,38 @@ public: | |||||
| */ | */ | ||||
| void centreWithSize (int width, int height); | void centreWithSize (int width, int height); | ||||
| //============================================================================== | |||||
| /** Sets a transform matrix to be applied to this component. | |||||
| If you set a transform for a component, the component's position will be warped by it, relative to | |||||
| the component's parent's top-left origin. This means that the values you pass into setBounds() will no | |||||
| longer reflect the actual area within the parent that the component covers, as the bounds will be | |||||
| transformed and the component will probably end up actually appearing somewhere else within its parent. | |||||
| When using transforms you need to be extremely careful when converting coordinates between the | |||||
| coordinate spaces of different components or the screen - you should always use getLocalPoint(), | |||||
| getLocalArea(), etc to do this, and never just manually add a component's position to a point in order to | |||||
| convert it between different components (but I'm sure you would never have done that anyway...). | |||||
| Currently, transforms are not supported for desktop windows, so the transform will be ignored if you | |||||
| put a component on the desktop. | |||||
| To remove a component's transform, simply pass AffineTransform::identity as the parameter to this method. | |||||
| */ | |||||
| void setTransform (const AffineTransform& transform); | |||||
| /** Returns the transform that is currently being applied to this component. | |||||
| For more details about transforms, see setTransform(). | |||||
| @see setTransform | |||||
| */ | |||||
| const AffineTransform getTransform() const; | |||||
| /** Returns true if a non-identity transform is being applied to this component. | |||||
| For more details about transforms, see setTransform(). | |||||
| @see setTransform | |||||
| */ | |||||
| bool isTransformed() const throw(); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns a proportion of the component's width. | /** Returns a proportion of the component's width. | ||||
| @@ -488,7 +580,7 @@ public: | |||||
| */ | */ | ||||
| int getParentHeight() const throw(); | int getParentHeight() const throw(); | ||||
| /** Returns the screen co-ordinates of the monitor that contains this component. | |||||
| /** Returns the screen coordinates of the monitor that contains this component. | |||||
| If there's only one monitor, this will return its size - if there are multiple | If there's only one monitor, this will return its size - if there are multiple | ||||
| monitors, it will return the area of the monitor that contains the component's | monitors, it will return the area of the monitor that contains the component's | ||||
| @@ -660,7 +752,7 @@ public: | |||||
| Overriding this method allows you to create components which only intercept | Overriding this method allows you to create components which only intercept | ||||
| mouse-clicks within a user-defined area. | mouse-clicks within a user-defined area. | ||||
| This is called to find out whether a particular x, y co-ordinate is | |||||
| This is called to find out whether a particular x, y coordinate is | |||||
| considered to be inside the component or not, and is used by methods such | considered to be inside the component or not, and is used by methods such | ||||
| as contains() and getComponentAt() to work out which component | as contains() and getComponentAt() to work out which component | ||||
| the mouse is clicked on. | the mouse is clicked on. | ||||
| @@ -682,10 +774,10 @@ public: | |||||
| Note that for components on the desktop, this method will be ignored, because it's | Note that for components on the desktop, this method will be ignored, because it's | ||||
| not always possible to implement this behaviour on all platforms. | not always possible to implement this behaviour on all platforms. | ||||
| @param x the x co-ordinate to test, relative to the left hand edge of this | |||||
| @param x the x coordinate to test, relative to the left hand edge of this | |||||
| component. This value is guaranteed to be greater than or equal to | component. This value is guaranteed to be greater than or equal to | ||||
| zero, and less than the component's width | zero, and less than the component's width | ||||
| @param y the y co-ordinate to test, relative to the top edge of this | |||||
| @param y the y coordinate to test, relative to the top edge of this | |||||
| component. This value is guaranteed to be greater than or equal to | component. This value is guaranteed to be greater than or equal to | ||||
| zero, and less than the component's height | zero, and less than the component's height | ||||
| @returns true if the click is considered to be inside the component | @returns true if the click is considered to be inside the component | ||||
| @@ -728,32 +820,29 @@ public: | |||||
| Never override this method! Use hitTest to create custom hit regions. | Never override this method! Use hitTest to create custom hit regions. | ||||
| @param point the x co-ordinate to test, relative to this component's top-left. | |||||
| @param localPoint the coordinate to test, relative to this component's top-left. | |||||
| @returns true if the point is within the component's hit-test area, but only if | @returns true if the point is within the component's hit-test area, but only if | ||||
| that part of the component isn't clipped by its parent component. Note | that part of the component isn't clipped by its parent component. Note | ||||
| that this won't take into account any overlapping sibling components | that this won't take into account any overlapping sibling components | ||||
| which might be in the way - for that, see reallyContains() | which might be in the way - for that, see reallyContains() | ||||
| @see hitTest, reallyContains, getComponentAt | @see hitTest, reallyContains, getComponentAt | ||||
| */ | */ | ||||
| bool contains (const Point<int>& point); | |||||
| bool contains (const Point<int>& localPoint); | |||||
| /** Returns true if a given point lies in this component, taking any overlapping | /** Returns true if a given point lies in this component, taking any overlapping | ||||
| siblings into account. | siblings into account. | ||||
| @param x the x co-ordinate to test, relative to this component's left hand edge. | |||||
| @param y the y co-ordinate to test, relative to this component's top edge. | |||||
| @param returnTrueIfWithinAChild if the point actually lies within a child of this | |||||
| component, this determines the value that will | |||||
| be returned. | |||||
| @param localPoint the coordinate to test, relative to this component's top-left. | |||||
| @param returnTrueIfWithinAChild if the point actually lies within a child of this component, | |||||
| this determines whether that is counted as a hit. | |||||
| @see contains, getComponentAt | @see contains, getComponentAt | ||||
| */ | */ | ||||
| bool reallyContains (int x, int y, bool returnTrueIfWithinAChild); | |||||
| bool reallyContains (const Point<int>& localPoint, bool returnTrueIfWithinAChild); | |||||
| /** Returns the component at a certain point within this one. | /** Returns the component at a certain point within this one. | ||||
| @param x the x co-ordinate to test, relative to this component's left hand edge. | |||||
| @param y the y co-ordinate to test, relative to this component's top edge. | |||||
| @param x the x coordinate to test, relative to this component's left edge. | |||||
| @param y the y coordinate to test, relative to this component's top edge. | |||||
| @returns the component that is at this position - which may be 0, this component, | @returns the component that is at this position - which may be 0, this component, | ||||
| or one of its children. Note that overlapping siblings that might actually | or one of its children. Note that overlapping siblings that might actually | ||||
| be in the way are not taken into account by this method - to account for these, | be in the way are not taken into account by this method - to account for these, | ||||
| @@ -764,7 +853,7 @@ public: | |||||
| /** Returns the component at a certain point within this one. | /** Returns the component at a certain point within this one. | ||||
| @param position the co-ordinates to test, relative to this component's top-left. | |||||
| @param position the coordinate to test, relative to this component's top-left. | |||||
| @returns the component that is at this position - which may be 0, this component, | @returns the component that is at this position - which may be 0, this component, | ||||
| or one of its children. Note that overlapping siblings that might actually | or one of its children. Note that overlapping siblings that might actually | ||||
| be in the way are not taken into account by this method - to account for these, | be in the way are not taken into account by this method - to account for these, | ||||
| @@ -1613,8 +1702,7 @@ public: | |||||
| static bool JUCE_CALLTYPE isMouseButtonDownAnywhere() throw(); | static bool JUCE_CALLTYPE isMouseButtonDownAnywhere() throw(); | ||||
| /** Returns the mouse's current position, relative to this component. | /** Returns the mouse's current position, relative to this component. | ||||
| The co-ordinates are relative to the component's top-left corner. | |||||
| The return value is relative to the component's top-left corner. | |||||
| */ | */ | ||||
| const Point<int> getMouseXYRelative() const; | const Point<int> getMouseXYRelative() const; | ||||
| @@ -2033,6 +2121,7 @@ private: | |||||
| String componentName_; | String componentName_; | ||||
| Component* parentComponent_; | Component* parentComponent_; | ||||
| Rectangle<int> bounds_; | Rectangle<int> bounds_; | ||||
| ScopedPointer <AffineTransform> affineTransform_; | |||||
| Array <Component*> childComponentList_; | Array <Component*> childComponentList_; | ||||
| LookAndFeel* lookAndFeel_; | LookAndFeel* lookAndFeel_; | ||||
| MouseCursor cursor_; | MouseCursor cursor_; | ||||
| @@ -2099,6 +2188,7 @@ private: | |||||
| void internalHierarchyChanged(); | void internalHierarchyChanged(); | ||||
| void paintComponentAndChildren (Graphics& g); | void paintComponentAndChildren (Graphics& g); | ||||
| void paintComponent (Graphics& g); | void paintComponent (Graphics& g); | ||||
| void paintTransformedChild (Graphics& g); | |||||
| void sendMovedResizedMessages (bool wasMoved, bool wasResized); | void sendMovedResizedMessages (bool wasMoved, bool wasResized); | ||||
| void repaintParent(); | void repaintParent(); | ||||
| void sendFakeMouseMove() const; | void sendFakeMouseMove() const; | ||||
| @@ -127,7 +127,7 @@ int MenuBarComponent::getItemAt (const int x, const int y) | |||||
| { | { | ||||
| for (int i = 0; i < xPositions.size(); ++i) | for (int i = 0; i < xPositions.size(); ++i) | ||||
| if (x >= xPositions[i] && x < xPositions[i + 1]) | if (x >= xPositions[i] && x < xPositions[i + 1]) | ||||
| return reallyContains (x, y, true) ? i : -1; | |||||
| return reallyContains (Point<int> (x, y), true) ? i : -1; | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| @@ -522,7 +522,7 @@ public: | |||||
| // comp that we're attached to. | // comp that we're attached to. | ||||
| const Point<int> mousePos (componentAttachedTo->getMouseXYRelative()); | const Point<int> mousePos (componentAttachedTo->getMouseXYRelative()); | ||||
| if (componentAttachedTo->reallyContains (mousePos.getX(), mousePos.getY(), true)) | |||||
| if (componentAttachedTo->reallyContains (mousePos, true)) | |||||
| { | { | ||||
| postCommandMessage (PopupMenuSettings::dismissCommandId); // dismiss asynchrounously | postCommandMessage (PopupMenuSettings::dismissCommandId); // dismiss asynchrounously | ||||
| return; | return; | ||||
| @@ -567,7 +567,7 @@ public: | |||||
| const uint32 now = Time::getMillisecondCounter(); | const uint32 now = Time::getMillisecondCounter(); | ||||
| if (now > timeEnteredCurrentChildComp + 100 | if (now > timeEnteredCurrentChildComp + 100 | ||||
| && reallyContains (localMousePos.getX(), localMousePos.getY(), true) | |||||
| && reallyContains (localMousePos, true) | |||||
| && currentChild != 0 | && currentChild != 0 | ||||
| && (! disableMouseMoves) | && (! disableMouseMoves) | ||||
| && ! (activeSubMenu != 0 && activeSubMenu->isVisible())) | && ! (activeSubMenu != 0 && activeSubMenu->isVisible())) | ||||
| @@ -659,7 +659,7 @@ public: | |||||
| else if (wasDown && now > menuCreationTime + 250 | else if (wasDown && now > menuCreationTime + 250 | ||||
| && ! (isDown || overScrollArea)) | && ! (isDown || overScrollArea)) | ||||
| { | { | ||||
| isOver = reallyContains (localMousePos.getX(), localMousePos.getY(), true); | |||||
| isOver = reallyContains (localMousePos, true); | |||||
| if (isOver) | if (isOver) | ||||
| { | { | ||||
| @@ -734,7 +734,7 @@ private: | |||||
| void updateMouseOverStatus (const Point<int>& globalMousePos) | void updateMouseOverStatus (const Point<int>& globalMousePos) | ||||
| { | { | ||||
| const Point<int> relPos (getLocalPoint (0, globalMousePos)); | const Point<int> relPos (getLocalPoint (0, globalMousePos)); | ||||
| isOver = reallyContains (relPos.getX(), relPos.getY(), true); | |||||
| isOver = reallyContains (relPos, true); | |||||
| if (activeSubMenu != 0) | if (activeSubMenu != 0) | ||||
| activeSubMenu->updateMouseOverStatus (globalMousePos); | activeSubMenu->updateMouseOverStatus (globalMousePos); | ||||
| @@ -1081,7 +1081,7 @@ private: | |||||
| void highlightItemUnderMouse (const Point<int>& globalMousePos, const Point<int>& localMousePos) | void highlightItemUnderMouse (const Point<int>& globalMousePos, const Point<int>& localMousePos) | ||||
| { | { | ||||
| isOver = reallyContains (localMousePos.getX(), localMousePos.getY(), true); | |||||
| isOver = reallyContains (localMousePos, true); | |||||
| if (isOver) | if (isOver) | ||||
| hasBeenOver = true; | hasBeenOver = true; | ||||
| @@ -76,7 +76,7 @@ void MouseHoverDetector::hoverTimerCallback() | |||||
| { | { | ||||
| const Point<int> pos (source->getMouseXYRelative()); | const Point<int> pos (source->getMouseXYRelative()); | ||||
| if (source->reallyContains (pos.getX(), pos.getY(), false)) | |||||
| if (source->reallyContains (pos, false)) | |||||
| { | { | ||||
| hasJustHovered = true; | hasJustHovered = true; | ||||
| mouseHovered (pos.getX(), pos.getY()); | mouseHovered (pos.getX(), pos.getY()); | ||||
| @@ -244,7 +244,7 @@ const uint8 MidiKeyboardComponent::blackNotes[] = { 1, 3, 6, 8, 10 }; | |||||
| int MidiKeyboardComponent::xyToNote (const Point<int>& pos, float& mousePositionVelocity) | int MidiKeyboardComponent::xyToNote (const Point<int>& pos, float& mousePositionVelocity) | ||||
| { | { | ||||
| if (! reallyContains (pos.getX(), pos.getY(), false)) | |||||
| if (! reallyContains (pos, false)) | |||||
| return -1; | return -1; | ||||
| Point<int> p (pos); | Point<int> p (pos); | ||||