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

  1. /*-----------------------------------------------------------------------------
  2.     StdPopup
  3.     Written 1994 Netscape Communications Corporation
  4.     
  5.     Portions derived from MacApp, 
  6.     Copyright ⌐ 1984-1994 Apple Computer, Inc. All rights reserved.
  7. -----------------------------------------------------------------------------*/
  8.  
  9. // primary header
  10. #include "PopupBox.h"
  11. // local libraries
  12. // cross-platform libraries
  13. #include "xpassert.h"
  14. #include "xp_trace.h"
  15. // PowerPlant
  16. #include <UDrawingState.h>
  17. #include <URegistrar.h>
  18. #include <LStdControl.h>
  19. // Macintosh headers
  20. #include <Icons.h>
  21. #include <Memory.h>
  22. #include <Menus.h>
  23. #include <OSUtils.h>
  24. #include <Traps.h>
  25. // ANSI headers
  26. #include <stdio.h>
  27. #include <UGAColorRamp.h>
  28. #include <UGraphicsUtilities.h>
  29. #include "UFontSwitcher.h"
  30. #include "UUTF8TextHandler.h"
  31. #include "UPropFontSwitcher.h"
  32. #include "UCustomizePopUp.h"
  33. #include "LCustomizeMenu.h"
  34.  
  35.  
  36. //-----------------------------------------------------------------------------
  37. // random stuff
  38. //-----------------------------------------------------------------------------
  39.  
  40. #define SETMODRECT(DEST,SOURCE,TOP,LEFT,BOTTOM,RIGHT) \
  41.     SetRect (&(DEST), (SOURCE).LEFT, (SOURCE).TOP, (SOURCE).RIGHT, (SOURCE).BOTTOM)
  42.  
  43.  
  44. #ifndef GetMenuProc
  45. #define GetMenuProc(menu)    (*((Handle *) ((*((Ptr *) (menu))) + 0x06)))
  46. #endif
  47.  
  48.  
  49. //-----------------------------------------------------------------------------
  50. // Discrete List Box
  51. //-----------------------------------------------------------------------------
  52. const Int16    fontNumber_Unknown    = -1;
  53.  
  54. StdPopup::StdPopup (CGAPopupMenu * target)
  55. :    LAttachment ()
  56. {
  57.     ThrowIfNil_(fTarget = target);
  58.     fTarget->SetNeedCustomDrawFlag(NeedCustomPopup());
  59.     mExecuteHost = false;
  60.     fMenu = nil;
  61.     fDirty = true;
  62. }
  63.  
  64. StdPopup::~StdPopup ()
  65. {
  66.     if (fMenu)
  67.         DisposeMenu (fMenu);
  68. }
  69.  
  70. //
  71. // definition
  72. //
  73.  
  74. short
  75. StdPopup::GetCount ()
  76. {
  77.     return 0;
  78. }
  79.  
  80. CStr255    
  81. StdPopup::GetText (short item)
  82. {
  83.     char buffer [20];
  84.     sprintf (buffer, "%hi", item);
  85.     return buffer;
  86. }
  87.  
  88. //
  89. // interface
  90. //
  91.  
  92. const int tlo = 18; // offset of text from left side of widget
  93. const int tls = 23; // offset from right side of widget to left side of triangle icon
  94.  
  95. Point
  96. StdPopup::CalcTargetFrame (short & baseline)
  97. {
  98.     SyncMenu (fTarget->GetMacMenuH());
  99.     
  100.     Point size;
  101.     size.v = /* text */ 16 + /* border */ 3;
  102.     size.h = CalcMaxWidth (fTarget->GetMacMenuH()) + tls;
  103.     
  104.     StColorPenState saveColorPenState;
  105.     StTextState saveTextState;
  106.     saveColorPenState.Normalize();
  107.     saveTextState.Normalize();
  108.     
  109.     FontInfo fontInfo;
  110.     GetFontInfo (&fontInfo);
  111.     baseline = 1 + fontInfo.ascent;
  112.     size.v = fontInfo.ascent+fontInfo.descent+fontInfo.leading+ 2;
  113.     return size;
  114. }
  115.  
  116. void
  117. StdPopup::DirtyMenu ()
  118. {
  119.     fDirty = true;
  120. }
  121.  
  122. //
  123. // internal
  124. //
  125.  
  126. short
  127. StdPopup::CalcMaxWidth (MenuHandle aquiredMenu)
  128. {
  129.     if (1 || fDirty)
  130.     {
  131.         Rect menuRect;
  132.         Point hitPt = {0,0};
  133.         short whichItem;
  134.         MenuDefUPP * menuProc = (MenuDefUPP*) (*aquiredMenu)->menuProc;
  135.         
  136.         SInt8 theState = HGetState((*aquiredMenu)->menuProc);
  137.         HLock((*aquiredMenu)->menuProc);
  138.         CallMenuDefProc (*menuProc, mSizeMsg, aquiredMenu, &menuRect, hitPt, &whichItem);
  139.         HSetState((*aquiredMenu)->menuProc, theState);
  140.     }
  141.     return (*aquiredMenu)->menuWidth;
  142. }
  143.  
  144. void StdPopup::DrawTruncTextBox (CStr255 text, const Rect& box)
  145. {
  146. /*
  147.         Truncates the text before drawing.
  148.         Does not word wrap.
  149. */
  150.         FontInfo fontInfo;
  151.         GetFontInfo (&fontInfo);
  152.         MoveTo (box.left, box.bottom - fontInfo.descent -1);
  153.         TruncString (box.right - box.left, text, truncEnd);
  154.         DrawString (text);
  155. }
  156.  
  157. void StdPopup::DrawWidget (MenuHandle aquiredMenu, const Rect & widgetFrame)
  158. {
  159.     StColorPenState saveColorPenState;
  160.     StTextState saveTextState;
  161.     saveColorPenState.Normalize();
  162.     saveTextState.Normalize();
  163.     
  164.     if (GetTextTraits() != fontNumber_Unknown)
  165.         UTextTraits::SetPortTextTraits(GetTextTraits());
  166.     Rect r;
  167.     
  168.     SETMODRECT(r,widgetFrame,top+1,left+1,bottom-2,right-2);
  169.     EraseRect (&r);
  170.     
  171.     MoveTo (widgetFrame.left + 3, widgetFrame.bottom - 1);
  172.     LineTo (widgetFrame.right -1, widgetFrame.bottom - 1);
  173.     MoveTo (widgetFrame.right -1, widgetFrame.top + 3);
  174.     LineTo (widgetFrame.right -1, widgetFrame.bottom - 1);
  175.     SETMODRECT(r,widgetFrame,top,left,bottom-1,right-1);
  176.     FrameRect (&r);
  177.     
  178.     SETMODRECT(r,widgetFrame,top-1,right-tls,top-1+16,right-tls+16);
  179.     ::PlotIconID (&r, atNone, ttNone, 'cz');
  180.     
  181.     short whichItem = fTarget->GetValue();
  182.     CStr255 itemText;
  183.     if (whichItem)
  184.         GetMenuItemText (aquiredMenu, whichItem, itemText);
  185.     SETMODRECT(r,widgetFrame,top+1,left+tlo,bottom-1,right-tls);
  186.     DrawTruncTextBox (itemText, r);
  187. }
  188.  
  189. void
  190. StdPopup::ExecuteSelf (MessageT message, void *param)
  191. {
  192.     fTarget->SetNeedCustomDrawFlag(NeedCustomPopup());
  193.     switch (message) {
  194.     case msg_DrawOrPrint: {
  195.         // 97-06-07 pkc -- put back SyncMenu otherwise Javascript reflection back
  196.         // into popup menu list is broken
  197.         SyncMenu (fTarget->GetMacMenuH());
  198.         mExecuteHost = true;
  199.         break;
  200.     }
  201.     case msg_Click: {
  202.         Rect frame;
  203.         SMouseDownEvent* event = (SMouseDownEvent*) param;
  204.         ThrowIfNil_(event);
  205.         {
  206.                                             // Determine which HotSpot was clicked
  207.             Int16    theHotSpot = fTarget->FindHotSpot(event->whereLocal);
  208.             
  209.             if (theHotSpot > 0)
  210.             {
  211.                 fTarget->FocusDraw();
  212.                                             // Track mouse while it is down
  213.                 if (fTarget->TrackHotSpot(theHotSpot, event->whereLocal, event->macEvent.modifiers))
  214.                 {
  215.                                             // Mouse released inside HotSpot
  216.                     fTarget->HotSpotResult(theHotSpot);
  217.                 }
  218.             }
  219.             
  220.             mExecuteHost = false;            
  221.         }
  222.         break;
  223.     }
  224.     }
  225. }
  226.  
  227. void
  228. StdPopup::SyncMenu (MenuHandle aquiredMenu)
  229. {
  230.     if (!fDirty)
  231.         return;
  232.     
  233.     int current = CountMItems (aquiredMenu);
  234.     int want = GetCount();
  235.     int add = want - current;
  236.     if (0 < add) {
  237.         for (int i = 1; i <= add; i++)
  238.             AppendMenu (aquiredMenu, "\pTest");
  239.     }
  240.     else if (add < 0) {
  241.         for (int i = 1; i <= -add; i++)
  242.             DeleteMenuItem (aquiredMenu, want + 1);
  243.     }
  244.     
  245.     for (int item = 1; item <= want; item++)
  246.     {
  247.         CStr255        itemText;
  248.         itemText = GetText( item );
  249.         if ( itemText[ 1 ] == '-' )
  250.             itemText = " " + itemText;
  251.         SetMenuItemText (aquiredMenu, item, itemText );
  252.     }
  253.     if (fTarget->GetMaxValue() != want)
  254.         fTarget->SetMaxValue (want);
  255.     
  256.     (*aquiredMenu)->menuWidth += tls;
  257.     fDirty = false;
  258. }
  259.  
  260.  
  261. Boolean    StdPopup::NeedCustomPopup() const
  262. {
  263.     return false;
  264. }
  265.  
  266. ResIDT StdPopup::GetTextTraits() const
  267. {
  268.     return fTarget->GetTextTraits();
  269. }
  270.  
  271. /*-----------------------------------------------------------------------------
  272.     LCustomizeFontMenu
  273. -----------------------------------------------------------------------------*/
  274. class LCustomizeFontMenu : public LCustomizeMenu {
  275. public: 
  276.     LCustomizeFontMenu(short fontNum);
  277.     virtual void Draw    (MenuHandle menu, MenuDefUPP* root, Rect *rect, Point hitPt, short *item);
  278.     virtual void Size    (MenuHandle menu, MenuDefUPP* root, Rect *rect, Point hitPt, short *item);
  279.     virtual void Choose(MenuHandle menu, MenuDefUPP* root, Rect *rect, Point hitPt, short *item);
  280. protected:
  281.     virtual void DrawItemText( Rect& itemrect, Str255 itemtext );
  282.     virtual void SetupFont() { ::TextFont(fFontNum); };
  283. private:
  284.     short fFontNum;
  285. };
  286.  
  287. #pragma mark == LCustomizeFontMenu ==
  288.  
  289. LCustomizeFontMenu::LCustomizeFontMenu(short fontNum)
  290.     : LCustomizeMenu()
  291. {
  292.     fFontNum = fontNum;
  293. }
  294.  
  295. void LCustomizeFontMenu::Draw(MenuHandle menu, MenuDefUPP* root, Rect *rect, Point hitPt, short *item)
  296. {
  297.     SetupFont();
  298.     LCustomizeMenu::Draw(menu,  root, rect, hitPt, item);
  299. }
  300. void LCustomizeFontMenu::Size(MenuHandle menu, MenuDefUPP* root, Rect *rect, Point hitPt, short *item)
  301. {
  302.     SetupFont();
  303.     LCustomizeMenu::Size(menu,  root, rect, hitPt, item);
  304. }
  305. void LCustomizeFontMenu::Choose(MenuHandle menu, MenuDefUPP* root, Rect *rect, Point hitPt, short *item)
  306. {
  307.     SetupFont();
  308.     LCustomizeMenu::Choose(menu,  root, rect, hitPt, item);
  309. }
  310. void LCustomizeFontMenu::DrawItemText( Rect& itemrect, Str255 itemtext )
  311. {
  312.     SetupFont();
  313.     LCustomizeMenu::DrawItemText(itemrect,itemtext);
  314. }
  315.  
  316. /*-----------------------------------------------------------------------------
  317.     LMultiFontTextMenu
  318. -----------------------------------------------------------------------------*/
  319. class LMultiFontTextMenu : public LCustomizeMenu {
  320. public: 
  321.     LMultiFontTextMenu(UMultiFontTextHandler* texthandler, UFontSwitcher* fs);
  322. protected:
  323.     virtual void DrawItemText( Rect& itemrect, Str255 itemtext )
  324.         { fTextHandler->DrawString(fFontSwitcher, itemtext); }
  325.         
  326.     virtual short MeasureItemText(Str255 itemtext )    
  327.         { return fTextHandler->StringWidth(fFontSwitcher, itemtext); };
  328. private:
  329.     UMultiFontTextHandler*    fTextHandler;
  330.     UFontSwitcher*            fFontSwitcher;
  331. };
  332.  
  333. LMultiFontTextMenu::LMultiFontTextMenu(UMultiFontTextHandler* texthandler, UFontSwitcher* fs)
  334.     : LCustomizeMenu()
  335. {
  336.     fTextHandler = texthandler;
  337.     fFontSwitcher = fs;
  338. }
  339.  
  340. #pragma mark -
  341.  
  342. // ===========================================================================
  343. // Ñ CGAPopupMenu                                               CGAPopupMenu Ñ
  344. // ===========================================================================
  345.  
  346. // ---------------------------------------------------------------------------
  347. //        Ñ CGAPopupMenu(LStream*)
  348. // ---------------------------------------------------------------------------
  349. //    Construct from data in a Stream
  350.  
  351. CGAPopupMenu::CGAPopupMenu(
  352.     LStream    *inStream)
  353.         :    mNeedCustomDraw(false),
  354.         
  355.             super(inStream)
  356. {    
  357. }
  358.  
  359. CGAPopupMenu::~CGAPopupMenu()
  360. {
  361. }
  362. //-------------------------------------------------------------------------------------
  363. // CGAPopupMenu::DrawPopupTitle
  364. //-------------------------------------------------------------------------------------
  365.  
  366. void
  367. CGAPopupMenu::DrawPopupTitle    ()
  368. {
  369.     if(! mNeedCustomDraw)
  370.     {    // hacky way, depend on mIsUTF8 to decide wheather we use the super class implementation
  371.         super::DrawPopupTitle();
  372.         return;
  373.     }
  374.     StColorPenState    theColorPenState;
  375.     StTextState         theTextState;
  376.     
  377.     // Ñ Get some loal variables setup including the rect for the title
  378.     ResIDT    textTID = GetTextTraitsID ();
  379.     Rect    titleRect;
  380.     Str255 title;
  381.     GetCurrentItemTitle ( title );
  382.     
  383.     // Ñ Figure out what the justification is from the text trait and 
  384.     // get the port setup with the text traits
  385.     UTextTraits::SetPortTextTraits ( textTID );
  386.     
  387.     // Ñ Setup the title justification which is always left justified
  388.     Int16    titleJust = teFlushLeft;
  389.     
  390.     // Ñ Calculate the title rect
  391.     CalcTitleRect ( titleRect );
  392.     
  393.     // Ñ Setup the text color which by default is black
  394.     RGBColor    textColor;
  395.     ::GetForeColor ( &textColor );
  396.     
  397.     // Ñ Get the current item's title
  398.     Str255 currentItemTitle;
  399.     GetCurrentItemTitle ( currentItemTitle );
  400.  
  401.     // Ñ Loop over any devices we might be spanning and handle the drawing
  402.     // appropriately for each devices screen depth
  403.     StDeviceLoop    theLoop ( titleRect );
  404.     Int16                depth;
  405.     while ( theLoop.NextDepth ( depth )) 
  406.     {
  407.         if ( depth < 4 )        //    Ñ BLACK & WHITE
  408.         {
  409.             // Ñ If the control is dimmed then we use the grayishTextOr 
  410.             // transfer mode to draw the text
  411.             if ( !IsEnabled ())
  412.             {
  413.                 ::RGBForeColor ( &UGAColorRamp::GetBlackColor () );
  414.                 ::TextMode ( grayishTextOr );
  415.             }
  416.             else if ( IsEnabled () && IsHilited () )
  417.             {
  418.                 // Ñ When we are hilited we simply draw the title in white
  419.                 ::RGBForeColor ( &UGAColorRamp::GetWhiteColor () );
  420.             }
  421.             
  422.             // Ñ Now get the actual title drawn with all the appropriate settings
  423.             UMultiFontTextHandler *th = UUTF8TextHandler::Instance();
  424.             UFontSwitcher *fs = UPropFontSwitcher::Instance();
  425.             
  426.             FontInfo info;    
  427.             th->GetFontInfo(fs, &info);
  428.             ::MoveTo(titleRect.left,
  429.                      (titleRect.top + titleRect.bottom + info.ascent - info.descent ) / 2);
  430.             th->DrawString(fs, currentItemTitle);    
  431.         }
  432.         else    // Ñ COLOR
  433.         {
  434.             // Ñ If control is selected we always draw the text in the title
  435.             // hilite color, if requested
  436.             if ( IsHilited ())
  437.                 ::RGBForeColor ( &UGAColorRamp::GetWhiteColor() );
  438.         
  439.             // Ñ If the box is dimmed then we have to do our own version of the
  440.             // grayishTextOr as it does not appear to work correctly across
  441.             // multiple devices
  442.             if ( !IsEnabled () || !IsActive ())
  443.             {
  444.                 textColor = UGraphicsUtilities::Lighten ( &textColor );
  445.                 ::TextMode ( srcOr );
  446.                 ::RGBForeColor ( &textColor );
  447.             }
  448.                 
  449.             // Ñ Now get the actual title drawn with all the appropriate settings
  450.             UMultiFontTextHandler *th = UUTF8TextHandler::Instance();
  451.             UFontSwitcher *fs = UPropFontSwitcher::Instance();
  452.             
  453.             FontInfo info;    
  454.             th->GetFontInfo(fs, &info);
  455.             ::MoveTo(titleRect.left,
  456.                      (titleRect.top + titleRect.bottom + info.ascent - info.descent) / 2);
  457.             th->DrawString(fs, currentItemTitle);    
  458.         }    
  459.     }
  460.                                                         
  461. }    //    CGAPopupMenu::DrawPopupTitle
  462. //-------------------------------------------------------------------------------------
  463. //
  464. //    This method is used to calculate the title rect for the currently selected item in
  465. //     the popup, this title is drawn inside the popup
  466. const Int16 gsPopup_RightInset             =     24;    //    Used to position the title rect
  467. const Int16 gsPopup_TitleInset            =     8;        // Apple specification
  468. void
  469. CGAPopupMenu::CalcTitleRect    ( Rect    &outRect )
  470. {
  471.     if(! mNeedCustomDraw)
  472.     {    // hacky way, depend on mIsUTF8 to decide wheather we use the super class implementation
  473.         super::CalcTitleRect(outRect);
  474.         return;
  475.     }    
  476.     StTextState            theTextState;
  477.     StColorPenState    thePenState;
  478.     Int16        bevelWidth = 2;
  479.     
  480.     // Ñ Get some loal variables setup including the rect for the title
  481.     ResIDT    textTID = GetTextTraitsID ();
  482.  
  483.     // Ñ Get the port setup with the text traits
  484.     UTextTraits::SetPortTextTraits ( textTID );
  485.     
  486.     // Ñ Figure out the height of the text for the selected font
  487.     FontInfo fInfo;
  488.     UFontSwitcher *fs = UPropFontSwitcher::Instance();
  489.     UMultiFontTextHandler *th = UUTF8TextHandler::Instance();
  490.     th->GetFontInfo(fs, &fInfo);
  491.     
  492.     Int16        textHeight = fInfo.ascent + fInfo.descent;
  493.     Int16        textBaseline = fInfo.ascent;
  494.     
  495.     // Ñ Get the local inset frame rectangle
  496.     CalcLocalPopupFrameRect ( outRect );
  497.     ::InsetRect ( &outRect, 0, bevelWidth );
  498.     outRect.right -= gsPopup_RightInset;
  499.     outRect.left += gsPopup_TitleInset;
  500.     
  501.     // Ñ Adjust the title rect to match the height of the font
  502.     outRect.top += (( UGraphicsUtilities::RectHeight ( outRect ) - textBaseline) / 2) - 2;
  503.     outRect.bottom = outRect.top + textHeight;
  504.         
  505. }    //    CGAPopupMenu::CalcTitleRect
  506. //=====================================================================================
  507. // ÑÑ POPUP MENU HANDLING
  508. //-------------------------------------------------------------------------------------
  509. // CGAPopupMenu::HandlePopupMenuSelect
  510. //-------------------------------------------------------------------------------------
  511.  
  512. void
  513. CGAPopupMenu::HandlePopupMenuSelect    (    Point        inPopupLoc,
  514.                                                 Int16        inCurrentItem,
  515.                                                 Int16        &outMenuID,
  516.                                                 Int16        &outMenuItem )
  517. {
  518.     MenuHandle    menuH = GetMacMenuH ();
  519.     ThrowIfNil_ ( menuH );
  520.     if ( menuH )
  521.     {
  522.         // BUG#69583: Make sure we *do* use the system font so that the current
  523.         // item will be checked properly as in Akbar. So we don't do the LMSetSysFont
  524.         // stuff that LGAPopup does.
  525.  
  526.         // Ñ Handle the actual insertion into the hierarchical menubar
  527.         ::InsertMenu ( menuH, hierMenu );
  528.         
  529.         FocusDraw ();
  530.  
  531.         // Ñ Before we display the menu we need to make sure that we have the
  532.         // current item marked in the menu. NOTE: we do NOT use the current
  533.         // item that has been passed in here as that always has a value of one
  534.         // in the case of a pulldown menu
  535.         SetupCurrentMenuItem ( menuH, GetValue () );
  536.  
  537.         // Ñ Then we call PopupMenuSelect and wait for it to return
  538.         
  539.         Int32 result;
  540.         
  541.         // hacky way, depend on mIsUTF8 to decide which implementation to use
  542.         if (!mNeedCustomDraw)
  543.         {
  544.             result = ::PopUpMenuSelect(menuH, inPopupLoc.v, inPopupLoc.h, inCurrentItem );
  545.         }
  546.         else
  547.         {
  548.              LMultiFontTextMenu utf8menu(UUTF8TextHandler::Instance(), UPropFontSwitcher::Instance());
  549.             result = UCustomizePopUp::PopUpMenuSelect(menuH, &utf8menu, inPopupLoc.v, inPopupLoc.h, inCurrentItem);
  550.         }
  551.  
  552.         // Ñ Then we extract the values from the returned result
  553.         // these are then passed back out to the caller
  554.         outMenuID = HiWord ( result );
  555.         outMenuItem = LoWord ( result );
  556.  
  557.         // Ñ Finally get the menu removed
  558.         ::DeleteMenu ( GetPopupMenuResID ());
  559.     }
  560. }    //    CGAPopupMenu::HandlePopupMenuSelect
  561.