home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / central / CBookmarksAttachment.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  10.5 KB  |  390 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. //    Handle creating and maintaining the top-level bookmarks menu. It pulls the info
  20. //    out of the RDF container the user designates as their "quickfile menu" and listens
  21. //    to the messages from RDF to update it.
  22.  
  23. #include "CBookmarksAttachment.h"
  24.  
  25. #include "htrdf.h"
  26. #include "CNetscapeWindow.h"
  27.  
  28. #include "net.h"
  29. #include "resgui.h"
  30. #include "uapp.h"
  31. #include "macutil.h"
  32.  
  33. #include "UMenuUtils.h"
  34.  
  35. #include <Icons.h>
  36. #include <Sound.h>
  37.  
  38. #define PERM_BOOKMARK_ITEMS 4
  39.  
  40. const CommandT cmd_BookmarkHierItem = BOOKMARKS_MENU_BASE_LAST;
  41.  
  42. LMenu *CBookmarksAttachment::sMenu = NULL;
  43. Boolean CBookmarksAttachment::sInvalidMenu = true;
  44. LArray CBookmarksAttachment::sMenusList; // this will use the default constructor
  45.  
  46. HT_View CBookmarksAttachment::sQuickfileView = NULL;
  47.  
  48.  
  49.  
  50. //===========================================================
  51. // CBookmarksAttachment
  52. //===========================================================
  53. CBookmarksAttachment::CBookmarksAttachment()
  54. {
  55.     InitQuickfileView();
  56. }
  57.  
  58.  
  59. //
  60. // InitQuickfileView
  61. //
  62. // Called at startup to get a new view from the HT backend that represents the
  63. // bookmarks menu. This can be called multiple times without problems.
  64. //
  65. void
  66. CBookmarksAttachment :: InitQuickfileView ( )
  67. {
  68.     if ( ! sQuickfileView ) {
  69.         HT_Notification notifyStruct = CreateNotificationStruct();
  70.         HT_Pane quickfilePane = HT_NewQuickFilePane(notifyStruct);
  71.         
  72.         sQuickfileView = HT_GetSelectedView(quickfilePane);
  73.     }
  74.     
  75. } // InitQuickfileView
  76.  
  77.  
  78. void
  79. CBookmarksAttachment :: HandleNotification( HT_Notification /* notifyStruct*/,
  80.                                                 HT_Resource node, HT_Event event)
  81. {
  82.     switch (event) {
  83.     
  84.         case HT_EVENT_NODE_ADDED:
  85.         case HT_EVENT_VIEW_REFRESH:
  86.             // only update menu if the quickfile view changes
  87.             if ( HT_GetView(node) == sQuickfileView ) {            
  88.                 sInvalidMenu = true;
  89.                 UpdateMenu();
  90.             }
  91.             break;
  92.             
  93.         case HT_EVENT_NODE_VPROP_CHANGED:
  94.             // optimization: only update when the name column changes
  95.             break;
  96.             
  97.         case HT_EVENT_NODE_DELETED_DATA:
  98.         case HT_EVENT_NODE_DELETED_NODATA:
  99.             // free FE data, but don't update the menu yet (HT not in good state)
  100.             break;
  101.             
  102.     } // case of which event
  103.  
  104. } // HandleNotification
  105.  
  106.  
  107. // Processes:
  108. // 
  109. void CBookmarksAttachment::ExecuteSelf( MessageT inMessage, void* ioParam )
  110. {
  111.     mExecuteHost = FALSE;
  112.  
  113.     switch ( inMessage )    
  114.     {
  115.         CNetscapeWindow *bookmarkableWindow = nil;
  116.         
  117.         case msg_CommandStatus:
  118.         {
  119.             SCommandStatus*        status = (SCommandStatus*)ioParam;
  120.                 
  121.             switch ( status->command )
  122.             {
  123.  
  124.                 default:
  125.                     if (CFrontApp::GetApplication()->HasBookmarksMenu())
  126.                     {
  127.                         if ( status->command >= BOOKMARKS_MENU_BASE && status->command <= BOOKMARKS_MENU_BASE_LAST )
  128.                         {
  129.                              *(status->enabled) = TRUE;
  130.                              *(status->usesMark) = FALSE;
  131.                             return;
  132.                         }
  133.                     }
  134.                 break;
  135.             }
  136.         }
  137.         break;
  138.         
  139.         default:
  140.         {
  141.             if (CFrontApp::GetApplication()->HasBookmarksMenu())
  142.             {
  143.                 if ( inMessage >= BOOKMARKS_MENU_BASE && inMessage <= BOOKMARKS_MENU_BASE_LAST )
  144.                 {
  145.                     Uint32 index = inMessage - BOOKMARKS_MENU_BASE;
  146.                     char* url = HT_GetNodeURL( HT_GetNthItem(sQuickfileView, index) );
  147.                     CFrontApp::DoGetURL ( url );
  148.  
  149.                     return;
  150.                 }
  151.             }
  152.         }
  153.         break;            
  154.     }
  155.     mExecuteHost = TRUE;    // Let application handle it
  156. }
  157.  
  158.  
  159. void CBookmarksAttachment::AddToBookmarks( const char* url, const CStr255& title )
  160. {
  161.     HT_Resource topNode = HT_TopNode ( sQuickfileView );
  162.     HT_AddBookmark ( const_cast<char*>(url), title );
  163. }
  164.  
  165.  
  166. LMenu *CBookmarksAttachment::GetMenu()
  167. {
  168.     if (!sMenu)
  169.     {
  170.         sMenu = new LMenu(cBookmarksMenuID);
  171.  
  172.         if (sMenu)
  173.         {
  174.             MenuHandle macMenu = sMenu->GetMacMenuH();
  175.             
  176.             if (macMenu)
  177.                 UMenuUtils::ConvertToIconMenu(macMenu, 15312);
  178.         }
  179.     }
  180.     return sMenu;
  181. }
  182.  
  183. void CBookmarksAttachment::UpdateMenu()
  184. {
  185.     if (CFrontApp::GetApplication()->HasBookmarksMenu())
  186.     {
  187.         if (!sInvalidMenu || !GetMenu() || !LMenuBar::GetCurrentMenuBar() )
  188.             return;
  189.         
  190.         int i;
  191.         
  192.         // Ñ delete all the dynamically created menus
  193.         // Ñ╩delete all the hierarchical menus we have added from the menubar
  194.         for ( i = 1; i <= sMenusList.GetCount(); i++ )
  195.         {
  196.             LMenu* m;
  197.             sMenusList.FetchItemAt( i, &m );
  198.             if ( m )
  199.                 LMenuBar::GetCurrentMenuBar()->RemoveMenu( m );
  200.             delete m;
  201.         }
  202.  
  203.         // Ñ delete all the menu items after the line in Bookmark menu
  204.         MenuHandle menu = sMenu->GetMacMenuH();
  205.         if ( menu )
  206.         {
  207.             int howMany = ::CountMItems( menu );
  208.             for ( i = howMany; i > PERM_BOOKMARK_ITEMS; i-- )
  209.                 sMenu->RemoveItem( i );
  210.         }
  211.         sMenusList.RemoveItemsAt( sMenusList.GetCount(), 1 );
  212.  
  213.         // Ñ walk through the list, and let the submenus be inserted recursively
  214.         int nextMenuID = cBookmarksFirstHierMenuID;
  215.         FillMenuFromList( HT_TopNode(sQuickfileView), sMenu, nextMenuID, PERM_BOOKMARK_ITEMS );
  216.         
  217.         sInvalidMenu = false;
  218.     }
  219. }
  220.  
  221. // Ñ╩recursively create submenus, given a list ptr
  222. //        returns NULL if the menu cannot be created
  223. //        it creates submenus recursively
  224. void CBookmarksAttachment::FillMenuFromList(
  225.     HT_Resource top, 
  226.     LMenu* newMenu,
  227.     int& nextMenuID,        // next menu to create
  228.     int whichItem )            // id of the first item to insert
  229. {
  230.     if (CFrontApp::GetApplication()->HasBookmarksMenu())
  231.     {
  232.         Try_
  233.         {
  234.             ThrowIfNil_( newMenu );
  235.             MenuHandle mHand = newMenu->GetMacMenuH();
  236.         
  237.             ThrowIfNil_( mHand );
  238.             
  239.             // Ñ╩remove all the extra items if they exist
  240.             long removeThese = ::CountMItems( mHand ) - whichItem;
  241.             for ( long i = 1; i < removeThese; i++ )
  242.                 newMenu->RemoveItem( whichItem );
  243.         
  244.             MenuHandle theMacMenu = newMenu->GetMacMenuH();
  245.             
  246.             // Open up the container and get an iterator on its contents (we have to open it before
  247.             // we can see anything inside it). If the cursor is null, it is probably because the container
  248.             // is locked so just put up a leaf item (disabled, of course) and bail.
  249.             HT_SetOpenState ( top, PR_TRUE );
  250.             HT_Cursor cursor = HT_NewCursor( top );
  251.             if ( !cursor ) {
  252.                 whichItem = UMenuUtils::InsertMenuItem(theMacMenu, "\pLocked", whichItem);
  253.                 newMenu->SetCommand(whichItem, 0);
  254.                 return;
  255.             }                
  256.             
  257.             HT_Resource currNode = HT_GetNextItem(cursor);
  258.             while ( currNode )
  259.             {
  260.                 if ( HT_IsSeparator(currNode) )
  261.                     newMenu->InsertCommand( "\p-", cmd_Nothing, whichItem++ );
  262.                 else if ( ! HT_IsContainer(currNode) )
  263.                 {
  264.                      // Ñ should really convert this to menu chars
  265.                     CStr255 urlName( HT_GetNodeName(currNode) );
  266.                     CreateMenuString( urlName );
  267.  
  268.                     whichItem = UMenuUtils::InsertMenuItem(theMacMenu, urlName, whichItem); // returns actual insert loc
  269.                     newMenu->SetCommand(whichItem, BOOKMARKS_MENU_BASE + HT_GetNodeIndex(sQuickfileView, currNode) );
  270.  
  271.                 }
  272.                 else
  273.                 {
  274.                     CStr255 headerName( HT_GetNodeName(currNode) );
  275.                     CreateMenuString( headerName );
  276.  
  277.                     whichItem = UMenuUtils::InsertMenuItem(theMacMenu, headerName, whichItem); // returns actual insert loc
  278.                     newMenu->SetCommand(whichItem, cmd_BookmarkHierItem);
  279.                     
  280.                     // Ñ╩do we have space to create more?
  281.                     if ( nextMenuID <= cBookmarksLastHierMenuID)
  282.                     {
  283.                         LMenu* subMenu = (LMenuBar::GetCurrentMenuBar())->FetchMenu( nextMenuID );
  284.                         if ( !subMenu )
  285.                         {
  286.                             StringHandle menuStringH = GetString( NEW_RESID );
  287.                             Assert_(menuStringH);
  288.                             if (menuStringH)
  289.                             {
  290.                                 StHandleLocker locker((Handle)menuStringH);
  291.                                 subMenu = new LMenu( nextMenuID,
  292.                                                     (unsigned char *)*menuStringH );
  293.                                 LMenuBar::GetCurrentMenuBar()->InstallMenu( subMenu, hierMenu );
  294.                             }
  295.                         }
  296.                         else
  297.                             SysBeep( 1 );
  298.         
  299.                         nextMenuID++;
  300.                         
  301.                         //    Skip the "Apple" menu or we're in deep donuts.
  302.                         if (nextMenuID == MENU_Apple)
  303.                             nextMenuID++;
  304.         
  305.                         if ( subMenu )
  306.                         {
  307.                             sMenusList.InsertItemsAt( 1, LArray::index_Last,  &subMenu );
  308.                             // Ñ╩make item hierarchical
  309.                             ::SetItemCmd( mHand, whichItem, hMenuCmd );
  310.                             ::SetItemMark( mHand, whichItem, subMenu->GetMenuID() );
  311.                             if ( currNode )
  312.                                 FillMenuFromList( currNode, subMenu, nextMenuID, 0 );
  313.                         }
  314.                     }
  315.                 }
  316.                 
  317.                 currNode = HT_GetNextItem ( cursor );
  318.                 
  319.             } // while
  320.         }
  321.         Catch_( inErr )
  322.         {
  323.         }
  324.         EndCatch_
  325.     }
  326. }
  327.  
  328. void CBookmarksAttachment::RemoveMenus()
  329. {
  330.     if (CFrontApp::GetApplication()->HasBookmarksMenu())
  331.     {
  332.         if (sMenu)
  333.         {
  334.             LMenuBar *currentMenuBar = LMenuBar::GetCurrentMenuBar();
  335.             
  336.             if (currentMenuBar)
  337.             {
  338.                 currentMenuBar->RemoveMenu(sMenu);
  339.                 
  340.                 for (ArrayIndexT index = 1; index <= sMenusList.GetCount(); ++index)
  341.                 {
  342.                     LMenu *menu;
  343.                     sMenusList.FetchItemAt(index, &menu);
  344.                     
  345.                     if (menu)
  346.                         currentMenuBar->RemoveMenu(menu);
  347.                 }
  348.             }
  349.         }
  350.     }
  351. }
  352.  
  353. void CBookmarksAttachment::InstallMenus()
  354. {
  355.     if (CFrontApp::GetApplication()->HasBookmarksMenu())
  356.     {
  357.         if (GetMenu())
  358.         {
  359.             LMenuBar *currentMenuBar = LMenuBar::GetCurrentMenuBar();
  360.             
  361.             if (currentMenuBar)
  362.             {
  363.                 for (ArrayIndexT index = sMenusList.GetCount(); index > 0; --index)
  364.                 {
  365.                     LMenu *menu;
  366.                     sMenusList.FetchItemAt(index, &menu);
  367.                     
  368.                     if (menu)
  369.                     {
  370.                         StValueChanger<EDebugAction> okayToFail(gDebugThrow, debugAction_Nothing);
  371.                         currentMenuBar->InstallMenu(menu, hierMenu);
  372.                     }
  373.                 }
  374.                 StValueChanger<EDebugAction> okayToFail(gDebugThrow, debugAction_Nothing);
  375.                 currentMenuBar->InstallMenu(sMenu, InstallMenu_AtEnd);
  376.                 
  377.                 LMenu *directoryMenu = currentMenuBar->FetchMenu(cDirectoryMenuID);
  378.                 
  379.                 if (directoryMenu)
  380.                 {
  381.                     CFrontApp::BuildConfigurableMenu( directoryMenu->GetMacMenuH(), "menu.places.item" );
  382.                     
  383.                     for (short index2 = CountMItems(directoryMenu->GetMacMenuH()); index2 > 0; --index2)
  384.                         directoryMenu->SetCommand(index2, DIR_MENU_BASE + index2 - 1);
  385.                 }
  386.             }
  387.         }
  388.     }
  389. }
  390.