Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtinfo / dtinfo / src / Agents / MapAgentMotif.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 /*      Copyright (c) 1994,1995,1996 FUJITSU LIMITED    */
24 /*      All Rights Reserved                             */
25
26 /*
27  * $TOG: MapAgentMotif.C /main/16 1998/04/17 11:33:40 mgreess $
28  *
29  * Copyright (c) 1992 HaL Computer Systems, Inc.  All rights reserved.
30  * UNPUBLISHED -- rights reserved under the Copyright Laws of the United
31  * States.  Use of a copyright notice is precautionary only and does not
32  * imply publication or disclosure.
33  * 
34  * This software contains confidential information and trade secrets of HaL
35  * Computer Systems, Inc.  Use, disclosure, or reproduction is prohibited
36  * without the prior express written permission of HaL Computer Systems, Inc.
37  * 
38  *                         RESTRICTED RIGHTS LEGEND
39  * Use, duplication, or disclosure by the Government is subject to
40  * restrictions as set forth in subparagraph (c)(l)(ii) of the Rights in
41  * Technical Data and Computer Software clause at DFARS 252.227-7013.
42  *                        HaL Computer Systems, Inc.
43  *                  1315 Dell Avenue, Campbell, CA  95008
44  * 
45  */
46
47 #include "UAS.hh"
48
49 #define C_TOC_Element
50 #define L_Basic
51
52 #define C_WindowSystem
53 #define L_Other
54
55 #define C_HelpAgent
56 #define C_Agent
57 #define C_MapAgent
58 #define L_Agents
59
60 #define C_WindowGeometryPref
61 #define L_Preferences
62
63 #define C_PrefMgr
64 #define C_MessageMgr
65 #define L_Managers
66
67 #include "Prelude.h"
68
69 #include "Other/XmStringLocalized.hh"
70 #include "Managers/CatMgr.hh"
71
72 #include "Registration.hh"
73
74 #include <WWL/WTopLevelShell.h>
75 #include <WWL/WXmForm.h>
76 #include <WWL/WXmPushButton.h>
77 #include <WWL/WXmPanedWindow.h>
78 #include <WWL/WXmFrame.h>
79 #include <WWL/WXmPushButton.h>
80 #include <WWL/WXmToggleButton.h>
81 #include <WWL/WXmArrowButton.h>
82
83 #include "Widgets/WXawPorthole.h"
84 #include "Widgets/WXawPanner.h"
85 #include "Widgets/WXawTree.h"
86
87 #define CLASS MapButton
88 #include "create_macros.hh"
89
90 class MapButton : public WWL
91 {
92 public:
93   MapButton (WComposite &parent, const UAS_Pointer<UAS_Common> &doc_ptr,
94              MapButton *ancestor);
95
96   void activate();
97   void expand();
98   void destroy();
99
100   WXmForm        f_form;
101   WXmPushButton  f_button;
102   WXmArrowButton f_arrow;
103   UAS_Pointer<UAS_Common> f_doc_ptr;
104   bool           f_expanded;
105
106   static void ManageKids();
107   static Widget *f_kids;
108   static int     f_num_kids;
109   static int     f_kids_size;
110 };
111
112 Widget *MapButton::f_kids;
113 int MapButton::f_num_kids;
114 int MapButton::f_kids_size;
115
116 MapButton::MapButton (WComposite &parent,
117                       const UAS_Pointer<UAS_Common> &doc_ptr,
118                       MapButton *ancestor)
119 : f_form (parent, "form"),
120   f_doc_ptr (doc_ptr),
121   f_expanded (FALSE)
122 {
123   ON_DEBUG (printf ("MapButton::MapButton (%s)\n", f_doc_ptr->title()));
124   static expandable_tree =
125     window_system().get_boolean_default ("ExpandableMap");
126   UAS_List<UAS_Common> kids (f_doc_ptr->children());
127   UAS_String t = f_doc_ptr->title();
128   if (kids.length() > 0 && expandable_tree)
129     {
130       f_arrow = WXmArrowButton (f_form, "expand", WAutoManage);
131       ON_ACTIVATE (f_arrow,expand);
132       f_button =
133         WXmPushButton (f_form, t, WAutoManage,
134                        WArgList (XmNrightWidget, (XtArgVal) ((Widget) f_arrow),
135                                  XmNrightAttachment, XmATTACH_WIDGET,
136                                  NULL));
137     }
138   else
139     {
140       f_button = WXmPushButton (f_form, t, WAutoManage);
141     }
142
143   ON_ACTIVATE (f_button,activate);
144   SET_CALLBACK (f_form,Destroy,destroy);
145
146   f_form.ShadowThickness (0);
147   // f_form.Realize();
148
149   // Add to the list so that we can manage 'em all at once. 
150   if (f_num_kids + 1 > f_kids_size)
151     {
152       f_kids_size *= 2;
153       f_kids = (Widget *) realloc (f_kids, sizeof (Widget) * f_kids_size);
154     }
155   f_kids[f_num_kids++] = (Widget) f_form;
156   ON_DEBUG (printf ("Form managed = %d\n", XtIsManaged (f_form)));
157     
158   if (ancestor != NULL)
159     {
160       CXawTree form (f_form);
161       WArgList args;
162
163       form.TreeParent (ancestor->f_form, args);
164       form.Set (args.Args(), args.NumArgs());
165     }
166 }
167
168 void
169 MapButton::ManageKids()
170 {
171   XtManageChildren (f_kids, f_num_kids);
172   f_num_kids = 0;
173 }
174
175 void
176 MapButton::activate()
177 {
178   f_doc_ptr->retrieve();
179 }
180
181 void
182 MapButton::expand()
183 {
184   if (f_expanded)
185     {
186       f_arrow.ArrowDirection (XmARROW_RIGHT);
187       f_expanded = FALSE;
188     }
189   else
190     {
191       f_arrow.ArrowDirection (XmARROW_DOWN);
192       f_expanded = TRUE;
193       // Create a button for each child.
194       UAS_List<UAS_Common> kids (f_doc_ptr->children());
195       WXawTree tree (XtParent (f_form));
196       for (int i = 0; i < kids.length(); i++)
197         new MapButton (tree, kids[i], this);
198       ON_DEBUG (puts ("managing kids"));
199       MapButton::ManageKids();
200       ON_DEBUG (puts ("calling force layout"));
201       tree.ForceLayout();
202       ON_DEBUG (puts ("called force layout"));
203     }
204 }
205
206
207 void
208 MapButton::destroy()
209 {
210   // Free object memory when the widget is destroyed.
211   // Assumes heap allocation of MapButton objects. 
212   delete this;
213 }
214
215
216 // /////////////////////////////////////////////////////////////////
217 // class constructor
218 // /////////////////////////////////////////////////////////////////
219
220 MapAgent::MapAgent()
221 : f_shell (NULL),
222   f_onscreen (FALSE)
223 {
224 }
225
226
227 // /////////////////////////////////////////////////////////////////
228 // mode - return the current map mode
229 // /////////////////////////////////////////////////////////////////
230
231 MapAgent::map_mode_t
232 MapAgent::mode() const
233 {
234   return (f_map_mode);
235 }
236
237
238 // /////////////////////////////////////////////////////////////////
239 // set_mode - set the map mode
240 // /////////////////////////////////////////////////////////////////
241
242 void
243 MapAgent::set_mode (const map_mode_t mode)
244 {
245   Xassert (mode == LOCAL_MODE || mode == GLOBAL_MODE);
246
247   f_map_mode = mode;
248 }
249
250
251 // /////////////////////////////////////////////////////////////////
252 // can_display - return true if this agent is willing to display
253 // /////////////////////////////////////////////////////////////////
254
255 bool
256 MapAgent::can_display (UAS_Pointer<UAS_Common> &) const
257 {
258   return (TRUE);
259 }
260
261
262 // /////////////////////////////////////////////////////////////////
263 // display - dislay a map localized around the specified document
264 // /////////////////////////////////////////////////////////////////
265
266 void
267 MapAgent::display (UAS_Pointer<UAS_Common> &doc_ptr, bool popup)
268 {
269   static bool first_time = True;
270   u_int i, num_children;
271   MapButton *parent_button, *child_button, *this_button = NULL;
272
273   if (f_shell == NULL)
274     create_ui();
275
276   // Just pop up the window if the map has already been created
277   // for the specified document.
278   if (doc_ptr == f_doc_ptr)
279     {
280       if (popup) {
281         f_shell->Popup();
282         XMapRaised(XtDisplay(*f_shell), XtWindow(*f_shell));
283       }
284       f_onscreen = TRUE;
285       return;
286     }
287
288   // Must have to create a new tree, so start by wiping out the old one. 
289   if (f_tree != NULL)
290     {
291       f_tree->Destroy();
292       delete f_tree;
293     }
294   f_tree = new WXawTree (*f_porthole, "tree");
295   //  f_tree->Realize();
296
297   // Tree gravity should be a preference that is retrieved right here.
298   // (Or better yet stored in the class record.) 
299
300   /* -------- Start the local map at this node's parent. -------- */
301
302   UAS_Pointer<UAS_Common> toc_this = doc_ptr;
303   UAS_Pointer<UAS_Common> toc_parent =
304       (doc_ptr != (UAS_Pointer<UAS_Common>)0)
305           ? doc_ptr->parent() : (UAS_Pointer<UAS_Common>)0;
306
307   // If the entry has a parent, create a button for it and each of
308   // the entry's siblings. 
309   if (toc_parent != (UAS_Pointer<UAS_Common>)NULL)
310     {
311       parent_button = new MapButton (*f_tree, toc_parent, NULL);
312       //  parent_button->expand();
313
314       /* -------- Create a button for each sibling. -------- */
315
316       UAS_List<UAS_Common> kids = toc_parent->children();
317       num_children = kids.length();
318       UAS_Pointer<UAS_Common> toc_kid;
319       for (i = 0; i < num_children; i++)
320         {
321           toc_kid = kids[i];
322           child_button = new MapButton (*f_tree, toc_kid, parent_button);
323           if (toc_kid == doc_ptr)
324             {
325               f_doc_ptr = doc_ptr;
326               this_button = child_button;
327             }
328         }
329     }
330   else // No TOC parent -- SWM: Also may be no TOC!!!
331     {
332       f_doc_ptr = doc_ptr;
333       this_button = new MapButton (*f_tree, toc_this, NULL);
334     }
335
336   if (this_button == NULL)
337     {
338       message_mgr().
339         error_dialog (CATGETS(Set_Messages, 7, "File a Bug"));
340       return;
341     }
342   else
343     {
344       static bool first_time = TRUE;
345       static Pixel highlight_bg, highlight_fg;
346       if (first_time)
347         {
348           const char *s;
349           unsigned long status;
350           s = window_system().get_string_default ("MapHighlightBackground");
351           if (s == NULL || *s == '\0')
352             {
353               highlight_bg = this_button->f_button.Foreground();
354             }
355           else
356             {
357               status = window_system().get_color (s, highlight_bg);
358               // On failure to allocate, just invert. 
359               if (status == 0)
360                 {
361                   highlight_bg = this_button->f_button.Foreground();
362                   highlight_fg = this_button->f_button.Background();
363                 }
364               // Got bg, so now try for fg. 
365               else
366                 {
367                   s = window_system().
368                         get_string_default ("MapHighlightForeground");
369                   if (s == NULL || *s == '\0')
370                     {
371                       highlight_fg =this_button->f_button.Background();
372                     }
373                   else
374                     {
375                       status = window_system().get_color (s, highlight_fg);
376                       // If we cant get both colors, just invert the button. 
377                       if (status == 0)
378                         {
379                           Display *dpy = window_system().display();
380                           XFreeColors (dpy,
381                                        DefaultColormap(dpy,DefaultScreen(dpy)),
382                                        &highlight_bg, 1, 0);
383                           highlight_bg = this_button->f_button.Foreground();
384                           highlight_fg = this_button->f_button.Background();
385                         }
386                     }
387                 }
388             }
389           if (highlight_fg == this_button->f_button.Foreground() ||
390               highlight_bg == this_button->f_button.Background() ||
391               highlight_fg == highlight_bg)
392             {
393               highlight_bg = this_button->f_button.Foreground();
394               highlight_fg = this_button->f_button.Background();
395             }
396           first_time = FALSE;
397         }
398       this_button->f_button.Background (highlight_bg);
399       this_button->f_button.Foreground (highlight_fg);
400       //  this_button->expand();
401     }
402
403   /* -------- Create a button for each child. -------- */
404
405   if (toc_this != (UAS_Pointer<UAS_Common>)NULL)
406     {
407       UAS_List<UAS_Common> myKids = toc_this->children();
408       num_children = myKids.length();
409       for (i = 0; i < num_children; i++)
410         child_button =
411           new MapButton (*f_tree, myKids[i], this_button);
412
413 #if 0
414   if (!XtIsRealized(*f_shell))
415     {
416       f_tree->Manage();
417       f_shell->Realize();
418     }
419 #endif
420
421     }
422   // Manage all the children.
423   MapButton::ManageKids();
424
425   UAS_String buffer = CATGETS(Set_MapAgent, 2, "Dtinfo: ");
426   buffer = buffer + doc_ptr->title();
427   f_shell->Title ((char*)buffer);
428
429   if (!XtIsRealized (*f_shell))
430     f_shell->Realize();
431
432   f_tree->Realize();
433   f_tree->ForceLayout();
434
435   f_min_tree_width = f_tree->Width();
436   f_min_tree_height = f_tree->Height();
437   ON_DEBUG (printf ("+++++ Tree min dims: %d x %d\n",
438                     f_min_tree_width, f_min_tree_height));
439
440   center_on (this_button);
441   f_tree->Manage();
442
443   if (popup)
444     {
445       if (first_time)
446         {
447           WXmForm form (XtParent (XtParent (*f_panner)));
448           form.Height (50);
449           first_time = False;
450         }
451       f_shell->Popup();
452       XMapRaised(XtDisplay(*f_shell), XtWindow(*f_shell));
453     }
454
455   f_onscreen = TRUE;
456 }
457
458
459 // /////////////////////////////////////////////////////////////////
460 // create_ui - create the map user interface
461 // /////////////////////////////////////////////////////////////////
462
463 void
464 MapAgent::create_ui()
465 {
466   MapButton::f_kids_size = 8;
467   MapButton::f_kids = (Widget *)
468                       malloc (sizeof (Widget) * MapButton::f_kids_size);
469   
470   f_shell = new WTopLevelShell (toplevel(), WPopup, "map");
471   window_system().register_shell (f_shell);
472
473   XtVaSetValues(*f_shell, XmNtitle,
474                 CATGETS(Set_MapAgent, 1, "Dtinfo: Local Map"), NULL);
475   WindowGeometry wg = pref_mgr().get_geometry (PrefMgr::MapGeometry);
476   f_shell->Set(WArgList(XmNwidth, wg.width,
477                         XmNheight, wg.height,
478                         NULL));
479
480   // rtp - added new code 8/27/92
481   WXmForm rootform (*f_shell, "rootform");
482
483   WXmForm bottomform (rootform, "bottomform");
484   WXmPushButton close (bottomform, "close", WAutoManage);
485   WXmPushButton help (bottomform, "help", WAutoManage);
486   help_agent().add_activate_help (help, "map_help");
487
488   XtVaSetValues(close, XmNlabelString,
489         (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 12, "Close")), NULL);
490   XtVaSetValues(help, XmNlabelString,
491         (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 48, "Help")), NULL);
492
493   WXmPanedWindow pane (rootform, "pane");
494   WXmForm topform (pane, "topform");
495   XtVaSetValues(topform, XmNheight, 75, NULL);
496   XtVaSetValues(pane, XmNpaneMinimum, 75, XmNpositionIndex, 1, NULL);
497
498   WXmFrame panner_frame (topform, "pframe", WAutoManage);
499   f_panner = new WXawPanner (panner_frame, "panner", WAutoManage);
500   WXmFrame tree_frame (pane, "tframe", WAutoManage);
501   f_porthole = new WXawPorthole (tree_frame, "porthole");
502
503   f_lock = new WXmToggleButton (topform, "lock", WAutoManage);
504   XtVaSetValues(*f_lock, XmNlabelString,
505      (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 196, "Auto Update")),
506                          XmNindicatorSize, 15, NULL);
507   bool lock_status = pref_mgr().get_boolean (PrefMgr::MapAutoUpdate);
508   f_lock->Set(lock_status);
509   f_locked = lock_status ;
510   // NOTE: Should have a way to remove displayer so that receive function
511   // isn't called every time a node is displayed.  14:08 12-Oct-93 DJB 
512   UAS_Common::request ((UAS_Receiver<UAS_DocumentRetrievedMsg> *) this);
513
514   f_lock->SetValueChangedCallback(this, (WWL_FUN) &MapAgent::lock_toggle);
515   f_porthole->SetReportCallback (this, (WWL_FUN) &MapAgent::porthole_resize);
516   f_panner->SetReportCallback (this, (WWL_FUN) &MapAgent::panner_movement);
517
518   bottomform.Manage();
519   
520   Dimension height;
521   f_lock->Get (WArgList (XmNheight, (XtArgVal)&height, NULL));
522   topform.Set(WArgList(XmNpaneMinimum, height, NULL));
523
524   topform.Manage();
525   f_porthole->Manage();
526   pane.Manage();
527
528   /* -------- Callbacks -------- */
529   f_wm_delete_callback =
530     new WCallback (*f_shell, window_system().WM_DELETE_WINDOW(),
531                    this, (WWL_FUN) &MapAgent::close_window);
532   close.SetActivateCallback (this, (WWL_FUN) &MapAgent::close_window);
533
534   rootform.Manage();
535
536   //  f_shell->Realize();
537
538   f_tree = NULL;
539 }
540
541
542 // /////////////////////////////////////////////////////////////////
543 // porthole_resize
544 // /////////////////////////////////////////////////////////////////
545
546 void
547 MapAgent::porthole_resize (WCallback *wcb)
548 {
549   WArgList args;
550   XawPannerReport *rep = (XawPannerReport *) wcb->CallData();
551
552   ON_DEBUG (printf (">>> Porthole resize, mtw = %d x %d\n",
553                     f_min_tree_width, f_min_tree_height));
554
555   // Don't let the tree widget get bigger that the space needed
556   // to hold the tree when it can't fit in the porthole.  If we
557   // allow this, the user could grow the tree to a large size
558   // by enlarging the map window, then shrink the map window and
559   // keep the tree at the large size and pan to empty space. 
560   if (rep->changed & ~(XawPRSliderX | XawPRSliderY))
561     {
562       Dimension twidth, theight;
563
564       twidth = f_tree->Width();
565       theight = f_tree->Height();
566       ON_DEBUG (printf ("Tree attempts width = %d, height = %d\n",
567                         twidth, theight));
568       if ((twidth > f_min_tree_width && twidth > f_porthole->Width()) ||
569           (theight > f_min_tree_height && theight > f_porthole->Height()))
570         {
571           f_tree->Width(f_min_tree_width, args);
572           f_tree->Height(f_min_tree_height, args);
573           ON_DEBUG (puts ("Adjusting tree"));
574           f_tree->Set (args);
575           ON_DEBUG (puts ("... Done adjusting tree"));
576           return;
577         }
578     }
579      
580   ON_DEBUG (printf (">>> Porthole resize (%d, %d, %d, %d, %d, %d)\n",
581                     rep->slider_x, rep->slider_y,
582                     rep->slider_width, rep->slider_height,
583                     rep->canvas_width, rep->canvas_height));
584   f_panner->SliderX (rep->slider_x, args);
585   f_panner->SliderY (rep->slider_y, args);
586   if (rep->changed & ~(XawPRSliderX | XawPRSliderY))
587     {
588       ON_DEBUG (printf (".....width & height change\n"));
589       f_panner->SliderWidth (rep->slider_width, args);
590       f_panner->SliderHeight (rep->slider_height, args);
591       f_panner->CanvasWidth (rep->canvas_width, args);
592       f_panner->CanvasHeight (rep->canvas_height, args);
593     }
594   f_panner->Set (args);
595 }
596
597
598 // /////////////////////////////////////////////////////////////////
599 // panner_movement
600 // /////////////////////////////////////////////////////////////////
601
602 void
603 MapAgent::panner_movement (WCallback *wcb)
604 {
605   WArgList args;
606   XawPannerReport *rep = (XawPannerReport *) wcb->CallData();
607
608   f_tree->X (-rep->slider_x, args);
609   f_tree->Y (-rep->slider_y, args);
610   f_tree->Set (args);
611 }
612
613
614 // /////////////////////////////////////////////////////////////////
615 // close_window
616 // /////////////////////////////////////////////////////////////////
617
618 void
619 MapAgent::close_window (WCallback *)
620 {
621   f_shell->Popdown();
622   f_onscreen = FALSE;
623 }
624
625 // /////////////////////////////////////////////////////////////////
626 // lock_toggle - callback for lock button
627 // /////////////////////////////////////////////////////////////////
628
629 void 
630 MapAgent::lock_toggle (WCallback *wcb)
631 {
632   ON_DEBUG(cerr << "lock toggle callback" << endl);
633
634   XmToggleButtonCallbackStruct &cbs =
635     *(XmToggleButtonCallbackStruct*) wcb->CallData();
636
637   f_locked = cbs.set;
638 }
639
640 // /////////////////////////////////////////////////////////////////
641 // can_update - return true if this agent is willing to update
642 // /////////////////////////////////////////////////////////////////
643
644 bool
645 MapAgent::can_update()
646 {
647   return (f_onscreen);
648 }
649
650 // /////////////////////////////////////////////////////////////////////////
651 // lock - set the lock
652 // /////////////////////////////////////////////////////////////////////////
653
654 void
655 MapAgent::lock()
656 {
657   f_locked = TRUE;
658   f_lock->Set(TRUE);
659 }
660
661 // /////////////////////////////////////////////////////////////////////////
662 // unlock - unset the lock
663 // /////////////////////////////////////////////////////////////////////////
664 void
665 MapAgent::unlock()
666 {
667   f_locked = FALSE ;
668   f_lock->Set(False);
669 }
670
671 // /////////////////////////////////////////////////////////////////
672 // center_on - center current node in tree view
673 // /////////////////////////////////////////////////////////////////
674
675 void
676 MapAgent::center_on (MapButton *map_button)
677 {
678   // WXmPushButton button = map_button->f_button;
679   WXmForm &button = map_button->f_form;
680   WArgList args;
681   Position bcenter_x, bcenter_y;
682   Position pcenter_x, pcenter_y;
683   Dimension pwidth, pheight;
684   Dimension twidth, theight;
685   Position off_x = 0, off_y = 0;
686
687   bcenter_x = button.X() + button.Width() / 2;
688   bcenter_y = button.Y() + button.Height() / 2;
689   ON_DEBUG (printf ("Form widget id = %p\n", (Widget) button));
690   ON_DEBUG (printf ("Button realized = %d\n", XtIsRealized (button)));
691   ON_DEBUG (printf ("Button coords = (%d,%d)\n", button.X(), button.Y()));
692   ON_DEBUG (printf("Button dims = (%d,%d)\n", button.Width(),button.Height()));
693   ON_DEBUG (printf ("Button center = (%d,%d)\n", bcenter_x, bcenter_y));
694
695   pwidth = f_porthole->Width();
696   pheight = f_porthole->Height();
697   twidth = f_tree->Width();
698   theight = f_tree->Height();
699   ON_DEBUG (printf ("Porthole dimensions = (%d,%d)\n", pwidth, pheight));
700   ON_DEBUG (printf ("Tree dimensions = (%d,%d)\n", twidth, theight));
701
702   pcenter_x = f_porthole->X() + pwidth / 2;
703   pcenter_y = f_porthole->Y() + pheight / 2;
704   ON_DEBUG (printf ("Porthole center = (%d,%d)\n", pcenter_x, pcenter_y));
705
706   if (bcenter_x > pcenter_x)
707     off_x = pcenter_x - bcenter_x;
708
709   if (bcenter_y > pcenter_y)
710     off_y = pcenter_y - bcenter_y;
711
712   if (off_x + twidth < pwidth)
713     off_x = pwidth - twidth;
714
715   if (off_y + theight < pheight)
716     off_y = pheight - theight;
717
718   ON_DEBUG (printf ("Button center offset = (%d,%d)\n", off_x, off_y));
719
720   if (off_x < 0)
721     {
722       f_tree->X (off_x, args);
723       ON_DEBUG (printf ("Setting Tree X to %d\n", off_x));
724     }
725
726   if (off_y < 0)
727     {
728       f_tree->Y (off_y, args);
729       ON_DEBUG (printf ("Setting Tree Y to %d\n", off_y));
730     }
731
732   if (args.NumArgs() > 0)
733     f_tree->Set (args);
734 }
735
736
737 // /////////////////////////////////////////////////////////////////
738 // receive - handle node display messages
739 // /////////////////////////////////////////////////////////////////
740
741 void
742 MapAgent::receive (UAS_DocumentRetrievedMsg &message, void* /*client_data*/)
743 {
744   extern bool g_style_sheet_update ;
745   ON_DEBUG (printf ("MapAgent::receive - updating the map!\n"));
746   if (f_locked && f_onscreen && !g_style_sheet_update)
747     {
748       // MapAgent::receive is just for automatic self-update, so
749       // there's no need for mapping/raising the window.
750       display (message.fDoc, FALSE);
751     }
752 }
753
754 void
755 MapAgent::clear_map(UAS_Pointer<UAS_Common> &lib)
756 {
757   if(lib->lid() == f_doc_ptr->lid())
758   {
759     clear_it();
760     f_doc_ptr = NULL;
761   }
762 }
763
764 void
765 MapAgent::clear_it()
766 {
767   if ((f_tree != NULL) && f_onscreen)
768   {
769     f_tree->Destroy();
770     delete f_tree;
771     f_tree = NULL;
772   }
773 }