home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / gui / CNavCenterSelectorPane.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  23.8 KB  |  801 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "CNavCenterSelectorPane.h"
  20.  
  21. #include <algorithm>
  22. #include <LStream.h>
  23.  
  24. #include "CRDFCoordinator.h"
  25. #include "CContextMenuAttachment.h"
  26. #include "Netscape_constants.h"
  27.  
  28.  
  29. #pragma mark -- CNavCenterSelectorPane methods --
  30.  
  31.  
  32. const RGBColor CNavCenterSelectorPane::mBGColor = { 0xDDDD, 0xDDDD, 0xDDDD };
  33.  
  34.  
  35. CNavCenterSelectorPane::CNavCenterSelectorPane( LStream* inStream )
  36.         : LView(inStream), LDragAndDrop ( GetMacPort(), this ),
  37.             mIsEmbedded(false), mHTPane(nil), mTooltipIndex(-1), mMouseIsInsidePane(false),
  38.             mImageMode(0L), mCellHeight(25), mCachedWorkspace(NULL)
  39. {
  40.     // nothing else to do here.
  41. }
  42.  
  43.  
  44. CNavCenterSelectorPane::~CNavCenterSelectorPane()
  45. {
  46.     // nothing else to do here since all FE data is cleaned up by workspace remove events
  47. }
  48.  
  49.  
  50. //
  51. // SetActiveWorkspace
  52. //
  53. // Call this to change the current workspace. Passing in NULL will clear the selection. Most
  54. // of the work is done in NoticeActiveWorkspaceChanged() where the view is redrawn and the
  55. // view change is broadcast to the RDFCoordinator. This doesn't actually change HT's
  56. // currently selected view, as it is done by the coordinator.
  57. //
  58. void
  59. CNavCenterSelectorPane :: SetActiveWorkspace ( HT_View inNewWorkspace )
  60. {
  61.     HT_View oldWorkspace = mCachedWorkspace;
  62.     mCachedWorkspace = inNewWorkspace;
  63.     NoticeActiveWorkspaceChanged(oldWorkspace);
  64.  
  65. } // SetActiveWorkspace
  66.  
  67.  
  68. //
  69. // DrawSelf
  70. //
  71. // Iterate over each view and draw it. We store the class that is responsible for drawing a 
  72. // workspace in the FE data in HT.
  73. //
  74. void
  75. CNavCenterSelectorPane::DrawSelf()
  76. {
  77.     Rect cellBounds;
  78.     CalcLocalFrameRect(cellBounds);
  79.     
  80.     // erase the background
  81.     StColorState saved;
  82.     ::RGBBackColor(&mBGColor);
  83.     ::EraseRect(&cellBounds);
  84.     
  85.     // find the bounds of the first cell
  86.     cellBounds.bottom = cellBounds.top + mCellHeight;
  87.  
  88. #if DRAW_WITH_TITLE
  89.     StTextState savedState;
  90.     UTextTraits::SetPortTextTraits(130);
  91. #endif
  92.         
  93.     // iterate over workspaces, drawing each in turn.
  94.     const listCount = HT_GetViewListCount(GetHTPane());
  95.     const HT_View selectedView = HT_GetSelectedView(GetHTPane());
  96.     for ( int i = 0; i < listCount; i++ ) {
  97.         unsigned long drawMode = mImageMode;
  98.  
  99.         HT_View currView = HT_GetNthView(GetHTPane(), i);
  100.         SelectorData* viewData = static_cast<SelectorData*>(HT_GetViewFEData(currView));
  101.         if ( viewData ) {
  102.             if ( currView == selectedView )
  103.                 drawMode |= kSelected;
  104.             viewData->workspaceImage->DrawInCurrentView(cellBounds, drawMode);
  105.         }
  106.         
  107.         // prepare to draw next selector
  108.         cellBounds.top += mCellHeight;
  109.         cellBounds.bottom += mCellHeight;
  110.  
  111.     } // for each selector
  112.     
  113. } // DrawSelf
  114.  
  115.  
  116. //
  117. // ClickSelf
  118. //
  119. // Handle when the user clicks in this pane. A click on a workspace icon will switch to that
  120. // view. Also handle opening and closing the shelf (if we're embedded) and context clicking.
  121. //
  122. void
  123. CNavCenterSelectorPane::ClickSelf( const SMouseDownEvent& inMouseDown )
  124. {
  125.     FocusDraw();    // to make the context menu stuff works
  126.  
  127.     CContextMenuAttachment::SExecuteParams params;
  128.     params.inMouseDown = &inMouseDown;
  129.                 
  130.     // do nothing if click not in any workspace except show context menu.
  131.     HT_View clickedView = FindSelectorForPoint(inMouseDown.whereLocal);
  132.     if ( !clickedView ) {
  133.         ExecuteAttachments(CContextMenuAttachment::msg_ContextMenu, (void*)¶ms);
  134.         return;
  135.     }
  136.     
  137.     // if the user clicks on a workspace icon, open the shelf to display the workspace. If
  138.     // they click on the same workspace icon as is already displayed, close the shelf. Don't
  139.     // change the shelf state on a context click.
  140.     if ( clickedView != GetActiveWorkspace() ) {
  141.         HT_View oldSelection = GetActiveWorkspace();
  142.         SetActiveWorkspace(clickedView);
  143.  
  144.         ExecuteAttachments(CContextMenuAttachment::msg_ContextMenu, (void*)¶ms);
  145.         if ( params.outResult != CContextMenuAttachment::eHandledByAttachment && mIsEmbedded ) {
  146.             bool value = true;
  147.             BroadcastMessage ( msg_ShelfStateShouldChange, &value );        // force open
  148.         }
  149.         else {
  150.             // this combats the problem when there is no workspace and the user context clicks. We
  151.             // select the one they clicked on, but don't open the shelf. We can't just leave the
  152.             // item selected and the shelf closed, so we just reset the active workspace to none.
  153.             // Icky code but it doesn't freak out the user. 
  154.             if ( !oldSelection )
  155.                 SetActiveWorkspace(NULL);
  156.         }
  157.     }
  158.     else {
  159.         ExecuteAttachments(CContextMenuAttachment::msg_ContextMenu, (void*)¶ms);
  160.         if ( params.outResult != CContextMenuAttachment::eHandledByAttachment && mIsEmbedded ) {
  161.             bool value = false;
  162.             BroadcastMessage ( msg_ShelfStateShouldChange, &value );        // force closed
  163.             SetActiveWorkspace( NULL );
  164.         }
  165.     }
  166.     
  167. } // ClickSelf
  168.  
  169.  
  170. //
  171. // AdjustCursorSelf
  172. //
  173. // Use the context menu attachment to handle showing context menu cursor when cmd key is
  174. // down and mouse is over this view.
  175. //
  176. void
  177. CNavCenterSelectorPane::AdjustCursorSelf( Point /*inPoint*/, const EventRecord& inEvent )
  178. {
  179.     ExecuteAttachments(CContextMenuAttachment::msg_ContextMenuCursor, 
  180.                                 static_cast<void*>(const_cast<EventRecord*>(&inEvent)));
  181.  
  182. } // AdjustCursorSelf
  183.  
  184.  
  185. //
  186. // FindTooltipForMouseLocation
  187. //
  188. // Provide the tooltip for the workspace that the mouse is hovering over
  189. //
  190. void
  191. CNavCenterSelectorPane :: FindTooltipForMouseLocation ( const EventRecord& inMacEvent,
  192.                                                         StringPtr outTip )
  193. {
  194.     Point temp = inMacEvent.where;
  195.     GlobalToPortPoint(temp);
  196.     PortToLocalPoint(temp);
  197.     
  198.     HT_View selector = FindSelectorForPoint ( temp );
  199.     if ( selector ) {
  200.         // pull the name out of HT and stuff it into the Pascal string...DO NOT DELETE |buffer|.
  201.         const char* buffer = HT_GetViewName ( selector );
  202.         outTip[0] = strlen(buffer);
  203.         strcpy ( (char*) &outTip[1], buffer );
  204.     } 
  205.     else
  206.         ::GetIndString ( outTip, 10506, 15);                // supply a helpful message...
  207.  
  208. } // FindTooltipForMouseLocation
  209.  
  210.  
  211. //
  212. // MouseLeave
  213. //
  214. // Called when the mouse leaves the view. Just update our "hot" cell to an invalid cell.
  215. //
  216. void 
  217. CNavCenterSelectorPane :: MouseLeave ( ) 
  218. {
  219.     mTooltipIndex = -1;
  220.     mMouseIsInsidePane = false;
  221.         
  222. } // MouseLeave
  223.  
  224.  
  225. //
  226. // MouseWithin
  227. //
  228. // Called while the mouse moves w/in the pane. Find which workspace the mouse is
  229. // currently over and if it differs from the last workspace it was in, hide the 
  230. // tooltip and remember the new cell. 
  231. //
  232. void 
  233. CNavCenterSelectorPane :: MouseWithin ( Point inPortPt, const EventRecord& /*inEvent*/ ) 
  234. {
  235.     mMouseIsInsidePane = true;
  236.     
  237.     size_t index = FindIndexForPoint ( inPortPt );
  238.     if ( mTooltipIndex != index ) {
  239.         mTooltipIndex = index;        
  240.         ExecuteAttachments(msg_HideTooltip, this);    // hide tooltip
  241.     }
  242.     
  243. } // MouseWithin
  244.  
  245.  
  246. //
  247. // NoticeActiveWorkspaceChanged
  248. //
  249. // Redraw the old and new workspace icons only when there is a change. Also tell the RDFCoordinator
  250. // to update HT's active workspace.
  251. //
  252. void
  253. CNavCenterSelectorPane :: NoticeActiveWorkspaceChanged ( HT_View inOldSel )
  254. {
  255.     BroadcastMessage(msg_ActiveSelectorChanged, GetActiveWorkspace());
  256.  
  257.     FocusDraw();
  258.     
  259. #if DRAW_WITH_TITLE
  260.     StTextState savedState;
  261.     ::TextFont(kFontIDGeneva);
  262.     ::TextSize(9);
  263.     ::TextFace(0);
  264. #endif
  265.     
  266.     // redraw old
  267.     Rect previous = { 0, 0, 0, 0 };
  268.     if ( inOldSel ) {
  269.         CalcLocalFrameRect(previous);
  270.         previous.top = HT_GetViewIndex(inOldSel) * mCellHeight;
  271.         previous.bottom = previous.top + mCellHeight;
  272.         SelectorData* data = static_cast<SelectorData*>(HT_GetViewFEData(inOldSel));
  273.         data->workspaceImage->DrawInCurrentView ( previous, mImageMode );
  274.     }
  275.     
  276.     // redraw new
  277.     Rect current = { 0, 0, 0, 0 };
  278.     if ( GetActiveWorkspace() ) {
  279.         CalcLocalFrameRect(current);
  280.         current.top = HT_GetViewIndex(GetActiveWorkspace()) * mCellHeight;
  281.         current.bottom = current.top + mCellHeight;
  282.         SelectorData* data = static_cast<SelectorData*>(HT_GetViewFEData(GetActiveWorkspace()));
  283.         data->workspaceImage->DrawInCurrentView ( current, mImageMode | kSelected );
  284.     }
  285.     
  286.     
  287. } // NoticeActiveWorkspaceChanged
  288.  
  289.  
  290. //
  291. // ItemIsAcceptable
  292. //
  293. // Just about anything should be acceptable because we just want to make sure
  294. // that the appropriate nav center view is open for the user to then drag into. Drops
  295. // can occur here, so I guess we have to make sure that it is something that we
  296. // recognize (TEXT, for example, should not be allowed).
  297. //
  298. Boolean
  299. CNavCenterSelectorPane :: ItemIsAcceptable ( DragReference /*inDragRef*/, ItemReference /*inItemRef*/ )
  300. {
  301.     return true;    // for now....
  302.         
  303. } // ItemIsAcceptable
  304.  
  305.  
  306. //
  307. // EnterDropArea
  308. //
  309. // If the drag comes from an outside source, record when the mouse entered this pane
  310. //
  311. void
  312. CNavCenterSelectorPane :: EnterDropArea ( DragReference /* inDragRef */, Boolean inDragHasLeftSender )
  313. {
  314.     // if the drag did not originate here, go into "timed switching" mode
  315.     if ( inDragHasLeftSender )
  316.         mDragAndDropTickCount = ::TickCount();
  317.  
  318. } // EnterDropArea
  319.  
  320.  
  321. //
  322. // LeaveDropArea
  323. //
  324. // Reset our counter
  325. //
  326. void
  327. CNavCenterSelectorPane :: LeaveDropArea ( DragReference /* inDragRef */ )
  328. {
  329.     mDragAndDropTickCount = 0L;
  330.  
  331. } // LeaveDropArea
  332.  
  333.  
  334. //
  335. // InsideDropArea
  336. //
  337. // Called when the mouse moves inside this pane on a drag and drop.
  338. //
  339. // There are two cases here: the drag originated here or it didn't. When it did, the user
  340. // is trying to rearrange the order of the views. When the drag comes from outside, we need
  341. // to do our fancy timed switching behavior. We can tell the difference between these two
  342. // modes by checking the value of |mDragAndDropTickCount| which will be non-zero if the 
  343. // drag originated outside.
  344. //
  345. void
  346. CNavCenterSelectorPane :: InsideDropArea ( DragReference inDragRef )
  347. {
  348.     const Uint32 kPaneSwitchDelay = 60;        // 1 second delay
  349.     
  350.     if ( mDragAndDropTickCount ) {
  351.     
  352.         FocusDraw();
  353.         Point mouseLoc;
  354.         ::GetDragMouse(inDragRef, &mouseLoc, NULL);
  355.         ::GlobalToLocal(&mouseLoc);
  356.  
  357.         // if the user has dragged down into a place where there are no
  358.         // workspaces, don't do anything.
  359.         HT_View newSelection = FindSelectorForPoint(mouseLoc);
  360.         if ( !newSelection ) {
  361.             mDragAndDropTickCount = ::TickCount();        // see comment below
  362.             return;
  363.         }
  364.             
  365.         // if the user hasn't sat here long enough, don't do anything...
  366.         if ( ::TickCount() - mDragAndDropTickCount < kPaneSwitchDelay )
  367.             return;
  368.         
  369.         // ...ok, they really want to switch panes...
  370.                 
  371.         // make sure the shelf is visible (only necessary if in chrome). This
  372.         // shouldn't be necessary, but things won't redraw correctly unless we do this.
  373.         if ( mIsEmbedded ) {
  374.             bool value = true;
  375.             BroadcastMessage ( msg_ShelfStateShouldChange, &value );        // force open
  376.         }
  377.         
  378.         // switch to the workspace the user is now hovering over
  379.         if ( newSelection != GetActiveWorkspace() )
  380.             SetActiveWorkspace ( newSelection );
  381.  
  382.         // we need to reset the timer so we don't get into the situation where the user
  383.         // hovers over the selected item for a long time and then when they move to the next
  384.         // selector, the time will be > |kPaneSwitchDelay| and it will instantly switch.
  385.         // Keeping our timer up to date should avoid this and force the user to always
  386.         // wait the delay. NOTE: we don't get here if they have yet to reach the delay amount
  387.         // so we're not actually reseting the timer every time this is called.
  388.         mDragAndDropTickCount = ::TickCount();
  389.  
  390.     } // if we are tracking an outside drag.
  391.     else {
  392.         // do nothing as of yet...
  393.     }
  394.     
  395. } // InsideDropArea
  396.  
  397.  
  398. //
  399. // CycleCurrentWorkspace
  400. //
  401. // If the shelf is open, advance the current workspace, wrapping around if we get to the end
  402. //
  403. void
  404. CNavCenterSelectorPane :: CycleCurrentWorkspace ( )
  405. {
  406.     if ( GetActiveWorkspace() ) {
  407.         HT_View newSelector = HT_GetNthView ( GetHTPane(), 
  408.                                     HT_GetViewIndex(GetActiveWorkspace()) + 1 );
  409.         if ( !newSelector )
  410.             newSelector = HT_GetNthView ( GetHTPane(), 0 );
  411.     
  412.         SetActiveWorkspace(newSelector);
  413.     } // if there is a selection
  414.  
  415. } // CycleCurrentWorkspace
  416.  
  417.  
  418. //
  419. // FindIndexForPoint
  420. //
  421. // Given a point in image coordinates, find the index of the selector the mouse was over. Right
  422. // now, this is just an easy division because the selector regions all butt up against each
  423. // other. If there were ever any space between them, this would need to be more complicated.
  424. //
  425. // This index is 0-based, not 1-based like most other things in Powerplant. This is ok because
  426. // HT is also 0-based and we only use this index when talking to HT. 
  427. //
  428. size_t
  429. CNavCenterSelectorPane :: FindIndexForPoint ( const Point & inMouseLoc ) const
  430. {
  431.     return inMouseLoc.v / mCellHeight;
  432.     
  433. } // FindIndexForPoint
  434.  
  435.  
  436. //
  437. // FindSelectorForPoint
  438. //
  439. // Grabs the view where the user clicked from HT and returns it.
  440. //
  441. HT_View
  442. CNavCenterSelectorPane :: FindSelectorForPoint ( const Point & inMouseLoc ) const
  443. {
  444.     return HT_GetNthView ( GetHTPane(), FindIndexForPoint(inMouseLoc) );
  445.     
  446. } // FindSelectorForPoint
  447.  
  448.  
  449. //
  450. // FindCommandStatus
  451. //
  452. void
  453. CNavCenterSelectorPane :: FindCommandStatus ( CommandT inCommand, Boolean &outEnabled,
  454.                                         Boolean &outUsesMark, Char16 &outMark, Str255 outName)
  455. {
  456.     if ( inCommand >= cmd_NavCenterBase && inCommand <= cmd_NavCenterCap )
  457.         outEnabled = HT_IsMenuCmdEnabled(GetHTPane(), (HT_MenuCmd)(inCommand - cmd_NavCenterBase));
  458.     else
  459.         LCommander::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
  460.     
  461. } // FindCommandStatus
  462.  
  463.  
  464. #pragma mark --- struct SelectorData ---
  465.  
  466.  
  467. SelectorData :: SelectorData ( HT_View inView )
  468. {
  469.     const ResIDT cFolderIconID = -3999;        // use the OS Finder folder icon
  470.     enum { kWorkspaceID = cFolderIconID, kHistoryID = 16251, kSearchID = 16252, kSiteMapID = 16253 };
  471.  
  472.     char viewName[64];
  473. #if DRAW_WITH_TITLE
  474.     HT_ViewDisplayString ( inView, viewName, 8 );
  475.     viewName[8] = NULL;
  476. #else
  477.     viewName[0] = NULL;
  478. #endif
  479.     
  480.     // ÑÑÑ HACK: figure out what pane this is and give it an icon. We should just be
  481.     // using the url given and pass that to the imageLib, but the API is too complicated
  482.     // and I just can't figure it out. Instead, parse the url string looking for things
  483.     // we recognize and use the "Finder folder" icon if we can't determine it.
  484.     char* iconURL = HT_GetWorkspaceLargeIconURL(inView);
  485.  
  486.     char workspace[500];
  487.     workspace[0] = NULL;            // clear out value left on stack from last time.
  488.     ResIDT iconID = kWorkspaceID;
  489.     sscanf ( iconURL, "icon/large:workspace,%s", workspace );
  490.     if ( strcmp(workspace, "history") == 0 )
  491.         iconID = kHistoryID;
  492.     else if ( strcmp(workspace, "search") == 0 )
  493.         iconID = kSearchID;
  494.     else if ( strcmp(workspace, "sitemap") == 0 )
  495.         iconID = kSiteMapID;
  496.     
  497.     workspaceImage = new TitleImage(viewName, iconID);
  498.  
  499. } // constructor
  500.  
  501. SelectorData :: ~SelectorData ( )
  502. {
  503.     delete workspaceImage;
  504. }
  505.  
  506.  
  507. #pragma mark -- class TitleImage --
  508.  
  509. #include "UGraphicGizmos.h"
  510.  
  511. TitleImage :: TitleImage ( const LStr255 & inTitle, ResIDT inIconID ) 
  512.     : mTitle(inTitle), mIconID(inIconID)
  513. {
  514. #if DRAW_WITH_TITLE
  515.     ::TextFont(kFontIDGeneva);
  516.     ::TextSize(9);
  517.     ::TextFace(0);
  518.     mTextWidth = ::TextWidth( inTitle, 0, inTitle.Length() ) + 6;
  519. #endif
  520. }
  521.  
  522.  
  523. //
  524. // DrawInCurrentView
  525. //
  526. // Draw a selector. The code for drawing the title has been commented out for now because
  527. // it has not been hooked up to the text/graphics prefs.
  528. //
  529. void
  530. TitleImage :: DrawInCurrentView( const Rect& inBounds, unsigned long inMode ) const
  531. {
  532.     StColorState saved;
  533.     
  534.     ::RGBBackColor(&CNavCenterSelectorPane::mBGColor);
  535.     ::EraseRect(&inBounds);
  536.     
  537.     Rect iconRect = inBounds;
  538.     Rect textbg = { 0, 0, 0, 0 };
  539.  
  540. #if DRAW_WITH_TITLE    
  541.     if ( TextWidth() > inBounds.right - inBounds.left )
  542.         textbg.right = inBounds.right - inBounds.left;
  543.     else
  544.         textbg.right = TextWidth();
  545.     UGraphicGizmos::CenterRectOnRect(textbg, inBounds);
  546.     textbg.bottom = inBounds.bottom;
  547.     textbg.top = inBounds.bottom - 12;
  548. #endif
  549.     
  550.     iconRect.right     = iconRect.left + 16;
  551.     iconRect.bottom    = iconRect.top  + 16;
  552.     UGraphicGizmos::CenterRectOnRect ( iconRect, inBounds );
  553.         
  554.     SInt16 iconTransform = kTransformNone;
  555.     if ( inMode & CNavCenterSelectorPane::kSelected ) {
  556.         iconTransform = kTransformSelected;
  557. #if DRAW_WITH_TITLE    
  558.         ::BackColor(blackColor);
  559.         ::EraseRect(&textbg);
  560.         ::TextMode(srcXor);
  561. #endif
  562. #if DRAW_SELECTED_AS_TAB
  563.         Rect temp = inBounds;
  564.         temp.left += 2;
  565.         StRegion boundsRgn(temp);
  566.         DrawOneTab(boundsRgn);
  567. #endif
  568.     }
  569.  
  570.     OSErr err = ::PlotIconID(&iconRect, kAlignNone, iconTransform, IconID());
  571.  
  572. #if DRAW_WITH_TITLE
  573.     ::MoveTo( textbg.left + 2, inBounds.bottom - 2 );
  574.     ::DrawString ( Title() );
  575. #endif
  576.  
  577. } // DrawInCurrentView
  578.  
  579. #if DRAW_SELECTED_AS_TAB
  580.  
  581. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  582. //    Ñ    
  583. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  584.  
  585. void TitleImage::DrawOneTabBackground(
  586.     RgnHandle inRegion,
  587.     Boolean inCurrentTab) const
  588. {
  589.     SBevelColorDesc            mActiveColors;
  590.     
  591.     SBevelColorDesc theTabColors;
  592.     UGraphicGizmos::LoadBevelTraits(1000, theTabColors);
  593.     Int16 thePaletteIndex = theTabColors.fillColor;
  594. //    if (mTrackInside)
  595. //        thePaletteIndex--;
  596.     ::PmForeColor(thePaletteIndex);
  597.     ::PaintRgn(inRegion);
  598. }
  599.  
  600. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  601. //    Ñ    
  602. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  603.  
  604. void TitleImage::DrawOneTabFrame(RgnHandle inRegion, Boolean inCurrentTab) const
  605. {
  606.     // Draw the tab frame    
  607.     SBevelColorDesc theTabColors;
  608.     UGraphicGizmos::LoadBevelTraits(1000, theTabColors);
  609.     Int16 thePaletteIndex = theTabColors.frameColor;
  610.     ::PmForeColor(thePaletteIndex);
  611.     ::FrameRgn(inRegion);
  612. }
  613.  
  614. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  615. //    Ñ    
  616. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  617.  
  618. void TitleImage::DrawCurrentTabSideClip(RgnHandle inRegion) const
  619. {
  620.     SBevelColorDesc theTabColors;
  621.     UGraphicGizmos::LoadBevelTraits(1000, theTabColors);
  622.     
  623.     // Always only for the current tab
  624.     ::SetClip(inRegion);
  625.     ::PmForeColor(theTabColors.fillColor);
  626. //    ::PaintRect(&mSideClipFrame);
  627. }
  628.  
  629. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  630. //    Ñ    
  631. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  632.  
  633.  
  634. void TitleImage::DrawOneTab(RgnHandle inBounds) const
  635. {
  636.     StClipRgnState theClipSaver;
  637.  
  638. #if 0
  639.     Rect theControlFrame;
  640.     CalcLocalFrameRect(theControlFrame);
  641.  
  642.     Boolean isCurrentTab = (inTab == mCurrentTab);
  643.     if (isCurrentTab)
  644.         {
  645.         StRegion theTempMask(inTab->mMask);
  646.         StRegion theSideMask(mSideClipFrame);
  647.         ::DiffRgn(theTempMask, theSideMask, theTempMask);
  648.         ::SetClip(theTempMask);
  649.         }
  650.     else
  651.         {
  652.         StRegion theTempMask(inTab->mMask);
  653.         ::DiffRgn(theTempMask, mCurrentTab->mMask, theTempMask);
  654.         ::SetClip(theTempMask);
  655.         }
  656. #endif
  657.     
  658.     // This draws the fill pattern in the tab    
  659.     DrawOneTabBackground(inBounds, true);
  660.     // This just calls FrameRgn on inTab->mMask
  661. //    DrawOneTabFrame(inBounds, true);
  662.  
  663.     StColorPenState thePenSaver;
  664.     thePenSaver.Normalize();
  665.  
  666.     DrawCurrentTabSideClip(inBounds);
  667.  
  668.     Uint8 mBevelDepth = 2;
  669.     if (mBevelDepth > 0)
  670.     {
  671.  
  672.         ::PenSize(mBevelDepth, mBevelDepth);
  673.  
  674.         bool isCurrentTab = true;
  675.         if (isCurrentTab) {
  676.             // Draw the top bevel        
  677.             RGBColor    theAddColor = {0x4000, 0x4000, 0x4000};
  678.             ::RGBForeColor(&theAddColor);
  679.             ::OpColor(&UGraphicGizmos::sLighter);
  680.             ::PenMode(subPin);
  681.             
  682.             // This runs the pen around the top and left sides
  683.             DrawTopBevel(inBounds);
  684.         }
  685.  
  686.         // Draw the bevel shadow
  687. //        StRegion theShadeRgn(inTab->mShadeFrame);
  688.         
  689. //        ::SetClip(theShadeRgn);
  690.         // Set up the colors for the bevel shadow
  691.         RGBColor    theSubColor = {0x4000, 0x4000, 0x4000};
  692.         ::RGBForeColor(&theSubColor);
  693.         ::OpColor(&UGraphicGizmos::sDarker);
  694.         ::PenMode(subPin);
  695.         // This runs the pen around the bottom and right sides
  696.         DrawBottomBevel(inBounds, true);
  697.     }
  698.  
  699. }
  700.  
  701. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  702. //    Ñ    
  703. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  704.  
  705. void TitleImage::DrawTopBevel(RgnHandle inBounds) const
  706. {
  707.     const Rect& theTabFrame = (**inBounds).rgnBBox;
  708.     enum { eNorthTab = 0, eEastTab, eSouthTab, eWestTab };
  709.     Uint8 mOrientation = eWestTab;
  710.     Uint8 mCornerPixels = 5, mBevelDepth = 2;
  711.     
  712.     switch (mOrientation)
  713.         {
  714.         case eNorthTab:
  715.             {
  716.             ::MoveTo(theTabFrame.left + 1, theTabFrame.bottom + 1);
  717.             ::LineTo(theTabFrame.left + 1, theTabFrame.top + mCornerPixels);
  718.             ::LineTo(theTabFrame.left + mCornerPixels, theTabFrame.top + 1);
  719.             ::LineTo(theTabFrame.right - (mCornerPixels + mBevelDepth) + 1, theTabFrame.top + 1);
  720.             }
  721.             break;
  722.  
  723.         case eEastTab:
  724.             {
  725.             // I'm not sure whether this is quite right...
  726.             ::MoveTo(theTabFrame.left - 1, theTabFrame.top + 1);
  727.             ::LineTo(theTabFrame.right - (mCornerPixels + mBevelDepth) + 1, theTabFrame.top + 1);
  728.             ::LineTo(theTabFrame.right - mBevelDepth, theTabFrame.top + mCornerPixels);
  729.             }
  730.             break;
  731.             
  732.         case eSouthTab:
  733.             {
  734.             // I'm not sure whether this is quite right...
  735.             ::MoveTo(theTabFrame.left + 1, theTabFrame.top - 1);
  736.             ::LineTo(theTabFrame.left + 1, theTabFrame.bottom - (mCornerPixels + mBevelDepth) + 1);
  737.             ::LineTo(theTabFrame.left + mCornerPixels, theTabFrame.bottom - mBevelDepth);
  738.             }
  739.             break;
  740.         
  741.         case eWestTab:
  742.             {
  743.             ::MoveTo(theTabFrame.right + 1, theTabFrame.top + 1);
  744.             ::LineTo(theTabFrame.left + mCornerPixels, theTabFrame.top + 1);
  745.             ::LineTo(theTabFrame.left + 1, theTabFrame.top + mCornerPixels);
  746.             ::LineTo(theTabFrame.left + 1, theTabFrame.bottom - (mCornerPixels + mBevelDepth) + 1);
  747.             }
  748.             break;
  749.         }
  750. }
  751.  
  752. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  753. //    Ñ    DrawBottomBevel
  754. // ╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  755.  
  756. void TitleImage::DrawBottomBevel(RgnHandle inBounds, Boolean    inCurrentTab) const
  757. {
  758.     const Rect& theTabFrame = (**inBounds).rgnBBox;
  759.     enum { eNorthTab = 0, eEastTab, eSouthTab, eWestTab };
  760.     Uint8 mOrientation = eWestTab;
  761.     Uint8 mCornerPixels = 5, mBevelDepth = 2;
  762.  
  763.     switch (mOrientation)
  764.         {
  765.         case eNorthTab:
  766.             {
  767.             ::MoveTo(theTabFrame.right - mBevelDepth, theTabFrame.top + mCornerPixels);
  768.             ::LineTo(theTabFrame.right - mBevelDepth, theTabFrame.bottom + 1);
  769.             }
  770.             break;
  771.  
  772.         case eEastTab:
  773.             {
  774.             // I'm not sure whether this is quite right...
  775.             ::MoveTo(theTabFrame.right - mBevelDepth, theTabFrame.top + mCornerPixels);            
  776.             ::LineTo(theTabFrame.right - mBevelDepth, theTabFrame.bottom - (mCornerPixels + mBevelDepth) + 1);
  777.             ::LineTo(theTabFrame.right - (mCornerPixels + mBevelDepth) + 1, theTabFrame.bottom - mBevelDepth);
  778.             ::LineTo(theTabFrame.left - 1, theTabFrame.bottom - mBevelDepth);
  779.             }
  780.             break;
  781.             
  782.         case eSouthTab:
  783.             {
  784.             // I'm not sure whether this is quite right...
  785.             ::MoveTo(theTabFrame.left + mCornerPixels, theTabFrame.bottom - mBevelDepth);
  786.             ::LineTo(theTabFrame.right - (mCornerPixels + mBevelDepth) + 1, theTabFrame.bottom - mBevelDepth);
  787.             ::LineTo(theTabFrame.right - mBevelDepth, theTabFrame.bottom - (mCornerPixels + mBevelDepth) + 1);
  788.             ::LineTo(theTabFrame.right - mBevelDepth, theTabFrame.top - 1);
  789.             }
  790.             break;
  791.         
  792.         case eWestTab:
  793.             {
  794.             ::MoveTo(theTabFrame.left + mCornerPixels, theTabFrame.bottom - mBevelDepth);
  795.             ::LineTo(theTabFrame.right + 1, theTabFrame.bottom - mBevelDepth);
  796.             }
  797.             break;
  798.         }
  799. }
  800.  
  801. #endif