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