2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* Copyright (c) 1994,1995,1996 FUJITSU LIMITED */
24 /* All Rights Reserved */
27 * $TOG: MapAgentMotif.C /main/16 1998/04/17 11:33:40 mgreess $
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.
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.
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
52 #define C_WindowSystem
60 #define C_WindowGeometryPref
69 #include "Other/XmStringLocalized.hh"
70 #include "Managers/CatMgr.hh"
72 #include "Registration.hh"
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>
83 #include "Widgets/WXawPorthole.h"
84 #include "Widgets/WXawPanner.h"
85 #include "Widgets/WXawTree.h"
87 #define CLASS MapButton
88 #include "create_macros.hh"
90 class MapButton : public WWL
93 MapButton (WComposite &parent, const UAS_Pointer<UAS_Common> &doc_ptr,
95 virtual ~MapButton() {}
102 WXmPushButton f_button;
103 WXmArrowButton f_arrow;
104 UAS_Pointer<UAS_Common> f_doc_ptr;
107 static void ManageKids();
108 static Widget *f_kids;
109 static int f_num_kids;
110 static int f_kids_size;
113 Widget *MapButton::f_kids;
114 int MapButton::f_num_kids;
115 int MapButton::f_kids_size;
117 MapButton::MapButton (WComposite &parent,
118 const UAS_Pointer<UAS_Common> &doc_ptr,
120 : f_form (parent, "form"),
124 ON_DEBUG (printf ("MapButton::MapButton (%s)\n", (char*)f_doc_ptr->title()));
125 static bool expandable_tree =
126 window_system().get_boolean_default ("ExpandableMap");
127 UAS_List<UAS_Common> kids (f_doc_ptr->children());
128 UAS_String t = f_doc_ptr->title();
129 if (kids.length() > 0 && expandable_tree)
131 f_arrow = WXmArrowButton (f_form, "expand", WAutoManage);
132 ON_ACTIVATE (f_arrow,expand);
134 WXmPushButton (f_form, t, WAutoManage,
135 WArgList (XmNrightWidget, (XtArgVal) ((Widget) f_arrow),
136 XmNrightAttachment, XmATTACH_WIDGET,
141 f_button = WXmPushButton (f_form, t, WAutoManage);
144 ON_ACTIVATE (f_button,activate);
145 SET_CALLBACK (f_form,Destroy,destroy);
147 f_form.ShadowThickness (0);
150 // Add to the list so that we can manage 'em all at once.
151 if (f_num_kids + 1 > f_kids_size)
154 f_kids = (Widget *) realloc (f_kids, sizeof (Widget) * f_kids_size);
156 f_kids[f_num_kids++] = (Widget) f_form;
157 ON_DEBUG (printf ("Form managed = %d\n", XtIsManaged (f_form)));
159 if (ancestor != NULL)
161 CXawTree form (f_form);
164 form.TreeParent (ancestor->f_form, args);
165 form.Set (args.Args(), args.NumArgs());
170 MapButton::ManageKids()
172 XtManageChildren (f_kids, f_num_kids);
177 MapButton::activate()
179 f_doc_ptr->retrieve();
187 f_arrow.ArrowDirection (XmARROW_RIGHT);
192 f_arrow.ArrowDirection (XmARROW_DOWN);
194 // Create a button for each child.
195 UAS_List<UAS_Common> kids (f_doc_ptr->children());
196 WXawTree tree (XtParent (f_form));
197 for (unsigned int i = 0; i < kids.length(); i++)
198 new MapButton (tree, kids[i], this);
199 ON_DEBUG (puts ("managing kids"));
200 MapButton::ManageKids();
201 ON_DEBUG (puts ("calling force layout"));
203 ON_DEBUG (puts ("called force layout"));
211 // Free object memory when the widget is destroyed.
212 // Assumes heap allocation of MapButton objects.
217 // /////////////////////////////////////////////////////////////////
219 // /////////////////////////////////////////////////////////////////
223 f_map_mode(LOCAL_MODE),
228 f_wm_delete_callback(NULL),
237 // /////////////////////////////////////////////////////////////////
238 // mode - return the current map mode
239 // /////////////////////////////////////////////////////////////////
242 MapAgent::mode() const
248 // /////////////////////////////////////////////////////////////////
249 // set_mode - set the map mode
250 // /////////////////////////////////////////////////////////////////
253 MapAgent::set_mode (const map_mode_t mode)
255 Xassert (mode == LOCAL_MODE || mode == GLOBAL_MODE);
261 // /////////////////////////////////////////////////////////////////
262 // can_display - return true if this agent is willing to display
263 // /////////////////////////////////////////////////////////////////
266 MapAgent::can_display (UAS_Pointer<UAS_Common> &) const
272 // /////////////////////////////////////////////////////////////////
273 // display - dislay a map localized around the specified document
274 // /////////////////////////////////////////////////////////////////
277 MapAgent::display (UAS_Pointer<UAS_Common> &doc_ptr, bool popup)
279 static bool first_time = True;
280 u_int i, num_children;
281 MapButton *parent_button, *child_button, *this_button = NULL;
286 // Just pop up the window if the map has already been created
287 // for the specified document.
288 if (doc_ptr == f_doc_ptr)
292 XMapRaised(XtDisplay(*f_shell), XtWindow(*f_shell));
298 // Must have to create a new tree, so start by wiping out the old one.
304 f_tree = new WXawTree (*f_porthole, "tree");
305 // f_tree->Realize();
307 // Tree gravity should be a preference that is retrieved right here.
308 // (Or better yet stored in the class record.)
310 /* -------- Start the local map at this node's parent. -------- */
312 UAS_Pointer<UAS_Common> toc_this = doc_ptr;
313 UAS_Pointer<UAS_Common> toc_parent =
314 (doc_ptr != (UAS_Pointer<UAS_Common>)0)
315 ? doc_ptr->parent() : (UAS_Pointer<UAS_Common>)0;
317 // If the entry has a parent, create a button for it and each of
318 // the entry's siblings.
319 if (toc_parent != (UAS_Pointer<UAS_Common>)NULL)
321 parent_button = new MapButton (*f_tree, toc_parent, NULL);
322 // parent_button->expand();
324 /* -------- Create a button for each sibling. -------- */
326 UAS_List<UAS_Common> kids = toc_parent->children();
327 num_children = kids.length();
328 UAS_Pointer<UAS_Common> toc_kid;
329 for (i = 0; i < num_children; i++)
332 child_button = new MapButton (*f_tree, toc_kid, parent_button);
333 if (toc_kid == doc_ptr)
336 this_button = child_button;
340 else // No TOC parent -- SWM: Also may be no TOC!!!
343 this_button = new MapButton (*f_tree, toc_this, NULL);
346 if (this_button == NULL)
349 error_dialog (CATGETS(Set_Messages, 7, "File a Bug"));
354 static bool first_time = TRUE;
355 static Pixel highlight_bg, highlight_fg;
359 unsigned long status;
360 s = window_system().get_string_default ("MapHighlightBackground");
361 if (s == NULL || *s == '\0')
363 highlight_bg = this_button->f_button.Foreground();
367 status = window_system().get_color (s, highlight_bg);
368 // On failure to allocate, just invert.
371 highlight_bg = this_button->f_button.Foreground();
372 highlight_fg = this_button->f_button.Background();
374 // Got bg, so now try for fg.
378 get_string_default ("MapHighlightForeground");
379 if (s == NULL || *s == '\0')
381 highlight_fg =this_button->f_button.Background();
385 status = window_system().get_color (s, highlight_fg);
386 // If we cant get both colors, just invert the button.
389 Display *dpy = window_system().display();
391 DefaultColormap(dpy,DefaultScreen(dpy)),
392 &highlight_bg, 1, 0);
393 highlight_bg = this_button->f_button.Foreground();
394 highlight_fg = this_button->f_button.Background();
399 if (highlight_fg == this_button->f_button.Foreground() ||
400 highlight_bg == this_button->f_button.Background() ||
401 highlight_fg == highlight_bg)
403 highlight_bg = this_button->f_button.Foreground();
404 highlight_fg = this_button->f_button.Background();
408 this_button->f_button.Background (highlight_bg);
409 this_button->f_button.Foreground (highlight_fg);
410 // this_button->expand();
413 /* -------- Create a button for each child. -------- */
415 if (toc_this != (UAS_Pointer<UAS_Common>)NULL)
417 UAS_List<UAS_Common> myKids = toc_this->children();
418 num_children = myKids.length();
419 for (i = 0; i < num_children; i++)
421 new MapButton (*f_tree, myKids[i], this_button);
424 if (!XtIsRealized(*f_shell))
432 // Manage all the children.
433 MapButton::ManageKids();
435 UAS_String buffer = CATGETS(Set_MapAgent, 2, "Dtinfo: ");
436 buffer = buffer + doc_ptr->title();
437 f_shell->Title ((char*)buffer);
439 if (!XtIsRealized (*f_shell))
443 f_tree->ForceLayout();
445 f_min_tree_width = f_tree->Width();
446 f_min_tree_height = f_tree->Height();
447 ON_DEBUG (printf ("+++++ Tree min dims: %d x %d\n",
448 f_min_tree_width, f_min_tree_height));
450 center_on (this_button);
457 WXmForm form (XtParent (XtParent (*f_panner)));
462 XMapRaised(XtDisplay(*f_shell), XtWindow(*f_shell));
469 // /////////////////////////////////////////////////////////////////
470 // create_ui - create the map user interface
471 // /////////////////////////////////////////////////////////////////
474 MapAgent::create_ui()
476 MapButton::f_kids_size = 8;
477 MapButton::f_kids = (Widget *)
478 malloc (sizeof (Widget) * MapButton::f_kids_size);
480 f_shell = new WTopLevelShell (toplevel(), WPopup, "map");
481 window_system().register_shell (f_shell);
483 XtVaSetValues(*f_shell, XmNtitle,
484 CATGETS(Set_MapAgent, 1, "Dtinfo: Local Map"), NULL);
485 WindowGeometry wg = pref_mgr().get_geometry (PrefMgr::MapGeometry);
486 f_shell->Set(WArgList(XmNwidth, wg.width,
487 XmNheight, wg.height,
490 // rtp - added new code 8/27/92
491 WXmForm rootform (*f_shell, "rootform");
493 WXmForm bottomform (rootform, "bottomform");
494 WXmPushButton close (bottomform, "close", WAutoManage);
495 WXmPushButton help (bottomform, "help", WAutoManage);
496 help_agent().add_activate_help (help, (char*)"map_help");
498 XtVaSetValues(close, XmNlabelString,
499 (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 12, "Close")), NULL);
500 XtVaSetValues(help, XmNlabelString,
501 (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 48, "Help")), NULL);
503 WXmPanedWindow pane (rootform, "pane");
504 WXmForm topform (pane, "topform");
505 XtVaSetValues(topform, XmNheight, 75, NULL);
506 XtVaSetValues(pane, XmNpaneMinimum, 75, XmNpositionIndex, 1, NULL);
508 WXmFrame panner_frame (topform, "pframe", WAutoManage);
509 f_panner = new WXawPanner (panner_frame, "panner", WAutoManage);
510 WXmFrame tree_frame (pane, "tframe", WAutoManage);
511 f_porthole = new WXawPorthole (tree_frame, "porthole");
513 f_lock = new WXmToggleButton (topform, "lock", WAutoManage);
514 XtVaSetValues(*f_lock, XmNlabelString,
515 (XmString)XmStringLocalized(CATGETS(Set_AgentLabel, 196, "Auto Update")),
516 XmNindicatorSize, 15, NULL);
517 bool lock_status = pref_mgr().get_boolean (PrefMgr::MapAutoUpdate);
518 f_lock->Set(lock_status);
519 f_locked = lock_status ;
520 // NOTE: Should have a way to remove displayer so that receive function
521 // isn't called every time a node is displayed. 14:08 12-Oct-93 DJB
522 UAS_Common::request ((UAS_Receiver<UAS_DocumentRetrievedMsg> *) this);
524 f_lock->SetValueChangedCallback(this, (WWL_FUN) &MapAgent::lock_toggle);
525 f_porthole->SetReportCallback (this, (WWL_FUN) &MapAgent::porthole_resize);
526 f_panner->SetReportCallback (this, (WWL_FUN) &MapAgent::panner_movement);
531 f_lock->Get (WArgList (XmNheight, (XtArgVal)&height, NULL));
532 topform.Set(WArgList(XmNpaneMinimum, height, NULL));
535 f_porthole->Manage();
538 /* -------- Callbacks -------- */
539 f_wm_delete_callback =
540 new WCallback (*f_shell, window_system().WM_DELETE_WINDOW(),
541 this, (WWL_FUN) &MapAgent::close_window);
542 close.SetActivateCallback (this, (WWL_FUN) &MapAgent::close_window);
546 // f_shell->Realize();
552 // /////////////////////////////////////////////////////////////////
554 // /////////////////////////////////////////////////////////////////
557 MapAgent::porthole_resize (WCallback *wcb)
560 XawPannerReport *rep = (XawPannerReport *) wcb->CallData();
562 ON_DEBUG (printf (">>> Porthole resize, mtw = %d x %d\n",
563 f_min_tree_width, f_min_tree_height));
565 // Don't let the tree widget get bigger that the space needed
566 // to hold the tree when it can't fit in the porthole. If we
567 // allow this, the user could grow the tree to a large size
568 // by enlarging the map window, then shrink the map window and
569 // keep the tree at the large size and pan to empty space.
570 if (rep->changed & ~(XawPRSliderX | XawPRSliderY))
572 Dimension twidth, theight;
574 twidth = f_tree->Width();
575 theight = f_tree->Height();
576 ON_DEBUG (printf ("Tree attempts width = %d, height = %d\n",
578 if ((twidth > f_min_tree_width && twidth > f_porthole->Width()) ||
579 (theight > f_min_tree_height && theight > f_porthole->Height()))
581 f_tree->Width(f_min_tree_width, args);
582 f_tree->Height(f_min_tree_height, args);
583 ON_DEBUG (puts ("Adjusting tree"));
585 ON_DEBUG (puts ("... Done adjusting tree"));
590 ON_DEBUG (printf (">>> Porthole resize (%d, %d, %d, %d, %d, %d)\n",
591 rep->slider_x, rep->slider_y,
592 rep->slider_width, rep->slider_height,
593 rep->canvas_width, rep->canvas_height));
594 f_panner->SliderX (rep->slider_x, args);
595 f_panner->SliderY (rep->slider_y, args);
596 if (rep->changed & ~(XawPRSliderX | XawPRSliderY))
598 ON_DEBUG (printf (".....width & height change\n"));
599 f_panner->SliderWidth (rep->slider_width, args);
600 f_panner->SliderHeight (rep->slider_height, args);
601 f_panner->CanvasWidth (rep->canvas_width, args);
602 f_panner->CanvasHeight (rep->canvas_height, args);
604 f_panner->Set (args);
608 // /////////////////////////////////////////////////////////////////
610 // /////////////////////////////////////////////////////////////////
613 MapAgent::panner_movement (WCallback *wcb)
616 XawPannerReport *rep = (XawPannerReport *) wcb->CallData();
618 f_tree->X (-rep->slider_x, args);
619 f_tree->Y (-rep->slider_y, args);
624 // /////////////////////////////////////////////////////////////////
626 // /////////////////////////////////////////////////////////////////
629 MapAgent::close_window (WCallback *)
635 // /////////////////////////////////////////////////////////////////
636 // lock_toggle - callback for lock button
637 // /////////////////////////////////////////////////////////////////
640 MapAgent::lock_toggle (WCallback *wcb)
642 ON_DEBUG(cerr << "lock toggle callback" << endl);
644 XmToggleButtonCallbackStruct &cbs =
645 *(XmToggleButtonCallbackStruct*) wcb->CallData();
650 // /////////////////////////////////////////////////////////////////
651 // can_update - return true if this agent is willing to update
652 // /////////////////////////////////////////////////////////////////
655 MapAgent::can_update()
660 // /////////////////////////////////////////////////////////////////////////
661 // lock - set the lock
662 // /////////////////////////////////////////////////////////////////////////
671 // /////////////////////////////////////////////////////////////////////////
672 // unlock - unset the lock
673 // /////////////////////////////////////////////////////////////////////////
681 // /////////////////////////////////////////////////////////////////
682 // center_on - center current node in tree view
683 // /////////////////////////////////////////////////////////////////
686 MapAgent::center_on (MapButton *map_button)
688 // WXmPushButton button = map_button->f_button;
689 WXmForm &button = map_button->f_form;
691 Position bcenter_x, bcenter_y;
692 Position pcenter_x, pcenter_y;
693 Dimension pwidth, pheight;
694 Dimension twidth, theight;
695 Position off_x = 0, off_y = 0;
697 bcenter_x = button.X() + button.Width() / 2;
698 bcenter_y = button.Y() + button.Height() / 2;
699 ON_DEBUG (printf ("Form widget id = %p\n", (Widget) button));
700 ON_DEBUG (printf ("Button realized = %d\n", XtIsRealized (button)));
701 ON_DEBUG (printf ("Button coords = (%d,%d)\n", button.X(), button.Y()));
702 ON_DEBUG (printf("Button dims = (%d,%d)\n", button.Width(),button.Height()));
703 ON_DEBUG (printf ("Button center = (%d,%d)\n", bcenter_x, bcenter_y));
705 pwidth = f_porthole->Width();
706 pheight = f_porthole->Height();
707 twidth = f_tree->Width();
708 theight = f_tree->Height();
709 ON_DEBUG (printf ("Porthole dimensions = (%d,%d)\n", pwidth, pheight));
710 ON_DEBUG (printf ("Tree dimensions = (%d,%d)\n", twidth, theight));
712 pcenter_x = f_porthole->X() + pwidth / 2;
713 pcenter_y = f_porthole->Y() + pheight / 2;
714 ON_DEBUG (printf ("Porthole center = (%d,%d)\n", pcenter_x, pcenter_y));
716 if (bcenter_x > pcenter_x)
717 off_x = pcenter_x - bcenter_x;
719 if (bcenter_y > pcenter_y)
720 off_y = pcenter_y - bcenter_y;
722 if (off_x + twidth < pwidth)
723 off_x = pwidth - twidth;
725 if (off_y + theight < pheight)
726 off_y = pheight - theight;
728 ON_DEBUG (printf ("Button center offset = (%d,%d)\n", off_x, off_y));
732 f_tree->X (off_x, args);
733 ON_DEBUG (printf ("Setting Tree X to %d\n", off_x));
738 f_tree->Y (off_y, args);
739 ON_DEBUG (printf ("Setting Tree Y to %d\n", off_y));
742 if (args.NumArgs() > 0)
747 // /////////////////////////////////////////////////////////////////
748 // receive - handle node display messages
749 // /////////////////////////////////////////////////////////////////
752 MapAgent::receive (UAS_DocumentRetrievedMsg &message, void* /*client_data*/)
754 extern bool g_style_sheet_update ;
755 ON_DEBUG (printf ("MapAgent::receive - updating the map!\n"));
756 if (f_locked && f_onscreen && !g_style_sheet_update)
758 // MapAgent::receive is just for automatic self-update, so
759 // there's no need for mapping/raising the window.
760 display (message.fDoc, FALSE);
765 MapAgent::clear_map(UAS_Pointer<UAS_Common> &lib)
767 if(lib->lid() == f_doc_ptr->lid())
777 if ((f_tree != NULL) && f_onscreen)