home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
-
- /*====================================================================================*/
- #pragma mark INCLUDE FILES
- /*====================================================================================*/
-
- #include "CGATabBox.h"
-
- #include <LGAPushButton.h>
- #include <UGraphicsUtilities.h>
- #include <UGAColorRamp.h>
-
-
- /*====================================================================================*/
- #pragma mark TYPEDEFS
- /*====================================================================================*/
-
- typedef struct {
- PaneIDT tabPaneID; // ID of the pane associated with the tab
- PaneIDT latentCommanderID; // Last active commander ID, 0 if none
- } TabLatentCommanderT;
-
-
- /*====================================================================================*/
- #pragma mark CONSTANTS
- /*====================================================================================*/
-
- static const Int16 cSelectedTabShiftH = 2;
- static const Int16 cSelectedTabShiftV = 2;
-
-
- /*====================================================================================*/
- #pragma mark INTERNAL CLASS DECLARATIONS
- /*====================================================================================*/
-
- // CGATabBoxTab
-
- class CGATabBoxTab : public LGAPushButton {
-
- public:
-
- enum { class_ID = 'TbBt' };
- CGATabBoxTab(LStream *inStream) :
- LGAPushButton(inStream),
- mSelected(false) {
- }
-
- void RefreshHiddenBottom(void);
-
- protected:
-
- virtual void DrawSelf(void);
- virtual void ClickSelf(const SMouseDownEvent &inMouseDown);
- virtual void BroadcastValueMessage(void);
-
- virtual void CalcTitleRect(Rect &outRect);
- virtual void DrawButtonNormalColor(void);
-
- Boolean IsSelectedTab(void) {
- return (((CGATabBox *) mSuperView)->GetCurrentTabID() == mPaneID);
- }
-
- // Instance variables
-
- Boolean mSelected;
- };
-
-
-
- /*====================================================================================*/
- #pragma mark INTERNAL FUNCTION PROTOTYPES
- /*====================================================================================*/
-
-
- /*====================================================================================*/
- #pragma mark CLASS IMPLEMENTATIONS
- /*====================================================================================*/
-
- #pragma mark -
-
- /*======================================================================================
- Register PP classes associated with this tab box.
- ======================================================================================*/
-
- void CGATabBox::RegisterTabBoxClasses(void) {
-
- RegisterClass_(CGATabBoxTab);
- RegisterClass_(CGATabBox);
- }
-
-
- /*======================================================================================
- Constructor.
- ======================================================================================*/
-
- CGATabBox::CGATabBox(LStream *inStream) :
- LGABox_fixes(inStream),
- LListener(),
- LBroadcaster(),
- mCurrentTabID(0),
- mCurrentPaneID(0),
- mTabLatentCommanders(sizeof(TabLatentCommanderT)) {
-
- mHasBorder = true;
- mBorderStyle = borderStyleGA_EmbossedOneBorder;
- mTitlePosition = titlePositionGA_None;
- mTitle[0] = 0;
- }
-
-
- /*======================================================================================
- Set the currently selected tab.
- ======================================================================================*/
-
- void CGATabBox::SetCurrentTabID(PaneIDT inTabID) {
-
- if ( mCurrentTabID == inTabID ) return;
- Boolean updatePort = false;
-
- CGATabBoxTab *lastTab = nil, *newTab = nil;
- LTabGroup *theTabGroup = nil;
-
- // Hide old view
-
- if ( mCurrentTabID != 0 ) {
- lastTab = GetTab(mCurrentTabID);
- if ( lastTab != nil ) {
- TabBoxCanChangeT canChangeRec = { this, true };
- BroadcastMessage(msg_TabViewCanChange, &canChangeRec);
- if ( canChangeRec.canChange ) {
- if ( lastTab->GetValueMessage() != 0 ) {
- LPane *thePane = FindPaneByID(lastTab->GetValueMessage());
- if ( thePane != nil ) {
- theTabGroup = FindTabGroup();
- StoreLatentTabCommander(dynamic_cast<LView *>(thePane));
- // Switch the window to the current commander so that a tab group
- // doesn't swap commanders as they are hidden
- if ( theTabGroup != nil ) {
- LCommander::SwitchTarget(LWindow::FetchWindowObject(GetMacPort()));
- }
- thePane->Hide();
- }
- }
- lastTab->SetTextTraitsID(GetTextTraitsID() + 1);
- lastTab->RefreshHiddenBottom();
- } else {
- return; // Can't change
- }
- }
- }
-
- mCurrentTabID = inTabID;
-
- if ( mCurrentTabID != 0 ) {
- newTab = GetTab(mCurrentTabID);
- if ( newTab != nil ) {
- PaneIDT paneID = newTab->GetValueMessage();
- if ( paneID != 0 ) {
- LPane *thePane = FindPaneByID(paneID);
- if ( thePane != nil ) {
- thePane->Show();
- if ( !RestoreLatentTabCommander(dynamic_cast<LView *>(thePane)) &&
- (theTabGroup != nil) ) {
-
- //StEmptyVisRgn emptyRgn(GetMacPort()); // Hide any flicker
- LCommander::SwitchTarget(theTabGroup);
- }
- }
- }
- newTab->SetTextTraitsID(GetTextTraitsID());
- newTab->RefreshHiddenBottom();
- BroadcastMessage(msg_TabViewChanged, this);
- }
- }
-
- if ( (lastTab != nil) || (newTab != nil) ) {
- if ( lastTab != nil ) lastTab->Draw(nil);
- if ( newTab != nil ) newTab->Draw(nil);
- UpdatePort();
- }
- }
-
-
- /*======================================================================================
- Calculate the border rect, which will be offset by the bottom of the tabs.
- ======================================================================================*/
-
- void CGATabBox::CalcBorderRect(Rect &outRect) {
-
- LGABox_fixes::CalcBorderRect(outRect);
-
- ::InsetRect(&outRect, 1, 1); // For border
-
- Rect tabRect;
- CalcCurrentTabRect(tabRect);
-
- outRect.top = tabRect.bottom - 4;
- }
-
-
- /*======================================================================================
- Calculate the current tab rect in local coordinates.
- ======================================================================================*/
-
- void CGATabBox::CalcCurrentTabRect(Rect &outRect) {
-
- Assert_(mCurrentTabID != 0);
-
- if ( mCurrentTabID ) {
- CGATabBoxTab *theTab = GetTab(mCurrentTabID);
- Assert_(theTab != nil);
- if ( theTab != nil ) {
- theTab->CalcPortFrameRect(outRect);
- PortToLocalPoint(topLeft(outRect));
- PortToLocalPoint(botRight(outRect));
- }
- }
- }
-
-
- /*======================================================================================
- Finish creating the tab box.
- ======================================================================================*/
-
- void CGATabBox::FinishCreateSelf(void) {
-
- LGABox_fixes::FinishCreateSelf();
-
- SetupTabs();
-
- SetCurrentTabID(GetUserCon());
- }
-
-
- /*======================================================================================
- Draw the box border.
- ======================================================================================*/
-
- void CGATabBox::DrawBoxBorder(void) {
-
- StColorPenState::Normalize();
-
- Rect borderRect;
- CalcBorderRect(borderRect);
- ::InsetRect(&borderRect, -1, -1);
-
- ::FrameRect(&borderRect);
-
- LGABox_fixes::DrawBoxBorder();
- }
-
-
- /*======================================================================================
- Respond to tab messages. Only tabs will broadcast messages to this class, so that's
- all we need to be concerned with.
- ======================================================================================*/
-
- void CGATabBox::ListenToMessage(MessageT inMessage, void */*ioParam*/) {
-
- SetCurrentTabID((PaneIDT) inMessage);
- }
-
-
- /*======================================================================================
- Called from FinishCreateSelf() to setup the tabs for the view.
- ======================================================================================*/
-
- void CGATabBox::SetupTabs(void) {
-
- // Loop through all subpanes to find the relevant tabs
-
- LArrayIterator iterator(mSubPanes, LArrayIterator::from_Start);
- LPane *theSub;
- CGATabBoxTab *theTab = nil;
- Boolean foundTabs = false;
- while ( iterator.Next(&theSub) ) {
- theTab = dynamic_cast<CGATabBoxTab *>(theSub);
- if ( theTab != nil ) {
- if ( theTab->GetValueMessage() != 0 ) {
- PaneIDT paneID = theTab->GetValueMessage();
- LPane *thePane = FindPaneByID(paneID);
- if ( thePane != nil ) {
- thePane->Hide();
- LView *theView = dynamic_cast<LView *>(thePane);
- if ( theView != nil ) {
- // Initialize the last active commander for the tab's pane
- TabLatentCommanderT rec = { paneID, 0 };
- mTabLatentCommanders.InsertItemsAt(1, LArray::index_Last, &rec);
- }
- }
- }
- theTab->SetTextTraitsID(GetTextTraitsID() + 1);
- theTab->AddListener(this);
- foundTabs = true;
- }
- }
- Assert_(foundTabs); // Should have found at least one tab!
- }
-
-
- /*======================================================================================
- A new tab view has just been activated. Try to find the last active commander and
- make it the currently active commander. Return true if a valid commander was actually
- found and stored.
- ======================================================================================*/
-
- Boolean CGATabBox::StoreLatentTabCommander(LView *inTabView) {
-
- if ( inTabView == nil ) return false;
-
- const Int32 count = mTabLatentCommanders.GetCount();
- if ( count < 1 ) return false;
-
- PaneIDT paneID = inTabView->GetPaneID();
- Int32 index = 1;
-
- // Try to find the tab pane id in our list
- do {
- if ( ((TabLatentCommanderT *) mTabLatentCommanders.GetItemPtr(index))->tabPaneID == paneID ) {
- break;
- }
- } while ( ++index < count );
-
- paneID = 0;
-
- if ( index < count ) {
- LCommander *curTarget = LCommander::GetTarget();
-
- if ( curTarget != nil ) {
- LPane *thePane = dynamic_cast<LPane *>(curTarget);
- if ( (thePane != nil) && thePane->IsEnabled() &&
- inTabView->FindPaneByID(thePane->GetPaneID()) ) {
-
- paneID = thePane->GetPaneID(); // We foud our commander!
- }
- }
-
- ((TabLatentCommanderT *) mTabLatentCommanders.GetItemPtr(index))->latentCommanderID = paneID;
- }
-
- return (paneID != 0);
- }
-
-
- /*======================================================================================
- A new tab view has just been activated. Try to find the last active commander and
- make it the currently active commander. Return true if a valid commander was actually
- found and restored.
- ======================================================================================*/
-
- Boolean CGATabBox::RestoreLatentTabCommander(LView *inTabView) {
-
- if ( inTabView == nil ) return false;
-
- Int32 count = mTabLatentCommanders.GetCount();
- if ( count < 1 ) return false;
-
- PaneIDT paneID = inTabView->GetPaneID();
- Int32 index = 1;
-
- // Try to find the tab pane id in our list
- do {
- if ( ((TabLatentCommanderT *) mTabLatentCommanders.GetItemPtr(index))->tabPaneID == paneID ) {
- break;
- }
- } while ( ++index < count );
-
- LCommander *theCommander = nil;
-
- if ( index < count ) {
- PaneIDT latentCommanderID = ((TabLatentCommanderT *) mTabLatentCommanders.GetItemPtr(index))->latentCommanderID;
- if ( latentCommanderID != 0 ) {
- // We found our view, now see if there was an active commander
- LPane *thePane = inTabView->FindPaneByID(latentCommanderID);
- if ( (thePane != nil) && thePane->IsEnabled() ) {
- theCommander = dynamic_cast<LCommander *>(thePane);
- if ( theCommander != nil ) {
- LCommander::SwitchTarget(theCommander);
- }
- }
- }
- }
-
- return (theCommander != nil);
- }
-
-
- /*======================================================================================
- Get the specified tab. Return nil if the tab cannot be found.
- ======================================================================================*/
-
- CGATabBoxTab *CGATabBox::GetTab(PaneIDT inID) {
-
- LArrayIterator iterator(mSubPanes, LArrayIterator::from_Start);
- LPane *theSub;
- while ( iterator.Next(&theSub) ) {
- if ( theSub->GetPaneID() == inID ) {
- CGATabBoxTab *theTab = dynamic_cast<CGATabBoxTab *>(theSub);
- if ( theTab != nil ) return theTab;
- }
- }
-
- Assert_(false); // Should have found tab!
- return nil;
- }
-
-
- /*======================================================================================
- Find the tab group for the window if it is currently active or nil if there is not
- one.
- ======================================================================================*/
-
- LTabGroup *CGATabBox::FindTabGroup(void) {
-
- LCommander *theCommander = LCommander::GetTarget();
-
- if ( !theCommander ) return nil;
-
- LCommander *windowCommander = dynamic_cast<LCommander *>(LWindow::FetchWindowObject(GetMacPort()));
- Assert_(windowCommander != nil);
-
- if ( windowCommander == theCommander ) return nil;
-
- LTabGroup *lastTabGroup = nil;
-
- do {
- LTabGroup *tabGroup = dynamic_cast<LTabGroup *>(theCommander);
- if ( tabGroup != nil ) {
- lastTabGroup = tabGroup;
- }
- } while ( ((theCommander = theCommander->GetSuperCommander()) != nil) &&
- (theCommander != windowCommander) );
-
- return lastTabGroup;
- }
-
-
- #pragma mark -
-
- /*======================================================================================
- Refresh just the bottom portion of the button.
- ======================================================================================*/
-
- void CGATabBoxTab::RefreshHiddenBottom(void) {
-
- Rect refreshRect;
- if ( IsVisible() && CalcPortFrameRect(refreshRect) ) {
- refreshRect.top = refreshRect.bottom - 5;
- Rect superRevealed;
- mSuperView->GetRevealedRect(superRevealed);
- if ( ::SectRect(&refreshRect, &superRevealed, &refreshRect) ) {
- InvalPortRect(&refreshRect);
- }
- }
- }
-
-
- /*======================================================================================
- Draw the button except for the bottom edge.
- ======================================================================================*/
-
- void CGATabBoxTab::DrawSelf(void) {
-
- Rect clipRect;
- CalcLocalFrameRect(clipRect);
-
- RgnHandle clipRgn = ::NewRgn();
-
- if ( IsSelectedTab() ) {
- RgnHandle tempRgn = ::NewRgn();
- clipRect.bottom -= 4;
- ::RectRgn(clipRgn, &clipRect);
- ::SetRect(&clipRect, clipRect.left + 1, clipRect.bottom, clipRect.right - 4, clipRect.bottom + 1);
- ::RectRgn(tempRgn, &clipRect);
- ::UnionRgn(clipRgn, tempRgn, clipRgn);
- ::DisposeRgn(tempRgn);
- } else {
- clipRect.bottom -= 5;
- ::RectRgn(clipRgn, &clipRect);
- }
-
- StClipRgnState saveClip(clipRgn);
- ::DisposeRgn(clipRgn);
-
- LGAPushButton::DrawSelf();
- }
-
-
- /*======================================================================================
- Clicking atomatically selects.
- ======================================================================================*/
-
- void CGATabBoxTab::ClickSelf(const SMouseDownEvent &/*inMouseDown*/) {
-
- BroadcastValueMessage();
- }
-
-
- /*======================================================================================
- Broadcast pane id instead of value message.
- ======================================================================================*/
-
- void CGATabBoxTab::BroadcastValueMessage(void) {
-
- MessageT valueMsg = mValueMessage;
- BroadcastMessage(mPaneID, &mValueMessage);
- }
-
-
- /*======================================================================================
- Offset since hiding a portion of button.
- ======================================================================================*/
-
- void CGATabBoxTab::CalcTitleRect(Rect &outRect) {
-
- LGAPushButton::CalcTitleRect(outRect);
-
- if ( IsSelectedTab() ) {
- ::OffsetRect(&outRect, 0, -1);
- } else {
- ::OffsetRect(&outRect, 0, -2);
- }
- }
-
-
- /*======================================================================================
- Draw darker if not selected. Direct copy/paste from LGAPushButton except for
- IsSelectedTab() sections.
- ======================================================================================*/
-
- void CGATabBoxTab::DrawButtonNormalColor(void) {
-
- StColorPenState theColorPenState;
- theColorPenState.Normalize();
-
- Boolean isSelected = IsSelectedTab();
-
- Rect localFrame;
- CalcLocalFrameRect ( localFrame );
-
- ::RGBForeColor (&UGAColorRamp::GetBlackColor());
- ::FrameRoundRect (&localFrame, 8, 8);
-
- if ( isSelected ) {
- ::RGBForeColor(&UGAColorRamp::GetColor(2));
- } else {
- ::RGBForeColor(&UGAColorRamp::GetColor(3));
- }
- ::InsetRect(&localFrame, 1, 1);
- ::PaintRoundRect(&localFrame, 4, 4);
- ::InsetRect(&localFrame, -1, -1);
-
- if ( isSelected ) {
- ::RGBForeColor(&UGAColorRamp::GetWhiteColor());
- } else {
- ::RGBForeColor(&UGAColorRamp::GetColor(1));
- }
- UGraphicsUtilities::TopLeftSide (&localFrame,
- 2, // TOP
- 2, // LEFT
- 3, // BOTTOM
- 3 ); // RIGHT
- UGraphicsUtilities::PaintColorPixel ( localFrame.left + 3, localFrame.top + 3, &UGAColorRamp::GetWhiteColor());
- UGraphicsUtilities::PaintColorPixel ( localFrame.left + 1, localFrame.top + 2, &UGAColorRamp::GetColor(4));
- UGraphicsUtilities::PaintColorPixel ( localFrame.left + 2, localFrame.top + 1, &UGAColorRamp::GetColor(4));
- UGraphicsUtilities::PaintColorPixel ( localFrame.left + 1, localFrame.bottom - 3, &UGAColorRamp::GetColor(4));
- UGraphicsUtilities::PaintColorPixel ( localFrame.left + 2, localFrame.bottom - 2, &UGAColorRamp::GetColor(4));
- UGraphicsUtilities::PaintColorPixel ( localFrame.right - 3, localFrame.top + 1, &UGAColorRamp::GetColor(4));
- UGraphicsUtilities::PaintColorPixel ( localFrame.right - 2, localFrame.top + 2, &UGAColorRamp::GetColor(4));
-
- // Ñ SHADOW EDGES
- ::RGBForeColor ( &UGAColorRamp::GetColor(8));
- ::MoveTo ( localFrame.left + 3, localFrame.bottom - 2 );
- ::LineTo ( localFrame.right - 3, localFrame.bottom - 2 );
- ::MoveTo ( localFrame.right - 2, localFrame.bottom - 3 );
- ::LineTo ( localFrame.right - 2, localFrame.top + 3 );
- ::RGBForeColor ( &UGAColorRamp::GetColor(5));
- UGraphicsUtilities::BottomRightSide ( &localFrame,
- 3, // TOP
- 3, // LEFT
- 2, // BOTTOM
- 2 ); // RIGHT
- UGraphicsUtilities::PaintColorPixel ( localFrame.right - 3, localFrame.bottom - 3, &UGAColorRamp::GetColor(8));
- UGraphicsUtilities::PaintColorPixel ( localFrame.right - 4, localFrame.bottom - 4, &UGAColorRamp::GetColor(5));
- }
-
-
-