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 librararies 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,
101 WXmPushButton f_button;
102 WXmArrowButton f_arrow;
103 UAS_Pointer<UAS_Common> f_doc_ptr;
106 static void ManageKids();
107 static Widget *f_kids;
108 static int f_num_kids;
109 static int f_kids_size;
112 Widget *MapButton::f_kids;
113 int MapButton::f_num_kids;
114 int MapButton::f_kids_size;
116 MapButton::MapButton (WComposite &parent,
117 const UAS_Pointer<UAS_Common> &doc_ptr,
119 : f_form (parent, "form"),
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)
130 f_arrow = WXmArrowButton (f_form, "expand", WAutoManage);
131 ON_ACTIVATE (f_arrow,expand);
133 WXmPushButton (f_form, t, WAutoManage,
134 WArgList (XmNrightWidget, (XtArgVal) ((Widget) f_arrow),
135 XmNrightAttachment, XmATTACH_WIDGET,
140 f_button = WXmPushButton (f_form, t, WAutoManage);
143 ON_ACTIVATE (f_button,activate);
144 SET_CALLBACK (f_form,Destroy,destroy);
146 f_form.ShadowThickness (0);
149 // Add to the list so that we can manage 'em all at once.
150 if (f_num_kids + 1 > f_kids_size)
153 f_kids = (Widget *) realloc (f_kids, sizeof (Widget) * f_kids_size);
155 f_kids[f_num_kids++] = (Widget) f_form;
156 ON_DEBUG (printf ("Form managed = %d\n", XtIsManaged (f_form)));
158 if (ancestor != NULL)
160 CXawTree form (f_form);
163 form.TreeParent (ancestor->f_form, args);
164 form.Set (args.Args(), args.NumArgs());
169 MapButton::ManageKids()
171 XtManageChildren (f_kids, f_num_kids);
176 MapButton::activate()
178 f_doc_ptr->retrieve();
186 f_arrow.ArrowDirection (XmARROW_RIGHT);
191 f_arrow.ArrowDirection (XmARROW_DOWN);
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"));
202 ON_DEBUG (puts ("called force layout"));
210 // Free object memory when the widget is destroyed.
211 // Assumes heap allocation of MapButton objects.
216 // /////////////////////////////////////////////////////////////////
218 // /////////////////////////////////////////////////////////////////
227 // /////////////////////////////////////////////////////////////////
228 // mode - return the current map mode
229 // /////////////////////////////////////////////////////////////////
232 MapAgent::mode() const
238 // /////////////////////////////////////////////////////////////////
239 // set_mode - set the map mode
240 // /////////////////////////////////////////////////////////////////
243 MapAgent::set_mode (const map_mode_t mode)
245 Xassert (mode == LOCAL_MODE || mode == GLOBAL_MODE);
251 // /////////////////////////////////////////////////////////////////
252 // can_display - return true if this agent is willing to display
253 // /////////////////////////////////////////////////////////////////
256 MapAgent::can_display (UAS_Pointer<UAS_Common> &) const
262 // /////////////////////////////////////////////////////////////////
263 // display - dislay a map localized around the specified document
264 // /////////////////////////////////////////////////////////////////
267 MapAgent::display (UAS_Pointer<UAS_Common> &doc_ptr, bool popup)
269 static bool first_time = True;
270 u_int i, num_children;
271 MapButton *parent_button, *child_button, *this_button = NULL;
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)
282 XMapRaised(XtDisplay(*f_shell), XtWindow(*f_shell));
288 // Must have to create a new tree, so start by wiping out the old one.
294 f_tree = new WXawTree (*f_porthole, "tree");
295 // f_tree->Realize();
297 // Tree gravity should be a preference that is retrieved right here.
298 // (Or better yet stored in the class record.)
300 /* -------- Start the local map at this node's parent. -------- */
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;
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)
311 parent_button = new MapButton (*f_tree, toc_parent, NULL);
312 // parent_button->expand();
314 /* -------- Create a button for each sibling. -------- */
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++)
322 child_button = new MapButton (*f_tree, toc_kid, parent_button);
323 if (toc_kid == doc_ptr)
326 this_button = child_button;
330 else // No TOC parent -- SWM: Also may be no TOC!!!
333 this_button = new MapButton (*f_tree, toc_this, NULL);
336 if (this_button == NULL)
339 error_dialog (CATGETS(Set_Messages, 7, "File a Bug"));
344 static bool first_time = TRUE;
345 static Pixel highlight_bg, highlight_fg;
349 unsigned long status;
350 s = window_system().get_string_default ("MapHighlightBackground");
351 if (s == NULL || *s == '\0')
353 highlight_bg = this_button->f_button.Foreground();
357 status = window_system().get_color (s, highlight_bg);
358 // On failure to allocate, just invert.
361 highlight_bg = this_button->f_button.Foreground();
362 highlight_fg = this_button->f_button.Background();
364 // Got bg, so now try for fg.
368 get_string_default ("MapHighlightForeground");
369 if (s == NULL || *s == '\0')
371 highlight_fg =this_button->f_button.Background();
375 status = window_system().get_color (s, highlight_fg);
376 // If we cant get both colors, just invert the button.
379 Display *dpy = window_system().display();
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();
389 if (highlight_fg == this_button->f_button.Foreground() ||
390 highlight_bg == this_button->f_button.Background() ||
391 highlight_fg == highlight_bg)
393 highlight_bg = this_button->f_button.Foreground();
394 highlight_fg = this_button->f_button.Background();
398 this_button->f_button.Background (highlight_bg);
399 this_button->f_button.Foreground (highlight_fg);
400 // this_button->expand();
403 /* -------- Create a button for each child. -------- */
405 if (toc_this != (UAS_Pointer<UAS_Common>)NULL)
407 UAS_List<UAS_Common> myKids = toc_this->children();
408 num_children = myKids.length();
409 for (i = 0; i < num_children; i++)
411 new MapButton (*f_tree, myKids[i], this_button);
414 if (!XtIsRealized(*f_shell))
422 // Manage all the children.
423 MapButton::ManageKids();
425 UAS_String buffer = CATGETS(Set_MapAgent, 2, "Dtinfo: ");
426 buffer = buffer + doc_ptr->title();
427 f_shell->Title ((char*)buffer);
429 if (!XtIsRealized (*f_shell))
433 f_tree->ForceLayout();
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));
440 center_on (this_button);
447 WXmForm form (XtParent (XtParent (*f_panner)));
452 XMapRaised(XtDisplay(*f_shell), XtWindow(*f_shell));
459 // /////////////////////////////////////////////////////////////////
460 // create_ui - create the map user interface
461 // /////////////////////////////////////////////////////////////////
464 MapAgent::create_ui()
466 MapButton::f_kids_size = 8;
467 MapButton::f_kids = (Widget *)
468 malloc (sizeof (Widget) * MapButton::f_kids_size);
470 f_shell = new WTopLevelShell (toplevel(), WPopup, "map");
471 window_system().register_shell (f_shell);
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,
480 // rtp - added new code 8/27/92
481 WXmForm rootform (*f_shell, "rootform");
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");
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);
493 WXmPanedWindow pane (rootform, "pane");
494 WXmForm topform (pane, "topform");
495 XtVaSetValues(topform, XmNheight, 75, NULL);
496 XtVaSetValues(pane, XmNpaneMinimum, 75, XmNpositionIndex, 1, NULL);
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");
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);
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);
521 f_lock->Get (WArgList (XmNheight, (XtArgVal)&height, NULL));
522 topform.Set(WArgList(XmNpaneMinimum, height, NULL));
525 f_porthole->Manage();
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);
536 // f_shell->Realize();
542 // /////////////////////////////////////////////////////////////////
544 // /////////////////////////////////////////////////////////////////
547 MapAgent::porthole_resize (WCallback *wcb)
550 XawPannerReport *rep = (XawPannerReport *) wcb->CallData();
552 ON_DEBUG (printf (">>> Porthole resize, mtw = %d x %d\n",
553 f_min_tree_width, f_min_tree_height));
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))
562 Dimension twidth, theight;
564 twidth = f_tree->Width();
565 theight = f_tree->Height();
566 ON_DEBUG (printf ("Tree attempts width = %d, height = %d\n",
568 if ((twidth > f_min_tree_width && twidth > f_porthole->Width()) ||
569 (theight > f_min_tree_height && theight > f_porthole->Height()))
571 f_tree->Width(f_min_tree_width, args);
572 f_tree->Height(f_min_tree_height, args);
573 ON_DEBUG (puts ("Adjusting tree"));
575 ON_DEBUG (puts ("... Done adjusting tree"));
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))
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);
594 f_panner->Set (args);
598 // /////////////////////////////////////////////////////////////////
600 // /////////////////////////////////////////////////////////////////
603 MapAgent::panner_movement (WCallback *wcb)
606 XawPannerReport *rep = (XawPannerReport *) wcb->CallData();
608 f_tree->X (-rep->slider_x, args);
609 f_tree->Y (-rep->slider_y, args);
614 // /////////////////////////////////////////////////////////////////
616 // /////////////////////////////////////////////////////////////////
619 MapAgent::close_window (WCallback *)
625 // /////////////////////////////////////////////////////////////////
626 // lock_toggle - callback for lock button
627 // /////////////////////////////////////////////////////////////////
630 MapAgent::lock_toggle (WCallback *wcb)
632 ON_DEBUG(cerr << "lock toggle callback" << endl);
634 XmToggleButtonCallbackStruct &cbs =
635 *(XmToggleButtonCallbackStruct*) wcb->CallData();
640 // /////////////////////////////////////////////////////////////////
641 // can_update - return true if this agent is willing to update
642 // /////////////////////////////////////////////////////////////////
645 MapAgent::can_update()
650 // /////////////////////////////////////////////////////////////////////////
651 // lock - set the lock
652 // /////////////////////////////////////////////////////////////////////////
661 // /////////////////////////////////////////////////////////////////////////
662 // unlock - unset the lock
663 // /////////////////////////////////////////////////////////////////////////
671 // /////////////////////////////////////////////////////////////////
672 // center_on - center current node in tree view
673 // /////////////////////////////////////////////////////////////////
676 MapAgent::center_on (MapButton *map_button)
678 // WXmPushButton button = map_button->f_button;
679 WXmForm &button = map_button->f_form;
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;
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));
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));
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));
706 if (bcenter_x > pcenter_x)
707 off_x = pcenter_x - bcenter_x;
709 if (bcenter_y > pcenter_y)
710 off_y = pcenter_y - bcenter_y;
712 if (off_x + twidth < pwidth)
713 off_x = pwidth - twidth;
715 if (off_y + theight < pheight)
716 off_y = pheight - theight;
718 ON_DEBUG (printf ("Button center offset = (%d,%d)\n", off_x, off_y));
722 f_tree->X (off_x, args);
723 ON_DEBUG (printf ("Setting Tree X to %d\n", off_x));
728 f_tree->Y (off_y, args);
729 ON_DEBUG (printf ("Setting Tree Y to %d\n", off_y));
732 if (args.NumArgs() > 0)
737 // /////////////////////////////////////////////////////////////////
738 // receive - handle node display messages
739 // /////////////////////////////////////////////////////////////////
742 MapAgent::receive (UAS_DocumentRetrievedMsg &message, void* /*client_data*/)
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)
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);
755 MapAgent::clear_map(UAS_Pointer<UAS_Common> &lib)
757 if(lib->lid() == f_doc_ptr->lid())
767 if ((f_tree != NULL) && f_onscreen)