home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / SubTabView.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  13.8 KB  |  615 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.    SubTabView.cpp -- 4.x subscribe ui tabs.
  20.    Created: Chris Toshok <toshok@netscape.com>, 18-Oct-1996.
  21.    */
  22.  
  23.  
  24.  
  25. #include "SubTabView.h"
  26. #include "Outliner.h"
  27. #include "Command.h"
  28.  
  29. #include "xfe.h"
  30. #include "msgcom.h"
  31. #include "xp_mem.h"
  32. #include "xpassert.h"
  33.  
  34. #include <Xm/DrawnB.h>
  35. #include <Xm/Form.h>
  36. #include <XmL/Folder.h>
  37. #include "DtWidgets/ComboBox.h"
  38.  
  39. #include "xpgetstr.h"
  40. extern int XFE_SUB_OUTLINER_COLUMN_NAME;
  41. extern int XFE_SUB_OUTLINER_COLUMN_POSTINGS;
  42.  
  43. const int XFE_SubTabView::OUTLINER_COLUMN_NAME = 0;
  44. const int XFE_SubTabView::OUTLINER_COLUMN_SUBSCRIBE = 1;
  45. const int XFE_SubTabView::OUTLINER_COLUMN_POSTINGS = 2;
  46.  
  47. fe_icon XFE_SubTabView::subscribedIcon = { 0 };
  48.  
  49. int XFE_SubTabView::m_numhosts = -1;
  50. MSG_Host **XFE_SubTabView::m_hosts = NULL;
  51.  
  52. XFE_SubTabView::XFE_SubTabView(XFE_Component *toplevel_component, Widget parent,
  53.                                XFE_View *parent_view, MWContext *context,
  54.                                int tab_string_id, MSG_Pane *p)
  55.     : XFE_MNListView(toplevel_component, parent_view, context, p)
  56. {
  57.     XmString xmstr;
  58.     xmstr = XmStringCreate(XP_GetString( tab_string_id ), XmFONTLIST_DEFAULT_TAG);
  59.     m_form = XmLFolderAddTabForm(parent, xmstr);
  60.     XmStringFree(xmstr);
  61.  
  62.     setBaseWidget(m_form);
  63.  
  64.     m_ancestorInfo = NULL;
  65. }
  66.  
  67. XFE_SubTabView::~XFE_SubTabView()
  68. {
  69.     if (m_hosts) delete [] m_hosts;
  70.  
  71.     m_hosts = NULL;
  72.     m_numhosts = -1;
  73. }
  74.  
  75. void
  76. XFE_SubTabView::init_outliner_icons(Widget outliner)
  77. {
  78.     {
  79.         Pixel bg_pixel;
  80.     
  81.         XtVaGetValues(outliner, XmNbackground, &bg_pixel, 0);
  82.     
  83.         if (!subscribedIcon.pixmap)
  84.             fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  85.                            getToplevel()->getFGPixel(),
  86.                            bg_pixel,
  87.                            &subscribedIcon,
  88.                            NULL, 
  89.                            MN_Check.width, MN_Check.height,
  90.                            MN_Check.mono_bits, MN_Check.color_bits, MN_Check.mask_bits, FALSE);
  91.  
  92.         // update this to the right icon once hagan gives it to us.
  93.         if (!msgReadIcon.pixmap)
  94.             fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  95.                            getToplevel()->getFGPixel(),
  96.                            bg_pixel,
  97.                            &msgReadIcon,
  98.                            NULL, 
  99.                            MN_DotRead.width, MN_DotRead.height,
  100.                            MN_DotRead.mono_bits, MN_DotRead.color_bits, MN_DotRead.mask_bits, FALSE);
  101.             
  102.         if (!newsgroupIcon.pixmap)
  103.             fe_NewMakeIcon(getToplevel()->getBaseWidget(),
  104.                            getToplevel()->getFGPixel(),
  105.                            bg_pixel,
  106.                            &newsgroupIcon,
  107.                            NULL, 
  108.                            MN_Newsgroup.width, MN_Newsgroup.height,
  109.                            MN_Newsgroup.mono_bits, MN_Newsgroup.color_bits, MN_Newsgroup.mask_bits, FALSE);
  110.     }
  111. }
  112.  
  113. Boolean
  114. XFE_SubTabView::isCommandEnabled(CommandType command, void */*calldata*/, XFE_CommandInfo*)
  115. {
  116.     MWContext *c = MSG_GetContext(m_pane);
  117.  
  118.     if (command == xfeCmdStopLoading)
  119.         {
  120.             return fe_IsContextStoppable(c);
  121.         }
  122.     else
  123.         {
  124.             XP_Bool selectable = False;
  125.             MSG_CommandType msg_cmd = commandToMsgCmd(command);
  126.       
  127.             if (msg_cmd != (MSG_CommandType)~0)
  128.                 {
  129.                     const int *selected;
  130.                     int count = 0;
  131.  
  132.                     m_outliner->getSelection(&selected, &count);
  133.       
  134.                     if (MSG_CommandStatus(m_pane, msg_cmd, (MSG_ViewIndex*)selected,
  135.                                           count, &selectable, NULL, NULL, NULL) < 0)
  136.                         selectable = FALSE;
  137.                 }
  138.  
  139.             
  140.             return selectable;
  141.         }
  142. }
  143.  
  144. Boolean
  145. XFE_SubTabView::handlesCommand(CommandType command, void */*calldata*/, XFE_CommandInfo*)
  146. {
  147.     if (command == xfeCmdToggleSubscribe
  148.         || command == xfeCmdStopLoading)
  149.         {
  150.             return True;
  151.         }
  152.     else
  153.         {
  154.             return False; // we don't want XFE_MNListView to get caught up in this
  155.         }
  156. }
  157.  
  158. void
  159. XFE_SubTabView::doCommand(CommandType command, void */*calldata*/, XFE_CommandInfo*)
  160. {
  161.     const int *selected;
  162.     int count;
  163.   
  164.     m_outliner->getSelection(&selected, &count);
  165.  
  166.     if (command == xfeCmdToggleSubscribe)
  167.         {
  168.             MSG_Command(m_pane, MSG_ToggleSubscribed, (MSG_ViewIndex*)selected, count);
  169.         }
  170.     else if (command == xfeCmdStopLoading)
  171.         {
  172.             XP_InterruptContext(m_contextData);
  173.         }
  174.     else
  175.         {
  176.             MSG_CommandType msg_cmd = commandToMsgCmd(command);
  177.  
  178.             if (msg_cmd != (MSG_CommandType)~0)
  179.                 MSG_Command(m_pane, msg_cmd, (MSG_ViewIndex*)selected, count);
  180.         }
  181.  
  182.     updateButtons();
  183. }
  184.  
  185. void *
  186. XFE_SubTabView::ConvFromIndex(int /*index*/)
  187. {
  188.     return 0;
  189. }
  190.  
  191. int
  192. XFE_SubTabView::ConvToIndex(void */*item*/)
  193. {
  194.     return 0;
  195. }
  196.  
  197. char *
  198. XFE_SubTabView::getColumnName(int column)
  199. {
  200.     switch (column)
  201.         {
  202.         case OUTLINER_COLUMN_NAME:    return "Name";
  203.         case OUTLINER_COLUMN_SUBSCRIBE:    return "Sub";
  204.         case OUTLINER_COLUMN_POSTINGS:    return "Postings";
  205.         default: XP_ASSERT(0); return 0;
  206.         }
  207. }
  208.  
  209. char *
  210. XFE_SubTabView::getColumnHeaderText(int column)
  211. {
  212.     switch (column)
  213.         {
  214.         case OUTLINER_COLUMN_NAME:
  215.             return XP_GetString(XFE_SUB_OUTLINER_COLUMN_NAME);
  216.         case OUTLINER_COLUMN_SUBSCRIBE:
  217.             return 0;
  218.         case OUTLINER_COLUMN_POSTINGS:
  219.             return XP_GetString(XFE_SUB_OUTLINER_COLUMN_POSTINGS);
  220.         default:
  221.             XP_ASSERT(0);
  222.             return 0;
  223.         }
  224. }
  225.  
  226. fe_icon *
  227. XFE_SubTabView::getColumnHeaderIcon(int column)
  228. {
  229.     if (column == OUTLINER_COLUMN_SUBSCRIBE)
  230.         return &subscribedIcon;
  231.     else
  232.         return 0;
  233. }
  234.  
  235. EOutlinerTextStyle
  236. XFE_SubTabView::getColumnHeaderStyle(int /*column*/)
  237. {
  238.     return OUTLINER_Default;
  239. }
  240.  
  241. void *
  242. XFE_SubTabView::acquireLineData(int line)
  243. {
  244.     if (!MSG_GetGroupNameLineByIndex(m_pane, line, 1, &m_groupLine))
  245.         return NULL;
  246.  
  247.     m_ancestorInfo = new OutlinerAncestorInfo[m_groupLine.level + 1];
  248.  
  249.     int i = m_groupLine.level;
  250.     int idx = line + 1;
  251.     while ( i > 0 ) 
  252.         {
  253.             if ( idx < m_outliner->getTotalLines())
  254.                 {
  255.                     MSG_GroupNameLine groupLine;
  256.                     MSG_GetGroupNameLineByIndex( m_pane, idx, 1, &groupLine );
  257.                     if ( groupLine.level == i ) 
  258.                         {
  259.                             m_ancestorInfo[i].has_prev = TRUE;
  260.                             m_ancestorInfo[i].has_next = TRUE;
  261.                             i--;
  262.                             idx++;
  263.                         } 
  264.                     else if ( groupLine.level < i ) 
  265.                         {
  266.                             m_ancestorInfo[i].has_prev = FALSE;
  267.                             m_ancestorInfo[i].has_next = FALSE;
  268.                             i--;
  269.                         }
  270.                     else
  271.                         {
  272.                             idx++;
  273.                         }
  274.                 }
  275.             else
  276.                 {
  277.                     m_ancestorInfo[i].has_prev = FALSE;
  278.                     m_ancestorInfo[i].has_next = FALSE;
  279.                     i--;
  280.                 }
  281.         }
  282.         m_ancestorInfo[i].has_prev = FALSE;
  283.         m_ancestorInfo[i].has_next = FALSE;
  284.  
  285.     return &m_groupLine;
  286. }
  287.  
  288. void
  289. XFE_SubTabView::getTreeInfo(XP_Bool *expandable, XP_Bool *is_expanded, int *depth,
  290.                             OutlinerAncestorInfo **ancestor)
  291. {
  292.     XP_Bool is_line_expandable;
  293.     XP_Bool is_line_expanded;
  294.  
  295.     is_line_expandable = (m_groupLine.flags & MSG_GROUPNAME_FLAG_HASCHILDREN) != 0;
  296.  
  297.     if (is_line_expandable)
  298.         {
  299.             is_line_expanded = (m_groupLine.flags & MSG_GROUPNAME_FLAG_ELIDED) == 0;
  300.         }
  301.     else
  302.         {
  303.             is_line_expanded = FALSE;
  304.         }
  305.  
  306.     if ( ancestor )
  307.         *ancestor = m_ancestorInfo;
  308.  
  309.     if (depth)
  310.         *depth = m_groupLine.level;
  311.  
  312.     if (expandable)
  313.         *expandable = is_line_expandable;
  314.  
  315.     if (is_expanded)
  316.         *is_expanded = is_line_expanded;
  317. }
  318.  
  319. EOutlinerTextStyle
  320. XFE_SubTabView::getColumnStyle(int /*column*/)
  321. {
  322.     if (m_groupLine.total > 0)
  323.         return OUTLINER_Bold;
  324.     else
  325.         return OUTLINER_Default;
  326. }
  327.  
  328. char *
  329. XFE_SubTabView::getColumnText(int column)
  330. {
  331.     static char postings_buf[256];
  332.  
  333.     switch (column)
  334.         {
  335.         case OUTLINER_COLUMN_NAME:
  336.             return m_groupLine.name;
  337.         case OUTLINER_COLUMN_SUBSCRIBE:
  338.             return 0;
  339.         case OUTLINER_COLUMN_POSTINGS:
  340.             if (m_groupLine.total > 0)
  341.                 {
  342.                     sprintf(postings_buf, "%d", m_groupLine.total);
  343.                     return postings_buf;
  344.                 }
  345.             else
  346.                 {
  347.                     return 0;
  348.                 }
  349.         default:
  350.             XP_ASSERT(0);
  351.             return 0;
  352.         }
  353. }
  354.  
  355. fe_icon *
  356. XFE_SubTabView::getColumnIcon(int column)
  357. {
  358.     switch (column)
  359.         {
  360.         case OUTLINER_COLUMN_NAME:
  361.             return &newsgroupIcon;
  362.         case OUTLINER_COLUMN_SUBSCRIBE:
  363.             if (!(m_groupLine.flags & MSG_GROUPNAME_FLAG_HASCHILDREN))
  364.                 if (m_groupLine.flags & MSG_GROUPNAME_FLAG_SUBSCRIBED)
  365.                     return &subscribedIcon;
  366.                 else
  367.                     return &msgReadIcon; // XXX 
  368.             else
  369.                 return 0;
  370.         case OUTLINER_COLUMN_POSTINGS:
  371.             return 0;
  372.         default:
  373.             XP_ASSERT(0);
  374.             return 0;
  375.         }
  376. }
  377.  
  378. void
  379. XFE_SubTabView::releaseLineData()
  380. {
  381.     if (m_ancestorInfo)
  382.         {
  383.             delete [] m_ancestorInfo;
  384.             m_ancestorInfo = NULL;
  385.         }
  386. }
  387.  
  388. void
  389. XFE_SubTabView::Buttonfunc(const OutlineButtonFuncData *data)
  390. {
  391.     if (data->row == -1)
  392.         return; // no sorting in these views.
  393.  
  394.     if (data->clicks == 2)
  395.         {
  396.             m_outliner->selectItemExclusive(data->row);
  397.  
  398.             if (m_groupLine.flags & MSG_GROUPNAME_FLAG_HASCHILDREN)
  399.                 {
  400.                     MSG_ToggleExpansion(m_pane, (MSG_ViewIndex)data->row, NULL);
  401.                 }
  402.             else
  403.                 MSG_Command(m_pane, MSG_ToggleSubscribed, (MSG_ViewIndex*)&data->row, 1);      
  404.         }
  405.     else
  406.         {
  407.             if (data->ctrl)
  408.                 {
  409.                     m_outliner->toggleSelected(data->row);
  410.                 }
  411.             else if (data->shift)
  412.                 {
  413.                     // select the range.
  414.                     const int *selected;
  415.                     int count;
  416.                     
  417.                     m_outliner->getSelection(&selected, &count);
  418.                     
  419.                     if (count == 0) /* there wasn't anything selected yet. */
  420.                         {
  421.                             m_outliner->selectItemExclusive(data->row);
  422.                         }
  423.                     else if (count == 1) /* there was only one, so we select the range from
  424.                                             that item to the new one. */
  425.                         {
  426.                             m_outliner->selectRangeByIndices(selected[0], data->row);
  427.                         }
  428.                     else /* we had a range of items selected, so let's do something really
  429.                             nice with them. */
  430.                         {
  431.                             m_outliner->trimOrExpandSelection(data->row);
  432.                         }
  433.                 }
  434.             else
  435.                 {
  436.                     // handle the columns that don't actually move the selection here
  437.                     if (data->column == OUTLINER_COLUMN_SUBSCRIBE)
  438.                         {
  439.                             if (!(m_groupLine.flags & MSG_GROUPNAME_FLAG_HASCHILDREN))
  440.                                 MSG_Command(m_pane, MSG_ToggleSubscribed, (MSG_ViewIndex*)&data->row, 1);
  441.                         }
  442.                     else
  443.                         {
  444.                             // we've selected a newsgroup
  445.                             m_outliner->selectItemExclusive(data->row);
  446.                         }
  447.                 }
  448.         }
  449.     
  450.     updateButtons();
  451. }
  452.  
  453. void
  454. XFE_SubTabView::Flippyfunc(const OutlineFlippyFuncData *data)
  455. {
  456.     int delta;
  457.     XP_Bool selection_needs_bubbling = False;
  458.  
  459.     delta = MSG_ExpansionDelta(m_pane, data->row);
  460.  
  461.     if (delta == 0)
  462.         return;
  463.  
  464.     /* we're not selected and we're being collapsed.
  465.        check if any of our children are selected, and if
  466.        so we select this row. */
  467.     if (!m_outliner->isSelected(data->row)
  468.         && delta < 0)
  469.         {
  470.             int num_children = -1 * delta;
  471.             int i;
  472.             
  473.             for (i = data->row + 1; i < data->row + num_children; i ++)
  474.                 if (m_outliner->isSelected(i))
  475.                     {
  476.                         selection_needs_bubbling = True;
  477.                     }
  478.         }
  479.  
  480.     MSG_ToggleExpansion(m_pane, data->row, NULL);
  481.  
  482.     if (selection_needs_bubbling)
  483.         m_outliner->selectItem(data->row);
  484.  
  485.     updateButtons();
  486. }
  487.  
  488. void
  489. XFE_SubTabView::updateButtons()
  490. {
  491. }
  492.  
  493. void
  494. XFE_SubTabView::initializeServerCombo(Widget parent)
  495. {
  496.     Colormap cmap;
  497.     Cardinal depth;
  498.     Visual *v;
  499.  
  500.     XtVaGetValues(getToplevel()->getBaseWidget(),
  501.                   XmNvisual, &v,
  502.                   XmNcolormap, &cmap,
  503.                   XmNdepth, &depth,
  504.                   NULL);
  505.  
  506.     m_serverCombo = XtVaCreateManagedWidget("serverCombo",
  507.                                             dtComboBoxWidgetClass,
  508.                                             parent,
  509.                                             XmNtype, XmDROP_DOWN_COMBO_BOX,
  510.                                             XmNarrowType, XmMOTIF,
  511.                                             XmNvisibleItemCount, 5,
  512.                                             XmNvisual, v,
  513.                                             XmNcolormap, cmap,
  514.                                             XmNdepth, depth,
  515.                                             NULL);
  516.  
  517.     XtAddCallback(m_serverCombo, XmNselectionCallback, server_select_cb, this);
  518. }
  519.  
  520. void
  521. XFE_SubTabView::serverSelected()
  522. {
  523.     // nothing to do here.  subclasses will do stuff, though.
  524. }
  525.  
  526. void
  527. XFE_SubTabView::server_select(int pos)
  528. {
  529.     XP_ASSERT(pos < m_numhosts && m_hosts);
  530.  
  531.     if (m_hosts [ pos ] != MSG_SubscribeGetHost(m_pane))
  532.         {
  533.             MSG_SubscribeSetHost(m_pane, m_hosts[ pos ]);
  534.       
  535.             serverSelected();
  536.         }
  537. }
  538.  
  539. void
  540. XFE_SubTabView::server_select_cb(Widget, XtPointer clientData, XtPointer cd)
  541. {
  542.     DtComboBoxCallbackStruct *cb = (DtComboBoxCallbackStruct *)cd;
  543.     XFE_SubTabView *obj = (XFE_SubTabView *)clientData;
  544.  
  545.     obj->server_select(cb->item_position);
  546. }
  547.  
  548. void
  549. XFE_SubTabView::defaultFocus()
  550. {
  551.     // nothing.
  552. }
  553.  
  554. int
  555. XFE_SubTabView::getButtonsMaxWidth()
  556. {
  557.   return 0;
  558. }
  559.  
  560. void
  561. XFE_SubTabView::setButtonsWidth(int /*width*/)
  562. {
  563.   // nothing.
  564. }
  565.  
  566. void
  567. XFE_SubTabView::syncServerList()
  568. {
  569.     if (m_hosts) delete [] m_hosts;
  570.  
  571.     // This needs to be updated to handle IMAP as well!
  572.     m_numhosts = MSG_GetSubscribingHosts(XFE_MNView::getMaster(),
  573.                                          NULL, 0);
  574.   
  575.   
  576.     m_hosts = new MSG_Host* [ m_numhosts ];
  577.  
  578.     MSG_GetSubscribingHosts(XFE_MNView::getMaster(), m_hosts, m_numhosts);
  579. }
  580.  
  581. // this method is called when a tab is activated.
  582. void
  583. XFE_SubTabView::syncServerCombo()
  584. {
  585.     int i;
  586.  
  587.     XP_ASSERT(m_hosts);
  588.  
  589.     DtComboBoxDeleteAllItems(m_serverCombo);
  590.  
  591.     for (i = 0; i < m_numhosts; i ++)
  592.         {
  593.             XmString str;
  594.       
  595.             str = XmStringCreate((char*)MSG_GetHostUIName(m_hosts[i]), XmFONTLIST_DEFAULT_TAG);
  596.             DtComboBoxAddItem(m_serverCombo, str, 0, True);
  597.             if (m_hosts[i] == MSG_SubscribeGetHost(m_pane))
  598.                 {
  599.                     DtComboBoxSelectItem(m_serverCombo, str);
  600.                     //                    DtComboBoxSetItem(m_serverCombo, str);
  601.                 }
  602.             XmStringFree(str);
  603.         }
  604. }
  605.  
  606. void
  607. XFE_SubTabView::button_callback(Widget w, 
  608.                                 XtPointer clientData,
  609.                                 XtPointer /*calldata*/)
  610. {
  611.     XFE_SubTabView *obj = (XFE_SubTabView*)clientData;
  612.   
  613.     obj->doCommand(Command::intern(XtName(w)));
  614. }
  615.