home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Linux / DDD331 / DDD-3_1_.000 / DDD-3_1_ / ddd-3.1.1 / ddd / toolbar.C < prev    next >
C/C++ Source or Header  |  1998-11-11  |  10KB  |  357 lines

  1. // $Id: toolbar.C,v 1.21 1998/11/11 10:29:32 zeller Exp $ -*- C++ -*-
  2. // Create toolbar
  3.  
  4. // Copyright (C) 1998 Technische Universitaet Braunschweig, Germany.
  5. // Written by Andreas Zeller <zeller@ips.cs.tu-bs.de>.
  6. // 
  7. // This file is part of DDD.
  8. // 
  9. // DDD is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. // 
  14. // DDD is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. // See the GNU General Public License for more details.
  18. // 
  19. // You should have received a copy of the GNU General Public
  20. // License along with DDD -- see the file COPYING.
  21. // If not, write to the Free Software Foundation, Inc.,
  22. // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. // 
  24. // DDD is the data display debugger.
  25. // For details, see the DDD World-Wide-Web page, 
  26. // `http://www.cs.tu-bs.de/softech/ddd/',
  27. // or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
  28.  
  29. char toolbar_rcsid[] = 
  30.     "$Id: toolbar.C,v 1.21 1998/11/11 10:29:32 zeller Exp $";
  31.  
  32. #ifdef __GNUG__
  33. #pragma implementation
  34. #endif
  35.  
  36. #include "toolbar.h"
  37.  
  38. #include "ddd.h"
  39. #include "logo.h"
  40. #include "misc.h"
  41. #include "verify.h"
  42. #include "HelpCB.h"
  43. #include "Delay.h"
  44. #include "AppData.h"
  45. #include "converters.h"
  46.  
  47. #include <Xm/Xm.h>
  48. #include <Xm/Form.h>
  49. #include <Xm/Label.h>
  50. #include <Xm/PushB.h>
  51. #include <Xm/PanedW.h>
  52.  
  53.  
  54. //-----------------------------------------------------------------------
  55. // Helpers
  56. //-----------------------------------------------------------------------
  57.  
  58. // Return the preferred height of W
  59. static Dimension preferred_height(Widget w)
  60. {
  61.     XtWidgetGeometry size;
  62.     size.request_mode = CWHeight;
  63.     XtQueryGeometry(w, NULL, &size);
  64.     Dimension real_height;
  65.     XtVaGetValues(w, XmNheight, &real_height, NULL);
  66.     return max(size.height, real_height);
  67. }
  68.  
  69. static void set_label_type(MMDesc items[], unsigned char label_type)
  70. {
  71.     for (MMDesc *item = items; item != 0 && item->name != 0; item++)
  72.     {
  73.     Widget w = item->widget;
  74.     if (w != 0 && XmIsLabel(w))
  75.     {
  76.         XtVaSetValues(w, XmNlabelType, label_type, NULL);
  77.  
  78.         if (label_type != XmSTRING)
  79.         continue;
  80.         
  81.         // In OSF/Motif, setting both labelString and labelPixmap
  82.         // causes the button to use the Pixmap extent and to
  83.         // ignore the labelString extent, even if its labelType is
  84.         // XmSTRING.  Hence, we set the size explicitly instead.
  85.         //
  86.         // (This only happens in OSF/Motif; LessTif works fine.)
  87.         unsigned char label_type;
  88.         XmString label_string;
  89.         XmFontList font_list;
  90.         Dimension border_width, shadow_thickness;
  91.         Dimension margin_bottom, margin_top, margin_left, margin_right;
  92.         Dimension margin_height, margin_width;
  93.         XtVaGetValues(w,
  94.               XmNlabelType,       &label_type,
  95.               XmNlabelString,     &label_string,
  96.               XmNfontList,        &font_list,
  97.               XmNborderWidth,     &border_width,
  98.               XmNshadowThickness, &shadow_thickness,
  99.               XmNmarginBottom,    &margin_bottom,
  100.               XmNmarginTop,       &margin_top,
  101.               XmNmarginLeft,      &margin_left,
  102.               XmNmarginRight,     &margin_right,
  103.               XmNmarginHeight,    &margin_height,
  104.               XmNmarginWidth,     &margin_width,
  105.               NULL);
  106.  
  107.         Dimension label_width, label_height;
  108.         XmStringExtent(font_list, label_string, 
  109.                &label_width, &label_height);
  110.  
  111.         Dimension width =
  112.         border_width * 2 + shadow_thickness * 2 + 
  113.         margin_width * 2 + 
  114.         margin_left + label_width + margin_right;
  115.  
  116.         Dimension height =
  117.         border_width * 2 + shadow_thickness * 2 + 
  118.         margin_height * 2 + 
  119.         margin_top + label_height + margin_bottom;
  120.  
  121.         XtVaSetValues(w,
  122.               XmNrecomputeSize, False,
  123.               XmNwidth,  width + 4,
  124.               XmNheight, height + 4,
  125.               NULL);
  126.  
  127.         XmStringFree(label_string);
  128.     }
  129.     }
  130. }
  131.  
  132. static void flatten_buttons(MMDesc items[])
  133. {
  134.     // Replace all `MMPush' by `MMFlatPush'
  135.     for (MMDesc *item = items; item != 0 && item->name != 0; item++)
  136.     {
  137.     if ((item->type & MMTypeMask) == MMPush)
  138.         item->type = (MMFlatPush | (item->type & ~MMTypeMask));
  139.     }
  140. }
  141.  
  142. static Widget align_buttons(MMDesc *items1, MMDesc *items2)
  143. {
  144.     Widget last_button  = 0;
  145.  
  146.     for (int j = 1; j >= 0; j--)
  147.     {
  148.     MMDesc *items = (j == 0 ? items1 : items2);
  149.     if (items == 0)
  150.         continue;
  151.  
  152.     int i = -1;
  153.     while (items[i + 1].widget != 0)
  154.         i++;
  155.     for (; i >= 0; i--)
  156.     {
  157.         Widget w = items[i].widget;
  158.  
  159.         if (!XtIsManaged(w))
  160.         continue;
  161.  
  162.         Arg args[10];
  163.         Cardinal arg = 0;
  164.  
  165.         XtSetArg(args[arg], XmNresizable,        False); arg++;
  166.         XtSetArg(args[arg], XmNtopAttachment,    XmATTACH_FORM); arg++;
  167.         XtSetArg(args[arg], XmNbottomAttachment, XmATTACH_FORM); arg++;
  168.  
  169.         if (last_button == 0)
  170.         {
  171.         XtSetArg(args[arg], XmNrightAttachment, XmATTACH_FORM); arg++;
  172.         }
  173.         else
  174.         {
  175.         XtSetArg(args[arg],
  176.              XmNrightAttachment, XmATTACH_WIDGET); arg++;
  177.         XtSetArg(args[arg],
  178.              XmNrightWidget,     last_button); arg++;
  179.         }
  180.  
  181.         XtSetValues(w, args, arg);
  182.  
  183.         last_button = w;
  184.     }
  185.     }
  186.  
  187.     return last_button;
  188. }
  189.  
  190.  
  191.  
  192. static void ResetLabelEH(Widget w, XtPointer, XEvent *, Boolean *)
  193. {
  194.     XmString label_string;
  195.     XtVaGetValues(w, XmNlabelString, &label_string, NULL);
  196.  
  197.     MString empty("");
  198.  
  199.     XtVaSetValues(w, XmNlabelString, empty.xmstring(), NULL);
  200.     XtVaSetValues(w, XmNlabelString, label_string, NULL);
  201.     XmStringFree(label_string);
  202.  
  203.     XtRemoveEventHandler(w, ExposureMask, False, 
  204.              ResetLabelEH, XtPointer(0));
  205. }
  206.  
  207. static void center_buttons(MMDesc items[], Dimension offset)
  208. {
  209.     for (MMDesc *item = items; item != 0 && item->name != 0; item++)
  210.     {
  211.     Widget w = item->widget;
  212.     if (w == 0)
  213.         continue;
  214.  
  215.     XtVaSetValues(w,
  216.               XmNtopOffset, offset / 2,
  217.               XmNbottomOffset, (offset + 1) / 2,
  218.               NULL);
  219.  
  220.     // In OSF/Motif, setting both labelString and labelPixmap
  221.     // causes the button to ignore the labelString extent, giving
  222.     // a bad alignment of the labelString.  This goes away as soon
  223.     // as the label string is reset.  Hence, reset it upon creation.
  224.     XtAddEventHandler(w, ExposureMask, False, 
  225.               ResetLabelEH, XtPointer(0));
  226.     }
  227. }
  228.  
  229.  
  230. //-----------------------------------------------------------------------
  231. // Toolbar creation
  232. //-----------------------------------------------------------------------
  233.  
  234. // Create a toolbar as child of parent, named `toolbar', having
  235. // the buttons ITEMS.  Return LABEL and ARGFIELD.
  236. Widget create_toolbar(Widget parent, string /* name */,
  237.               MMDesc *items1, MMDesc *items2,
  238.               Widget& label, ArgField*& argfield,
  239.               unsigned char label_type)
  240. {
  241.     assert(label_type == XmPIXMAP || label_type == XmSTRING);
  242.  
  243.     Arg args[10];
  244.     Cardinal arg = 0;
  245.  
  246.     // Create toolbar
  247.     string toolbar_name = "toolbar";
  248.  
  249.     arg = 0;
  250.     XtSetArg(args[arg], XmNmarginWidth,        0); arg++;
  251.     XtSetArg(args[arg], XmNmarginHeight,       0); arg++;
  252.     XtSetArg(args[arg], XmNborderWidth,        0); arg++;
  253.     XtSetArg(args[arg], XmNhighlightThickness, 0); arg++;
  254.     Widget toolbar = verify(XmCreateForm(parent, toolbar_name, args, arg));
  255.  
  256.     // Create `():'
  257.     label = create_arg_label(toolbar);
  258.  
  259.     // Create argument field
  260.     string argfield_name = "arg";
  261.     argfield = new ArgField (toolbar, argfield_name);
  262.     Widget combobox = argfield->top();
  263.  
  264.     registerOwnConverters();
  265.  
  266.     // We install the icons AFTER having created the argument field,
  267.     // because otherwise we might eat up all colors.
  268.     install_icons(toolbar,
  269.           app_data.button_color_key,
  270.           app_data.active_button_color_key);
  271.  
  272.     if (label_type == XmPIXMAP && app_data.flat_toolbar_buttons)
  273.     {
  274.     // Use flat buttons
  275.     flatten_buttons(items1);
  276.     flatten_buttons(items2);
  277.     }
  278.  
  279.     // Create buttons
  280.     MMaddItems(toolbar, items1);
  281.     MMaddCallbacks(items1);
  282.     MMaddHelpCallback(items1, ImmediateHelpCB);
  283.     set_label_type(items1, label_type);
  284.  
  285.     if (items2 != 0)
  286.     {
  287.     MMaddItems(toolbar, items2);
  288.     MMaddCallbacks(items2);
  289.     MMaddHelpCallback(items2, ImmediateHelpCB);
  290.     set_label_type(items2, label_type);
  291.     }
  292.  
  293.     Widget first_button = align_buttons(items1, items2);
  294.  
  295.     // Set form constraints
  296.     XtVaSetValues(label,
  297.           XmNresizable,        False,
  298.           XmNleftAttachment,   XmATTACH_FORM,
  299.           XmNtopAttachment,    XmATTACH_FORM,
  300.           XmNbottomAttachment, XmATTACH_FORM,
  301.           NULL);
  302.  
  303.     XtVaSetValues(combobox,
  304.           XmNresizable,        False,
  305.           XmNleftAttachment,   XmATTACH_WIDGET,
  306.           XmNleftWidget,       label,
  307.           XmNrightAttachment,  XmATTACH_WIDGET,
  308.           XmNrightWidget,      first_button,
  309.           XmNtopAttachment,    XmATTACH_FORM,
  310.           NULL);
  311.  
  312.     XtManageChild(toolbar);
  313.     register_menu_shell(items1);
  314.  
  315.     if (items2 != 0)
  316.     register_menu_shell(items2);
  317.  
  318.     // Check geometry
  319.     Dimension button_height  = preferred_height(items1[0].widget);
  320.     Dimension arg_height     = preferred_height(combobox);
  321.     Dimension toolbar_height = max(button_height, arg_height);
  322.     XtVaSetValues(toolbar, XmNheight, toolbar_height, NULL);
  323.  
  324.     if (XmIsPanedWindow(parent))
  325.     {
  326.     // Make sure the toolbar cannot be resized
  327.     XtVaSetValues(toolbar,
  328.               XmNpaneMaximum, toolbar_height,
  329.               XmNpaneMinimum, toolbar_height,
  330.               NULL);
  331.  
  332.     if (label_type == XmSTRING)
  333.     {
  334.         Dimension offset = max(arg_height - button_height, 0);
  335.  
  336.         // Center all labels.  This must also be done if offset is
  337.         // zero, since OSF/Motif 2.0 has trouble centering the
  338.         // labels.
  339.         center_buttons(items1, offset);
  340.         center_buttons(items2, offset);
  341.     }
  342.  
  343.     if (button_height > arg_height)
  344.     {
  345.         Dimension offset = max(button_height - arg_height, 0);
  346.  
  347.         // Center arg field
  348.         XtVaSetValues(argfield->top(),
  349.               XmNtopOffset, offset / 2,
  350.               XmNbottomOffset, (offset + 1) / 2,
  351.               NULL);
  352.     }
  353.     }
  354.  
  355.     return toolbar;
  356. }
  357.