From 79899f87e046203c6c5c8a5b775d275adb0abcf9 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Mon, 8 Nov 2010 22:45:19 +0000 Subject: [PATCH] Fix for mouse event click counts. Fix for webkit mouse-moves. Cleaned up some Component coordinate conversion methods, adding some new ones for rectangle conversion. --- .../Source/Application/jucer_Application.h | 20 +- .../Source/demos/AudioDemoPlaybackPage.cpp | 4 +- .../Source/demos/AudioDemoRecordPage.cpp | 2 +- juce_amalgamated.cpp | 381 +++--- juce_amalgamated.h | 163 ++- .../plugins/formats/juce_VSTPluginFormat.cpp | 2 +- src/audio/processors/juce_AudioProcessor.h | 3 +- src/containers/juce_ReferenceCountedObject.h | 55 +- src/core/juce_StandardHeader.h | 2 +- src/events/juce_ListenerList.h | 34 +- src/gui/components/controls/juce_ListBox.cpp | 4 +- src/gui/components/controls/juce_Slider.cpp | 4 +- src/gui/components/controls/juce_TreeView.cpp | 2 +- src/gui/components/juce_Component.cpp | 174 ++- src/gui/components/juce_Component.h | 61 +- src/gui/components/juce_Desktop.cpp | 4 +- .../layout/juce_ComponentMovementWatcher.cpp | 2 +- .../lookandfeel/juce_LookAndFeel.cpp | 18 +- src/gui/components/menus/juce_PopupMenu.cpp | 4 +- .../mouse/juce_ComponentDragger.cpp | 4 +- .../mouse/juce_DragAndDropContainer.cpp | 12 +- src/gui/components/mouse/juce_MouseEvent.cpp | 8 +- .../mouse/juce_MouseInputSource.cpp | 42 +- .../special/juce_BubbleComponent.cpp | 4 +- .../special/juce_MagnifierComponent.cpp | 10 +- .../components/windows/juce_CallOutBox.cpp | 3 +- .../components/windows/juce_ComponentPeer.cpp | 16 +- .../components/windows/juce_ComponentPeer.h | 10 +- .../components/windows/juce_TooltipWindow.cpp | 2 +- .../windows/juce_TopLevelWindow.cpp | 12 +- src/native/linux/juce_linux_Fonts.cpp | 1144 ++++++++--------- src/native/linux/juce_linux_Windowing.cpp | 4 +- .../mac/juce_iphone_UIViewComponentPeer.mm | 10 +- src/native/mac/juce_mac_NSViewComponent.mm | 2 +- .../mac/juce_mac_NSViewComponentPeer.mm | 8 +- .../mac/juce_mac_WebBrowserComponent.mm | 8 + .../windows/juce_win32_ActiveXComponent.cpp | 5 +- src/native/windows/juce_win32_Windowing.cpp | 10 +- 38 files changed, 1282 insertions(+), 971 deletions(-) diff --git a/extras/Jucer (experimental)/Source/Application/jucer_Application.h b/extras/Jucer (experimental)/Source/Application/jucer_Application.h index 53e9fa870c..a6158ee6a0 100644 --- a/extras/Jucer (experimental)/Source/Application/jucer_Application.h +++ b/extras/Jucer (experimental)/Source/Application/jucer_Application.h @@ -33,7 +33,7 @@ //============================================================================== -class JucerApplication : public JUCEApplication +class JucerApplication : public JUCEApplication { public: //============================================================================== @@ -76,18 +76,18 @@ public: openFile (projects.getReference(i)); } -#if JUCE_MAC + #if JUCE_MAC MenuBarModel::setMacMainMenu (menuModel); -#endif + #endif main->setVisible (true); } void shutdown() { -#if JUCE_MAC + #if JUCE_MAC MenuBarModel::setMacMainMenu (0); -#endif + #endif menuModel = 0; StoredSettings::deleteInstance(); @@ -116,10 +116,10 @@ public: jassert (mainWindows.contains (w)); mainWindows.removeObject (w); -#if ! JUCE_MAC + #if ! JUCE_MAC if (mainWindows.size() == 0) systemRequestedQuit(); -#endif + #endif updateRecentProjectList(); } @@ -137,11 +137,11 @@ public: bool moreThanOneInstanceAllowed() { -#ifndef JUCE_LINUX + #ifndef JUCE_LINUX return false; -#else + #else return true; //xxx should be false but doesn't work on linux.. -#endif + #endif } void anotherInstanceStarted (const String& commandLine) diff --git a/extras/juce demo/Source/demos/AudioDemoPlaybackPage.cpp b/extras/juce demo/Source/demos/AudioDemoPlaybackPage.cpp index b23226e19b..1e57f6049c 100644 --- a/extras/juce demo/Source/demos/AudioDemoPlaybackPage.cpp +++ b/extras/juce demo/Source/demos/AudioDemoPlaybackPage.cpp @@ -105,12 +105,12 @@ public: repaint(); } - bool isInterestedInFileDrag (const StringArray& files) + bool isInterestedInFileDrag (const StringArray& /*files*/) { return true; } - void filesDropped (const StringArray& files, int x, int y) + void filesDropped (const StringArray& files, int /*x*/, int /*y*/) { AudioDemoPlaybackPage* demoPage = findParentComponentOfClass ((AudioDemoPlaybackPage*) 0); diff --git a/extras/juce demo/Source/demos/AudioDemoRecordPage.cpp b/extras/juce demo/Source/demos/AudioDemoRecordPage.cpp index ecadf7ad77..3e4b3ed1a5 100644 --- a/extras/juce demo/Source/demos/AudioDemoRecordPage.cpp +++ b/extras/juce demo/Source/demos/AudioDemoRecordPage.cpp @@ -110,7 +110,7 @@ public: sampleRate = 0; } - void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels, + void audioDeviceIOCallback (const float** inputChannelData, int /*numInputChannels*/, float** outputChannelData, int numOutputChannels, int numSamples) { diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index f07cae2ff2..e8c0fbba04 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -34077,7 +34077,7 @@ public: if (topComp->getPeer() != 0) { - const Point pos (relativePositionToOtherComponent (topComp, Point())); + const Point pos (topComp->getLocalPoint (this, Point())); recursiveResize = true; @@ -40045,8 +40045,7 @@ Component::~Component() { parentComponent_->removeChildComponent (this); } - else if ((currentlyFocusedComponent == this) - || isParentOf (currentlyFocusedComponent)) + else if (currentlyFocusedComponent == this || isParentOf (currentlyFocusedComponent)) { giveAwayFocus(); } @@ -40216,7 +40215,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo) jmax (1, getHeight())); #endif - const Point topLeft (relativePositionToGlobal (Point (0, 0))); + const Point topLeft (getScreenPosition()); bool wasFullscreen = false; bool wasMinimised = false; @@ -40555,7 +40554,7 @@ int Component::getScreenY() const const Point Component::getScreenPosition() const { - return relativePositionToGlobal (Point()); + return localPointToGlobal (Point()); } const Rectangle Component::getScreenBounds() const @@ -40563,51 +40562,116 @@ const Rectangle Component::getScreenBounds() const return bounds_.withPosition (getScreenPosition()); } +namespace CoordinateHelpers +{ + const Point convertFromParentSpace (const Component* comp, const Point& pointInParentSpace) + { + return pointInParentSpace - comp->getPosition(); + } + + const Rectangle convertFromParentSpace (const Component* comp, const Rectangle& areaInParentSpace) + { + return areaInParentSpace - comp->getPosition(); + } + + const Point convertToParentSpace (const Component* comp, const Point& pointInLocalSpace) + { + return pointInLocalSpace + comp->getPosition(); + } + + const Rectangle convertToParentSpace (const Component* comp, const Rectangle& areaInLocalSpace) + { + return areaInLocalSpace + comp->getPosition(); + } + + template + const Type convertFromDistantParentSpace (const Component* parent, const Component* target, Type coordInParent) + { + const Component* const directParent = target->getParentComponent(); + jassert (directParent != 0); + + if (directParent == parent) + return convertFromParentSpace (target, coordInParent); + + return convertFromParentSpace (target, convertFromDistantParentSpace (parent, directParent, coordInParent)); + } + + template + const Type convertCoordinate (const Component* target, const Component* source, Type p) + { + while (source != 0) + { + if (source == target) + return p; + + if (source->isParentOf (target)) + return convertFromDistantParentSpace (source, target, p); + + if (source->isOnDesktop()) + { + p = source->getPeer()->localToGlobal (p); + source = 0; + } + else + { + p = convertToParentSpace (source, p); + source = source->getParentComponent(); + } + } + + jassert (source == 0); + if (target == 0) + return p; + + const Component* const topLevelComp = target->getTopLevelComponent(); + + if (topLevelComp->isOnDesktop()) + p = topLevelComp->getPeer()->globalToLocal (p); + else + p = convertFromParentSpace (topLevelComp, p); + + if (topLevelComp == target) + return p; + + return convertFromDistantParentSpace (topLevelComp, target, p); + } +} + +const Point Component::getLocalPoint (const Component* source, const Point& point) const +{ + return CoordinateHelpers::convertCoordinate (this, source, point); +} + +const Rectangle Component::getLocalArea (const Component* source, const Rectangle& area) const +{ + return CoordinateHelpers::convertCoordinate (this, source, area); +} + +const Point Component::localPointToGlobal (const Point& point) const +{ + return CoordinateHelpers::convertCoordinate (0, this, point); +} + +const Rectangle Component::localAreaToGlobal (const Rectangle& area) const +{ + return CoordinateHelpers::convertCoordinate (0, this, area); +} + +/* Deprecated methods... */ const Point Component::relativePositionToGlobal (const Point& relativePosition) const { - return relativePositionToOtherComponent (0, relativePosition); + return localPointToGlobal (relativePosition); } const Point Component::globalPositionToRelative (const Point& screenPosition) const { - if (flags.hasHeavyweightPeerFlag) - { - return getPeer()->globalPositionToRelative (screenPosition); - } - else - { - if (parentComponent_ != 0) - return parentComponent_->globalPositionToRelative (screenPosition) - getPosition(); - - return screenPosition - getPosition(); - } + return getLocalPoint (0, screenPosition); } const Point Component::relativePositionToOtherComponent (const Component* const targetComponent, const Point& positionRelativeToThis) const { - Point p (positionRelativeToThis); - const Component* c = this; - - do - { - if (c == targetComponent) - return p; - - if (c->flags.hasHeavyweightPeerFlag) - { - p = c->getPeer()->relativePositionToGlobal (p); - break; - } - - p += c->getPosition(); - c = c->parentComponent_; - } - while (c != 0); - - if (targetComponent != 0) - p = targetComponent->globalPositionToRelative (p); - - return p; + return targetComponent == 0 ? localPointToGlobal (positionRelativeToThis) + : targetComponent->getLocalPoint (this, positionRelativeToThis); } void Component::setBounds (const int x, const int y, int w, int h) @@ -41685,7 +41749,7 @@ void Component::getVisibleArea (RectangleList& result, const bool includeSibling { const Component* const c = getTopLevelComponent(); - c->subtractObscuredRegions (result, c->relativePositionToOtherComponent (this, Point()), + c->subtractObscuredRegions (result, getLocalPoint (c, Point()), c->getLocalBounds(), this); } @@ -41896,7 +41960,7 @@ void Component::internalMouseEnter (MouseInputSource& source, const Point& { flags.mouseInsideFlag = true; flags.mouseOverFlag = true; - flags.draggingFlag = false; + flags.mouseDownFlag = false; BailOutChecker checker (this); @@ -41921,7 +41985,7 @@ void Component::internalMouseExit (MouseInputSource& source, const Point& r { BailOutChecker checker (this); - if (flags.draggingFlag) + if (flags.mouseDownFlag) { internalMouseUp (source, relativePos, time, source.getCurrentModifiers().getRawFlags()); @@ -41933,7 +41997,7 @@ void Component::internalMouseExit (MouseInputSource& source, const Point& r { flags.mouseInsideFlag = false; flags.mouseOverFlag = false; - flags.draggingFlag = false; + flags.mouseDownFlag = false; if (flags.repaintOnMouseActivityFlag) repaint(); @@ -42059,7 +42123,7 @@ void Component::internalMouseDown (MouseInputSource& source, const Point& r return; } - flags.draggingFlag = true; + flags.mouseDownFlag = true; flags.mouseOverFlag = true; if (flags.repaintOnMouseActivityFlag) @@ -42081,11 +42145,11 @@ void Component::internalMouseDown (MouseInputSource& source, const Point& r void Component::internalMouseUp (MouseInputSource& source, const Point& relativePos, const Time& time, const ModifierKeys& oldModifiers) { - if (flags.draggingFlag) + if (flags.mouseDownFlag) { Desktop& desktop = Desktop::getInstance(); - flags.draggingFlag = false; + flags.mouseDownFlag = false; BailOutChecker checker (this); @@ -42094,7 +42158,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel const MouseEvent me (source, relativePos, oldModifiers, this, this, time, - globalPositionToRelative (source.getLastMouseDownPosition()), + getLocalPoint (0, source.getLastMouseDownPosition()), source.getLastMouseDownTime(), source.getNumberOfMultipleClicks(), source.hasMouseMovedSignificantlySincePressed()); @@ -42128,7 +42192,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel void Component::internalMouseDrag (MouseInputSource& source, const Point& relativePos, const Time& time) { - if (flags.draggingFlag) + if (flags.mouseDownFlag) { Desktop& desktop = Desktop::getInstance(); @@ -42138,7 +42202,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r const MouseEvent me (source, relativePos, source.getCurrentModifiers(), this, this, time, - globalPositionToRelative (source.getLastMouseDownPosition()), + getLocalPoint (0, source.getLastMouseDownPosition()), source.getLastMouseDownTime(), source.getNumberOfMultipleClicks(), source.hasMouseMovedSignificantlySincePressed()); @@ -42161,8 +42225,7 @@ void Component::internalMouseMove (MouseInputSource& source, const Point& r BailOutChecker checker (this); const MouseEvent me (source, relativePos, source.getCurrentModifiers(), - this, this, time, relativePos, - time, 0, false); + this, this, time, relativePos, time, 0, false); if (isCurrentlyBlockedByAnotherModalComponent()) { @@ -42572,12 +42635,12 @@ bool Component::isMouseOver() const throw() bool Component::isMouseButtonDown() const throw() { - return flags.draggingFlag; + return flags.mouseDownFlag; } bool Component::isMouseOverOrDragging() const throw() { - return flags.mouseOverFlag || flags.draggingFlag; + return flags.mouseOverFlag || flags.mouseDownFlag; } bool JUCE_CALLTYPE Component::isMouseButtonDownAnywhere() throw() @@ -42587,13 +42650,13 @@ bool JUCE_CALLTYPE Component::isMouseButtonDownAnywhere() throw() const Point Component::getMouseXYRelative() const { - return globalPositionToRelative (Desktop::getMousePosition()); + return getLocalPoint (0, Desktop::getMousePosition()); } const Rectangle Component::getParentMonitorArea() const { return Desktop::getInstance() - .getMonitorAreaContaining (relativePositionToGlobal (getLocalBounds().getCentre())); + .getMonitorAreaContaining (localPointToGlobal (getLocalBounds().getCentre())); } void Component::addKeyListener (KeyListener* const newListener) @@ -42800,7 +42863,7 @@ Component* Desktop::findComponentAt (const Point& screenPosition) const if (c->isVisible()) { - const Point relative (c->globalPositionToRelative (screenPosition)); + const Point relative (c->getLocalPoint (0, screenPosition)); if (c->contains (relative.getX(), relative.getY())) return c->getComponentAt (relative.getX(), relative.getY()); @@ -42941,7 +43004,7 @@ void Desktop::sendMouseMove() if (target != 0) { Component::BailOutChecker checker (target); - const Point pos (target->globalPositionToRelative (lastFakeMouseMove)); + const Point pos (target->getLocalPoint (0, lastFakeMouseMove)); const Time now (Time::getCurrentTime()); const MouseEvent me (getMainMouseSource(), pos, ModifierKeys::getCurrentModifiers(), @@ -49341,7 +49404,7 @@ const Image ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) if (rowComp != 0 && isRowSelected (firstRow + i)) { - const Point pos (rowComp->relativePositionToOtherComponent (this, Point())); + const Point pos (getLocalPoint (rowComp, Point())); const Rectangle rowRect (pos.getX(), pos.getY(), rowComp->getWidth(), rowComp->getHeight()); imageArea = imageArea.getUnion (rowRect); } @@ -49358,7 +49421,7 @@ const Image ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) if (rowComp != 0 && isRowSelected (firstRow + i)) { - const Point pos (rowComp->relativePositionToOtherComponent (this, Point())); + const Point pos (getLocalPoint (rowComp, Point())); Graphics g (snapshot); g.setOrigin (pos.getX() - imageX, pos.getY() - imageY); @@ -50634,8 +50697,8 @@ void Slider::restoreMouseIfHidden() { const int pixelPos = (int) getLinearSliderPos (pos); - mousePos = relativePositionToGlobal (Point (isHorizontal() ? pixelPos : (getWidth() / 2), - isVertical() ? pixelPos : (getHeight() / 2))); + mousePos = localPointToGlobal (Point (isHorizontal() ? pixelPos : (getWidth() / 2), + isVertical() ? pixelPos : (getHeight() / 2))); } Desktop::setMousePosition (mousePos); @@ -56676,7 +56739,7 @@ TreeViewItem* TreeView::getItemAt (int y) const throw() { TreeViewContentComponent* const tc = static_cast (viewport->getViewedComponent()); Rectangle pos; - return tc->findItemAt (relativePositionToOtherComponent (tc, Point (0, y)).getY(), pos); + return tc->findItemAt (tc->getLocalPoint (this, Point (0, y)).getY(), pos); } TreeViewItem* TreeView::findItemFromIdentifierString (const String& identifierString) const @@ -62028,7 +62091,7 @@ void ComponentMovementWatcher::componentMovedOrResized (Component&, bool wasMove if (wasMoved) { - const Point pos (component->relativePositionToOtherComponent (component->getTopLevelComponent(), Point())); + const Point pos (component->getTopLevelComponent()->getLocalPoint (component, Point())); wasMoved = lastBounds.getPosition() != pos; lastBounds.setPosition (pos); @@ -65059,6 +65122,9 @@ namespace LookAndFeelHelpers return tl; } + + LookAndFeel* defaultLF = 0; + LookAndFeel* currentDefaultLF = 0; } LookAndFeel::LookAndFeel() @@ -65212,6 +65278,8 @@ LookAndFeel::LookAndFeel() LookAndFeel::~LookAndFeel() { + if (this == LookAndFeelHelpers::currentDefaultLF) + setDefaultLookAndFeel (0); } const Colour LookAndFeel::findColour (const int colourId) const throw() @@ -65245,21 +65313,20 @@ bool LookAndFeel::isColourSpecified (const int colourId) const throw() return colourIds.contains (colourId); } -static LookAndFeel* defaultLF = 0; -static LookAndFeel* currentDefaultLF = 0; - LookAndFeel& LookAndFeel::getDefaultLookAndFeel() throw() { // if this happens, your app hasn't initialised itself properly.. if you're // trying to hack your own main() function, have a look at // JUCEApplication::initialiseForGUI() - jassert (currentDefaultLF != 0); + jassert (LookAndFeelHelpers::currentDefaultLF != 0); - return *currentDefaultLF; + return *LookAndFeelHelpers::currentDefaultLF; } void LookAndFeel::setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel) throw() { + using namespace LookAndFeelHelpers; + if (newDefaultLookAndFeel == 0) { if (defaultLF == 0) @@ -65268,7 +65335,7 @@ void LookAndFeel::setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel) thr newDefaultLookAndFeel = defaultLF; } - currentDefaultLF = newDefaultLookAndFeel; + LookAndFeelHelpers::currentDefaultLF = newDefaultLookAndFeel; for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) { @@ -65281,6 +65348,8 @@ void LookAndFeel::setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel) thr void LookAndFeel::clearDefaultLookAndFeel() throw() { + using namespace LookAndFeelHelpers; + if (currentDefaultLF == defaultLF) currentDefaultLF = 0; @@ -69481,7 +69550,7 @@ public: // move rather than a real timer callback const Point globalMousePos (Desktop::getMousePosition()); - const Point localMousePos (globalPositionToRelative (globalMousePos)); + const Point localMousePos (getLocalPoint (0, globalMousePos)); const uint32 now = Time::getMillisecondCounter(); @@ -69649,7 +69718,7 @@ private: void updateMouseOverStatus (const Point& globalMousePos) { - const Point relPos (globalPositionToRelative (globalMousePos)); + const Point relPos (getLocalPoint (0, globalMousePos)); isOver = reallyContains (relPos.getX(), relPos.getY(), true); if (activeSubMenu != 0) @@ -70633,7 +70702,7 @@ void ComponentDragger::startDraggingComponent (Component* const componentToDrag, if (componentToDrag != 0) { constrainer = constrainer_; - originalPos = componentToDrag->relativePositionToGlobal (Point()); + originalPos = componentToDrag->localPointToGlobal (Point()); } } @@ -70648,7 +70717,7 @@ void ComponentDragger::dragComponent (Component* const componentToDrag, const Mo const Component* const parentComp = componentToDrag->getParentComponent(); if (parentComp != 0) - bounds.setPosition (parentComp->globalPositionToRelative (originalPos)); + bounds.setPosition (parentComp->getLocalPoint (0, originalPos)); bounds.setPosition (bounds.getPosition() + e.getOffsetFromDragStart()); @@ -70737,7 +70806,7 @@ public: } else { - const Point relPos (hit->globalPositionToRelative (screenPos)); + const Point relPos (hit->getLocalPoint (0, screenPos)); hit = hit->getComponentAt (relPos.getX(), relPos.getY()); } @@ -70751,7 +70820,7 @@ public: if (ddt != 0 && ddt->isInterestedInDragSource (dragDescLocal, source)) { - relativePos = hit->globalPositionToRelative (screenPos); + relativePos = hit->getLocalPoint (0, screenPos); return ddt; } @@ -70789,8 +70858,8 @@ public: } else { - const Point target (source->relativePositionToGlobal (source->getLocalBounds().getCentre())); - const Point ourCentre (relativePositionToGlobal (getLocalBounds().getCentre())); + const Point target (source->localPointToGlobal (source->getLocalBounds().getCentre())); + const Point ourCentre (localPointToGlobal (getLocalBounds().getCentre())); Desktop::getInstance().getAnimator().animateComponent (this, getBounds() + (target - ourCentre), @@ -70826,7 +70895,7 @@ public: Point newPos (screenPos + imageOffset); if (getParentComponent() != 0) - newPos = getParentComponent()->globalPositionToRelative (newPos); + newPos = getParentComponent()->getLocalPoint (0, newPos); //if (newX != getX() || newY != getY()) { @@ -70972,7 +71041,7 @@ void DragAndDropContainer::startDragging (const String& sourceDescription, const int lo = 150; const int hi = 400; - Point relPos (sourceComponent->globalPositionToRelative (lastMouseDown)); + Point relPos (sourceComponent->getLocalPoint (0, lastMouseDown)); Point clipped (dragImage.getBounds().getConstrainedPoint (relPos)); for (int y = dragImage.getHeight(); --y >= 0;) @@ -71276,9 +71345,9 @@ const MouseEvent MouseEvent::getEventRelativeTo (Component* const otherComponent return *this; } - return MouseEvent (source, eventComponent->relativePositionToOtherComponent (otherComponent, getPosition()), + return MouseEvent (source, otherComponent->getLocalPoint (eventComponent, getPosition()), mods, otherComponent, originalComponent, eventTime, - eventComponent->relativePositionToOtherComponent (otherComponent, mouseDownPos), + otherComponent->getLocalPoint (eventComponent, mouseDownPos), mouseDownTime, numberOfClicks, wasMovedSinceMouseDown); } @@ -71354,7 +71423,7 @@ int MouseEvent::getScreenY() const const Point MouseEvent::getScreenPosition() const { - return eventComponent->relativePositionToGlobal (Point (x, y)); + return eventComponent->localPointToGlobal (Point (x, y)); } int MouseEvent::getMouseDownScreenX() const @@ -71369,7 +71438,7 @@ int MouseEvent::getMouseDownScreenY() const const Point MouseEvent::getMouseDownScreenPosition() const { - return eventComponent->relativePositionToGlobal (mouseDownPos); + return eventComponent->localPointToGlobal (mouseDownPos); } int MouseEvent::doubleClickTimeOutMs = 400; @@ -71400,7 +71469,6 @@ public: isUnboundedMouseModeOn (false), isCursorVisibleUntilOffscreen (false), currentCursorHandle (0), mouseEventCounter (0), lastTime (0) { - zerostruct (mouseDowns); } ~MouseInputSourceInternal() @@ -71437,7 +71505,7 @@ public: if (peer != 0) { Component* const comp = peer->getComponent(); - const Point relativePos (comp->globalPositionToRelative (screenPos)); + const Point relativePos (comp->getLocalPoint (0, screenPos)); // (the contains() call is needed to test for overlapping desktop windows) if (comp->contains (relativePos.getX(), relativePos.getY())) @@ -71454,44 +71522,44 @@ public: void sendMouseEnter (Component* const comp, const Point& screenPos, const int64 time) { - //DBG ("Mouse " + String (source.getIndex()) + " enter: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseEnter (source, comp->globalPositionToRelative (screenPos), time); + //DBG ("Mouse " + String (source.getIndex()) + " enter: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseEnter (source, comp->getLocalPoint (0, screenPos), time); } void sendMouseExit (Component* const comp, const Point& screenPos, const int64 time) { - //DBG ("Mouse " + String (source.getIndex()) + " exit: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseExit (source, comp->globalPositionToRelative (screenPos), time); + //DBG ("Mouse " + String (source.getIndex()) + " exit: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseExit (source, comp->getLocalPoint (0, screenPos), time); } void sendMouseMove (Component* const comp, const Point& screenPos, const int64 time) { - //DBG ("Mouse " + String (source.getIndex()) + " move: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseMove (source, comp->globalPositionToRelative (screenPos), time); + //DBG ("Mouse " + String (source.getIndex()) + " move: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseMove (source, comp->getLocalPoint (0, screenPos), time); } void sendMouseDown (Component* const comp, const Point& screenPos, const int64 time) { - //DBG ("Mouse " + String (source.getIndex()) + " down: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseDown (source, comp->globalPositionToRelative (screenPos), time); + //DBG ("Mouse " + String (source.getIndex()) + " down: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseDown (source, comp->getLocalPoint (0, screenPos), time); } void sendMouseDrag (Component* const comp, const Point& screenPos, const int64 time) { - //DBG ("Mouse " + String (source.getIndex()) + " drag: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseDrag (source, comp->globalPositionToRelative (screenPos), time); + //DBG ("Mouse " + String (source.getIndex()) + " drag: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseDrag (source, comp->getLocalPoint (0, screenPos), time); } void sendMouseUp (Component* const comp, const Point& screenPos, const int64 time) { - //DBG ("Mouse " + String (source.getIndex()) + " up: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseUp (source, comp->globalPositionToRelative (screenPos), time, getCurrentModifiers()); + //DBG ("Mouse " + String (source.getIndex()) + " up: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseUp (source, comp->getLocalPoint (0, screenPos), time, getCurrentModifiers()); } void sendMouseWheel (Component* const comp, const Point& screenPos, const int64 time, float x, float y) { - //DBG ("Mouse " + String (source.getIndex()) + " wheel: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseWheel (source, comp->globalPositionToRelative (screenPos), time, x, y); + //DBG ("Mouse " + String (source.getIndex()) + " wheel: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseWheel (source, comp->getLocalPoint (0, screenPos), time, x, y); } // (returns true if the button change caused a modal event loop) @@ -71615,7 +71683,7 @@ public: jassert (newPeer != 0); lastTime = time; ++mouseEventCounter; - const Point screenPos (newPeer->relativePositionToGlobal (positionWithinPeer)); + const Point screenPos (newPeer->localToGlobal (positionWithinPeer)); if (isDragging() && newMods.isAnyMouseButtonDown()) { @@ -71643,7 +71711,7 @@ public: jassert (peer != 0); lastTime = time; ++mouseEventCounter; - const Point screenPos (peer->relativePositionToGlobal (positionWithinPeer)); + const Point screenPos (peer->localToGlobal (positionWithinPeer)); setPeer (peer, screenPos, time); setScreenPos (screenPos, time, false); @@ -71678,7 +71746,7 @@ public: for (int i = 1; i < numElementsInArray (mouseDowns); ++i) { - if (mouseDowns[0].canBePartOfMultipleClickWith (mouseDowns[1], (int) (MouseEvent::getDoubleClickTimeout() * (1.0 + 0.25 * (i - 1))))) + if (mouseDowns[0].canBePartOfMultipleClickWith (mouseDowns[i], (int) (MouseEvent::getDoubleClickTimeout() * (1.0 + 0.25 * (i - 1))))) ++numClicks; else break; @@ -71794,6 +71862,11 @@ private: struct RecentMouseDown { + RecentMouseDown() + : time (0), component (0) + { + } + Point position; int64 time; Component* component; @@ -74035,9 +74108,9 @@ void BubbleComponent::setPosition (Component* componentToPointTo) Point pos; if (getParentComponent() != 0) - pos = componentToPointTo->relativePositionToOtherComponent (getParentComponent(), pos); + pos = getParentComponent()->getLocalPoint (componentToPointTo, pos); else - pos = componentToPointTo->relativePositionToGlobal (pos); + pos = componentToPointTo->localPointToGlobal (pos); setPosition (Rectangle (pos.getX(), pos.getY(), componentToPointTo->getWidth(), componentToPointTo->getHeight())); } @@ -75173,16 +75246,16 @@ public: return magnifierComp->getScreenPosition(); } - const Point relativePositionToGlobal (const Point& relativePosition) + const Point localToGlobal (const Point& relativePosition) { const double zoom = magnifierComp->getScaleFactor(); - return magnifierComp->relativePositionToGlobal (Point (roundToInt (relativePosition.getX() * zoom), - roundToInt (relativePosition.getY() * zoom))); + return magnifierComp->localPointToGlobal (Point (roundToInt (relativePosition.getX() * zoom), + roundToInt (relativePosition.getY() * zoom))); } - const Point globalPositionToRelative (const Point& screenPosition) + const Point globalToLocal (const Point& screenPosition) { - const Point p (magnifierComp->globalPositionToRelative (screenPosition)); + const Point p (magnifierComp->getLocalPoint (0, screenPosition)); const double zoom = magnifierComp->getScaleFactor(); return Point (roundToInt (p.getX() / zoom), @@ -77376,8 +77449,7 @@ CallOutBox::CallOutBox (Component& contentComponent, { parentComponent->addChildComponent (this); - updatePosition (componentToPointTo.getLocalBounds() - + componentToPointTo.relativePositionToOtherComponent (parentComponent, Point()), + updatePosition (parentComponent->getLocalArea (&componentToPointTo, componentToPointTo.getLocalBounds()), parentComponent->getLocalBounds()); setVisible (true); @@ -77953,6 +78025,16 @@ const Rectangle& ComponentPeer::getNonFullScreenBounds() const throw() return lastNonFullscreenBounds; } +const Rectangle ComponentPeer::localToGlobal (const Rectangle& relativePosition) +{ + return relativePosition.withPosition (localToGlobal (relativePosition.getPosition())); +} + +const Rectangle ComponentPeer::globalToLocal (const Rectangle& screenPosition) +{ + return screenPosition.withPosition (globalToLocal (screenPosition.getPosition())); +} + namespace ComponentPeerHelpers { FileDragAndDropTarget* findDragAndDropTarget (Component* c, @@ -77999,7 +78081,7 @@ void ComponentPeer::handleFileDragMove (const StringArray& files, const Point (newTarget); - const Point pos (component->relativePositionToOtherComponent (dragAndDropTargetComponent, position)); + const Point pos (dragAndDropTargetComponent->getLocalPoint (component, position)); newTarget->fileDragEnter (files, pos.getX(), pos.getY()); } } @@ -78012,7 +78094,7 @@ void ComponentPeer::handleFileDragMove (const StringArray& files, const Point (newTarget); - const Point pos (component->relativePositionToOtherComponent (targetComp, position)); + const Point pos (targetComp->getLocalPoint (component, position)); newTarget->fileDragMove (files, pos.getX(), pos.getY()); } @@ -78050,7 +78132,7 @@ void ComponentPeer::handleFileDragDrop (const StringArray& files, const Point pos (component->relativePositionToOtherComponent (targetComp, position)); + const Point pos (targetComp->getLocalPoint (component, position)); target->filesDropped (files, pos.getX(), pos.getY()); } } @@ -79270,7 +79352,7 @@ void TooltipWindow::showFor (const String& tip) Point mousePos (Desktop::getMousePosition()); if (getParentComponent() != 0) - mousePos = getParentComponent()->globalPositionToRelative (mousePos); + mousePos = getParentComponent()->getLocalPoint (0, mousePos); int x, y, w, h; getLookAndFeel().getTooltipSize (tip, w, h); @@ -79629,21 +79711,19 @@ void TopLevelWindow::centreAroundComponent (Component* c, const int width, const } else { - Point p (c->relativePositionToGlobal (Point ((c->getWidth() - width) / 2, - (c->getHeight() - height) / 2))); - + Point targetCentre (c->localPointToGlobal (c->getLocalBounds().getCentre())); Rectangle parentArea (c->getParentMonitorArea()); if (getParentComponent() != 0) { - p = getParentComponent()->globalPositionToRelative (p); - parentArea.setBounds (0, 0, getParentWidth(), getParentHeight()); + targetCentre = getParentComponent()->getLocalPoint (0, targetCentre); + parentArea = getParentComponent()->getLocalBounds(); } parentArea.reduce (12, 12); - setBounds (jlimit (parentArea.getX(), jmax (parentArea.getX(), parentArea.getRight() - width), p.getX()), - jlimit (parentArea.getY(), jmax (parentArea.getY(), parentArea.getBottom() - height), p.getY()), + setBounds (jlimit (parentArea.getX(), jmax (parentArea.getX(), parentArea.getRight() - width), targetCentre.getX() - width / 2), + jlimit (parentArea.getY(), jmax (parentArea.getY(), parentArea.getBottom() - height), targetCentre.getY() - height / 2), width, height); } } @@ -242097,12 +242177,12 @@ public: r.top + windowBorder.getTop()); } - const Point relativePositionToGlobal (const Point& relativePosition) + const Point localToGlobal (const Point& relativePosition) { return relativePosition + getScreenPosition(); } - const Point globalPositionToRelative (const Point& screenPosition) + const Point globalToLocal (const Point& screenPosition) { return screenPosition - getScreenPosition(); } @@ -243179,7 +243259,7 @@ private: HRESULT __stdcall DragEnter (IDataObject* pDataObject, DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) { updateFileList (pDataObject); - owner->handleFileDragMove (files, owner->globalPositionToRelative (Point (mousePos.x, mousePos.y))); + owner->handleFileDragMove (files, owner->globalToLocal (Point (mousePos.x, mousePos.y))); *pdwEffect = DROPEFFECT_COPY; return S_OK; } @@ -243192,7 +243272,7 @@ private: HRESULT __stdcall DragOver (DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) { - owner->handleFileDragMove (files, owner->globalPositionToRelative (Point (mousePos.x, mousePos.y))); + owner->handleFileDragMove (files, owner->globalToLocal (Point (mousePos.x, mousePos.y))); *pdwEffect = DROPEFFECT_COPY; return S_OK; } @@ -243200,7 +243280,7 @@ private: HRESULT __stdcall Drop (IDataObject* pDataObject, DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) { updateFileList (pDataObject); - owner->handleFileDragDrop (files, owner->globalPositionToRelative (Point (mousePos.x, mousePos.y))); + owner->handleFileDragDrop (files, owner->globalToLocal (Point (mousePos.x, mousePos.y))); *pdwEffect = DROPEFFECT_COPY; return S_OK; } @@ -244927,8 +245007,7 @@ public: if (topComp->getPeer() != 0) { - const Point pos (owner.relativePositionToOtherComponent (topComp, Point())); - + const Point pos (topComp->getLocalPoint (&owner, Point())); owner.setControlBounds (Rectangle (pos.getX(), pos.getY(), owner.getWidth(), owner.getHeight())); } } @@ -245027,7 +245106,7 @@ bool ActiveXControlComponent::createControl (const void* controlIID) if (dynamic_cast (peer) != 0) { - const Point pos (relativePositionToOtherComponent (getTopLevelComponent(), Point())); + const Point pos (getTopLevelComponent()->getLocalPoint (this, Point())); HWND hwnd = (HWND) peer->getNativeHandle(); ScopedPointer newControl (new Pimpl (hwnd, *this)); @@ -258534,12 +258613,12 @@ public: const Rectangle getBounds() const { return Rectangle (wx, wy, ww, wh); } const Point getScreenPosition() const { return Point (wx, wy); } - const Point relativePositionToGlobal (const Point& relativePosition) + const Point localToGlobal (const Point& relativePosition) { return relativePosition + getScreenPosition(); } - const Point globalPositionToRelative (const Point& screenPosition) + const Point globalToLocal (const Point& screenPosition) { return screenPosition - getScreenPosition(); } @@ -267493,8 +267572,8 @@ public: const Rectangle getBounds() const; const Rectangle getBounds (const bool global) const; const Point getScreenPosition() const; - const Point relativePositionToGlobal (const Point& relativePosition); - const Point globalPositionToRelative (const Point& screenPosition); + const Point localToGlobal (const Point& relativePosition); + const Point globalToLocal (const Point& screenPosition); void setAlpha (float newAlpha); void setMinimised (bool shouldBeMinimised); bool isMinimised() const; @@ -267910,12 +267989,12 @@ const Point UIViewComponentPeer::getScreenPosition() const return getBounds (true).getPosition(); } -const Point UIViewComponentPeer::relativePositionToGlobal (const Point& relativePosition) +const Point UIViewComponentPeer::localToGlobal (const Point& relativePosition) { return relativePosition + getScreenPosition(); } -const Point UIViewComponentPeer::globalPositionToRelative (const Point& screenPosition) +const Point UIViewComponentPeer::globalToLocal (const Point& screenPosition) { return screenPosition - getScreenPosition(); } @@ -268232,7 +268311,7 @@ void UIViewComponentPeer::globalFocusChanged (Component*) { Component* comp = dynamic_cast (target); - Point pos (comp->relativePositionToOtherComponent (component, Point())); + Point pos (component->getLocalPoint (comp, Point())); view->hiddenTextView.frame = CGRectMake (pos.getX(), pos.getY(), 0, 0); updateHiddenTextContent (target); @@ -269535,6 +269614,14 @@ public: [webView reload: nil]; } + void mouseMove (const MouseEvent&) + { + // WebKit doesn't capture mouse-moves itself, so it seems the only way to make + // them work is to push them via this non-public method.. + if ([webView respondsToSelector: @selector (_updateMouseoverWithFakeEvent)]) + [webView performSelector: @selector (_updateMouseoverWithFakeEvent)]; + } + private: WebView* webView; DownloadClickDetector* clickListener; @@ -272270,8 +272357,8 @@ public: const Rectangle getBounds (const bool global) const; const Rectangle getBounds() const; const Point getScreenPosition() const; - const Point relativePositionToGlobal (const Point& relativePosition); - const Point globalPositionToRelative (const Point& screenPosition); + const Point localToGlobal (const Point& relativePosition); + const Point globalToLocal (const Point& screenPosition); void setAlpha (float newAlpha); void setMinimised (bool shouldBeMinimised); bool isMinimised() const; @@ -273145,12 +273232,12 @@ const Point NSViewComponentPeer::getScreenPosition() const return getBounds (true).getPosition(); } -const Point NSViewComponentPeer::relativePositionToGlobal (const Point& relativePosition) +const Point NSViewComponentPeer::localToGlobal (const Point& relativePosition) { return relativePosition + getScreenPosition(); } -const Point NSViewComponentPeer::globalPositionToRelative (const Point& screenPosition) +const Point NSViewComponentPeer::globalToLocal (const Point& screenPosition) { return screenPosition - getScreenPosition(); } @@ -274050,7 +274137,7 @@ public: if (topComp->getPeer() != 0) { - const Point pos (owner->relativePositionToOtherComponent (topComp, Point())); + const Point pos (topComp->getLocalPoint (owner, Point())); NSRect r = NSMakeRect ((float) pos.getX(), (float) pos.getY(), (float) owner->getWidth(), (float) owner->getHeight()); r.origin.y = [[view superview] frame].size.height - (r.origin.y + r.size.height); @@ -277330,6 +277417,14 @@ public: [webView reload: nil]; } + void mouseMove (const MouseEvent&) + { + // WebKit doesn't capture mouse-moves itself, so it seems the only way to make + // them work is to push them via this non-public method.. + if ([webView respondsToSelector: @selector (_updateMouseoverWithFakeEvent)]) + [webView performSelector: @selector (_updateMouseoverWithFakeEvent)]; + } + private: WebView* webView; DownloadClickDetector* clickListener; diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 48da2fb7ae..500f456f69 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -64,7 +64,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 87 +#define JUCE_BUILDNUMBER 88 /** Current Juce version number. @@ -6468,18 +6468,6 @@ public: return referencedObject; } - /** Returns true if this pointer refers to the given object. */ - inline bool operator== (ReferenceCountedObjectClass* const object) const throw() - { - return referencedObject == object; - } - - /** Returns true if this pointer doesn't refer to the given object. */ - inline bool operator!= (ReferenceCountedObjectClass* const object) const throw() - { - return referencedObject != object; - } - // the -> operator is called on the referenced object inline ReferenceCountedObjectClass* operator->() const throw() { @@ -6499,6 +6487,48 @@ private: ReferenceCountedObjectClass* referencedObject; }; +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator== (const ReferenceCountedObjectPtr& object1, ReferenceCountedObjectClass* const object2) throw() +{ + return object1.getObject() == object2; +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator== (const ReferenceCountedObjectPtr& object1, const ReferenceCountedObjectPtr& object2) throw() +{ + return object1.getObject() == object2.getObject(); +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator== (ReferenceCountedObjectClass* object1, ReferenceCountedObjectPtr& object2) throw() +{ + return object1 == object2.getObject(); +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator!= (const ReferenceCountedObjectPtr& object1, const ReferenceCountedObjectClass* object2) throw() +{ + return object1.getObject() != object2; +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator!= (const ReferenceCountedObjectPtr& object1, ReferenceCountedObjectPtr& object2) throw() +{ + return object1.getObject() != object2.getObject(); +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator!= (ReferenceCountedObjectClass* object1, ReferenceCountedObjectPtr& object2) throw() +{ + return object1 != object2.getObject(); +} + #endif // __JUCE_REFERENCECOUNTEDOBJECT_JUCEHEADER__ /*** End of inlined file: juce_ReferenceCountedObject.h ***/ @@ -12545,7 +12575,7 @@ public: void callChecked (const BailOutCheckerType& bailOutChecker, void (ListenerClass::*callbackFunction) ()) { - for (Iterator iter (*this, bailOutChecker); iter.next();) + for (Iterator iter (*this); iter.next (bailOutChecker);) (iter.getListener()->*callbackFunction) (); } @@ -12553,7 +12583,7 @@ public: template void call (void (ListenerClass::*callbackFunction) (P1), LL_PARAM(1)) { - for (Iterator iter (*this, DummyBailOutChecker()); iter.next();) + for (Iterator iter (*this); iter.next();) (iter.getListener()->*callbackFunction) (param1); } @@ -12564,7 +12594,7 @@ public: void (ListenerClass::*callbackFunction) (P1), LL_PARAM(1)) { - for (Iterator iter (*this, bailOutChecker); iter.next();) + for (Iterator iter (*this); iter.next (bailOutChecker);) (iter.getListener()->*callbackFunction) (param1); } @@ -12573,7 +12603,7 @@ public: void call (void (ListenerClass::*callbackFunction) (P1, P2), LL_PARAM(1), LL_PARAM(2)) { - for (Iterator iter (*this, DummyBailOutChecker()); iter.next();) + for (Iterator iter (*this); iter.next();) (iter.getListener()->*callbackFunction) (param1, param2); } @@ -12584,7 +12614,7 @@ public: void (ListenerClass::*callbackFunction) (P1, P2), LL_PARAM(1), LL_PARAM(2)) { - for (Iterator iter (*this, bailOutChecker); iter.next();) + for (Iterator iter (*this); iter.next (bailOutChecker);) (iter.getListener()->*callbackFunction) (param1, param2); } @@ -12593,7 +12623,7 @@ public: void call (void (ListenerClass::*callbackFunction) (P1, P2, P3), LL_PARAM(1), LL_PARAM(2), LL_PARAM(3)) { - for (Iterator iter (*this, DummyBailOutChecker()); iter.next();) + for (Iterator iter (*this); iter.next();) (iter.getListener()->*callbackFunction) (param1, param2, param3); } @@ -12604,7 +12634,7 @@ public: void (ListenerClass::*callbackFunction) (P1, P2, P3), LL_PARAM(1), LL_PARAM(2), LL_PARAM(3)) { - for (Iterator iter (*this, bailOutChecker); iter.next();) + for (Iterator iter (*this); iter.next (bailOutChecker);) (iter.getListener()->*callbackFunction) (param1, param2, param3); } @@ -12613,7 +12643,7 @@ public: void call (void (ListenerClass::*callbackFunction) (P1, P2, P3, P4), LL_PARAM(1), LL_PARAM(2), LL_PARAM(3), LL_PARAM(4)) { - for (Iterator iter (*this, DummyBailOutChecker()); iter.next();) + for (Iterator iter (*this); iter.next();) (iter.getListener()->*callbackFunction) (param1, param2, param3, param4); } @@ -12624,7 +12654,7 @@ public: void (ListenerClass::*callbackFunction) (P1, P2, P3, P4), LL_PARAM(1), LL_PARAM(2), LL_PARAM(3), LL_PARAM(4)) { - for (Iterator iter (*this, bailOutChecker); iter.next();) + for (Iterator iter (*this); iter.next (bailOutChecker);) (iter.getListener()->*callbackFunction) (param1, param2, param3, param4); } @@ -12633,7 +12663,7 @@ public: void call (void (ListenerClass::*callbackFunction) (P1, P2, P3, P4, P5), LL_PARAM(1), LL_PARAM(2), LL_PARAM(3), LL_PARAM(4), LL_PARAM(5)) { - for (Iterator iter (*this, DummyBailOutChecker()); iter.next();) + for (Iterator iter (*this); iter.next();) (iter.getListener()->*callbackFunction) (param1, param2, param3, param4, param5); } @@ -12644,7 +12674,7 @@ public: void (ListenerClass::*callbackFunction) (P1, P2, P3, P4, P5), LL_PARAM(1), LL_PARAM(2), LL_PARAM(3), LL_PARAM(4), LL_PARAM(5)) { - for (Iterator iter (*this, bailOutChecker); iter.next();) + for (Iterator iter (*this); iter.next (bailOutChecker);) (iter.getListener()->*callbackFunction) (param1, param2, param3, param4, param5); } @@ -12663,15 +12693,15 @@ public: { public: - Iterator (const ListType& list_, const BailOutCheckerType& bailOutChecker_) - : list (list_), bailOutChecker (bailOutChecker_), index (list_.size()) + Iterator (const ListType& list_) + : list (list_), index (list_.size()) {} ~Iterator() {} bool next() { - if (index <= 0 || bailOutChecker.shouldBailOut()) + if (index <= 0) return false; const int listSize = list.size(); @@ -12683,6 +12713,11 @@ public: return index >= 0; } + bool next (const BailOutCheckerType& bailOutChecker) + { + return (! bailOutChecker.shouldBailOut()) && next(); + } + typename ListType::ListenerType* getListener() const throw() { return list.getListeners().getUnchecked (index); @@ -12690,7 +12725,6 @@ public: private: const ListType& list; - const BailOutCheckerType& bailOutChecker; int index; Iterator (const Iterator&); @@ -26044,7 +26078,7 @@ public: /** Destructor. - Note that when a component is deleted, any child components it contain are NOT + Note that when a component is deleted, any child components it contains are NOT automatically deleted. It's your responsibilty to manage their lifespan - you may want to use helper methods like deleteAllChildren(), or less haphazard approaches like using ScopedPointers or normal object aggregation to manage them. @@ -26278,12 +26312,12 @@ public: bool includeSiblings) const; /** Returns this component's x co-ordinate relative the the screen's top-left origin. - @see getX, relativePositionToGlobal + @see getX, localPointToGlobal */ int getScreenX() const; /** Returns this component's y co-ordinate relative the the screen's top-left origin. - @see getY, relativePositionToGlobal + @see getY, localPointToGlobal */ int getScreenY() const; @@ -26297,24 +26331,33 @@ public: */ const Rectangle getScreenBounds() const; - /** Converts a position relative to this component's top-left into a screen co-ordinate. - @see globalPositionToRelative, relativePositionToOtherComponent - */ - const Point relativePositionToGlobal (const Point& relativePosition) const; + /** Converts a point to be relative to this component's coordinate space. - /** Converts a screen co-ordinate into a position relative to this component's top-left. - @see relativePositionToGlobal, relativePositionToOtherComponent + This takes a point relative to a different component, and returns its position relative to this + component. If the sourceComponent parameter is null, the source point is assumed to be a global + screen coordinate. */ - const Point globalPositionToRelative (const Point& screenPosition) const; + const Point getLocalPoint (const Component* sourceComponent, + const Point& pointRelativeToSourceComponent) const; - /** Converts a position relative to this component's top-left into a position - relative to another component's top-left. - If the targetComponent parameter is null, the coordinate is converted to global screen - coordinates. - @see relativePositionToGlobal, globalPositionToRelative + /** Converts a rectangle to be relative to this component's coordinate space. + + 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. */ - const Point relativePositionToOtherComponent (const Component* targetComponent, - const Point& positionRelativeToThis) const; + const Rectangle getLocalArea (const Component* sourceComponent, + const Rectangle& areaRelativeToSourceComponent) const; + + /** Converts a point relative to this component's top-left into a screen coordinate. + @see getLocalPoint, localAreaToGlobal + */ + const Point localPointToGlobal (const Point& localPoint) const; + + /** Converts a rectangle from this component's coordinate space to a screen coordinate. + @see getLocalPoint, localPointToGlobal + */ + const Rectangle localAreaToGlobal (const Rectangle& localArea) const; /** Moves the component to a new position. @@ -27910,6 +27953,21 @@ public: BailOutChecker& operator= (const BailOutChecker&); }; + #ifndef DOXYGEN + /** @internal + This method is deprecated - use localPointToGlobal instead. */ + const Point relativePositionToGlobal (const Point& relativePosition) const; + + /** @internal + This method is deprecated - use getLocalPoint instead. */ + const Point globalPositionToRelative (const Point& screenPosition) const; + + /** @internal + This method is deprecated - use getLocalPoint instead. */ + const Point relativePositionToOtherComponent (const Component* targetComponent, + const Point& positionRelativeToThis) const; + #endif + juce_UseDebuggingNewOperator private: @@ -27952,7 +28010,7 @@ private: bool bufferToImageFlag : 1; bool bringToFrontOnClickFlag : 1; bool repaintOnMouseActivityFlag : 1; - bool draggingFlag : 1; + bool mouseDownFlag : 1; bool mouseOverFlag : 1; bool mouseInsideFlag : 1; bool currentlyModalFlag : 1; @@ -40361,8 +40419,7 @@ protected: This might return 0 if the data's unsuitable or corrupted. Otherwise it will return an XmlElement object that the caller must delete when no longer needed. */ - static XmlElement* getXmlFromBinary (const void* data, - int sizeInBytes); + static XmlElement* getXmlFromBinary (const void* data, int sizeInBytes); /** @internal */ AudioPlayHead* playHead; @@ -59103,10 +59160,16 @@ public: virtual const Point getScreenPosition() const = 0; /** Converts a position relative to the top-left of this component to screen co-ordinates. */ - virtual const Point relativePositionToGlobal (const Point& relativePosition) = 0; + virtual const Point localToGlobal (const Point& relativePosition) = 0; + + /** Converts a rectangle relative to the top-left of this component to screen co-ordinates. */ + virtual const Rectangle localToGlobal (const Rectangle& relativePosition); /** Converts a screen co-ordinate to a position relative to the top-left of this component. */ - virtual const Point globalPositionToRelative (const Point& screenPosition) = 0; + virtual const Point globalToLocal (const Point& screenPosition) = 0; + + /** Converts a screen area to a position relative to the top-left of this component. */ + virtual const Rectangle globalToLocal (const Rectangle& screenPosition); /** Minimises the window. */ virtual void setMinimised (bool shouldBeMinimised) = 0; diff --git a/src/audio/plugins/formats/juce_VSTPluginFormat.cpp b/src/audio/plugins/formats/juce_VSTPluginFormat.cpp index 40369ed9ea..1e3c78b176 100644 --- a/src/audio/plugins/formats/juce_VSTPluginFormat.cpp +++ b/src/audio/plugins/formats/juce_VSTPluginFormat.cpp @@ -1198,7 +1198,7 @@ public: if (topComp->getPeer() != 0) { - const Point pos (relativePositionToOtherComponent (topComp, Point())); + const Point pos (topComp->getLocalPoint (this, Point())); recursiveResize = true; diff --git a/src/audio/processors/juce_AudioProcessor.h b/src/audio/processors/juce_AudioProcessor.h index bb79a994a0..e258ef6404 100644 --- a/src/audio/processors/juce_AudioProcessor.h +++ b/src/audio/processors/juce_AudioProcessor.h @@ -573,8 +573,7 @@ protected: This might return 0 if the data's unsuitable or corrupted. Otherwise it will return an XmlElement object that the caller must delete when no longer needed. */ - static XmlElement* getXmlFromBinary (const void* data, - int sizeInBytes); + static XmlElement* getXmlFromBinary (const void* data, int sizeInBytes); /** @internal */ AudioPlayHead* playHead; diff --git a/src/containers/juce_ReferenceCountedObject.h b/src/containers/juce_ReferenceCountedObject.h index bf423b8dc2..915020f779 100644 --- a/src/containers/juce_ReferenceCountedObject.h +++ b/src/containers/juce_ReferenceCountedObject.h @@ -220,18 +220,6 @@ public: return referencedObject; } - /** Returns true if this pointer refers to the given object. */ - inline bool operator== (ReferenceCountedObjectClass* const object) const throw() - { - return referencedObject == object; - } - - /** Returns true if this pointer doesn't refer to the given object. */ - inline bool operator!= (ReferenceCountedObjectClass* const object) const throw() - { - return referencedObject != object; - } - // the -> operator is called on the referenced object inline ReferenceCountedObjectClass* operator->() const throw() { @@ -252,4 +240,47 @@ private: }; +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator== (const ReferenceCountedObjectPtr& object1, ReferenceCountedObjectClass* const object2) throw() +{ + return object1.getObject() == object2; +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator== (const ReferenceCountedObjectPtr& object1, const ReferenceCountedObjectPtr& object2) throw() +{ + return object1.getObject() == object2.getObject(); +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator== (ReferenceCountedObjectClass* object1, ReferenceCountedObjectPtr& object2) throw() +{ + return object1 == object2.getObject(); +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator!= (const ReferenceCountedObjectPtr& object1, const ReferenceCountedObjectClass* object2) throw() +{ + return object1.getObject() != object2; +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator!= (const ReferenceCountedObjectPtr& object1, ReferenceCountedObjectPtr& object2) throw() +{ + return object1.getObject() != object2.getObject(); +} + +/** Compares two ReferenceCountedObjectPointers. */ +template +bool operator!= (ReferenceCountedObjectClass* object1, ReferenceCountedObjectPtr& object2) throw() +{ + return object1 != object2.getObject(); +} + + #endif // __JUCE_REFERENCECOUNTEDOBJECT_JUCEHEADER__ diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index 458d486472..d8b69d6406 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 87 +#define JUCE_BUILDNUMBER 88 /** Current Juce version number. diff --git a/src/events/juce_ListenerList.h b/src/events/juce_ListenerList.h index 2f5cfbbdaa..89128842ad 100644 --- a/src/events/juce_ListenerList.h +++ b/src/events/juce_ListenerList.h @@ -149,7 +149,7 @@ public: void callChecked (const BailOutCheckerType& bailOutChecker, void (ListenerClass::*callbackFunction) ()) { - for (Iterator iter (*this, bailOutChecker); iter.next();) + for (Iterator iter (*this); iter.next (bailOutChecker);) (iter.getListener()->*callbackFunction) (); } @@ -158,7 +158,7 @@ public: template void call (void (ListenerClass::*callbackFunction) (P1), LL_PARAM(1)) { - for (Iterator iter (*this, DummyBailOutChecker()); iter.next();) + for (Iterator iter (*this); iter.next();) (iter.getListener()->*callbackFunction) (param1); } @@ -169,7 +169,7 @@ public: void (ListenerClass::*callbackFunction) (P1), LL_PARAM(1)) { - for (Iterator iter (*this, bailOutChecker); iter.next();) + for (Iterator iter (*this); iter.next (bailOutChecker);) (iter.getListener()->*callbackFunction) (param1); } @@ -179,7 +179,7 @@ public: void call (void (ListenerClass::*callbackFunction) (P1, P2), LL_PARAM(1), LL_PARAM(2)) { - for (Iterator iter (*this, DummyBailOutChecker()); iter.next();) + for (Iterator iter (*this); iter.next();) (iter.getListener()->*callbackFunction) (param1, param2); } @@ -190,7 +190,7 @@ public: void (ListenerClass::*callbackFunction) (P1, P2), LL_PARAM(1), LL_PARAM(2)) { - for (Iterator iter (*this, bailOutChecker); iter.next();) + for (Iterator iter (*this); iter.next (bailOutChecker);) (iter.getListener()->*callbackFunction) (param1, param2); } @@ -200,7 +200,7 @@ public: void call (void (ListenerClass::*callbackFunction) (P1, P2, P3), LL_PARAM(1), LL_PARAM(2), LL_PARAM(3)) { - for (Iterator iter (*this, DummyBailOutChecker()); iter.next();) + for (Iterator iter (*this); iter.next();) (iter.getListener()->*callbackFunction) (param1, param2, param3); } @@ -211,7 +211,7 @@ public: void (ListenerClass::*callbackFunction) (P1, P2, P3), LL_PARAM(1), LL_PARAM(2), LL_PARAM(3)) { - for (Iterator iter (*this, bailOutChecker); iter.next();) + for (Iterator iter (*this); iter.next (bailOutChecker);) (iter.getListener()->*callbackFunction) (param1, param2, param3); } @@ -221,7 +221,7 @@ public: void call (void (ListenerClass::*callbackFunction) (P1, P2, P3, P4), LL_PARAM(1), LL_PARAM(2), LL_PARAM(3), LL_PARAM(4)) { - for (Iterator iter (*this, DummyBailOutChecker()); iter.next();) + for (Iterator iter (*this); iter.next();) (iter.getListener()->*callbackFunction) (param1, param2, param3, param4); } @@ -232,7 +232,7 @@ public: void (ListenerClass::*callbackFunction) (P1, P2, P3, P4), LL_PARAM(1), LL_PARAM(2), LL_PARAM(3), LL_PARAM(4)) { - for (Iterator iter (*this, bailOutChecker); iter.next();) + for (Iterator iter (*this); iter.next (bailOutChecker);) (iter.getListener()->*callbackFunction) (param1, param2, param3, param4); } @@ -242,7 +242,7 @@ public: void call (void (ListenerClass::*callbackFunction) (P1, P2, P3, P4, P5), LL_PARAM(1), LL_PARAM(2), LL_PARAM(3), LL_PARAM(4), LL_PARAM(5)) { - for (Iterator iter (*this, DummyBailOutChecker()); iter.next();) + for (Iterator iter (*this); iter.next();) (iter.getListener()->*callbackFunction) (param1, param2, param3, param4, param5); } @@ -253,7 +253,7 @@ public: void (ListenerClass::*callbackFunction) (P1, P2, P3, P4, P5), LL_PARAM(1), LL_PARAM(2), LL_PARAM(3), LL_PARAM(4), LL_PARAM(5)) { - for (Iterator iter (*this, bailOutChecker); iter.next();) + for (Iterator iter (*this); iter.next (bailOutChecker);) (iter.getListener()->*callbackFunction) (param1, param2, param3, param4, param5); } @@ -275,8 +275,8 @@ public: { public: //============================================================================== - Iterator (const ListType& list_, const BailOutCheckerType& bailOutChecker_) - : list (list_), bailOutChecker (bailOutChecker_), index (list_.size()) + Iterator (const ListType& list_) + : list (list_), index (list_.size()) {} ~Iterator() {} @@ -284,7 +284,7 @@ public: //============================================================================== bool next() { - if (index <= 0 || bailOutChecker.shouldBailOut()) + if (index <= 0) return false; const int listSize = list.size(); @@ -296,6 +296,11 @@ public: return index >= 0; } + bool next (const BailOutCheckerType& bailOutChecker) + { + return (! bailOutChecker.shouldBailOut()) && next(); + } + typename ListType::ListenerType* getListener() const throw() { return list.getListeners().getUnchecked (index); @@ -304,7 +309,6 @@ public: //============================================================================== private: const ListType& list; - const BailOutCheckerType& bailOutChecker; int index; Iterator (const Iterator&); diff --git a/src/gui/components/controls/juce_ListBox.cpp b/src/gui/components/controls/juce_ListBox.cpp index eb73a08bf0..4cf82b9a94 100644 --- a/src/gui/components/controls/juce_ListBox.cpp +++ b/src/gui/components/controls/juce_ListBox.cpp @@ -878,7 +878,7 @@ const Image ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) if (rowComp != 0 && isRowSelected (firstRow + i)) { - const Point pos (rowComp->relativePositionToOtherComponent (this, Point())); + const Point pos (getLocalPoint (rowComp, Point())); const Rectangle rowRect (pos.getX(), pos.getY(), rowComp->getWidth(), rowComp->getHeight()); imageArea = imageArea.getUnion (rowRect); } @@ -895,7 +895,7 @@ const Image ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) if (rowComp != 0 && isRowSelected (firstRow + i)) { - const Point pos (rowComp->relativePositionToOtherComponent (this, Point())); + const Point pos (getLocalPoint (rowComp, Point())); Graphics g (snapshot); g.setOrigin (pos.getX() - imageX, pos.getY() - imageY); diff --git a/src/gui/components/controls/juce_Slider.cpp b/src/gui/components/controls/juce_Slider.cpp index 6d2db6b0ee..13948ec3a2 100644 --- a/src/gui/components/controls/juce_Slider.cpp +++ b/src/gui/components/controls/juce_Slider.cpp @@ -1172,8 +1172,8 @@ void Slider::restoreMouseIfHidden() { const int pixelPos = (int) getLinearSliderPos (pos); - mousePos = relativePositionToGlobal (Point (isHorizontal() ? pixelPos : (getWidth() / 2), - isVertical() ? pixelPos : (getHeight() / 2))); + mousePos = localPointToGlobal (Point (isHorizontal() ? pixelPos : (getWidth() / 2), + isVertical() ? pixelPos : (getHeight() / 2))); } Desktop::setMousePosition (mousePos); diff --git a/src/gui/components/controls/juce_TreeView.cpp b/src/gui/components/controls/juce_TreeView.cpp index a2a6077090..8adabd555a 100644 --- a/src/gui/components/controls/juce_TreeView.cpp +++ b/src/gui/components/controls/juce_TreeView.cpp @@ -625,7 +625,7 @@ TreeViewItem* TreeView::getItemAt (int y) const throw() { TreeViewContentComponent* const tc = static_cast (viewport->getViewedComponent()); Rectangle pos; - return tc->findItemAt (relativePositionToOtherComponent (tc, Point (0, y)).getY(), pos); + return tc->findItemAt (tc->getLocalPoint (this, Point (0, y)).getY(), pos); } TreeViewItem* TreeView::findItemFromIdentifierString (const String& identifierString) const diff --git a/src/gui/components/juce_Component.cpp b/src/gui/components/juce_Component.cpp index f9836b6a2e..176457052e 100644 --- a/src/gui/components/juce_Component.cpp +++ b/src/gui/components/juce_Component.cpp @@ -259,8 +259,7 @@ Component::~Component() { parentComponent_->removeChildComponent (this); } - else if ((currentlyFocusedComponent == this) - || isParentOf (currentlyFocusedComponent)) + else if (currentlyFocusedComponent == this || isParentOf (currentlyFocusedComponent)) { giveAwayFocus(); } @@ -434,7 +433,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo) jmax (1, getHeight())); #endif - const Point topLeft (relativePositionToGlobal (Point (0, 0))); + const Point topLeft (getScreenPosition()); bool wasFullscreen = false; bool wasMinimised = false; @@ -777,7 +776,7 @@ int Component::getScreenY() const const Point Component::getScreenPosition() const { - return relativePositionToGlobal (Point()); + return localPointToGlobal (Point()); } const Rectangle Component::getScreenBounds() const @@ -785,53 +784,119 @@ const Rectangle Component::getScreenBounds() const return bounds_.withPosition (getScreenPosition()); } +namespace CoordinateHelpers +{ + const Point convertFromParentSpace (const Component* comp, const Point& pointInParentSpace) + { + return pointInParentSpace - comp->getPosition(); + } + + const Rectangle convertFromParentSpace (const Component* comp, const Rectangle& areaInParentSpace) + { + return areaInParentSpace - comp->getPosition(); + } + + const Point convertToParentSpace (const Component* comp, const Point& pointInLocalSpace) + { + return pointInLocalSpace + comp->getPosition(); + } + + const Rectangle convertToParentSpace (const Component* comp, const Rectangle& areaInLocalSpace) + { + return areaInLocalSpace + comp->getPosition(); + } + + template + const Type convertFromDistantParentSpace (const Component* parent, const Component* target, Type coordInParent) + { + const Component* const directParent = target->getParentComponent(); + jassert (directParent != 0); + + if (directParent == parent) + return convertFromParentSpace (target, coordInParent); + + return convertFromParentSpace (target, convertFromDistantParentSpace (parent, directParent, coordInParent)); + } + + template + const Type convertCoordinate (const Component* target, const Component* source, Type p) + { + while (source != 0) + { + if (source == target) + return p; + + if (source->isParentOf (target)) + return convertFromDistantParentSpace (source, target, p); + + if (source->isOnDesktop()) + { + p = source->getPeer()->localToGlobal (p); + source = 0; + } + else + { + p = convertToParentSpace (source, p); + source = source->getParentComponent(); + } + } + + jassert (source == 0); + if (target == 0) + return p; + + const Component* const topLevelComp = target->getTopLevelComponent(); + + if (topLevelComp->isOnDesktop()) + p = topLevelComp->getPeer()->globalToLocal (p); + else + p = convertFromParentSpace (topLevelComp, p); + + if (topLevelComp == target) + return p; + + return convertFromDistantParentSpace (topLevelComp, target, p); + } +} + +const Point Component::getLocalPoint (const Component* source, const Point& point) const +{ + return CoordinateHelpers::convertCoordinate (this, source, point); +} + +const Rectangle Component::getLocalArea (const Component* source, const Rectangle& area) const +{ + return CoordinateHelpers::convertCoordinate (this, source, area); +} + +const Point Component::localPointToGlobal (const Point& point) const +{ + return CoordinateHelpers::convertCoordinate (0, this, point); +} + +const Rectangle Component::localAreaToGlobal (const Rectangle& area) const +{ + return CoordinateHelpers::convertCoordinate (0, this, area); +} + +/* Deprecated methods... */ const Point Component::relativePositionToGlobal (const Point& relativePosition) const { - return relativePositionToOtherComponent (0, relativePosition); + return localPointToGlobal (relativePosition); } const Point Component::globalPositionToRelative (const Point& screenPosition) const { - if (flags.hasHeavyweightPeerFlag) - { - return getPeer()->globalPositionToRelative (screenPosition); - } - else - { - if (parentComponent_ != 0) - return parentComponent_->globalPositionToRelative (screenPosition) - getPosition(); - - return screenPosition - getPosition(); - } + return getLocalPoint (0, screenPosition); } const Point Component::relativePositionToOtherComponent (const Component* const targetComponent, const Point& positionRelativeToThis) const { - Point p (positionRelativeToThis); - const Component* c = this; - - do - { - if (c == targetComponent) - return p; - - if (c->flags.hasHeavyweightPeerFlag) - { - p = c->getPeer()->relativePositionToGlobal (p); - break; - } - - p += c->getPosition(); - c = c->parentComponent_; - } - while (c != 0); - - if (targetComponent != 0) - p = targetComponent->globalPositionToRelative (p); - - return p; + return targetComponent == 0 ? localPointToGlobal (positionRelativeToThis) + : targetComponent->getLocalPoint (this, positionRelativeToThis); } + //============================================================================== void Component::setBounds (const int x, const int y, int w, int h) { @@ -1922,7 +1987,7 @@ void Component::getVisibleArea (RectangleList& result, const bool includeSibling { const Component* const c = getTopLevelComponent(); - c->subtractObscuredRegions (result, c->relativePositionToOtherComponent (this, Point()), + c->subtractObscuredRegions (result, getLocalPoint (c, Point()), c->getLocalBounds(), this); } @@ -2142,7 +2207,7 @@ void Component::internalMouseEnter (MouseInputSource& source, const Point& { flags.mouseInsideFlag = true; flags.mouseOverFlag = true; - flags.draggingFlag = false; + flags.mouseDownFlag = false; BailOutChecker checker (this); @@ -2167,7 +2232,7 @@ void Component::internalMouseExit (MouseInputSource& source, const Point& r { BailOutChecker checker (this); - if (flags.draggingFlag) + if (flags.mouseDownFlag) { internalMouseUp (source, relativePos, time, source.getCurrentModifiers().getRawFlags()); @@ -2179,7 +2244,7 @@ void Component::internalMouseExit (MouseInputSource& source, const Point& r { flags.mouseInsideFlag = false; flags.mouseOverFlag = false; - flags.draggingFlag = false; + flags.mouseDownFlag = false; if (flags.repaintOnMouseActivityFlag) repaint(); @@ -2308,7 +2373,7 @@ void Component::internalMouseDown (MouseInputSource& source, const Point& r return; } - flags.draggingFlag = true; + flags.mouseDownFlag = true; flags.mouseOverFlag = true; if (flags.repaintOnMouseActivityFlag) @@ -2331,11 +2396,11 @@ void Component::internalMouseDown (MouseInputSource& source, const Point& r //============================================================================== void Component::internalMouseUp (MouseInputSource& source, const Point& relativePos, const Time& time, const ModifierKeys& oldModifiers) { - if (flags.draggingFlag) + if (flags.mouseDownFlag) { Desktop& desktop = Desktop::getInstance(); - flags.draggingFlag = false; + flags.mouseDownFlag = false; BailOutChecker checker (this); @@ -2344,7 +2409,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel const MouseEvent me (source, relativePos, oldModifiers, this, this, time, - globalPositionToRelative (source.getLastMouseDownPosition()), + getLocalPoint (0, source.getLastMouseDownPosition()), source.getLastMouseDownTime(), source.getNumberOfMultipleClicks(), source.hasMouseMovedSignificantlySincePressed()); @@ -2378,7 +2443,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel void Component::internalMouseDrag (MouseInputSource& source, const Point& relativePos, const Time& time) { - if (flags.draggingFlag) + if (flags.mouseDownFlag) { Desktop& desktop = Desktop::getInstance(); @@ -2388,7 +2453,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r const MouseEvent me (source, relativePos, source.getCurrentModifiers(), this, this, time, - globalPositionToRelative (source.getLastMouseDownPosition()), + getLocalPoint (0, source.getLastMouseDownPosition()), source.getLastMouseDownTime(), source.getNumberOfMultipleClicks(), source.hasMouseMovedSignificantlySincePressed()); @@ -2411,8 +2476,7 @@ void Component::internalMouseMove (MouseInputSource& source, const Point& r BailOutChecker checker (this); const MouseEvent me (source, relativePos, source.getCurrentModifiers(), - this, this, time, relativePos, - time, 0, false); + this, this, time, relativePos, time, 0, false); if (isCurrentlyBlockedByAnotherModalComponent()) { @@ -2825,12 +2889,12 @@ bool Component::isMouseOver() const throw() bool Component::isMouseButtonDown() const throw() { - return flags.draggingFlag; + return flags.mouseDownFlag; } bool Component::isMouseOverOrDragging() const throw() { - return flags.mouseOverFlag || flags.draggingFlag; + return flags.mouseOverFlag || flags.mouseDownFlag; } bool JUCE_CALLTYPE Component::isMouseButtonDownAnywhere() throw() @@ -2840,14 +2904,14 @@ bool JUCE_CALLTYPE Component::isMouseButtonDownAnywhere() throw() const Point Component::getMouseXYRelative() const { - return globalPositionToRelative (Desktop::getMousePosition()); + return getLocalPoint (0, Desktop::getMousePosition()); } //============================================================================== const Rectangle Component::getParentMonitorArea() const { return Desktop::getInstance() - .getMonitorAreaContaining (relativePositionToGlobal (getLocalBounds().getCentre())); + .getMonitorAreaContaining (localPointToGlobal (getLocalBounds().getCentre())); } //============================================================================== diff --git a/src/gui/components/juce_Component.h b/src/gui/components/juce_Component.h index ff21f97953..cceb03f8fd 100644 --- a/src/gui/components/juce_Component.h +++ b/src/gui/components/juce_Component.h @@ -73,7 +73,7 @@ public: /** Destructor. - Note that when a component is deleted, any child components it contain are NOT + Note that when a component is deleted, any child components it contains are NOT automatically deleted. It's your responsibilty to manage their lifespan - you may want to use helper methods like deleteAllChildren(), or less haphazard approaches like using ScopedPointers or normal object aggregation to manage them. @@ -313,12 +313,12 @@ public: //============================================================================== /** Returns this component's x co-ordinate relative the the screen's top-left origin. - @see getX, relativePositionToGlobal + @see getX, localPointToGlobal */ int getScreenX() const; /** Returns this component's y co-ordinate relative the the screen's top-left origin. - @see getY, relativePositionToGlobal + @see getY, localPointToGlobal */ int getScreenY() const; @@ -332,24 +332,33 @@ public: */ const Rectangle getScreenBounds() const; - /** Converts a position relative to this component's top-left into a screen co-ordinate. - @see globalPositionToRelative, relativePositionToOtherComponent - */ - const Point relativePositionToGlobal (const Point& relativePosition) const; + /** Converts a point to be relative to this component's coordinate space. - /** Converts a screen co-ordinate into a position relative to this component's top-left. - @see relativePositionToGlobal, relativePositionToOtherComponent + This takes a point relative to a different component, and returns its position relative to this + component. If the sourceComponent parameter is null, the source point is assumed to be a global + screen coordinate. */ - const Point globalPositionToRelative (const Point& screenPosition) const; + const Point getLocalPoint (const Component* sourceComponent, + const Point& pointRelativeToSourceComponent) const; - /** Converts a position relative to this component's top-left into a position - relative to another component's top-left. - If the targetComponent parameter is null, the coordinate is converted to global screen - coordinates. - @see relativePositionToGlobal, globalPositionToRelative + /** Converts a rectangle to be relative to this component's coordinate space. + + 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. */ - const Point relativePositionToOtherComponent (const Component* targetComponent, - const Point& positionRelativeToThis) const; + const Rectangle getLocalArea (const Component* sourceComponent, + const Rectangle& areaRelativeToSourceComponent) const; + + /** Converts a point relative to this component's top-left into a screen coordinate. + @see getLocalPoint, localAreaToGlobal + */ + const Point localPointToGlobal (const Point& localPoint) const; + + /** Converts a rectangle from this component's coordinate space to a screen coordinate. + @see getLocalPoint, localPointToGlobal + */ + const Rectangle localAreaToGlobal (const Rectangle& localArea) const; //============================================================================== /** Moves the component to a new position. @@ -1981,6 +1990,22 @@ public: BailOutChecker& operator= (const BailOutChecker&); }; + //============================================================================== + #ifndef DOXYGEN + /** @internal + This method is deprecated - use localPointToGlobal instead. */ + const Point relativePositionToGlobal (const Point& relativePosition) const; + + /** @internal + This method is deprecated - use getLocalPoint instead. */ + const Point globalPositionToRelative (const Point& screenPosition) const; + + /** @internal + This method is deprecated - use getLocalPoint instead. */ + const Point relativePositionToOtherComponent (const Component* targetComponent, + const Point& positionRelativeToThis) const; + #endif + //============================================================================== juce_UseDebuggingNewOperator @@ -2025,7 +2050,7 @@ private: bool bufferToImageFlag : 1; bool bringToFrontOnClickFlag : 1; bool repaintOnMouseActivityFlag : 1; - bool draggingFlag : 1; + bool mouseDownFlag : 1; bool mouseOverFlag : 1; bool mouseInsideFlag : 1; bool currentlyModalFlag : 1; diff --git a/src/gui/components/juce_Desktop.cpp b/src/gui/components/juce_Desktop.cpp index f2bbbfd14d..77d4e5f2e4 100644 --- a/src/gui/components/juce_Desktop.cpp +++ b/src/gui/components/juce_Desktop.cpp @@ -160,7 +160,7 @@ Component* Desktop::findComponentAt (const Point& screenPosition) const if (c->isVisible()) { - const Point relative (c->globalPositionToRelative (screenPosition)); + const Point relative (c->getLocalPoint (0, screenPosition)); if (c->contains (relative.getX(), relative.getY())) return c->getComponentAt (relative.getX(), relative.getY()); @@ -305,7 +305,7 @@ void Desktop::sendMouseMove() if (target != 0) { Component::BailOutChecker checker (target); - const Point pos (target->globalPositionToRelative (lastFakeMouseMove)); + const Point pos (target->getLocalPoint (0, lastFakeMouseMove)); const Time now (Time::getCurrentTime()); const MouseEvent me (getMainMouseSource(), pos, ModifierKeys::getCurrentModifiers(), diff --git a/src/gui/components/layout/juce_ComponentMovementWatcher.cpp b/src/gui/components/layout/juce_ComponentMovementWatcher.cpp index 0a1e649011..f2b45964bb 100644 --- a/src/gui/components/layout/juce_ComponentMovementWatcher.cpp +++ b/src/gui/components/layout/juce_ComponentMovementWatcher.cpp @@ -88,7 +88,7 @@ void ComponentMovementWatcher::componentMovedOrResized (Component&, bool wasMove if (wasMoved) { - const Point pos (component->relativePositionToOtherComponent (component->getTopLevelComponent(), Point())); + const Point pos (component->getTopLevelComponent()->getLocalPoint (component, Point())); wasMoved = lastBounds.getPosition() != pos; lastBounds.setPosition (pos); diff --git a/src/gui/components/lookandfeel/juce_LookAndFeel.cpp b/src/gui/components/lookandfeel/juce_LookAndFeel.cpp index 7f0eb15e53..73a1872f27 100644 --- a/src/gui/components/lookandfeel/juce_LookAndFeel.cpp +++ b/src/gui/components/lookandfeel/juce_LookAndFeel.cpp @@ -155,6 +155,9 @@ namespace LookAndFeelHelpers return tl; } + + LookAndFeel* defaultLF = 0; + LookAndFeel* currentDefaultLF = 0; } //============================================================================== @@ -309,6 +312,8 @@ LookAndFeel::LookAndFeel() LookAndFeel::~LookAndFeel() { + if (this == LookAndFeelHelpers::currentDefaultLF) + setDefaultLookAndFeel (0); } //============================================================================== @@ -344,21 +349,20 @@ bool LookAndFeel::isColourSpecified (const int colourId) const throw() } //============================================================================== -static LookAndFeel* defaultLF = 0; -static LookAndFeel* currentDefaultLF = 0; - LookAndFeel& LookAndFeel::getDefaultLookAndFeel() throw() { // if this happens, your app hasn't initialised itself properly.. if you're // trying to hack your own main() function, have a look at // JUCEApplication::initialiseForGUI() - jassert (currentDefaultLF != 0); + jassert (LookAndFeelHelpers::currentDefaultLF != 0); - return *currentDefaultLF; + return *LookAndFeelHelpers::currentDefaultLF; } void LookAndFeel::setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel) throw() { + using namespace LookAndFeelHelpers; + if (newDefaultLookAndFeel == 0) { if (defaultLF == 0) @@ -367,7 +371,7 @@ void LookAndFeel::setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel) thr newDefaultLookAndFeel = defaultLF; } - currentDefaultLF = newDefaultLookAndFeel; + LookAndFeelHelpers::currentDefaultLF = newDefaultLookAndFeel; for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) { @@ -380,6 +384,8 @@ void LookAndFeel::setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel) thr void LookAndFeel::clearDefaultLookAndFeel() throw() { + using namespace LookAndFeelHelpers; + if (currentDefaultLF == defaultLF) currentDefaultLF = 0; diff --git a/src/gui/components/menus/juce_PopupMenu.cpp b/src/gui/components/menus/juce_PopupMenu.cpp index db54b05af9..5acb7fd655 100644 --- a/src/gui/components/menus/juce_PopupMenu.cpp +++ b/src/gui/components/menus/juce_PopupMenu.cpp @@ -580,7 +580,7 @@ public: // move rather than a real timer callback const Point globalMousePos (Desktop::getMousePosition()); - const Point localMousePos (globalPositionToRelative (globalMousePos)); + const Point localMousePos (getLocalPoint (0, globalMousePos)); const uint32 now = Time::getMillisecondCounter(); @@ -750,7 +750,7 @@ private: void updateMouseOverStatus (const Point& globalMousePos) { - const Point relPos (globalPositionToRelative (globalMousePos)); + const Point relPos (getLocalPoint (0, globalMousePos)); isOver = reallyContains (relPos.getX(), relPos.getY(), true); if (activeSubMenu != 0) diff --git a/src/gui/components/mouse/juce_ComponentDragger.cpp b/src/gui/components/mouse/juce_ComponentDragger.cpp index 7b9d2993f5..84285aac83 100644 --- a/src/gui/components/mouse/juce_ComponentDragger.cpp +++ b/src/gui/components/mouse/juce_ComponentDragger.cpp @@ -50,7 +50,7 @@ void ComponentDragger::startDraggingComponent (Component* const componentToDrag, if (componentToDrag != 0) { constrainer = constrainer_; - originalPos = componentToDrag->relativePositionToGlobal (Point()); + originalPos = componentToDrag->localPointToGlobal (Point()); } } @@ -65,7 +65,7 @@ void ComponentDragger::dragComponent (Component* const componentToDrag, const Mo const Component* const parentComp = componentToDrag->getParentComponent(); if (parentComp != 0) - bounds.setPosition (parentComp->globalPositionToRelative (originalPos)); + bounds.setPosition (parentComp->getLocalPoint (0, originalPos)); bounds.setPosition (bounds.getPosition() + e.getOffsetFromDragStart()); diff --git a/src/gui/components/mouse/juce_DragAndDropContainer.cpp b/src/gui/components/mouse/juce_DragAndDropContainer.cpp index 6523775544..98e4f326c8 100644 --- a/src/gui/components/mouse/juce_DragAndDropContainer.cpp +++ b/src/gui/components/mouse/juce_DragAndDropContainer.cpp @@ -110,7 +110,7 @@ public: } else { - const Point relPos (hit->globalPositionToRelative (screenPos)); + const Point relPos (hit->getLocalPoint (0, screenPos)); hit = hit->getComponentAt (relPos.getX(), relPos.getY()); } @@ -124,7 +124,7 @@ public: if (ddt != 0 && ddt->isInterestedInDragSource (dragDescLocal, source)) { - relativePos = hit->globalPositionToRelative (screenPos); + relativePos = hit->getLocalPoint (0, screenPos); return ddt; } @@ -162,8 +162,8 @@ public: } else { - const Point target (source->relativePositionToGlobal (source->getLocalBounds().getCentre())); - const Point ourCentre (relativePositionToGlobal (getLocalBounds().getCentre())); + const Point target (source->localPointToGlobal (source->getLocalBounds().getCentre())); + const Point ourCentre (localPointToGlobal (getLocalBounds().getCentre())); Desktop::getInstance().getAnimator().animateComponent (this, getBounds() + (target - ourCentre), @@ -199,7 +199,7 @@ public: Point newPos (screenPos + imageOffset); if (getParentComponent() != 0) - newPos = getParentComponent()->globalPositionToRelative (newPos); + newPos = getParentComponent()->getLocalPoint (0, newPos); //if (newX != getX() || newY != getY()) { @@ -347,7 +347,7 @@ void DragAndDropContainer::startDragging (const String& sourceDescription, const int lo = 150; const int hi = 400; - Point relPos (sourceComponent->globalPositionToRelative (lastMouseDown)); + Point relPos (sourceComponent->getLocalPoint (0, lastMouseDown)); Point clipped (dragImage.getBounds().getConstrainedPoint (relPos)); for (int y = dragImage.getHeight(); --y >= 0;) diff --git a/src/gui/components/mouse/juce_MouseEvent.cpp b/src/gui/components/mouse/juce_MouseEvent.cpp index ec13b0a1e3..70e47bf042 100644 --- a/src/gui/components/mouse/juce_MouseEvent.cpp +++ b/src/gui/components/mouse/juce_MouseEvent.cpp @@ -69,9 +69,9 @@ const MouseEvent MouseEvent::getEventRelativeTo (Component* const otherComponent return *this; } - return MouseEvent (source, eventComponent->relativePositionToOtherComponent (otherComponent, getPosition()), + return MouseEvent (source, otherComponent->getLocalPoint (eventComponent, getPosition()), mods, otherComponent, originalComponent, eventTime, - eventComponent->relativePositionToOtherComponent (otherComponent, mouseDownPos), + otherComponent->getLocalPoint (eventComponent, mouseDownPos), mouseDownTime, numberOfClicks, wasMovedSinceMouseDown); } @@ -149,7 +149,7 @@ int MouseEvent::getScreenY() const const Point MouseEvent::getScreenPosition() const { - return eventComponent->relativePositionToGlobal (Point (x, y)); + return eventComponent->localPointToGlobal (Point (x, y)); } int MouseEvent::getMouseDownScreenX() const @@ -164,7 +164,7 @@ int MouseEvent::getMouseDownScreenY() const const Point MouseEvent::getMouseDownScreenPosition() const { - return eventComponent->relativePositionToGlobal (mouseDownPos); + return eventComponent->localPointToGlobal (mouseDownPos); } //============================================================================== diff --git a/src/gui/components/mouse/juce_MouseInputSource.cpp b/src/gui/components/mouse/juce_MouseInputSource.cpp index 06bb3bab0f..30ed412932 100644 --- a/src/gui/components/mouse/juce_MouseInputSource.cpp +++ b/src/gui/components/mouse/juce_MouseInputSource.cpp @@ -45,7 +45,6 @@ public: isUnboundedMouseModeOn (false), isCursorVisibleUntilOffscreen (false), currentCursorHandle (0), mouseEventCounter (0), lastTime (0) { - zerostruct (mouseDowns); } ~MouseInputSourceInternal() @@ -83,7 +82,7 @@ public: if (peer != 0) { Component* const comp = peer->getComponent(); - const Point relativePos (comp->globalPositionToRelative (screenPos)); + const Point relativePos (comp->getLocalPoint (0, screenPos)); // (the contains() call is needed to test for overlapping desktop windows) if (comp->contains (relativePos.getX(), relativePos.getY())) @@ -101,44 +100,44 @@ public: //============================================================================== void sendMouseEnter (Component* const comp, const Point& screenPos, const int64 time) { - //DBG ("Mouse " + String (source.getIndex()) + " enter: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseEnter (source, comp->globalPositionToRelative (screenPos), time); + //DBG ("Mouse " + String (source.getIndex()) + " enter: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseEnter (source, comp->getLocalPoint (0, screenPos), time); } void sendMouseExit (Component* const comp, const Point& screenPos, const int64 time) { - //DBG ("Mouse " + String (source.getIndex()) + " exit: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseExit (source, comp->globalPositionToRelative (screenPos), time); + //DBG ("Mouse " + String (source.getIndex()) + " exit: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseExit (source, comp->getLocalPoint (0, screenPos), time); } void sendMouseMove (Component* const comp, const Point& screenPos, const int64 time) { - //DBG ("Mouse " + String (source.getIndex()) + " move: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseMove (source, comp->globalPositionToRelative (screenPos), time); + //DBG ("Mouse " + String (source.getIndex()) + " move: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseMove (source, comp->getLocalPoint (0, screenPos), time); } void sendMouseDown (Component* const comp, const Point& screenPos, const int64 time) { - //DBG ("Mouse " + String (source.getIndex()) + " down: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseDown (source, comp->globalPositionToRelative (screenPos), time); + //DBG ("Mouse " + String (source.getIndex()) + " down: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseDown (source, comp->getLocalPoint (0, screenPos), time); } void sendMouseDrag (Component* const comp, const Point& screenPos, const int64 time) { - //DBG ("Mouse " + String (source.getIndex()) + " drag: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseDrag (source, comp->globalPositionToRelative (screenPos), time); + //DBG ("Mouse " + String (source.getIndex()) + " drag: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseDrag (source, comp->getLocalPoint (0, screenPos), time); } void sendMouseUp (Component* const comp, const Point& screenPos, const int64 time) { - //DBG ("Mouse " + String (source.getIndex()) + " up: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseUp (source, comp->globalPositionToRelative (screenPos), time, getCurrentModifiers()); + //DBG ("Mouse " + String (source.getIndex()) + " up: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseUp (source, comp->getLocalPoint (0, screenPos), time, getCurrentModifiers()); } void sendMouseWheel (Component* const comp, const Point& screenPos, const int64 time, float x, float y) { - //DBG ("Mouse " + String (source.getIndex()) + " wheel: " + comp->globalPositionToRelative (screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); - comp->internalMouseWheel (source, comp->globalPositionToRelative (screenPos), time, x, y); + //DBG ("Mouse " + String (source.getIndex()) + " wheel: " + comp->getLocalPoint (0, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp)); + comp->internalMouseWheel (source, comp->getLocalPoint (0, screenPos), time, x, y); } //============================================================================== @@ -264,7 +263,7 @@ public: jassert (newPeer != 0); lastTime = time; ++mouseEventCounter; - const Point screenPos (newPeer->relativePositionToGlobal (positionWithinPeer)); + const Point screenPos (newPeer->localToGlobal (positionWithinPeer)); if (isDragging() && newMods.isAnyMouseButtonDown()) { @@ -292,7 +291,7 @@ public: jassert (peer != 0); lastTime = time; ++mouseEventCounter; - const Point screenPos (peer->relativePositionToGlobal (positionWithinPeer)); + const Point screenPos (peer->localToGlobal (positionWithinPeer)); setPeer (peer, screenPos, time); setScreenPos (screenPos, time, false); @@ -328,7 +327,7 @@ public: for (int i = 1; i < numElementsInArray (mouseDowns); ++i) { - if (mouseDowns[0].canBePartOfMultipleClickWith (mouseDowns[1], (int) (MouseEvent::getDoubleClickTimeout() * (1.0 + 0.25 * (i - 1))))) + if (mouseDowns[0].canBePartOfMultipleClickWith (mouseDowns[i], (int) (MouseEvent::getDoubleClickTimeout() * (1.0 + 0.25 * (i - 1))))) ++numClicks; else break; @@ -448,6 +447,11 @@ private: struct RecentMouseDown { + RecentMouseDown() + : time (0), component (0) + { + } + Point position; int64 time; Component* component; diff --git a/src/gui/components/special/juce_BubbleComponent.cpp b/src/gui/components/special/juce_BubbleComponent.cpp index 31619c8d5c..ba8a463114 100644 --- a/src/gui/components/special/juce_BubbleComponent.cpp +++ b/src/gui/components/special/juce_BubbleComponent.cpp @@ -101,9 +101,9 @@ void BubbleComponent::setPosition (Component* componentToPointTo) Point pos; if (getParentComponent() != 0) - pos = componentToPointTo->relativePositionToOtherComponent (getParentComponent(), pos); + pos = getParentComponent()->getLocalPoint (componentToPointTo, pos); else - pos = componentToPointTo->relativePositionToGlobal (pos); + pos = componentToPointTo->localPointToGlobal (pos); setPosition (Rectangle (pos.getX(), pos.getY(), componentToPointTo->getWidth(), componentToPointTo->getHeight())); } diff --git a/src/gui/components/special/juce_MagnifierComponent.cpp b/src/gui/components/special/juce_MagnifierComponent.cpp index 2d62509aa9..54514e0bc7 100644 --- a/src/gui/components/special/juce_MagnifierComponent.cpp +++ b/src/gui/components/special/juce_MagnifierComponent.cpp @@ -96,16 +96,16 @@ public: return magnifierComp->getScreenPosition(); } - const Point relativePositionToGlobal (const Point& relativePosition) + const Point localToGlobal (const Point& relativePosition) { const double zoom = magnifierComp->getScaleFactor(); - return magnifierComp->relativePositionToGlobal (Point (roundToInt (relativePosition.getX() * zoom), - roundToInt (relativePosition.getY() * zoom))); + return magnifierComp->localPointToGlobal (Point (roundToInt (relativePosition.getX() * zoom), + roundToInt (relativePosition.getY() * zoom))); } - const Point globalPositionToRelative (const Point& screenPosition) + const Point globalToLocal (const Point& screenPosition) { - const Point p (magnifierComp->globalPositionToRelative (screenPosition)); + const Point p (magnifierComp->getLocalPoint (0, screenPosition)); const double zoom = magnifierComp->getScaleFactor(); return Point (roundToInt (p.getX() / zoom), diff --git a/src/gui/components/windows/juce_CallOutBox.cpp b/src/gui/components/windows/juce_CallOutBox.cpp index 26cc9f66f5..e0cfdff3f8 100644 --- a/src/gui/components/windows/juce_CallOutBox.cpp +++ b/src/gui/components/windows/juce_CallOutBox.cpp @@ -45,8 +45,7 @@ CallOutBox::CallOutBox (Component& contentComponent, { parentComponent->addChildComponent (this); - updatePosition (componentToPointTo.getLocalBounds() - + componentToPointTo.relativePositionToOtherComponent (parentComponent, Point()), + updatePosition (parentComponent->getLocalArea (&componentToPointTo, componentToPointTo.getLocalBounds()), parentComponent->getLocalBounds()); setVisible (true); diff --git a/src/gui/components/windows/juce_ComponentPeer.cpp b/src/gui/components/windows/juce_ComponentPeer.cpp index 9309239665..6146c9f516 100644 --- a/src/gui/components/windows/juce_ComponentPeer.cpp +++ b/src/gui/components/windows/juce_ComponentPeer.cpp @@ -399,6 +399,16 @@ const Rectangle& ComponentPeer::getNonFullScreenBounds() const throw() return lastNonFullscreenBounds; } +const Rectangle ComponentPeer::localToGlobal (const Rectangle& relativePosition) +{ + return relativePosition.withPosition (localToGlobal (relativePosition.getPosition())); +} + +const Rectangle ComponentPeer::globalToLocal (const Rectangle& screenPosition) +{ + return screenPosition.withPosition (globalToLocal (screenPosition.getPosition())); +} + //============================================================================== namespace ComponentPeerHelpers { @@ -446,7 +456,7 @@ void ComponentPeer::handleFileDragMove (const StringArray& files, const Point (newTarget); - const Point pos (component->relativePositionToOtherComponent (dragAndDropTargetComponent, position)); + const Point pos (dragAndDropTargetComponent->getLocalPoint (component, position)); newTarget->fileDragEnter (files, pos.getX(), pos.getY()); } } @@ -459,7 +469,7 @@ void ComponentPeer::handleFileDragMove (const StringArray& files, const Point (newTarget); - const Point pos (component->relativePositionToOtherComponent (targetComp, position)); + const Point pos (targetComp->getLocalPoint (component, position)); newTarget->fileDragMove (files, pos.getX(), pos.getY()); } @@ -497,7 +507,7 @@ void ComponentPeer::handleFileDragDrop (const StringArray& files, const Point pos (component->relativePositionToOtherComponent (targetComp, position)); + const Point pos (targetComp->getLocalPoint (component, position)); target->filesDropped (files, pos.getX(), pos.getY()); } } diff --git a/src/gui/components/windows/juce_ComponentPeer.h b/src/gui/components/windows/juce_ComponentPeer.h index dc5d588a41..ee74356edf 100644 --- a/src/gui/components/windows/juce_ComponentPeer.h +++ b/src/gui/components/windows/juce_ComponentPeer.h @@ -152,10 +152,16 @@ public: virtual const Point getScreenPosition() const = 0; /** Converts a position relative to the top-left of this component to screen co-ordinates. */ - virtual const Point relativePositionToGlobal (const Point& relativePosition) = 0; + virtual const Point localToGlobal (const Point& relativePosition) = 0; + + /** Converts a rectangle relative to the top-left of this component to screen co-ordinates. */ + virtual const Rectangle localToGlobal (const Rectangle& relativePosition); /** Converts a screen co-ordinate to a position relative to the top-left of this component. */ - virtual const Point globalPositionToRelative (const Point& screenPosition) = 0; + virtual const Point globalToLocal (const Point& screenPosition) = 0; + + /** Converts a screen area to a position relative to the top-left of this component. */ + virtual const Rectangle globalToLocal (const Rectangle& screenPosition); /** Minimises the window. */ virtual void setMinimised (bool shouldBeMinimised) = 0; diff --git a/src/gui/components/windows/juce_TooltipWindow.cpp b/src/gui/components/windows/juce_TooltipWindow.cpp index 25a4821ad8..15ad076719 100644 --- a/src/gui/components/windows/juce_TooltipWindow.cpp +++ b/src/gui/components/windows/juce_TooltipWindow.cpp @@ -87,7 +87,7 @@ void TooltipWindow::showFor (const String& tip) Point mousePos (Desktop::getMousePosition()); if (getParentComponent() != 0) - mousePos = getParentComponent()->globalPositionToRelative (mousePos); + mousePos = getParentComponent()->getLocalPoint (0, mousePos); int x, y, w, h; getLookAndFeel().getTooltipSize (tip, w, h); diff --git a/src/gui/components/windows/juce_TopLevelWindow.cpp b/src/gui/components/windows/juce_TopLevelWindow.cpp index 90320ebae6..a8faaa283c 100644 --- a/src/gui/components/windows/juce_TopLevelWindow.cpp +++ b/src/gui/components/windows/juce_TopLevelWindow.cpp @@ -291,21 +291,19 @@ void TopLevelWindow::centreAroundComponent (Component* c, const int width, const } else { - Point p (c->relativePositionToGlobal (Point ((c->getWidth() - width) / 2, - (c->getHeight() - height) / 2))); - + Point targetCentre (c->localPointToGlobal (c->getLocalBounds().getCentre())); Rectangle parentArea (c->getParentMonitorArea()); if (getParentComponent() != 0) { - p = getParentComponent()->globalPositionToRelative (p); - parentArea.setBounds (0, 0, getParentWidth(), getParentHeight()); + targetCentre = getParentComponent()->getLocalPoint (0, targetCentre); + parentArea = getParentComponent()->getLocalBounds(); } parentArea.reduce (12, 12); - setBounds (jlimit (parentArea.getX(), jmax (parentArea.getX(), parentArea.getRight() - width), p.getX()), - jlimit (parentArea.getY(), jmax (parentArea.getY(), parentArea.getBottom() - height), p.getY()), + setBounds (jlimit (parentArea.getX(), jmax (parentArea.getX(), parentArea.getRight() - width), targetCentre.getX() - width / 2), + jlimit (parentArea.getY(), jmax (parentArea.getY(), parentArea.getBottom() - height), targetCentre.getY() - height / 2), width, height); } } diff --git a/src/native/linux/juce_linux_Fonts.cpp b/src/native/linux/juce_linux_Fonts.cpp index dd4d5c40ff..b38900e4c6 100644 --- a/src/native/linux/juce_linux_Fonts.cpp +++ b/src/native/linux/juce_linux_Fonts.cpp @@ -1,572 +1,572 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-10 by Raw Material Software Ltd. - - ------------------------------------------------------------------------------ - - JUCE can be redistributed and/or modified under the terms of the GNU General - Public License (Version 2), as published by the Free Software Foundation. - A copy of the license is included in the JUCE distribution, or can be found - online at www.gnu.org/licenses. - - JUCE is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - To release a closed-source product which uses JUCE, commercial licenses are - available: visit www.rawmaterialsoftware.com/juce for more information. - - ============================================================================== -*/ - -// (This file gets included by juce_linux_NativeCode.cpp, rather than being -// compiled on its own). -#if JUCE_INCLUDED_FILE - - -//============================================================================== -class FreeTypeFontFace -{ -public: - //============================================================================== - enum FontStyle - { - Plain = 0, - Bold = 1, - Italic = 2 - }; - - //============================================================================== - FreeTypeFontFace (const String& familyName) - : hasSerif (false), - monospaced (false) - { - family = familyName; - } - - void setFileName (const String& name, const int faceIndex, FontStyle style) - { - if (names [(int) style].fileName.isEmpty()) - { - names [(int) style].fileName = name; - names [(int) style].faceIndex = faceIndex; - } - } - - const String& getFamilyName() const throw() { return family; } - - const String& getFileName (const int style, int& faceIndex) const throw() - { - faceIndex = names[style].faceIndex; - return names[style].fileName; - } - - void setMonospaced (bool mono) throw() { monospaced = mono; } - bool getMonospaced() const throw() { return monospaced; } - - void setSerif (const bool serif) throw() { hasSerif = serif; } - bool getSerif() const throw() { return hasSerif; } - -private: - //============================================================================== - String family; - - struct FontNameIndex - { - String fileName; - int faceIndex; - }; - - FontNameIndex names[4]; - bool hasSerif, monospaced; -}; - -//============================================================================== -class FreeTypeInterface : public DeletedAtShutdown -{ -public: - //============================================================================== - FreeTypeInterface() - : ftLib (0), - lastFace (0), - lastBold (false), - lastItalic (false) - { - if (FT_Init_FreeType (&ftLib) != 0) - { - ftLib = 0; - DBG ("Failed to initialize FreeType"); - } - - StringArray fontDirs; - fontDirs.addTokens (String::fromUTF8 (getenv ("JUCE_FONT_PATH")), ";,", String::empty); - fontDirs.removeEmptyStrings (true); - - if (fontDirs.size() == 0) - { - const ScopedPointer fontsInfo (XmlDocument::parse (File ("/etc/fonts/fonts.conf"))); - - if (fontsInfo != 0) - { - forEachXmlChildElementWithTagName (*fontsInfo, e, "dir") - { - fontDirs.add (e->getAllSubText().trim()); - } - } - } - - if (fontDirs.size() == 0) - fontDirs.add ("/usr/X11R6/lib/X11/fonts"); - - for (int i = 0; i < fontDirs.size(); ++i) - enumerateFaces (fontDirs[i]); - } - - ~FreeTypeInterface() - { - if (lastFace != 0) - FT_Done_Face (lastFace); - - if (ftLib != 0) - FT_Done_FreeType (ftLib); - - clearSingletonInstance(); - } - - //============================================================================== - FreeTypeFontFace* findOrCreate (const String& familyName, const bool create = false) - { - for (int i = 0; i < faces.size(); i++) - if (faces[i]->getFamilyName() == familyName) - return faces[i]; - - if (! create) - return 0; - - FreeTypeFontFace* newFace = new FreeTypeFontFace (familyName); - faces.add (newFace); - - return newFace; - } - - // Enumerate all font faces available in a given directory - void enumerateFaces (const String& path) - { - File dirPath (path); - if (path.isEmpty() || ! dirPath.isDirectory()) - return; - - DirectoryIterator di (dirPath, true); - - while (di.next()) - { - File possible (di.getFile()); - - if (possible.hasFileExtension ("ttf") - || possible.hasFileExtension ("pfb") - || possible.hasFileExtension ("pcf")) - { - FT_Face face; - int faceIndex = 0; - int numFaces = 0; - - do - { - if (FT_New_Face (ftLib, possible.getFullPathName().toUTF8(), - faceIndex, &face) == 0) - { - if (faceIndex == 0) - numFaces = face->num_faces; - - if ((face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) - { - FreeTypeFontFace* const newFace = findOrCreate (face->family_name, true); - int style = (int) FreeTypeFontFace::Plain; - - if ((face->style_flags & FT_STYLE_FLAG_BOLD) != 0) - style |= (int) FreeTypeFontFace::Bold; - - if ((face->style_flags & FT_STYLE_FLAG_ITALIC) != 0) - style |= (int) FreeTypeFontFace::Italic; - - newFace->setFileName (possible.getFullPathName(), faceIndex, (FreeTypeFontFace::FontStyle) style); - newFace->setMonospaced ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0); - - // Surely there must be a better way to do this? - const String name (face->family_name); - newFace->setSerif (! (name.containsIgnoreCase ("Sans") - || name.containsIgnoreCase ("Verdana") - || name.containsIgnoreCase ("Arial"))); - } - - FT_Done_Face (face); - } - - ++faceIndex; - } - while (faceIndex < numFaces); - } - } - } - - // Create a FreeType face object for a given font - FT_Face createFT_Face (const String& fontName, const bool bold, const bool italic) - { - FT_Face face = 0; - - if (fontName == lastFontName && bold == lastBold && italic == lastItalic) - { - face = lastFace; - } - else - { - if (lastFace != 0) - { - FT_Done_Face (lastFace); - lastFace = 0; - } - - lastFontName = fontName; - lastBold = bold; - lastItalic = italic; - - FreeTypeFontFace* const ftFace = findOrCreate (fontName); - - if (ftFace != 0) - { - int style = (int) FreeTypeFontFace::Plain; - - if (bold) - style |= (int) FreeTypeFontFace::Bold; - - if (italic) - style |= (int) FreeTypeFontFace::Italic; - - int faceIndex; - String fileName (ftFace->getFileName (style, faceIndex)); - - if (fileName.isEmpty()) - { - style ^= (int) FreeTypeFontFace::Bold; - - fileName = ftFace->getFileName (style, faceIndex); - - if (fileName.isEmpty()) - { - style ^= (int) FreeTypeFontFace::Bold; - style ^= (int) FreeTypeFontFace::Italic; - - fileName = ftFace->getFileName (style, faceIndex); - - if (! fileName.length()) - { - style ^= (int) FreeTypeFontFace::Bold; - fileName = ftFace->getFileName (style, faceIndex); - } - } - } - - if (! FT_New_Face (ftLib, fileName.toUTF8(), faceIndex, &lastFace)) - { - face = lastFace; - - // If there isn't a unicode charmap then select the first one. - if (FT_Select_Charmap (face, ft_encoding_unicode)) - FT_Set_Charmap (face, face->charmaps[0]); - } - } - } - - return face; - } - - bool addGlyph (FT_Face face, CustomTypeface& dest, uint32 character) - { - const unsigned int glyphIndex = FT_Get_Char_Index (face, character); - const float height = (float) (face->ascender - face->descender); - const float scaleX = 1.0f / height; - const float scaleY = -1.0f / height; - Path destShape; - - if (FT_Load_Glyph (face, glyphIndex, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM) != 0 - || face->glyph->format != ft_glyph_format_outline) - { - return false; - } - - const FT_Outline* const outline = &face->glyph->outline; - const short* const contours = outline->contours; - const char* const tags = outline->tags; - FT_Vector* const points = outline->points; - - for (int c = 0; c < outline->n_contours; c++) - { - const int startPoint = (c == 0) ? 0 : contours [c - 1] + 1; - const int endPoint = contours[c]; - - for (int p = startPoint; p <= endPoint; p++) - { - const float x = scaleX * points[p].x; - const float y = scaleY * points[p].y; - - if (p == startPoint) - { - if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Conic) - { - float x2 = scaleX * points [endPoint].x; - float y2 = scaleY * points [endPoint].y; - - if (FT_CURVE_TAG (tags[endPoint]) != FT_Curve_Tag_On) - { - x2 = (x + x2) * 0.5f; - y2 = (y + y2) * 0.5f; - } - - destShape.startNewSubPath (x2, y2); - } - else - { - destShape.startNewSubPath (x, y); - } - } - - if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_On) - { - if (p != startPoint) - destShape.lineTo (x, y); - } - else if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Conic) - { - const int nextIndex = (p == endPoint) ? startPoint : p + 1; - float x2 = scaleX * points [nextIndex].x; - float y2 = scaleY * points [nextIndex].y; - - if (FT_CURVE_TAG (tags [nextIndex]) == FT_Curve_Tag_Conic) - { - x2 = (x + x2) * 0.5f; - y2 = (y + y2) * 0.5f; - } - else - { - ++p; - } - - destShape.quadraticTo (x, y, x2, y2); - } - else if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Cubic) - { - if (p >= endPoint) - return false; - - const int next1 = p + 1; - const int next2 = (p == (endPoint - 1)) ? startPoint : p + 2; - - const float x2 = scaleX * points [next1].x; - const float y2 = scaleY * points [next1].y; - const float x3 = scaleX * points [next2].x; - const float y3 = scaleY * points [next2].y; - - if (FT_CURVE_TAG (tags[next1]) != FT_Curve_Tag_Cubic - || FT_CURVE_TAG (tags[next2]) != FT_Curve_Tag_On) - return false; - - destShape.cubicTo (x, y, x2, y2, x3, y3); - p += 2; - } - } - - destShape.closeSubPath(); - } - - dest.addGlyph (character, destShape, face->glyph->metrics.horiAdvance / height); - - if ((face->face_flags & FT_FACE_FLAG_KERNING) != 0) - addKerning (face, dest, character, glyphIndex); - - return true; - } - - void addKerning (FT_Face face, CustomTypeface& dest, const uint32 character, const uint32 glyphIndex) - { - const float height = (float) (face->ascender - face->descender); - - uint32 rightGlyphIndex; - uint32 rightCharCode = FT_Get_First_Char (face, &rightGlyphIndex); - - while (rightGlyphIndex != 0) - { - FT_Vector kerning; - - if (FT_Get_Kerning (face, glyphIndex, rightGlyphIndex, ft_kerning_unscaled, &kerning) == 0) - { - if (kerning.x != 0) - dest.addKerningPair (character, rightCharCode, kerning.x / height); - } - - rightCharCode = FT_Get_Next_Char (face, rightCharCode, &rightGlyphIndex); - } - } - - // Add a glyph to a font - bool addGlyphToFont (const uint32 character, const String& fontName, - bool bold, bool italic, CustomTypeface& dest) - { - FT_Face face = createFT_Face (fontName, bold, italic); - - return face != 0 && addGlyph (face, dest, character); - } - - //============================================================================== - void getFamilyNames (StringArray& familyNames) const - { - for (int i = 0; i < faces.size(); i++) - familyNames.add (faces[i]->getFamilyName()); - } - - void getMonospacedNames (StringArray& monoSpaced) const - { - for (int i = 0; i < faces.size(); i++) - if (faces[i]->getMonospaced()) - monoSpaced.add (faces[i]->getFamilyName()); - } - - void getSerifNames (StringArray& serif) const - { - for (int i = 0; i < faces.size(); i++) - if (faces[i]->getSerif()) - serif.add (faces[i]->getFamilyName()); - } - - void getSansSerifNames (StringArray& sansSerif) const - { - for (int i = 0; i < faces.size(); i++) - if (! faces[i]->getSerif()) - sansSerif.add (faces[i]->getFamilyName()); - } - - juce_DeclareSingleton_SingleThreaded_Minimal (FreeTypeInterface) - -private: - //============================================================================== - FT_Library ftLib; - FT_Face lastFace; - String lastFontName; - bool lastBold, lastItalic; - OwnedArray faces; -}; - -juce_ImplementSingleton_SingleThreaded (FreeTypeInterface) - - -//============================================================================== -class FreetypeTypeface : public CustomTypeface -{ -public: - FreetypeTypeface (const Font& font) - { - FT_Face face = FreeTypeInterface::getInstance() - ->createFT_Face (font.getTypefaceName(), font.isBold(), font.isItalic()); - - if (face == 0) - { -#if JUCE_DEBUG - String msg ("Failed to create typeface: "); - msg << font.getTypefaceName() << " " << (font.isBold() ? 'B' : ' ') << (font.isItalic() ? 'I' : ' '); - DBG (msg); -#endif - } - else - { - setCharacteristics (font.getTypefaceName(), - face->ascender / (float) (face->ascender - face->descender), - font.isBold(), font.isItalic(), - L' '); - } - } - - bool loadGlyphIfPossible (juce_wchar character) - { - return FreeTypeInterface::getInstance() - ->addGlyphToFont (character, name, isBold, isItalic, *this); - } -}; - -const Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font) -{ - return new FreetypeTypeface (font); -} - -//============================================================================== -const StringArray Font::findAllTypefaceNames() -{ - StringArray s; - FreeTypeInterface::getInstance()->getFamilyNames (s); - s.sort (true); - return s; -} - -namespace -{ - const String pickBestFont (const StringArray& names, - const char* const choicesString) - { - StringArray choices; - choices.addTokens (String (choicesString), ",", String::empty); - choices.trim(); - choices.removeEmptyStrings(); - - int i, j; - for (j = 0; j < choices.size(); ++j) - if (names.contains (choices[j], true)) - return choices[j]; - - for (j = 0; j < choices.size(); ++j) - for (i = 0; i < names.size(); i++) - if (names[i].startsWithIgnoreCase (choices[j])) - return names[i]; - - for (j = 0; j < choices.size(); ++j) - for (i = 0; i < names.size(); i++) - if (names[i].containsIgnoreCase (choices[j])) - return names[i]; - - return names[0]; - } - - const String linux_getDefaultSansSerifFontName() - { - StringArray allFonts; - FreeTypeInterface::getInstance()->getSansSerifNames (allFonts); - - return pickBestFont (allFonts, "Verdana, Bitstream Vera Sans, Luxi Sans, Sans"); - } - - const String linux_getDefaultSerifFontName() - { - StringArray allFonts; - FreeTypeInterface::getInstance()->getSerifNames (allFonts); - - return pickBestFont (allFonts, "Bitstream Vera Serif, Times, Nimbus Roman, Serif"); - } - - const String linux_getDefaultMonospacedFontName() - { - StringArray allFonts; - FreeTypeInterface::getInstance()->getMonospacedNames (allFonts); - - return pickBestFont (allFonts, "Bitstream Vera Sans Mono, Courier, Sans Mono, Mono"); - } -} - -void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSerif, String& defaultFixed, String& /*defaultFallback*/) -{ - defaultSans = linux_getDefaultSansSerifFontName(); - defaultSerif = linux_getDefaultSerifFontName(); - defaultFixed = linux_getDefaultMonospacedFontName(); -} - -#endif +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-10 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +// (This file gets included by juce_linux_NativeCode.cpp, rather than being +// compiled on its own). +#if JUCE_INCLUDED_FILE + + +//============================================================================== +class FreeTypeFontFace +{ +public: + //============================================================================== + enum FontStyle + { + Plain = 0, + Bold = 1, + Italic = 2 + }; + + //============================================================================== + FreeTypeFontFace (const String& familyName) + : hasSerif (false), + monospaced (false) + { + family = familyName; + } + + void setFileName (const String& name, const int faceIndex, FontStyle style) + { + if (names [(int) style].fileName.isEmpty()) + { + names [(int) style].fileName = name; + names [(int) style].faceIndex = faceIndex; + } + } + + const String& getFamilyName() const throw() { return family; } + + const String& getFileName (const int style, int& faceIndex) const throw() + { + faceIndex = names[style].faceIndex; + return names[style].fileName; + } + + void setMonospaced (bool mono) throw() { monospaced = mono; } + bool getMonospaced() const throw() { return monospaced; } + + void setSerif (const bool serif) throw() { hasSerif = serif; } + bool getSerif() const throw() { return hasSerif; } + +private: + //============================================================================== + String family; + + struct FontNameIndex + { + String fileName; + int faceIndex; + }; + + FontNameIndex names[4]; + bool hasSerif, monospaced; +}; + +//============================================================================== +class FreeTypeInterface : public DeletedAtShutdown +{ +public: + //============================================================================== + FreeTypeInterface() + : ftLib (0), + lastFace (0), + lastBold (false), + lastItalic (false) + { + if (FT_Init_FreeType (&ftLib) != 0) + { + ftLib = 0; + DBG ("Failed to initialize FreeType"); + } + + StringArray fontDirs; + fontDirs.addTokens (String::fromUTF8 (getenv ("JUCE_FONT_PATH")), ";,", String::empty); + fontDirs.removeEmptyStrings (true); + + if (fontDirs.size() == 0) + { + const ScopedPointer fontsInfo (XmlDocument::parse (File ("/etc/fonts/fonts.conf"))); + + if (fontsInfo != 0) + { + forEachXmlChildElementWithTagName (*fontsInfo, e, "dir") + { + fontDirs.add (e->getAllSubText().trim()); + } + } + } + + if (fontDirs.size() == 0) + fontDirs.add ("/usr/X11R6/lib/X11/fonts"); + + for (int i = 0; i < fontDirs.size(); ++i) + enumerateFaces (fontDirs[i]); + } + + ~FreeTypeInterface() + { + if (lastFace != 0) + FT_Done_Face (lastFace); + + if (ftLib != 0) + FT_Done_FreeType (ftLib); + + clearSingletonInstance(); + } + + //============================================================================== + FreeTypeFontFace* findOrCreate (const String& familyName, const bool create = false) + { + for (int i = 0; i < faces.size(); i++) + if (faces[i]->getFamilyName() == familyName) + return faces[i]; + + if (! create) + return 0; + + FreeTypeFontFace* newFace = new FreeTypeFontFace (familyName); + faces.add (newFace); + + return newFace; + } + + // Enumerate all font faces available in a given directory + void enumerateFaces (const String& path) + { + File dirPath (path); + if (path.isEmpty() || ! dirPath.isDirectory()) + return; + + DirectoryIterator di (dirPath, true); + + while (di.next()) + { + File possible (di.getFile()); + + if (possible.hasFileExtension ("ttf") + || possible.hasFileExtension ("pfb") + || possible.hasFileExtension ("pcf")) + { + FT_Face face; + int faceIndex = 0; + int numFaces = 0; + + do + { + if (FT_New_Face (ftLib, possible.getFullPathName().toUTF8(), + faceIndex, &face) == 0) + { + if (faceIndex == 0) + numFaces = face->num_faces; + + if ((face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) + { + FreeTypeFontFace* const newFace = findOrCreate (face->family_name, true); + int style = (int) FreeTypeFontFace::Plain; + + if ((face->style_flags & FT_STYLE_FLAG_BOLD) != 0) + style |= (int) FreeTypeFontFace::Bold; + + if ((face->style_flags & FT_STYLE_FLAG_ITALIC) != 0) + style |= (int) FreeTypeFontFace::Italic; + + newFace->setFileName (possible.getFullPathName(), faceIndex, (FreeTypeFontFace::FontStyle) style); + newFace->setMonospaced ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0); + + // Surely there must be a better way to do this? + const String name (face->family_name); + newFace->setSerif (! (name.containsIgnoreCase ("Sans") + || name.containsIgnoreCase ("Verdana") + || name.containsIgnoreCase ("Arial"))); + } + + FT_Done_Face (face); + } + + ++faceIndex; + } + while (faceIndex < numFaces); + } + } + } + + // Create a FreeType face object for a given font + FT_Face createFT_Face (const String& fontName, const bool bold, const bool italic) + { + FT_Face face = 0; + + if (fontName == lastFontName && bold == lastBold && italic == lastItalic) + { + face = lastFace; + } + else + { + if (lastFace != 0) + { + FT_Done_Face (lastFace); + lastFace = 0; + } + + lastFontName = fontName; + lastBold = bold; + lastItalic = italic; + + FreeTypeFontFace* const ftFace = findOrCreate (fontName); + + if (ftFace != 0) + { + int style = (int) FreeTypeFontFace::Plain; + + if (bold) + style |= (int) FreeTypeFontFace::Bold; + + if (italic) + style |= (int) FreeTypeFontFace::Italic; + + int faceIndex; + String fileName (ftFace->getFileName (style, faceIndex)); + + if (fileName.isEmpty()) + { + style ^= (int) FreeTypeFontFace::Bold; + + fileName = ftFace->getFileName (style, faceIndex); + + if (fileName.isEmpty()) + { + style ^= (int) FreeTypeFontFace::Bold; + style ^= (int) FreeTypeFontFace::Italic; + + fileName = ftFace->getFileName (style, faceIndex); + + if (! fileName.length()) + { + style ^= (int) FreeTypeFontFace::Bold; + fileName = ftFace->getFileName (style, faceIndex); + } + } + } + + if (! FT_New_Face (ftLib, fileName.toUTF8(), faceIndex, &lastFace)) + { + face = lastFace; + + // If there isn't a unicode charmap then select the first one. + if (FT_Select_Charmap (face, ft_encoding_unicode)) + FT_Set_Charmap (face, face->charmaps[0]); + } + } + } + + return face; + } + + bool addGlyph (FT_Face face, CustomTypeface& dest, uint32 character) + { + const unsigned int glyphIndex = FT_Get_Char_Index (face, character); + const float height = (float) (face->ascender - face->descender); + const float scaleX = 1.0f / height; + const float scaleY = -1.0f / height; + Path destShape; + + if (FT_Load_Glyph (face, glyphIndex, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM) != 0 + || face->glyph->format != ft_glyph_format_outline) + { + return false; + } + + const FT_Outline* const outline = &face->glyph->outline; + const short* const contours = outline->contours; + const char* const tags = outline->tags; + FT_Vector* const points = outline->points; + + for (int c = 0; c < outline->n_contours; c++) + { + const int startPoint = (c == 0) ? 0 : contours [c - 1] + 1; + const int endPoint = contours[c]; + + for (int p = startPoint; p <= endPoint; p++) + { + const float x = scaleX * points[p].x; + const float y = scaleY * points[p].y; + + if (p == startPoint) + { + if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Conic) + { + float x2 = scaleX * points [endPoint].x; + float y2 = scaleY * points [endPoint].y; + + if (FT_CURVE_TAG (tags[endPoint]) != FT_Curve_Tag_On) + { + x2 = (x + x2) * 0.5f; + y2 = (y + y2) * 0.5f; + } + + destShape.startNewSubPath (x2, y2); + } + else + { + destShape.startNewSubPath (x, y); + } + } + + if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_On) + { + if (p != startPoint) + destShape.lineTo (x, y); + } + else if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Conic) + { + const int nextIndex = (p == endPoint) ? startPoint : p + 1; + float x2 = scaleX * points [nextIndex].x; + float y2 = scaleY * points [nextIndex].y; + + if (FT_CURVE_TAG (tags [nextIndex]) == FT_Curve_Tag_Conic) + { + x2 = (x + x2) * 0.5f; + y2 = (y + y2) * 0.5f; + } + else + { + ++p; + } + + destShape.quadraticTo (x, y, x2, y2); + } + else if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Cubic) + { + if (p >= endPoint) + return false; + + const int next1 = p + 1; + const int next2 = (p == (endPoint - 1)) ? startPoint : p + 2; + + const float x2 = scaleX * points [next1].x; + const float y2 = scaleY * points [next1].y; + const float x3 = scaleX * points [next2].x; + const float y3 = scaleY * points [next2].y; + + if (FT_CURVE_TAG (tags[next1]) != FT_Curve_Tag_Cubic + || FT_CURVE_TAG (tags[next2]) != FT_Curve_Tag_On) + return false; + + destShape.cubicTo (x, y, x2, y2, x3, y3); + p += 2; + } + } + + destShape.closeSubPath(); + } + + dest.addGlyph (character, destShape, face->glyph->metrics.horiAdvance / height); + + if ((face->face_flags & FT_FACE_FLAG_KERNING) != 0) + addKerning (face, dest, character, glyphIndex); + + return true; + } + + void addKerning (FT_Face face, CustomTypeface& dest, const uint32 character, const uint32 glyphIndex) + { + const float height = (float) (face->ascender - face->descender); + + uint32 rightGlyphIndex; + uint32 rightCharCode = FT_Get_First_Char (face, &rightGlyphIndex); + + while (rightGlyphIndex != 0) + { + FT_Vector kerning; + + if (FT_Get_Kerning (face, glyphIndex, rightGlyphIndex, ft_kerning_unscaled, &kerning) == 0) + { + if (kerning.x != 0) + dest.addKerningPair (character, rightCharCode, kerning.x / height); + } + + rightCharCode = FT_Get_Next_Char (face, rightCharCode, &rightGlyphIndex); + } + } + + // Add a glyph to a font + bool addGlyphToFont (const uint32 character, const String& fontName, + bool bold, bool italic, CustomTypeface& dest) + { + FT_Face face = createFT_Face (fontName, bold, italic); + + return face != 0 && addGlyph (face, dest, character); + } + + //============================================================================== + void getFamilyNames (StringArray& familyNames) const + { + for (int i = 0; i < faces.size(); i++) + familyNames.add (faces[i]->getFamilyName()); + } + + void getMonospacedNames (StringArray& monoSpaced) const + { + for (int i = 0; i < faces.size(); i++) + if (faces[i]->getMonospaced()) + monoSpaced.add (faces[i]->getFamilyName()); + } + + void getSerifNames (StringArray& serif) const + { + for (int i = 0; i < faces.size(); i++) + if (faces[i]->getSerif()) + serif.add (faces[i]->getFamilyName()); + } + + void getSansSerifNames (StringArray& sansSerif) const + { + for (int i = 0; i < faces.size(); i++) + if (! faces[i]->getSerif()) + sansSerif.add (faces[i]->getFamilyName()); + } + + juce_DeclareSingleton_SingleThreaded_Minimal (FreeTypeInterface) + +private: + //============================================================================== + FT_Library ftLib; + FT_Face lastFace; + String lastFontName; + bool lastBold, lastItalic; + OwnedArray faces; +}; + +juce_ImplementSingleton_SingleThreaded (FreeTypeInterface) + + +//============================================================================== +class FreetypeTypeface : public CustomTypeface +{ +public: + FreetypeTypeface (const Font& font) + { + FT_Face face = FreeTypeInterface::getInstance() + ->createFT_Face (font.getTypefaceName(), font.isBold(), font.isItalic()); + + if (face == 0) + { +#if JUCE_DEBUG + String msg ("Failed to create typeface: "); + msg << font.getTypefaceName() << " " << (font.isBold() ? 'B' : ' ') << (font.isItalic() ? 'I' : ' '); + DBG (msg); +#endif + } + else + { + setCharacteristics (font.getTypefaceName(), + face->ascender / (float) (face->ascender - face->descender), + font.isBold(), font.isItalic(), + L' '); + } + } + + bool loadGlyphIfPossible (juce_wchar character) + { + return FreeTypeInterface::getInstance() + ->addGlyphToFont (character, name, isBold, isItalic, *this); + } +}; + +const Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font) +{ + return new FreetypeTypeface (font); +} + +//============================================================================== +const StringArray Font::findAllTypefaceNames() +{ + StringArray s; + FreeTypeInterface::getInstance()->getFamilyNames (s); + s.sort (true); + return s; +} + +namespace +{ + const String pickBestFont (const StringArray& names, + const char* const choicesString) + { + StringArray choices; + choices.addTokens (String (choicesString), ",", String::empty); + choices.trim(); + choices.removeEmptyStrings(); + + int i, j; + for (j = 0; j < choices.size(); ++j) + if (names.contains (choices[j], true)) + return choices[j]; + + for (j = 0; j < choices.size(); ++j) + for (i = 0; i < names.size(); i++) + if (names[i].startsWithIgnoreCase (choices[j])) + return names[i]; + + for (j = 0; j < choices.size(); ++j) + for (i = 0; i < names.size(); i++) + if (names[i].containsIgnoreCase (choices[j])) + return names[i]; + + return names[0]; + } + + const String linux_getDefaultSansSerifFontName() + { + StringArray allFonts; + FreeTypeInterface::getInstance()->getSansSerifNames (allFonts); + + return pickBestFont (allFonts, "Verdana, Bitstream Vera Sans, Luxi Sans, Sans"); + } + + const String linux_getDefaultSerifFontName() + { + StringArray allFonts; + FreeTypeInterface::getInstance()->getSerifNames (allFonts); + + return pickBestFont (allFonts, "Bitstream Vera Serif, Times, Nimbus Roman, Serif"); + } + + const String linux_getDefaultMonospacedFontName() + { + StringArray allFonts; + FreeTypeInterface::getInstance()->getMonospacedNames (allFonts); + + return pickBestFont (allFonts, "Bitstream Vera Sans Mono, Courier, Sans Mono, Mono"); + } +} + +void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSerif, String& defaultFixed, String& /*defaultFallback*/) +{ + defaultSans = linux_getDefaultSansSerifFontName(); + defaultSerif = linux_getDefaultSerifFontName(); + defaultFixed = linux_getDefaultMonospacedFontName(); +} + +#endif diff --git a/src/native/linux/juce_linux_Windowing.cpp b/src/native/linux/juce_linux_Windowing.cpp index 8bc4599b8f..2407e70a88 100644 --- a/src/native/linux/juce_linux_Windowing.cpp +++ b/src/native/linux/juce_linux_Windowing.cpp @@ -810,12 +810,12 @@ public: const Rectangle getBounds() const { return Rectangle (wx, wy, ww, wh); } const Point getScreenPosition() const { return Point (wx, wy); } - const Point relativePositionToGlobal (const Point& relativePosition) + const Point localToGlobal (const Point& relativePosition) { return relativePosition + getScreenPosition(); } - const Point globalPositionToRelative (const Point& screenPosition) + const Point globalToLocal (const Point& screenPosition) { return screenPosition - getScreenPosition(); } diff --git a/src/native/mac/juce_iphone_UIViewComponentPeer.mm b/src/native/mac/juce_iphone_UIViewComponentPeer.mm index 3c01588f24..97bb669daf 100644 --- a/src/native/mac/juce_iphone_UIViewComponentPeer.mm +++ b/src/native/mac/juce_iphone_UIViewComponentPeer.mm @@ -109,8 +109,8 @@ public: const Rectangle getBounds() const; const Rectangle getBounds (const bool global) const; const Point getScreenPosition() const; - const Point relativePositionToGlobal (const Point& relativePosition); - const Point globalPositionToRelative (const Point& screenPosition); + const Point localToGlobal (const Point& relativePosition); + const Point globalToLocal (const Point& screenPosition); void setAlpha (float newAlpha); void setMinimised (bool shouldBeMinimised); bool isMinimised() const; @@ -539,12 +539,12 @@ const Point UIViewComponentPeer::getScreenPosition() const return getBounds (true).getPosition(); } -const Point UIViewComponentPeer::relativePositionToGlobal (const Point& relativePosition) +const Point UIViewComponentPeer::localToGlobal (const Point& relativePosition) { return relativePosition + getScreenPosition(); } -const Point UIViewComponentPeer::globalPositionToRelative (const Point& screenPosition) +const Point UIViewComponentPeer::globalToLocal (const Point& screenPosition) { return screenPosition - getScreenPosition(); } @@ -863,7 +863,7 @@ void UIViewComponentPeer::globalFocusChanged (Component*) { Component* comp = dynamic_cast (target); - Point pos (comp->relativePositionToOtherComponent (component, Point())); + Point pos (component->getLocalPoint (comp, Point())); view->hiddenTextView.frame = CGRectMake (pos.getX(), pos.getY(), 0, 0); updateHiddenTextContent (target); diff --git a/src/native/mac/juce_mac_NSViewComponent.mm b/src/native/mac/juce_mac_NSViewComponent.mm index 52f09f245e..18d8d63142 100644 --- a/src/native/mac/juce_mac_NSViewComponent.mm +++ b/src/native/mac/juce_mac_NSViewComponent.mm @@ -76,7 +76,7 @@ public: if (topComp->getPeer() != 0) { - const Point pos (owner->relativePositionToOtherComponent (topComp, Point())); + const Point pos (topComp->getLocalPoint (owner, Point())); NSRect r = NSMakeRect ((float) pos.getX(), (float) pos.getY(), (float) owner->getWidth(), (float) owner->getHeight()); r.origin.y = [[view superview] frame].size.height - (r.origin.y + r.size.height); diff --git a/src/native/mac/juce_mac_NSViewComponentPeer.mm b/src/native/mac/juce_mac_NSViewComponentPeer.mm index fe9139bb34..c8d1ed9f54 100644 --- a/src/native/mac/juce_mac_NSViewComponentPeer.mm +++ b/src/native/mac/juce_mac_NSViewComponentPeer.mm @@ -158,8 +158,8 @@ public: const Rectangle getBounds (const bool global) const; const Rectangle getBounds() const; const Point getScreenPosition() const; - const Point relativePositionToGlobal (const Point& relativePosition); - const Point globalPositionToRelative (const Point& screenPosition); + const Point localToGlobal (const Point& relativePosition); + const Point globalToLocal (const Point& screenPosition); void setAlpha (float newAlpha); void setMinimised (bool shouldBeMinimised); bool isMinimised() const; @@ -1050,12 +1050,12 @@ const Point NSViewComponentPeer::getScreenPosition() const return getBounds (true).getPosition(); } -const Point NSViewComponentPeer::relativePositionToGlobal (const Point& relativePosition) +const Point NSViewComponentPeer::localToGlobal (const Point& relativePosition) { return relativePosition + getScreenPosition(); } -const Point NSViewComponentPeer::globalPositionToRelative (const Point& screenPosition) +const Point NSViewComponentPeer::globalToLocal (const Point& screenPosition) { return screenPosition - getScreenPosition(); } diff --git a/src/native/mac/juce_mac_WebBrowserComponent.mm b/src/native/mac/juce_mac_WebBrowserComponent.mm index 0993953b44..25513d47ce 100644 --- a/src/native/mac/juce_mac_WebBrowserComponent.mm +++ b/src/native/mac/juce_mac_WebBrowserComponent.mm @@ -153,6 +153,14 @@ public: [webView reload: nil]; } + void mouseMove (const MouseEvent&) + { + // WebKit doesn't capture mouse-moves itself, so it seems the only way to make + // them work is to push them via this non-public method.. + if ([webView respondsToSelector: @selector (_updateMouseoverWithFakeEvent)]) + [webView performSelector: @selector (_updateMouseoverWithFakeEvent)]; + } + private: WebView* webView; DownloadClickDetector* clickListener; diff --git a/src/native/windows/juce_win32_ActiveXComponent.cpp b/src/native/windows/juce_win32_ActiveXComponent.cpp index e1205355d9..7cdc412e21 100644 --- a/src/native/windows/juce_win32_ActiveXComponent.cpp +++ b/src/native/windows/juce_win32_ActiveXComponent.cpp @@ -256,8 +256,7 @@ public: if (topComp->getPeer() != 0) { - const Point pos (owner.relativePositionToOtherComponent (topComp, Point())); - + const Point pos (topComp->getLocalPoint (&owner, Point())); owner.setControlBounds (Rectangle (pos.getX(), pos.getY(), owner.getWidth(), owner.getHeight())); } } @@ -356,7 +355,7 @@ bool ActiveXControlComponent::createControl (const void* controlIID) if (dynamic_cast (peer) != 0) { - const Point pos (relativePositionToOtherComponent (getTopLevelComponent(), Point())); + const Point pos (getTopLevelComponent()->getLocalPoint (this, Point())); HWND hwnd = (HWND) peer->getNativeHandle(); ScopedPointer newControl (new Pimpl (hwnd, *this)); diff --git a/src/native/windows/juce_win32_Windowing.cpp b/src/native/windows/juce_win32_Windowing.cpp index 52608c7532..5123bc8ad6 100644 --- a/src/native/windows/juce_win32_Windowing.cpp +++ b/src/native/windows/juce_win32_Windowing.cpp @@ -649,12 +649,12 @@ public: r.top + windowBorder.getTop()); } - const Point relativePositionToGlobal (const Point& relativePosition) + const Point localToGlobal (const Point& relativePosition) { return relativePosition + getScreenPosition(); } - const Point globalPositionToRelative (const Point& screenPosition) + const Point globalToLocal (const Point& screenPosition) { return screenPosition - getScreenPosition(); } @@ -1745,7 +1745,7 @@ private: HRESULT __stdcall DragEnter (IDataObject* pDataObject, DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) { updateFileList (pDataObject); - owner->handleFileDragMove (files, owner->globalPositionToRelative (Point (mousePos.x, mousePos.y))); + owner->handleFileDragMove (files, owner->globalToLocal (Point (mousePos.x, mousePos.y))); *pdwEffect = DROPEFFECT_COPY; return S_OK; } @@ -1758,7 +1758,7 @@ private: HRESULT __stdcall DragOver (DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) { - owner->handleFileDragMove (files, owner->globalPositionToRelative (Point (mousePos.x, mousePos.y))); + owner->handleFileDragMove (files, owner->globalToLocal (Point (mousePos.x, mousePos.y))); *pdwEffect = DROPEFFECT_COPY; return S_OK; } @@ -1766,7 +1766,7 @@ private: HRESULT __stdcall Drop (IDataObject* pDataObject, DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) { updateFileList (pDataObject); - owner->handleFileDragDrop (files, owner->globalPositionToRelative (Point (mousePos.x, mousePos.y))); + owner->handleFileDragDrop (files, owner->globalToLocal (Point (mousePos.x, mousePos.y))); *pdwEffect = DROPEFFECT_COPY; return S_OK; }