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