|
- /*
- ==============================================================================
-
- 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.
-
- ==============================================================================
- */
-
- #ifndef __JUCE_MAC_CARBONVIEWWRAPPERCOMPONENT_JUCEHEADER__
- #define __JUCE_MAC_CARBONVIEWWRAPPERCOMPONENT_JUCEHEADER__
-
-
- //==============================================================================
- /**
- Creates a floating carbon window that can be used to hold a carbon UI.
-
- This is a handy class that's designed to be inlined where needed, e.g.
- in the audio plugin hosting code.
- */
- class CarbonViewWrapperComponent : public Component,
- public ComponentMovementWatcher,
- public Timer
- {
- public:
- CarbonViewWrapperComponent()
- : ComponentMovementWatcher (this),
- wrapperWindow (0),
- embeddedView (0),
- recursiveResize (false)
- {
- }
-
- virtual ~CarbonViewWrapperComponent()
- {
- jassert (embeddedView == 0); // must call deleteWindow() in the subclass's destructor!
- }
-
- virtual HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) = 0;
- virtual void removeView (HIViewRef embeddedView) = 0;
- virtual void mouseDown (int x, int y) {}
- virtual void paint() {}
-
- virtual bool getEmbeddedViewSize (int& w, int& h)
- {
- if (embeddedView == 0)
- return false;
-
- HIRect bounds;
- HIViewGetBounds (embeddedView, &bounds);
- w = jmax (1, roundFloatToInt (bounds.size.width));
- h = jmax (1, roundFloatToInt (bounds.size.height));
- return true;
- }
-
- void createWindow()
- {
- if (wrapperWindow == 0)
- {
- Rect r;
- r.left = getScreenX();
- r.top = getScreenY();
- r.right = r.left + getWidth();
- r.bottom = r.top + getHeight();
-
- CreateNewWindow (kDocumentWindowClass,
- (WindowAttributes) (kWindowStandardHandlerAttribute | kWindowCompositingAttribute
- | kWindowNoShadowAttribute | kWindowNoTitleBarAttribute),
- &r, &wrapperWindow);
-
- jassert (wrapperWindow != 0);
- if (wrapperWindow == 0)
- return;
-
- NSWindow* carbonWindow = [[NSWindow alloc] initWithWindowRef: wrapperWindow];
- NSWindow* ownerWindow = [((NSView*) getWindowHandle()) window];
-
- [ownerWindow addChildWindow: carbonWindow
- ordered: NSWindowAbove];
-
- embeddedView = attachView (wrapperWindow, HIViewGetRoot (wrapperWindow));
-
- EventTypeSpec windowEventTypes[] = { { kEventClassWindow, kEventWindowGetClickActivation },
- { kEventClassWindow, kEventWindowHandleDeactivate } };
-
- EventHandlerUPP upp = NewEventHandlerUPP (carbonEventCallback);
- InstallWindowEventHandler (wrapperWindow, upp,
- sizeof (windowEventTypes) / sizeof (EventTypeSpec),
- windowEventTypes, this, &eventHandlerRef);
-
- setOurSizeToEmbeddedViewSize();
- setEmbeddedWindowToOurSize();
-
- creationTime = Time::getCurrentTime();
- }
- }
-
- void deleteWindow()
- {
- removeView (embeddedView);
- embeddedView = 0;
-
- if (wrapperWindow != 0)
- {
- RemoveEventHandler (eventHandlerRef);
- DisposeWindow (wrapperWindow);
- wrapperWindow = 0;
- }
- }
-
- //==============================================================================
- void setOurSizeToEmbeddedViewSize()
- {
- int w, h;
- if (getEmbeddedViewSize (w, h))
- {
- if (w != getWidth() || h != getHeight())
- {
- startTimer (50);
-
- setSize (w, h);
- if (getParentComponent() != 0)
- getParentComponent()->setSize (w, h);
- }
- else
- {
- startTimer (jlimit (50, 500, getTimerInterval() + 20));
- }
- }
- else
- {
- stopTimer();
- }
- }
-
- void setEmbeddedWindowToOurSize()
- {
- if (! recursiveResize)
- {
- recursiveResize = true;
-
- if (embeddedView != 0)
- {
- HIRect r;
- r.origin.x = 0;
- r.origin.y = 0;
- r.size.width = (float) getWidth();
- r.size.height = (float) getHeight();
- HIViewSetFrame (embeddedView, &r);
- }
-
- if (wrapperWindow != 0)
- {
- Rect wr;
- wr.left = getScreenX();
- wr.top = getScreenY();
- wr.right = wr.left + getWidth();
- wr.bottom = wr.top + getHeight();
-
- SetWindowBounds (wrapperWindow, kWindowContentRgn, &wr);
- ShowWindow (wrapperWindow);
- }
-
- recursiveResize = false;
- }
- }
-
- void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
- {
- setEmbeddedWindowToOurSize();
- }
-
- void componentPeerChanged()
- {
- deleteWindow();
- createWindow();
- }
-
- void componentVisibilityChanged (Component&)
- {
- if (isShowing())
- createWindow();
- else
- deleteWindow();
-
- setEmbeddedWindowToOurSize();
- }
-
- void timerCallback()
- {
- setOurSizeToEmbeddedViewSize();
-
- // To avoid strange overpainting problems when the UI is first opened, we'll
- // repaint it a few times during the first second that it's on-screen..
- if ((Time::getCurrentTime() - creationTime).inMilliseconds() < 1000)
- HIViewSetNeedsDisplay (embeddedView, true);
- }
-
- OSStatus carbonEventHandler (EventHandlerCallRef nextHandlerRef,
- EventRef event)
- {
- switch (GetEventKind (event))
- {
- case kEventWindowHandleDeactivate:
- ActivateWindow (wrapperWindow, TRUE);
- break;
-
- case kEventWindowGetClickActivation:
- {
- getTopLevelComponent()->toFront (false);
-
- ClickActivationResult howToHandleClick = kActivateAndHandleClick;
-
- SetEventParameter (event, kEventParamClickActivation, typeClickActivationResult,
- sizeof (ClickActivationResult), &howToHandleClick);
-
- HIViewSetNeedsDisplay (embeddedView, true);
- }
- break;
- }
-
- return noErr;
- }
-
- static pascal OSStatus carbonEventCallback (EventHandlerCallRef nextHandlerRef,
- EventRef event, void* userData)
- {
- return ((CarbonViewWrapperComponent*) userData)->carbonEventHandler (nextHandlerRef, event);
- }
-
- protected:
- WindowRef wrapperWindow;
- HIViewRef embeddedView;
- bool recursiveResize;
- Time creationTime;
-
- EventHandlerRef eventHandlerRef;
- };
-
- #endif // __JUCE_MAC_CARBONVIEWWRAPPERCOMPONENT_JUCEHEADER__
|