1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11 
12 
13 
14 #include <Xm/RowColumn.h>
15 #include <Xm/Form.h>
16 #include <Xm/ScrolledW.h>
17 #include <Xm/PushB.h>
18 #include <Xm/DrawingA.h>
19 #include <Xm/Label.h>
20 #include <Xm/Separator.h>
21 
22 //
23 // Is it a good idea to provide a button which will sort up/down the ticks
24 // according to the tick value?  Pro: The user doesn't have the ability to
25 // move individual entries around in the list and the AutoAxes module seems
26 // to care about sorted order.  Con:  The module should be able to deal with
27 // the entries in any order, sort them if it wants to, and echo them back in
28 // sorted order.  The ui should just respond to that and not get cluttered up
29 // with sorting code.
30 //
31 // If you use the SORT_TICKS code, then touch TickLabelList.h so that Makefile
32 // does the right thing.
33 //
34 //#define UI_SHOULD_SORT_TICKS 1
35 
36 #include "TickLabelList.h"
37 #include "TickLabel.h"
38 #include "ListIterator.h"
39 #include "DXStrings.h"
40 #include "DXApplication.h"
41 
42 
43 //
44 //
45 String TickLabelList::DefaultResources[] = {
46     "*tllMenuB.width:			20",
47     "*tllMenuB.labelString:		...",
48     "*tllMenuB.recomputeSize:		False",
49 
50     "*listRC.marginWidth:		1",
51     "*listRC.marginHeight:		1",
52     "*listRC.spacing:			0",
53 
54     "*newTop.labelString:		Insert at top",
55     "*deleteAll.labelString:		Delete all items",
56     "*aasBut.labelString:		Append after selection",
57     "*iasBut.labelString:		Insert above selection",
58     "*dsBut.labelString:		Delete Selection",
59     "*suBut.labelString:		Sort in Ascending Order",
60     "*sdBut.labelString:		Sort in Descending Order",
61     NULL
62 };
63 
64 boolean TickLabelList::SortUp = TRUE;
65 
66 boolean TickLabelList::ClassInitialized = FALSE;
67 
68 #define DIRTY_APPEND 1
69 #define DIRTY_DELETE 2
70 
TickLabelList(const char * header,TickListModifyCB tlmcb,void * clientData)71 TickLabelList::TickLabelList (const char *header, TickListModifyCB tlmcb,
72 	void *clientData): UIComponent ("tickList")
73 {
74    this->header = DuplicateString(header);
75    this->dirty = 0;
76 
77    this->header_label = this->header_button = this->listRC = NULL;
78    this->popupMenu = NULL;
79 
80    this->oldDvals = NULL;
81    this->oldString = NULL;
82 
83    this->highest_set_number = 0;
84 
85    this->tlmcb = tlmcb;
86    this->clientData = clientData;
87 }
88 
initialize()89 void TickLabelList::initialize()
90 {
91     //
92     // Initialize default resources (once only).
93     //
94     if (NOT TickLabelList::ClassInitialized) {
95 	this->setDefaultResources(theApplication->getRootWidget(),
96 	    TickLabelList::DefaultResources);
97 	TickLabelList::ClassInitialized = TRUE;
98     }
99 }
100 
~TickLabelList()101 TickLabelList::~TickLabelList()
102 {
103     if (this->header) delete this->header;
104 
105     ListIterator it(this->ticks);
106     TickLabel *tl;
107 
108     while ( (tl = (TickLabel*)it.getNext()) )
109 	delete tl;
110     this->ticks.clear();
111 
112     if (this->oldDvals) delete this->oldDvals;
113 
114     if (this->oldString)
115 	delete this->oldString;
116 }
117 
118 
119 void
createList(Widget parent)120 TickLabelList::createList (Widget parent)
121 {
122 int n;
123 Arg args[25];
124 
125     this->initialize();
126 
127     Widget form = XtVaCreateWidget (this->name,
128 	xmFormWidgetClass, 	parent,
129 	XmNshadowThickness,	2,
130 	XmNshadowType,		XmSHADOW_ETCHED_IN,
131     NULL);
132 
133     n = 0;
134     XtSetArg (args[n], XmNtopAttachment,	XmATTACH_FORM); n++;
135     XtSetArg (args[n], XmNtopOffset,		50); n++;
136     XtSetArg (args[n], XmNleftAttachment,	XmATTACH_FORM); n++;
137     XtSetArg (args[n], XmNrightAttachment,	XmATTACH_FORM); n++;
138     XtSetArg (args[n], XmNbottomAttachment,	XmATTACH_FORM); n++;
139     XtSetArg (args[n], XmNleftOffset,		2); n++;
140     XtSetArg (args[n], XmNrightOffset,		2); n++;
141     XtSetArg (args[n], XmNbottomOffset,		2); n++;
142     XtSetArg (args[n], XmNheight,		150); n++;
143     XtSetArg (args[n], XmNshadowThickness, 	0); n++;
144     XtSetArg (args[n], XmNspacing, 		0); n++;
145     XtSetArg (args[n], XmNscrollingPolicy, 	XmAUTOMATIC); n++;
146     Widget sw = XmCreateScrolledWindow (form, "ticksSW", args, n);
147     XtManageChild (sw);
148     Widget sb = NULL;
149     XtVaGetValues (sw, XmNhorizontalScrollBar, &sb, NULL);
150     if (sb) XtUnmanageChild (sb);
151 
152     n = 0;
153     XtSetArg (args[n], XmNresizeWidth,		False); n++;
154     this->listRC = XmCreateRowColumn (sw, "listRC", args, n);
155     XtManageChild (this->listRC);
156     XmScrolledWindowSetAreas (sw, NULL, NULL, this->listRC);
157 
158     //
159     // Title line...
160     //
161     XmString xmstr = XmStringCreate (this->header, "bold");
162     Widget xlab = XtVaCreateManagedWidget ("listHeader",
163 	xmLabelWidgetClass,	form,
164 	XmNbottomAttachment,	XmATTACH_WIDGET,
165 	XmNbottomWidget,	sw,
166 	XmNbottomOffset,	20,
167 	XmNleftAttachment,	XmATTACH_POSITION,
168 	XmNleftPosition,	50,
169 	XmNleftOffset,		-50,
170 	XmNalignment,		XmALIGNMENT_CENTER,
171 	XmNlabelString,		xmstr,
172     NULL);
173     XmStringFree (xmstr);
174 
175     //
176     // Labels over the numbers and the text.
177     //
178     xmstr = XmStringCreate ("Tick Location", "small_bold");
179     XtVaCreateManagedWidget ("tickTitle",
180 	xmLabelWidgetClass,	form,
181 	XmNbottomAttachment,	XmATTACH_WIDGET,
182 	XmNbottomWidget,	sw,
183 	XmNbottomOffset,	1,
184 	XmNleftAttachment,	XmATTACH_FORM,
185 	XmNleftOffset,		4,
186 	XmNlabelString,		xmstr,
187     NULL);
188     XmStringFree(xmstr);
189     xmstr = XmStringCreate ("Tick Label", "small_bold");
190     this->labelLabel = XtVaCreateManagedWidget ("textTitle",
191 	xmLabelWidgetClass,	form,
192 	XmNbottomAttachment,	XmATTACH_WIDGET,
193 	XmNbottomWidget,	sw,
194 	XmNbottomOffset,	1,
195 	XmNrightAttachment,	XmATTACH_FORM,
196 	XmNrightOffset,		4,
197 	XmNlabelString,		xmstr,
198     NULL);
199     XmStringFree(xmstr);
200 
201 
202     //
203     // button for list ops...
204     //
205     Widget button = XtVaCreateManagedWidget ("tllMenuB",
206 	xmPushButtonWidgetClass,form,
207 	XmNbottomAttachment,	XmATTACH_OPPOSITE_WIDGET,
208 	XmNbottomWidget,	xlab,
209 	XmNbottomOffset,	0,
210 	XmNleftAttachment,	XmATTACH_WIDGET,
211 	XmNleftWidget,		xlab,
212 	XmNleftOffset,		10,
213     NULL);
214     XtUninstallTranslations (button);
215     XtAddEventHandler (button, ButtonPressMask|ButtonReleaseMask, False,
216 	(XtEventHandler)TickLabelList_ButtonEH, (XtPointer)this);
217 
218     n = 0;
219     XtSetArg (args[0], XmNmenuPost, "Shift<Btn4Down>");
220     this->popupMenu = XmCreatePopupMenu(form, "tllPopup", args, 1);
221 
222     button = this->ntiButton = XtVaCreateManagedWidget ("newTop",
223 	xmPushButtonWidgetClass,	this->popupMenu,
224 	XmNuserData,			0,
225     NULL);
226     XtAddCallback (button, XmNactivateCallback,
227 	(XtCallbackProc)TickLabelList_AppendCB, (XtPointer)this);
228 
229     button = this->daButton = XtVaCreateManagedWidget ("deleteAll",
230 	xmPushButtonWidgetClass,	this->popupMenu,
231     NULL);
232     XtAddCallback (button, XmNactivateCallback,
233 	(XtCallbackProc)TickLabelList_DeleteAllCB, (XtPointer)this);
234 
235     XtVaCreateManagedWidget ("sep", xmSeparatorWidgetClass, this->popupMenu, NULL);
236 
237     button = this->iasButton = XtVaCreateManagedWidget ("iasBut",
238 	xmPushButtonWidgetClass,	this->popupMenu,
239     NULL);
240     XtAddCallback (button, XmNactivateCallback,
241 	(XtCallbackProc)TickLabelList_InsertAboveSelCB, (XtPointer)this);
242 
243     button = this->aasButton = XtVaCreateManagedWidget ("aasBut",
244 	xmPushButtonWidgetClass,	this->popupMenu,
245     NULL);
246     XtAddCallback (button, XmNactivateCallback,
247 	(XtCallbackProc)TickLabelList_AppendAfterSelCB, (XtPointer)this);
248 
249     button = this->dsButton = XtVaCreateManagedWidget ("dsBut",
250 	xmPushButtonWidgetClass,	this->popupMenu,
251     NULL);
252     XtAddCallback (button, XmNactivateCallback,
253 	(XtCallbackProc)TickLabelList_DeleteSelCB, (XtPointer)this);
254 
255 #if UI_SHOULD_SORT_TICKS
256     XtVaCreateManagedWidget ("sep", xmSeparatorWidgetClass, this->popupMenu, NULL);
257 
258     button = this->suButton = XtVaCreateManagedWidget("suBut",
259 	xmPushButtonWidgetClass,	this->popupMenu,
260     NULL);
261     XtAddCallback (button, XmNactivateCallback,
262 	(XtCallbackProc)TickLabelList_SortUpCB, (XtPointer)this);
263 
264     button = this->sdButton = XtVaCreateManagedWidget("sdBut",
265 	xmPushButtonWidgetClass,	this->popupMenu,
266     NULL);
267     XtAddCallback (button, XmNactivateCallback,
268 	(XtCallbackProc)TickLabelList_SortDownCB, (XtPointer)this);
269 #endif
270 
271     //
272     // Create a dummy drawing area in order to catch resize events.  This is
273     // necessary for scrolled windows.  Their contents' must be manually stretched
274     // horizontally when the window is resized.
275     //
276     n = 0;
277     XtSetArg (args[n], XmNtopAttachment,	XmATTACH_FORM); n++;
278     XtSetArg (args[n], XmNtopOffset,		35); n++;
279     XtSetArg (args[n], XmNleftAttachment,	XmATTACH_FORM); n++;
280     XtSetArg (args[n], XmNrightAttachment,	XmATTACH_FORM); n++;
281     XtSetArg (args[n], XmNbottomAttachment,	XmATTACH_FORM); n++;
282     XtSetArg (args[n], XmNleftOffset,		2); n++;
283     XtSetArg (args[n], XmNrightOffset,		2); n++;
284     XtSetArg (args[n], XmNbottomOffset,		2); n++;
285     XtSetArg (args[n], XmNmappedWhenManaged,	False); n++;
286     Widget drawa = XmCreateDrawingArea (form, "junk", args, n);
287     XtManageChild (drawa);
288     XtAddCallback (drawa, XmNresizeCallback,
289 	(XtCallbackProc)TickLabelList_ResizeTicksCB, (XtPointer)this);
290 
291     this->setRootWidget(form);
292 
293     ListIterator it(this->ticks);
294     TickLabel *tl;
295     while ( (tl = (TickLabel*)it.getNext()) )
296 	tl->createLine (this->listRC);
297 }
298 
299 
300 void
createLine(double dval,const char * str,int pos)301 TickLabelList::createLine (double dval, const char *str, int pos)
302 {
303     TickLabel *tl = new TickLabel (dval, str, pos,
304 	(TickSelectCB)TickLabelList::SelectCB, (void*)this);
305     ASSERT (pos);
306     ASSERT (pos <= (this->ticks.getSize() + 1));
307     this->ticks.insertElement((void *)tl, pos);
308     this->dirty|= DIRTY_APPEND;
309     if (this->listRC)
310 	tl->createLine(this->listRC);
311 
312     int newpos = this->ticks.getPosition((void*)tl);
313     ASSERT (newpos == pos);
314     this->highest_set_number = MAX(pos, this->highest_set_number);
315 
316     this->resizeCallback();
317 }
318 
319 void
SelectCB(TickLabel * tlab,void * clientData)320 TickLabelList::SelectCB (TickLabel* tlab, void* clientData)
321 {
322     ASSERT(tlab);
323     if (!tlab->isSelected()) return ;
324 
325     ASSERT(clientData);
326     TickLabelList *tll = (TickLabelList*)clientData;
327 
328     ListIterator it(tll->ticks);
329     TickLabel *nextTL;
330     while ( (nextTL = (TickLabel*)it.getNext()) ) {
331 	if ((nextTL != tlab) && (nextTL->isSelected())) {
332 	    nextTL->setSelected (FALSE, FALSE);
333 	}
334     }
335 
336     if (tll->tlmcb)
337 	tll->tlmcb (tll, tll->clientData);
338 }
339 
340 boolean
isModified()341 TickLabelList::isModified()
342 {
343     if (this->dirty) return TRUE;
344 
345     TickLabel *tl;
346     ListIterator it(this->ticks);
347 
348     while ( (tl = (TickLabel*)it.getNext()) )
349 	if (tl->isModified()) return TRUE;
350     return FALSE;
351 }
352 
353 boolean
isNumberModified()354 TickLabelList::isNumberModified()
355 {
356     if (this->dirty) return TRUE;
357 
358     TickLabel *tl;
359     ListIterator it(this->ticks);
360 
361     while ( (tl = (TickLabel*)it.getNext()) )
362 	if (tl->isNumberModified()) return TRUE;
363     return FALSE;
364 }
365 
366 boolean
isTextModified()367 TickLabelList::isTextModified()
368 {
369     if (this->dirty) return TRUE;
370 
371     TickLabel *tl;
372     ListIterator it(this->ticks);
373 
374     while ( (tl = (TickLabel*)it.getNext()) )
375 	if (tl->isTextModified()) return TRUE;
376     return FALSE;
377 }
378 
379 //
380 // Caller must not free the memory.
381 //
382 double *
getTickNumbers()383 TickLabelList::getTickNumbers()
384 {
385     if (!this->ticks.getSize()) return NULL;
386 
387     if (this->oldDvals) {
388 	delete this->oldDvals;
389 	this->oldDvals = NULL;
390     }
391 
392     ListIterator it(this->ticks);
393     TickLabel *tl;
394     double *dvals = new double[this->ticks.getSize()];
395 
396     int i = 0;
397     while ( (tl = (TickLabel*)it.getNext()) )
398 	dvals[i++] = tl->getNumber();
399 
400     return (this->oldDvals = dvals);
401 }
402 
403 //
404 // Caller must not free the memory.
405 //
406 String
getTickTextString()407 TickLabelList::getTickTextString()
408 {
409 
410     int size = this->ticks.getSize();
411     if (!size) return NULL;
412 
413     if ((!this->isTextModified())&&(this->oldString))
414 	return this->oldString;
415 
416     if (this->oldString) {
417 	delete this->oldString;
418 	this->oldString = NULL;
419     }
420 
421     boolean is_any_text_set = FALSE;
422     ListIterator it(this->ticks);
423     TickLabel *tl;
424     int len = 0;
425     const char *cp;
426     while ( (tl = (TickLabel*)it.getNext()) ) {
427 	cp = tl->getText();
428 	if (!cp) continue;
429 	len+= strlen(cp);
430 	if ((len!=2)&&(len!=0)) is_any_text_set = TRUE;
431 	else if ((len == 2) && (strcmp(cp, "\"\""))) is_any_text_set = TRUE;
432     }
433 
434     if (!is_any_text_set) {
435 	return NULL;
436     }
437 
438     int newSize = len+10 + (5*size);
439     char *buf = this->oldString = new char[newSize];
440     strcpy (buf, "{ ");
441     int bufLen = strlen(buf);
442     boolean first_loop = TRUE;
443     boolean add_quotes;
444 
445     it.setList(this->ticks);
446     while ( (tl = (TickLabel*)it.getNext()) ) {
447 	if (!first_loop) {
448 	    strcpy (&buf[bufLen], ", "); bufLen+= 2;
449 	}
450 	cp = tl->getText();
451 	len = strlen(cp);
452 	add_quotes = TRUE;
453 	if ((cp[0] == '"') && (cp[len-1] == '"')) add_quotes = FALSE;
454 	if (add_quotes) buf[bufLen++] = '"';
455 	strcpy (&buf[bufLen], cp); bufLen+= len;
456 	if (add_quotes) buf[bufLen++] = '"';
457 
458 	first_loop = FALSE;
459     }
460 
461     ASSERT (newSize > bufLen);
462     strcpy (&buf[bufLen], " }"); bufLen+= 2;
463     return this->oldString;
464 }
465 
466 void
markClean()467 TickLabelList::markClean()
468 {
469     this->dirty = 0;
470     TickLabel *tl;
471     ListIterator it(this->ticks);
472 
473     while ( (tl = (TickLabel*)it.getNext()) ) {
474 	tl->setText();
475 	tl->setNumber();
476     }
477 }
478 
479 void
markNumbersClean()480 TickLabelList::markNumbersClean()
481 {
482     TickLabel *tl;
483     ListIterator it(this->ticks);
484 
485     while ( (tl = (TickLabel*)it.getNext()) ) {
486 	tl->setNumber();
487     }
488 }
489 
490 void
markTextClean()491 TickLabelList::markTextClean()
492 {
493     TickLabel *tl;
494     ListIterator it(this->ticks);
495 
496     while ( (tl = (TickLabel*)it.getNext()) ) {
497 	tl->setText();
498     }
499 }
500 
501 void
clear()502 TickLabelList::clear()
503 {
504     ListIterator it(this->ticks);
505     TickLabel *tl;
506     while ( (tl = (TickLabel*)it.getNext()) )
507 	delete tl;
508     this->ticks.clear();
509 
510     ASSERT (this->ticks.getSize() == 0);
511     this->dirty = 0;
512 }
513 
514 void
setNumber(int pos,double dval)515 TickLabelList::setNumber (int pos, double dval)
516 {
517 int size = this->ticks.getSize();
518 
519     if (pos > size)
520 	this->setListSize (pos);
521 
522     TickLabel *tl = (TickLabel*)this->ticks.getElement(pos);
523     ASSERT(tl);
524     tl->setNumber(dval);
525 
526     this->highest_set_number = MAX(pos, this->highest_set_number);
527 }
528 
529 void
setText(int pos,char * str)530 TickLabelList::setText (int pos, char *str)
531 {
532 int size = this->ticks.getSize();
533 
534     if (pos > size)
535 	this->setListSize (pos);
536 
537     TickLabel *tl = (TickLabel*)this->ticks.getElement(pos);
538     ASSERT(tl);
539     tl->setText(str);
540 }
541 
542 void
setListSize(int new_size)543 TickLabelList::setListSize (int new_size)
544 {
545 int i, current_size = this->ticks.getSize();
546 TickLabel *tl;
547 
548     if (new_size == current_size) {
549     } else if (new_size > current_size) {
550 	for (i=current_size+1; i<=new_size; i++)
551 	    this->createLine (0.0, "", i);
552     } else {
553 	List tmpList;
554 	for (i=new_size+1; i<=current_size; i++) {
555 	    tl = (TickLabel*)this->ticks.getElement(i);
556 	    ASSERT(tl);
557 	    tmpList.appendElement((void*)tl);
558 	}
559 	ListIterator it(tmpList);
560 	while ( (tl = (TickLabel*)it.getNext()) ) {
561 	    this->ticks.removeElement((void*)tl);
562 	    delete tl;
563 	}
564     }
565 }
566 
resizeCallback()567 void TickLabelList::resizeCallback ()
568 {
569     Dimension width, height, rch;
570     Widget sw = this->listRC;
571 
572     while ((sw) && (XtClass(sw)!=xmScrolledWindowWidgetClass))
573 	sw = XtParent(sw);
574 
575     XtVaGetValues (sw, XmNwidth, &width, XmNheight, &height, NULL);
576     XtVaGetValues (this->listRC,
577 	XmNheight, &rch,
578     NULL);
579 
580     boolean scrollbar_in_use;
581     if (rch > height) scrollbar_in_use = TRUE;
582     else scrollbar_in_use = FALSE;
583 
584     if (scrollbar_in_use) {
585 	XtVaSetValues (this->listRC, XmNwidth, width-20, NULL);
586 	XtVaSetValues (this->labelLabel, XmNrightOffset, 26, NULL);
587     } else {
588 	XtVaSetValues (this->listRC, XmNwidth, width-2, NULL);
589 	XtVaSetValues (this->labelLabel, XmNrightOffset, 8, NULL);
590     }
591 }
592 
593 //
594 // Using the list of TickLabel objects, create an array.  Sort the array.
595 // Then clear the original list and rebuild it using the contents of the array.
596 //
sortList(boolean up)597 void TickLabelList::sortList (boolean up)
598 {
599 #if UI_SHOULD_SORT_TICKS
600     int size = this->ticks.getSize();
601     TickLabelList::SortUp = up;
602     ASSERT (size > 1);
603     int i;
604     TickLabel **tla = new TickLabel*[size];
605     for (i=1; i<=size; i++)
606 	tla[i-1] = (TickLabel*)this->ticks.getElement(i);
607 
608     qsort (tla, size, sizeof(TickLabel*), TickLabelList_SortFunc);
609 
610     this->ticks.clear();
611 
612     XtUnmanageChild (this->listRC);
613     for (i=0; i<size; i++) {
614 	this->ticks.appendElement((void*)tla[i]);
615 	tla[i]->destroyLine();
616     }
617     for (i=0; i<size; i++) {
618 	tla[i]->setPosition(i+1);
619 	tla[i]->createLine(this->listRC);
620     }
621     XtManageChild (this->listRC);
622 
623     this->dirty|= DIRTY_APPEND;
624 
625     delete tla;
626 #endif
627 }
628 
629 extern "C" {
630 
631 int
TickLabelList_SortFunc(const void * e1,const void * e2)632 TickLabelList_SortFunc (const void* e1, const void* e2)
633 {
634 #if UI_SHOULD_SORT_TICKS
635     TickLabel** tlp1 = (TickLabel**)e1;
636     TickLabel** tlp2 = (TickLabel**)e2;
637     TickLabel* tl1 = *tlp1;
638     TickLabel* tl2 = *tlp2;
639     double dval1 = tl1->getNumber();
640     double dval2 = tl2->getNumber();
641 
642     if (TickLabelList::SortUp) {
643 	if (dval1 > dval2) return 1;
644 	if (dval1 < dval2) return -1;
645     } else {
646 	if (dval1 < dval2) return 1;
647 	if (dval1 > dval2) return -1;
648     }
649     ASSERT (dval1 == dval2);
650 #endif
651     return 0;
652 }
653 
TickLabelList_ButtonEH(Widget,XtPointer clientData,XEvent * e,Boolean *)654 void TickLabelList_ButtonEH(Widget , XtPointer clientData,
655                                         XEvent *e, Boolean *)
656 {
657     TickLabelList *tlab = (TickLabelList *)clientData;
658     ASSERT(tlab);
659     XmMenuPosition(tlab->popupMenu , (XButtonPressedEvent *)e);
660 
661     if (e->type == ButtonRelease) XtManageChild(tlab->popupMenu);
662     else XtAppAddTimeOut (theApplication->getApplicationContext(), 100,
663         (XtTimerCallbackProc)XtManageChild, (XtPointer)tlab->popupMenu);
664 
665     //
666     // Enable/Disable certain items based on list selection.
667     //
668     TickLabel *tl;
669     ListIterator it(tlab->ticks);
670     boolean any_selected = FALSE;
671     while ((!any_selected) && (tl = (TickLabel*)it.getNext()))
672 	if (tl->isSelected()) any_selected = TRUE;
673     XtSetSensitive (tlab->aasButton, (Boolean)any_selected);
674     XtSetSensitive (tlab->iasButton, (Boolean)any_selected);
675     XtSetSensitive (tlab->dsButton,  (Boolean)any_selected);
676 
677     XtSetSensitive (tlab->daButton, (Boolean)(tlab->ticks.getSize() != 0));
678 
679 #if UI_SHOULD_SORT_TICKS
680     XtSetSensitive (tlab->suButton, (Boolean)(tlab->ticks.getSize() > 1));
681     XtSetSensitive (tlab->sdButton, (Boolean)(tlab->ticks.getSize() > 1));
682 #endif
683 }
684 
685 
686 //
687 // Horizontally resize the contents of the 3 scrolled windows in TicksLabels.
688 //
TickLabelList_ResizeTicksCB(Widget,XtPointer clientData,XtPointer)689 void TickLabelList_ResizeTicksCB(Widget , XtPointer clientData, XtPointer)
690 {
691     ASSERT(clientData);
692     TickLabelList *tll = (TickLabelList *)clientData;
693     tll->resizeCallback();
694 }
695 
TickLabelList_DeleteAllCB(Widget,XtPointer clientData,XtPointer)696 void TickLabelList_DeleteAllCB(Widget , XtPointer clientData, XtPointer)
697 {
698     ASSERT(clientData);
699     TickLabelList *tll = (TickLabelList *)clientData;
700 
701 
702     tll->clear();
703     tll->dirty|= DIRTY_DELETE;
704 
705     tll->highest_set_number = 0;
706 
707     tll->resizeCallback();
708     if (tll->tlmcb)
709 	tll->tlmcb (tll, tll->clientData);
710 }
711 
TickLabelList_AppendCB(Widget w,XtPointer clientData,XtPointer)712 void TickLabelList_AppendCB(Widget w, XtPointer clientData, XtPointer)
713 {
714     ASSERT(clientData);
715     TickLabelList *tll = (TickLabelList *)clientData;
716 
717     //
718     // Inovke the callback only if adding the first iterm.
719     //
720     boolean call_callback = FALSE;
721     int size = tll->ticks.getSize();
722     if (size == 0) call_callback = TRUE;
723 
724     int newTail;
725     XtVaGetValues (w, XmNuserData, &newTail, NULL);
726 
727     int newPos;
728     if (newTail)
729 	newPos = 1 + size;
730     else
731 	newPos = 1;
732 
733     tll->createLine (0.0, "", newPos);
734     if ((tll->tlmcb) && (call_callback))
735 	tll->tlmcb (tll, tll->clientData);
736 }
737 
TickLabelList_AppendAfterSelCB(Widget,XtPointer clientData,XtPointer)738 void TickLabelList_AppendAfterSelCB(Widget , XtPointer clientData, XtPointer)
739 {
740 int newPos;
741 
742     ASSERT(clientData);
743     TickLabelList *tll = (TickLabelList *)clientData;
744 
745     TickLabel *tl, *sel;
746     ListIterator it(tll->ticks);
747     sel = NULL;
748     newPos = 1;
749     while ( (tl = (TickLabel*)it.getNext()) ) {
750 	if (tl->isSelected()) {
751 	    sel = tl;
752 	    break;
753 	}
754 	newPos++;
755     }
756     ASSERT(sel);
757 
758     tll->createLine (0.0, "", newPos+1);
759 }
760 
TickLabelList_InsertAboveSelCB(Widget,XtPointer clientData,XtPointer)761 void TickLabelList_InsertAboveSelCB(Widget , XtPointer clientData, XtPointer)
762 {
763 int newPos;
764 
765     ASSERT(clientData);
766     TickLabelList *tll = (TickLabelList *)clientData;
767 
768     TickLabel *tl, *sel;
769     ListIterator it(tll->ticks);
770     sel = NULL;
771     newPos = 1;
772     while ( (tl = (TickLabel*)it.getNext()) ) {
773 	if (tl->isSelected()) {
774 	    sel = tl;
775 	    break;
776 	}
777 	newPos++;
778     }
779     ASSERT(sel);
780 
781     tll->createLine (0.0, "", newPos);
782 }
783 
TickLabelList_DeleteSelCB(Widget,XtPointer clientData,XtPointer)784 void TickLabelList_DeleteSelCB(Widget , XtPointer clientData, XtPointer)
785 {
786     ASSERT(clientData);
787     TickLabelList *tll = (TickLabelList *)clientData;
788 
789     TickLabel *tl, *sel;
790     ListIterator it(tll->ticks);
791     sel = NULL;
792     while ( (tl = (TickLabel*)it.getNext()) ) {
793 	if (tl->isSelected()) {
794 	    sel = tl;
795 	    break;
796 	}
797     }
798     ASSERT(sel);
799 
800     tll->ticks.removeElement((void*)sel);
801     delete sel;
802 
803     tll->resizeCallback();
804 }
805 
TickLabelList_SortUpCB(Widget,XtPointer clientData,XtPointer)806 void TickLabelList_SortUpCB(Widget , XtPointer clientData, XtPointer)
807 {
808     ASSERT(clientData);
809     TickLabelList *tll = (TickLabelList *)clientData;
810     tll->sortList(TRUE);
811 }
812 
TickLabelList_SortDownCB(Widget,XtPointer clientData,XtPointer)813 void TickLabelList_SortDownCB(Widget , XtPointer clientData, XtPointer)
814 {
815     ASSERT(clientData);
816     TickLabelList *tll = (TickLabelList *)clientData;
817     tll->sortList(FALSE);
818 }
819 
820 } // extern "C"
821