home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / FolderMenu.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  11.7 KB  |  428 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.    Folder.cpp -- class for doing the dynamic folder menus
  20.    Created: Chris Toshok <toshok@netscape.com>, 19-Dec-1996.
  21.  */
  22.  
  23.  
  24.  
  25. #include "FolderMenu.h"
  26. #include "MNView.h"
  27. #include "MozillaApp.h"
  28. #include "felocale.h"
  29.  
  30. #include <Xm/LabelG.h>
  31. #include <Xm/SeparatoG.h>
  32. #include <Xfe/Xfe.h>
  33.  
  34.  
  35.  
  36. #include "xpgetstr.h"
  37. extern int XFE_FOLDER_MENU_FILE_HERE;
  38.  
  39. #define MORE_BUTTON_NAME    "mailNewsMoreButton"
  40. #define MORE_PULLDOWN_NAME    "mailNewsMorePulldown"
  41.  
  42. typedef struct FolderCons {
  43.     XFE_FolderMenu *menu;
  44.     MSG_FolderInfo *info;
  45. } FolderCons;
  46.  
  47. XFE_FolderMenu::XFE_FolderMenu(CommandType cmd, Widget w, XFE_Frame *frame)
  48. {
  49.   m_cascade = w;
  50.   m_parentFrame = frame;
  51.   m_cmd = cmd;
  52.  
  53.   XtAddCallback(m_cascade, XmNdestroyCallback, destroy_cb, this);
  54.   
  55.   XtVaGetValues(m_cascade,
  56.         XmNsubMenuId, &m_submenu,
  57.         NULL);
  58.  
  59.   XtVaGetValues(m_submenu,
  60.         XmNnumChildren, &m_firstslot,
  61.         NULL);
  62.  
  63.   XP_ASSERT(m_submenu);
  64.  
  65.   XFE_MozillaApp::theApp()->registerInterest(XFE_MNView::foldersHaveChanged,
  66.                          this,
  67.                          (XFE_FunctionNotification)foldersHaveChanged_cb);
  68.  
  69.   // make sure we initially install an update callback
  70.   foldersHaveChanged(NULL, NULL, NULL);
  71. }
  72.  
  73. XFE_FolderMenu::~XFE_FolderMenu()
  74. {
  75.   XFE_MozillaApp::theApp()->unregisterInterest(XFE_MNView::foldersHaveChanged,
  76.                            this,
  77.                            (XFE_FunctionNotification)foldersHaveChanged_cb);
  78. }
  79.  
  80. void
  81. XFE_FolderMenu::generate(Widget cascade, XtPointer clientData, XFE_Frame *frame)
  82. {
  83.   XFE_FolderMenu *obj;
  84.   CommandType cmd = Command::intern((char*)clientData);
  85.  
  86.   obj = new XFE_FolderMenu(cmd, cascade, frame);
  87. }
  88.  
  89. void
  90. XFE_FolderMenu::activate_cb(Widget, XtPointer cd, XtPointer)
  91. {
  92.     FolderCons *cons = (FolderCons*)cd;
  93.     XFE_FolderMenu *obj = cons->menu;
  94.     MSG_FolderInfo *info = cons->info;
  95.  
  96.     XP_ASSERT(info);
  97.     
  98.     if (obj->m_parentFrame->handlesCommand(obj->m_cmd, (void*)info))
  99.         obj->m_parentFrame->doCommand(obj->m_cmd, (void*)info);
  100. }
  101.  
  102. void
  103. XFE_FolderMenu::add_folder_menu_items(Widget menu,
  104.                       MSG_FolderInfo *info,
  105.                       XP_Bool filing_allowed_here)
  106. {
  107.   int32 count;
  108.   Arg av [20];
  109.   int ac;
  110.           
  111.  
  112.   if (filing_allowed_here)
  113.       {
  114.           Widget button;
  115.           FolderCons *cons = XP_NEW_ZAP(FolderCons);
  116.           char buf[500];
  117.           XmString xmname;
  118.           char *folderFileName, *folderName;
  119.  
  120.           folderName = (char*)MSG_GetFolderNameFromID(info);
  121.           if (strrchr(folderName, '/'))
  122.               folderFileName = strrchr(folderName, '/') + 1;
  123.           else
  124.               folderFileName = folderName;
  125.  
  126.           PR_snprintf(buf, sizeof(buf), XP_GetString(XFE_FOLDER_MENU_FILE_HERE), folderFileName);
  127.  
  128.           xmname = XmStringCreate(buf, XmFONTLIST_DEFAULT_TAG);
  129.           
  130.           cons->menu = this;
  131.           cons->info = info;
  132.  
  133.           ac = 0;
  134.           XtSetArg(av[ac], XmNuserData, NULL); ac ++;
  135.           XtSetArg (av[ac], XmNlabelString, xmname); ac++;
  136.  
  137.           button = XmCreatePushButtonGadget(menu, Command::getString(m_cmd), av, ac);
  138.  
  139.           XmStringFree(xmname);
  140.           
  141.           XtAddCallback(button, XmNactivateCallback, activate_cb, cons);
  142.           XtAddCallback(button, XmNdestroyCallback, free_cons_cb, cons);
  143.           XtManageChild(button);
  144.           XtVaCreateManagedWidget("sep",
  145.                                   xmSeparatorGadgetClass,
  146.                                   menu,
  147.                                   XmNshadowThickness, 2,
  148.                                   NULL);
  149.     }
  150.  
  151.   count = MSG_GetFolderChildren(fe_getMNMaster(), info, NULL, 0);
  152.   
  153.   if (count == 0)
  154.       {
  155.           return;
  156.       }
  157.   else
  158.       {
  159.           MSG_FolderInfo **infos = (MSG_FolderInfo**)XP_CALLOC(count, sizeof(MSG_FolderInfo*));
  160.           int i;
  161.           
  162.           MSG_GetFolderChildren(fe_getMNMaster(), info, infos, count);
  163.           
  164.           for (i = 0; i < count; i ++)
  165.               {
  166.                   XmString xmname;
  167.                   FolderCons *cons = XP_NEW_ZAP(FolderCons);
  168.  
  169.                   // Find the last of the "More..." menu panes
  170.                   Widget parent = getLastMoreMenu(menu);
  171.  
  172.                   XP_ASSERT( XfeIsAlive(parent) );
  173.                   XP_ASSERT( XmIsRowColumn(parent) );
  174.  
  175.                   cons->menu = this;
  176.                   cons->info = infos[i];
  177.  
  178.                   if (MSG_GetFolderChildren(fe_getMNMaster(), infos[i], NULL, 0) > 0)
  179.                       {
  180.                           Visual *v;
  181.                           Colormap cmap;
  182.                           Cardinal depth;
  183.                           Widget button;
  184.                           Widget submenu;
  185.                           char *folderName;
  186.                           char *folderFileName;
  187.                           
  188.                           XtVaGetValues (XtParent(parent), XtNvisual, &v,
  189.                                          XtNcolormap, &cmap, XtNdepth, &depth, 0);
  190.                           
  191.                           ac = 0;
  192.                           XtSetArg (av[ac], XmNvisual, v); ac++;
  193.                           XtSetArg (av[ac], XmNdepth, depth); ac++;
  194.                           XtSetArg (av[ac], XmNcolormap, cmap); ac++;
  195.                           submenu = XmCreatePulldownMenu (parent, "folderCascadeMenu",
  196.                                                           av, ac);
  197.                           
  198.                           folderName = (char*)MSG_GetFolderNameFromID(infos[i]);
  199.                           if (strrchr(folderName, '/'))
  200.                               folderFileName = strrchr(folderName, '/') + 1;
  201.                           else
  202.                               folderFileName = folderName;
  203.                           
  204.                           xmname = XmStringCreate(folderFileName, XmFONTLIST_DEFAULT_TAG);
  205.  
  206.                           ac = 0;
  207.                           XtSetArg (av[ac], XmNlabelString, xmname); ac++;
  208.                           XtSetArg (av[ac], XmNsubMenuId, submenu); ac++;
  209.                           XtSetArg (av[ac], XmNuserData, NULL); ac++;
  210.                           button = XmCreateCascadeButtonGadget (parent, "folderCascadeButton",
  211.                                                                 av, ac);
  212.                           
  213.                           XtAddCallback(button, XmNcascadingCallback, fillin_menu,
  214.                                         cons);
  215.                           XtAddCallback(button, XmNdestroyCallback, free_cons_cb, cons);
  216.                           XtManageChild (button);
  217.                       }
  218.                   else
  219.                       {
  220.                           Widget button;
  221.                           char *folderName;
  222.                           char *folderFileName;
  223.                           
  224.                           folderName = (char*)MSG_GetFolderNameFromID(infos[i]);
  225.                           if (strrchr(folderName, '/'))
  226.                               folderFileName = strrchr(folderName, '/') + 1;
  227.                           else
  228.                               folderFileName = folderName;
  229.                           
  230.                           xmname = XmStringCreate(folderFileName, XmFONTLIST_DEFAULT_TAG);
  231.                           
  232.                           ac = 0;
  233.                           XtSetArg(av[ac], XmNuserData, NULL); ac ++;
  234.                           XtSetArg (av[ac], XmNlabelString, xmname); ac++;
  235.  
  236.                           button = XmCreatePushButtonGadget(parent, Command::getString(m_cmd), av, ac);
  237.                           
  238.                           XtAddCallback(button, XmNactivateCallback, activate_cb, cons);
  239.                           XtAddCallback(button, XmNdestroyCallback, free_cons_cb, cons);
  240.                           XtManageChild(button);
  241.                       }
  242.                   XmStringFree(xmname);
  243.               }
  244.           
  245.           XP_FREE(infos);
  246.       }
  247. }
  248.  
  249. void
  250. XFE_FolderMenu::fillin_menu(Widget widget, XtPointer clientData, XtPointer)
  251. {
  252.     FolderCons *cons = (FolderCons*)clientData;
  253.     XFE_FolderMenu *obj = cons->menu;
  254.     MSG_FolderInfo *info = cons->info;
  255.     Widget menu = 0;
  256.     XtVaGetValues(widget, XmNsubMenuId, &menu, 0);
  257.     
  258.     if (info)
  259.         obj->add_folder_menu_items(menu, info, True);
  260.     
  261.     XtRemoveCallback(widget, XmNcascadingCallback, fillin_menu, cons);
  262. }
  263.  
  264. void
  265. XFE_FolderMenu::update()
  266. {
  267.   Widget *kids;
  268.   int nkids;
  269.  
  270.   XtVaGetValues (m_submenu, XmNchildren, &kids, XmNnumChildren, &nkids, 0);
  271.  
  272.   if (nkids) 
  273.     {
  274.       kids = &(kids[m_firstslot]);
  275.       nkids -= m_firstslot;
  276.  
  277.       XtUnmanageChildren (kids, nkids);
  278.       fe_DestroyWidgetTree(kids, nkids);
  279.     }
  280.  
  281.   {
  282.       MSG_FolderInfo **mailfolderinfos = NULL;
  283.       int num_mailfolderinfos, i;
  284.  
  285.       num_mailfolderinfos = MSG_GetFoldersWithFlag(fe_getMNMaster(), MSG_FOLDER_FLAG_MAIL, NULL, 0);
  286.       if (num_mailfolderinfos > 0)
  287.           {
  288.               mailfolderinfos = (MSG_FolderInfo**)XP_ALLOC(sizeof(MSG_FolderInfo*) * num_mailfolderinfos);
  289.               MSG_GetFoldersWithFlag(fe_getMNMaster(), MSG_FOLDER_FLAG_MAIL, mailfolderinfos, num_mailfolderinfos);
  290.           }
  291.       
  292.       for (i = 0; i < num_mailfolderinfos; i ++)
  293.           {
  294.               MSG_FolderLine line;
  295.  
  296.               if (MSG_GetFolderLineById(fe_getMNMaster(), mailfolderinfos[i], &line))
  297.                   {
  298.                       if (line.level == 1)
  299.                           {
  300.                               XmString label_str = XmStringCreate((char*)(line.prettyName 
  301.                                                                           ? line.prettyName : line.name),
  302.                                                                   XmFONTLIST_DEFAULT_TAG);
  303.                               XtVaCreateManagedWidget("sep",
  304.                                                       xmSeparatorGadgetClass,
  305.                                                       m_submenu,
  306.                                                       XmNshadowThickness, 2,
  307.                                                       NULL);
  308.                               XtVaCreateManagedWidget("label",
  309.                                                       xmLabelGadgetClass,
  310.                                                       m_submenu,
  311.                                                       XmNlabelString, label_str,
  312.                                                       NULL);
  313.                               XmStringFree(label_str);
  314.                               XtVaCreateManagedWidget("sep",
  315.                                                       xmSeparatorGadgetClass,
  316.                                                       m_submenu,
  317.                                                       XmNshadowThickness, 2,
  318.                                                       NULL);
  319.                               
  320.                               add_folder_menu_items(m_submenu, mailfolderinfos[i], False);
  321.                           }
  322.                   }
  323.           }
  324.  
  325.       if (mailfolderinfos)
  326.           XP_FREE(mailfolderinfos);
  327.   }
  328.  
  329.   XtRemoveCallback(m_cascade, XmNcascadingCallback, update_cb, this);
  330. }
  331.  
  332. void
  333. XFE_FolderMenu::update_cb(Widget, XtPointer clientData, XtPointer)
  334. {
  335.   XFE_FolderMenu *obj = (XFE_FolderMenu*)clientData;
  336.  
  337.   obj->update();
  338. }
  339.  
  340. void
  341. XFE_FolderMenu::destroy_cb(Widget, XtPointer clientData, XtPointer)
  342. {
  343.   XFE_FolderMenu *obj = (XFE_FolderMenu*)clientData;
  344.  
  345.   delete obj;
  346. }
  347.  
  348. void
  349. XFE_FolderMenu::free_cons_cb(Widget, XtPointer clientData, XtPointer)
  350. {
  351.     XP_FREE(clientData);
  352. }
  353.  
  354. XFE_CALLBACK_DEFN(XFE_FolderMenu, foldersHaveChanged)(XFE_NotificationCenter *,
  355.                               void *,
  356.                               void *)
  357. {
  358.   // This may seem stupid, but it keeps us from having more than
  359.   // one reference to this particular callback without having
  360.   // to worry about other cascadingCallbacks.
  361.  
  362.   // remove it if it's already there
  363.   XtRemoveCallback(m_cascade, XmNcascadingCallback, update_cb, this);
  364.  
  365.   // and then add it back.
  366.   XtAddCallback(m_cascade, XmNcascadingCallback, update_cb, this);
  367. }
  368.  
  369. Widget 
  370. XFE_FolderMenu::getLastMoreMenu(Widget menu)
  371. {
  372.     XP_ASSERT( XfeIsAlive(menu) );
  373.     XP_ASSERT( XmIsRowColumn(menu) );
  374.  
  375.     // Find the last more... menu
  376.     Widget last_more_menu = XfeMenuFindLastMoreMenu(menu,MORE_BUTTON_NAME);
  377.  
  378.     XP_ASSERT( XfeIsAlive(last_more_menu) );
  379.  
  380.     // Check if the last menu is full
  381.     if (XfeMenuIsFull(last_more_menu))
  382.     {
  383.         // Look for the More... button for the last menu
  384.         Widget more_button = XfeMenuGetMoreButton(last_more_menu,
  385.                                                   MORE_BUTTON_NAME);
  386.  
  387.         // If no more button, create one plus a submenu
  388.         if (!more_button)
  389.         {
  390.             more_button = createMoreButton(last_more_menu);
  391.  
  392.             XtManageChild(more_button);
  393.         }
  394.  
  395.         // Set the last more menu to the submenu of the new more button
  396.         last_more_menu = XfeCascadeGetSubMenu(more_button);
  397.     }
  398.  
  399.     return last_more_menu;
  400. }
  401. //////////////////////////////////////////////////////////////////////////
  402. Widget 
  403. XFE_FolderMenu::createMoreButton(Widget menu)
  404. {
  405.     XP_ASSERT( XfeIsAlive(menu) );
  406.     XP_ASSERT( XmIsRowColumn(menu) );
  407.  
  408.     Widget        cascade;
  409.     Widget        submenu = NULL;
  410.     Arg            av[5];
  411.     Cardinal    ac = 0;
  412.  
  413.     ac = 0;
  414.     XtSetArg(av[ac],XmNvisual,        XfeVisual(menu));    ac++;
  415.     XtSetArg(av[ac],XmNdepth,        XfeDepth(menu));    ac++;
  416.     XtSetArg(av[ac],XmNcolormap,    XfeColormap(menu));    ac++;
  417.     
  418.     submenu = XmCreatePulldownMenu(menu,MORE_PULLDOWN_NAME,av,ac);
  419.  
  420.     ac = 0;
  421.     XtSetArg(av[ac],XmNsubMenuId,    submenu);    ac++;
  422.  
  423.     cascade = XmCreateCascadeButtonGadget(menu,MORE_BUTTON_NAME,av,ac);
  424.  
  425.     return cascade;
  426. }
  427. //////////////////////////////////////////////////////////////////////////
  428.