home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / EditorToolbar.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  34.5 KB  |  1,371 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. /*
  20.  *----------------------------------------------------------------------------
  21.  *
  22.  *  EditorToolbar.cpp --- Toolbar for Editor and HTML Mail Compose.
  23.  *
  24.  *  Created: David Williams <djw@netscape.com>, Feb-7-1997
  25.  *  RCSID: "$Id: EditorToolbar.cpp,v 3.1 1998/03/28 03:26:24 ltabb Exp $"
  26.  *
  27.  *----------------------------------------------------------------------------
  28.  */
  29.  
  30.  
  31. #include "Frame.h"
  32. #include "View.h"
  33. #include "EditorView.h"
  34. #include "Logo.h"
  35. #include "Button.h" // for fe_buttonSetPixmaps()
  36.  
  37. #include <DtWidgets/ComboBoxP.h>
  38. #include <Xm/MenuUtilP.h>   /* for _XmGrabPointer(), etc */
  39. #include <Xm/VendorSP.h>    /* for _XmAddGrab(), _XmRemoveGrab(), etc */
  40. #include <Xm/Label.h>
  41. #include <Xm/ArrowB.h>
  42. #include <Xm/RowColumnP.h>
  43. #include <Xfe/Xfe.h>
  44. #include <Xfe/Primitive.h>
  45. #include <Xfe/Cascade.h>
  46. #include <Xfe/Button.h>
  47. #include <pa_tags.h>        /* for P_UNUM_LIST, P_NUM_LIST, etc */
  48.  
  49.  
  50. #include "EditorToolbar.h"
  51. #include "xeditor.h"
  52.  
  53. extern struct _WidgetClassRec xfePrimitiveClassRec;
  54.  
  55. static void
  56. install_children_from_toolspec(Widget w_parent,
  57.                                ToolbarSpec* tb_spec,
  58.                                XFE_Component* cp_parent);
  59.  
  60. #define SAVE_ME(w) XtVaSetValues((w), XmNuserData, (XtPointer)this, 0)
  61.  
  62. class XFE_ComponentList
  63. {
  64. public:
  65.     XFE_AbstractMenuItem* item() {
  66.         return m_item;
  67.     }
  68.     XFE_ComponentList*   next() {
  69.         return m_next;
  70.     }
  71.     XFE_ComponentList* push(XFE_AbstractMenuItem* item) {
  72.         XFE_ComponentList* foo = new XFE_ComponentList;
  73.         foo->m_next = this;
  74.         foo->m_item = item;
  75.         return foo;
  76.     }
  77. private:
  78.     XFE_AbstractMenuItem* m_item;
  79.     XFE_ComponentList*    m_next;
  80. };
  81.  
  82. static void
  83. getIcons(Widget widget, ToolbarSpec* spec,
  84.          Pixmap* r_pixmap,
  85.          Pixmap* r_ipixmap,
  86.          Pixmap* r_rpixmap,
  87.          Pixmap* r_apixmap)
  88. {
  89.     Pixmap  pixmap = 0;;
  90.     Pixmap ipixmap = 0;
  91.     Pixmap rpixmap = 0;
  92.     Pixmap apixmap = 0;
  93.  
  94.     Widget parent = XtParent(widget);
  95.  
  96.     if (spec->iconGroup != NULL) {
  97.         Widget toplevel = XfeAncestorFindTopLevelShell(parent);
  98.         Pixel  fg = XfeForeground(parent);
  99.         Pixel  bg = XfeBackground(parent);
  100.         
  101.         IconGroup_createAllIcons(spec->iconGroup, toplevel,    fg, bg);
  102.         
  103.         pixmap = spec->iconGroup->pixmap_icon.pixmap;
  104.         ipixmap = spec->iconGroup->pixmap_i_icon.pixmap;
  105.         rpixmap = spec->iconGroup->pixmap_mo_icon.pixmap;
  106.         apixmap = spec->iconGroup->pixmap_md_icon.pixmap;
  107.     }
  108.  
  109.     if (r_pixmap != NULL)
  110.         *r_pixmap = pixmap;
  111.     if (r_ipixmap != NULL)
  112.         *r_ipixmap = ipixmap;
  113.     if (r_rpixmap != NULL)
  114.         *r_rpixmap = rpixmap;
  115.     if (r_apixmap != NULL)
  116.         *r_apixmap = apixmap;
  117. }
  118.  
  119. static void
  120. fe_setLabelTypeFromSpec(Widget widget, ToolbarSpec* spec)
  121. {
  122.     if (XfeIsButton(widget))
  123.     {
  124.          if (spec && spec->iconGroup)
  125.         {
  126.             fe_buttonSetPixmaps(widget,spec->iconGroup);
  127.         }
  128.     }
  129.     else
  130.     {
  131.         if (spec && spec->iconGroup)        
  132.         {
  133.             Pixmap        pixmap;
  134.             Pixmap        ipixmap;
  135.             Arg            args[4];
  136.             Cardinal    n = 0;
  137.             
  138.             getIcons(widget, spec, &pixmap, &ipixmap, NULL, NULL);
  139.             
  140.             XtSetArg(args[n], XmNlabelType, XmPIXMAP); n++;
  141.             XtSetArg(args[n], XmNlabelPixmap, pixmap); n++;
  142.             
  143.             if (ipixmap != 0 && ipixmap != pixmap) 
  144.             {
  145.                 XtSetArg(args[n], XmNlabelInsensitivePixmap, ipixmap); n++;
  146.             }
  147.             
  148.             if (n)
  149.             {
  150.                 XtSetValues(widget, args, n);
  151.             }
  152.         }
  153.         else
  154.         {
  155.             XtVaSetValues(widget,
  156.                           XmNlabelType, XmSTRING,
  157.                           NULL);
  158.         }
  159.     }
  160. }
  161.  
  162. XP_Bool
  163. XFE_ActionMenuItem::showsUpdate()
  164. {
  165.     if (m_cmd_handler != NULL)
  166.         return m_cmd_handler->isDynamic();
  167.     else
  168.         return TRUE;
  169. }
  170.  
  171. static void
  172. pb_arm_cb(Widget /*widget*/, XtPointer clientData, XtPointer)
  173. {
  174.     XFE_ActionMenuItem*  menu_item = (XFE_ActionMenuItem*)clientData;
  175.     XFE_Component*       frame = menu_item->getToplevel();
  176.     CommandType          cmd = menu_item->getCmdId();
  177.  
  178.     frame->notifyInterested(Command::commandArmedCallback, (void*)cmd);
  179. }
  180.  
  181. static void
  182. pb_activate_cb(Widget widget, XtPointer clientData, XtPointer callData)
  183. {
  184.     XmPushButtonCallbackStruct* cbs
  185.         = (XmPushButtonCallbackStruct*)callData;
  186.     XFE_ActionMenuItem*  menu_item = (XFE_ActionMenuItem*)clientData;
  187.     XFE_Frame*           frame = menu_item->getParentFrame();
  188.     CommandType          cmd = menu_item->getCmdId();
  189.  
  190.     XFE_CommandInfo e_info(XFE_COMMAND_BUTTON_ACTIVATE,
  191.                            widget,
  192.                            cbs->event);
  193.  
  194.     menu_item->doCommand(&e_info);
  195.  
  196.     frame->notifyInterested(Command::commandDispatchedCallback, (void*)cmd);
  197. }
  198.  
  199. static void
  200. pb_disarm_cb(Widget /*widget*/, XtPointer clientData, XtPointer)
  201. {
  202.     XFE_ActionMenuItem*  menu_item = (XFE_ActionMenuItem*)clientData;
  203.     XFE_Frame*           frame = menu_item->getParentFrame();
  204.     CommandType          cmd = menu_item->getCmdId();
  205.  
  206.     frame->notifyInterested(Command::commandDisarmedCallback, (void*)cmd);
  207. }
  208.  
  209. XFE_EditorToolbarPushButton::XFE_EditorToolbarPushButton(Widget,
  210.                                                          ToolbarSpec* spec,
  211.                                                          XFE_Component* tb)
  212.     : XFE_EditorToolbarItem(tb, spec)
  213. {
  214. }
  215.  
  216. void
  217. XFE_EditorToolbarPushButton::update()
  218. {
  219.     XFE_CommandInfo e_info(XFE_COMMAND_BUTTON_ACTIVATE, m_widget);
  220.     Boolean         sensitive = False;
  221.  
  222.     //
  223.     //    Do we have a command handler?
  224.     //
  225.     if (!m_cmd_handler)
  226.         m_cmd_handler = getParentFrame()->getCommand(m_cmd_id);
  227.  
  228.     if (m_cmd_handler != NULL)
  229.         sensitive = m_cmd_handler->isEnabled(getParentFrame(), &e_info);
  230.  
  231.     XtVaSetValues(m_widget, XtNsensitive, sensitive, 0);
  232. }
  233.  
  234. class XFE_XfePushButton : public XFE_EditorToolbarPushButton
  235. {
  236. public:
  237.     XFE_XfePushButton(Widget parent, ToolbarSpec* spec, XFE_Component* tb);
  238. };
  239.  
  240. XFE_XfePushButton::XFE_XfePushButton(Widget parent,
  241.                                      ToolbarSpec* spec,
  242.                                      XFE_Component* tb)
  243.     : XFE_EditorToolbarPushButton(parent, spec, tb)
  244. {
  245.     Arg      args[8];
  246.     Cardinal n = 0;
  247.  
  248.     m_widget = XtCreateWidget((char*)spec->toolbarButtonName,
  249.                               xfeButtonWidgetClass,
  250.                               parent,
  251.                               args,
  252.                               n);
  253.     fe_setLabelTypeFromSpec(m_widget, spec);
  254.  
  255.     XtAddCallback(m_widget, XmNarmCallback, pb_arm_cb, this);
  256.     XtAddCallback(m_widget, XmNactivateCallback, pb_activate_cb, this);
  257.     XtAddCallback(m_widget, XmNdisarmCallback, pb_disarm_cb, this);
  258.  
  259.     fe_WidgetAddToolTips(m_widget);
  260.  
  261.     SAVE_ME(m_widget);
  262.  
  263.     installDestroyHandler();
  264. }
  265.  
  266. class XFE_XmPushButton : public XFE_EditorToolbarPushButton
  267. {
  268. public:
  269.     XFE_XmPushButton(Widget parent,
  270.                      ToolbarSpec* spec,
  271.                      XFE_Component* tb);
  272. };
  273.  
  274. XFE_XmPushButton::XFE_XmPushButton(Widget parent,
  275.                                    ToolbarSpec* spec,
  276.                                    XFE_Component* tb)
  277.     : XFE_EditorToolbarPushButton(parent, spec, tb)
  278. {
  279.     Arg      args[8];
  280.     Cardinal n = 0;
  281.  
  282.     m_widget = XmCreatePushButtonGadget(parent,
  283.                                         (char*)spec->toolbarButtonName,
  284.                                         args,
  285.                                         n);
  286.     fe_setLabelTypeFromSpec(m_widget, spec);
  287.  
  288.     XtAddCallback(m_widget, XmNarmCallback, pb_arm_cb, this);
  289.     XtAddCallback(m_widget, XmNactivateCallback, pb_activate_cb, this);
  290.     XtAddCallback(m_widget, XmNdisarmCallback, pb_disarm_cb, this);
  291.  
  292.  
  293.     SAVE_ME(m_widget);
  294.  
  295.     installDestroyHandler();
  296. }
  297.  
  298. static void
  299. tb_valuechanged_cb(Widget widget, XtPointer closure, XtPointer cb_d)
  300. {
  301.     XfeButtonCallbackStruct*  cbs = (XfeButtonCallbackStruct*)cb_d;
  302.     XFE_EditorToolbarToggleButton* button =
  303.         (XFE_EditorToolbarToggleButton*)closure;
  304.  
  305.     XFE_Frame*  frame = button->getParentFrame();
  306.     CommandType cmd = button->getCmdId();
  307.  
  308.     XFE_CommandInfo e_info(XFE_COMMAND_BUTTON_ACTIVATE,
  309.                            widget,
  310.                            cbs->event);
  311.   
  312.     button->doCommand(&e_info);
  313.  
  314.     frame->notifyInterested(Command::commandDispatchedCallback, (void*)cmd);
  315. }
  316.  
  317. void
  318. XFE_EditorToolbarToggleButton::update()
  319. {
  320.     XFE_CommandInfo e_info(XFE_COMMAND_BUTTON_ACTIVATE, m_widget);
  321.     Boolean         sensitive = False;
  322.     Boolean         selected = False;
  323.     Boolean         determinate = True;
  324.     XFE_Frame*      frame = getParentFrame();
  325.  
  326.     //
  327.     //    Do we have a command handler?
  328.     //
  329.     if (!m_cmd_handler)
  330.         m_cmd_handler = getParentFrame()->getCommand(m_cmd_id);
  331.  
  332.     if (m_cmd_handler != NULL) {
  333.         sensitive = m_cmd_handler->isEnabled(frame, &e_info);
  334.         selected = m_cmd_handler->isSelected(frame, &e_info);
  335.         determinate = m_cmd_handler->isDeterminate(frame, &e_info);
  336.     }
  337.  
  338.     XtVaSetValues(m_widget,
  339.                   XtNsensitive, sensitive,
  340.                   XmNdeterminate, determinate,
  341.                   XmNarmed, (selected || !determinate),
  342.                   0);
  343. }
  344.  
  345. XFE_EditorToolbarToggleButton::XFE_EditorToolbarToggleButton(Widget parent,
  346.                                                              ToolbarSpec* spec,
  347.                                                              XFE_Component* tb)
  348.     : XFE_EditorToolbarItem(tb, spec)
  349. {
  350.     Arg args[16];
  351.     Cardinal n = 0;
  352.  
  353.      XtSetArg(args[n], XmNbuttonType, XmBUTTON_TOGGLE); n++;
  354.      XtSetArg(args[n], XmNlabelString, NULL); n++;
  355.     m_widget = XfeCreateButton(parent,
  356.                                (char*)spec->toolbarButtonName,
  357.                                args,
  358.                                n);
  359.  
  360.     fe_setLabelTypeFromSpec(m_widget, spec);
  361.  
  362.     XtAddCallback(m_widget, XmNarmCallback, pb_arm_cb, this);
  363.     XtAddCallback(m_widget, XmNactivateCallback, tb_valuechanged_cb, this);
  364.     XtAddCallback(m_widget, XmNdisarmCallback, pb_disarm_cb, this);
  365.  
  366.     installDestroyHandler();
  367.  
  368.     fe_WidgetAddToolTips(m_widget);
  369.  
  370.     SAVE_ME(m_widget);
  371. }
  372.  
  373. XFE_EditorToolbarSpacer::XFE_EditorToolbarSpacer(Widget parent, 
  374.                                                  XFE_Component* tb) :
  375.     XFE_EditorToolbarItem(tb, NULL)
  376. {
  377.     m_widget = XmCreateLabelGadget(parent,
  378.                                    (char*)"spacer",
  379.                                    NULL, 0);
  380.     XmString xms = XmStringCreateLtoR ("", XmSTRING_DEFAULT_CHARSET);
  381.     XtVaSetValues(m_widget,
  382.                   XmNlabelType, XmSTRING,
  383.                   XmNlabelString, xms,
  384.                   NULL);
  385.     XmStringFree(xms);
  386.  
  387.     SAVE_ME(m_widget);
  388.  
  389.     installDestroyHandler();
  390. }
  391.  
  392. class XFE_ComboList : public XFE_EditorToolbarItem
  393. {
  394. public:
  395.     XFE_ComboList(Widget parent,
  396.                   ToolbarSpec* spec,
  397.                   XFE_Component* tb);
  398.     virtual void update() = 0;
  399.     virtual void itemSelected(unsigned index) = 0;
  400.     void    selectItem(int index);
  401.     void    addItems(XFE_CommandParameters* list);
  402. protected:
  403.     Widget m_combo;
  404. };
  405.  
  406. static void
  407. cl_selection_cb(Widget /*widget*/, XtPointer client_data, XtPointer cb_data)
  408. {
  409.     DtComboBoxCallbackStruct* info = (DtComboBoxCallbackStruct*)cb_data;
  410.     XFE_ComboList*            list = (XFE_ComboList*)client_data;
  411.     
  412.     list->itemSelected(info->item_position);
  413. }
  414.  
  415. XFE_ComboList::XFE_ComboList(Widget parent, ToolbarSpec* spec,
  416.                              XFE_Component* tb)
  417.     : XFE_EditorToolbarItem(tb, spec)
  418. {
  419.     Arg args[16];
  420.     Cardinal n;
  421.     char buf[256];
  422.  
  423.     sprintf(buf, "%sFrame", (char*)spec->toolbarButtonName);
  424.  
  425.     n = 0;
  426.     XtSetArg(args[n], XmNshadowType, XmSHADOW_IN); n++;
  427.     XtSetArg(args[n], XmNshadowThickness, 1); n++;
  428.     XtSetArg(args[n], XmNmarginWidth, 0); n++;
  429.     XtSetArg(args[n], XmNmarginHeight, 0); n++;
  430.     m_widget = XmCreateFrame(parent, buf, args, n);
  431.  
  432.     Visual*  v = 0;
  433.     Colormap cmap = 0;
  434.     Cardinal depth = 0;
  435.     XtVaGetValues(XfeAncestorFindTopLevelShell(parent),
  436.                   XtNvisual, &v,
  437.                   XtNcolormap, &cmap,
  438.                   XtNdepth, &depth,
  439.                   0);
  440.  
  441.     n = 0;
  442.     XtSetArg(args[n], XmNvisual, v); n++;
  443.     XtSetArg(args[n], XmNdepth, depth); n++;
  444.     XtSetArg(args[n], XmNcolormap, cmap); n++;
  445.     XtSetArg(args[n], XmNtype, XmDROP_DOWN_LIST_BOX); n++;
  446.     XtSetArg(args[n], XmNshadowThickness, 1); n++;
  447.     XtSetArg(args[n], XmNmarginWidth, 0); n++;
  448.     XtSetArg(args[n], XmNmarginHeight, 0); n++;
  449.     XtSetArg(args[n], XmNarrowType, XmMOTIF); n++;
  450.     m_combo = DtCreateComboBox(m_widget,
  451.                                 (char*)spec->toolbarButtonName,
  452.                                 args, n);
  453.     XtManageChild(m_combo);
  454.  
  455.     XtAddCallback(m_combo, XmNselectionCallback, cl_selection_cb, this);
  456.  
  457.     Widget arrow = XtNameToWidget(m_combo, "ComboBoxArrow");
  458.     Widget label = XtNameToWidget(m_combo, "Label");
  459.     if (arrow != NULL)
  460.         fe_WidgetAddToolTips(arrow);
  461.     if (label != NULL)
  462.         fe_WidgetAddToolTips(label);
  463.  
  464.     SAVE_ME(m_widget);
  465.  
  466.     installDestroyHandler();
  467. }
  468.  
  469. void
  470. XFE_ComboList::addItems(XFE_CommandParameters* list)
  471. {
  472.     unsigned i;
  473.     char* string;
  474.     XmString xm_string;
  475.  
  476.     if (!list)
  477.         return;
  478.  
  479.     for (i = 0; list[i].name != NULL; i++) {
  480.  
  481.         string = XfeSubResourceGetStringValue(m_combo,
  482.                                               list[i].name, 
  483.                                               "SetParagraphStyle",
  484.                                               XmNlabelString, 
  485.                                               XmCXmString,
  486.                                               NULL);
  487.  
  488.         if (!string)
  489.             string = list[i].name;
  490.         xm_string = XmStringCreateLocalized(string);
  491.         DtComboBoxAddItem(m_combo, xm_string, i + 1, FALSE);
  492.         XmStringFree(xm_string);
  493.     }
  494.     XtVaSetValues(m_combo, XmNvisibleItemCount, (XtPointer)i, 0);
  495. }
  496.  
  497. void
  498. XFE_ComboList::selectItem(int index)
  499. {
  500.    if (index < 0) {
  501.        XmString blank = XmStringCreateLocalized("");
  502.        XtVaSetValues(m_combo,
  503.                      XmNupdateLabel, False,
  504.                      XmNlabelString, blank,
  505.                      0);
  506.        XmStringFree(blank);
  507.    } else {
  508.        XtVaSetValues(m_combo,
  509.                      XmNupdateLabel, True,
  510.                      XmNselectedPosition, index,
  511.                      0);
  512.    }
  513. }
  514.  
  515. class XFE_SmartComboList : public XFE_ComboList
  516. {
  517. public:
  518.     XFE_SmartComboList(Widget parent,
  519.                   ToolbarSpec* spec,
  520.                   XFE_Component* tb);
  521.     void itemSelected(unsigned index);
  522.     void update();
  523.     
  524. protected:
  525.     XFE_CommandParameters* m_params;
  526. };
  527.  
  528. XFE_SmartComboList::XFE_SmartComboList(Widget parent, ToolbarSpec* spec,
  529.                              XFE_Component* tb)
  530.     : XFE_ComboList(parent, spec, tb)
  531. {
  532.     //
  533.     //    ask the command for list of parameters.
  534.     //
  535.     m_params = NULL;
  536. }
  537.  
  538. void
  539. XFE_SmartComboList::itemSelected(unsigned index)
  540. {
  541.     String params[2];
  542.     unsigned i;
  543.  
  544.     if (m_params == NULL)
  545.         return;
  546.  
  547.     for (i = 0; i < index; i++) {
  548.         if (m_params[i].name == NULL)
  549.             return;
  550.     }
  551.     
  552.     params[0] = m_params[index].name;
  553.     params[1] = NULL;
  554.  
  555.     XFE_CommandInfo e_info(XFE_COMMAND_BUTTON_ACTIVATE,
  556.                            m_widget,
  557.                            NULL,
  558.                            params, 1);
  559.     doCommand(&e_info);
  560. }
  561.  
  562. void
  563. XFE_SmartComboList::update()
  564. {
  565.     XFE_Frame* frame = getParentFrame();
  566.     int        index = -1;
  567.  
  568.     if (!m_cmd_handler)
  569.         m_cmd_handler = getParentFrame()->getCommand(m_cmd_id);
  570.  
  571.     if (m_cmd_handler != NULL) {
  572.         if (!m_params) {
  573.             m_params = m_cmd_handler->getParameters(frame);
  574.             addItems(m_params);
  575.         }
  576.  
  577.         index = m_cmd_handler->getParameterIndex(frame);
  578.     }
  579.  
  580.     selectItem(index);
  581. }
  582.  
  583. class XFE_RamiroCascadeMenu : public XFE_EditorToolbarItem
  584. {
  585. public:
  586.     XFE_RamiroCascadeMenu(Widget         parent,
  587.                           ToolbarSpec*   spec,
  588.                           XFE_Component* tb);
  589.     virtual XP_Bool showsUpdate() { return False; };
  590. protected:
  591.     Widget       getMenuWidget();
  592.     Widget       addChildPushButton(ToolbarSpec* spec);
  593. };
  594.  
  595. XFE_RamiroCascadeMenu::XFE_RamiroCascadeMenu(Widget         parent,
  596.                                              ToolbarSpec*   spec,
  597.                                              XFE_Component* tb)
  598.     : XFE_EditorToolbarItem(tb, spec)
  599. {
  600.     Arg args[16];
  601.     Cardinal n;
  602.  
  603.     n = 0;
  604.     XtSetArg(args[n], XmNshowArrows, True); n++;
  605.     XtSetArg(args[n], XmNcascadeArrowWidth, 9); n++;
  606.     XtSetArg(args[n], XmNcascadeArrowHeight, 9); n++;
  607.     XtSetArg(args[n], XmNcascadeArrowLocation, XmLOCATION_SOUTH_WEST); n++;
  608.     XtSetArg(args[n], XmNdrawCascadeArrow, True); n++;
  609.  
  610.     m_widget = XtCreateWidget((char*)spec->toolbarButtonName,
  611.                               xfeCascadeWidgetClass,
  612.                               parent,
  613.                               args,
  614.                               n);
  615.     fe_setLabelTypeFromSpec(m_widget, spec);
  616.  
  617.     installDestroyHandler();
  618.  
  619.     fe_WidgetAddToolTips(m_widget);
  620.  
  621.     SAVE_ME(m_widget);
  622. }
  623.  
  624. Widget
  625. XFE_RamiroCascadeMenu::getMenuWidget()
  626. {
  627.     Widget sub_menu;
  628.     XtVaGetValues(m_widget, XmNsubMenuId, &sub_menu, 0);
  629.     return sub_menu;
  630. }
  631.  
  632. Widget
  633. XFE_RamiroCascadeMenu::addChildPushButton(ToolbarSpec* spec)
  634. {
  635.     Widget sub_menu = getMenuWidget();
  636.     Arg args[16];
  637.     Cardinal n = 0;
  638.  
  639.     Widget baby = XmCreatePushButton(sub_menu,
  640.                                      (char*)spec->toolbarButtonName,
  641.                                      args,
  642.                                      n);
  643.     fe_setLabelTypeFromSpec(baby, spec);
  644.  
  645.     XtManageChild(baby);
  646.  
  647.     return baby;
  648. }
  649.  
  650. class XFE_AlignmentMenu : public XFE_RamiroCascadeMenu
  651. {
  652. public:
  653.     XFE_AlignmentMenu(Widget         parent,
  654.                       ToolbarSpec*   spec,
  655.                       XFE_Component* tb);
  656.     void doIndex(unsigned index);
  657.     void updateDisplayed(int index);
  658.     void update();
  659.     XP_Bool showsUpdate() { return TRUE; };
  660. };
  661.  
  662. void
  663. XFE_AlignmentMenu::update()
  664. {
  665.     XFE_Frame* frame = getParentFrame();
  666.     int        index = -1;
  667.  
  668.     if (!m_cmd_handler)
  669.         m_cmd_handler = getParentFrame()->getCommand(m_cmd_id);
  670.  
  671.     if (m_cmd_handler != NULL)
  672.         index = m_cmd_handler->getParameterIndex(frame);
  673.  
  674.     updateDisplayed(index);
  675. }
  676.  
  677. void
  678. XFE_AlignmentMenu::doIndex(unsigned index)
  679. {
  680.     XFE_Frame* frame = getParentFrame();
  681.     
  682.     m_cmd_handler->setParameterIndex(frame, index);
  683. }
  684.  
  685. void
  686. XFE_AlignmentMenu::updateDisplayed(int index)
  687. {
  688.     ToolbarSpec* c_specs;
  689.  
  690.     if (index < 0) { // in-determinate
  691.         c_specs = m_spec;
  692.     } else {
  693.         c_specs = (ToolbarSpec*)m_spec->submenu;
  694.     }
  695.  
  696.     fe_buttonSetPixmaps(m_widget,c_specs[index].iconGroup);
  697.     
  698. }
  699.  
  700. static void
  701. am_activate_cb(Widget widget, XtPointer closure, XtPointer /*cb_data*/)
  702. {
  703.     XFE_AlignmentMenu* menu = (XFE_AlignmentMenu*)closure;
  704.     Widget             menu_widget = XtParent(widget);
  705.     Widget*            children;
  706.     Cardinal           nchildren;
  707.     
  708.     XtVaGetValues(menu_widget,
  709.                   XmNchildren, &children,
  710.                   XmNnumChildren, &nchildren,
  711.                   0);
  712.     
  713.     unsigned n;
  714.     for (n = 0; n < nchildren; n++) {
  715.         if (children[n] == widget) {
  716.             menu->doIndex(n);
  717.             //
  718.             //    I'm in two minds as to whether this should update
  719.             //    or let the update() method take care of it. I'm
  720.             //    doing it here, or there is consistancy betwen Motif
  721.             //    option menus, drop boxes, and hand made selecting menus.
  722.             //
  723.             menu->updateDisplayed(n);
  724.         }
  725.     }
  726. }
  727.  
  728. XFE_AlignmentMenu::    XFE_AlignmentMenu(Widget         parent,
  729.                                       ToolbarSpec*   spec,
  730.                                       XFE_Component* tb)
  731.     : XFE_RamiroCascadeMenu(parent, spec, tb)
  732. {
  733.     ToolbarSpec* children_spec = (ToolbarSpec*)m_spec->submenu;
  734.  
  735.     for (; children_spec->toolbarButtonName != NULL; children_spec++) {
  736.         Widget baby = addChildPushButton(children_spec);
  737.         XtAddCallback(baby, XmNactivateCallback, am_activate_cb, this);
  738.     }
  739.  
  740.     updateDisplayed(-1);
  741. }
  742.  
  743. class XFE_PixmapMenu : public XFE_RamiroCascadeMenu
  744. {
  745. public:
  746.     XFE_PixmapMenu(Widget         parent,
  747.                    ToolbarSpec*   spec,
  748.                    XFE_Component* tb);
  749. };
  750.  
  751. XFE_PixmapMenu::XFE_PixmapMenu(Widget         parent,
  752.                                ToolbarSpec*   spec,
  753.                                XFE_Component* tb)
  754.     : XFE_RamiroCascadeMenu(parent, spec, tb)
  755. {
  756.     ToolbarSpec* child_spec = (ToolbarSpec*)m_spec->submenu;
  757.     Widget       menu = getMenuWidget();
  758.  
  759.     for (; child_spec->toolbarButtonName != NULL; child_spec++) {
  760.         XFE_XmPushButton* baby = new XFE_XmPushButton(menu, child_spec, this);
  761.         baby->show();
  762.     }
  763. }
  764.  
  765. class XFE_ColorMenu : public XFE_EditorToolbarItem
  766. {
  767. public:
  768.     XFE_ColorMenu(Widget         parent,
  769.                      ToolbarSpec*   spec,
  770.                      XFE_Component* tb);
  771.     void setValue(LO_Color* color);
  772.     void update();
  773. protected:
  774.     void instanciateMenu();
  775.     Widget m_arrow;
  776.     Widget m_label;
  777.     Widget m_popup;
  778.     Widget m_rowcol;
  779. };
  780.  
  781. void
  782. XFE_ColorMenu::setValue(LO_Color* color)
  783. {
  784.     XFE_Frame* frame = getParentFrame();
  785.     LO_Color   default_color;
  786.     String params[2];
  787.     char buf[32];
  788.  
  789.     if (m_cmd_handler == NULL)
  790.         return;
  791.  
  792.     if (color == NULL) {
  793.         MWContext* context = frame->getContext();
  794.  
  795.         //    Get the default color.
  796.         fe_EditorDocumentGetColors(context,
  797.                                    NULL, /* bg image */
  798.                                    NULL, /* leave image */
  799.                                    NULL, /* bg color */
  800.                                    &default_color,/* normal color */
  801.                                    NULL, /* link color */
  802.                                    NULL, /* active color */
  803.                                    NULL); /* followed color */
  804.  
  805.         color = &default_color;
  806.     }
  807.  
  808.     sprintf(buf, "#%02x%02x%02x", color->red, color->green, color->blue);
  809.  
  810.     params[0] = buf;
  811.     params[1] = NULL;
  812.  
  813.     XFE_CommandInfo e_info(XFE_COMMAND_BUTTON_ACTIVATE,
  814.                            m_widget,
  815.                            NULL,
  816.                            params, 1);
  817.     doCommand(&e_info);
  818. }
  819.  
  820. static void
  821. cm_popupdown_cb(Widget /*widget*/, XtPointer closure, XtPointer /*cb_data*/)
  822. {
  823.     Widget frame = (Widget)closure;
  824.     Widget shell = XtParent(frame);
  825.  
  826.     XtPopdown(shell);
  827.     XtUngrabPointer(shell, CurrentTime);
  828.     XtUngrabKeyboard(shell, CurrentTime);
  829.     XtRemoveGrab(shell);
  830. }
  831.  
  832. static XtPointer
  833. fe_find_widget_mappee(Widget widget, XtPointer data)
  834. {
  835.     Window window = (Window)data;
  836.  
  837.     if (XtWindow(widget) == window)
  838.         return widget;
  839.     else
  840.         return 0;
  841. }
  842.  
  843. static void
  844. cm_shell_eh(Widget widget, XtPointer closure, XEvent* event, Boolean* dispatch)
  845. {
  846.     Widget frame = (Widget)closure;
  847.     Widget shell = XtParent(frame);
  848.     Window window = event->xbutton.window;
  849.  
  850.     if ((((ShellWidget)(shell))->shell.popped_up)
  851.         &&
  852.         !fe_WidgetTreeWalk(frame, fe_find_widget_mappee, (XtPointer)window)) {
  853.  
  854.         cm_popupdown_cb(widget, frame, NULL);
  855.         *dispatch = False;
  856.     }
  857. }
  858.  
  859. static void
  860. cm_activate_cb(Widget widget, XtPointer closure, XtPointer cb_data)
  861. {
  862.     XmArrowButtonCallbackStruct* cb = (XmArrowButtonCallbackStruct*)cb_data;
  863.  
  864.     if ((cb->event->type != ButtonPress && cb->event->type != ButtonRelease)
  865.         ||
  866.         cb->event->xbutton.button != Button1)
  867.         return;
  868.  
  869.     Widget    location_widget = XtParent(XtParent(widget));
  870.     Widget    frame = (Widget)closure;
  871.     Widget    shell = XtParent(frame);
  872.     Display*  display = XtDisplayOfObject(widget);
  873.     Screen*   screen = XtScreen(widget);
  874.     Dimension border_width;
  875.     Dimension width;
  876.     Dimension height;
  877.     Position  x;
  878.     Position  y;
  879.     Position  root_x;
  880.     Position  root_y;
  881.     char      buf[128];
  882.  
  883.     XtVaGetValues(location_widget,
  884.                   XmNx, &x,
  885.                   XmNy, &y,
  886.                   XmNwidth, &width,
  887.                   XmNheight, &height,
  888.                   0);
  889.     XtTranslateCoords(XtParent(location_widget), x, y, &root_x, &root_y);
  890.     root_y += height;
  891.  
  892.     /*
  893.      *    Make sure it fits on screen.
  894.      */
  895.     if (!XtIsRealized(shell))
  896.         XtRealizeWidget(shell);
  897.     XtVaGetValues(shell, XmNborderWidth, &border_width, 0);
  898.     XtVaGetValues(frame, XmNwidth, &width, XmNheight, &height, 0);
  899.  
  900.     height += (2*border_width);
  901.     width += (2*border_width);
  902.  
  903.     if (root_x + width > WidthOfScreen(screen))
  904.         root_x = WidthOfScreen(screen) - width;
  905.     else if (root_x < 0)
  906.         root_x = 0;
  907.  
  908.     if (root_y + height > HeightOfScreen(screen))
  909.         /*
  910.          *    Position at bottom of screen. Maybe it would be better to
  911.          *    position above arrow row.
  912.          */
  913.         root_y = HeightOfScreen(screen) - height;
  914.     else if (root_y < 0)
  915.         root_y = 0;
  916.  
  917.     /*
  918.      *    Make sure the user cannot shoot themselves with a random
  919.      *    geometry spec.
  920.      */
  921.     sprintf(buf, "%dx%d", width, height);
  922.     XtVaSetValues(shell,
  923.                   XmNx, root_x, XmNy, root_y,
  924.                   XmNwidth, width, XmNheight, height,
  925.                   XmNgeometry, buf, 0);
  926.  
  927.     XtPopup(shell, XtGrabNone);
  928.  
  929.     XtGrabPointer(shell, True, ButtonPressMask,
  930.                   GrabModeAsync, GrabModeAsync, None, 
  931.                   XmGetMenuCursor(display), CurrentTime);
  932.     XtGrabKeyboard(shell, False, GrabModeAsync, GrabModeAsync, 
  933.                    CurrentTime);
  934.     XtAddGrab(shell, True, True);
  935. }
  936.  
  937. static void
  938. cm_matrix_cb(Widget widget, XtPointer closure, XtPointer cbd)
  939. {
  940.     XFE_ColorMenu* color_menu = (XFE_ColorMenu*)closure;
  941.     XmDrawnButtonCallbackStruct* cbs = (XmDrawnButtonCallbackStruct*)cbd;
  942.     int    colorn;
  943.     XColor color;
  944.     XButtonEvent* event = (XButtonEvent*)cbs->event;
  945.  
  946.     colorn = fe_SwatchMatrixGetColor(widget, event->x, event->y, &color);
  947.  
  948.     if (colorn == -1)
  949.         return;
  950.  
  951.     LO_Color lo_color;
  952.     lo_color.red = color.red;
  953.     lo_color.green = color.green;
  954.     lo_color.blue =    color.blue;
  955.  
  956.     color_menu->setValue(&lo_color);
  957. }
  958.  
  959. static void
  960. cm_default_cb(Widget /*widget*/, XtPointer closure, XtPointer /*cbd*/)
  961. {
  962.     XFE_ColorMenu* color_menu = (XFE_ColorMenu*)closure;
  963.  
  964.     color_menu->setValue(NULL);
  965. }
  966.  
  967. static void
  968. cm_picker_cb(Widget /*widget*/, XtPointer closure, XtPointer /*cbd*/)
  969. {
  970.     XFE_ColorMenu* color_menu = (XFE_ColorMenu*)closure;
  971.     XFE_Frame*     frame = color_menu->getParentFrame();
  972.  
  973.     if (frame->handlesCommand(xfeCmdSetCharacterColor)
  974.         && frame->isCommandEnabled(xfeCmdSetCharacterColor)) {
  975.         frame->doCommand(xfeCmdSetCharacterColor);
  976.     }
  977. }
  978.  
  979. void
  980. XFE_ColorMenu::instanciateMenu()
  981. {
  982.     Widget     parent = XtParent(m_widget);
  983.     XFE_Frame* frame = getParentFrame();
  984.  
  985.     //
  986.     //    Do we have a command handler?
  987.     //
  988.     m_cmd_handler = frame->getCommand(m_cmd_id);
  989.  
  990.     if (!m_cmd_handler)
  991.         return;
  992.  
  993.     Cardinal n = 0;
  994.     Arg      args[16];
  995.     XtSetArg(args[n], XmNcolormap, XfeColormap(parent));    n++;
  996.     XtSetArg(args[n], XmNdepth, XfeDepth(parent)); n++;
  997.     XtSetArg(args[n], XmNvisual,    XfeVisual(parent));    n++;
  998.     XtSetArg(args[n], XtNoverrideRedirect, TRUE); n++;
  999.     XtSetArg(args[n], XtNallowShellResize, TRUE); n++;
  1000.     XtSetArg(args[n], XtNsaveUnder, TRUE); n++;
  1001.     XtSetArg(args[n], XtNtransientFor, frame->getBaseWidget()); n++;
  1002.  
  1003.     Widget shell = XtCreatePopupShell("setColorsPopup", 
  1004.                                       transientShellWidgetClass,
  1005.                                       parent,
  1006.                                       args, n);
  1007.  
  1008.     n = 0;
  1009.     XtSetArg(args[n], XmNshadowType, XmSHADOW_ETCHED_OUT); n++;
  1010.     XtSetArg(args[n], XmNshadowThickness, 2); n++;
  1011.     XtSetArg(args[n], XmNmarginWidth, 0); n++;
  1012.     XtSetArg(args[n], XmNmarginHeight, 0); n++;
  1013.     Widget f_widget = XmCreateFrame(shell, "frame", args, n);
  1014.     XtManageChild(f_widget);
  1015.     
  1016.     n = 0;
  1017.     XtSetArg(args[n], XmNmarginHeight, 0); n++;
  1018.     XtSetArg(args[n], XmNmarginWidth, 0); n++;
  1019.     XtSetArg(args[n], XmNrowColumnType, XmWORK_AREA); n++;
  1020.     XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
  1021.     XtSetArg(args[n], XmNpacking, XmPACK_TIGHT); n++;
  1022.     XtSetArg(args[n], XmNspacing, 0); n++;
  1023.     m_rowcol = XmCreateRowColumn(f_widget, "colorPicker", args, n);
  1024.     XtManageChild(m_rowcol);
  1025.  
  1026.     m_popup = f_widget;
  1027.  
  1028.     XtInsertEventHandler(shell, ButtonPressMask, True,
  1029.                          (XtEventHandler)cm_shell_eh, 
  1030.                          (XtPointer)m_popup, XtListHead);
  1031.  
  1032.     n = 0;
  1033.     Widget matrix = fe_CreateSwatchMatrix(m_rowcol, "colorMatrix", args, n);
  1034.  
  1035.     fe_AddSwatchMatrixCallback(matrix,
  1036.                                XmNactivateCallback, cm_matrix_cb, this);
  1037.     fe_AddSwatchMatrixCallback(matrix,
  1038.                                XmNactivateCallback, cm_popupdown_cb, m_popup);
  1039.  
  1040.     XtManageChild(matrix);
  1041.  
  1042.     n = 0;
  1043.     Widget default_b = XmCreatePushButtonGadget(m_rowcol, "defaultColor",
  1044.                                                 args, n);
  1045.     XtManageChild(default_b);
  1046.     XtAddCallback(default_b,
  1047.                   XmNactivateCallback, cm_popupdown_cb, m_popup);
  1048.     XtAddCallback(default_b,
  1049.                   XmNactivateCallback, cm_default_cb, this);
  1050.  
  1051.     n = 0;
  1052.     Widget picker_b = XmCreatePushButtonGadget(m_rowcol, "otherColor",
  1053.                                                args, n);
  1054.     XtManageChild(picker_b);
  1055.     XtAddCallback(picker_b,
  1056.                   XmNactivateCallback, cm_popupdown_cb, m_popup);
  1057.     XtAddCallback(picker_b,
  1058.                   XmNactivateCallback, cm_picker_cb, this);
  1059.  
  1060.     XtAddCallback(m_arrow, XmNactivateCallback, cm_activate_cb, m_popup);
  1061.     XtAddCallback(m_label, XmNactivateCallback, cm_activate_cb, m_popup);
  1062.     //FIXME: add tooltips.
  1063. }
  1064.  
  1065. XFE_ColorMenu::XFE_ColorMenu(Widget         parent,
  1066.                               ToolbarSpec*   spec,
  1067.                               XFE_Component* tb)
  1068.     : XFE_EditorToolbarItem(tb, spec)
  1069. {
  1070.     Arg args[16];
  1071.     Cardinal n = 0;
  1072.     Widget rowcol;
  1073.     Widget frame_widget;
  1074.  
  1075.     n = 0;
  1076.     XtSetArg(args[n], XmNshadowType, XmSHADOW_ETCHED_IN); n++;
  1077.     XtSetArg(args[n], XmNshadowThickness, 2); n++;
  1078.     XtSetArg(args[n], XmNmarginWidth, 0); n++;
  1079.     XtSetArg(args[n], XmNmarginHeight, 0); n++;
  1080.     frame_widget = XmCreateFrame(parent, "frame", args, n);
  1081.  
  1082.     n = 0;
  1083.     XtSetArg(args[n], XmNmarginHeight, 0); n++;
  1084.     XtSetArg(args[n], XmNmarginWidth, 0); n++;
  1085.     XtSetArg(args[n], XmNrowColumnType, XmWORK_AREA); n++;
  1086.     XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
  1087.     XtSetArg(args[n], XmNpacking, XmPACK_TIGHT); n++;
  1088.     XtSetArg(args[n], XmNspacing, 0); n++;
  1089.     rowcol = XmCreateRowColumn(frame_widget,
  1090.                                (char*)spec->toolbarButtonName,
  1091.                                args,
  1092.                                n);
  1093.     XtManageChild(rowcol);
  1094.  
  1095.     XmString xm_string = XmStringCreateLocalized("");
  1096.     n = 0;
  1097.     XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
  1098.     XtSetArg(args[n], XmNrecomputeSize, FALSE); n++;
  1099.     XtSetArg(args[n], XmNshadowThickness, 1); n++;
  1100.     XtSetArg(args[n], XmNlabelString, xm_string); n++;
  1101.     XtSetArg(args[n], XmNmarginLeft, LABEL_PADDING); n++;
  1102.     XtSetArg(args[n], XmNmarginRight, LABEL_PADDING); n++;
  1103.     XtSetArg(args[n], XmNmarginWidth, 0); n++;
  1104.     XtSetArg(args[n], XmNmarginHeight, 0); n++;
  1105.     XtSetArg(args[n], XmNfillOnArm, False); n++;
  1106.  
  1107.     m_label = XmCreatePushButton(rowcol, "label", args, n);
  1108.     XtManageChild(m_label);
  1109.     XmStringFree(xm_string);
  1110.  
  1111.     n = 0;
  1112.     XtSetArg(args[n], XmNheight, 14); n++;
  1113.     XtSetArg(args[n], XmNtraversalOn, FALSE); n++;
  1114.     XtSetArg(args[n], XmNhighlightThickness, 0); n++;
  1115.     XtSetArg(args[n], XmNshadowThickness, 1); n++;
  1116.     XtSetArg(args[n], XmNarrowDirection, XmARROW_DOWN); n++;
  1117.     XtSetArg(args[n], XmNforeground, XfeBackground(parent)); n++;
  1118.     XtSetArg(args[n], XmNmarginHeight, 0); n++;
  1119.     XtSetArg(args[n], XmNmarginHeight, 0); n++;
  1120.     m_arrow = XmCreateArrowButton(rowcol, "arrow", args, n);
  1121.     XtManageChild(m_arrow);
  1122.  
  1123.     fe_WidgetAddToolTips(m_arrow);
  1124.     fe_WidgetAddToolTips(m_label);
  1125.  
  1126.     /*
  1127.      *   Make the label symetrical with the arrow.
  1128.      */
  1129.     Dimension width;
  1130.     Dimension height;
  1131.     XtVaGetValues(m_arrow, XmNwidth, &width, XmNheight, &height, 0);
  1132.     XtVaSetValues(m_label, XmNwidth, width, XmNheight, height, 0);
  1133.  
  1134.     m_widget = frame_widget;
  1135.     SAVE_ME(m_widget);
  1136.  
  1137.     installDestroyHandler();
  1138.  
  1139.     //    Don't instanciate menu until later - it requires us
  1140.     //    binding to cmd_handler which would suck.
  1141.     m_rowcol = rowcol;
  1142.     m_popup = NULL;
  1143. }
  1144.  
  1145. void
  1146. XFE_ColorMenu::update()
  1147. {
  1148.     XFE_Frame* frame = getParentFrame();
  1149.     MWContext* context = frame->getContext();
  1150.     LO_Color   color;
  1151.  
  1152.     if (!m_cmd_handler)
  1153.         m_cmd_handler = getParentFrame()->getCommand(m_cmd_id);
  1154.  
  1155.     if (!m_popup)
  1156.         instanciateMenu();
  1157.  
  1158.     Pixel pixel;
  1159.  
  1160.     if (m_cmd_handler->isDeterminate(frame, 0)) { /* is it defined */
  1161.         fe_EditorColorGet(context, &color);
  1162.         pixel = fe_GetPixel(context, color.red, color.green, color.blue);
  1163.     } else {
  1164.         XtVaGetValues(m_rowcol, XmNbackground, &pixel, NULL);
  1165.     }
  1166.  
  1167.     XtVaSetValues(m_label, XmNbackground, pixel, NULL);
  1168. }
  1169.  
  1170. static void
  1171. chrome_update_cb(XFE_NotificationCenter*, XFE_NotificationCenter* obj,
  1172.                  void*, void*)
  1173. {
  1174.     XFE_EditorToolbar* tb = (XFE_EditorToolbar*)obj;
  1175.     tb->update();
  1176. }
  1177.  
  1178. static void
  1179. command_update_cb(XFE_NotificationCenter*, XFE_NotificationCenter* obj,
  1180.                  void*, void* call_data)
  1181. {
  1182.     XFE_EditorToolbar* tb = (XFE_EditorToolbar*)obj;
  1183.     tb->updateCommand((CommandType)call_data);
  1184. }
  1185.  
  1186. static Widget
  1187. make_toolbar(Widget parent, char* name,
  1188.              ToolbarSpec* spec, XFE_EditorToolbar* owner, Boolean do_frame)
  1189. {
  1190.     Arg      args[20];
  1191.     Cardinal n;
  1192.  
  1193.     if (do_frame) {
  1194.         char buf[256];
  1195.  
  1196.         strcpy(buf, name);
  1197.         strcat(buf, "Frame");
  1198.  
  1199.         n = 0;
  1200.         XtSetArg(args[n], XmNshadowType, XmSHADOW_OUT); n++;
  1201.         XtSetArg(args[n], XmNshadowThickness, 1); n++;
  1202.         Widget frame = XmCreateFrame(parent, buf, args, n);
  1203.         parent = frame;
  1204.     }
  1205.  
  1206.     n = 0;
  1207.     XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
  1208.     XtSetArg(args[n], XmNpacking, XmPACK_TIGHT); n++;
  1209.     XtSetArg(args[n], XmNadjustMargin, False); n++;
  1210.     Widget toolbar = XmCreateRowColumn(parent, name, args, n);
  1211.  
  1212.     if (do_frame)
  1213.         XtManageChild(toolbar);
  1214.  
  1215.     install_children_from_toolspec(toolbar, spec, owner);
  1216.  
  1217.     return toolbar;
  1218. }
  1219.  
  1220. XFE_EditorToolbar::XFE_EditorToolbar(XFE_Component* parent_frame,
  1221.                                      XFE_Toolbox *    parent_toolbox,
  1222.                                      char*        name,
  1223.                                      ToolbarSpec* spec,
  1224.                                      Boolean      do_frame) :
  1225.     XFE_ToolboxItem(parent_frame,parent_toolbox)
  1226. {
  1227.     m_toplevel = parent_frame;
  1228.     m_update_list = NULL;
  1229.  
  1230.     m_rowcol = make_toolbar(parent_toolbox->getBaseWidget(),
  1231.                             name, spec, this, do_frame);
  1232.  
  1233.     if (do_frame)
  1234.         m_widget = XtParent(m_rowcol);
  1235.     else
  1236.         m_widget = m_rowcol;
  1237.  
  1238.     // This is needed so that the toolbox frame can have access this
  1239.     // object without having to maintain a list.
  1240.     XtVaSetValues(m_widget,XmNuserData,this,NULL);
  1241.  
  1242.     // Add drag widgets for the editor toolbar
  1243.     addDragWidget(getBaseWidget());
  1244.     addDragWidget(getChildrenManager());
  1245.  
  1246.     parent_frame->registerInterest(XFE_View::chromeNeedsUpdating,
  1247.                                    this,
  1248.                                    chrome_update_cb);
  1249.  
  1250.     parent_frame->registerInterest(XFE_View::commandNeedsUpdating,
  1251.                                    this,
  1252.                                    command_update_cb);
  1253.     installDestroyHandler();
  1254. }
  1255.  
  1256. XFE_EditorToolbar::~XFE_EditorToolbar()
  1257. {
  1258.     m_toplevel->unregisterInterest(XFE_View::chromeNeedsUpdating,
  1259.                                    this,
  1260.                                    chrome_update_cb);
  1261.  
  1262.     m_toplevel->unregisterInterest(XFE_View::commandNeedsUpdating,
  1263.                                    this,
  1264.                                    command_update_cb);
  1265. }
  1266.  
  1267. Widget
  1268. XFE_EditorToolbar::findButton(const char* /*name*/,
  1269.                               EChromeTag /*tag*/)
  1270. {
  1271.     return NULL;
  1272. }
  1273.  
  1274. static void
  1275. update_children(Widget parent, CommandType cmd)
  1276. {
  1277.     Widget* children;
  1278.     int     nchildren;
  1279.     int     i;
  1280.   
  1281.     XtVaGetValues(parent,
  1282.                   XmNchildren, &children,
  1283.                   XmNnumChildren, &nchildren,
  1284.                   NULL);
  1285.  
  1286.     for (i = 0; i < nchildren; i++) {
  1287.         XFE_MenuItem* menu_item = (XFE_MenuItem*)XfeUserData(children[i]);
  1288.         
  1289.         if (!menu_item)
  1290.             continue;
  1291.  
  1292.  
  1293.         if ((cmd == 0 || menu_item->getCmdId() == cmd)
  1294.             &&
  1295.             menu_item->showsUpdate()) {
  1296.  
  1297.             menu_item->update();
  1298.         }
  1299.     }
  1300. }
  1301.  
  1302. void
  1303. XFE_EditorToolbar::updateCommand(CommandType cmd)
  1304. {
  1305.     if (!XtIsManaged(m_widget))
  1306.         return;
  1307.   
  1308.     update_children(m_rowcol, cmd);
  1309. }
  1310.  
  1311. void
  1312. XFE_EditorToolbar::update()
  1313. {
  1314.     updateCommand(0);
  1315. }
  1316.  
  1317. void
  1318. XFE_EditorToolbar::show()
  1319. {
  1320.     update_children(m_rowcol, 0); // skip the updateCommand() managed check.
  1321.     XFE_ToolboxItem::show();
  1322. }
  1323.  
  1324. static void
  1325. install_children_from_toolspec(Widget w_parent,
  1326.                                ToolbarSpec* tb_spec,
  1327.                                XFE_Component* cp_parent)
  1328. {
  1329.     ToolbarSpec* spec;
  1330.     
  1331.     for (spec = tb_spec; spec->toolbarButtonName != NULL; spec++) {
  1332.         
  1333.         XFE_EditorToolbarItem* item;
  1334.         
  1335.         if (spec->tag == PUSHBUTTON) {
  1336.             
  1337.             item = new XFE_XfePushButton(w_parent, spec, cp_parent);
  1338.  
  1339.         } else if (spec->tag == TOGGLEBUTTON) {
  1340.             
  1341.             item = new XFE_EditorToolbarToggleButton(w_parent,spec, cp_parent);
  1342.  
  1343.         } else if (spec->tag == CASCADEBUTTON) {
  1344.             
  1345.             if (spec->toolbarButtonName == xfeCmdSetAlignmentStyle)
  1346.                 item = new XFE_AlignmentMenu(w_parent, spec, cp_parent);
  1347.             else
  1348.                 item = new XFE_PixmapMenu(w_parent, spec, cp_parent);
  1349.  
  1350.         } else if (spec->tag == COMBOBOX) {
  1351.  
  1352.             if (spec->toolbarButtonName == xfeCmdSetFontColor)
  1353.                 item = new XFE_ColorMenu(w_parent, spec, cp_parent);
  1354.             else
  1355.                 item = new XFE_SmartComboList(w_parent, spec, cp_parent);
  1356.  
  1357.         } else if (spec->tag == SEPARATOR) {
  1358.             
  1359.             item = new XFE_EditorToolbarSpacer(w_parent, cp_parent);
  1360.  
  1361.         } else {
  1362.             /*error*/
  1363.             continue;
  1364.         }
  1365.         
  1366.         item->show(); /* manage */
  1367.     }
  1368. }
  1369.  
  1370.  
  1371.