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 / PannedGE.C < prev    next >
C/C++ Source or Header  |  1998-08-05  |  13KB  |  404 lines

  1. // $Id: PannedGE.C,v 1.16 1998/08/05 09:25:45 zeller Exp $ -*- C++ -*-
  2. // Panned Graph Editor
  3.  
  4. // Copyright (C) 1995 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 PannedGraphEdit_rcsid[] = 
  30.     "$Id: PannedGE.C,v 1.16 1998/08/05 09:25:45 zeller Exp $";
  31.  
  32. #ifdef __GNUG__
  33. #pragma implementation
  34. #endif
  35.  
  36. #include "config.h"
  37. #include "misc.h"
  38. #include "PannedGE.h"
  39. #include "BoxPoint.h"
  40. #include "verify.h"
  41. #include "strclass.h"
  42. #include "Graph.h"
  43.  
  44. #if HAVE_ATHENA && \
  45.     HAVE_X11_XAW_FORM_H && \
  46.     HAVE_X11_XAW_PANNER_H && \
  47.     HAVE_X11_XAW_PORTHOLE_H
  48.  
  49. #include <X11/Intrinsic.h>
  50. #include <X11/StringDefs.h>
  51. #include <X11/Xaw/XawInit.h>
  52. #include <X11/Xaw/Form.h>
  53. #include <X11/Xaw/Panner.h>
  54. #include <X11/Xaw/Porthole.h>
  55. #include "PannedGEP.h"
  56.  
  57. static void PortholeCB(Widget w, XtPointer client_data, XtPointer call_data);
  58. static void PannerCB(Widget w, XtPointer client_data, XtPointer call_data);
  59.  
  60.  
  61. // Method function declarations
  62.  
  63. static void Resize(Widget w);
  64.  
  65. // Resource list
  66.  
  67. static XtResource resources[] = {
  68. #define offset(field) XtOffsetOf(PannedGraphEditRec, pannedGraphEdit.field)
  69.     // {name, class, type, size, offset, default_type, default_addr}
  70.  
  71.     { XtNminimumPannerWidth, XtCMinimumPannerWidth, XtRDimension, 
  72.       sizeof(Dimension), offset(minimumPannerWidth), 
  73.       XtRImmediate, XtPointer(50) },
  74.  
  75.     { XtNminimumPannerHeight, XtCMinimumPannerHeight, XtRDimension, 
  76.       sizeof(Dimension), offset(minimumPannerHeight), 
  77.       XtRImmediate, XtPointer(50) },
  78.  
  79.     { XtNmaximumScale, XtCMaximumScale, XtRDimension, 
  80.       sizeof(Dimension), offset(maximumScale), 
  81.       XtRImmediate, XtPointer(33) }
  82.  
  83. #undef offset
  84. };
  85.  
  86. // Class record initialization
  87.  
  88. PannedGraphEditClassRec pannedGraphEditClassRec = {
  89.   {     /* core fields */
  90.     /* superclass               */  portholeWidgetClass,
  91.     /* class_name               */  "PannedGraphEdit",
  92.     /* widget_size              */  sizeof(PannedGraphEditRec),
  93.     /* class_initialize         */  XawInitializeWidgetSet,
  94.     /* class_part_initialize    */  XtWidgetClassProc(0),
  95.     /* class_inited             */  False,
  96.     /* initialize               */  XtInitProc(0),
  97.     /* initialize_hook          */  XtArgsProc(0),
  98.     /* realize                  */  XtInheritRealize,
  99.     /* actions                  */  NULL,
  100.     /* num_actions              */  0,
  101.     /* resources                */  resources,
  102.     /* num_resources            */  XtNumber(resources),
  103.     /* xrm_class                */  NULLQUARK,
  104.     /* compress_motion          */  True,
  105.     /* compress_exposure        */  True,
  106.     /* compress_enterleave      */  True,
  107.     /* visible_interest         */  False,
  108.     /* destroy                  */  XtWidgetProc(0),
  109.     /* resize                   */  Resize,
  110.     /* expose                   */  XtInheritExpose,
  111.     /* set_values               */  XtSetValuesFunc(0),
  112.     /* set_values_hook          */  XtArgsFunc(0),
  113.     /* set_values_almost        */  XtInheritSetValuesAlmost,
  114.     /* get_values_hook          */  XtArgsProc(0),
  115.     /* accept_focus             */  XtAcceptFocusProc(0),
  116.     /* version                  */  XtVersion,
  117.     /* callback_private         */  NULL,
  118.     /* tm_table                 */  NULL,
  119.     /* query_geometry           */  XtInheritQueryGeometry,
  120.     /* display_accelerator      */  XtInheritDisplayAccelerator,
  121.     /* extension                */  NULL,
  122.   },
  123.   {     /* Composite fields */
  124.     /* geometry_manager         */  XtInheritGeometryManager,
  125.     /* change_managed           */  XtInheritChangeManaged,
  126.     /* insert_child             */  XtInheritInsertChild,
  127.     /* delete_child             */  XtInheritDeleteChild,
  128.     /* extension                */  NULL,
  129.   },
  130.   {     /* Porthole fields */
  131.     /* dummy                    */  0,
  132.   },
  133.   {    /* PannedGraphEdit fields */
  134.     /* extension                */  0,
  135.   },
  136. };
  137.  
  138. WidgetClass pannedGraphEditWidgetClass = WidgetClass(&pannedGraphEditClassRec);
  139.  
  140.  
  141. static void Resize(Widget w)
  142. {
  143.     XtCheckSubclass(w, pannedGraphEditWidgetClass, "Bad widget class");
  144.     const PannedGraphEditWidget pw = PannedGraphEditWidget(w);
  145.  
  146.     for (unsigned i = 0; i < pw->composite.num_children; i++)
  147.     {
  148.     // Resize each graphEdit child
  149.     Widget child = pw->composite.children[i];
  150.     if (XtIsSubclass(child, graphEditWidgetClass))
  151.         graphEditSizeChanged(child);
  152.     }
  153.  
  154.     // Call superclass resize method
  155.     pannedGraphEditClassRec.core_class.superclass->core_class.resize(w);
  156. }
  157.  
  158.  
  159. // create a graph editor with panner; return the graph editor widget ID
  160. Widget createPannedGraphEdit(Widget parent, String name, 
  161.                  ArgList graph_edit_args,
  162.                  Cardinal graph_edit_arg)
  163. {
  164.     Arg args[10];
  165.     int arg = 0;
  166.  
  167.     string form_name = string(name) + "_form";
  168.     arg = 0;
  169.     XtSetArg(args[arg], XtNborderWidth,     0); arg++;
  170.     XtSetArg(args[arg], XtNdefaultDistance, 0); arg++;
  171.     Widget form =
  172.     verify(XtCreateManagedWidget(form_name, 
  173.                      formWidgetClass, parent, args, arg));
  174.  
  175.     string panner_name = string(name) + "_panner";
  176.     arg = 0;
  177.     XtSetArg(args[arg], XtNresize,    False);          arg++;
  178.     XtSetArg(args[arg], XtNresizable, True);           arg++;
  179.     XtSetArg(args[arg], XtNbottom,    XawChainBottom); arg++;
  180.     XtSetArg(args[arg], XtNtop,       XawChainBottom); arg++;
  181.     XtSetArg(args[arg], XtNleft,      XawChainRight);  arg++;
  182.     XtSetArg(args[arg], XtNright,     XawChainRight);  arg++;
  183.     Widget panner = 
  184.     verify(XtCreateWidget(panner_name, 
  185.                   pannerWidgetClass, form, args, arg));
  186.  
  187.     string porthole_name = string(name) + "_porthole";
  188.     arg = 0;
  189.     XtSetArg(args[arg], XtNresizable, True);           arg++;
  190.     XtSetArg(args[arg], XtNbottom,    XawChainBottom); arg++;
  191.     XtSetArg(args[arg], XtNtop,       XawChainTop);    arg++;
  192.     XtSetArg(args[arg], XtNleft,      XawChainLeft);   arg++;
  193.     XtSetArg(args[arg], XtNright,     XawChainRight);  arg++;
  194.     Widget porthole = 
  195.     verify(XtCreateManagedWidget(porthole_name,
  196.                      pannedGraphEditWidgetClass, 
  197.                      form, args, arg));
  198.  
  199.     Widget graph_edit = 
  200.     verify(XtCreateManagedWidget(name, graphEditWidgetClass, porthole, 
  201.                      graph_edit_args, graph_edit_arg));
  202.     XtVaSetValues(graph_edit,
  203.           XtNresizable, True,
  204.           NULL);
  205.  
  206.     // Allow the porthole and the panner to talk to each other
  207.     XtAddCallback(porthole, XtNreportCallback, PortholeCB, XtPointer(panner));
  208.     XtAddCallback(panner, XtNreportCallback, PannerCB, XtPointer(graph_edit));
  209.  
  210.     // Propagate requested width and height of graph editor to form
  211.     Dimension width, height;
  212.     XtVaGetValues(graph_edit,
  213.           XtNrequestedWidth, &width,
  214.           XtNrequestedHeight, &height,
  215.           NULL);
  216.  
  217.     if (width > 0)
  218.     XtVaSetValues(form, XmNwidth, width, NULL);
  219.     if (height > 0)
  220.     XtVaSetValues(form, XmNheight, height, NULL);
  221.  
  222.     return graph_edit;
  223. }
  224.  
  225. static void PortholeCB(Widget w, 
  226.                XtPointer client_data, 
  227.                XtPointer call_data)
  228. {
  229.     // Setup panner after change in porthole
  230.  
  231.     XtCheckSubclass(w, pannedGraphEditWidgetClass, "Bad widget class");
  232.     const PannedGraphEditWidget pw = PannedGraphEditWidget(w);
  233.  
  234.     Arg args[10];
  235.     int arg = 0;
  236.     XawPannerReport *report = (XawPannerReport *) call_data;
  237.     Widget panner = Widget(client_data);
  238.  
  239.     Widget form = XtParent(w);
  240.     Dimension form_width, form_height, form_border_width;
  241.     XtVaGetValues(form,
  242.           XtNwidth,       &form_width,
  243.           XtNheight,      &form_height,
  244.           XtNborderWidth, &form_border_width,
  245.           NULL);
  246.  
  247.     WidgetList children;
  248.     XtVaGetValues(w,
  249.                   XtNchildren, &children,
  250.                   NULL);
  251.     Widget graph_edit = children[0];
  252.  
  253.     arg = 0;
  254.     XtSetArg (args[arg], XtNsliderX, report->slider_x); arg++;
  255.     XtSetArg (args[arg], XtNsliderY, report->slider_y); arg++;
  256.     if (report->changed != (XawPRSliderX | XawPRSliderY))
  257.     {
  258.     XtSetArg (args[arg], XtNsliderWidth,  report->slider_width);  arg++;
  259.     XtSetArg (args[arg], XtNsliderHeight, report->slider_height); arg++;
  260.     XtSetArg (args[arg], XtNcanvasWidth,  report->canvas_width);  arg++;
  261.     XtSetArg (args[arg], XtNcanvasHeight, report->canvas_height); arg++;
  262.     }
  263.     XtSetValues (panner, args, arg);
  264.  
  265.     // clog << "Form   size " << BoxPoint(form_width, form_height) << "\n";
  266.     // clog << "Canvas size " << BoxPoint(report->canvas_width, 
  267.     //                    report->canvas_height) << "\n";
  268.  
  269.     Dimension scale, panner_border_width;
  270.     XtVaGetValues(panner, 
  271.           XtNdefaultScale, &scale,
  272.           XtNborderWidth,  &panner_border_width,
  273.           NULL);
  274.  
  275.     // Determine new panner size
  276.     Dimension panner_width  = 
  277.     min(max((report->canvas_width * scale) / 100, 
  278.         pw->pannedGraphEdit.minimumPannerWidth),
  279.         (form_width * pw->pannedGraphEdit.maximumScale) / 100);
  280.  
  281.     Dimension panner_height = 
  282.     min(max((report->canvas_height * scale) / 100, 
  283.         pw->pannedGraphEdit.minimumPannerHeight), 
  284.         (form_height * pw->pannedGraphEdit.maximumScale) / 100);
  285.  
  286.     // clog << "Panner size " << BoxPoint(panner_width, panner_height) << "\n";
  287.  
  288.     Dimension extra_width;
  289.     Dimension extra_height;
  290.     Graph *graph;
  291.     XtVaGetValues(graph_edit,
  292.           XtNextraWidth,  &extra_width,
  293.           XtNextraHeight, &extra_height,
  294.           XtNgraph,       &graph,
  295.           NULL);
  296.  
  297.     bool need_panner = 
  298.     graph != 0
  299.     && graph->firstVisibleNode() != 0
  300.     && (report->canvas_width  - extra_width  >= form_width ||
  301.         report->canvas_height - extra_height >= form_height);
  302.  
  303.     if (need_panner && panner_width > 0 && panner_height > 0)
  304.     {
  305.     // Map panner in lower right edge of the form
  306.  
  307.     Dimension panner_window_width = 
  308.         panner_width  + panner_border_width * 2;
  309.     Dimension panner_window_height = 
  310.         panner_height + panner_border_width * 2;
  311.  
  312.     if (!XtIsManaged(panner))
  313.         XtManageChild(panner);
  314.  
  315.     // Add the panner size as extra space to graph editor such
  316.     // that the panner cannot obscure parts of the graph.
  317.  
  318.     extra_width =  panner_window_width;
  319.     extra_height = panner_window_height;
  320.     XtVaSetValues(graph_edit,
  321.               XtNextraWidth,  extra_width,
  322.               XtNextraHeight, extra_height,
  323.               NULL);
  324.  
  325.     int panner_x = form_width  - form_border_width - panner_window_width;
  326.     int panner_y = form_height - form_border_width - panner_window_height;
  327.  
  328.     XtConfigureWidget(panner,
  329.               panner_x, panner_y, 
  330.               panner_width, panner_height,
  331.               panner_border_width);
  332.     }
  333.     else
  334.     {
  335.     // Unmap panner
  336.     XtUnmanageChild(panner);
  337.     XtVaSetValues(graph_edit,
  338.               XtNextraWidth,  0,
  339.               XtNextraHeight, 0,
  340.               NULL);
  341.     }
  342. }
  343.  
  344. static void PannerCB(Widget /* panner */,
  345.              XtPointer client_data, 
  346.              XtPointer call_data)
  347. {
  348.     // Setup porthole after change in panner
  349.  
  350.     Arg args[2];
  351.     int arg = 0;
  352.     XawPannerReport *report = (XawPannerReport *)call_data;
  353.     Widget graph_edit = Widget(client_data);
  354.  
  355.     XtSetArg (args[arg], XtNx, -report->slider_x); arg++;
  356.     XtSetArg (args[arg], XtNy, -report->slider_y); arg++;
  357.     XtSetValues(graph_edit, args, arg);
  358. }
  359.  
  360. // For a given graph editor W, return its panner
  361. Widget pannerOfGraphEdit(Widget w)
  362. {
  363.     XtCheckSubclass(w, GraphEditWidgetClass, "Bad widget class");
  364.  
  365.     Widget parent = w;
  366.  
  367.     while (parent != 0)
  368.     {
  369.     if (XtIsSubclass(parent, formWidgetClass))
  370.         break;
  371.     parent = XtParent(parent);
  372.     }
  373.     return parent;
  374. }
  375.  
  376. #else // No Athena 
  377.  
  378. #include "ScrolledGE.h"
  379.  
  380. Widget createPannedGraphEdit(Widget parent, String name, 
  381.                  ArgList graph_edit_args,
  382.                  Cardinal graph_edit_arg)
  383. {
  384.     static bool warned = false;
  385.     if (!warned)
  386.     {
  387.     cerr << "Warning: panned graph editors are not supported "
  388.         "in this configuration.\n";
  389.     cerr << "Using scrolled graph editors instead.\n";
  390.     warned = true;
  391.     }
  392.  
  393.     return createScrolledGraphEdit(parent, name,
  394.                    graph_edit_args, graph_edit_arg);
  395. }
  396.  
  397. // For a given graph editor W, return its panner
  398. Widget pannerOfGraphEdit(Widget w)
  399. {
  400.     return scrollerOfGraphEdit(w);
  401. }
  402.  
  403. #endif
  404.