dtinfo subtree dtinfo
[oweals/cde.git] / cde / programs / dtinfo / dtinfo / src / Agents / ScopeMenu.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 /* $XConsortium: ScopeMenu.C /main/6 1996/10/14 17:59:18 cde-hal $ */
24 /*
25  * (c) Copyright 1996 Digital Equipment Corporation.
26  * (c) Copyright 1996 Hewlett-Packard Company.
27  * (c) Copyright 1996 International Business Machines Corp.
28  * (c) Copyright 1996 Sun Microsystems, Inc.
29  * (c) Copyright 1996 Novell, Inc. 
30  * (c) Copyright 1996 FUJITSU LIMITED.
31  * (c) Copyright 1996 Hitachi.
32  */
33 /*
34  * Copyright (c) 1994 HAL Computer Systems International, Ltd.
35  * All rights reserved.  Unpublished -- rights reserved under
36  * the Copyright Laws of the United States.  USE OF A COPYRIGHT
37  * NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
38  * OR DISCLOSURE.
39  * 
40  * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
41  * SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.  USE,
42  * DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
43  * PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
44  * INTERNATIONAL, LTD.
45  * 
46  *                         RESTRICTED RIGHTS LEGEND
47  * Use, duplication, or disclosure by the Government is subject
48  * to the restrictions as set forth in subparagraph (c)(l)(ii)
49  * of the Rights in Technical Data and Computer Software clause
50  * at DFARS 252.227-7013.
51  *
52  *          HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
53  *                  1315 Dell Avenue
54  *                  Campbell, CA  95008
55  * 
56  */
57
58 #include "UAS.hh"
59
60 #define C_TOC_Element
61 #define L_Basic
62
63 #define C_ScopeMenu
64 #define C_SearchScopeAgent
65 #define L_Agents
66
67 #define C_xList
68 #define L_Support
69
70 #define C_SearchScopeMgr
71 #define C_MessageMgr
72 #define L_Managers
73
74 #define C_WindowSystem
75 #define L_Other
76
77 #include "Prelude.h"
78
79 #define CLASS ScopeMenu
80 #include "create_macros.hh"
81
82 #include <WWL/WXmPushButtonGadget.h>
83 #include <WWL/WXmSeparator.h>
84 #include <WWL/WXmMenu.h>
85 #include <WWL/WXmCascadeButton.h>
86
87 ScopeMenu::ScopeMenu (Widget option_menu, bool require_current_section)
88 : f_current_scope (NULL),
89   f_use_current_section(require_current_section),
90   f_option_menu(option_menu)
91 {
92   Arg args[1];
93   int n;
94
95   n = 0;
96   XtSetArg(args[n], XmNsubMenuId, &f_pull_menu); n++;
97   XtGetValues(option_menu, args, n);
98
99   fill_menu();
100
101   UAS_SearchScope::request ((UAS_Receiver<ScopeCreated> *) this);
102   UAS_SearchScope::request ((UAS_Receiver<ScopeDeleted> *) this);
103   UAS_SearchScope::request ((UAS_Receiver<ScopeRenamed> *) this);
104
105   SearchScopeAgent::request ((UAS_Receiver<UpdateMenu> *) this);
106 }
107
108 ScopeMenu::~ScopeMenu()
109 {
110 }
111
112
113 void
114 ScopeMenu::fill_menu()
115 {
116   int position = 0;
117   Wait_Cursor bob;
118
119   // Create toggle buttons for each scope.
120   xList<UAS_SearchScope *> &scope_list = search_scope_mgr().scope_list();
121   List_Iterator<UAS_SearchScope *> s (scope_list);
122   bool old_read_only = TRUE;
123
124   // Set the current scope to the first entry
125   //  (Current Section or Information Library) 
126   f_current_scope = s.item();
127
128   ON_DEBUG(cerr << "Scope Popup" << endl);
129
130   int first = TRUE;
131   for (; s != 0; s++)
132     {
133       
134       // in case we are not using Current Section
135       if (f_current_scope == NULL)
136         f_current_scope = s.item();
137
138       ON_DEBUG(cerr << "\t" << f_current_scope->name() << endl);
139 //    ON_DEBUG(f_current_scope->dump_items());
140
141       // Add a separator when they change from read only to changable. 
142       if (old_read_only != s.item()->read_only())
143         {
144           DECLM (WXmSeparator, sep1, f_pull_menu, "separator");
145           sep1.PositionIndex (position++);
146           old_read_only = FALSE;
147         }
148       DECLM (WXmPushButtonGadget, scope, f_pull_menu, s.item()->name());
149       if (first && !f_use_current_section)
150         {
151           first = FALSE;
152           scope.Unmanage();
153           // Reset current scope so that it is set to Library on next pass.
154           f_current_scope = NULL;
155         }
156       scope.UserData (s.item());
157       scope.PositionIndex (position++);
158
159       WCallback *cb = SET_CALLBACK(scope,Activate,set_scope);
160       SET_CALLBACK_D (scope,Destroy,destroy_scope,cb);
161       if (f_current_scope == s.item())
162         {
163           Arg args[1];
164           int n = 0;
165           XtSetArg(args[n], XmNmenuHistory, (Widget)scope); n++;
166           XtSetValues(f_option_menu, args, n);
167         }
168     }
169
170   //UAS_SearchScope::request ((UAS_Receiver<ScopeCreated> *) this);
171   //UAS_SearchScope::request ((UAS_Receiver<ScopeDeleted> *) this);
172   //UAS_SearchScope::request ((UAS_Receiver<ScopeRenamed> *) this);
173 }
174
175
176 void
177 ScopeMenu::set_scope (WCallback *wcb)
178 {
179   CALL_DATA (XmToggleButtonCallbackStruct,tbcs);
180
181   f_current_scope =
182         (UAS_SearchScope *) WXmPushButtonGadget(wcb->GetWidget()).UserData();
183 }
184
185
186 void
187 ScopeMenu::destroy_scope (WCallback *wcb)
188 {
189   WCallback *cb = (WCallback *) wcb->ClientData();
190   delete cb;
191   delete wcb;
192 }
193
194 // /////////////////////////////////////////////////////////////////
195 // receive - handle scope created / deleted messages
196 // /////////////////////////////////////////////////////////////////
197
198 void
199 ScopeMenu::receive (ScopeCreated &msg, void *client_data)
200 {
201   int position = 0;
202   const char *scope_name = msg.f_search_scope->name();
203   xList<UAS_SearchScope *> &scope_list = search_scope_mgr().scope_list();
204   List_Iterator<UAS_SearchScope *> s (scope_list);
205   bool need_sep = TRUE;
206
207   int n;
208   Arg args[2];
209   WidgetList kids;
210   Cardinal num_kids;
211
212   n = 0;
213   XtSetArg(args[n], XmNnumChildren, &num_kids); n++;
214   XtSetArg(args[n], XmNchildren, &kids); n++;
215   XtGetValues(f_pull_menu, args, n);
216
217   UAS_SearchScope *scope;
218
219   if (msg.f_search_scope->read_only())
220   {
221     // insert read-only scopes at the start; reserve position 0
222     // for "Current Section" scope and position 1 for
223     // the "All Libraries" scope
224     position = 2;
225     need_sep = FALSE;
226   }
227   else
228   {
229     // Scan the current menu to find the correct insertion position. 
230     for (; s != 0; s++, position++)
231     {
232       scope = s.item();
233       if (need_sep != scope->read_only())
234       {
235         position++;  // skip separator
236         need_sep = FALSE;
237       }
238       if (scope->read_only())
239         continue;
240       // Find the first item that the new entry belongs after.
241       ON_DEBUG (printf ("Scope strcmp to <%s>\n", scope->name()));
242       if (strcmp (scope_name, scope->name()) < 0)
243         break;
244     }
245   }
246
247   ON_DEBUG (printf ("Final position = %d\n", position));
248
249   // Add a separator if this is the first user-defined entry. 
250   if (need_sep == TRUE)
251   {
252     DECLM (WXmSeparator, separator, f_pull_menu, "separator");
253     separator.PositionIndex (position);
254     position++;
255   }
256
257   // Create the new toggle button. 
258   DECLM (WXmPushButtonGadget, scope_btn, f_pull_menu, scope_name);
259   scope_btn.PositionIndex (position);
260   scope_btn.UserData (msg.f_search_scope);
261   WCallback *cb = SET_CALLBACK(scope_btn,Activate,set_scope);
262   SET_CALLBACK_D(scope_btn,Destroy,destroy_scope,cb);
263 }
264
265 void
266 ScopeMenu::receive (ScopeDeleted &msg, void *client_data)
267 {
268   // find the associated button and nuke it
269   ON_DEBUG (puts ("ScopeMenu: handling delete message"));
270   // First find renamed button in our list.
271   Arg args[2];
272   int n, theKid;
273   Cardinal num_kids;
274   WidgetList kids;
275   int separator_pos = -1;
276   Widget selected;
277
278   n = 0;
279   XtSetArg(args[n], XmNmenuHistory, &selected); n++;
280   XtGetValues(f_option_menu, args, n);
281
282   n = 0;
283   XtSetArg(args[n], XmNnumChildren, &num_kids); n++;
284   XtSetArg(args[n], XmNchildren, &kids); n++;
285   XtGetValues(f_pull_menu, args, n);
286
287   int i;
288   for (i = 0; i < num_kids; i++)
289     {
290       if (XmIsSeparator (kids[i]))
291       {
292         separator_pos = i + 1;
293         continue;
294       }
295       if (XmIsPushButtonGadget (kids[i]) &&
296           msg.f_search_scope ==
297           ((UAS_SearchScope *) WXmPushButtonGadget (kids[i]).UserData()))
298         break;
299     }
300
301   // It had better be in the list! 
302   theKid = i;
303   Xassert (theKid != num_kids);
304   ON_DEBUG (printf ("widget #%d is the button\n", theKid));
305
306   // if it is selected, select first w/ callback called
307   if (kids[theKid] == selected)
308     {
309       n = 0;
310       if (XtIsManaged (kids[0]))
311           XtSetArg(args[n], XmNmenuHistory, kids[0]);
312       else
313           XtSetArg(args[n], XmNmenuHistory, kids[1]);
314       n++;
315       XtSetValues(f_option_menu, args, n);
316     }
317
318   XtUnmanageChild (kids[theKid]);
319   XtDestroyWidget (kids[theKid]);
320
321   // Get rid of the separator if no user scopes remain.
322   ON_DEBUG (printf ("ScopeMenu: sep pos = %d, num_kids = %d (%d)\n",
323                     separator_pos, num_kids, num_kids -1 -2));
324   // - 1 for deleted widget
325   if (separator_pos == (num_kids - 1))
326     {
327       ON_DEBUG (puts ("   destroying separator"));
328       XtDestroyWidget (kids[separator_pos-1]);
329     }
330 }
331
332
333 void
334 ScopeMenu::receive (ScopeRenamed &msg, void *client_data)
335 {
336   ON_DEBUG (puts ("ScopeMenu: handling rename message"));
337   // First find renamed button in our list.
338   Arg args[2];
339   int n;
340   Cardinal num_kids;
341   WidgetList kids;
342   int separator_pos = -1;
343
344   n = 0;
345   XtSetArg(args[n], XmNnumChildren, &num_kids); n++;
346   XtSetArg(args[n], XmNchildren, &kids); n++;
347   XtGetValues(f_pull_menu, args, n);
348
349   int i;
350   for (i = 0; i < num_kids; i++)
351     {
352       if (XmIsPushButtonGadget (kids[i]) &&
353           msg.f_search_scope ==
354           ((UAS_SearchScope *) WXmPushButtonGadget (kids[i]).UserData()))
355         break;
356     }
357
358   // It had better be in the list! 
359   Xassert (i != num_kids);
360   ON_DEBUG (printf ("ScopeMenu: widget #%d is the button\n", i));
361
362   // Now find the new insertion position in the list.
363   int position = 0, old_position = i;
364   xList<UAS_SearchScope *> &scope_list = search_scope_mgr().scope_list();
365   List_Iterator<UAS_SearchScope *> s (scope_list);
366
367   // find the new position in the list
368   for (; s != 0; s++)
369     {
370       if (s.item() == msg.f_search_scope)
371         continue;
372       position++;
373       if (s.item()->read_only())
374         continue;
375       ON_DEBUG (printf ("ScopeMenu: strcmp <%s>\n", s.item()->name()));
376       if (strcmp (msg.f_search_scope->name(), s.item()->name()) < 0)
377         break;
378     }
379
380   if (s == NULL)
381     position++;
382
383   ON_DEBUG (printf ("ScopeMenu: Rename position = %d, old = %d\n",
384                     position, old_position));
385   WXmPushButtonGadget scope_btn (kids[i]);
386   scope_btn.LabelString (msg.f_search_scope->name());
387   if (position != old_position)
388     scope_btn.PositionIndex (position);
389 }
390
391 void
392 ScopeMenu::receive (UpdateMenu &msg, void *client_data)
393 {
394   xList<UAS_SearchScope *> &scope_list = search_scope_mgr().scope_list();
395   List_Iterator<UAS_SearchScope *> s (scope_list);
396
397   int n;
398   Arg args[2];
399   WidgetList kids;
400   Cardinal num_kids;
401
402   n = 0;
403   XtSetArg(args[n], XmNnumChildren, &num_kids); n++;
404   XtSetArg(args[n], XmNchildren, &kids); n++;
405   XtGetValues(f_pull_menu, args, n);
406
407   // destroy all toggle buttons in menu
408   for (int i = 0; i < num_kids; i++)
409   {
410     XtUnmanageChild (kids[i]);
411     XtDestroyWidget (kids[i]);
412   }
413
414   // select current scope
415   if(f_use_current_section)
416     f_current_scope = s.item();
417   else
418   {
419     s++;
420     f_current_scope = s.item();
421   }
422   fill_menu();
423   XtUnmanageChild(XtParent(f_option_menu));
424   XtManageChild(XtParent(f_option_menu));
425   XtUnmanageChild(f_option_menu);
426   XtManageChild(f_option_menu);
427 }
428