| @@ -1088,7 +1088,8 @@ public: | |||
| //============================================================================== | |||
| class WidgetsDemo : public Component, | |||
| public ButtonListener | |||
| public ButtonListener, | |||
| public SliderListener | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| @@ -1111,9 +1112,17 @@ public: | |||
| //============================================================================== | |||
| addAndMakeVisible (&enableButton); | |||
| enableButton.setBounds (230, 10, 180, 24); | |||
| enableButton.setTooltip ("toggle button"); | |||
| enableButton.setTooltip ("Enables/disables all the components"); | |||
| enableButton.setToggleState (true, false); | |||
| 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() | |||
| @@ -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: | |||
| TextButton menuButton; | |||
| ToggleButton enableButton; | |||
| Slider transformSlider; | |||
| DemoTabbedComponent tabs; | |||
| }; | |||
| @@ -39782,7 +39782,7 @@ END_JUCE_NAMESPACE | |||
| /*** Start of inlined file: juce_Component.cpp ***/ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #define checkMessageManagerIsLocked jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||
| #define CHECK_MESSAGE_MANAGER_IS_LOCKED jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); | |||
| Component* Component::currentlyFocusedComponent = 0; | |||
| @@ -39982,22 +39982,34 @@ public: | |||
| 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) | |||
| { | |||
| 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) | |||
| { | |||
| 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) | |||
| { | |||
| return areaInLocalSpace + comp.getPosition(); | |||
| if (comp.affineTransform_ == 0) | |||
| return areaInLocalSpace + comp.getPosition(); | |||
| return (areaInLocalSpace + comp.getPosition()).toFloat().transformed (*comp.affineTransform_).getSmallestIntegerContainer(); | |||
| } | |||
| template <typename Type> | |||
| @@ -40070,8 +40082,7 @@ public: | |||
| { | |||
| 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_)); | |||
| @@ -40195,7 +40206,7 @@ void Component::setName (const String& name) | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| if (componentName_ != name) | |||
| { | |||
| @@ -40221,7 +40232,7 @@ void Component::setVisible (bool shouldBeVisible) | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| 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 | |||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| if (isOpaque()) | |||
| styleWanted &= ~ComponentPeer::windowIsSemiTransparent; | |||
| @@ -40397,7 +40408,7 @@ void Component::removeFromDesktop() | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| 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 | |||
| // 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) | |||
| { | |||
| @@ -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 | |||
| // 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 (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) | |||
| { | |||
| if (! flags.ignoresMouseClicksFlag) | |||
| @@ -40953,15 +40999,13 @@ bool Component::contains (const Point<int>& point) | |||
| 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; | |||
| 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)); | |||
| } | |||
| @@ -40994,7 +41038,7 @@ void Component::addChildComponent (Component* const child, int zOrder) | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| 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 | |||
| // 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]; | |||
| @@ -41215,7 +41259,7 @@ void Component::enterModalState (const bool takeKeyboardFocus_, ModalComponentMa | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| // Check for an attempt to make a component modal when it already is! | |||
| // 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 | |||
| // 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) | |||
| { | |||
| @@ -41412,7 +41456,17 @@ void Component::internalRepaint (int x, int y, int w, int h) | |||
| if (parentComponent_ != 0) | |||
| { | |||
| 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) | |||
| { | |||
| @@ -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) | |||
| { | |||
| const Rectangle<int> clipBounds (g.getClipBounds()); | |||
| @@ -41476,8 +41539,7 @@ void Component::paintComponentAndChildren (Graphics& g) | |||
| if (child->flags.dontClipGraphicsFlag) | |||
| { | |||
| g.setOrigin (child->getX(), child->getY()); | |||
| child->paintEntireComponent (g, false); | |||
| child->paintTransformedChild (g); | |||
| } | |||
| else | |||
| { | |||
| @@ -41497,10 +41559,7 @@ void Component::paintComponentAndChildren (Graphics& g) | |||
| } | |||
| 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 | |||
| // 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 | |||
| // 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 | |||
| // 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) | |||
| mouseListeners_->removeListener (listenerToRemove); | |||
| @@ -42131,7 +42190,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point<int>& r | |||
| { | |||
| Desktop& desktop = Desktop::getInstance(); | |||
| flags.mouseOverFlag = reallyContains (relativePos.getX(), relativePos.getY(), false); | |||
| flags.mouseOverFlag = reallyContains (relativePos, false); | |||
| BailOutChecker checker (this); | |||
| @@ -42499,7 +42558,7 @@ void Component::grabKeyboardFocus() | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| grabFocusInternal (focusChangedDirectly); | |||
| } | |||
| @@ -42508,7 +42567,7 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext) | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| if (parentComponent_ != 0) | |||
| { | |||
| @@ -42563,20 +42622,9 @@ void Component::giveAwayFocus() | |||
| 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() | |||
| { | |||
| @@ -42590,8 +42638,7 @@ const Point<int> Component::getMouseXYRelative() 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) | |||
| @@ -43515,34 +43562,29 @@ void Button::turnOffOtherButtonsInGroup (const bool sendChangeNotification) | |||
| void Button::enablementChanged() | |||
| { | |||
| updateState (0); | |||
| updateState(); | |||
| 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()) | |||
| { | |||
| 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) | |||
| state = buttonDown; | |||
| newState = buttonDown; | |||
| else if (over) | |||
| state = buttonOver; | |||
| newState = buttonOver; | |||
| } | |||
| setState (state); | |||
| return state; | |||
| setState (newState); | |||
| return newState; | |||
| } | |||
| void Button::setState (const ButtonState newState) | |||
| @@ -43687,19 +43729,19 @@ void Button::paint (Graphics& g) | |||
| 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) | |||
| { | |||
| updateState (&e); | |||
| updateState (true, true); | |||
| if (isDown()) | |||
| { | |||
| @@ -43714,7 +43756,7 @@ void Button::mouseDown (const MouseEvent& e) | |||
| void Button::mouseUp (const MouseEvent& e) | |||
| { | |||
| const bool wasDown = isDown(); | |||
| updateState (&e); | |||
| updateState (isMouseOver(), false); | |||
| if (wasDown && isOver() && ! triggerOnMouseDown) | |||
| internalClickCallback (e.mods); | |||
| @@ -43723,7 +43765,7 @@ void Button::mouseUp (const MouseEvent& e) | |||
| void Button::mouseDrag (const MouseEvent& e) | |||
| { | |||
| const ButtonState oldState = buttonState; | |||
| updateState (&e); | |||
| updateState (isMouseOver(), true); | |||
| if (autoRepeatDelay >= 0 && buttonState != oldState && isDown()) | |||
| getRepeatTimer().startTimer (autoRepeatSpeed); | |||
| @@ -43731,13 +43773,13 @@ void Button::mouseDrag (const MouseEvent& e) | |||
| void Button::focusGained (FocusChangeType) | |||
| { | |||
| updateState (0); | |||
| updateState(); | |||
| repaint(); | |||
| } | |||
| void Button::focusLost (FocusChangeType) | |||
| { | |||
| updateState (0); | |||
| updateState(); | |||
| repaint(); | |||
| } | |||
| @@ -43750,7 +43792,7 @@ void Button::setVisible (bool shouldBeVisible) | |||
| if (! shouldBeVisible) | |||
| needsToRelease = false; | |||
| updateState (0); | |||
| updateState(); | |||
| } | |||
| else | |||
| { | |||
| @@ -43878,7 +43920,7 @@ bool Button::keyStateChanged (const bool, Component*) | |||
| if (autoRepeatDelay >= 0 && (isKeyDown && ! wasDown)) | |||
| getRepeatTimer().startTimer (autoRepeatDelay); | |||
| updateState (0); | |||
| updateState(); | |||
| if (isEnabled() && wasDown && ! isKeyDown) | |||
| { | |||
| @@ -43922,10 +43964,10 @@ void Button::repeatTimerCallback() | |||
| if (needsRepainting) | |||
| { | |||
| getRepeatTimer().stopTimer(); | |||
| updateState (0); | |||
| updateState(); | |||
| needsRepainting = false; | |||
| } | |||
| else if (autoRepeatSpeed > 0 && (isKeyDown || (updateState (0) == buttonDown))) | |||
| else if (autoRepeatSpeed > 0 && (isKeyDown || (updateState() == buttonDown))) | |||
| { | |||
| int repeatSpeed = autoRepeatSpeed; | |||
| @@ -48020,7 +48062,7 @@ void ComboBox::mouseUp (const MouseEvent& e2) | |||
| const MouseEvent e (e2.getEventRelativeTo (this)); | |||
| if (reallyContains (e.x, e.y, true) | |||
| if (reallyContains (e.getPosition(), true) | |||
| && (e2.eventComponent == this || ! label->isEditable())) | |||
| { | |||
| showPopup(); | |||
| @@ -49804,6 +49846,10 @@ void Slider::lookAndFeelChanged() | |||
| valueBox->setTooltip (getTooltip()); | |||
| } | |||
| else | |||
| { | |||
| valueBox = 0; | |||
| } | |||
| if (style == IncDecButtons) | |||
| { | |||
| @@ -51750,7 +51796,7 @@ int TableHeaderComponent::getResizeDraggerAt (const int mouseX) const | |||
| 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; | |||
| if (newCol != columnIdUnderMouse) | |||
| @@ -68454,7 +68500,7 @@ int MenuBarComponent::getItemAt (const int x, const int y) | |||
| { | |||
| for (int i = 0; i < xPositions.size(); ++i) | |||
| 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; | |||
| } | |||
| @@ -69243,7 +69289,7 @@ public: | |||
| // comp that we're attached to. | |||
| const Point<int> mousePos (componentAttachedTo->getMouseXYRelative()); | |||
| if (componentAttachedTo->reallyContains (mousePos.getX(), mousePos.getY(), true)) | |||
| if (componentAttachedTo->reallyContains (mousePos, true)) | |||
| { | |||
| postCommandMessage (PopupMenuSettings::dismissCommandId); // dismiss asynchrounously | |||
| return; | |||
| @@ -69287,7 +69333,7 @@ public: | |||
| const uint32 now = Time::getMillisecondCounter(); | |||
| if (now > timeEnteredCurrentChildComp + 100 | |||
| && reallyContains (localMousePos.getX(), localMousePos.getY(), true) | |||
| && reallyContains (localMousePos, true) | |||
| && currentChild != 0 | |||
| && (! disableMouseMoves) | |||
| && ! (activeSubMenu != 0 && activeSubMenu->isVisible())) | |||
| @@ -69379,7 +69425,7 @@ public: | |||
| else if (wasDown && now > menuCreationTime + 250 | |||
| && ! (isDown || overScrollArea)) | |||
| { | |||
| isOver = reallyContains (localMousePos.getX(), localMousePos.getY(), true); | |||
| isOver = reallyContains (localMousePos, true); | |||
| if (isOver) | |||
| { | |||
| @@ -69452,7 +69498,7 @@ private: | |||
| void updateMouseOverStatus (const Point<int>& globalMousePos) | |||
| { | |||
| const Point<int> relPos (getLocalPoint (0, globalMousePos)); | |||
| isOver = reallyContains (relPos.getX(), relPos.getY(), true); | |||
| isOver = reallyContains (relPos, true); | |||
| if (activeSubMenu != 0) | |||
| activeSubMenu->updateMouseOverStatus (globalMousePos); | |||
| @@ -69798,7 +69844,7 @@ private: | |||
| void highlightItemUnderMouse (const Point<int>& globalMousePos, const Point<int>& localMousePos) | |||
| { | |||
| isOver = reallyContains (localMousePos.getX(), localMousePos.getY(), true); | |||
| isOver = reallyContains (localMousePos, true); | |||
| if (isOver) | |||
| hasBeenOver = true; | |||
| @@ -71732,7 +71778,7 @@ void MouseHoverDetector::hoverTimerCallback() | |||
| { | |||
| const Point<int> pos (source->getMouseXYRelative()); | |||
| if (source->reallyContains (pos.getX(), pos.getY(), false)) | |||
| if (source->reallyContains (pos, false)) | |||
| { | |||
| hasJustHovered = true; | |||
| 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) | |||
| { | |||
| if (! reallyContains (pos.getX(), pos.getY(), false)) | |||
| if (! reallyContains (pos, false)) | |||
| return -1; | |||
| Point<int> p (pos); | |||
| @@ -64,7 +64,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 52 | |||
| #define JUCE_BUILDNUMBER 94 | |||
| #define JUCE_BUILDNUMBER 95 | |||
| /** Current Juce version number. | |||
| @@ -26113,15 +26113,21 @@ public: | |||
| */ | |||
| 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. | |||
| @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(); } | |||
| /** 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. | |||
| @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(); } | |||
| @@ -26131,26 +26137,38 @@ public: | |||
| /** Returns the component's height in pixels. */ | |||
| 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. | |||
| 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(); } | |||
| /** Returns the component's top-left position as a Point. */ | |||
| 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. | |||
| 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(); } | |||
| /** Returns this component's bounding box. | |||
| 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_; } | |||
| /** 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. | |||
| */ | |||
| const Rectangle<int> getLocalBounds() const throw(); | |||
| @@ -26166,12 +26184,12 @@ public: | |||
| void getVisibleArea (RectangleList& result, | |||
| 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 | |||
| */ | |||
| 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 | |||
| */ | |||
| int getScreenY() const; | |||
| @@ -26200,6 +26218,10 @@ public: | |||
| 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 | |||
| 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>& areaRelativeToSourceComponent) const; | |||
| @@ -26210,6 +26232,10 @@ public: | |||
| const Point<int> localPointToGlobal (const Point<int>& localPoint) const; | |||
| /** 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 | |||
| */ | |||
| 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(). | |||
| 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 | |||
| */ | |||
| void setTopLeftPosition (int x, int y); | |||
| @@ -26231,29 +26261,51 @@ public: | |||
| 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(). | |||
| 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); | |||
| /** Changes the size of the component. | |||
| 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); | |||
| /** 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. | |||
| 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 setTopLeftPosition, setSize, ComponentListener::componentMovedOrResized | |||
| */ | |||
| void setBounds (int x, int y, int width, int height); | |||
| /** 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 | |||
| */ | |||
| 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 | |||
| width and height of the parent, with its top-left position 20% of | |||
| the way across and down the parent. | |||
| @see setBounds | |||
| */ | |||
| void setBoundsRelative (float proportionalX, float proportionalY, | |||
| float proportionalWidth, float proportionalHeight); | |||
| @@ -26272,6 +26326,8 @@ public: | |||
| This will position the component within its parent, leaving the specified number of | |||
| pixels around each edge. | |||
| @see setBounds | |||
| */ | |||
| void setBoundsInset (const BorderSize& borders); | |||
| @@ -26286,6 +26342,8 @@ public: | |||
| It will then be positioned within the rectangle according to the justification flags | |||
| specified. | |||
| @see setBounds | |||
| */ | |||
| void setBoundsToFit (int x, int y, int width, int height, | |||
| const Justification& justification, | |||
| @@ -26295,6 +26353,8 @@ public: | |||
| Leaves the component's size unchanged, but sets the position of its centre | |||
| relative to its parent's top-left. | |||
| @see setBounds | |||
| */ | |||
| void setCentrePosition (int x, int y); | |||
| @@ -26314,6 +26374,37 @@ public: | |||
| */ | |||
| 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. | |||
| This is a handy equivalent of (getWidth() * proportion). | |||
| @@ -26340,7 +26431,7 @@ public: | |||
| */ | |||
| 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 | |||
| 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 | |||
| 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 | |||
| as contains() and getComponentAt() to work out which component | |||
| 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 | |||
| 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 | |||
| 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 | |||
| zero, and less than the component's height | |||
| @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. | |||
| @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 | |||
| that part of the component isn't clipped by its parent component. Note | |||
| that this won't take into account any overlapping sibling components | |||
| which might be in the way - for that, see reallyContains() | |||
| @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 | |||
| 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 | |||
| */ | |||
| 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. | |||
| @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, | |||
| 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, | |||
| @@ -26612,7 +26700,7 @@ public: | |||
| /** 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, | |||
| 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, | |||
| @@ -27442,8 +27530,7 @@ public: | |||
| static bool JUCE_CALLTYPE isMouseButtonDownAnywhere() throw(); | |||
| /** 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; | |||
| @@ -27849,6 +27936,7 @@ private: | |||
| String componentName_; | |||
| Component* parentComponent_; | |||
| Rectangle<int> bounds_; | |||
| ScopedPointer <AffineTransform> affineTransform_; | |||
| Array <Component*> childComponentList_; | |||
| LookAndFeel* lookAndFeel_; | |||
| MouseCursor cursor_; | |||
| @@ -27914,6 +28002,7 @@ private: | |||
| void internalHierarchyChanged(); | |||
| void paintComponentAndChildren (Graphics& g); | |||
| void paintComponent (Graphics& g); | |||
| void paintTransformedChild (Graphics& g); | |||
| void sendMovedResizedMessages (bool wasMoved, bool wasResized); | |||
| void repaintParent(); | |||
| void sendFakeMouseMove() const; | |||
| @@ -36206,7 +36295,8 @@ private: | |||
| void repeatTimerCallback(); | |||
| RepeatTimer& getRepeatTimer(); | |||
| ButtonState updateState (const MouseEvent*); | |||
| ButtonState updateState(); | |||
| ButtonState updateState (bool isOver, bool isDown); | |||
| bool isShortcutPressed() const; | |||
| void turnOffOtherButtonsInGroup (bool sendChangeNotification); | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 52 | |||
| #define JUCE_BUILDNUMBER 94 | |||
| #define JUCE_BUILDNUMBER 95 | |||
| /** Current Juce version number. | |||
| @@ -227,34 +227,29 @@ void Button::turnOffOtherButtonsInGroup (const bool sendChangeNotification) | |||
| //============================================================================== | |||
| void Button::enablementChanged() | |||
| { | |||
| updateState (0); | |||
| updateState(); | |||
| 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()) | |||
| { | |||
| 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) | |||
| state = buttonDown; | |||
| newState = buttonDown; | |||
| else if (over) | |||
| state = buttonOver; | |||
| newState = buttonOver; | |||
| } | |||
| setState (state); | |||
| return state; | |||
| setState (newState); | |||
| return 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) | |||
| { | |||
| updateState (&e); | |||
| updateState (true, true); | |||
| if (isDown()) | |||
| { | |||
| @@ -430,7 +425,7 @@ void Button::mouseDown (const MouseEvent& e) | |||
| void Button::mouseUp (const MouseEvent& e) | |||
| { | |||
| const bool wasDown = isDown(); | |||
| updateState (&e); | |||
| updateState (isMouseOver(), false); | |||
| if (wasDown && isOver() && ! triggerOnMouseDown) | |||
| internalClickCallback (e.mods); | |||
| @@ -439,7 +434,7 @@ void Button::mouseUp (const MouseEvent& e) | |||
| void Button::mouseDrag (const MouseEvent& e) | |||
| { | |||
| const ButtonState oldState = buttonState; | |||
| updateState (&e); | |||
| updateState (isMouseOver(), true); | |||
| if (autoRepeatDelay >= 0 && buttonState != oldState && isDown()) | |||
| getRepeatTimer().startTimer (autoRepeatSpeed); | |||
| @@ -447,13 +442,13 @@ void Button::mouseDrag (const MouseEvent& e) | |||
| void Button::focusGained (FocusChangeType) | |||
| { | |||
| updateState (0); | |||
| updateState(); | |||
| repaint(); | |||
| } | |||
| void Button::focusLost (FocusChangeType) | |||
| { | |||
| updateState (0); | |||
| updateState(); | |||
| repaint(); | |||
| } | |||
| @@ -467,7 +462,7 @@ void Button::setVisible (bool shouldBeVisible) | |||
| if (! shouldBeVisible) | |||
| needsToRelease = false; | |||
| updateState (0); | |||
| updateState(); | |||
| } | |||
| else | |||
| { | |||
| @@ -597,7 +592,7 @@ bool Button::keyStateChanged (const bool, Component*) | |||
| if (autoRepeatDelay >= 0 && (isKeyDown && ! wasDown)) | |||
| getRepeatTimer().startTimer (autoRepeatDelay); | |||
| updateState (0); | |||
| updateState(); | |||
| if (isEnabled() && wasDown && ! isKeyDown) | |||
| { | |||
| @@ -642,10 +637,10 @@ void Button::repeatTimerCallback() | |||
| if (needsRepainting) | |||
| { | |||
| getRepeatTimer().stopTimer(); | |||
| updateState (0); | |||
| updateState(); | |||
| needsRepainting = false; | |||
| } | |||
| else if (autoRepeatSpeed > 0 && (isKeyDown || (updateState (0) == buttonDown))) | |||
| else if (autoRepeatSpeed > 0 && (isKeyDown || (updateState() == buttonDown))) | |||
| { | |||
| int repeatSpeed = autoRepeatSpeed; | |||
| @@ -495,7 +495,8 @@ private: | |||
| void repeatTimerCallback(); | |||
| RepeatTimer& getRepeatTimer(); | |||
| ButtonState updateState (const MouseEvent*); | |||
| ButtonState updateState(); | |||
| ButtonState updateState (bool isOver, bool isDown); | |||
| bool isShortcutPressed() const; | |||
| void turnOffOtherButtonsInGroup (bool sendChangeNotification); | |||
| @@ -590,7 +590,7 @@ void ComboBox::mouseUp (const MouseEvent& e2) | |||
| const MouseEvent e (e2.getEventRelativeTo (this)); | |||
| if (reallyContains (e.x, e.y, true) | |||
| if (reallyContains (e.getPosition(), true) | |||
| && (e2.eventComponent == this || ! label->isEditable())) | |||
| { | |||
| showPopup(); | |||
| @@ -352,6 +352,10 @@ void Slider::lookAndFeelChanged() | |||
| valueBox->setTooltip (getTooltip()); | |||
| } | |||
| else | |||
| { | |||
| valueBox = 0; | |||
| } | |||
| if (style == IncDecButtons) | |||
| { | |||
| @@ -909,7 +909,7 @@ int TableHeaderComponent::getResizeDraggerAt (const int mouseX) const | |||
| 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; | |||
| 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; | |||
| @@ -249,22 +249,34 @@ public: | |||
| 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) | |||
| { | |||
| 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) | |||
| { | |||
| 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) | |||
| { | |||
| return areaInLocalSpace + comp.getPosition(); | |||
| if (comp.affineTransform_ == 0) | |||
| return areaInLocalSpace + comp.getPosition(); | |||
| return (areaInLocalSpace + comp.getPosition()).toFloat().transformed (*comp.affineTransform_).getSmallestIntegerContainer(); | |||
| } | |||
| template <typename Type> | |||
| @@ -337,8 +349,7 @@ public: | |||
| { | |||
| 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_)); | |||
| @@ -465,7 +476,7 @@ void Component::setName (const String& name) | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| if (componentName_ != name) | |||
| { | |||
| @@ -491,7 +502,7 @@ void Component::setVisible (bool shouldBeVisible) | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| 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 | |||
| // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| if (isOpaque()) | |||
| styleWanted &= ~ComponentPeer::windowIsSemiTransparent; | |||
| @@ -670,7 +681,7 @@ void Component::removeFromDesktop() | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| 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 | |||
| // 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) | |||
| { | |||
| @@ -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 | |||
| // 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 (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) | |||
| { | |||
| @@ -1233,15 +1280,13 @@ bool Component::contains (const Point<int>& point) | |||
| 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; | |||
| 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)); | |||
| } | |||
| @@ -1275,7 +1320,7 @@ void Component::addChildComponent (Component* const child, int zOrder) | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| 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 | |||
| // 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]; | |||
| @@ -1500,7 +1545,7 @@ void Component::enterModalState (const bool takeKeyboardFocus_, ModalComponentMa | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| // Check for an attempt to make a component modal when it already is! | |||
| // 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 | |||
| // 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) | |||
| { | |||
| @@ -1701,7 +1746,17 @@ void Component::internalRepaint (int x, int y, int w, int h) | |||
| if (parentComponent_ != 0) | |||
| { | |||
| 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) | |||
| { | |||
| @@ -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) | |||
| { | |||
| const Rectangle<int> clipBounds (g.getClipBounds()); | |||
| @@ -1766,8 +1830,7 @@ void Component::paintComponentAndChildren (Graphics& g) | |||
| if (child->flags.dontClipGraphicsFlag) | |||
| { | |||
| g.setOrigin (child->getX(), child->getY()); | |||
| child->paintEntireComponent (g, false); | |||
| child->paintTransformedChild (g); | |||
| } | |||
| else | |||
| { | |||
| @@ -1787,10 +1850,7 @@ void Component::paintComponentAndChildren (Graphics& g) | |||
| } | |||
| 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 | |||
| // 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 | |||
| // 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 | |||
| // 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) | |||
| mouseListeners_->removeListener (listenerToRemove); | |||
| @@ -2437,7 +2497,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point<int>& r | |||
| { | |||
| Desktop& desktop = Desktop::getInstance(); | |||
| flags.mouseOverFlag = reallyContains (relativePos.getX(), relativePos.getY(), false); | |||
| flags.mouseOverFlag = reallyContains (relativePos, false); | |||
| BailOutChecker checker (this); | |||
| @@ -2807,7 +2867,7 @@ void Component::grabKeyboardFocus() | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| grabFocusInternal (focusChangedDirectly); | |||
| } | |||
| @@ -2816,7 +2876,7 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext) | |||
| { | |||
| // 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. | |||
| checkMessageManagerIsLocked | |||
| CHECK_MESSAGE_MANAGER_IS_LOCKED | |||
| 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() | |||
| { | |||
| @@ -2900,8 +2949,7 @@ const Point<int> Component::getMouseXYRelative() 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(); | |||
| //============================================================================== | |||
| /** 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. | |||
| @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(); } | |||
| /** 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. | |||
| @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(); } | |||
| @@ -276,26 +282,38 @@ public: | |||
| /** Returns the component's height in pixels. */ | |||
| 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. | |||
| 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(); } | |||
| /** Returns the component's top-left position as a Point. */ | |||
| 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. | |||
| 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(); } | |||
| /** Returns this component's bounding box. | |||
| 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_; } | |||
| /** 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. | |||
| */ | |||
| const Rectangle<int> getLocalBounds() const throw(); | |||
| @@ -312,12 +330,12 @@ public: | |||
| 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 | |||
| */ | |||
| 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 | |||
| */ | |||
| int getScreenY() const; | |||
| @@ -346,6 +364,10 @@ public: | |||
| 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 | |||
| 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>& areaRelativeToSourceComponent) const; | |||
| @@ -356,6 +378,10 @@ public: | |||
| const Point<int> localPointToGlobal (const Point<int>& localPoint) const; | |||
| /** 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 | |||
| */ | |||
| 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(). | |||
| 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 | |||
| */ | |||
| void setTopLeftPosition (int x, int y); | |||
| @@ -378,29 +408,51 @@ public: | |||
| 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(). | |||
| 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); | |||
| /** Changes the size of the component. | |||
| 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); | |||
| /** 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. | |||
| 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 setTopLeftPosition, setSize, ComponentListener::componentMovedOrResized | |||
| */ | |||
| void setBounds (int x, int y, int width, int height); | |||
| /** 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 | |||
| */ | |||
| 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 | |||
| width and height of the parent, with its top-left position 20% of | |||
| the way across and down the parent. | |||
| @see setBounds | |||
| */ | |||
| void setBoundsRelative (float proportionalX, float proportionalY, | |||
| float proportionalWidth, float proportionalHeight); | |||
| @@ -419,6 +473,8 @@ public: | |||
| This will position the component within its parent, leaving the specified number of | |||
| pixels around each edge. | |||
| @see setBounds | |||
| */ | |||
| void setBoundsInset (const BorderSize& borders); | |||
| @@ -433,6 +489,8 @@ public: | |||
| It will then be positioned within the rectangle according to the justification flags | |||
| specified. | |||
| @see setBounds | |||
| */ | |||
| void setBoundsToFit (int x, int y, int width, int height, | |||
| const Justification& justification, | |||
| @@ -442,6 +500,8 @@ public: | |||
| Leaves the component's size unchanged, but sets the position of its centre | |||
| relative to its parent's top-left. | |||
| @see setBounds | |||
| */ | |||
| void setCentrePosition (int x, int y); | |||
| @@ -461,6 +521,38 @@ public: | |||
| */ | |||
| 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. | |||
| @@ -488,7 +580,7 @@ public: | |||
| */ | |||
| 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 | |||
| 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 | |||
| 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 | |||
| as contains() and getComponentAt() to work out which component | |||
| 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 | |||
| 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 | |||
| 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 | |||
| zero, and less than the component's height | |||
| @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. | |||
| @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 | |||
| that part of the component isn't clipped by its parent component. Note | |||
| that this won't take into account any overlapping sibling components | |||
| which might be in the way - for that, see reallyContains() | |||
| @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 | |||
| 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 | |||
| */ | |||
| 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. | |||
| @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, | |||
| 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, | |||
| @@ -764,7 +853,7 @@ public: | |||
| /** 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, | |||
| 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, | |||
| @@ -1613,8 +1702,7 @@ public: | |||
| static bool JUCE_CALLTYPE isMouseButtonDownAnywhere() throw(); | |||
| /** 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; | |||
| @@ -2033,6 +2121,7 @@ private: | |||
| String componentName_; | |||
| Component* parentComponent_; | |||
| Rectangle<int> bounds_; | |||
| ScopedPointer <AffineTransform> affineTransform_; | |||
| Array <Component*> childComponentList_; | |||
| LookAndFeel* lookAndFeel_; | |||
| MouseCursor cursor_; | |||
| @@ -2099,6 +2188,7 @@ private: | |||
| void internalHierarchyChanged(); | |||
| void paintComponentAndChildren (Graphics& g); | |||
| void paintComponent (Graphics& g); | |||
| void paintTransformedChild (Graphics& g); | |||
| void sendMovedResizedMessages (bool wasMoved, bool wasResized); | |||
| void repaintParent(); | |||
| void sendFakeMouseMove() const; | |||
| @@ -127,7 +127,7 @@ int MenuBarComponent::getItemAt (const int x, const int y) | |||
| { | |||
| for (int i = 0; i < xPositions.size(); ++i) | |||
| 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; | |||
| } | |||
| @@ -522,7 +522,7 @@ public: | |||
| // comp that we're attached to. | |||
| const Point<int> mousePos (componentAttachedTo->getMouseXYRelative()); | |||
| if (componentAttachedTo->reallyContains (mousePos.getX(), mousePos.getY(), true)) | |||
| if (componentAttachedTo->reallyContains (mousePos, true)) | |||
| { | |||
| postCommandMessage (PopupMenuSettings::dismissCommandId); // dismiss asynchrounously | |||
| return; | |||
| @@ -567,7 +567,7 @@ public: | |||
| const uint32 now = Time::getMillisecondCounter(); | |||
| if (now > timeEnteredCurrentChildComp + 100 | |||
| && reallyContains (localMousePos.getX(), localMousePos.getY(), true) | |||
| && reallyContains (localMousePos, true) | |||
| && currentChild != 0 | |||
| && (! disableMouseMoves) | |||
| && ! (activeSubMenu != 0 && activeSubMenu->isVisible())) | |||
| @@ -659,7 +659,7 @@ public: | |||
| else if (wasDown && now > menuCreationTime + 250 | |||
| && ! (isDown || overScrollArea)) | |||
| { | |||
| isOver = reallyContains (localMousePos.getX(), localMousePos.getY(), true); | |||
| isOver = reallyContains (localMousePos, true); | |||
| if (isOver) | |||
| { | |||
| @@ -734,7 +734,7 @@ private: | |||
| void updateMouseOverStatus (const Point<int>& globalMousePos) | |||
| { | |||
| const Point<int> relPos (getLocalPoint (0, globalMousePos)); | |||
| isOver = reallyContains (relPos.getX(), relPos.getY(), true); | |||
| isOver = reallyContains (relPos, true); | |||
| if (activeSubMenu != 0) | |||
| activeSubMenu->updateMouseOverStatus (globalMousePos); | |||
| @@ -1081,7 +1081,7 @@ private: | |||
| void highlightItemUnderMouse (const Point<int>& globalMousePos, const Point<int>& localMousePos) | |||
| { | |||
| isOver = reallyContains (localMousePos.getX(), localMousePos.getY(), true); | |||
| isOver = reallyContains (localMousePos, true); | |||
| if (isOver) | |||
| hasBeenOver = true; | |||
| @@ -76,7 +76,7 @@ void MouseHoverDetector::hoverTimerCallback() | |||
| { | |||
| const Point<int> pos (source->getMouseXYRelative()); | |||
| if (source->reallyContains (pos.getX(), pos.getY(), false)) | |||
| if (source->reallyContains (pos, false)) | |||
| { | |||
| hasJustHovered = true; | |||
| 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) | |||
| { | |||
| if (! reallyContains (pos.getX(), pos.getY(), false)) | |||
| if (! reallyContains (pos, false)) | |||
| return -1; | |||
| Point<int> p (pos); | |||