Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtinfo / dtinfo / src / Agents / GraphicAgentMotif.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  * $TOG: GraphicAgentMotif.C /main/30 1998/04/17 11:32:58 mgreess $
25  *
26  * Copyright (c) 1992 HAL Computer Systems International, Ltd.
27  * All rights reserved.  Unpublished -- rights reserved under
28  * the Copyright Laws of the United States.  USE OF A COPYRIGHT
29  * NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
30  * OR DISCLOSURE.
31  * 
32  * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
33  * SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.  USE,
34  * DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
35  * PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
36  * INTERNATIONAL, LTD.
37  * 
38 *                         RESTRICTED RIGHTS LEGEND
39  * Use, duplication, or disclosure by the Government is subject
40  * to the restrictions as set forth in subparagraph (c)(l)(ii)
41  * of the Rights in Technical Data and Computer Software clause
42  * at DFARS 252.227-7013.
43  *
44  *          HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
45  *                  1315 Dell Avenue
46  *                  Campbell, CA  95008
47  * 
48  */
49
50 #ifdef JBM
51 #include <tml/tml_objects.hxx>
52 #endif
53
54 #define C_TOC_Element
55 #define L_Basic
56
57 #define C_PixmapGraphic
58 #define C_PostScript
59 #define L_Graphics
60
61 #define C_MessageMgr
62 #define C_GraphicsMgr
63 #define C_NodeMgr
64 #define C_GhostScriptEventMgr
65 #define L_Managers
66
67 #define C_HelpAgent
68 #define C_GraphicAgent
69 #define L_Agents
70
71 #include <WWL/WTopLevelShell.h>
72 #include <WWL/WXmMenu.h>
73 #include <WWL/WXmForm.h>
74 #include <WWL/WXmPushButton.h>
75 #include <WWL/WXmToggleButton.h>
76 #include <WWL/WXmFrame.h>
77 #include <WWL/WXmSeparator.h>
78
79 #include "Managers/CatMgr.hh"
80 #include "Other/XmStringLocalized.hh"
81
82 #include <Prelude.h>
83 #include <iostream.h>
84 #include <string.h>
85 #include <stdio.h>
86
87 #include "Registration.hh"
88
89 #include "Widgets/WXawPorthole.h"
90 #include "Widgets/WXawPanner.h"
91 #include "Widgets/WPixmap.h"
92
93 #include "utility/funcs.h"
94
95 #define CLASS GraphicAgent
96 #include "create_macros.hh"
97
98 enum { PANNER_UPPER_LEFT,
99        PANNER_UPPER_RIGHT,
100        PANNER_LOWER_RIGHT,
101        PANNER_LOWER_LEFT,
102        PANNER_NONE,
103        PANNER_NUM_STATES };
104
105 inline int
106 min(int i1, int i2)
107 {
108   return i1 < i2 ? i1 : i2 ;
109 }
110
111 // /////////////////////////////////////////////////////////////////////////
112 // Constructor
113 // /////////////////////////////////////////////////////////////////////////
114
115 GraphicAgent::GraphicAgent (UAS_Pointer<UAS_Common> &node_ptr,
116                             UAS_Pointer<Graphic> &gr)
117 : f_shell (NULL),
118   f_node_ptr(node_ptr),
119   f_graphic (gr),
120   f_panner_state (PANNER_NONE),
121   f_current_scale (100),
122   f_scale_button(NULL),
123   f_setcustom(0)
124
125 {
126   f_graphic->pixmap_graphic()->agent(this);
127
128   UAS_Common::request ((UAS_Receiver<UAS_LibraryDestroyedMsg> *) this);
129 }
130
131 // /////////////////////////////////////////////////////////////////////////
132 // Destructor
133 // /////////////////////////////////////////////////////////////////////////
134
135 GraphicAgent::~GraphicAgent()
136 {
137   f_graphic->pixmap_graphic()->agent(NULL);
138   Pixmap pixmap = f_pixmap_widget->Picture();
139   if (pixmap && pixmap != f_graphic->pixmap_graphic()->pixmap())
140     {
141       XFreePixmap(XtDisplay(*f_pixmap_widget),
142                   pixmap);      // a scaled pixmap...give it back 
143
144     }
145   if(f_shell != NULL)
146     f_shell.Destroy();
147 }
148
149 // /////////////////////////////////////////////////////////////////////////
150 // popup
151 // /////////////////////////////////////////////////////////////////////////
152
153 void 
154 GraphicAgent::popup()
155 {
156   if (f_shell == NULL)
157     create_ui();
158
159   f_shell.Popup();
160   f_shell.DeIconify();
161 }
162
163 // /////////////////////////////////////////////////////////////////////////
164 // display
165 // /////////////////////////////////////////////////////////////////////////
166
167 void 
168 GraphicAgent::display()
169 {
170   if (f_shell == NULL)
171     create_ui();
172     
173   // assume all graphics are scalable for now.
174   bool scalable;
175   scalable = True;
176   if(scalable)
177   {
178     Widget *kids = f_view_menu->Children() ;
179     int num_children = f_view_menu->NumChildren();
180     for (int i = 0 ; i < num_children; i++)
181     {
182       WXmPrimitive prim(kids[i]);
183       prim.SetSensitive(True);
184     }
185   }
186   popup();
187 }
188
189
190 void
191 GraphicAgent::receive(DisplayGraphic &message, void* /*client_data*/)
192 {
193   ON_DEBUG(cerr << "GraphicAgent::receive(DisplayGraphic( " <<
194            message.graphic()->locator() << "))" << endl);
195
196   ON_DEBUG(cerr << "local locator is " <<
197            f_graphic->locator() << endl);
198
199   if (message.graphic() == f_graphic)
200     {
201       ON_DEBUG(cerr << "GraphicAgent::receive(DISPLAY)" << endl);
202       display();
203     }
204 }
205
206 void
207 GraphicAgent::receive(ReAttachGraphic &message, void* /*client_data*/)
208 {
209   //reattach();
210 }
211
212 void
213 GraphicAgent::receive (UAS_LibraryDestroyedMsg &msg, void* /*client_data*/)
214 {
215   if(f_node_ptr->lid() == (msg.fLib)->lid())
216   {
217     graphics_mgr().remove_detached((GraphicAgent*)this);
218     delete this;
219   }
220 }
221 // /////////////////////////////////////////////////////////////////////////
222 // create ui
223 // /////////////////////////////////////////////////////////////////////////
224
225 #define AM WAutoManage
226 void
227 GraphicAgent::create_ui()
228 {
229   XmStringLocalized mtfstring;
230   String            string;
231
232   f_shell = WTopLevelShell (window_system().toplevel(), WPopup, "graphic");
233   window_system().register_shell (&f_shell);
234
235   string = CATGETS(Set_GraphicAgent, 1, "Dtinfo: Detached Graphic");
236   XtVaSetValues((Widget)f_shell, XmNtitle, string, NULL);
237
238   // just use "delete_response" instead
239   // add a destroy callback to nuke the agent when widget is destroyed.
240   f_shell.SetDestroyCallback (this, (WWL_FUN) &GraphicAgent::ui_destroyed);
241
242   DECL  (WXmForm,           form,         f_shell,      "form"         );
243   DECLM (WXmMenuBar,        menu_bar,     form,         "menu_bar"     );
244 #ifdef hpux
245   //
246   //  rtp: hard-wire the menu bar's background, since
247   //       it comes up a bogus color. Copied from swm's
248   //       change in NodeWindowAgentMotif.C
249   //
250   Pixel bg = form.Background();
251   menu_bar.Background(bg);
252
253 #endif
254   DECLM (WXmCascadeButton,  file,         menu_bar,     "file"         );
255   DECLM (WXmPulldownMenu,   file_menu,    menu_bar,     "file_menu"    );
256   DECLM (WXmPushButton,     attach,       file_menu,    "attach"       );
257   DECLM (WXmPushButton,     visit,        file_menu,    "visit"        );
258   DECLM (WXmPushButton,     close,        file_menu,    "close"        );
259
260   XtVaSetValues(file, XmNlabelString,
261     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 1, "File")),
262     XmNmnemonic,
263     *CATGETS(Set_AgentLabel, 2, ""),
264     NULL);
265
266   XtVaSetValues(attach, XmNlabelString,
267     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 167, "Attach")),
268     XmNmnemonic,
269     *CATGETS(Set_AgentLabel, 21, ""),
270     NULL);
271
272   XtVaSetValues(visit, XmNlabelString,
273     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel,168,"Display Section")),
274     XmNmnemonic,
275     *CATGETS(Set_AgentLabel, 119, ""),
276     NULL);
277
278   XtVaSetValues(close, XmNlabelString,
279     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 12, "Close")),
280     XmNmnemonic,
281     *CATGETS(Set_AgentLabel, 13, ""),
282     NULL);
283
284   DECLM (WXmCascadeButton,  pan,          menu_bar,     "panner"       );
285   DECLM (WXmPulldownMenu,   panner_menu,  menu_bar,     "panner_menu"  );
286   DECLM (WXmToggleButton,   none,         panner_menu,  "none"         );
287   DECLM (WXmToggleButton,   up_left,      panner_menu,  "up_left"      );
288   DECLM (WXmToggleButton,   up_right,     panner_menu,  "up_right"     );
289   DECLM (WXmToggleButton,   low_left,     panner_menu,  "low_left"     );
290   DECLM (WXmToggleButton,   low_right,    panner_menu,  "low_right"    );
291
292   XtVaSetValues(pan, XmNlabelString,
293     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 166, "Panner")),
294     XmNmnemonic,
295     *CATGETS(Set_AgentLabel, 9, ""),
296     NULL);
297
298   XtVaSetValues(none, XmNlabelString,
299     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 178, "None")),
300     XmNmnemonic,
301     *CATGETS(Set_AgentLabel, 7, ""),
302     NULL);
303
304   XtVaSetValues(up_left, XmNlabelString,
305     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 179, "Upper Left")),
306     XmNmnemonic,
307     *CATGETS(Set_AgentLabel, 254, ""),
308     NULL);
309
310   XtVaSetValues(up_right, XmNlabelString,
311     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 180, "Upper Right")),
312     XmNmnemonic,
313     *CATGETS(Set_AgentLabel, 252, ""),
314     NULL);
315
316   XtVaSetValues(low_left, XmNlabelString,
317     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 181, "Lower Left")),
318     XmNmnemonic,
319     *CATGETS(Set_AgentLabel, 113, ""),
320     NULL);
321
322   XtVaSetValues(low_right, XmNlabelString,
323     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 182, "Lower Right")),
324     XmNmnemonic,
325     *CATGETS(Set_AgentLabel, 259, ""),
326     NULL);
327
328   // NOTE: some code in this module depends upon the exact ordering of items
329   // view menu will only be sensitive for scalable graphics 
330   DECL (WXmCascadeButton,   view,         menu_bar,     "view"         );
331   DECLM (WXmPulldownMenu,   view_menu,   menu_bar,     "view_menu"    );
332   DECLM (WXmPushButton,     fit_gr_to_win, view_menu,    "fit_window"  );
333   DECLM (WXmPushButton,     fit_win_to_gr, view_menu,    "fit_graphic" );
334
335   XtVaSetValues(view, XmNlabelString,
336     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 4, "View")),
337     XmNmnemonic,
338     *CATGETS(Set_AgentLabel, 5, ""),
339     NULL);
340
341   XtVaSetValues(fit_gr_to_win, XmNlabelString,
342     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 169, "Fit to Window")),
343     XmNmnemonic,
344     *CATGETS(Set_AgentLabel, 35, ""),
345     NULL);
346
347
348   XtVaSetValues(fit_win_to_gr, XmNlabelString,
349     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 170, "Fit to Graphic")),
350     XmNmnemonic,
351     *CATGETS(Set_AgentLabel, 37, ""),
352     NULL);
353
354   DECLM (WXmSeparator,      separator,    view_menu,    "separator"    );
355   DECLM (WXmToggleButton,   z_25,         view_menu,    "z_25"         );
356   DECLM (WXmToggleButton,   z_50,         view_menu,    "z_50"         );
357   DECLM (WXmToggleButton,   z_100,        view_menu,    "z_100"        );
358   DECLM (WXmToggleButton,   z_125,        view_menu,    "z_125"        );
359   DECLM (WXmToggleButton,   z_150,        view_menu,    "z_150"        );
360   DECLM (WXmToggleButton,   z_200,        view_menu,    "z_200"        );
361   DECLM (WXmToggleButton,   z_custom,     view_menu,    "z_custom"     );
362   
363   mtfstring = CATGETS(Set_AgentLabel, 171, "25 %");
364   XtVaSetValues(z_25, XmNlabelString, (XmString)mtfstring, NULL);
365   mtfstring = CATGETS(Set_AgentLabel, 172, "50 %");
366   XtVaSetValues(z_50, XmNlabelString, (XmString)mtfstring, NULL);
367   mtfstring = CATGETS(Set_AgentLabel, 173, "100 %");
368   XtVaSetValues(z_100, XmNlabelString, (XmString)mtfstring, NULL);
369   mtfstring = CATGETS(Set_AgentLabel, 174, "125 %");
370   XtVaSetValues(z_125, XmNlabelString, (XmString)mtfstring, NULL);
371   mtfstring = CATGETS(Set_AgentLabel, 175, "150 %");
372   XtVaSetValues(z_150, XmNlabelString, (XmString)mtfstring, NULL);
373   mtfstring = CATGETS(Set_AgentLabel, 176, "200 %");
374   XtVaSetValues(z_200, XmNlabelString, (XmString)mtfstring, NULL);
375
376   XtVaSetValues(z_custom, XmNlabelString,
377     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 177, "Custom...")),
378     XmNmnemonic,
379     *CATGETS(Set_AgentLabel, 13, ""),
380     NULL);
381
382   z_100.Set(1);
383   f_scale_button = (WXmToggleButton*)(Widget)z_100 ;
384   f_custom_scale = (WXmToggleButton*)(Widget)z_custom ;
385
386   f_view_menu = (WXmPulldownMenu*)(Widget)view_menu ;
387
388   DECLM (WXmCascadeButton,  help,         menu_bar,      "help"        );
389   DECLM (WXmPulldownMenu,   help_menu,    menu_bar,      "help_menu"   );
390   DECLM (WXmPushButton,     on_window,    help_menu,     "on_window"   );
391   DECLM (WXmPushButton,     on_help,      help_menu,     "on_help"     );
392
393   XtVaSetValues(help, XmNlabelString,
394     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 48, "Help")),
395     XmNmnemonic,
396     *CATGETS(Set_AgentLabel, 39, ""),
397     NULL);
398
399   XtVaSetValues(on_window, XmNlabelString,
400     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 147, "On Window")),
401     XmNmnemonic,
402     *CATGETS(Set_AgentLabel, 35, ""),
403     NULL);
404
405   XtVaSetValues(on_help, XmNlabelString,
406     (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 153, "On Help")),
407     XmNmnemonic,
408     *CATGETS(Set_AgentLabel, 39, ""),
409     NULL);
410
411   DECLM (WXmLabel, message_area, form, "message");
412   f_message_area = (WXmLabel*)(Widget)message_area ;
413
414   DECLM (WXmSeparator, sep, form, "sep2");
415
416   DECL  (WXmFrame,          frame,        form,         "frame"        );
417   DECL  (WXmForm,           subform,      frame,        "subform"      );
418   DECLM (WXawPanner,        panner,       subform,      "panner"       );
419   DECLM (WXawPorthole,      porthole,     subform,      "porthole"     );
420   DECLM (WPixmap,           pixmap,       porthole,     "pixmap"       );
421
422
423   f_panner = (WXawPanner*)(Widget)panner ;
424   f_pixmap_widget = (WPixmap*)(Widget)pixmap ;
425
426   file.SubMenuId (file_menu);
427   view.SubMenuId (view_menu);
428   pan.SubMenuId (panner_menu);
429   help.SubMenuId (help_menu);
430   menu_bar.MenuHelpWidget (help);
431     
432   WArgList args;
433
434   PixmapGraphic &pgraphic = *(f_graphic->pixmap_graphic());
435
436   Graphic *graphic = f_graphic ;
437   UAS_String titleStr(graphic->title());
438   const char *title = titleStr ;
439
440   if (title == NULL || *title == '\0')  // empty string 
441     title = (char *)CATGETS(Set_GraphicAgent, 2, "Detached Graphic");
442
443   {
444
445     UAS_String buffer = CATGETS(Set_GraphicAgent, 8, "Dtinfo: ");
446     buffer = buffer + title;
447
448     f_shell.Title((char*)buffer);
449     f_shell.IconName((char*)buffer);
450
451   }
452
453   args.Reset();
454   panner.CanvasWidth (pgraphic.width(), args);
455   panner.CanvasHeight (pgraphic.height(), args);
456   panner.Set (args);
457
458   SET_CALLBACK_D (porthole,Report,porthole_report,(Widget) panner);
459   install_new_picture(&pgraphic);
460   SET_CALLBACK_D (panner,Report,panner_report,(Widget) pixmap);
461
462   ON_ACTIVATE (visit,visit_node);
463   ON_ACTIVATE (close,close_window);
464   ON_ACTIVATE (attach,reattach);
465
466   SET_CALLBACK_D (none,ValueChanged,set_panner,PANNER_NONE);
467   SET_CALLBACK_D (up_left,ValueChanged,set_panner,PANNER_UPPER_LEFT);
468   SET_CALLBACK_D (up_right,ValueChanged,set_panner,PANNER_UPPER_RIGHT);
469   SET_CALLBACK_D (low_left,ValueChanged,set_panner,PANNER_LOWER_LEFT);
470   SET_CALLBACK_D (low_right,ValueChanged,set_panner,PANNER_LOWER_RIGHT);
471
472   ON_ACTIVATE (fit_gr_to_win,fit_graphic_to_window_callback);
473   ON_ACTIVATE (fit_win_to_gr,fit_window_to_graphic_callback);
474
475   SET_CALLBACK_D (z_25,ValueChanged,zoom_callback,25);
476   SET_CALLBACK_D (z_50,ValueChanged,zoom_callback,50);
477   SET_CALLBACK_D (z_100,ValueChanged,zoom_callback,100);
478   SET_CALLBACK_D (z_125,ValueChanged,zoom_callback,125);
479   SET_CALLBACK_D (z_150,ValueChanged,zoom_callback,150);
480   SET_CALLBACK_D (z_200,ValueChanged,zoom_callback,200);
481   SET_CALLBACK_D (z_custom,ValueChanged,zoom_callback,0);
482
483   help_agent().add_activate_help (on_window, "graphic_on_window");
484   help_agent().add_activate_help (on_help,   "graphic_on_help");
485
486   view.Manage();
487
488   // menubars for scalable graphics 
489
490   // assume all graphics are scalable
491   bool scalable = True;
492   if(scalable)
493   {
494     if (f_graphic->content_type() == "application/CGM")
495        mtfstring = CATGETS(Set_GraphicAgent, 4, "Vector illustration (scalable)");
496     else
497        mtfstring = CATGETS(Set_GraphicAgent, 9, "Raster illustration (scalable)");
498   }
499   else
500   {
501 #if !defined(VF_DEBUG)
502       for (int i = 0 ; i < view_menu.NumChildren(); i++)
503         WRect(view_menu.Children()[i]).SetSensitive(False);
504 #endif
505     mtfstring = CATGETS(Set_GraphicAgent, 3,
506                 "Raster illustration (non-scalable)");
507   }
508
509 #if EAM
510   if (f_graphic->content_type() != "application/postscript") {
511
512 #if !defined(VF_DEBUG)
513       for (int i = 0 ; i < view_menu.NumChildren(); i++)
514         WRect(view_menu.Children()[i]).SetSensitive(False);
515 #endif
516       mtfstring = CATGETS(Set_GraphicAgent, 3,
517                                 "Raster illustration (non-scalable)");
518   }
519   else {
520       mtfstring = CATGETS(Set_GraphicAgent, 4,
521                                 "Vector illustration (scalable)");
522   }
523 #endif
524
525   XtVaSetValues((Widget)f_message_area, XmNlabelString, (XmString)mtfstring, NULL);
526
527   // porthole.Manage();
528   frame.Manage();
529   subform.ShadowThickness(0);
530   subform.Manage();
531   form.ShadowThickness(0);
532   form.Manage();
533
534   // when panner first appears, it should be in upper-left corner
535   up_left.Set (TRUE);
536   adjust_panner (PANNER_UPPER_LEFT); 
537
538   // Set Max width/height if not scalable 
539   f_shell.Realize();
540
541   
542   Display *display = XtDisplay(f_shell);
543   Screen      *retScr = XtScreen(f_shell);
544   int screen =  XScreenNumberOfScreen(retScr);
545   int dw = DisplayWidth(display, screen);
546   int dh = DisplayHeight(display, screen);
547
548   Dimension width = dw, height = dh;
549
550   //if (f_graphic->content_type() == "application/CGM")
551
552   // assume all graphics are scalable
553   scalable = True;
554   if(scalable)
555   {
556     // set max size of window
557     height = min(height, dh - 100);
558     width  = min(width,  dw - 100);
559
560     f_shell.Set (WArgList (XmNmaxHeight, height,
561                            XmNmaxWidth,  width,
562                            NULL));
563
564     // don't allow window to shrink smaller than original size
565     f_shell.Get (WArgList (XmNheight, (XtArgVal) &height,
566                            NULL));
567     height = min(height, dh - 100);
568
569     f_shell.Set (WArgList (XmNminHeight, height,
570                              NULL));
571   }
572   else
573   {
574     f_shell.Get (WArgList (XmNheight, (XtArgVal) &height,
575                      XmNwidth, &width,
576                      NULL));
577     height = min(height, dh - 100);
578     width  = min(width,  dw - 100);
579
580     f_shell.Set (WArgList (XmNmaxHeight, height,
581                      XmNmaxWidth,  width,
582                      NULL));
583   }
584 }
585
586
587 void
588 GraphicAgent::close_window()
589 {
590   reattach();
591   f_shell.Popdown();
592 }
593
594 // /////////////////////////////////////////////////////////////////
595 // ui_destroyed - user nuked Motif window, so kill myself
596 // /////////////////////////////////////////////////////////////////
597  
598 void
599 GraphicAgent::ui_destroyed()
600 {
601   // Set f_shell to NULL, since Xt is destroying it for us.
602   reattach();
603   f_shell = NULL;
604 }
605
606
607 void
608 GraphicAgent::attach_graphic()
609 {
610   reattach();
611 }
612
613
614 void
615 GraphicAgent::reattach()
616 {
617   graphics_mgr().reattach_graphic(f_graphic);
618 //  Wait_Cursor bob;
619 //  UAS_String idata(*image_data);
620 //  PixmapGraphic *pgr = f_graphic->pixmap_graphic();
621
622 //  ON_DEBUG(cerr << "Graphic Agent reattach" << endl);
623 //  f_graphic->set_detached(FALSE);
624 //  f_graphic->
625 //    pixmap_graphic()->
626 //    UAS_Sender<ReAttachGraphic>::send_message(ReAttachGraphic(f_graphic));
627
628 //  graphics_mgr().remove_detached((GraphicAgent*)this);
629 //  delete this ;
630 }
631
632
633 void
634 GraphicAgent::visit_node()
635 {
636   extern char g_top_locator[];
637   extern bool g_scroll_to_locator;
638   const char *glocator = f_graphic->locator();
639   ON_DEBUG (printf ("Graphic jumping to <%s>\n", glocator));
640   ON_DEBUG (printf ("  copying to %p\n", g_top_locator));
641   strcpy (g_top_locator, &glocator[8]);
642   g_scroll_to_locator = TRUE;
643   f_node_ptr->retrieve();
644 }
645
646
647 void
648 GraphicAgent::porthole_report(WCallback *wcb)
649 {
650   XawPannerReport *repp = (XawPannerReport*)wcb->CallData();
651   XawPannerReport &rep = *repp;
652   ON_DEBUG(cerr << "got a porthole_report" << hex << rep.changed << endl);
653   if (rep.changed & (XawPRCanvasHeight | XawPRCanvasWidth)){
654     ON_DEBUG(cerr << "porthole height or width change" << endl);
655
656     WXawPorthole porthole(wcb->GetWidget());
657     WXawPanner panner((Widget)wcb->ClientData());
658
659     WCore picture(porthole.Children()[0]);
660
661     Dimension port_width  = porthole.Width();
662     Dimension port_height = porthole.Height();
663     Dimension cwidth = panner.CanvasWidth();
664     Dimension cheight= panner.CanvasHeight();
665
666     ON_DEBUG(cerr << "Canvas ( " << cwidth << ", " << cheight << ")"<<endl); 
667     ON_DEBUG(cerr << "Porthle( " << port_width << ", " << port_height << ")"
668              << endl); 
669
670     WArgList args ;
671
672     // re-adjust the slider 
673     if (rep.changed & XawPRCanvasHeight)
674       {
675         ON_DEBUG(cerr << "adjust panner SliderHeight " << port_height <<
676                  endl); 
677         panner.SliderHeight(port_height, args);
678       }
679
680     if (rep.changed & XawPRCanvasWidth)
681       {
682         ON_DEBUG(cerr << "adjust panner SliderWidth " << port_width <<
683                  endl); 
684         panner.SliderWidth(port_width, args);
685       }
686
687     panner.Set(args);
688
689
690     if ((cwidth <= port_width) &&
691          (cheight <= port_height))
692       {
693         ON_DEBUG(cerr << "PANNER UNmanage" << endl);
694         panner.Unmanage();
695       } else {
696         if (f_panner_state != PANNER_NONE)
697           panner.Manage();
698       }
699   }
700 }
701
702
703 void
704 GraphicAgent::panner_report(WCallback *wcb)
705 {
706   ON_DEBUG(cerr << "panner report " << endl);
707   XawPannerReport *repp = (XawPannerReport*)wcb->CallData();
708   XawPannerReport &rep = *repp;
709
710   // slide the picture 
711
712   WArgList args ;
713   WCore core((Widget)wcb->ClientData());
714   core.X(0 - rep.slider_x, args);
715   core.Y(0 - rep.slider_y, args);
716   core.Set(args);
717 }
718
719
720 void
721 GraphicAgent::adjust_panner(unsigned int state)
722 {
723   ON_DEBUG(cerr << "adjust_panner( " << state << ")" << endl);
724   if (state == f_panner_state)
725     return;
726
727   f_panner_state = state ;
728
729   WArgList args ;
730
731   WXawPanner &panner(*f_panner) ;
732
733   switch (state){
734   case PANNER_UPPER_LEFT:
735     {
736       /* upper left */
737       panner.LeftAttachment(XmATTACH_FORM, args);
738       panner.TopAttachment(XmATTACH_FORM, args);
739       panner.RightAttachment(XmATTACH_POSITION, args);
740       panner.RightPosition(20, args);
741       panner.BottomAttachment(XmATTACH_POSITION, args);
742       panner.BottomPosition(20, args);
743     }
744     break;
745   case PANNER_UPPER_RIGHT:
746     {
747       /* upper right */
748       panner.RightAttachment(XmATTACH_FORM, args);
749       panner.TopAttachment(XmATTACH_FORM, args);
750       panner.LeftAttachment(XmATTACH_POSITION, args);
751       panner.LeftPosition(80, args);
752       panner.BottomAttachment(XmATTACH_POSITION, args);
753       panner.BottomPosition(20, args);
754     }
755     break;
756   case PANNER_LOWER_RIGHT:
757     {
758       /* lower right */
759       panner.RightAttachment(XmATTACH_FORM, args);
760       panner.BottomAttachment(XmATTACH_FORM, args);
761       panner.LeftAttachment(XmATTACH_POSITION, args);
762       panner.LeftPosition(80, args);
763       panner.TopAttachment(XmATTACH_POSITION, args);
764       panner.TopPosition(80, args);
765     }
766     break;
767   case PANNER_LOWER_LEFT:
768     {
769       /* lower left */
770       panner.LeftAttachment(XmATTACH_FORM, args);
771       panner.BottomAttachment(XmATTACH_FORM, args);
772       panner.RightAttachment(XmATTACH_POSITION, args);
773       panner.RightPosition(20, args);
774       panner.TopAttachment(XmATTACH_POSITION, args);
775       panner.TopPosition(80, args);
776     }
777     break;
778   case PANNER_NONE:
779     {
780       /* unmanaged */
781       panner.Unmanage();
782     }
783     break;
784   default:
785     assert(0);
786     break;
787   }
788
789   panner.Set(args);
790
791   // see if we can display it 
792
793   Dimension cwidth =  panner.CanvasWidth();
794   Dimension cheight = panner.CanvasHeight();
795
796   WXawPorthole porthole(XtParent(*f_panner)) ;
797
798   ON_DEBUG(cerr << "Panner - state: " << state << " canvas ( " << cwidth
799            << ", " << cheight << ") porthole ( " << porthole.Width() <<
800            ", " << porthole.Height() << ")" << endl);
801
802   if ((state != PANNER_NONE) &&
803       ((cwidth > porthole.Width()) ||
804        (cheight > porthole.Height())))
805     {
806       panner.Manage();
807     }
808 }
809
810
811 void
812 GraphicAgent::set_panner(WCallback *wcb)
813 {
814   // adjust panner to the Set state 
815   WXmToggleButton button(wcb->GetWidget());
816   if (button.Set())
817     {
818       unsigned int state = (unsigned int)wcb->ClientData();
819       adjust_panner(state);
820     }      
821 }
822
823
824 void
825 GraphicAgent::zoom_callback(WCallback *wcb)
826 {
827   ON_DEBUG (puts ("GraphicAgent::zoom_callback() called"));
828   WXmToggleButton button(wcb->GetWidget());
829   XmToggleButtonCallbackStruct &cbs = 
830     *(XmToggleButtonCallbackStruct*)wcb->CallData();
831
832   ON_DEBUG(cerr << "cbs.set = " << cbs.set << endl);
833   ON_DEBUG(cerr << "cbs.rsn = " << cbs.reason << endl);
834   ON_DEBUG(cerr << "cbs.event = " << cbs.event << endl);
835   
836   if (button.Set())
837     {
838       int scale = (unsigned int) wcb->ClientData();
839       if (scale > 0)
840         {
841           set_zoom (scale);
842           f_scale_button = (WXmToggleButton*)(Widget)button ;
843           f_setcustom = 0 ;
844         }
845       else
846         {
847           // we get called twice when selecting already selected custom button
848           // just do nothing second time around 
849           if (f_setcustom)
850             {
851               f_setcustom = 0 ;
852               return ;
853             }
854           f_setcustom = 1 ;
855
856           UAS_String msg   = CATGETS(Set_GraphicAgent, 6,
857                                         "Enter the new scaling percentage:");
858           UAS_String title = CATGETS(Set_GraphicAgent, 7, "Dtinfo: Set Scale");
859           scale = message_mgr().
860                     get_integer((char*)msg, (char*)title, f_current_scale,
861                                 (Widget)f_shell);
862
863           ON_DEBUG(cerr << "scale value is " << scale << endl);
864           if (scale == -1)
865             {
866               // unset Custom option in list 
867               if (((Widget)*f_scale_button) != ((Widget)button))
868                 {
869                   button.Set(0);
870                   f_scale_button->Set(1);
871                   f_setcustom = 0 ;
872                 }
873               return;
874             }
875           set_zoom (scale);
876           f_scale_button = (WXmToggleButton*)(Widget)button ;
877         }
878         // maybe this should be a user option
879         //fit_window_to_graphic();
880     }
881 }
882
883
884 void
885 GraphicAgent::set_zoom(unsigned int scale)
886 {
887   // Deal with bogus values. 
888   if (scale < 10)
889     scale = 10;
890   else if (scale > 999)
891     scale = 999;
892
893   if (scale == f_current_scale)
894     return;
895
896   Wait_Cursor bob;
897
898   XmStringLocalized mtfstring = CATGETS(Set_GraphicAgent, 5,
899                                 "Scaling illustration, please wait...");
900
901   XtVaSetValues((Widget)f_message_area, XmNlabelString, (XmString)mtfstring, NULL);
902
903   XmUpdateDisplay((Widget)f_message_area);
904
905   f_current_scale = scale;
906
907   UAS_String f_graphic_content_type(f_graphic->content_type());
908   UAS_String temp_str = f_graphic->data();
909
910   PixmapGraphic *pgr = 
911       f_graphic->pixmap_graphic(temp_str, f_graphic->data_length(),
912                                  f_graphic_content_type, scale);
913   install_new_picture(pgr);
914   refresh(graphic());
915
916   if (f_graphic->content_type() == "application/CGM")
917     mtfstring = CATGETS(Set_GraphicAgent, 4, "Vector illustration (scalable)");
918   else
919     mtfstring = CATGETS(Set_GraphicAgent, 9, "Raster illustration (scalable)");
920
921   XtVaSetValues((Widget)f_message_area, XmNlabelString, (XmString)mtfstring, NULL);
922
923 }
924
925
926 void
927 GraphicAgent::refresh(const UAS_Pointer<Graphic> &)
928 {
929   // refresh by clearing window and sending in expose event
930   XClearArea(XtDisplay(*f_pixmap_widget),
931              XtWindow(*f_pixmap_widget),
932              0, 0, 0, 0, TRUE);
933
934   // update message area 
935   XmStringLocalized mtfstring;
936   if (f_graphic->content_type() == "application/CGM")
937     mtfstring = CATGETS(Set_GraphicAgent, 4, "Vector illustration (scalable)");
938   else
939     mtfstring = CATGETS(Set_GraphicAgent, 9, "Raster illustration (scalable)");
940
941   XtVaSetValues((Widget)f_message_area, XmNlabelString, (XmString)mtfstring, NULL);
942 }
943
944
945 void
946 GraphicAgent::fit_graphic_to_window_callback(WCallback *)
947 {
948   Dimension gr_width;
949   Dimension gr_height;
950   int wscale, hscale;
951   unsigned int scale_factor;
952
953   // get size of graphic
954   gr_width = f_graphic->pixmap_graphic()->width();
955   gr_height = f_graphic->pixmap_graphic()->height();
956
957   int dx, dy;
958   WXawPorthole porthole(XtParent(*f_pixmap_widget));
959   dx = abs(porthole.Width() - f_graphic->pixmap_graphic()->width());
960   dy = abs(porthole.Height() - f_graphic->pixmap_graphic()->height());
961   if (dx < dy)
962     scale_factor = 
963          (100 * porthole.Width()) / f_graphic->pixmap_graphic()->width();
964   else
965     scale_factor = 
966          (100 * porthole.Height()) / f_graphic->pixmap_graphic()->height();
967   
968
969   wscale = (100 * porthole.Width()) / gr_width;
970   hscale = (100 * porthole.Height()) / gr_height;
971
972   // scaling from dimensions of original pixmap graphic 
973   if (wscale < hscale)
974     set_zoom(wscale);
975   else
976     set_zoom(hscale);
977
978   // fit graphic to window means custom scale, so
979   // toggle the button.
980   f_scale_button->Set(0);
981   f_scale_button = f_custom_scale;
982   f_scale_button->Set(1);
983
984 }
985
986
987 void
988 GraphicAgent::fit_window_to_graphic_callback(WCallback *)
989 {
990   fit_window_to_graphic();
991 }
992 void
993 GraphicAgent::fit_window_to_graphic()
994 {
995   WXawPorthole porthole(XtParent(*f_pixmap_widget));
996   WPixmap   picture(*f_pixmap_widget) ;
997   WXawPanner panner(*f_panner);
998
999   // desired width of porthole is in panner.Canvas{Width,Height}
1000   Dimension cwidth  = panner.CanvasWidth();
1001   Dimension cheight = panner.CanvasHeight() ;
1002
1003   // menu_bar is first child of form which is first child of f_shell 
1004   WComposite form(f_shell.Children()[0]);
1005   WComposite menu_bar(form.Children()[0]) ;
1006   // f_message_area is Children()[1]
1007   WXmSeparator separator(form.Children()[2]);
1008
1009   // account for frame margins 
1010   // frame is parent of subform is parent of panner 
1011   WXmFrame frame(XtParent(XtParent(panner)));
1012
1013   cheight += menu_bar.Height() + frame.MarginHeight() * 2 + frame.TopOffset()
1014     + frame.BottomOffset() + separator.Height() + 2 * separator.Margin() +
1015     separator.TopOffset() + separator.BottomOffset() + 
1016     f_message_area->Height() + f_message_area->TopOffset() +
1017     f_message_area->BottomOffset() + f_message_area->MarginTop() +
1018     f_message_area->MarginBottom();// + 2 * f_message_area->MarginHeight(); 
1019
1020   cwidth  += frame.MarginWidth() * 2 + frame.LeftOffset() +
1021     frame.RightOffset();
1022
1023   WArgList args ;
1024   f_shell.Width(cwidth + 4, args);
1025   f_shell.Height(cheight + 4, args);
1026   f_shell.Set(args);
1027
1028   panner.Unmanage();
1029 }
1030
1031 void
1032 GraphicAgent::install_new_picture(PixmapGraphic *pgr)
1033 {
1034   // dispose of the old Pixmap if needed 
1035   Pixmap pixmap = f_pixmap_widget->Picture() ;
1036   if (pixmap && (pixmap != f_graphic->pixmap_graphic()->pixmap()))
1037     XFreePixmap(XtDisplay(*f_pixmap_widget), pixmap);   // a scaled pixmap...give it back 
1038
1039
1040   // put the new Pixmap into the pixmap widget
1041   WArgList args ;
1042   f_pixmap_widget->Picture(pgr->pixmap(), args) ; // install the new one 
1043   f_pixmap_widget->Width(pgr->width(), args);     // update size 
1044   f_pixmap_widget->Height(pgr->height(), args);   
1045   f_pixmap_widget->Set(args);
1046
1047   // update some more UI crud
1048
1049   args.Reset();
1050   WXawPorthole porthole(XtParent(*f_pixmap_widget));
1051
1052   args.Reset();
1053   WXawPanner panner(*f_panner);
1054   panner.CanvasWidth(pgr->width(), args);
1055   panner.CanvasHeight(pgr->height(),args);
1056   panner.SliderWidth(porthole.Width(), args);
1057   panner.SliderHeight(porthole.Height(), args);
1058   panner.Set(args);
1059
1060   if ((f_panner_state != PANNER_NONE) &&
1061       ((pgr->width() > porthole.Width()) ||
1062        (pgr->height() > porthole.Height())))
1063     {
1064
1065       panner.Manage();
1066
1067     } else {
1068
1069       panner.Unmanage();
1070
1071     }
1072   
1073
1074   if (pgr != f_graphic->pixmap_graphic())
1075     {
1076       // clean up PixmapGraphic storage, but keep the X Pixmap
1077       // (its in the pixmap_widget) 
1078       pgr->set_type(PixmapGraphic::PRESERVE) ;
1079       delete pgr ;
1080     }
1081 }
1082
1083 void
1084 GraphicAgent::unset_scale_buttons()
1085 {
1086   for (int i = 0 ; i < 10; i++)
1087     WXmToggleButton((*f_view_menu).Children()[i]).Set(False);
1088 }
1089