gecko-dev/lib/mac/UserInterface/UTearOffPalette.cp

1157 строки
35 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
// author: atotic
// See UTearOffPalette.h for usage instructions and design notes
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
#include "UTearOffPalette.h"
#include "prtypes.h"
#include "CToolbarModeManager.h"
#include "CToolbarPatternBevelView.h"
#include "prefapi.h"
#include "uapp.h"
// PowerPlant
#include <LStream.h>
#include <URegions.h>
#include <LArray.h>
#include <LArrayIterator.h>
#define FLOAT_ID -19844 // Same define is in UFloatWindow.r
#define SIDE_FLOAT_ID -19845 // Same define is in UFloatWindow.r
#pragma mark CTearOffBar
#pragma mark -
// ---------------------------------------------------------------------------
// ¥ Constructor from stream
// ---------------------------------------------------------------------------
// Read in the data
CTearOffBar::CTearOffBar(LStream* inStream) : LView(inStream)
{
*inStream >> fFloatingSubpaneID;
*inStream >> fInPlaceSubpaneID;
*inStream >> fAutoResize;
*inStream >> fVisibility;
*inStream >> fTitle;
*inStream >> fSideTitle;
*inStream >> fDisablePaletteWithWindow;
fOriginalFrameSize = mFrameSize;
fShown = false;
fTransparentPane = 0;
fAllowClickDrag = false;
}
// ---------------------------------------------------------------------------
// ¥ Destructor
// ---------------------------------------------------------------------------
// Unregister with the manager
CTearOffBar::~CTearOffBar()
{
CTearOffManager::GetDefaultManager()->UnregisterBar(this);
}
// ---------------------------------------------------------------------------
// ¥ FinishCreateSelf
// ---------------------------------------------------------------------------
// Register with the manager
void CTearOffBar::FinishCreateSelf()
{
CTearOffManager::GetDefaultManager()->RegisterBar(this);
}
// ---------------------------------------------------------------------------
// ¥ Click
// ---------------------------------------------------------------------------
// Slightly modified LView::Click
// We should handle clicks in the transparent pane
// We need this because the PPob view that holds the buttons that we put inside
// completely covers this view. Unless we make that view transparent, we'll never
// get any clicks
void CTearOffBar::Click( SMouseDownEvent &inMouseDown )
{
// Check if a SubPane of this View
// is hit
// Modified code
// Check if we have clicked on a 0 pane
LPane *clickedPane = FindDeepSubPaneContaining(inMouseDown.wherePort.h,
inMouseDown.wherePort.v );
if (clickedPane != nil && clickedPane->GetPaneID() == fTransparentPane)
{
LPane::Click(inMouseDown);
return;
}
// LView::Click code
clickedPane = FindSubPaneHitBy(inMouseDown.wherePort.h,
inMouseDown.wherePort.v);
if ( clickedPane != nil )
{ // SubPane is hit, let it respond to the Click
clickedPane->Click(inMouseDown);
} else { // No SubPane hit, or maybe pane 0. Inherited function
LPane::Click(inMouseDown); // will process click on this View
}
}
// ---------------------------------------------------------------------------
// ¥ ClickSelf
// ---------------------------------------------------------------------------
// Drag the outline of the bar out of the window
// Roughly copied out of UDesktop::DragDeskWindow
void CTearOffBar::ClickSelf(const SMouseDownEvent &inMouseDown)
{
if (::WaitMouseUp()) { // Continue if mouse hasn't been
// released
GrafPtr savePort; // Use ScreenPort for dragging
GetPort(&savePort);
GrafPtr screenPort = UScreenPort::GetScreenPort();
::SetPort(screenPort);
StColorPenState::Normalize();
// Get surrounding rectangle in global port coordinates
Rect frame;
Point topLeft, botRight;
topLeft.h = mFrameLocation.h;
topLeft.v = mFrameLocation.v;
botRight.h = topLeft.h + mFrameSize.width;
botRight.v = topLeft.v + mFrameSize.height;
PortToGlobalPoint(topLeft);
PortToGlobalPoint(botRight);
::SetRect( &frame, topLeft.h, topLeft.v, botRight.h, botRight.v );
StRegion dragRgn(frame);
// Let user drag a dotted outline
// of the Window
Rect dragRect = (**(GetGrayRgn())).rgnBBox;
::InsetRect(&dragRect, 4, 4);
Int32 dragDistance = ::DragGrayRgn(dragRgn, inMouseDown.macEvent.where,
&dragRect, &dragRect,
noConstraint, nil);
::SetPort(savePort);
// Check if the Window moved to a new, valid location.
// DragGrayRgn returns the constant Drag_Aborted if the
// user dragged outside the DragRect, which cancels
// the drag operation. We also check for the case where
// the drag finished at its original location (zero distance).
Int16 horizDrag = LoWord(dragDistance);
Int16 vertDrag = HiWord(dragDistance);
if (dragDistance == 0x80008000) return;
// 0x80008000 == Drag_Aborted from UFloatingDesktop
Boolean realDrag = horizDrag != 0 || vertDrag != 0;
if (fAllowClickDrag || realDrag)
{
// A valid drag occurred. horizDrag and vertDrag are
// distances from the current location. We need to
// get the new location for the Window in global
// coordinates. The bounding box of the Window's
// content region gives the current location in
// global coordinates. Add drag distances to this
// to get the new location.
CTearOffManager::GetDefaultManager()->DragBar(this,
topLeft.h + horizDrag,
topLeft.v + vertDrag,
realDrag);
}
}
}
// ---------------------------------------------------------------------------
// ¥ AddListener
// ---------------------------------------------------------------------------
// Tell manager that we have a listener
void CTearOffBar::AddListener(LListener *inListener)
{
LBroadcaster::AddListener(inListener);
CTearOffManager::GetDefaultManager()->RegisterListener(this, inListener);
}
// ---------------------------------------------------------------------------
// ¥ ListenToMessage
// ---------------------------------------------------------------------------
// Tell TearOffManager that we got the message
void CTearOffBar::ListenToMessage(MessageT inMessage, void *ioParam)
{
CTearOffManager::GetDefaultManager()->BarReceivedMessage(this, inMessage, ioParam);
}
// ---------------------------------------------------------------------------
// ¥ ListenToMessage
// ---------------------------------------------------------------------------
// Tell TearOffManager that we got the message
void CTearOffBar::ActivateSelf()
{
LView::ActivateSelf();
CTearOffManager::GetDefaultManager()->BarActivated(this);
}
// ---------------------------------------------------------------------------
// ¥ ListenToMessage
// ---------------------------------------------------------------------------
// Tell TearOffManager that we got the message
void CTearOffBar::DeactivateSelf()
{
LView::DeactivateSelf();
CTearOffManager::GetDefaultManager()->BarDeactivated(this);
}
// ---------------------------------------------------------------------------
// ¥ HidePalette
// ---------------------------------------------------------------------------
// Delete all the subpanes.
// Manager will broadcast a message msg_FloatPalleteRemoved to your listener
void CTearOffBar::HidePalette()
{
DeleteAllSubPanes();
if (fAutoResize)
ResizeFrameTo(0,0,TRUE);
else
Refresh();
fShown = false;
}
// ---------------------------------------------------------------------------
// ¥ ShowPalette
// ---------------------------------------------------------------------------
// Reads in the subview from PPob.
// Position the view properly
void CTearOffBar::ShowPalette()
{
if (fShown)
return;
// setup commander (window), superview(this), and listener(this)
SetDefaultView(this);
LWindow * commander = LWindow::FetchWindowObject(GetMacPort());
SignalIfNot_( commander );
LView * view = UReanimator::CreateView(fInPlaceSubpaneID, this, commander);
SignalIfNot_ ( view ); // We need that pane ID
view->FinishCreate();
fTransparentPane = view->GetPaneID();
UReanimator::LinkListenerToControls(this, this, fInPlaceSubpaneID);
UReanimator::LinkListenerToControls(CTearOffManager::GetDefaultManager(),
this, fInPlaceSubpaneID);
if (fAutoResize)
ResizeFrameTo(fOriginalFrameSize.width, fOriginalFrameSize.height, TRUE);
#ifdef DEBUG
if (fAutoResize)
{
SDimension16 s;
view->GetFrameSize(s);
// The container and the loaded view should be the same width/height???
SignalIf_(s.width != fOriginalFrameSize.width);
SignalIf_(s.height != fOriginalFrameSize.height);
}
#endif
fShown = true;
}
#pragma mark -
#pragma mark CTearOffWindow
#pragma mark -
/************************************************************************
* class CTearOffWindow
*
* just registers/unregisters itself with the
* You cannot subclass this class, because CTearOffManager creates all
* palettes out of a single PPob.
************************************************************************/
#define SAVE_POSITION 1
#if SAVE_POSITION
#include "CSaveWindowStatus.h"
#endif // SAVE_POSITION
//======================================
class CTearOffWindow
: public LWindow,
public CToolbarModeChangeListener
#if SAVE_POSITION
, public CSaveWindowStatus
#endif // SAVE_POSITION
//======================================
{
private:
typedef LWindow Inherited;
friend class CTearOffManager;
public:
enum { class_ID = 'DRFW' };
// Constructors
CTearOffWindow(LStream* inStream);
virtual ~CTearOffWindow();
// Events
virtual void ListenToMessage(MessageT inMessage, void *ioParam);
virtual void HandleModeChange(Int8 inNewMode);
virtual void DoSetZoom( Boolean );
virtual void AdjustWindowSizeBy( SDimension16& size_change );
#if SAVE_POSITION
private:
virtual ResIDT GetStatusResID(void) const { return FLOAT_ID; }
virtual UInt16 GetValidStatusVersion(void) const { return 0x0111; }
virtual void FinishCreateSelf();
virtual void AttemptClose();
virtual void DoClose();
#endif // SAVE_POSITION
private:
UInt8 fVisibility; // Inherited from the bar
};
//-----------------------------------
CTearOffWindow::CTearOffWindow(LStream* inStream)
//-----------------------------------
: LWindow(inStream)
, CSaveWindowStatus(this)
{
PREF_SetBoolPref("taskbar.mac.is_open", true);
}
//-----------------------------------
CTearOffWindow::~CTearOffWindow()
//-----------------------------------
{
// Notify the manager
CTearOffManager::GetDefaultManager()->UnregisterWindow(this);
// YIKES! Save this preference if the app _isn't_ quitting. What an ugly hack!
if ( CFrontApp::sApplication->GetState() == programState_ProcessingEvents )
PREF_SetBoolPref("taskbar.mac.is_open", false);
}
#if SAVE_POSITION
//-----------------------------------
void CTearOffWindow::FinishCreateSelf()
//-----------------------------------
{
Inherited::FinishCreateSelf();
CSaveWindowStatus::FinishCreateWindow();
SDimension16 zero_zero = {0,0};
AdjustWindowSizeBy(zero_zero);
}
//-----------------------------------
void CTearOffWindow::AttemptClose()
//-----------------------------------
{
AttemptCloseWindow();
Inherited::AttemptClose();
}
//-----------------------------------
void CTearOffWindow::DoClose()
//-----------------------------------
{
AttemptCloseWindow();
Inherited::DoClose();
}
#endif // SAVE_POSITION
void CTearOffWindow::HandleModeChange( Int8 inNewMode )
{
SDimension16 size_change={ 0, 0 };
if ( CToolbarButtonContainer* container_ptr = dynamic_cast<CToolbarButtonContainer*>(FindPaneByID('TBPv')) )
container_ptr->HandleModeChange(inNewMode, size_change);
AdjustWindowSizeBy(size_change);
}
void CTearOffWindow::DoSetZoom( Boolean )
{
SDimension16 size_change={ 0, 0 };
if ( CToolbarPatternBevelView* container_ptr = dynamic_cast<CToolbarPatternBevelView*>(FindPaneByID('TBPv')) )
container_ptr->RotateArrangement(size_change);
AdjustWindowSizeBy(size_change);
SDimension16 frameSize;
GetFrameSize(frameSize);
PREF_SetBoolPref("taskbar.mac.is_vertical", XP_Bool(frameSize.height > frameSize.width));
}
void CTearOffWindow::AdjustWindowSizeBy( SDimension16& size_change )
{
/*
Always adjust the size (even if size_change is {0,0}) because the caller
might be trying to ensure that the window is pinned to the screen.
*/
Rect frame_rect;
CalcPortFrameRect(frame_rect);
PortToGlobalPoint(topLeft(frame_rect));
PortToGlobalPoint(botRight(frame_rect));
frame_rect.right += size_change.width;
frame_rect.bottom += size_change.height;
VerifyWindowBounds(mWindowSelf, &frame_rect);
DoSetBounds(frame_rect);
}
// ---------------------------------------------------------------------------
// ¥ CTearOffWindow destructor
// ---------------------------------------------------------------------------
// Pass on to the manager
void CTearOffWindow::ListenToMessage(MessageT inMessage, void *ioParam)
{
if ( inMessage == CToolbarModeManager::msg_ToolbarModeChange )
HandleModeChange((Int8)ioParam);
else
CTearOffManager::GetDefaultManager()->WindowReceivedMessage(this, inMessage, ioParam);
}
/*****************************************************************************
* class CTearOffManager
*****************************************************************************/
#pragma mark -
#pragma mark CTearOffManager
#pragma mark -
CTearOffManager * CTearOffManager::sDefaultFloatManager = NULL;
#pragma mark struct ButtonBarRecord
// holds information about a single button bar, stored in fPaletteBars list
struct ButtonBarRecord
{
ResIDT fID; // ResID of the PPob loaded into the button bar.
ResIDT fWindowID; // ResID of the PPob loaded into the floating window.
CTearOffBar * fBar; // Pointer to the bar
LListener * fListener; // The listener for this bar
ButtonBarRecord()
{
fID = -1;
fWindowID = -1;
fBar = NULL;
fListener = NULL;
}
ButtonBarRecord(ResIDT id, ResIDT wID, CTearOffBar * bar, LListener * listener)
{
fID = id;
fWindowID = wID;
fBar = bar;
fListener = listener;
}
};
/****************************************************************************
* struct FloatWindowRecord
* used to keep a list of loaded windows
****************************************************************************/
#pragma mark struct FloatWindowRecord
struct FloatWindowRecord
{
CTearOffWindow * fWindow;
ResIDT fID; // Res ID of the PPob to be loaeded
CTearOffBar * fActiveBar;
FloatWindowRecord(CTearOffWindow * window, ResIDT resID, CTearOffBar * activeBar = NULL)
{
fWindow = window;
fID = resID;
fActiveBar = activeBar;
}
};
// ---------------------------------------------------------------------------
// ¥ Compare the window records
// ---------------------------------------------------------------------------
// Wildcards can be used for fID and fWindow fields
// fListener field is not used.
#define WILDCARD -1
Int32 CTearOffManager::CPaletteWindowComparator::Compare(const void* inItemOne,
const void* inItemTwo,
Uint32 inSizeOne,
Uint32 inSizeTwo) const
{
#pragma unused (inSizeOne, inSizeTwo) // Cause we know what the items are
FloatWindowRecord * item1 = (FloatWindowRecord *)inItemOne;
FloatWindowRecord * item2 = (FloatWindowRecord *)inItemTwo;
if ( item1->fID != item2->fID && // Different floaters
(item1->fID != WILDCARD) &&
(item2->fID != WILDCARD))
return (item1->fWindow - item2->fWindow);
else // Same floaters
if ( item1->fWindow == item2->fWindow ||
( item1->fWindow == (void*)WILDCARD ) ||
( item2->fWindow == (void*)WILDCARD ) )
return 0;
else
return item1->fWindow - item2->fWindow;
}
// ---------------------------------------------------------------------------
// ¥ Compare the bars
// ---------------------------------------------------------------------------
// Wildcards can be used for fID and fBar fields
// fListener field is not used.
Int32 CTearOffManager::CPaletteBarComparator::Compare(const void* inItemOne,
const void* inItemTwo,
Uint32 inSizeOne,
Uint32 inSizeTwo) const
{
#pragma unused (inSizeOne, inSizeTwo) // Cause we know what the items are
ButtonBarRecord * item1 = (ButtonBarRecord *)inItemOne;
ButtonBarRecord * item2 = (ButtonBarRecord *)inItemTwo;
if ( item1->fID != item2->fID && // Different IDs
(item1->fID != WILDCARD) &&
(item2->fID != WILDCARD) )
return ( item1->fBar - item2->fBar );
if (item1->fWindowID != item2->fWindowID && // Different floaters
(item1->fWindowID != WILDCARD) &&
(item2->fWindowID != WILDCARD) )
return ( item1->fBar - item2->fBar );
else // Same floaters
if ( item1->fBar == item2->fBar ||
( item1->fBar == (void*)WILDCARD ) ||
( item2->fBar == (void*)WILDCARD ) )
return 0;
else
return item1->fBar - item2->fBar;
return 0; // Kill the warning
}
// ---------------------------------------------------------------------------
// ¥ CTearOffManager Constructor
// ---------------------------------------------------------------------------
// sets the default manager
CTearOffManager::CTearOffManager(LCommander * defaultCommander)
{
sDefaultFloatManager = this;
// These lists cannot be sorted, because sometimes we do wildcard lookups
// If you want to sort them, implement CompareKey better
fPaletteBars = new LArray( sizeof (ButtonBarRecord), &fBarCompare, false );
fPaletteWindows = new LArray( sizeof (FloatWindowRecord), &fWindowCompare, false );
fDefaultCommander = defaultCommander;
}
// ---------------------------------------------------------------------------
// ¥ CTearOffManager destructor -- never called, here for completeness
// ---------------------------------------------------------------------------
// clean up
CTearOffManager::~CTearOffManager()
{
delete fPaletteBars;
delete fPaletteWindows;
}
void CTearOffManager::ListenToMessage(MessageT inMessage, void *ioParam)
{
BroadcastMessage(inMessage, ioParam);
}
// ---------------------------------------------------------------------------
// ¥ RegisterBar
// ---------------------------------------------------------------------------
// Insert the bar in the bar list. Hide or show it, depending on the window
void CTearOffManager::RegisterBar(CTearOffBar * inBar)
{
// Insert it into the list
ButtonBarRecord barRec( inBar->fInPlaceSubpaneID, inBar->fFloatingSubpaneID, inBar, NULL);
fPaletteBars->InsertItemsAt(1, fPaletteBars->GetCount(), &barRec, sizeof( barRec ) );
// Decide whether to hide or show the bar
FloatWindowRecord fr( (CTearOffWindow *)WILDCARD, inBar->fFloatingSubpaneID );
ArrayIndexT where = fPaletteWindows->FetchIndexOfKey( &fr );
if ( where != LArray::index_Bad )
inBar->HidePalette();
else
inBar->ShowPalette();
}
// ---------------------------------------------------------------------------
// ¥ UnregisterBar
// ---------------------------------------------------------------------------
// Remove the bar from the bar list
// If there are any "left-over" floaters, remove them
void CTearOffManager::UnregisterBar(CTearOffBar * inBar)
{
ButtonBarRecord bar( WILDCARD, WILDCARD, inBar, NULL);
ArrayIndexT where = fPaletteBars->FetchIndexOfKey(&bar);
if ( where != LArray::index_Bad )
fPaletteBars->RemoveItemsAt( 1, where );
else
SignalCStr_("Unregistering a bar that was never registered?");
// If there are no other bars with the same ID,
// remove the floater window (floater might not exist)
ButtonBarRecord brotherBar( inBar->fInPlaceSubpaneID, inBar->fFloatingSubpaneID,
(CTearOffBar *)WILDCARD, NULL );
where = fPaletteBars->FetchIndexOfKey(&brotherBar);
if ( where == LArray::index_Bad )
// Remove the floaters with this ID
{
FloatWindowRecord fw( (CTearOffWindow*) WILDCARD, inBar->fFloatingSubpaneID );
ArrayIndexT where = fPaletteWindows->FetchIndexOfKey( &fw );
if ( where != LArray::index_Bad )
{
fPaletteWindows->FetchItemAt( where, &fw );
if (fw.fWindow->fVisibility != 0)
delete fw.fWindow; // this will automatically remove it from the list
}
}
}
// ---------------------------------------------------------------------------
// ¥ RegisterListener
// ---------------------------------------------------------------------------
// Set the listener
// Broadcast the palette message to the window, depending on where the palette is
void CTearOffManager::RegisterListener(CTearOffBar * inBar,
LListener * listener)
{
ButtonBarRecord bar( WILDCARD, WILDCARD, inBar, listener );
ArrayIndexT where = fPaletteBars->FetchIndexOfKey(&bar);
if (where != LArray::index_Bad)
{
// assign the listener
fPaletteBars->FetchItemAt( where, &bar );
bar.fListener = listener;
fPaletteBars->AssignItemsAt( 1, where , &bar );
// broadcast the palette message to the listener
FloatWindowRecord fr( (CTearOffWindow *)WILDCARD, inBar->fFloatingSubpaneID );
ArrayIndexT where = fPaletteWindows->FetchIndexOfKey( &fr );
if ( where != LArray::index_Bad )
{
// We have a window to register
fPaletteWindows->FetchItemAt( where, &fr );
SetBarsView( inBar, fr.fWindow );
}
else
// The bar holds the palette
{
SetBarsView( inBar, inBar );
}
}
else
SignalCStr_("Bar never registered?");
}
// ---------------------------------------------------------------------------
// ¥ BarReceivedMessage
// ---------------------------------------------------------------------------
// Relay the message to its listeners
void CTearOffManager::BarReceivedMessage(CTearOffBar * inBar,
MessageT inMessage,
void *ioParam)
{
ButtonBarRecord bar( WILDCARD, WILDCARD, inBar, NULL );
ArrayIndexT where = fPaletteBars->FetchIndexOfKey(&bar);
if ( where != LArray::index_Bad )
{
fPaletteBars->FetchItemAt( where, &bar );
// SignalIfNot_(bar.fListener);
if (bar.fListener)
bar.fListener->ListenToMessage( inMessage, ioParam );
}
else
SignalCStr_("Bar never registered?");
}
// ---------------------------------------------------------------------------
// ¥ DragBar
// ---------------------------------------------------------------------------
// Assert that the window exists
// move it to the new location
void CTearOffManager::DragBar( CTearOffBar * inBar,
Int16 inH,
Int16 inV,
Boolean usePosition )
{
try
{
CTearOffWindow * win = AssertBarWindowExists(inBar);
#if SAVE_POSITION
if (usePosition) {
#endif
Point topLeft;
topLeft.h = inH;
topLeft.v = inV;
win->DoSetPosition(topLeft);
#if SAVE_POSITION
}
#endif
win->Show();
SetBarsView( inBar, win );
}
catch(OSErr inErr)
{
SignalCStr_("Did you include UTearOffPalette.r in your project?");
// No window, button bar stays where it was
}
}
// ---------------------------------------------------------------------------
// ¥ BarActivated
// ---------------------------------------------------------------------------
// Upon activation:
// Tell its float windowGets the floater window for the bar
// Tells listener what the current palette is
//
void CTearOffManager::BarActivated( CTearOffBar * inBar)
{
// Find the floater window
FloatWindowRecord fw( (CTearOffWindow *) WILDCARD, inBar->fFloatingSubpaneID );
ArrayIndexT where = fPaletteWindows->FetchIndexOfKey( &fw );
// If we have a window, make this bar the active one
if ( where != LArray::index_Bad )
{
fPaletteWindows->FetchItemAt( where, &fw );
if ( fw.fActiveBar != inBar )
{
if ( fw.fActiveBar == NULL ) // If there was no view, we need to enable us
{
LPane * view;
LArrayIterator iter( fw.fWindow->GetSubPanes());
if ( iter.Next(&view) ) // We have disabled this on suspends
view->Enable();
}
fw.fActiveBar = inBar;
fPaletteWindows->AssignItemsAt( 1, where , &fw );
fw.fWindow->Show();
SetBarsView(inBar, fw.fWindow);
}
}
}
// ---------------------------------------------------------------------------
// ¥ BarDeactivated
// ---------------------------------------------------------------------------
// Upon deactivation
// If we have a floating window, make it inactive and tell listener about it
void CTearOffManager::BarDeactivated( CTearOffBar * inBar)
{
FloatWindowRecord fw( (CTearOffWindow *) WILDCARD, inBar->fFloatingSubpaneID );
ArrayIndexT where = fPaletteWindows->FetchIndexOfKey( &fw );
if ( where != LArray::index_Bad )
{
fPaletteWindows->FetchItemAt( where, &fw );
if ( fw.fActiveBar == inBar )
{
if ( fw.fWindow->fVisibility == 2 )
fw.fWindow->Hide();
else
{
if (inBar->DisablePaletteWindow())
{
// Disable all the subpanes of our main subpane
// Do not disable the main pane, because no one enables it
LPane * view;
LArrayIterator iter( fw.fWindow->GetSubPanes());
if ( iter.Next(&view) )
view->Disable();
}
}
fw.fActiveBar = NULL;
fPaletteWindows->AssignItemsAt( 1, where , &fw );
RemoveBarsView(inBar, inBar->fTransparentPane);
}
}
}
// ---------------------------------------------------------------------------
// ¥ SetBarsView
// ---------------------------------------------------------------------------
// Tell listener what its palette view is
// InView is either FBar, or FWindow. In either case, the palette is the first subview
void CTearOffManager::SetBarsView( CTearOffBar * inBar,
LView * inView)
{
SignalIfNot_( inView );
// Get the bar record
ButtonBarRecord br( WILDCARD, WILDCARD, inBar, (LListener*) WILDCARD );
ArrayIndexT where = fPaletteBars->FetchIndexOfKey( &br );
if ( where != LArray::index_Bad )
{
fPaletteBars->FetchItemAt( where, &br );
if ( br.fListener )
{
// Palette is the first subview
LView * topPaletteView;
LArrayIterator iter( inView->GetSubPanes());
if ( iter.Next(&topPaletteView) )
br.fListener->ListenToMessage( msg_SetTearOffPalette, topPaletteView );
}
}
else
SignalCStr_("Where is the bar?");
}
// ---------------------------------------------------------------------------
// ¥ RemoveBarsView
// ---------------------------------------------------------------------------
// Similar to SetBarsView. Must get the top pane ID from somewhere
void CTearOffManager::RemoveBarsView( CTearOffBar * inBar, PaneIDT inViewID)
{
ButtonBarRecord br( WILDCARD, WILDCARD, inBar, (LListener*) WILDCARD );
ArrayIndexT where = fPaletteBars->FetchIndexOfKey( &br );
if ( where != LArray::index_Bad )
{
fPaletteBars->FetchItemAt( where, &br );
if ( br.fListener )
br.fListener->ListenToMessage( msg_RemoveTearOffPalette, (void*) inViewID );
}
else
SignalCStr_("Where is the bar?");
}
// ---------------------------------------------------------------------------
// ¥ AssertBarWindowExists
// ---------------------------------------------------------------------------
// Create the window if it does not exist
CTearOffWindow * CTearOffManager::AssertBarWindowExists(CTearOffBar * inBar)
{
return AssertBarWindowExists(
inBar->fFloatingSubpaneID,
inBar->IsFloaterOnSide(),
inBar->fVisibility,
inBar->fTitle
);
}
// ---------------------------------------------------------------------------
// ¥ AssertBarWindowExists
// ---------------------------------------------------------------------------
// Create the window if it does not exist
CTearOffWindow * CTearOffManager::AssertBarWindowExists(ResIDT inWinID,
Boolean inSideways,
UInt8 visibility,
Str255 &title)
{
FloatWindowRecord fw( (CTearOffWindow *) WILDCARD, inWinID );
ArrayIndexT where = fPaletteWindows->FetchIndexOfKey( &fw );
CTearOffWindow * newWindow = nil;
if (where == LArray::index_Bad)
{
// Create a new window, load the palette into it
ResIDT windowResID = inSideways ? SIDE_FLOAT_ID : FLOAT_ID;
newWindow = (CTearOffWindow *) LWindow::CreateWindow(windowResID, fDefaultCommander);
ThrowIfNil_(newWindow);
newWindow->fVisibility = visibility;
LView * view = UReanimator::CreateView(inWinID, newWindow, newWindow);
ThrowIfNil_( view );
view->FinishCreate();
UReanimator::LinkListenerToControls(CTearOffManager::GetDefaultManager(),
view, inWinID);
// Resize the window
Point corner = {0,0};
#if SAVE_POSITION
newWindow->PortToGlobalPoint(corner);
#endif
SDimension16 viewSize;
Rect winBounds;
view->GetFrameSize(viewSize);
::SetRect(&winBounds,
corner.h, corner.v,
corner.h + viewSize.width, corner.v + viewSize.height);
newWindow->DoSetBounds( winBounds );
newWindow->SetDescriptor(title);
SBooleanRect boundToSuperview={ true, true, true, true };
view->SetFrameBinding(boundToSuperview);
Int32 toolbarStyle;
if ( (PREF_GetIntPref("browser.chrome.toolbar_style", &toolbarStyle) == PREF_NOERROR)
&& (toolbarStyle != CToolbarModeManager::defaultToolbarMode) )
{
((CTearOffWindow*)newWindow)->HandleModeChange(toolbarStyle);
}
XP_Bool is_vertical = true;
if ( (PREF_GetBoolPref("taskbar.mac.is_vertical", &is_vertical) == PREF_NOERROR)
&& !is_vertical )
{
((CTearOffWindow*)newWindow)->DoSetZoom(Boolean());
}
// Add the record to the list of managed floaters
FloatWindowRecord fw(newWindow, inWinID, NULL);
fPaletteWindows->InsertItemsAt( 1, fPaletteWindows->GetCount(), &fw, sizeof (fw) );
// Hide the bars button palletes
LArrayIterator iter(*fPaletteBars);
ButtonBarRecord bar;
while ( iter.Next(&bar) )
if (bar.fWindowID == fw.fID)
{
bar.fBar->HidePalette();
bar.fBar->fTransparentPane = view->GetPaneID();
RemoveBarsView( bar.fBar, bar.fBar->fTransparentPane );
}
// Link up the new controls
UReanimator::LinkListenerToControls( newWindow, newWindow, fw.fID );
}
else
{
fPaletteWindows->FetchItemAt( where, &fw );
return fw.fWindow;
}
return newWindow;
} // CTearOffManager::AssertBarWindowExists
// ---------------------------------------------------------------------------
// ¥ UnregisterWindow
// ---------------------------------------------------------------------------
// Remove the window from the list
// Show all the floaters
void CTearOffManager::UnregisterWindow(CTearOffWindow * window)
{
// Remove the window from the list
FloatWindowRecord fw( window, WILDCARD );
ArrayIndexT where = fPaletteWindows->FetchIndexOfKey( &fw );
if ( where != LArray::index_Bad )
{
fPaletteWindows->FetchItemAt( where, &fw );
fPaletteWindows->RemoveItemsAt( 1, where );
}
else
SignalCStr_("Removal of unregistered window?");
// Tell all button bars to show themselves
LArrayIterator iter(*fPaletteBars);
ButtonBarRecord bar;
while ( iter.Next(&bar) )
if (bar.fWindowID == fw.fID)
{
bar.fBar->ShowPalette();
SetBarsView(bar.fBar, bar.fBar);
}
}
// ---------------------------------------------------------------------------
// ¥ CloseFloatingWindow
// ---------------------------------------------------------------------------
// Closes the Floating Window
void CTearOffManager::CloseFloatingWindow(ResIDT inWinID)
{
// find the window in the list
FloatWindowRecord fw((CTearOffWindow *)WILDCARD, inWinID, (CTearOffBar *)WILDCARD );
ArrayIndexT where = fPaletteWindows->FetchIndexOfKey( &fw );
if ( where != LArray::index_Bad )
{
fPaletteWindows->FetchItemAt( where, &fw );
fw.fWindow->ProcessCommand(cmd_Close);
}
else
{
SignalCStr_("close of unregistered window?");
}
}
// ---------------------------------------------------------------------------
// ¥ OpenFloatingWindow
// ---------------------------------------------------------------------------
// Opens the Floating Window
void CTearOffManager::OpenFloatingWindow( ResIDT inWinID,
Point /* inTopLeft */,
Boolean inSideways,
UInt8 visibility,
Str255 &title)
{
// find the window in the list
FloatWindowRecord fw((CTearOffWindow *)WILDCARD, inWinID, (CTearOffBar *)WILDCARD );
ArrayIndexT where = fPaletteWindows->FetchIndexOfKey( &fw );
if (LArray::index_Bad == where)
{
try
{
CTearOffWindow * win = AssertBarWindowExists(inWinID, inSideways, visibility, title);
#if !SAVE_POSITION
win->DoSetPosition(inTopLeft);
#endif
win->Show();
}
catch(OSErr inErr)
{
SignalCStr_("Did you include UTearOffPalette.r in your project?");
// No window, button bar stays where it was
}
}
else
{
SignalCStr_("open of open window?");
}
}
// ---------------------------------------------------------------------------
// ¥ IsFloatingWindow
// ---------------------------------------------------------------------------
// Closes the Floating Window
Boolean CTearOffManager::IsFloatingWindow(ResIDT inWinID)
{
// find the window in the list
FloatWindowRecord fw((CTearOffWindow *)WILDCARD, inWinID, (CTearOffBar *)WILDCARD );
ArrayIndexT where = fPaletteWindows->FetchIndexOfKey( &fw );
return where != LArray::index_Bad;
}
// ---------------------------------------------------------------------------
// ¥ WindowReceivedMessage
// ---------------------------------------------------------------------------
// Rebroadcast the message to the listener of the currently active bar
void CTearOffManager::WindowReceivedMessage(CTearOffWindow * inWin,
MessageT inMessage,
void *ioParam)
{
// Get the window record
FloatWindowRecord fw( inWin, WILDCARD );
ArrayIndexT where = fPaletteWindows->FetchIndexOfKey( &fw );
if ( where != LArray::index_Bad )
{
fPaletteWindows->FetchItemAt( where, &fw );
// If there is an active bar attached to this window
// rebroadcast the message to its listener
if (fw.fActiveBar)
{
ButtonBarRecord bar( WILDCARD, WILDCARD, fw.fActiveBar , NULL );
where = fPaletteBars->FetchIndexOfKey(&bar);
if ( where != LArray::index_Bad )
{
fPaletteBars->FetchItemAt( where, &bar );
if ( bar.fListener != NULL )
bar.fListener->ListenToMessage( inMessage, ioParam );
}
}
}
else
SignalCStr_("Message from a window we do not know about?");
}
#pragma mark -
// ---------------------------------------------------------------------------
// ¥ InitUTearOffPalette [static]
// ---------------------------------------------------------------------------
// Registers classes, creates a single float manager
void InitUTearOffPalette(LCommander * defCommander)
{
RegisterClass_( CTearOffBar);
RegisterClass_( CTearOffWindow);
new CTearOffManager(defCommander);
}