home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / OS / FWMenu / Sources / FWPullDM.cpp < prev   
Encoding:
Text File  |  1995-11-08  |  28.0 KB  |  871 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWPullDM.cpp
  4. //    Release Version:    $ 1.0d11 $
  5. //
  6. //    Copyright:    © 1993, 1995 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWOS.hpp"
  11.  
  12. #ifndef FWPULLDM_H
  13. #include "FWPullDM.h"
  14. #endif
  15.  
  16. #ifndef FWMNUBAR_H
  17. #include "FWMnuBar.h"
  18. #endif
  19.  
  20. #ifndef FWRESTYP_H
  21. #include "FWResTyp.h"
  22. #endif
  23.  
  24. #ifndef FWACQUIR_H
  25. #include "FWAcquir.h"
  26. #endif
  27.  
  28. // ----- Foundation Includes -----
  29.  
  30. #ifndef FWSTREAM_H
  31. #include "FWStream.h"
  32. #endif
  33.  
  34. #ifndef FWSTRS_H
  35. #include "FWStrs.h"
  36. #endif
  37.  
  38. #ifndef FWBNDSTR_H
  39. #include "FWBndStr.h"
  40. #endif
  41.  
  42. //========================================================================================
  43. //    RunTime Info
  44. //========================================================================================
  45.  
  46. #if FW_LIB_EXPORT_PRAGMAS
  47. #pragma lib_export on
  48. #endif
  49.  
  50. #ifdef FW_BUILD_MAC
  51. #pragma segment fwmenu
  52. #endif
  53.  
  54. FW_DEFINE_CLASS_M0(FW_CPullDownMenu)
  55.  
  56. FW_REGISTER_ARCHIVABLE_CLASS(FW_LPullDownMenu, FW_CPullDownMenu, FW_CPullDownMenu::Read, FW_CPullDownMenu::Write)
  57.  
  58. //========================================================================================
  59. //    class FW_CPullDownMenu
  60. //========================================================================================
  61.  
  62. //----------------------------------------------------------------------------------------
  63. //    FW_CPullDownMenu::FW_CPullDownMenu
  64. //----------------------------------------------------------------------------------------
  65.  
  66. FW_CPullDownMenu::FW_CPullDownMenu(Environment* ev) :
  67.     fMenuID(-1)
  68. {
  69.     FW_CString32 menuTitle(" ");
  70.     this->PrivInitialize(ev, menuTitle);
  71. }
  72.  
  73. //----------------------------------------------------------------------------------------
  74. //    FW_CPullDownMenu::FW_CPullDownMenu
  75. //----------------------------------------------------------------------------------------
  76.  
  77. FW_CPullDownMenu::FW_CPullDownMenu(Environment* ev, const FW_CString& menuTitle) :
  78.     fMenuID(-1)
  79. {
  80.     this->PrivInitialize(ev, menuTitle);
  81. }
  82.  
  83. //----------------------------------------------------------------------------------------
  84. //    FW_CPullDownMenu::FW_CPullDownMenu
  85. //----------------------------------------------------------------------------------------
  86.  
  87. FW_CPullDownMenu::FW_CPullDownMenu(Environment* ev,
  88.                                     FW_CResourceFile &resFile,
  89.                                     FW_ResourceId resourceId,
  90.                                     unsigned long stringId) :
  91.     fMenuID(-1)
  92. {
  93.     FW_CString32 menuTitle;
  94.     ::FW_LoadStringByID(resFile, resourceId, MULTISTRINGRES, stringId, menuTitle);
  95.     this->PrivInitialize(ev, menuTitle);
  96. }
  97.  
  98. //----------------------------------------------------------------------------------------
  99. //    FW_CPullDownMenu::FW_CPullDownMenu
  100. //----------------------------------------------------------------------------------------
  101.  
  102. FW_CPullDownMenu::FW_CPullDownMenu(Environment* ev, FW_CReadableStream& archive)
  103. {
  104.     FW_Char str[256];
  105.     
  106.     archive >> fMenuID;
  107.     archive >> str;
  108.  
  109.     FW_CString32 menuTitle(str);
  110.     this->PrivInitialize(ev, menuTitle);
  111.     
  112.     // ----- Read every items -----
  113.     unsigned long count;
  114.     archive >> count;
  115.     for (unsigned long i = 0; i < count; i++)
  116.     {
  117.         FW_CMenuItem* menuItem;
  118.         FW_READ_DYNAMIC_OBJECT(archive, &menuItem, FW_CMenuItem);
  119.         AdoptMenuItemLast(ev, menuItem);
  120.     }
  121. }
  122.  
  123. //----------------------------------------------------------------------------------------
  124. //    FW_CPullDownMenu::PrivInitialize
  125. //----------------------------------------------------------------------------------------
  126.  
  127. void FW_CPullDownMenu::PrivInitialize(Environment* ev, const FW_CString& menuTitle)
  128. {
  129.     fMenuBar = NULL;
  130.     fParentMenuItem = NULL;
  131.     
  132.     fItems = new FW_CPrivOrderedCollection;
  133.     
  134. #ifdef FW_BUILD_MAC
  135.     Str255 str;
  136.     menuTitle.ExportPascal(str);
  137.     fPlatformMenu = ::NewMenu(fMenuID, str);
  138. #endif
  139.  
  140. #ifdef FW_BUILD_WIN
  141.     fPlatformMenu.menu = ::CreatePopupMenu();
  142.     menuTitle.Export(fPlatformMenu.strMenu);
  143. #endif
  144. }
  145.  
  146. //----------------------------------------------------------------------------------------
  147. //    FW_CPullDownMenu::~FW_CPullDownMenu
  148. //----------------------------------------------------------------------------------------
  149.  
  150. FW_CPullDownMenu::~FW_CPullDownMenu()
  151. {
  152.     if (fItems)
  153.     {
  154.         FW_CMenuItem* item;
  155.         while ((item = (FW_CMenuItem*)fItems->First()) != NULL)
  156.         {
  157.             fItems->Remove(item);
  158.             delete item;
  159.         }        
  160.         
  161.         delete fItems;
  162.         fItems = NULL;
  163.     }
  164.  
  165. #ifdef FW_BUILD_MAC
  166.     if (fPlatformMenu)
  167.     {
  168.         ::DisposeMenu(fPlatformMenu);
  169.         fPlatformMenu = NULL;
  170.     }
  171. #endif
  172.  
  173. #ifdef FW_BUILD_WIN
  174.     if (fPlatformMenu.menu) 
  175.     {
  176.         ::DestroyMenu(fPlatformMenu.menu);
  177.         fPlatformMenu.menu = NULL;
  178.     }    
  179. #endif
  180. }
  181.  
  182. //----------------------------------------------------------------------------------------
  183. //    FW_CPullDownMenu::AppendTextItem
  184. //----------------------------------------------------------------------------------------
  185.  
  186. void FW_CPullDownMenu::AppendTextItem(Environment* ev,
  187.                                     const FW_CString& text,
  188.                                     ODCommandID commandID,
  189.                                     FW_MenuKey menuKey)
  190. {
  191.     short index = CountItems(ev) + 1;
  192.     FW_CMenuItem* menuItem = new FW_CTextItem(ev, this, index, text, commandID, menuKey);
  193.     this->AdoptMenuItemLast(ev, menuItem);
  194. }
  195.  
  196. //----------------------------------------------------------------------------------------
  197. //    FW_CPullDownMenu::AppendTextItem
  198. //----------------------------------------------------------------------------------------
  199.  
  200. void FW_CPullDownMenu::AppendTextItem(Environment* ev,
  201.                                     FW_CResourceFile &resFile,
  202.                                     FW_ResourceId resourceId,
  203.                                     unsigned long id,                                
  204.                                     ODCommandID commandID,
  205.                                     FW_MenuKey menuKey)
  206. {
  207.     FW_CString255 string;
  208.     ::FW_LoadStringByID(resFile, resourceId, MULTISTRINGRES, id, string);
  209.     this->AppendTextItem(ev, string, commandID, menuKey);
  210. }
  211.  
  212. //----------------------------------------------------------------------------------------
  213. //    FW_CPullDownMenu::InsertTextItem
  214. //----------------------------------------------------------------------------------------
  215.  
  216. void FW_CPullDownMenu::InsertTextItem(Environment* ev,
  217.                                     const FW_CString& text,
  218.                                     ODCommandID commandID,
  219.                                     short afterItem,
  220.                                     FW_MenuKey menuKey)
  221. {
  222.     if (afterItem > CountItems(ev))
  223.         afterItem = CountItems(ev);
  224.     
  225.     short index = afterItem + 1;
  226.     
  227.     FW_CMenuItem* menuItem = new FW_CTextItem(ev, this, index, text, commandID, menuKey);
  228.     this->AdoptMenuItemAfter(ev, menuItem, afterItem);
  229. }
  230.  
  231. //----------------------------------------------------------------------------------------
  232. //    FW_CPullDownMenu::InsertTextItem
  233. //----------------------------------------------------------------------------------------
  234.  
  235. void FW_CPullDownMenu::InsertTextItem(Environment* ev,
  236.                                     FW_CResourceFile &resFile,
  237.                                     FW_ResourceId resourceId,
  238.                                     unsigned long id,                                
  239.                                     ODCommandID commandID,
  240.                                     short afterItem,
  241.                                     FW_MenuKey menuKey)
  242. {
  243.     FW_CString255 string;
  244.     ::FW_LoadStringByID(resFile, resourceId, MULTISTRINGRES, id, string);
  245.     this->InsertTextItem(ev, string, commandID, afterItem, menuKey);
  246. }
  247.  
  248. //----------------------------------------------------------------------------------------
  249. //    FW_CPullDownMenu::InsertTextItemAfterCommand
  250. //----------------------------------------------------------------------------------------
  251.  
  252. void FW_CPullDownMenu::InsertTextItemAfterCommand(Environment* ev,
  253.                                     const FW_CString& text,
  254.                                     ODCommandID commandID,
  255.                                     ODCommandID afterCommand,
  256.                                     FW_MenuKey menuKey)
  257. {
  258.     FW_CMenuItem* item = this->PrivGetMenuItem(ev, afterCommand);
  259.     this->InsertTextItem(ev, text, commandID, item->GetIndex(ev), menuKey);
  260. }
  261.  
  262. //----------------------------------------------------------------------------------------
  263. //    FW_CPullDownMenu::InsertTextItemAfterCommand
  264. //----------------------------------------------------------------------------------------
  265.  
  266. void FW_CPullDownMenu::InsertTextItemAfterCommand(Environment* ev,
  267.                                     FW_CResourceFile &resFile,
  268.                                     FW_ResourceId resourceId,
  269.                                     unsigned long id,                                
  270.                                     ODCommandID commandID,
  271.                                     ODCommandID afterCommand,
  272.                                     FW_MenuKey menuKey)
  273. {
  274.     FW_CMenuItem* item = this->PrivGetMenuItem(ev, afterCommand);
  275.     this->InsertTextItem(ev, resFile, resourceId, id, commandID, item->GetIndex(ev), menuKey);
  276. }
  277.  
  278. //----------------------------------------------------------------------------------------
  279. //    FW_CPullDownMenu::AppendToggleItem
  280. //----------------------------------------------------------------------------------------
  281.  
  282. void FW_CPullDownMenu::AppendToggleItem(Environment* ev,
  283.                                     const FW_CString& trueText,
  284.                                     const FW_CString& falseText,
  285.                                     ODCommandID commandID,
  286.                                     FW_MenuKey menuKey)
  287. {
  288.     short index = CountItems(ev) + 1;
  289.     FW_CMenuItem* menuItem = new FW_CToggleItem(ev, this, index, trueText, falseText, commandID, menuKey);
  290.     this->AdoptMenuItemLast(ev, menuItem);
  291. }
  292.  
  293. //----------------------------------------------------------------------------------------
  294. //    FW_CPullDownMenu::AppendToggleItem
  295. //----------------------------------------------------------------------------------------
  296.  
  297. void FW_CPullDownMenu::AppendToggleItem(Environment* ev,
  298.                                     FW_CResourceFile &resFile,
  299.                                     FW_ResourceId resourceId,
  300.                                     unsigned long trueId,
  301.                                     unsigned long falseId,
  302.                                     ODCommandID commandID,
  303.                                     FW_MenuKey menuKey)
  304. {
  305.     FW_CString255 trueString;
  306.     FW_CString255 falseString;
  307.     ::FW_LoadStringByID(resFile, resourceId, MULTISTRINGRES, trueId, trueString);
  308.     ::FW_LoadStringByID(resFile, resourceId, MULTISTRINGRES, falseId, falseString);
  309.     this->AppendToggleItem(ev, trueString, falseString, commandID, menuKey);
  310. }
  311.  
  312. //----------------------------------------------------------------------------------------
  313. //    FW_CPullDownMenu::InsertToggleItem
  314. //----------------------------------------------------------------------------------------
  315.  
  316. void FW_CPullDownMenu::InsertToggleItem(Environment* ev,
  317.                                     const FW_CString& trueText,
  318.                                     const FW_CString& falseText,
  319.                                     ODCommandID commandID,
  320.                                     short afterItem,
  321.                                     FW_MenuKey menuKey)
  322. {
  323.     if (afterItem > CountItems(ev))
  324.         afterItem = CountItems(ev);
  325.     
  326.     short index = afterItem + 1;
  327.     
  328.     FW_CMenuItem* menuItem = new FW_CToggleItem(ev, this, index, trueText, falseText, commandID, menuKey);
  329.     this->AdoptMenuItemAfter(ev, menuItem, afterItem);
  330. }
  331.  
  332. //----------------------------------------------------------------------------------------
  333. //    FW_CPullDownMenu::InsertToggleItem
  334. //----------------------------------------------------------------------------------------
  335.  
  336. void FW_CPullDownMenu::InsertToggleItem(Environment* ev,
  337.                                     FW_CResourceFile &resFile,
  338.                                     FW_ResourceId resourceId,
  339.                                     unsigned long trueId,
  340.                                     unsigned long falseId,
  341.                                     ODCommandID commandID,
  342.                                     short afterItem,
  343.                                     FW_MenuKey menuKey)
  344. {
  345.     FW_CString255 trueString;
  346.     FW_CString255 falseString;
  347.     ::FW_LoadStringByID(resFile, resourceId, MULTISTRINGRES, trueId, trueString);
  348.     ::FW_LoadStringByID(resFile, resourceId, MULTISTRINGRES, falseId, falseString);
  349.     this->InsertToggleItem(ev, trueString, falseString, commandID, afterItem, menuKey);
  350. }
  351.  
  352. //----------------------------------------------------------------------------------------
  353. //    FW_CPullDownMenu::InsertToggleItemAfterCommand
  354. //----------------------------------------------------------------------------------------
  355.  
  356. void FW_CPullDownMenu::InsertToggleItemAfterCommand(Environment* ev,
  357.                                     const FW_CString& trueText,
  358.                                     const FW_CString& falseText,
  359.                                     ODCommandID commandID,
  360.                                     ODCommandID afterCommand,
  361.                                     FW_MenuKey menuKey)
  362. {
  363.     FW_CMenuItem* item = this->PrivGetMenuItem(ev, afterCommand);
  364.     this->InsertToggleItem(ev, trueText, falseText, commandID, item->GetIndex(ev), menuKey);
  365. }
  366.  
  367. //----------------------------------------------------------------------------------------
  368. //    FW_CPullDownMenu::InsertToggleItemAfterCommand
  369. //----------------------------------------------------------------------------------------
  370.  
  371. void FW_CPullDownMenu::InsertToggleItemAfterCommand(Environment* ev,
  372.                                     FW_CResourceFile &resFile,
  373.                                     FW_ResourceId resourceId,
  374.                                     unsigned long trueId,
  375.                                     unsigned long falseId,
  376.                                     ODCommandID commandID,
  377.                                     ODCommandID afterCommand,
  378.                                     FW_MenuKey menuKey)
  379. {
  380.     FW_CMenuItem* item = this->PrivGetMenuItem(ev, afterCommand);
  381.     this->InsertToggleItem(ev, resFile, resourceId, trueId, falseId, commandID, item->GetIndex(ev), menuKey);
  382. }
  383.  
  384. //----------------------------------------------------------------------------------------
  385. //    FW_CPullDownMenu::AppendSubMenu
  386. //----------------------------------------------------------------------------------------
  387.  
  388. void FW_CPullDownMenu::AppendSubMenu(Environment* ev,
  389.                                     FW_CPullDownMenu* adoptSubMenu)
  390. {
  391.     short index = CountItems(ev) + 1;
  392.     FW_CMenuItem* menuItem = new FW_CSubMenuItem(ev, this, index, adoptSubMenu);
  393.     this->AdoptMenuItemLast(ev, menuItem);
  394. }
  395.  
  396. //----------------------------------------------------------------------------------------
  397. //    FW_CPullDownMenu::InsertSubMenu
  398. //----------------------------------------------------------------------------------------
  399.  
  400. void FW_CPullDownMenu::InsertSubMenu(Environment* ev,
  401.                                     FW_CPullDownMenu* adoptSubMenu,
  402.                                     short afterItem)
  403. {
  404.     if (afterItem > CountItems(ev))
  405.         afterItem = CountItems(ev);
  406.     
  407.     short index = afterItem + 1;
  408.     
  409.     FW_CMenuItem* menuItem = new FW_CSubMenuItem(ev, this, index, adoptSubMenu);
  410.     this->AdoptMenuItemAfter(ev, menuItem, afterItem);
  411. }
  412.  
  413. //----------------------------------------------------------------------------------------
  414. //    FW_CPullDownMenu::InsertSubMenuAfterCommand
  415. //----------------------------------------------------------------------------------------
  416.  
  417. void FW_CPullDownMenu::InsertSubMenuAfterCommand(Environment* ev,
  418.                                     FW_CPullDownMenu* adoptSubMenu,
  419.                                     ODCommandID afterCommand)
  420. {
  421.     FW_CMenuItem* item = this->PrivGetMenuItem(ev, afterCommand);
  422.     this->InsertSubMenu(ev, adoptSubMenu, item->GetIndex(ev));
  423. }
  424.  
  425. //----------------------------------------------------------------------------------------
  426. //    FW_CPullDownMenu::AppendSeparator
  427. //----------------------------------------------------------------------------------------
  428.  
  429. void FW_CPullDownMenu::AppendSeparator(Environment* ev)
  430. {
  431.     short index = CountItems(ev) + 1;
  432.     FW_CMenuItem* menuItem = new FW_CSeparatorItem(ev, this, index);
  433.     this->AdoptMenuItemLast(ev, menuItem);
  434. }
  435.  
  436. //----------------------------------------------------------------------------------------
  437. //    FW_CPullDownMenu::InsertSeparator
  438. //----------------------------------------------------------------------------------------
  439.  
  440. void FW_CPullDownMenu::InsertSeparator(Environment* ev,
  441.                                     short afterItem)
  442. {
  443.     if (afterItem > CountItems(ev))
  444.         afterItem = CountItems(ev);
  445.     
  446.     short index = afterItem + 1;
  447.     
  448.     FW_CMenuItem* menuItem = new FW_CSeparatorItem(ev, this, index);
  449.     this->AdoptMenuItemAfter(ev, menuItem, afterItem);
  450. }
  451.  
  452. //----------------------------------------------------------------------------------------
  453. //    FW_CPullDownMenu::InsertSeparatorAfterCommand
  454. //----------------------------------------------------------------------------------------
  455.  
  456. void FW_CPullDownMenu::InsertSeparatorAfterCommand(Environment* ev,
  457.                                     ODCommandID afterCommand)
  458. {
  459.     FW_CMenuItem* item = this->PrivGetMenuItem(ev, afterCommand);
  460.     this->InsertSeparator(ev, item->GetIndex(ev));
  461. }
  462.  
  463. //----------------------------------------------------------------------------------------
  464. //    FW_CPullDownMenu::RemoveItem
  465. //
  466. //  If an index greater than the number of items in the menu is specified,
  467. //    the last item is deleted.
  468. //----------------------------------------------------------------------------------------
  469.  
  470. void FW_CPullDownMenu::RemoveItem(Environment* ev, short position)
  471. {
  472.     FW_ASSERT(position > 0);
  473.     
  474.     if (position > CountItems(ev))
  475.         position = CountItems(ev);
  476.     
  477.     FW_COrderedCollectionIterator ite(fItems);    
  478.     FW_CMenuItem* itemToRemove = NULL;
  479.     
  480.     for (FW_CMenuItem* item = (FW_CMenuItem*)ite.First(); ite.IsNotComplete(); item = (FW_CMenuItem*)ite.Next())
  481.     {
  482.         short index = item->GetIndex(ev);
  483.         
  484.         if (index == position)
  485.             itemToRemove = item;
  486.         else if (index > position)
  487.         // if the current item is beneath the new item in the menu...
  488.         {
  489.             item->PrivSetIndex(ev, index - 1);
  490.             
  491. #ifdef FW_BUILD_MAC
  492.             if (fMenuBar != NULL)  // need to unregister and re-register the item
  493.             {
  494.                 fMenuBar->PrivMacUnregisterCommand(ev, item->GetCommandID(ev));
  495.                 fMenuBar->PrivMacRegisterCommand(ev, item->GetCommandID(ev), fMenuID, index - 1);
  496.             }
  497. #endif
  498.         }
  499.     }
  500.     
  501.     FW_ASSERT(itemToRemove);
  502.     fItems->Remove(itemToRemove);
  503.     
  504.     if (fMenuBar != NULL)
  505.         itemToRemove->PrivDetach(ev, fMenuBar);
  506.     
  507.     // now, actually delete the item
  508.     
  509. #ifdef FW_BUILD_MAC
  510.     DeleteMenuItem(fPlatformMenu, position);
  511. #endif
  512.  
  513. #ifdef FW_BUILD_WIN
  514.     DeleteMenu(fPlatformMenu.menu, position - 1, MF_BYPOSITION);
  515. #endif
  516.  
  517.     delete itemToRemove;
  518. }
  519.  
  520. //----------------------------------------------------------------------------------------
  521. //    FW_CPullDownMenu::AdoptMenuItemLast
  522. //----------------------------------------------------------------------------------------
  523.  
  524. void FW_CPullDownMenu::AdoptMenuItemLast(Environment* ev, FW_CMenuItem* menuItem)
  525. {
  526.     fItems->AddLast(menuItem);
  527.     
  528.     if (fMenuBar != NULL)
  529.         menuItem->PrivAttach(ev, fMenuBar);
  530. }
  531.  
  532. //----------------------------------------------------------------------------------------
  533. //    FW_CPullDownMenu::AdoptMenuItemAfter
  534. //----------------------------------------------------------------------------------------
  535. //  If afterItem is greater than the number of items in the menu, the item is added to
  536. //  then bottom of the menu; if it's zero, the item is added to the top.
  537.  
  538. void FW_CPullDownMenu::AdoptMenuItemAfter(Environment* ev, FW_CMenuItem* menuItem, short afterItem)
  539. {
  540.     FW_ASSERT(afterItem >= 0 && afterItem <= CountItems(ev));
  541.     
  542.     FW_COrderedCollectionIterator ite(fItems);    
  543.     FW_CMenuItem* prevItem = NULL;
  544.     
  545.     for (FW_CMenuItem* item = (FW_CMenuItem*)ite.First(); ite.IsNotComplete(); item = (FW_CMenuItem*)ite.Next())
  546.     {
  547.         short index = item->GetIndex(ev);
  548.         
  549.         if (index == afterItem)
  550.             prevItem = item;
  551.         else if (index > afterItem)
  552.         // if the current item is beneath the new item in the menu...
  553.         {
  554.             item->PrivSetIndex(ev, index + 1);  // adjust item numbers
  555.             
  556. #ifdef FW_BUILD_MAC    
  557.             if (fMenuBar != NULL)  // need to unregister and re-register the item
  558.             {
  559.                 fMenuBar->PrivMacUnregisterCommand(ev, item->GetCommandID(ev));
  560.                 fMenuBar->PrivMacRegisterCommand(ev, item->GetCommandID(ev), fMenuID, index + 1);
  561.             }
  562. #endif
  563.         }
  564.     }
  565.     
  566.     if (afterItem == 0)  // add the item to the menu
  567.         fItems->AddFirst(menuItem);
  568.     else
  569.     {
  570.         FW_ASSERT(prevItem);
  571.         fItems->AddAfter(prevItem, menuItem);
  572.     }
  573.     
  574.     if (fMenuBar != NULL)
  575.         menuItem->PrivAttach(ev, fMenuBar);
  576. }
  577.  
  578. //----------------------------------------------------------------------------------------
  579. //    FW_CPullDownMenu::GetCommandID
  580. //----------------------------------------------------------------------------------------
  581. //    returns FW_kNoCommand if not found or submenu, FW_kSeparatorCommand if separator
  582.  
  583. ODCommandID FW_CPullDownMenu::GetCommandID(Environment* ev, short position) const
  584. {
  585. #ifdef FW_BUILD_MAC
  586.     FW_COrderedCollectionIterator ite(fItems);
  587.     for (FW_CMenuItem* item = (FW_CMenuItem*)ite.First(); ite.IsNotComplete(); item = (FW_CMenuItem*)ite.Next())
  588.     {
  589.         if (item->GetIndex(ev) == position)
  590.             return item->GetCommandID(ev);
  591.     }
  592.         
  593.     return FW_kNoCommand;
  594. #endif
  595.  
  596. #ifdef FW_BUILD_WIN
  597.     return ::GetMenuItemID(fPlatformMenu.menu, position-1);    // zero-based on windows
  598. #endif
  599. }
  600.  
  601. //----------------------------------------------------------------------------------------
  602. //    FW_CPullDownMenu::PrivGetMenuItem
  603. //----------------------------------------------------------------------------------------
  604.  
  605. FW_CMenuItem* FW_CPullDownMenu::PrivGetMenuItem(Environment* ev, ODCommandID commandID) const
  606. {
  607.     FW_ASSERT(commandID != FW_kNoCommand);
  608.     FW_ASSERT(commandID != FW_kSeparatorCommand);
  609.     
  610.     FW_COrderedCollectionIterator ite(fItems);
  611.     for (FW_CMenuItem* item = (FW_CMenuItem*)ite.First(); ite.IsNotComplete(); item = (FW_CMenuItem*)ite.Next())
  612.     {
  613.         if (item->GetCommandID(ev) == commandID)
  614.             return item;
  615.         else 
  616.         {
  617.             FW_CMenuItem* subItem = item->PrivGetMenuItem(ev, commandID);
  618.             if (subItem != NULL)
  619.                 return subItem;
  620.         }
  621.             
  622.     }
  623.         
  624.     return NULL;
  625. }
  626.  
  627. //----------------------------------------------------------------------------------------
  628. //    FW_CPullDownMenu::PrivFindMenuWithID
  629. //----------------------------------------------------------------------------------------
  630.  
  631. FW_CPullDownMenu* FW_CPullDownMenu::PrivFindMenuWithID(Environment* ev, ODMenuID menuID) const
  632. {
  633.     FW_ASSERT(IsAttachedToMenuBar(ev)); // Otherwise it doesn't make sense because menuID 
  634.                                         // are only assigned when the menu is attached
  635.     
  636.     FW_COrderedCollectionIterator ite(fItems);
  637.     for (FW_CMenuItem* item = (FW_CMenuItem*)ite.First(); ite.IsNotComplete(); item = (FW_CMenuItem*)ite.Next())
  638.     {
  639.         FW_CPullDownMenu* subMenu = item->PrivFindMenuWithID(ev, menuID);
  640.         if (subMenu != NULL)
  641.             return subMenu;
  642.     }
  643.     
  644.     return NULL;
  645. }
  646.  
  647. //----------------------------------------------------------------------------------------
  648. //    FW_CPullDownMenu::DisableAll
  649. //----------------------------------------------------------------------------------------
  650.  
  651. void FW_CPullDownMenu::DisableAll(Environment* ev)
  652. {
  653. #ifdef FW_BUILD_MAC
  654.         // ----- On the Mac disable all the items at once
  655.         (*fPlatformMenu)->enableFlags &= 0x00000001;
  656. #endif
  657.  
  658.     FW_COrderedCollectionIterator ite(fItems);
  659.     for (FW_CMenuItem* item = (FW_CMenuItem*)ite.First(); ite.IsNotComplete(); item = (FW_CMenuItem*)ite.Next())
  660.     {
  661.         item->PrivDisableAll(ev);
  662.     }    
  663. }
  664.  
  665. //----------------------------------------------------------------------------------------
  666. //    FW_CPullDownMenu::EnableAll
  667. //----------------------------------------------------------------------------------------
  668.  
  669. void FW_CPullDownMenu::EnableAll(Environment* ev)
  670. {
  671. #ifdef FW_BUILD_MAC
  672.         // ----- On the Mac enale all the items at once
  673.         (*fPlatformMenu)->enableFlags &= 0xFFFFFFFF;
  674. #endif
  675.  
  676.     FW_COrderedCollectionIterator ite(fItems);
  677.     for (FW_CMenuItem* item = (FW_CMenuItem*)ite.First(); ite.IsNotComplete(); item = (FW_CMenuItem*)ite.Next())
  678.     {
  679.         item->PrivEnableAll(ev);
  680.     }    
  681. }
  682.  
  683. //----------------------------------------------------------------------------------------
  684. //    FW_CPullDownMenu::PrivAcquireMenuID
  685. //----------------------------------------------------------------------------------------
  686.  
  687. short FW_CPullDownMenu::PrivAcquireMenuID(Environment* ev, FW_CMenuBar* menuBar)
  688. {
  689.     FW_ASSERT(fMenuID == -1);
  690.     fMenuID = menuBar->PrivGetNewMenuID(ev);
  691. #ifdef FW_BUILD_MAC    
  692.     (*fPlatformMenu)->menuID = fMenuID;
  693. #endif
  694.     return fMenuID;
  695. }
  696.  
  697. //----------------------------------------------------------------------------------------
  698. //    FW_CPullDownMenu::PrivRelinquishMenuID
  699. //----------------------------------------------------------------------------------------
  700.  
  701. void FW_CPullDownMenu::PrivRelinquishMenuID(Environment* ev)
  702. {
  703.     FW_ASSERT(fMenuID != -1);
  704.     fMenuID = -1;
  705. #ifdef FW_BUILD_MAC    
  706.     (*fPlatformMenu)->menuID = -1;
  707. #endif
  708. }
  709.  
  710. //----------------------------------------------------------------------------------------
  711. //    FW_CPullDownMenu::PrivAttach
  712. //----------------------------------------------------------------------------------------
  713.  
  714. void FW_CPullDownMenu::PrivAttach(Environment* ev, FW_CMenuBar* menuBar)
  715. {
  716.     FW_ASSERT(fMenuBar == NULL);
  717.     fMenuBar = menuBar;
  718.     
  719.     FW_COrderedCollectionIterator ite(fItems);
  720.     for (FW_CMenuItem* item = (FW_CMenuItem*)ite.First(); ite.IsNotComplete(); item = (FW_CMenuItem*)ite.Next())
  721.     {
  722.         item->PrivAttach(ev, menuBar);
  723.     }
  724. }
  725.  
  726. //----------------------------------------------------------------------------------------
  727. //    FW_CPullDownMenu::PrivDetach
  728. //----------------------------------------------------------------------------------------
  729.  
  730. void FW_CPullDownMenu::PrivDetach(Environment* ev, FW_CMenuBar* menuBar)
  731. {    
  732.     FW_ASSERT(fMenuBar == menuBar);
  733.     fMenuBar = NULL;
  734.     
  735.     FW_COrderedCollectionIterator ite(fItems);
  736.     for (FW_CMenuItem* item = (FW_CMenuItem*)ite.First(); ite.IsNotComplete(); item = (FW_CMenuItem*)ite.Next())
  737.     {
  738.         item->PrivDetach(ev, menuBar);
  739.     }
  740. }
  741.  
  742. //----------------------------------------------------------------------------------------
  743. //    FW_CPullDownMenu::PrivAttachedToMenuBar
  744. //----------------------------------------------------------------------------------------
  745.  
  746. void FW_CPullDownMenu::PrivAttachedToMenuBar(Environment* ev, FW_CMenuBar* menuBar, ODMenuID beforeID)
  747. {
  748.     FW_ASSERT(menuBar != NULL);
  749.     FW_ASSERT(fMenuBar == NULL);
  750.     FW_ASSERT(fMenuID == -1);
  751.     
  752.     PrivAcquireMenuID(ev, menuBar);
  753.  
  754.     FW_CAcquiredODMenuBar aqODMenuBar = menuBar->AcquireODMenuBar(ev);
  755.     ODPart* odPart = menuBar->GetODPart(ev);
  756.     
  757.     if (beforeID == -1)
  758.     {
  759. #ifdef FW_BUILD_WIN
  760.         // [WIN_PORT]: AddMenuLast takes an ODPlatformMenu* in OD/Win -- different from OD/Mac
  761.         aqODMenuBar->AddMenuLast(ev, fMenuID, &fPlatformMenu, odPart);
  762. #else
  763.         aqODMenuBar->AddMenuLast(ev, fMenuID, fPlatformMenu, odPart);
  764. #endif
  765.     }
  766.     else
  767.     {
  768. #ifdef FW_BUILD_WIN
  769.         // [WIN_PORT]: AddMenuBefore takes an ODPlatformMenu* in OD/Win -- different from OD/Mac
  770.         aqODMenuBar->AddMenuBefore(ev, fMenuID, &fPlatformMenu, odPart, beforeID);
  771. #else
  772.         aqODMenuBar->AddMenuBefore(ev, fMenuID, fPlatformMenu, odPart, beforeID);
  773. #endif
  774.     }
  775.     
  776.     PrivAttach(ev, menuBar);
  777. }
  778.  
  779. //----------------------------------------------------------------------------------------
  780. //    FW_CPullDownMenu::PrivDetachedFromMenuBar
  781. //----------------------------------------------------------------------------------------
  782.  
  783. void FW_CPullDownMenu::PrivDetachedFromMenuBar(Environment* ev, FW_CMenuBar* menuBar)
  784. {
  785.     FW_ASSERT(fMenuBar != NULL);
  786.     FW_ASSERT(fMenuBar == menuBar);
  787.     
  788.     fMenuBar->PrivRemoveMenu(ev, fMenuID);
  789.     
  790.     PrivDetach(ev, fMenuBar);
  791.     
  792.     PrivRelinquishMenuID(ev);
  793. }
  794.  
  795. //----------------------------------------------------------------------------------------
  796. //    FW_CPullDownMenu::Read
  797. //----------------------------------------------------------------------------------------
  798.  
  799. void* FW_CPullDownMenu::Read(FW_CReadableStream& archive)
  800. {
  801.     return new FW_CPullDownMenu(somGetGlobalEnvironment(), archive);
  802. }
  803.  
  804. //----------------------------------------------------------------------------------------
  805. //    FW_CPullDownMenu::Write
  806. //----------------------------------------------------------------------------------------
  807.  
  808. void FW_CPullDownMenu::Write(FW_CWritableStream& archive, const void* thePullDownMenu)
  809. {
  810.     ((FW_CPullDownMenu*) thePullDownMenu)->Flatten(somGetGlobalEnvironment(), archive);
  811. }
  812.  
  813. //----------------------------------------------------------------------------------------
  814. //    FW_CPullDownMenu::Flatten
  815. //----------------------------------------------------------------------------------------
  816.  
  817. void FW_CPullDownMenu::Flatten(Environment* ev, FW_CWritableStream& archive) const
  818. {
  819.     //----- Save menu data -----
  820.     FW_CString255 menuTitle;
  821.     unsigned long count = fItems->Count();
  822.     
  823. #ifdef FW_BUILD_MAC
  824.     menuTitle.ReplaceAll((*fPlatformMenu)->menuData);
  825.     FW_ASSERT(count == ::CountMItems(fPlatformMenu));
  826. #endif
  827. #ifdef FW_BUILD_WIN
  828.     menuTitle = fPlatformMenu.strMenu;
  829.     FW_ASSERT(count == ::GetMenuItemCount(fPlatformMenu.menu));
  830. #endif
  831.  
  832.     archive << this->GetMenuID(ev);
  833.     archive << menuTitle;
  834.     archive << count;
  835.     
  836.     //----- Save menu items -----
  837.     FW_COrderedCollectionIterator itemIter(fItems);
  838.     for (FW_CMenuItem* menuItem = (FW_CMenuItem*)itemIter.First(); itemIter.IsNotComplete(); menuItem = (FW_CMenuItem*)itemIter.Next())
  839.     {
  840.         FW_WRITE_DYNAMIC_OBJECT(archive, menuItem, FW_CMenuItem);
  841.     }
  842. }
  843.  
  844. //========================================================================================
  845. //    Global operators << and >>
  846. //========================================================================================
  847.  
  848. //----------------------------------------------------------------------------------------
  849. //    operator>>
  850. //----------------------------------------------------------------------------------------
  851.  
  852. FW_FUNC_ATTR FW_CReadableStream& operator>>(FW_CReadableStream& archive, FW_CPullDownMenu*& object)
  853. {
  854.     void* voidPtr = NULL;
  855.     FW_CDynamicArchiver::InputObject(archive, voidPtr);
  856.     object = (FW_CPullDownMenu*) voidPtr;
  857.  
  858.     return archive;
  859. }
  860.  
  861. //----------------------------------------------------------------------------------------
  862. //    operator<<
  863. //----------------------------------------------------------------------------------------
  864.  
  865. FW_FUNC_ATTR FW_CWritableStream& operator<<(FW_CWritableStream& archive, const FW_CPullDownMenu* object)
  866. {
  867.     FW_ASSERT(object != NULL);
  868.     FW_CDynamicArchiver::OutputObject(archive, object, FW_CLASSNAME_FROM_POINTER(object));
  869.     return archive;
  870. }
  871.