dtinfo subtree dtinfo
[oweals/cde.git] / cde / programs / dtinfo / dtinfo / src / Agents / MarkIconMotif.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  * $XConsortium: MarkIconMotif.C /main/13 1996/11/19 15:03:42 cde-hal $
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 #define C_TOC_Element
48 #define L_Basic
49
50 #define C_WindowSystem
51 #define L_Other
52
53 #define C_MarkCanvas
54 #define C_MarkIcon
55 #define C_MarkChooser
56 #define L_Agents
57
58 #define C_MessageMgr
59 #define L_Managers
60
61 #define USES_OLIAS_FONT
62
63 #include <X11/IntrinsicP.h>
64 #include <X11/Intrinsic.h>
65 #include <X11/CoreP.h>
66
67 #include "Prelude.h"
68
69 #include "Managers/CatMgr.hh"
70 #include "Other/XmStringLocalized.hh"
71
72 #include "Registration.hh"
73
74 #include <ctype.h>
75 #include <WWL/WXmSeparatorGadget.h>
76 #include <WWL/WXmLabelGadget.h>
77 #include <WWL/WXmPushButton.h>
78
79 #include <iostream>
80 using namespace std;
81
82 #define CLASS MarkIcon
83 #include "create_macros.hh"
84
85 WTimeOut *g_timeout;
86
87 static void register_actions();
88
89
90 // /////////////////////////////////////////////////////////////////
91 // class constructor
92 // /////////////////////////////////////////////////////////////////
93
94 MarkIcon::MarkIcon (Widget parent, 
95                     Widget chooser_parent,
96                     MarkCanvas *mark, 
97                     int ypos, int scrollbar_offset)
98 : f_icon_char (0),
99   f_selected (FALSE),
100   f_y_position (ypos),
101   f_chooser_parent (chooser_parent)
102 {
103   static XtTranslations translations;
104
105   if (translations == NULL) {
106
107     register_actions();
108
109     translations = XtParseTranslationTable ( 
110         "<Btn1Down>:single_click()\n"
111         "<Btn1Down>(2):double_click()\n"
112         "<Key>osfHelp:Help()\n"
113         "<Key>Return:double_click()\n"
114         "Ctrl<Key>Return:double_click()\n"
115         "<Key>osfActivate: double_click()");
116   }
117
118   widget = WXmPushButton (parent, "mark_icon", WAutoManage);
119
120   XtOverrideTranslations(widget, translations);
121
122   // ON_ACTIVATE (*this, activate);
123
124   append (mark);
125
126   UserData (this);
127
128   ON_DEBUG(cerr << "MarkIcon::MarkIcon -> ypos: " << ypos << " offset: " <<
129     scrollbar_offset << endl);
130
131
132   Y ((Position) ypos - scrollbar_offset);
133   TopOffset(ypos - scrollbar_offset);
134   Raise();
135 }
136
137
138 // /////////////////////////////////////////////////////////////////
139 // register_actions
140 // /////////////////////////////////////////////////////////////////
141
142 void
143 MarkIcon::register_actions()
144 {
145  static bool registered = FALSE;
146
147  if (registered)
148     return;
149
150  static XtActionsRec actions_list[] =
151  { 
152       {(char*)"double_click",    &MarkIcon::static_double_click},
153       {(char*)"single_click",    &MarkIcon::static_single_click},
154  };
155
156  XtAppAddActions (window_system().app_context(), actions_list, XtNumber (actions_list));
157
158
159 }
160
161 // /////////////////////////////////////////////////////////////////
162 // static_double_click
163 // /////////////////////////////////////////////////////////////////
164
165 void 
166 MarkIcon::static_double_click(Widget widget, XEvent *event, String *args, Cardinal *num_args)
167 {
168
169  ((MarkIcon *) WXmPushButton(widget).UserData())->double_click (event);
170
171 }
172
173 // /////////////////////////////////////////////////////////////////
174 // static_single_click
175 // /////////////////////////////////////////////////////////////////
176
177 void 
178 MarkIcon::static_single_click(Widget widget, XEvent *event, String *args, Cardinal *num_args)
179 {
180
181  ((MarkIcon *) WXmPushButton(widget).UserData())->single_click (event);
182
183 }
184
185
186 // /////////////////////////////////////////////////////////////////
187 // double_click
188 // /////////////////////////////////////////////////////////////////
189
190 void 
191 MarkIcon::double_click(XEvent *event)
192 {
193  
194   if (mark_count() == 1)
195   {
196       List_Iterator<MarkCanvas *> m (f_mark_list);
197           m.item()->select();
198           m.item()->mark_ptr()->edit();
199   }
200   else // mark_mark_count() > 1
201   {
202       assert (mark_count() > 1);
203
204       if (g_timeout) {
205         delete g_timeout;
206         g_timeout = NULL;
207       }
208
209       UAS_String title  = CATGETS(Set_MarkChooser, 2, "Dtinfo: Edit Mark");
210       UAS_String btitle = CATGETS(Set_AgentLabel, 16, "Edit");
211       MarkChooser chooser (f_chooser_parent, f_mark_list,
212                                         (char*)title, (char*)btitle);
213           
214       MarkCanvas *choice = chooser.get_choice();
215       if (choice != NULL)
216       {
217         choice->select();
218         choice->mark_ptr()->edit();
219       }
220    }
221 }
222
223 // /////////////////////////////////////////////////////////////////
224 // single_click
225 // /////////////////////////////////////////////////////////////////
226
227 void 
228 MarkIcon::single_click(XEvent *event)
229 {
230
231   if (mark_count() == 1)
232     {
233       List_Iterator<MarkCanvas *> m (f_mark_list);
234           if (!f_selected)
235             m.item()->select();
236           else
237             m.item()->deselect();
238     }
239   else // mark_mark_count() > 1
240     {
241       assert (mark_count() > 1);
242
243       // Use the double click delay plus 30 milliseconds. 
244       int delay = XtGetMultiClickTime (XtDisplay (widget)) + 30;
245       g_timeout =
246         new WTimeOut (window_system().app_context(), delay, this,
247                   (WTimeOutFunc) &MarkIcon::select_mark_timeout);
248     }
249 }
250
251
252 // /////////////////////////////////////////////////////////////////
253 // class destructor
254 // /////////////////////////////////////////////////////////////////
255
256 MarkIcon::~MarkIcon()
257 {
258   List_Iterator<MarkCanvas *> m (f_mark_list);
259   while (m)
260     {
261       m.item()->set_mark_icon (NULL);
262       m++;
263     }
264
265   if (g_timeout) {
266     delete g_timeout;
267     g_timeout = NULL;
268   }
269
270   XtDestroyWidget (widget);
271 }
272
273
274 // /////////////////////////////////////////////////////////////////
275 // highlight
276 // /////////////////////////////////////////////////////////////////
277
278 inline void
279 MarkIcon::highlight()
280 {
281   if (f_selected == FALSE)
282     {
283       ON_DEBUG(printf ("highlighting mark %p\n", this));
284       swap_colors();
285     }
286 }
287
288 void
289 MarkIcon::select (MarkCanvas *)
290 {
291   highlight();
292
293   f_selected = TRUE;
294 }
295
296
297 // /////////////////////////////////////////////////////////////////
298 // unhighlight
299 // /////////////////////////////////////////////////////////////////
300
301 inline void
302 MarkIcon::unhighlight()
303 {
304   if (f_selected == TRUE)
305     {
306       ON_DEBUG(printf ("unhighlighting mark %p\n", this));
307       swap_colors();
308     }
309 }
310
311 void
312 MarkIcon::deselect (MarkCanvas *)
313 {
314   unhighlight();
315
316   f_selected = FALSE;
317 }
318
319
320 // /////////////////////////////////////////////////////////////////
321 // update_icon
322 // /////////////////////////////////////////////////////////////////
323
324 void
325 MarkIcon::update_icon (MarkCanvas *)
326 {
327   Pixmap button_pixmap = 0;
328
329   int multi = mark_count() > 1;
330   int anno  = False;
331
332
333   List_Iterator<MarkCanvas *> m (f_mark_list);
334   while (m)
335     {
336       if (*(m.item()->mark_ptr()->notes()) != '\0')
337         {
338           anno = True;
339           break;
340         }
341       m++;
342     }
343
344   if (anno) {
345     if (multi)
346       button_pixmap = XmGetPixmap(window_system().screen(),(char*)"anno_double",
347                                   Foreground(), Background());
348     else
349       button_pixmap = XmGetPixmap(window_system().screen(),(char*)"anno_single",
350                                   Foreground(), Background());
351   }
352   else {
353     if (multi)
354       button_pixmap = XmGetPixmap(window_system().screen(),(char*)"mark_double",
355                                   Foreground(), Background());
356     else
357       button_pixmap = XmGetPixmap(window_system().screen(),(char*)"mark_single",
358                                   Foreground(), Background());
359   }
360
361   if (button_pixmap && button_pixmap != XmUNSPECIFIED_PIXMAP) {
362     LabelPixmap(button_pixmap);
363   }
364   else {
365 #ifdef BOOKMARK_DEBUG
366     cerr << "XmGetPixmap failed." << endl;
367 #endif
368   }
369
370 #if 0
371   static char buf[2];
372   *buf = OLIAS_BOOKMARK_ICON;
373
374   List_Iterator<MarkCanvas *> m (f_mark_list);
375   while (m)
376     {
377       if (*(m.item()->mark_ptr()->notes()) != '\0')
378         {
379           *buf = OLIAS_ANNOTATION_ICON;
380           break;
381         }
382       m++;
383     }
384
385   // NOTE: Slight hack here.  Depends on multi-icons being uppercase version
386   // of single icons.  DJB 10/27/92 
387   if (mark_count() > 1)
388     *buf = toupper (*buf);
389
390   if (f_icon_char != *buf)
391     {
392       f_icon_char = *buf;
393       LabelString (buf);
394     }
395 #endif
396 }
397
398
399 // /////////////////////////////////////////////////////////////////
400 // insert - add a mark to this icon
401 // /////////////////////////////////////////////////////////////////
402
403 void
404 MarkIcon::insert (MarkCanvas *mark_canvas)
405 {
406   mark_canvas->set_mark_icon (this);
407
408   // Insert the new mark in the mark list in sorted order. 
409   List_Iterator<MarkCanvas *> m (f_mark_list);
410   while (m && mark_canvas->offset() > m.item()->offset())
411     m++;
412
413   // Check for last mark in the icon (ie: start of list)
414   if (m == NULL)
415     {
416       f_offset = mark_canvas->offset();
417       f_mark_list.append (mark_canvas);
418     }
419   else
420     {
421       f_mark_list.insert_before (m, mark_canvas);
422     }
423
424   // BUG ALERT!! 
425   // If mark_canvas is first item in list, we might have a problem
426   // since the later items in the list may no longer overlap it :-(
427
428   if (mark_canvas->selected())
429     highlight();
430
431   update_icon (mark_canvas);
432 }
433
434
435 // /////////////////////////////////////////////////////////////////
436 // append - add to the end of the list 'o marks
437 // /////////////////////////////////////////////////////////////////
438
439 void
440 MarkIcon::append (MarkCanvas *mark_canvas)
441 {
442   mark_canvas->set_mark_icon (this);
443   f_mark_list.append (mark_canvas);
444   f_offset = mark_canvas->offset();
445
446   if (mark_canvas->selected())
447     highlight();
448
449   update_icon (mark_canvas);
450 }
451
452
453 // /////////////////////////////////////////////////////////////////
454 // remove - remove a mark tml from this icon
455 // /////////////////////////////////////////////////////////////////
456
457 void
458 MarkIcon::remove (MarkCanvas *mark_canvas)
459 {
460   mark_canvas->set_mark_icon (NULL);
461   f_mark_list.remove (mark_canvas);
462
463   // See if we need to recompute the offset. 
464   if (mark_count() > 0 && mark_canvas->offset() == f_offset)
465     {
466       List_Iterator<MarkCanvas *> m (f_mark_list);
467       m.last();
468       f_offset = m.item()->offset();
469     }
470   update_icon (NULL);
471 }
472
473
474 // /////////////////////////////////////////////////////////////////
475 // activate - activate callback
476 // /////////////////////////////////////////////////////////////////
477
478 void
479 MarkIcon::activate (WCallback *wcb)
480 {
481   CALL_DATA (XmPushButtonCallbackStruct, pbcs);
482
483   if (mark_count() == 1)
484     {
485       List_Iterator<MarkCanvas *> m (f_mark_list);
486       if (pbcs->click_count == 1)
487         {
488           if (!f_selected)
489             m.item()->select();
490           else
491             m.item()->deselect();
492         }
493       else if (pbcs->click_count == 2)
494         {
495           m.item()->select();
496           m.item()->mark_ptr()->edit();
497         }
498     }
499   else // mark_mark_count() > 1
500     {
501       assert (mark_count() > 1);
502       
503       if (pbcs->click_count == 1)
504         {
505           // Use the double click delay plus 20 milliseconds. 
506           int delay = XtGetMultiClickTime (XtDisplay (widget)) + 2000;
507           g_timeout =
508             new WTimeOut (window_system().app_context(), delay, this,
509                           (WTimeOutFunc) &MarkIcon::select_mark_timeout);
510                 
511         }
512       else if (pbcs->click_count == 2)
513         {
514           delete g_timeout;
515           g_timeout = NULL;
516
517           UAS_String title  = CATGETS(Set_MarkChooser, 2, "Dtinfo: Edit Mark");
518           UAS_String btitle = CATGETS(Set_AgentLabel, 16, "Edit");
519           MarkChooser chooser (f_chooser_parent, f_mark_list,
520                                         (char*)title, (char*)btitle);
521           
522             MarkCanvas *choice = chooser.get_choice();
523             if (choice != NULL)
524               {
525                 choice->select();
526                 choice->mark_ptr()->edit();
527               }
528
529         }
530     }
531 }
532
533 // /////////////////////////////////////////////////////////////////
534 // select_mark_timeout
535 // /////////////////////////////////////////////////////////////////
536
537 void
538 MarkIcon::select_mark_timeout()
539 {
540   // WTimeOut will destruct itself, do not delete g_timeout here
541   g_timeout = NULL;
542
543   UAS_String title  = CATGETS(Set_MarkChooser, 1, "Dtinfo: Select Mark");
544   UAS_String btitle = CATGETS(Set_AgentLabel, 161, "Ok");
545   MarkChooser chooser (f_chooser_parent, f_mark_list,
546                                         (char*)title, (char*)btitle);
547
548   MarkCanvas *choice = chooser.get_choice();
549
550   if (choice)
551   {
552     if (! f_selected)
553       choice->select();
554     else
555       choice->deselect();
556   }
557 }
558
559 // /////////////////////////////////////////////////////////////////
560 // swap_colors - swap the foreground and background colors
561 // /////////////////////////////////////////////////////////////////
562
563 void
564 MarkIcon::swap_colors()
565 {
566   // Swap the fg and bg colors.
567
568   int multi = mark_count() > 1;
569   int anno  = False;
570
571   List_Iterator<MarkCanvas *> m (f_mark_list);
572   while (m)
573     {
574       if (*(m.item()->mark_ptr()->notes()) != '\0')
575         {
576           anno = True;
577           break;
578         }
579       m++;
580     }
581
582   Pixel background, foreground;
583
584   if (f_selected == FALSE) { // about to select
585     foreground = Background();
586     background = Foreground();
587   }
588   else {                     // about to de-select
589     foreground = Foreground();
590     background = Background();
591   }
592
593   Pixmap button_pixmap;
594
595   if (anno) {
596     if (multi)
597       button_pixmap = XmGetPixmap(window_system().screen(),(char*)"anno_double",
598                                   foreground, background);
599     else
600       button_pixmap = XmGetPixmap(window_system().screen(),(char*)"anno_single",
601                                   foreground, background);
602   }
603   else {
604     if (multi)
605       button_pixmap = XmGetPixmap(window_system().screen(),(char*)"mark_double",
606                                   foreground, background);
607     else
608       button_pixmap = XmGetPixmap(window_system().screen(),(char*)"mark_single",
609                                   foreground, background);
610   }
611
612   if (button_pixmap && button_pixmap != XmUNSPECIFIED_PIXMAP) {
613     LabelPixmap(button_pixmap);
614   }
615
616 }  
617