home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / usertlbr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  37.7 KB  |  1,352 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 "stdafx.h"
  20. #include "usertlbr.h"
  21. #include "shcut.h"
  22. #include "dropmenu.h"
  23. #include "prefapi.h"
  24. #include "rdfliner.h"
  25.  
  26. extern "C" {
  27. #include "xpgetstr.h"
  28. };
  29.  
  30. #define LEFT_TOOLBAR_MARGIN 10
  31. #define RIGHT_TOOLBAR_MARGIN 20
  32. #define SPACE_BETWEEN_BUTTONS 2
  33.  
  34. #define MAX_TOOLBAR_BUTTONS 60
  35. #define MAX_TOOLBAR_ROWS 3
  36.  
  37. int CLinkToolbar::m_nMinToolbarButtonChars = 15;
  38. int CLinkToolbar::m_nMaxToolbarButtonChars = 30;
  39.  
  40. //////////////////////////////////////////////////////////////////////////////////////
  41. //                            CLinkToolbarButtonDropTarget
  42. //////////////////////////////////////////////////////////////////////////////////////
  43.  
  44. DROPEFFECT CLinkToolbarButtonDropTarget::ProcessDragEnter(CWnd *pWnd, COleDataObject *pDataObject, 
  45.             DWORD dwKeyState, CPoint point)
  46. {
  47.  
  48.     // Drop target is only used for drops directly onto folder personal toolbar buttons.
  49.     // This drop target is NOT used for the Aurora selector bar drops.
  50.     return ProcessDragOver(pWnd, pDataObject, dwKeyState, point);
  51. }
  52.  
  53. DROPEFFECT CLinkToolbarButtonDropTarget::ProcessDragOver(CWnd *pWnd, COleDataObject *pDataObject, 
  54.             DWORD dwKeyState, CPoint point)
  55. {
  56.     CLinkToolbarButton* pButton = (CLinkToolbarButton*)m_pButton;
  57.  
  58.     // Treat as a drop onto the folder.
  59.     return RDFGLOBAL_TranslateDropAction(pButton->GetNode(), pDataObject, 2);
  60. }
  61.  
  62. BOOL CLinkToolbarButtonDropTarget::ProcessDrop(CWnd *pWnd, COleDataObject *pDataObject, 
  63.             DROPEFFECT dropEffect, CPoint point)
  64. {
  65.     // Treat as a drop onto the folder.
  66.     CLinkToolbarButton* pButton = (CLinkToolbarButton*)m_pButton;
  67.     RDFGLOBAL_PerformDrop(pDataObject, pButton->GetNode(), 2);
  68.     return TRUE;
  69. }
  70.  
  71. //////////////////////////////////////////////////////////////////////////////////////
  72. //                            CLinkToolbarButton
  73. //////////////////////////////////////////////////////////////////////////////////////
  74. static HBITMAP m_hbmpBM = NULL;
  75. static HBITMAP m_hbmpBMSelected = NULL;
  76. static HBITMAP m_hbmpFolder = NULL;
  77. static HBITMAP m_hbmpSelectedFolder = NULL;
  78. static HBITMAP m_hbmpFolderOpen =  NULL;
  79. static int nBitmapRefCount = 0;
  80.  
  81. CLinkToolbarButton::CLinkToolbarButton()
  82. {
  83.     m_bShouldShowRMMenu = TRUE;
  84.  
  85.     m_Node = NULL;
  86.  
  87.     m_uCurBMID = 0;
  88.  
  89.     currentRow = 0;
  90. }
  91.  
  92.  
  93. CLinkToolbarButton::~CLinkToolbarButton()
  94. {
  95.     if(m_Node && HT_IsContainer(m_Node))
  96.     {
  97.         nBitmapRefCount--;
  98.  
  99.         if(nBitmapRefCount == 0)
  100.         {
  101.             if(m_hbmpBM)
  102.             {
  103.                 DeleteObject(m_hbmpBM);
  104.             }
  105.  
  106.             if(m_hbmpFolder)
  107.             {
  108.                 DeleteObject(m_hbmpFolder);
  109.             }
  110.  
  111.             if(m_hbmpSelectedFolder)
  112.             {
  113.                 DeleteObject(m_hbmpSelectedFolder);
  114.             }
  115.  
  116.             if(m_hbmpFolderOpen)
  117.             {
  118.                 DeleteObject(m_hbmpFolderOpen);
  119.             }
  120.  
  121.             if(m_hbmpBMSelected)
  122.             {
  123.                 DeleteObject(m_hbmpBMSelected);
  124.             }
  125.         }
  126.  
  127.     }
  128. }
  129.  
  130. int CLinkToolbarButton::Create(CWnd *pParent, int nToolbarStyle, CSize noviceButtonSize, CSize advancedButtonSize,
  131.                                 LPCTSTR pButtonText, LPCTSTR pToolTipText,
  132.                                 LPCTSTR pStatusText, 
  133.                                 CSize bitmapSize, int nMaxTextChars, int nMinTextChars, BOOKMARKITEM bookmark,
  134.                                 HT_Resource pNode, DWORD dwButtonStyle )
  135. {
  136.     
  137.     m_bookmark = bookmark;
  138.  
  139.     char *protocol = NULL;
  140.  
  141.     BOOL bResult = CToolbarButton::Create(pParent, nToolbarStyle, noviceButtonSize, advancedButtonSize,
  142.         pButtonText, pToolTipText, pStatusText, 0, 0,
  143.         bitmapSize, TRUE, 0, nMaxTextChars, nMinTextChars, dwButtonStyle);
  144.  
  145.     if(bResult)
  146.     {
  147.         SetNode(pNode);
  148.         m_nIconType = DetermineIconType(pNode, UseLargeIcons());
  149.  
  150.         m_nBitmapID = GetBitmapID();
  151.         m_nBitmapIndex = GetBitmapIndex();
  152.  
  153.         HDC hDC = ::GetDC(m_hWnd);
  154.  
  155.         HPALETTE hPalette = WFE_GetUIPalette(GetParentFrame());
  156.         HBITMAP hBitmap = WFE_LookupLoadAndEnterBitmap(hDC, m_nBitmapID, TRUE, hPalette,
  157.                                                        sysInfo.m_clrBtnFace, RGB(255, 0, 255));
  158.         ::ReleaseDC(m_hWnd, hDC);
  159.  
  160.         SetBitmap(hBitmap, TRUE);
  161.         
  162.         if (m_menu.m_hMenu == NULL || (m_menu.m_hMenu != NULL && !IsMenu(m_menu.m_hMenu)))
  163.           m_menu.CreatePopupMenu();
  164.     }
  165.  
  166.     return bResult;
  167. }
  168.  
  169. CSize CLinkToolbarButton::GetMinimalButtonSize(void)
  170. {
  171.     CString szText(HT_GetNodeName(m_Node));
  172.     return GetButtonSizeFromChars(szText, m_nMinTextChars);
  173. }
  174.  
  175. CSize CLinkToolbarButton::GetMaximalButtonSize(void)
  176. {
  177.     CString szText(HT_GetNodeName(m_Node));
  178.     return GetButtonSizeFromChars(szText, m_nMaxTextChars);
  179. }
  180.  
  181. void CLinkToolbarButton::OnAction(void)
  182. {
  183.     if(m_Node && !HT_IsContainer(m_Node))
  184.     {
  185.             CAbstractCX * pCX = FEU_GetLastActiveFrameContext();
  186.             ASSERT(pCX != NULL);
  187.             if (pCX != NULL)
  188.             {
  189.                 pCX->NormalGetUrl((LPTSTR)HT_GetNodeURL(m_Node));
  190.             }
  191.     }
  192. }
  193.  
  194. void CLinkToolbarButton::FillInOleDataSource(COleDataSource *pDataSource)
  195. {
  196.     CLIPFORMAT cfHTNode = (CLIPFORMAT)RegisterClipboardFormat(NETSCAPE_HTNODE_FORMAT);
  197.     HANDLE hString = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,1);
  198.     pDataSource->CacheGlobalData(cfHTNode, hString);
  199.  
  200.     // Need to "select" the button in the view.  Hack.
  201.     HT_SetSelection(m_Node);
  202.  
  203.     // Now the view is sufficient
  204.     RDFGLOBAL_BeginDrag(pDataSource, HT_GetView(m_Node));
  205.     
  206. }
  207.  
  208. BOOKMARKITEM CLinkToolbarButton::GetBookmarkItem(void)
  209. {
  210.     return m_bookmark;
  211. }
  212.  
  213. void CLinkToolbarButton::SetBookmarkItem(BOOKMARKITEM bookmark)
  214. {
  215. /*    m_bookmark = bookmark;
  216.     CString strText(bookmark.szText);
  217.     CToolbarButton::SetText(strText);
  218.     */
  219. }
  220.  
  221. void CLinkToolbarButton::SetNode(HT_Resource pNode, BOOL bAddRef)
  222. {
  223.     if (pNode == NULL)
  224.         return;
  225.  
  226.     m_Node = pNode;
  227.     
  228.     // if it's a header and we haven't already loaded the bitmaps, load the bitmaps
  229.     if(HT_IsContainer(pNode) && bAddRef)
  230.     {    
  231.         HDC hDC = ::GetDC(m_hWnd);
  232.  
  233.         HINSTANCE hInstance = AfxGetResourceHandle();
  234.         WFE_InitializeUIPalette(hDC);
  235.         HPALETTE hPalette = WFE_GetUIPalette(GetParentFrame());
  236.         if(nBitmapRefCount == 0)
  237.         {
  238.             m_hbmpBM = WFE_LoadTransparentBitmap(hInstance, hDC, sysInfo.m_clrMenu, RGB(255, 0, 255),
  239.                                                  hPalette, IDB_BOOKMARK_ITEM);
  240.             m_hbmpBMSelected = WFE_LoadTransparentBitmap(hInstance, hDC,sysInfo.m_clrHighlight,
  241.                                                          RGB(255, 0, 255), hPalette, IDB_BOOKMARK_ITEM);
  242.             m_hbmpFolder = WFE_LoadTransparentBitmap(hInstance, hDC,sysInfo.m_clrMenu, RGB(255, 0, 255),
  243.                                                      hPalette, IDB_BOOKMARK_FOLDER2);
  244.  
  245.             m_hbmpSelectedFolder = WFE_LoadTransparentBitmap(hInstance, hDC, sysInfo.m_clrHighlight, RGB(255, 0, 255),
  246.                                                      hPalette, IDB_BOOKMARK_FOLDER2);
  247.  
  248.             m_hbmpFolderOpen = WFE_LoadTransparentBitmap(hInstance, hDC, sysInfo.m_clrHighlight,
  249.                                                          RGB(255, 0, 255), hPalette, IDB_BOOKMARK_FOLDER_OPEN);
  250.         }
  251.         nBitmapRefCount++;
  252.  
  253.         ::ReleaseDC(m_hWnd, hDC);
  254.     }
  255.  
  256. }
  257.  
  258. void CLinkToolbarButton::EditTextChanged(char *pText)
  259. {
  260.     if (pText)
  261.     {
  262.         HT_SetNodeName(m_Node, pText);
  263.         SetText(pText);    
  264.         SetToolTipText(pText);
  265.         delete []pText;
  266.     }
  267.     RemoveTextEdit();
  268.  
  269.     ((CLinkToolbar*)GetParent())->LayoutButtons(-1);
  270. }
  271.  
  272. void CLinkToolbarButton::DrawPicturesAndTextMode(HDC hDC, CRect rect)
  273. {
  274.      DrawBitmapOnSide(hDC, rect);
  275. }
  276.  
  277. void CLinkToolbarButton::DrawPicturesMode(HDC hDC, CRect rect)
  278. {
  279.     DrawBitmapOnSide(hDC, rect);
  280. }
  281.  
  282. void CLinkToolbarButton::DrawButtonText(HDC hDC, CRect rcTxt, CSize sizeTxt, CString strTxt)
  283. {
  284.     CToolbarButton::DrawButtonText(hDC, rcTxt, sizeTxt, strTxt);
  285. }
  286.  
  287. CSize CLinkToolbarButton::GetButtonSizeFromChars(CString s, int c)
  288. {
  289.     if(m_nToolbarStyle != TB_TEXT)
  290.         return(GetBitmapOnSideSize(s, c));
  291.     else
  292.         return(GetTextOnlySize(s, c));
  293. }
  294.  
  295. void CLinkToolbarButton::GetPicturesAndTextModeTextRect(CRect &rect)
  296. {
  297.     GetBitmapOnSideTextRect(rect);
  298. }
  299.  
  300. void CLinkToolbarButton::GetPicturesModeTextRect(CRect &rect)
  301. {
  302.     GetBitmapOnSideTextRect(rect);
  303. }
  304.  
  305.  
  306. BOOL CLinkToolbarButton::CreateRightMouseMenu(void)
  307. {
  308.     if (m_bShouldShowRMMenu)
  309.     {
  310.         m_MenuCommandMap.Clear();
  311.         HT_SetSelection(m_Node); // Make sure the node is the selection in the view.
  312.         HT_View theView = HT_GetView(m_Node);
  313.         HT_Cursor theCursor = HT_NewContextualMenuCursor(theView, PR_FALSE, PR_FALSE);
  314.         if (theCursor != NULL)
  315.         {
  316.             // We have a cursor. Attempt to iterate
  317.             HT_MenuCmd theCommand; 
  318.             while (HT_NextContextMenuItem(theCursor, &theCommand))
  319.             {
  320.                 char* menuName = HT_GetMenuCmdName(theCommand);
  321.                 if (theCommand == HT_CMD_SEPARATOR)
  322.                     m_menu.AppendMenu(MF_SEPARATOR);
  323.                 else
  324.                 {
  325.                     // Add the command to our command map
  326.                     CRDFMenuCommand* rdfCommand = new CRDFMenuCommand(menuName, theCommand);
  327.                     int index = m_MenuCommandMap.AddCommand(rdfCommand);
  328.                     m_menu.AppendMenu(MF_ENABLED, index+FIRST_HT_MENU_ID, menuName);
  329.                 }
  330.             }
  331.             HT_DeleteCursor(theCursor);
  332.         }
  333.     }
  334.     return m_bShouldShowRMMenu;
  335. }
  336.  
  337. CWnd* CLinkToolbarButton::GetMenuParent(void)
  338. {
  339.     return this;
  340. }
  341.  
  342. BOOL CLinkToolbarButton::OnCommand(UINT wParam, LONG lParam)
  343. {
  344.     BOOL bRtn = TRUE;
  345.     
  346.     if (wParam >= FIRST_HT_MENU_ID && wParam <= LAST_HT_MENU_ID)
  347.     {
  348.         // A selection was made from the context menu.
  349.         // Use the menu map to get the HT command value
  350.         CRDFMenuCommand* theCommand = (CRDFMenuCommand*)(m_MenuCommandMap.GetCommand((int)wParam-FIRST_HT_MENU_ID));
  351.         if (theCommand)
  352.         {
  353.             HT_MenuCmd htCommand = theCommand->GetHTCommand();
  354.             HT_DoMenuCmd(HT_GetPane(GetHTView()), htCommand);
  355.         }
  356.  
  357.         return bRtn;
  358.     }
  359.  
  360.     if(wParam == ID_HOTLIST_VIEW || wParam == ID_HOTLIST_ADDCURRENTTOHOTLIST)
  361.     {
  362.         GetParentFrame()->SendMessage(WM_COMMAND, wParam, lParam);
  363.     }
  364.     else if(wParam == ID_DELETE_BUTTON)
  365.     {
  366.         HT_RemoveChild(HT_GetParent(m_Node), m_Node);
  367.     }
  368.     else if(wParam == ID_BUTTON_PROPERTIES)
  369.     {
  370.         // PROPERTIES
  371.     }
  372.     else if(wParam == ID_RENAME_BUTTON)
  373.     {
  374.         AddTextEdit();
  375.         SetTextEditText(m_pButtonText);
  376.     }
  377.     // Only interested in commands from bookmark quick file menu
  378.     else if ((wParam >= FIRST_BOOKMARK_MENU_ID))
  379.     {
  380.         void * pBookmark = NULL;
  381.         m_BMMenuMap.Lookup(wParam, pBookmark);
  382.         if (pBookmark != NULL)
  383.         {
  384.             HT_Resource theNode = (HT_Resource)pBookmark;
  385.             CAbstractCX *pCX = FEU_GetLastActiveFrameContext();
  386.             ASSERT(pCX != NULL);
  387.             if (pCX != NULL)
  388.             {
  389.                 pCX->NormalGetUrl((LPTSTR)HT_GetNodeURL(theNode));
  390.             }
  391.         }
  392.     }
  393.     else 
  394.     {
  395.         bRtn = CLinkToolbarButtonBase::OnCommand(wParam, lParam);
  396.     }
  397.     
  398.     return(bRtn);
  399.     
  400.  
  401. ///////////////////////////////////////////////////////////////////////////////////
  402. //                                    CLinkToolbarButton Messages
  403. ///////////////////////////////////////////////////////////////////////////////////
  404.  
  405. BEGIN_MESSAGE_MAP(CLinkToolbarButton, CLinkToolbarButtonBase)
  406.     //{{AFX_MSG_MAP(CLinkToolbarButton)
  407.     ON_MESSAGE(NSDRAGMENUOPEN, OnDragMenuOpen) 
  408.     ON_MESSAGE(DM_FILLINMENU, OnFillInMenu)
  409.     ON_MESSAGE(DT_DROPOCCURRED, OnDropMenuDropOccurred)
  410.     ON_MESSAGE(DT_DRAGGINGOCCURRED, OnDropMenuDraggingOccurred)
  411.     ON_MESSAGE(DM_MENUCLOSED, OnDropMenuClosed)
  412.     ON_WM_SYSCOLORCHANGE()
  413.     //}}AFX_MSG_MAP
  414.  
  415. END_MESSAGE_MAP()
  416.  
  417. LRESULT CLinkToolbarButton::OnDragMenuOpen(WPARAM wParam, LPARAM lParam)
  418. {
  419. // Set our drop menu's user data.
  420.     if (m_pDropMenu)
  421.         m_pDropMenu->SetUserData(m_Node);
  422.  
  423.     if(m_Node == NULL || !HT_IsContainer(m_Node))
  424.         return 1;
  425.     m_uCurBMID = FIRST_BOOKMARK_MENU_ID;
  426.  
  427.     m_pCachedDropMenu = (CDropMenu *)lParam;  // Set our drop menu
  428.     PRBool isOpen;
  429.  
  430.     HT_Resource theNode = (HT_Resource)m_pCachedDropMenu->GetUserData();
  431.     HT_GetOpenState(theNode, &isOpen);
  432.     if (isOpen)
  433.         FillInMenu(theNode);
  434.     else HT_SetOpenState(theNode, (PRBool)TRUE);
  435.  
  436.     return 1;
  437.  
  438. }
  439.  
  440. LRESULT CLinkToolbarButton::OnFillInMenu(WPARAM wParam, LPARAM lParam)
  441. {
  442. // Set our drop menu's user data.
  443.     if (m_pDropMenu)
  444.         m_pDropMenu->SetUserData(m_Node);
  445.  
  446.     m_pCachedDropMenu = (CDropMenu *)lParam;  // Set our drop menu
  447.     PRBool isOpen;
  448.     HT_Resource theNode = (HT_Resource)m_pCachedDropMenu->GetUserData();
  449.     HT_GetOpenState(theNode, &isOpen);
  450.     if (isOpen)
  451.         FillInMenu(theNode);
  452.     else HT_SetOpenState(theNode, (PRBool)TRUE);
  453.     
  454.     return 1;
  455. }
  456.  
  457. LRESULT CLinkToolbarButton::OnDropMenuDraggingOccurred(WPARAM wParam, LPARAM lParam)
  458. {
  459.     CDropMenuDragData* pData = (CDropMenuDragData*)lParam;
  460.     UINT nCommand = pData->m_nCommand;
  461.     MenuSelectionType eSelType = pData->eSelType;
  462.  
  463.     void * pBookmarkInsertAfter = NULL;
  464.     m_BMMenuMap.Lookup(nCommand, pBookmarkInsertAfter);
  465.     HT_Resource theNode = (HT_Resource)pBookmarkInsertAfter;
  466.  
  467.     int dragFraction = 2;
  468.     if (eSelType == eON)
  469.         dragFraction = 2;
  470.     else if (eSelType == eBELOW)
  471.         dragFraction = 3;
  472.     else if (eSelType == eABOVE)
  473.         dragFraction = 1;
  474.  
  475.     // Next we get the result.
  476.     DROPEFFECT answer = RDFGLOBAL_TranslateDropAction(theNode, pData->m_pDataSource, dragFraction);
  477.     
  478.     // Place the result into our data structure for the droptarget to use.
  479.     pData->m_DropEffect = answer;
  480.     
  481.     return 1;
  482.  
  483. }
  484.  
  485. LRESULT CLinkToolbarButton::OnDropMenuDropOccurred(WPARAM wParam, LPARAM lParam)
  486. {
  487.     CDropMenuDragData* pData = (CDropMenuDragData*)lParam;
  488.     UINT nCommand = pData->m_nCommand;
  489.     MenuSelectionType eSelType = pData->eSelType;
  490.  
  491.     void * pBookmarkInsertAfter = NULL;
  492.     m_BMMenuMap.Lookup(nCommand, pBookmarkInsertAfter);
  493.     HT_Resource theNode = (HT_Resource)pBookmarkInsertAfter;
  494.  
  495.     int dragFraction = 2;
  496.     if (eSelType == eON)
  497.         dragFraction = 2;
  498.     else if (eSelType == eBELOW)
  499.         dragFraction = 3;
  500.     else if (eSelType == eABOVE)
  501.         dragFraction = 1;
  502.  
  503.     RDFGLOBAL_PerformDrop(pData->m_pDataSource, theNode, dragFraction);
  504.     
  505.     delete pData; // Clean this structure up.
  506.  
  507.     return 1;
  508. }
  509.     
  510. LRESULT CLinkToolbarButton::OnDropMenuClosed(WPARAM wParam, LPARAM lParam)
  511. {
  512.     int nCount;
  513.     if(m_pDropMenu != NULL)
  514.     {
  515.         HT_Resource theNode = (HT_Resource)m_pDropMenu->GetUserData();
  516.         nCount = m_pDropMenu->GetMenuItemCount();
  517.  
  518.         // clean out the menu 
  519.         for(int i = nCount - 1; i >= 0; i--)
  520.         {
  521.             m_pDropMenu->DeleteMenu(i, MF_BYPOSITION);
  522.         }
  523.         m_pDropMenu->DestroyDropMenu();
  524.         delete m_pDropMenu;
  525.         m_pDropMenu = NULL;
  526.  
  527.         if (theNode != NULL)
  528.             HT_SetOpenState(theNode, (PRBool)FALSE);
  529.     }
  530.     
  531.     return 1;
  532. }
  533.  
  534. void CLinkToolbarButton::OnSysColorChange( )
  535. {
  536.     if(nBitmapRefCount > 0)
  537.     {
  538.         VERIFY(::DeleteObject(m_hbmpBM));
  539.         VERIFY(::DeleteObject(m_hbmpBMSelected));
  540.         VERIFY(::DeleteObject(m_hbmpFolder));
  541.         VERIFY(::DeleteObject(m_hbmpSelectedFolder));
  542.         VERIFY(::DeleteObject(m_hbmpFolderOpen));
  543.         
  544.         HINSTANCE hInstance = AfxGetResourceHandle();
  545.         HDC hDC = ::GetDC(m_hWnd);
  546.         WFE_InitializeUIPalette(hDC);
  547.         HPALETTE hPalette = WFE_GetUIPalette(GetParentFrame());
  548.  
  549.         m_hbmpBM = WFE_LoadTransparentBitmap(hInstance, hDC, sysInfo.m_clrMenu, RGB(255, 0, 255),
  550.                                              hPalette, IDB_BOOKMARK_ITEM);
  551.         m_hbmpBMSelected = WFE_LoadTransparentBitmap(hInstance, hDC,sysInfo.m_clrHighlight,
  552.                                                      RGB(255, 0, 255), hPalette, IDB_BOOKMARK_ITEM);
  553.         m_hbmpFolder = WFE_LoadTransparentBitmap(hInstance, hDC,sysInfo.m_clrMenu, RGB(255, 0, 255),
  554.                                                  hPalette, IDB_BOOKMARK_FOLDER2);
  555.  
  556.         m_hbmpSelectedFolder = WFE_LoadTransparentBitmap(hInstance, hDC,sysInfo.m_clrHighlight, RGB(255, 0, 255),
  557.                                                  hPalette, IDB_BOOKMARK_FOLDER2);
  558.  
  559.         m_hbmpFolderOpen = WFE_LoadTransparentBitmap(hInstance, hDC, sysInfo.m_clrHighlight,
  560.                                                          RGB(255, 0, 255), hPalette, IDB_BOOKMARK_FOLDER_OPEN);
  561.  
  562.         ::ReleaseDC(m_hWnd, hDC);
  563.     }
  564.  
  565.     if(m_bBitmapFromParent)
  566.     {
  567.         HDC hDC = ::GetDC(m_hWnd);
  568.  
  569.         HPALETTE hPalette = WFE_GetUIPalette(GetParentFrame());
  570.  
  571.         HBITMAP hBitmap = WFE_LookupLoadAndEnterBitmap(hDC, m_nBitmapID, TRUE, hPalette,
  572.                                                        sysInfo.m_clrBtnFace, RGB(255, 0, 255));
  573.         ::ReleaseDC(m_hWnd, hDC);
  574.         SetBitmap(hBitmap, TRUE);
  575.     }
  576.     CToolbarButton::OnSysColorChange();
  577. }
  578.  
  579. ///////////////////////////////////////////////////////////////////////////
  580. //                            CLinkToolbarButton Helpers
  581. ///////////////////////////////////////////////////////////////////////////
  582.  
  583. void CLinkToolbarButton::FillInMenu(HT_Resource theNode)
  584. {
  585.     m_pCachedDropMenu->CreateOverflowMenuItem(ID_HOTLIST_VIEW, CString(szLoadString(IDS_MORE_BOOKMARKS)), NULL, NULL );
  586.  
  587.     HT_Cursor theCursor = HT_NewCursor(theNode);
  588.     HT_Resource theItem = NULL;
  589.     while (theItem = HT_GetNextItem(theCursor))
  590.     {
  591.         IconType nIconType = DetermineIconType(theItem, FALSE);
  592.         void* pCustomIcon = NULL;
  593.         if (nIconType == LOCAL_FILE)
  594.             pCustomIcon = FetchLocalFileIcon(theItem);
  595.         else if (nIconType == ARBITRARY_URL)
  596.             pCustomIcon = FetchCustomIcon(theItem, this, FALSE);
  597.  
  598.         HT_SetNodeFEData(theItem, this);
  599.  
  600.         if (HT_IsContainer(theItem))
  601.         {
  602.             CDropMenu *pSubMenu = new CDropMenu;
  603.             pSubMenu->SetUserData(theItem);
  604.  
  605.             CString csAmpersandString = FEU_EscapeAmpersand(HT_GetNodeName(theItem));
  606.  
  607.             m_pCachedDropMenu->AppendMenu(MF_POPUP, m_uCurBMID, pSubMenu, FALSE, 
  608.                 csAmpersandString, TRUE, m_hbmpFolder, m_hbmpFolderOpen, pCustomIcon, nIconType);
  609.             
  610.             m_BMMenuMap.SetAt(m_uCurBMID, theItem);
  611.             m_uCurBMID++;
  612.         }
  613.         else if (!HT_IsSeparator(theItem))
  614.         {
  615.             CString csAmpersandString = FEU_EscapeAmpersand(HT_GetNodeName(theItem));
  616.             m_pCachedDropMenu->AppendMenu(MF_STRING, m_uCurBMID, csAmpersandString, TRUE, 
  617.                 m_hbmpBM, m_hbmpBMSelected, pCustomIcon, nIconType);
  618.             m_BMMenuMap.SetAt(m_uCurBMID, theItem);
  619.             m_uCurBMID++;
  620.         }
  621.         else
  622.         {
  623.             m_pCachedDropMenu->AppendMenu(MF_SEPARATOR, 0, TRUE, NULL, NULL);
  624.         }
  625.     }
  626.     
  627.     HT_DeleteCursor(theCursor);
  628.     m_pCachedDropMenu = NULL;
  629. }
  630.  
  631. UINT CLinkToolbarButton::GetBitmapID(void)
  632. {
  633.     if (m_nBitmapID != 0)
  634.         return m_nBitmapID;
  635.  
  636.     if (m_Node && HT_IsContainer(m_Node))
  637.         return IDB_BUTTON_FOLDER;
  638.     else return IDB_USERBTN;
  639. }
  640.  
  641. UINT CLinkToolbarButton::GetBitmapIndex(void)
  642. {
  643.     return 0;
  644. }
  645.  
  646. void CLinkToolbarButton::SetTextWithoutResize(CString text)
  647. {
  648.     if(m_pButtonText != NULL)
  649.     {
  650.         XP_FREE(m_pButtonText);
  651.     }
  652.  
  653.     m_pButtonText = (LPTSTR)XP_ALLOC(text.GetLength() +1);
  654.     XP_STRCPY(m_pButtonText, text);
  655. }
  656.  
  657. void CLinkToolbarButton::LoadComplete(HT_Resource r)
  658. {
  659.     Invalidate();
  660. }
  661.  
  662. void CLinkToolbarButton::DrawCustomIcon(HDC hDC, int x, int y)
  663. {
  664.     int size = UseLargeIcons() ? 23 : 16;
  665.     DrawArbitraryURL(m_Node, x, y, size, size, hDC, 
  666.                     m_bDepressed ? (::GetSysColor(COLOR_BTNSHADOW)) :  (::GetSysColor(COLOR_BTNFACE)), 
  667.                      this, UseLargeIcons());
  668. }
  669.  
  670.  
  671. void CLinkToolbarButton::DrawLocalIcon(HDC hDC, int x, int y)
  672. {
  673.     if (m_Node)
  674.         DrawLocalFileIcon(m_Node, x, y, hDC);
  675. }
  676.  
  677.  
  678. ///////////////////////////////////////////////////////////////////////////
  679. //                            Class CLinkToolbarDropTarget
  680. ///////////////////////////////////////////////////////////////////////////
  681.  
  682. void CLinkToolbarDropTarget::Toolbar(CLinkToolbar *pToolbar)
  683. {
  684.     m_pToolbar = pToolbar;
  685. }
  686.  
  687. DROPEFFECT CLinkToolbarDropTarget::OnDragEnter(CWnd * pWnd,    COleDataObject * pDataObject,
  688.                                                DWORD dwKeyState, CPoint point)
  689. {
  690.     return OnDragOver(pWnd, pDataObject, dwKeyState, point);    
  691. }
  692.  
  693. DROPEFFECT CLinkToolbarDropTarget::OnDragOver(CWnd * pWnd, COleDataObject * pDataObject,
  694.                                               DWORD dwKeyState, CPoint point )
  695. {
  696.     int nStartX = 0;
  697.  
  698.     RECT buttonRect;
  699.  
  700.     int currentRow = 0;
  701.  
  702.     CLinkToolbarButton* pButton = NULL;
  703.  
  704.     for(int i = 0; i < m_pToolbar->GetNumButtons(); i++)
  705.     {
  706.         pButton = (CLinkToolbarButton*)(m_pToolbar->GetNthButton(i));
  707.         pButton->GetClientRect(&buttonRect);
  708.         pButton->MapWindowPoints(m_pToolbar, &buttonRect);
  709.         
  710.         nStartX += (buttonRect.right - buttonRect.left) + SPACE_BETWEEN_BUTTONS;
  711.         if (currentRow != pButton->GetRow())
  712.         {
  713.             currentRow++;
  714.             nStartX = LEFT_TOOLBAR_MARGIN + (buttonRect.right - buttonRect.left) + SPACE_BETWEEN_BUTTONS;
  715.         }
  716.  
  717.         if(point.x < nStartX && (point.y >= buttonRect.top && point.y <= buttonRect.bottom))
  718.            break;
  719.  
  720.         pButton = NULL;
  721.     }
  722.     
  723.     HT_Resource theNode = pButton ? pButton->GetNode() : HT_TopNode(HT_GetSelectedView(m_pToolbar->GetPane()));
  724.     
  725.     m_pToolbar->SetDragButton(pButton);
  726.  
  727.     if (pButton == NULL)
  728.         m_pToolbar->SetDragFraction(2);
  729.     else 
  730.     {
  731.         // Do the whole computation of drag fraction.  Cache our drag fraction and button.
  732.         CRect rect;
  733.         pButton->GetClientRect(&rect);
  734.         if (HT_IsContainer(pButton->GetNode()))
  735.         {
  736.             if (point.x <= rect.Width()/3)
  737.                 m_pToolbar->SetDragFraction(1);
  738.             else if (point.x <= 2*(rect.Width()/3))
  739.                 m_pToolbar->SetDragFraction(2);
  740.             else m_pToolbar->SetDragFraction(3);
  741.         }
  742.         else if (point.x <= rect.Width()/2)
  743.             m_pToolbar->SetDragFraction(1);
  744.         else m_pToolbar->SetDragFraction(2);
  745.     }
  746.  
  747.     return RDFGLOBAL_TranslateDropAction(theNode, pDataObject, m_pToolbar->GetDragFraction());
  748. }
  749.  
  750. BOOL CLinkToolbarDropTarget::OnDrop(CWnd * pWnd, COleDataObject * pDataObject,
  751.             DROPEFFECT dropEffect, CPoint point)
  752. {
  753.     HT_Resource theNode = HT_TopNode(HT_GetSelectedView(m_pToolbar->GetPane()));
  754.     if (m_pToolbar->GetDragButton())
  755.       theNode = m_pToolbar->GetDragButton()->GetNode();
  756.  
  757.     RDFGLOBAL_PerformDrop(pDataObject, theNode, m_pToolbar->GetDragFraction());
  758.     
  759.     return TRUE;
  760. }
  761.  
  762. // End CLinkToolbarDropTarget implementation
  763.  
  764. ///////////////////////////////////////////////////////////////////////////
  765. //                            Class CLinkToolbar
  766. ///////////////////////////////////////////////////////////////////////////
  767. #define LINKTOOLBARHEIGHT 21
  768. #define SPACE_BETWEEN_ROWS 2
  769.  
  770. // The Event Handler for HT notifications on the personal toolbar
  771. static void ptNotifyProcedure (HT_Notification ns, HT_Resource n, HT_Event whatHappened) 
  772. {
  773.   CLinkToolbar* theToolbar = (CLinkToolbar*)ns->data;
  774.   if (n != NULL)
  775.   {
  776.     HT_View theView = HT_GetView(n);
  777.     if (theView != NULL)
  778.     {
  779.         if (whatHappened == HT_EVENT_NODE_OPENCLOSE_CHANGED)
  780.         {
  781.             PRBool openState;
  782.             HT_GetOpenState(n, &openState);
  783.             if (openState)
  784.             {
  785.                 if (n == HT_TopNode(theView))
  786.                 {
  787.                     // Initial population of the toolbar. We should only receive this event once.
  788.                     theToolbar->FillInToolbar();
  789.                 }
  790.                 else 
  791.                 {
  792.                     // Toolbar button menu.  Populate it.
  793.                     CLinkToolbarButton* theButton = (CLinkToolbarButton*)(HT_GetNodeFEData(n));
  794.                     theButton->FillInMenu(n);
  795.                 }
  796.             }
  797.         }
  798.         else if (whatHappened == HT_EVENT_VIEW_REFRESH)
  799.         {
  800.             theToolbar->LayoutButtons(-1);
  801.         }
  802.         else if (HT_TopNode(theView) == HT_GetParent(n))
  803.         {
  804.             // Aside from the opening/closing, we only respond to events that occurred on the top node of
  805.             // the view or the immediate children (the buttons on the toolbar).
  806.             if (whatHappened == HT_EVENT_NODE_DELETED_DATA ||
  807.                  whatHappened == HT_EVENT_NODE_DELETED_NODATA)
  808.             {
  809.                 // Delete the button
  810.                 if (HT_EVENT_NODE_DELETED_DATA == whatHappened)
  811.                 {
  812.                     // Destroy the toolbar button
  813.                     CLinkToolbarButton* pButton = (CLinkToolbarButton*)HT_GetNodeFEData(n);
  814.                     if (theToolbar->m_hWnd)
  815.                       theToolbar->RemoveButton(pButton);
  816.                     else theToolbar->DecrementButtonCount();
  817.                     delete pButton;
  818.  
  819.                 }
  820.             }
  821.             else if (whatHappened == HT_EVENT_NODE_ADDED)
  822.             {
  823.                 theToolbar->AddHTButton(n);
  824.                 theToolbar->LayoutButtons(-1);
  825.             }
  826.             else if (whatHappened == HT_EVENT_NODE_VPROP_CHANGED)
  827.             {
  828.                 CLinkToolbarButton* pButton = (CLinkToolbarButton*)HT_GetNodeFEData(n);
  829.                 pButton->SetText(HT_GetNodeName(n)); // Update our name.
  830.                 theToolbar->LayoutButtons(-1);
  831.             }
  832.         }
  833.     }
  834.   }
  835. }
  836.  
  837. CLinkToolbar::CLinkToolbar(int nMaxButtons, int nToolbarStyle, int nPicturesAndTextHeight, int nPicturesHeight,
  838.                            int nTextHeight)
  839.      : CNSToolbar2(nMaxButtons, nToolbarStyle, nPicturesAndTextHeight, nPicturesHeight, nTextHeight)
  840. {
  841.     m_nNumberOfRows = 1;
  842.     
  843.     // Construct the notification struct used by HT
  844.     HT_Notification ns = new HT_NotificationStruct;
  845.     ns->notifyProc = ptNotifyProcedure;
  846.     ns->data = this;
  847.     
  848.     // Construct the pane and give it our notification struct
  849.     m_PersonalToolbarPane = HT_NewPersonalToolbarPane(ns);
  850.     if (m_PersonalToolbarPane)
  851.         HT_SetPaneFEData(m_PersonalToolbarPane, this);
  852. }
  853.  
  854. CLinkToolbar* CLinkToolbar::CreateUserToolbar(CWnd* pParent)
  855. {
  856.     // read in the maximum size we're allowing for personal toolbar items
  857.     int32 nMaxToolbarButtonChars;
  858.     int32 nMinToolbarButtonChars;
  859.  
  860.     if(PREF_GetIntPref("browser.personal_toolbar_button.max_chars", &nMaxToolbarButtonChars) ==
  861.         PREF_ERROR)
  862.         m_nMaxToolbarButtonChars = 30;
  863.     else
  864.         m_nMaxToolbarButtonChars = CASTINT(nMaxToolbarButtonChars);
  865.  
  866.     if(PREF_GetIntPref("browser.personal_toolbar_button.min_chars", &nMinToolbarButtonChars) ==
  867.         PREF_ERROR)
  868.         m_nMinToolbarButtonChars = 15;
  869.     else
  870.         m_nMinToolbarButtonChars = CASTINT(nMinToolbarButtonChars);
  871.  
  872.     CLinkToolbar* pToolbar = new CLinkToolbar(MAX_TOOLBAR_BUTTONS,theApp.m_pToolbarStyle, 43, 27, 27);
  873.  
  874.     if (pToolbar->Create(pParent))
  875.     {
  876.         pToolbar->SetButtonsSameWidth(FALSE);
  877.  
  878.         // Top node is already open.  Fill it in.
  879.         pToolbar->FillInToolbar();
  880.     }
  881.  
  882.     return pToolbar;
  883. }
  884.  
  885. CLinkToolbar::~CLinkToolbar()
  886. {
  887.     if (m_PersonalToolbarPane)
  888.     {
  889.         HT_Pane oldPane = m_PersonalToolbarPane;
  890.         m_PersonalToolbarPane = NULL;
  891.         HT_DeletePane(oldPane);
  892.     }
  893. }
  894.  
  895. int CLinkToolbar::Create(CWnd *pParent)
  896. {
  897.  
  898.     int result = CNSToolbar2::Create(pParent);
  899.  
  900.     if(!result)
  901.         return FALSE;
  902.  
  903.     m_DropTarget.Register(this);
  904.     m_DropTarget.Toolbar(this);
  905.  
  906.     DragAcceptFiles(FALSE);
  907.  
  908.     return result;
  909. }
  910.  
  911. void CLinkToolbar::FillInToolbar()
  912. {
  913.     if (!m_PersonalToolbarPane)
  914.         return;
  915.  
  916.     HT_View theView = HT_GetSelectedView(m_PersonalToolbarPane);
  917.     if (theView == NULL)
  918.         return;
  919.  
  920.     HT_Resource top = HT_TopNode(theView);
  921.     HT_Cursor cursor = HT_NewCursor(top);
  922.     if (cursor == NULL)
  923.         return;
  924.  
  925.     HT_Resource item = NULL;
  926.     while (item = HT_GetNextItem(cursor))
  927.         AddHTButton(item);
  928.  
  929.     HT_DeleteCursor(cursor);
  930.  
  931.     LayoutButtons(-1);
  932. }
  933.  
  934. void CLinkToolbar::AddHTButton(HT_Resource item)
  935. {
  936.     if (HT_IsSeparator(item))
  937.         return;
  938.  
  939.     CLinkToolbarButton* pButton = new CLinkToolbarButton;
  940.     BOOKMARKITEM bookmark;
  941.  
  942.     XP_STRCPY(bookmark.szText, HT_GetNodeName(item));
  943.     XP_STRCPY(bookmark.szAnchor, HT_GetNodeURL(item));
  944.  
  945.     CString csAmpersandString = FEU_EscapeAmpersand(CString(bookmark.szText));
  946.  
  947.     pButton->Create(this, theApp.m_pToolbarStyle, CSize(60,42), CSize(85, 25), csAmpersandString,
  948.                     bookmark.szText, bookmark.szAnchor, CSize(23,17), 
  949.                     m_nMaxToolbarButtonChars, m_nMinToolbarButtonChars, bookmark,
  950.                     item,
  951.                     (HT_IsContainer(item) ? TB_HAS_DRAGABLE_MENU | TB_HAS_IMMEDIATE_MENU : 0));
  952.         
  953.     if(HT_IsContainer(item))
  954.     {
  955.         CLinkToolbarButtonDropTarget *pDropTarget = new CLinkToolbarButtonDropTarget;
  956.         pButton->SetDropTarget(pDropTarget);
  957.     }
  958.  
  959.     HT_SetNodeFEData(item, pButton);
  960.  
  961.     AddButtonAtIndex(pButton); // Have to put the button in the array, since the toolbar base class depends on it.
  962. }
  963.  
  964. int CLinkToolbar::GetHeight(void)
  965. {
  966.     return m_nNumberOfRows * (LINKTOOLBARHEIGHT + SPACE_BETWEEN_ROWS) + SPACE_BETWEEN_ROWS;
  967. }
  968.  
  969.  
  970.  
  971. void CLinkToolbar::SetMinimumRows(int rowWidth)
  972. {
  973.     int rowCount = 1;
  974.     int totalLine = 0;
  975.     int rowSpace = rowWidth - RIGHT_TOOLBAR_MARGIN - LEFT_TOOLBAR_MARGIN;
  976.  
  977.     if (rowSpace <= 0)
  978.     {
  979.         SetRows(rowCount);
  980.         return;
  981.     }
  982.  
  983.     HT_Cursor cursor = HT_NewCursor(HT_TopNode(HT_GetSelectedView(m_PersonalToolbarPane)));
  984.     if (!cursor)
  985.         return;
  986.     HT_Resource item;
  987.     while (rowCount < MAX_TOOLBAR_ROWS && (item = HT_GetNextItem(cursor)))
  988.     {
  989.         // Get the current button
  990.         CLinkToolbarButton* pButton = (CLinkToolbarButton*)(HT_GetNodeFEData(item));
  991.         if (!pButton) // Separator
  992.             continue;
  993.  
  994.         CSize s = pButton->GetMinimalButtonSize();
  995.         int tempTotal = totalLine + s.cx;
  996.         if (tempTotal > rowSpace)
  997.         {
  998.             rowCount++;
  999.             totalLine = s.cx;
  1000.         }
  1001.         else totalLine = tempTotal;
  1002.  
  1003.         totalLine += SPACE_BETWEEN_BUTTONS;
  1004.     }
  1005.     HT_DeleteCursor(cursor);
  1006.  
  1007.     SetRows(rowCount); 
  1008. }
  1009.     
  1010. void CLinkToolbar::ComputeLayoutInfo(CLinkToolbarButton* pButton, int numChars, int rowWidth, int& usedSpace)
  1011. {
  1012.    CString originalText = HT_GetNodeName(pButton->GetNode());
  1013.  
  1014.    int currCount = originalText.GetLength();
  1015.         
  1016.    // Start off at the maximal string
  1017.    CString strTxt = originalText;
  1018.  
  1019.    if (currCount > numChars)
  1020.    {
  1021.        strTxt = originalText.Left(numChars-3) + "...";
  1022.    }
  1023.    
  1024.    pButton->SetTextWithoutResize(strTxt);
  1025.    pButton->SetButtonSize(pButton->GetButtonSizeFromChars(strTxt, numChars));
  1026.  
  1027. // Determine how much additional padding we'll use to fill out a row if this button doesn't fit.
  1028.     int rowUsage = usedSpace % rowWidth;
  1029.     if (rowUsage == 0)
  1030.         rowUsage = rowWidth;
  1031.     int additionalPadding = rowWidth - rowUsage;
  1032.         
  1033.     int tempTotal = rowUsage + pButton->GetButtonSize().cx;
  1034.  
  1035. // The button doesn't fit.  Flesh out this row and start a new one.    
  1036.     if (tempTotal > rowWidth)
  1037.       usedSpace += additionalPadding;
  1038.     
  1039. // Add this button to the row.
  1040.     usedSpace += pButton->GetButtonSize().cx + SPACE_BETWEEN_BUTTONS;
  1041.  
  1042. // Set this button's row information, so it knows which row it is currently residing on.
  1043.     int currentRow = usedSpace/rowWidth;
  1044.     if (usedSpace % rowWidth == 0)
  1045.         currentRow--;
  1046.  
  1047.     pButton->SetRow(currentRow);
  1048.  
  1049. }
  1050.  
  1051. void CLinkToolbar::LayoutButtons(int nIndex)
  1052. {
  1053.     int width = m_nWidth;
  1054.  
  1055.     if (width <= 0)
  1056.     {
  1057.         CRect rect;
  1058.         GetParentFrame()->GetClientRect(&rect);
  1059.         width = rect.Width();
  1060.     }
  1061.     
  1062.     int numButtonsAtMin = 0;
  1063.     int numButtonsAtMax = 0;
  1064.     int idealSpace = 0;
  1065.    
  1066. // First quickly determine what the minimum # of rows we consume is.  This is our allowed space.
  1067.     int oldRows = GetRows();
  1068.  
  1069.     int rowWidth = width-RIGHT_TOOLBAR_MARGIN-LEFT_TOOLBAR_MARGIN;
  1070.     
  1071.     if (rowWidth <= 0 && m_nWidth > 0)
  1072.         rowWidth = m_nWidth - RIGHT_TOOLBAR_MARGIN - LEFT_TOOLBAR_MARGIN;
  1073.  
  1074.     SetMinimumRows(rowWidth);
  1075.  
  1076.     int newRows = GetRows();
  1077.  
  1078.     int allowedSpace = rowWidth * GetRows(); // Toolbar width * numRows
  1079.     int usedSpace = 0;
  1080.  
  1081.     int numChars = 0; // Start off trying to fit the whole thing on the toolbar.
  1082.     int minChars = 0;
  1083.     
  1084.     HT_Cursor cursor = HT_NewCursor(HT_TopNode(HT_GetSelectedView(m_PersonalToolbarPane)));
  1085.     if (!cursor)
  1086.         return;
  1087.     HT_Resource item;
  1088.     while ((item = HT_GetNextItem(cursor)))
  1089.     {
  1090.         // Get the current button
  1091.         CLinkToolbarButton* pButton = (CLinkToolbarButton*)(HT_GetNodeFEData(item));
  1092.         if (!pButton)
  1093.             continue;
  1094.  
  1095.         if (numChars == 0)
  1096.         {
  1097.             numChars = pButton->GetMaxTextCharacters();
  1098.             minChars = pButton->GetMinTextCharacters();
  1099.         }
  1100.  
  1101.         // See how much this num chars takes up
  1102.         ComputeLayoutInfo(pButton, numChars, rowWidth, usedSpace);
  1103.     }
  1104.     HT_DeleteCursor(cursor);
  1105.  
  1106.     while (usedSpace > allowedSpace && numChars > minChars)
  1107.     {
  1108.         usedSpace = 0;
  1109.         numChars--;
  1110.         // Let's see what we can fit.
  1111.         HT_Cursor cursor = HT_NewCursor(HT_TopNode(HT_GetSelectedView(m_PersonalToolbarPane)));
  1112.         if (!cursor)
  1113.             return;
  1114.         HT_Resource item;
  1115.         while ((item = HT_GetNextItem(cursor)))
  1116.         {
  1117.             // Get the current button
  1118.             CLinkToolbarButton* pButton = (CLinkToolbarButton*)(HT_GetNodeFEData(item));
  1119.             if (!pButton)  // Separator
  1120.                 continue;
  1121.  
  1122.             // See how much this num chars takes up
  1123.             ComputeLayoutInfo(pButton, numChars, rowWidth, usedSpace);
  1124.         }
  1125.         HT_DeleteCursor(cursor);
  1126.     }
  1127.  
  1128.     // That's it.  lay them out with this number of characters.
  1129.     
  1130.     int nStartX = LEFT_TOOLBAR_MARGIN;
  1131.     int nStartY = SPACE_BETWEEN_ROWS;
  1132.  
  1133.     int row = 0;
  1134.  
  1135.     CSize buttonSize;
  1136.     CString strTxt;
  1137.  
  1138.     cursor = HT_NewCursor(HT_TopNode(HT_GetSelectedView(m_PersonalToolbarPane)));
  1139.     if (!cursor)
  1140.         return;
  1141.     while ((item = HT_GetNextItem(cursor)))
  1142.     {
  1143.         // Get the current button
  1144.         CLinkToolbarButton* pButton = (CLinkToolbarButton*)(HT_GetNodeFEData(item));
  1145.         if (!pButton)  // Separator
  1146.             continue;
  1147.  
  1148.         buttonSize = pButton->GetButtonSize();  // The size we must be
  1149.         
  1150.         int tempTotal = nStartX + buttonSize.cx;
  1151.         if (tempTotal > (width - RIGHT_TOOLBAR_MARGIN))
  1152.         {
  1153.             nStartX = LEFT_TOOLBAR_MARGIN;
  1154.             nStartY += LINKTOOLBARHEIGHT + SPACE_BETWEEN_ROWS;
  1155.         }
  1156.  
  1157.         pButton->MoveWindow(nStartX, nStartY,
  1158.                                       buttonSize.cx, buttonSize.cy);
  1159.  
  1160.         nStartX += buttonSize.cx + SPACE_BETWEEN_BUTTONS;
  1161.     }
  1162.     HT_DeleteCursor(cursor);
  1163.  
  1164.     //record the width of our toolbar
  1165.     //if (nStartY == SPACE_BETWEEN_ROWS && nStartX < (width - RIGHT_TOOLBAR_MARGIN))
  1166.     //  m_nWidth = nStartX;
  1167.     //else 
  1168.        m_nWidth = width;
  1169.  
  1170.     if (oldRows != newRows)
  1171.         GetParentFrame()->RecalcLayout();    
  1172. }
  1173.  
  1174. void CLinkToolbar::WidthChanged(int animWidth)
  1175. {
  1176.     CRect rect;
  1177.    
  1178.     GetParentFrame()->GetClientRect(&rect);
  1179.     int width = rect.Width() - animWidth;
  1180.     
  1181.     int numButtonsAtMin = 0;
  1182.     int numButtonsAtMax = 0;
  1183.     int idealSpace = 0;
  1184.    
  1185. // First quickly determine what the minimum # of rows we consume is.  This is our allowed space.
  1186.     int oldRows = GetRows();
  1187.  
  1188.     int rowWidth = width-RIGHT_TOOLBAR_MARGIN-LEFT_TOOLBAR_MARGIN;
  1189.     
  1190.     if (rowWidth <= 0 && m_nWidth > 0)
  1191.         rowWidth = m_nWidth - RIGHT_TOOLBAR_MARGIN - LEFT_TOOLBAR_MARGIN;
  1192.  
  1193.     SetMinimumRows(rowWidth);
  1194.  
  1195.     int newRows = GetRows();
  1196.  
  1197.     int allowedSpace = rowWidth * GetRows(); // Toolbar width * numRows
  1198.     int usedSpace = 0;
  1199.  
  1200.     int numChars = 0; // Start off trying to fit the whole thing on the toolbar.
  1201.     int minChars = 0;
  1202.     HT_Cursor cursor = HT_NewCursor(HT_TopNode(HT_GetSelectedView(m_PersonalToolbarPane)));
  1203.     if (!cursor)
  1204.         return;
  1205.     HT_Resource item;
  1206.     while ((item = HT_GetNextItem(cursor)))
  1207.     {
  1208.         // Get the current button
  1209.         CLinkToolbarButton* pButton = (CLinkToolbarButton*)(HT_GetNodeFEData(item));
  1210.         if (!pButton)  // Separator
  1211.             continue;
  1212.  
  1213.         if (numChars == 0)
  1214.         {
  1215.             numChars = pButton->GetMaxTextCharacters();
  1216.             minChars = pButton->GetMinTextCharacters();
  1217.         }
  1218.  
  1219.         // See how much this num chars takes up
  1220.         ComputeLayoutInfo(pButton, numChars, rowWidth, usedSpace);
  1221.     }
  1222.     HT_DeleteCursor(cursor);
  1223.  
  1224.     while (usedSpace > allowedSpace && numChars > minChars)
  1225.     {
  1226.         usedSpace = 0;
  1227.         numChars--;
  1228.         // Let's see what we can fit.
  1229.         HT_Cursor cursor = HT_NewCursor(HT_TopNode(HT_GetSelectedView(m_PersonalToolbarPane)));
  1230.         if (!cursor)
  1231.             return;
  1232.         HT_Resource item;
  1233.         while ((item = HT_GetNextItem(cursor)))
  1234.         {
  1235.             // Get the current button
  1236.             CLinkToolbarButton* pButton = (CLinkToolbarButton*)(HT_GetNodeFEData(item));
  1237.             if (!pButton)
  1238.                 continue;
  1239.  
  1240.             // See how much this num chars takes up
  1241.             ComputeLayoutInfo(pButton, numChars, rowWidth, usedSpace);
  1242.         }
  1243.         HT_DeleteCursor(cursor);
  1244.     }
  1245.  
  1246.     // That's it.  lay them out with this number of characters.
  1247.     
  1248.     int nStartX = LEFT_TOOLBAR_MARGIN;
  1249.     int nStartY = SPACE_BETWEEN_ROWS;
  1250.  
  1251.     int row = 0;
  1252.  
  1253.     CSize buttonSize;
  1254.     CString strTxt;
  1255.  
  1256.     cursor = HT_NewCursor(HT_TopNode(HT_GetSelectedView(m_PersonalToolbarPane)));
  1257.     if (!cursor)
  1258.         return;
  1259.     
  1260.     while ((item = HT_GetNextItem(cursor)))
  1261.     {
  1262.         // Get the current button
  1263.         CLinkToolbarButton* pButton = (CLinkToolbarButton*)(HT_GetNodeFEData(item));
  1264.         if (!pButton)
  1265.             continue;
  1266.  
  1267.         buttonSize = pButton->GetButtonSize();  // The size we must be
  1268.         
  1269.         int tempTotal = nStartX + buttonSize.cx;
  1270.         if (tempTotal > (width - RIGHT_TOOLBAR_MARGIN))
  1271.         {
  1272.             nStartX = LEFT_TOOLBAR_MARGIN;
  1273.             nStartY += LINKTOOLBARHEIGHT + SPACE_BETWEEN_ROWS;
  1274.         }
  1275.  
  1276.         pButton->MoveWindow(nStartX, nStartY,
  1277.                                       buttonSize.cx, buttonSize.cy);
  1278.  
  1279.         nStartX += buttonSize.cx + SPACE_BETWEEN_BUTTONS;
  1280.     }
  1281.     HT_DeleteCursor(cursor);
  1282.  
  1283.  
  1284.     m_nWidth = width;
  1285.  
  1286.     if (oldRows != newRows)
  1287.         GetParentFrame()->RecalcLayout();
  1288. }
  1289.  
  1290.  
  1291.  
  1292. ///////////////////////////////////////////////////////////////////////////////////
  1293. //                                    CLinkToolbar Messages
  1294. ///////////////////////////////////////////////////////////////////////////////////
  1295.  
  1296. BEGIN_MESSAGE_MAP(CLinkToolbar, CNSToolbar2)
  1297.     //{{AFX_MSG_MAP(CNSToolbar2)
  1298.     ON_WM_RBUTTONDOWN()
  1299.     //}}AFX_MSG_MAP
  1300.  
  1301. END_MESSAGE_MAP()
  1302.  
  1303. void CLinkToolbar::OnRButtonDown(UINT nFlags, CPoint point)
  1304. {
  1305.     m_MenuCommandMap.Clear();
  1306.     HT_View theView = HT_GetSelectedView(m_PersonalToolbarPane);
  1307.     HT_Cursor theCursor = HT_NewContextualMenuCursor(theView, PR_FALSE, PR_TRUE);
  1308.     CMenu menu;
  1309.     ClientToScreen(&point);
  1310.     if (menu.CreatePopupMenu() != 0 && theCursor != NULL)
  1311.     {
  1312.         // We have a cursor. Attempt to iterate
  1313.         HT_MenuCmd theCommand; 
  1314.         while (HT_NextContextMenuItem(theCursor, &theCommand))
  1315.         {
  1316.             char* menuName = HT_GetMenuCmdName(theCommand);
  1317.             if (theCommand == HT_CMD_SEPARATOR)
  1318.                 menu.AppendMenu(MF_SEPARATOR);
  1319.             else
  1320.             {
  1321.                 // Add the command to our command map
  1322.                 CRDFMenuCommand* rdfCommand = new CRDFMenuCommand(menuName, theCommand);
  1323.                 int index = m_MenuCommandMap.AddCommand(rdfCommand);
  1324.                 menu.AppendMenu(MF_ENABLED, index+FIRST_HT_MENU_ID, menuName);
  1325.             }
  1326.         }
  1327.         HT_DeleteCursor(theCursor);
  1328.  
  1329.         menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this, NULL);    
  1330.  
  1331.         menu.DestroyMenu();
  1332.     }
  1333. }
  1334.  
  1335. BOOL CLinkToolbar::OnCommand( WPARAM wParam, LPARAM lParam )
  1336. {
  1337.     if (wParam >= FIRST_HT_MENU_ID && wParam <= LAST_HT_MENU_ID)
  1338.     {
  1339.         // A selection was made from the context menu.
  1340.         // Use the menu map to get the HT command value
  1341.         CRDFMenuCommand* theCommand = (CRDFMenuCommand*)(m_MenuCommandMap.GetCommand((int)wParam-FIRST_HT_MENU_ID));
  1342.         if (theCommand)
  1343.         {
  1344.             HT_MenuCmd htCommand = theCommand->GetHTCommand();
  1345.             HT_DoMenuCmd(m_PersonalToolbarPane, htCommand);
  1346.         }
  1347.         return TRUE;
  1348.     }
  1349.     return((BOOL)GetParentFrame()->SendMessage(WM_COMMAND, wParam, lParam));
  1350. }
  1351.