|
- /*
- ==============================================================================
-
- This file is part of the JUCE library - "Jules' Utility Class Extensions"
- Copyright 2004-7 by Raw Material Software ltd.
-
- ------------------------------------------------------------------------------
-
- JUCE can be redistributed and/or modified under the terms of the
- GNU General Public License, as published by the Free Software Foundation;
- either version 2 of the License, or (at your option) any later version.
-
- 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.
-
- You should have received a copy of the GNU General Public License
- along with JUCE; if not, visit www.gnu.org/licenses or write to the
- Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- Boston, MA 02111-1307 USA
-
- ------------------------------------------------------------------------------
-
- If you'd like to release a closed-source product which uses JUCE, commercial
- licenses are also available: visit www.rawmaterialsoftware.com/juce for
- more information.
-
- ==============================================================================
- */
-
- #include "../../../../juce_core/basics/juce_StandardHeader.h"
-
- BEGIN_JUCE_NAMESPACE
-
- #include "../../../application/juce_Application.h"
- #include "../juce_Component.h"
- #include "../juce_ComponentDeletionWatcher.h"
- #include "../juce_Desktop.h"
- #include "../../../events/juce_MessageManager.h"
- #include "../../../../juce_core/basics/juce_Time.h"
- #include "../../../../juce_core/basics/juce_Random.h"
- #include "../layout/juce_ComponentBoundsConstrainer.h"
-
-
- //#define JUCE_ENABLE_REPAINT_DEBUGGING 1
-
-
- //==============================================================================
- // these are over in juce_component.cpp
- extern int64 juce_recentMouseDownTimes[4];
- extern int juce_recentMouseDownX [4];
- extern int juce_recentMouseDownY [4];
- extern Component* juce_recentMouseDownComponent [4];
- extern int juce_LastMousePosX;
- extern int juce_LastMousePosY;
- extern int juce_MouseClickCounter;
- extern bool juce_MouseHasMovedSignificantlySincePressed;
-
- static const int fakeMouseMoveMessage = 0x7fff00ff;
-
- static VoidArray heavyweightPeers (4);
-
-
- //==============================================================================
- ComponentPeer::ComponentPeer (Component* const component_,
- const int styleFlags_)
- : component (component_),
- styleFlags (styleFlags_),
- lastPaintTime (0),
- constrainer (0),
- lastFocusedComponent (0),
- fakeMouseMessageSent (false),
- isWindowMinimised (false)
- {
- heavyweightPeers.add (this);
- }
-
- ComponentPeer::~ComponentPeer()
- {
- heavyweightPeers.removeValue (this);
- }
-
- //==============================================================================
- int ComponentPeer::getNumPeers() throw()
- {
- return heavyweightPeers.size();
- }
-
- ComponentPeer* ComponentPeer::getPeer (const int index) throw()
- {
- return (ComponentPeer*) heavyweightPeers [index];
- }
-
- ComponentPeer* ComponentPeer::getPeerFor (const Component* const component) throw()
- {
- for (int i = heavyweightPeers.size(); --i >= 0;)
- {
- ComponentPeer* const peer = (ComponentPeer*) heavyweightPeers.getUnchecked(i);
-
- if (peer->getComponent() == component)
- return peer;
- }
-
- return 0;
- }
-
- bool ComponentPeer::isValidPeer (const ComponentPeer* const peer) throw()
- {
- return heavyweightPeers.contains (const_cast <ComponentPeer*> (peer));
- }
-
- void ComponentPeer::updateCurrentModifiers()
- {
- ModifierKeys::updateCurrentModifiers();
- }
-
- //==============================================================================
- void ComponentPeer::handleMouseEnter (int x, int y, const int64 time)
- {
- jassert (component->isValidComponent());
- updateCurrentModifiers();
-
- Component* c = component->getComponentAt (x, y);
- const ComponentDeletionWatcher deletionChecker (component);
-
- if (c != Component::componentUnderMouse && Component::componentUnderMouse != 0)
- {
- jassert (Component::componentUnderMouse->isValidComponent());
-
- const int oldX = x;
- const int oldY = y;
- component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
- Component::componentUnderMouse->internalMouseExit (x, y, time);
- Component::componentUnderMouse = 0;
-
- if (deletionChecker.hasBeenDeleted())
- return;
-
- c = component->getComponentAt (oldX, oldY);
- }
-
- Component::componentUnderMouse = c;
-
- if (Component::componentUnderMouse != 0)
- {
- component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
- Component::componentUnderMouse->internalMouseEnter (x, y, time);
- }
- }
-
- void ComponentPeer::handleMouseMove (int x, int y, const int64 time)
- {
- jassert (component->isValidComponent());
- updateCurrentModifiers();
-
- fakeMouseMessageSent = false;
-
- const ComponentDeletionWatcher deletionChecker (component);
- Component* c = component->getComponentAt (x, y);
-
- if (c != Component::componentUnderMouse)
- {
- const int oldX = x;
- const int oldY = y;
-
- if (Component::componentUnderMouse != 0)
- {
- component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
- Component::componentUnderMouse->internalMouseExit (x, y, time);
- x = oldX;
- y = oldY;
-
- Component::componentUnderMouse = 0;
-
- if (deletionChecker.hasBeenDeleted())
- return; // if this window has just been deleted..
-
- c = component->getComponentAt (x, y);
- }
-
- Component::componentUnderMouse = c;
-
- if (c != 0)
- {
- component->relativePositionToOtherComponent (c, x, y);
- c->internalMouseEnter (x, y, time);
- x = oldX;
- y = oldY;
-
- if (deletionChecker.hasBeenDeleted())
- return; // if this window has just been deleted..
- }
- }
-
- if (Component::componentUnderMouse != 0)
- {
- component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
- Component::componentUnderMouse->internalMouseMove (x, y, time);
- }
- }
-
- void ComponentPeer::handleMouseDown (int x, int y, const int64 time)
- {
- ++juce_MouseClickCounter;
-
- updateCurrentModifiers();
-
- int numMouseButtonsDown = 0;
-
- if (ModifierKeys::getCurrentModifiers().isLeftButtonDown())
- ++numMouseButtonsDown;
-
- if (ModifierKeys::getCurrentModifiers().isRightButtonDown())
- ++numMouseButtonsDown;
-
- if (ModifierKeys::getCurrentModifiers().isMiddleButtonDown())
- ++numMouseButtonsDown;
-
- if (numMouseButtonsDown == 1)
- {
- Component::componentUnderMouse = component->getComponentAt (x, y);
-
- if (Component::componentUnderMouse != 0)
- {
- // can't set these in the mouseDownInt() method, because it's re-entrant, so do it here..
-
- for (int i = numElementsInArray (juce_recentMouseDownTimes); --i > 0;)
- {
- juce_recentMouseDownTimes [i] = juce_recentMouseDownTimes [i - 1];
- juce_recentMouseDownX [i] = juce_recentMouseDownX [i - 1];
- juce_recentMouseDownY [i] = juce_recentMouseDownY [i - 1];
- juce_recentMouseDownComponent [i] = juce_recentMouseDownComponent [i - 1];
- }
-
- juce_recentMouseDownTimes[0] = time;
- juce_recentMouseDownX[0] = x;
- juce_recentMouseDownY[0] = y;
- juce_recentMouseDownComponent[0] = Component::componentUnderMouse;
- relativePositionToGlobal (juce_recentMouseDownX[0], juce_recentMouseDownY[0]);
- juce_MouseHasMovedSignificantlySincePressed = false;
-
- component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
- Component::componentUnderMouse->internalMouseDown (x, y);
- }
- }
- }
-
- void ComponentPeer::handleMouseDrag (int x, int y, const int64 time)
- {
- updateCurrentModifiers();
-
- if (Component::componentUnderMouse != 0)
- {
- component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
-
- Component::componentUnderMouse->internalMouseDrag (x, y, time);
- }
- }
-
- void ComponentPeer::handleMouseUp (const int oldModifiers, int x, int y, const int64 time)
- {
- updateCurrentModifiers();
-
- int numMouseButtonsDown = 0;
-
- if ((oldModifiers & ModifierKeys::leftButtonModifier) != 0)
- ++numMouseButtonsDown;
-
- if ((oldModifiers & ModifierKeys::rightButtonModifier) != 0)
- ++numMouseButtonsDown;
-
- if ((oldModifiers & ModifierKeys::middleButtonModifier) != 0)
- ++numMouseButtonsDown;
-
- if (numMouseButtonsDown == 1)
- {
- const ComponentDeletionWatcher deletionChecker (component);
- Component* c = component->getComponentAt (x, y);
-
- if (c != Component::componentUnderMouse)
- {
- const int oldX = x;
- const int oldY = y;
-
- if (Component::componentUnderMouse != 0)
- {
- component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
- Component::componentUnderMouse->internalMouseUp (oldModifiers, x, y, time);
- x = oldX;
- y = oldY;
-
- if (Component::componentUnderMouse != 0)
- Component::componentUnderMouse->internalMouseExit (x, y, time);
-
- if (deletionChecker.hasBeenDeleted())
- return;
-
- c = component->getComponentAt (oldX, oldY);
- }
-
- Component::componentUnderMouse = c;
-
- if (Component::componentUnderMouse != 0)
- {
- component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
- Component::componentUnderMouse->internalMouseEnter (x, y, time);
- }
- }
- else
- {
- if (Component::componentUnderMouse != 0)
- {
- component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
- Component::componentUnderMouse->internalMouseUp (oldModifiers, x, y, time);
- }
- }
- }
- }
-
- void ComponentPeer::handleMouseExit (int x, int y, const int64 time)
- {
- jassert (component->isValidComponent());
- updateCurrentModifiers();
-
- if (Component::componentUnderMouse != 0)
- {
- component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
-
- Component::componentUnderMouse->internalMouseExit (x, y, time);
- Component::componentUnderMouse = 0;
- }
- }
-
- void ComponentPeer::handleMouseWheel (const int amountX, const int amountY, const int64 time)
- {
- updateCurrentModifiers();
-
- if (Component::componentUnderMouse != 0)
- Component::componentUnderMouse->internalMouseWheel (amountX, amountY, time);
- }
-
- void ComponentPeer::sendFakeMouseMove() throw()
- {
- if ((! fakeMouseMessageSent)
- && component->flags.hasHeavyweightPeerFlag
- && ! ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown())
- {
- int realX, realY, realW, realH;
- getBounds (realX, realY, realW, realH);
-
- component->bounds_.setBounds (realX, realY, realW, realH);
-
- int x, y;
- component->getMouseXYRelative (x, y);
-
- if (x >= 0
- && y >= 0
- && x < component->getWidth()
- && y < component->getHeight()
- && contains (x, y, false))
- {
- postMessage (new Message (fakeMouseMoveMessage, x, y, 0));
- }
-
- fakeMouseMessageSent = true;
- }
- }
-
- void ComponentPeer::handleMessage (const Message& message)
- {
- if (message.intParameter1 == fakeMouseMoveMessage)
- {
- handleMouseMove (message.intParameter2,
- message.intParameter3,
- Time::currentTimeMillis());
- }
- }
-
- //==============================================================================
- void ComponentPeer::handlePaint (LowLevelGraphicsContext& contextToPaintTo)
- {
- Graphics g (&contextToPaintTo);
-
- #if JUCE_ENABLE_REPAINT_DEBUGGING
- g.saveState();
- #endif
-
- JUCE_TRY
- {
- component->paintEntireComponent (g);
- }
- JUCE_CATCH_EXCEPTION
-
- #if JUCE_ENABLE_REPAINT_DEBUGGING
- // enabling this code will fill all areas that get repainted with a colour overlay, to show
- // clearly when things are being repainted.
- {
- g.restoreState();
-
- g.fillAll (Colour ((uint8) Random::getSystemRandom().nextInt (255),
- (uint8) Random::getSystemRandom().nextInt (255),
- (uint8) Random::getSystemRandom().nextInt (255),
- (uint8) 0x50));
- }
- #endif
- }
-
- bool ComponentPeer::handleKeyPress (const int keyCode,
- const juce_wchar textCharacter)
- {
- updateCurrentModifiers();
-
- Component* target = Component::currentlyFocusedComponent->isValidComponent()
- ? Component::currentlyFocusedComponent
- : component;
-
- if (target->isCurrentlyBlockedByAnotherModalComponent())
- {
- Component* const currentModalComp = Component::getCurrentlyModalComponent();
-
- if (currentModalComp != 0)
- target = currentModalComp;
- }
-
- const KeyPress keyInfo (keyCode,
- ModifierKeys::getCurrentModifiers().getRawFlags()
- & ModifierKeys::allKeyboardModifiers,
- textCharacter);
-
- bool keyWasUsed = false;
-
- while (target != 0)
- {
- const ComponentDeletionWatcher deletionChecker (target);
-
- keyWasUsed = target->keyPressed (keyInfo);
-
- if (keyWasUsed || deletionChecker.hasBeenDeleted())
- break;
-
- if (target->keyListeners_ != 0)
- {
- for (int i = target->keyListeners_->size(); --i >= 0;)
- {
- keyWasUsed = ((KeyListener*) target->keyListeners_->getUnchecked(i))->keyPressed (keyInfo, target);
-
- if (keyWasUsed || deletionChecker.hasBeenDeleted())
- return keyWasUsed;
-
- i = jmin (i, target->keyListeners_->size());
- }
- }
-
- if (keyInfo.isKeyCode (KeyPress::tabKey) && Component::getCurrentlyFocusedComponent() != 0)
- {
- Component::getCurrentlyFocusedComponent()
- ->moveKeyboardFocusToSibling (! keyInfo.getModifiers().isShiftDown());
-
- keyWasUsed = true;
- break;
- }
-
- target = target->parentComponent_;
- }
-
- return keyWasUsed;
- }
-
- bool ComponentPeer::handleKeyUpOrDown()
- {
- updateCurrentModifiers();
-
- Component* target = Component::currentlyFocusedComponent->isValidComponent()
- ? Component::currentlyFocusedComponent
- : component;
-
- if (target->isCurrentlyBlockedByAnotherModalComponent())
- {
- Component* const currentModalComp = Component::getCurrentlyModalComponent();
-
- if (currentModalComp != 0)
- target = currentModalComp;
- }
-
- bool keyWasUsed = false;
-
- while (target != 0)
- {
- const ComponentDeletionWatcher deletionChecker (target);
-
- keyWasUsed = target->keyStateChanged();
-
- if (keyWasUsed || deletionChecker.hasBeenDeleted())
- break;
-
- if (target->keyListeners_ != 0)
- {
- for (int i = target->keyListeners_->size(); --i >= 0;)
- {
- keyWasUsed = ((KeyListener*) target->keyListeners_->getUnchecked(i))->keyStateChanged (target);
-
- if (keyWasUsed || deletionChecker.hasBeenDeleted())
- return keyWasUsed;
-
- i = jmin (i, target->keyListeners_->size());
- }
- }
-
- target = target->parentComponent_;
- }
-
- return keyWasUsed;
- }
-
- void ComponentPeer::handleModifierKeysChange()
- {
- updateCurrentModifiers();
-
- Component* target = Component::getComponentUnderMouse();
-
- if (target == 0)
- target = Component::getCurrentlyFocusedComponent();
-
- if (target == 0)
- target = component;
-
- if (target->isValidComponent())
- target->internalModifierKeysChanged();
- }
-
- //==============================================================================
- void ComponentPeer::handleBroughtToFront()
- {
- updateCurrentModifiers();
-
- if (component != 0)
- component->internalBroughtToFront();
- }
-
- void ComponentPeer::setConstrainer (ComponentBoundsConstrainer* newConstrainer)
- {
- constrainer = newConstrainer;
- }
-
- void ComponentPeer::handleMovedOrResized()
- {
- jassert (component->isValidComponent());
- updateCurrentModifiers();
-
- const bool nowMinimised = isMinimised();
-
- if (component->flags.hasHeavyweightPeerFlag && ! nowMinimised)
- {
- const ComponentDeletionWatcher deletionChecker (component);
-
- int realX, realY, realW, realH;
- getBounds (realX, realY, realW, realH);
-
- const bool wasMoved = (component->getX() != realX || component->getY() != realY);
- const bool wasResized = (component->getWidth() != realW || component->getHeight() != realH);
-
- if (wasMoved || wasResized)
- {
- component->bounds_.setBounds (realX, realY, realW, realH);
-
- if (wasResized)
- component->repaint();
-
- component->sendMovedResizedMessages (wasMoved, wasResized);
-
- if (deletionChecker.hasBeenDeleted())
- return;
- }
- }
-
- if (isWindowMinimised != nowMinimised)
- {
- isWindowMinimised = nowMinimised;
- component->minimisationStateChanged (nowMinimised);
- component->sendVisibilityChangeMessage();
- }
-
- if (! isFullScreen())
- lastNonFullscreenBounds = component->getBounds();
- }
-
- void ComponentPeer::handleFocusGain()
- {
- updateCurrentModifiers();
-
- if (component->isParentOf (lastFocusedComponent))
- {
- Component::currentlyFocusedComponent = lastFocusedComponent;
- Desktop::getInstance().triggerFocusCallback();
- lastFocusedComponent->internalFocusGain (Component::focusChangedDirectly);
- }
- else
- {
- if (! component->isCurrentlyBlockedByAnotherModalComponent())
- {
- component->grabKeyboardFocus();
- }
- else
- {
- Component* const currentModalComp = Component::getCurrentlyModalComponent();
-
- if (currentModalComp != 0)
- currentModalComp->toFront (! currentModalComp->hasKeyboardFocus (true));
- }
- }
- }
-
- void ComponentPeer::handleFocusLoss()
- {
- updateCurrentModifiers();
-
- if (component->hasKeyboardFocus (true))
- {
- lastFocusedComponent = Component::currentlyFocusedComponent;
-
- if (lastFocusedComponent != 0)
- {
- Component::currentlyFocusedComponent = 0;
- Desktop::getInstance().triggerFocusCallback();
- lastFocusedComponent->internalFocusLoss (Component::focusChangedByMouseClick);
- }
- }
- }
-
- Component* ComponentPeer::getLastFocusedSubcomponent() const
- {
- return (component->isParentOf (lastFocusedComponent) && lastFocusedComponent->isShowing())
- ? lastFocusedComponent
- : component;
- }
-
- void ComponentPeer::handleScreenSizeChange()
- {
- updateCurrentModifiers();
-
- component->parentSizeChanged();
- handleMovedOrResized();
- }
-
- //==============================================================================
- void ComponentPeer::handleFilesDropped (int x, int y, const StringArray& files)
- {
- updateCurrentModifiers();
-
- component->internalFilesDropped (x, y, files);
- }
-
- void ComponentPeer::handleUserClosingWindow()
- {
- updateCurrentModifiers();
-
- component->userTriedToCloseWindow();
- }
-
- //==============================================================================
- void ComponentPeer::clearMaskedRegion()
- {
- maskedRegion.clear();
- }
-
- void ComponentPeer::addMaskedRegion (int x, int y, int w, int h)
- {
- maskedRegion.add (x, y, w, h);
- }
-
-
- END_JUCE_NAMESPACE
|