1 /*****************************************************************************
2 Major portions of this software are copyrighted by the Medical College
3 of Wisconsin, 1994-2000, and are released under the Gnu General Public
4 License, Version 2. See the file README.Copyright for details.
5 ******************************************************************************/
6
7 #undef MAIN
8 #include "afni.h"
9 #include <ctype.h>
10
11 #ifndef ALLOW_PLUGINS
12 # error "Plugins not properly set up -- see machdep.h"
13 #endif
14
15 /*-- prototypes --*/
16
17 static char * TAG_main( PLUGIN_interface * ) ;
18
19 static void TAG_make_widgets(void) ;
20
21 static void TAG_dset_CB ( Widget , XtPointer , XtPointer ) ;
22 static void TAG_quit_CB ( Widget , XtPointer , XtPointer ) ;
23 static void TAG_help_CB ( Widget , XtPointer , XtPointer ) ;
24 static void TAG_set_CB ( Widget , XtPointer , XtPointer ) ;
25 static void TAG_clear_CB ( Widget , XtPointer , XtPointer ) ;
26 static void TAG_done_CB ( Widget , XtPointer , XtPointer ) ;
27 static void TAG_tog_CB ( Widget , XtPointer , XtPointer ) ;
28 static void TAG_read_CB ( Widget , XtPointer , XtPointer ) ;
29 static void TAG_write_CB ( Widget , XtPointer , XtPointer ) ;
30 static void TAG_copy_CB ( Widget , XtPointer , XtPointer ) ;
31 static void TAG_save_CB ( Widget , XtPointer , XtPointer ) ;
32 static void TAG_clearall_CB( Widget , XtPointer , XtPointer ) ;
33 static void TAG_add_CB ( Widget , XtPointer , XtPointer ) ;
34 static void TAG_delete_CB ( Widget , XtPointer , XtPointer ) ;
35 static void TAG_relabel_CB ( Widget , XtPointer , XtPointer ) ;
36 static void TAG_beep_CB ( Widget , XtPointer , XtPointer ) ;
37
38 static void TAG_value_CB ( MCW_arrowval * , XtPointer ) ;
39 static void TAG_columnize(void) ;
40 static void TAG_reset_widgets(void) ;
41
42 static void TAG_onoff( int ) ;
43
44 /*-- Widgets for the user interface --*/
45
46 static Widget shell=NULL , thetop ;
47 static Widget dset_pb , info_lab ;
48 static Widget quit_pb, help_pb, read_pb, write_pb, copy_pb, save_pb, done_pb ;
49 static Widget set_pb, clear_pb, clearall_pb, add_pb, delete_pb, relabel_pb, beep_pb ;
50 static Widget scrollw, wframe, workwin ;
51 static Widget actar ;
52
53 static Widget * tagtog ; /* one for each possible tag */
54 static int * toginv ;
55 static int tognum = 4 ; /* default number of active toggles */
56
57 static THD_usertaglist * mytagset = NULL ; /* what we are working on */
58 static THD_usertaglist * oldtagset = NULL ; /* in case of Quit */
59
60 static PLUGIN_strval * file_strav ;
61 static PLUGIN_strval * label_strav ;
62 static MCW_arrowval * value_av ;
63
64 #define DEFAULT_INFOLAB "[No dataset has yet been selected]"
65
66 static int on_flag = 0 ;
67 static Widget * onoff_wid[] = {
68 &read_pb , &write_pb , ©_pb , &save_pb , &done_pb ,
69 &set_pb , &clear_pb , &clearall_pb ,
70 NULL } ;
71
72 #define DSET_ON SENSITIZE(dset_pb,True)
73 #define DSET_OFF do{ if( dset != NULL ) SENSITIZE(dset_pb,False) ; } while(0)
74
75 #define POPUP_MESG(mm) MCW_popup_message(save_pb,(mm),MCW_USER_KILL|MCW_TIMER_KILL)
76
77 /*-- Other Data --*/
78
79 static PLUGIN_interface * plint = NULL ;
80
81 static int value_int = 0 ; /* from value_av */
82 static float value_float = 0.0 ; /* ditto */
83 static int active_tog = -1 ; /* active toggle index */
84
85 static int editor_open = 0 ; /* is the editor already on screen? */
86
87 static MCW_DC * dc ;
88 static Three_D_View * im3d ;
89 static THD_3dim_dataset * dset = NULL ;
90
91 /***********************************************************************
92 Set up the interface to the user. Note that we bypass the
93 normal interface creation, and simply have the menu selection
94 directly call the main function, which will create a custom
95 set of interface widgets.
96 ************************************************************************/
97
98
99 DEFINE_PLUGIN_PROTOTYPE
100
PLUGIN_init(int ncall)101 PLUGIN_interface * PLUGIN_init( int ncall )
102 {
103 if( ncall > 0 ) return NULL ; /* only one interface */
104
105 plint = PLUTO_new_interface( "Edit Tagset" , NULL , NULL ,
106 PLUGIN_CALL_IMMEDIATELY , TAG_main ) ;
107
108 PLUTO_add_hint( plint , "Interactive Tagset Editor" ) ;
109
110 PLUTO_set_sequence( plint , "A:misc" ) ;
111 return plint ;
112 }
113
114 /*--------------------------------------------------------------------------*/
115
TAG_main(PLUGIN_interface * plint)116 static char * TAG_main( PLUGIN_interface * plint )
117 {
118 int ii ;
119 XmString xstr ;
120
121 /*-- sanity checks --*/
122
123 if( ! IM3D_OPEN(plint->im3d) ) return "AFNI Controller\nnot opened?!" ;
124
125 if( editor_open ){
126 XtMapWidget(shell) ;
127 XRaiseWindow( XtDisplay(shell) , XtWindow(shell) ) ;
128 return NULL ;
129 }
130
131 im3d = plint->im3d ; /* save for local use */
132
133 /*-- create widgets, first time through --*/
134
135 if( shell == NULL ){
136 dc = im3d->dc ; /* save this too */
137 if( mytagset == NULL ) mytagset = myXtNew(THD_usertaglist) ;
138 if( oldtagset == NULL ) oldtagset = myXtNew(THD_usertaglist) ;
139 TAG_make_widgets() ;
140 PLUTO_set_topshell( plint , shell ) ; /* 22 Sep 2000 */
141 RWC_visibilize_widget( shell ) ; /* 27 Sep 2000 */
142 }
143
144 /*-- set titlebar --*/
145
146 { char ttl[PLUGIN_STRING_SIZE] ;
147 sprintf( ttl , "Tagset Editor %s" , AFNI_controller_label(im3d) ) ;
148 XtVaSetValues( shell , XmNtitle , ttl , NULL ) ;
149 }
150
151 /*-- reset the info label --*/
152
153 xstr = XmStringCreateLtoR( DEFAULT_INFOLAB , XmFONTLIST_DEFAULT_TAG ) ;
154 XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
155 XmStringFree(xstr) ;
156
157 /*-- pop the widgets up --*/
158
159 TAG_onoff(0) ; /* widgets off until a dataset is selected */
160 DSET_ON ;
161 SENSITIZE(beep_pb,True) ;
162 tognum = mytagset->num ;
163 TAG_reset_widgets() ;
164
165 XtMapWidget(shell) ;
166 PLUTO_cursorize(shell) ;
167
168 /*-- misc initialization --*/
169
170 dset = NULL ; /* not editing anything */
171 editor_open = 1 ; /* editor is now open for business */
172
173 active_tog = -1 ;
174 for( ii=0 ; ii < tognum ; ii++ ){
175 if( XmToggleButtonGetState( tagtog[ii] ) ){ active_tog = ii; break; }
176 }
177
178 oldtagset->num = 0 ;
179 return NULL ;
180 }
181
182 /*--------------------------------------------------------------------------
183 Make the plugin user interface
184 ----------------------------------------------------------------------------*/
185
186 /*-- structures defining 1st set of action buttons --*/
187
188 #define NACT1 7 /* number of action buttons */
189
190 static MCW_action_item TAG_actor1[NACT1] = {
191 {"Quit",TAG_quit_CB,NULL,
192 "Discard changes\nand close Tag plugin" ,
193 "Discard changes & close",0} ,
194
195 {"Help",TAG_help_CB,NULL,
196 "Displays more help" , "Displays more help",0} ,
197
198 {"Read",TAG_read_CB,NULL,
199 "Read a tagset from disk" , "Read tagset from disk",0} ,
200
201 {"Write",TAG_write_CB,NULL,
202 "Write the tagset to disk" , "Write tagset to disk",0} ,
203
204 {"Copy",TAG_copy_CB,NULL,
205 "Copy tagset from another dataset" , "Copy from another dataset",0} ,
206
207 {"Save",TAG_save_CB,NULL,
208 "Save tagset in dataset header" , "Save tagset in dataset header",0} ,
209
210 {"Done",TAG_done_CB,NULL,
211 "Save changes in dataset\nand close Tag plugin" , "Save and close",1}
212 } ;
213
214 /*-- structures defining 2nd set of action buttons --*/
215
216 #define NACT2 7 /* number of action buttons */
217
218 static MCW_action_item TAG_actor2[NACT2] = {
219
220 {"Set",TAG_set_CB,NULL,
221 "Set the selected tag at the\ncurrent crosshair location" ,
222 "Sets selected tag" , 0 } ,
223
224 {"Clear",TAG_clear_CB,NULL,
225 "Clears the selected tag\n(opposite of Set)" ,
226 "Clears selected tag" , 0 } ,
227
228 {"Clr All",TAG_clearall_CB,NULL,
229 "Clears all tags (opposite of Set)" ,
230 "Clears all tags" , 0 } ,
231
232 {"Add",TAG_add_CB,NULL,
233 "Add a new tag at\nthe end of list" ,
234 "Add new tag at end" , 0 } ,
235
236 {"Delete",TAG_delete_CB,NULL,
237 "Remove the last\ntag from the list" ,
238 "Remove last tag" , 0 } ,
239
240 {"Relabel",TAG_relabel_CB,NULL,
241 "Changes label of selected tag;\nUse after editing Tag Label\nstring field below",
242 "Changes label of selected tag", 0 } ,
243
244 {"Beep",TAG_beep_CB,NULL, NULL , NULL , 0 }
245 } ;
246
247 /*--------------------------------------------------------------------------*/
248
TAG_make_widgets(void)249 static void TAG_make_widgets(void)
250 {
251 XmString xstr ;
252 char tlab[MAX_TAG_LABEL] ;
253 int ii , ww , hh ;
254 Pixel fg_pix=0 ;
255 Widget wjunk ;
256
257 /*** top level shell for window manager ***/
258
259 shell =
260 XtVaAppCreateShell(
261 "AFNI" , "AFNI" , topLevelShellWidgetClass , dc->display ,
262
263 XmNtitle , "AFNI Editor" , /* top of window */
264 XmNiconName , "Editor" , /* label on icon */
265 XmNdeleteResponse , XmDO_NOTHING , /* deletion handled below */
266 XmNallowShellResize , False , /* let code resize shell? */
267 XmNmappedWhenManaged , False , /* must map it manually */
268 XmNinitialResourcesPersistent , False ,
269 NULL ) ;
270
271 DC_yokify( shell , dc ) ;
272
273 if( afni48_good ) /* set icon pixmap */
274 XtVaSetValues( shell ,
275 XmNiconPixmap , afni48_pixmap ,
276 NULL ) ;
277
278 if( MCW_isitmwm(shell) ) /* remove some MWM functions */
279 XtVaSetValues( shell ,
280 XmNmwmFunctions , MWM_FUNC_MOVE |
281 MWM_FUNC_CLOSE |
282 MWM_FUNC_MINIMIZE |
283 MWM_FUNC_RESIZE ,
284 NULL ) ;
285
286 XmAddWMProtocolCallback( /* make "Close" window menu work */
287 shell ,
288 XmInternAtom( dc->display , "WM_DELETE_WINDOW" , False ) ,
289 TAG_quit_CB , (XtPointer) plint ) ;
290
291 /*** form widget to hold all user interface stuff ***/
292
293 thetop = XtVaCreateWidget(
294 "AFNI" , xmFormWidgetClass , shell ,
295 XmNborderWidth , 0 ,
296 XmNborderColor , 0 ,
297 XmNtraversalOn , True ,
298 XmNinitialResourcesPersistent , False ,
299 NULL ) ;
300
301 /*** pushbutton to select dataset for tagging ***/
302
303 xstr = XmStringCreateLtoR( "Dataset" , XmFONTLIST_DEFAULT_TAG ) ;
304 dset_pb = XtVaCreateManagedWidget(
305 "AFNI" , xmPushButtonWidgetClass , thetop ,
306 XmNlabelString , xstr ,
307 XmNmarginHeight , 4 ,
308 XmNmarginWidth , 4 ,
309 XmNtraversalOn , True ,
310 XmNinitialResourcesPersistent , False ,
311 XmNleftAttachment , XmATTACH_FORM ,
312 XmNtopAttachment , XmATTACH_FORM ,
313 XmNtopOffset , 7 ,
314 XmNleftOffset , 5 ,
315 NULL ) ;
316 XmStringFree(xstr) ;
317
318 XtAddCallback( dset_pb , XmNactivateCallback , TAG_dset_CB , NULL ) ;
319
320 MCW_register_help( dset_pb , "Select dataset for tagging" ) ;
321 MCW_register_hint( dset_pb , "Select dataset" ) ;
322
323 /*** label at top to let user know who we are ***/
324
325 xstr = XmStringCreateLtoR( DEFAULT_INFOLAB , XmFONTLIST_DEFAULT_TAG ) ;
326 info_lab = XtVaCreateManagedWidget(
327 "AFNI" , xmLabelWidgetClass , thetop ,
328 XmNleftAttachment , XmATTACH_WIDGET ,
329 XmNleftWidget , dset_pb ,
330 XmNleftOffset , 10 ,
331 XmNtopAttachment , XmATTACH_FORM ,
332 XmNtopOffset , 5 ,
333 XmNrightAttachment, XmATTACH_FORM ,
334 XmNlabelString , xstr ,
335 XmNmarginHeight , 1 ,
336 XmNalignment , XmALIGNMENT_BEGINNING ,
337 XmNrecomputeSize , True ,
338 XmNinitialResourcesPersistent , False ,
339 NULL ) ;
340 XmStringFree(xstr) ;
341 MCW_register_help( info_lab , "Shows dataset being tagged" ) ;
342 MCW_register_hint( info_lab , "Shows dataset being tagged" ) ;
343
344 /*** separator for visual neatness ***/
345
346 wjunk = XtVaCreateManagedWidget(
347 "AFNI" , xmSeparatorWidgetClass , thetop ,
348 XmNseparatorType , XmSINGLE_LINE ,
349 XmNleftAttachment , XmATTACH_FORM ,
350 XmNrightAttachment, XmATTACH_FORM ,
351 XmNtopAttachment , XmATTACH_WIDGET ,
352 XmNtopWidget , dset_pb ,
353 XmNtopOffset , 5 ,
354 XmNinitialResourcesPersistent , False ,
355 NULL ) ;
356
357 /*** 1st set of action buttons below the line ***/
358
359 actar = MCW_action_area( thetop , TAG_actor1 , NACT1 ) ;
360
361 XtVaSetValues( actar ,
362 XmNleftAttachment , XmATTACH_FORM ,
363 XmNrightAttachment, XmATTACH_FORM ,
364 XmNtopAttachment , XmATTACH_WIDGET ,
365 XmNtopOffset , 5 ,
366 XmNtopWidget , wjunk ,
367 NULL ) ;
368
369 quit_pb = (Widget) TAG_actor1[0].data ; /* save individual buttons */
370 help_pb = (Widget) TAG_actor1[1].data ;
371 read_pb = (Widget) TAG_actor1[2].data ;
372 write_pb = (Widget) TAG_actor1[3].data ;
373 copy_pb = (Widget) TAG_actor1[4].data ;
374 save_pb = (Widget) TAG_actor1[5].data ;
375 done_pb = (Widget) TAG_actor1[6].data ;
376
377 /*** separator for visual neatness ***/
378
379 wjunk = XtVaCreateManagedWidget(
380 "AFNI" , xmSeparatorWidgetClass , thetop ,
381 XmNseparatorType , XmSINGLE_LINE ,
382 XmNleftAttachment , XmATTACH_FORM ,
383 XmNrightAttachment, XmATTACH_FORM ,
384 XmNtopAttachment , XmATTACH_WIDGET ,
385 XmNtopWidget , actar ,
386 XmNtopOffset , 5 ,
387 XmNinitialResourcesPersistent , False ,
388 NULL ) ;
389
390 /*** 2nd set of action buttons ***/
391
392 actar = MCW_action_area( thetop , TAG_actor2 , NACT2 ) ;
393
394 XtVaSetValues( actar ,
395 XmNleftAttachment , XmATTACH_FORM ,
396 XmNrightAttachment, XmATTACH_FORM ,
397 XmNtopAttachment , XmATTACH_WIDGET ,
398 XmNtopOffset , 5 ,
399 XmNtopWidget , wjunk ,
400 NULL ) ;
401
402 set_pb = (Widget) TAG_actor2[0].data ; /* save individual buttons */
403 clear_pb = (Widget) TAG_actor2[1].data ;
404 clearall_pb= (Widget) TAG_actor2[2].data ;
405 add_pb = (Widget) TAG_actor2[3].data ;
406 delete_pb = (Widget) TAG_actor2[4].data ;
407 relabel_pb = (Widget) TAG_actor2[5].data ;
408 beep_pb = (Widget) TAG_actor2[6].data ;
409
410 /*** separator for visual neatness ***/
411
412 wjunk = XtVaCreateManagedWidget(
413 "AFNI" , xmSeparatorWidgetClass , thetop ,
414 XmNseparatorType , XmSINGLE_LINE ,
415 XmNleftAttachment , XmATTACH_FORM ,
416 XmNrightAttachment, XmATTACH_FORM ,
417 XmNtopAttachment , XmATTACH_WIDGET ,
418 XmNtopWidget , actar ,
419 XmNtopOffset , 5 ,
420 XmNinitialResourcesPersistent , False ,
421 NULL ) ;
422
423 /*** string chooser for tagset filename ***/
424
425 file_strav = new_PLUGIN_strval( thetop , "Tag File: " ) ;
426 alter_PLUGIN_strval_width( file_strav , 37 ) ;
427
428 MCW_reghelp_children( file_strav->rowcol ,
429 "Use this to enter the tagset filename\n"
430 "before using the Read or Write buttons.\n"
431 "(Tagset filenames must end in '.tag'.)"
432 ) ;
433 MCW_reghint_children( file_strav->rowcol , "Used with Read/Write buttons" ) ;
434
435 XtVaSetValues( file_strav->rowcol ,
436 XmNleftAttachment , XmATTACH_FORM ,
437 XmNrightAttachment, XmATTACH_FORM ,
438 XmNtopAttachment , XmATTACH_WIDGET ,
439 XmNtopOffset , 5 ,
440 XmNtopWidget , wjunk ,
441 NULL ) ;
442
443 /*** string chooser for relabeling tags ***/
444
445 label_strav = new_PLUGIN_strval( thetop , "Tag Label: " ) ;
446 alter_PLUGIN_strval_width( label_strav , 37 ) ;
447
448 MCW_reghelp_children( label_strav->rowcol ,
449 "Use this to enter the new tag label\n"
450 "before using the Relabel button."
451 ) ;
452 MCW_reghint_children( label_strav->rowcol , "Used with Relabel button" ) ;
453
454 XtVaSetValues( label_strav->rowcol ,
455 XmNleftAttachment , XmATTACH_FORM ,
456 XmNrightAttachment, XmATTACH_FORM ,
457 XmNtopAttachment , XmATTACH_WIDGET ,
458 XmNtopOffset , 5 ,
459 XmNtopWidget , file_strav->rowcol ,
460 NULL ) ;
461
462 /*** arrowval to choose value that is drawn into dataset voxels ***/
463
464 value_av = new_MCW_arrowval( thetop , "Tag Value: " ,
465 MCW_AV_downup , -32767,32767,value_int ,
466 MCW_AV_editext , 0 ,
467 TAG_value_CB , NULL , NULL,NULL ) ;
468
469 MCW_reghelp_children( value_av->wrowcol ,
470 "Use this to set the value that\n"
471 "will be associated with a tag."
472 ) ;
473 MCW_reghint_children( value_av->wrowcol , "Value associated with tag" ) ;
474
475 XtVaSetValues( value_av->wrowcol ,
476 XmNleftAttachment , XmATTACH_FORM ,
477 XmNrightAttachment, XmATTACH_FORM ,
478 XmNtopAttachment , XmATTACH_WIDGET ,
479 XmNtopOffset , 5 ,
480 XmNtopWidget , label_strav->rowcol ,
481 NULL ) ;
482
483 /*** separator for visual neatness ***/
484
485 wjunk = XtVaCreateManagedWidget(
486 "AFNI" , xmSeparatorWidgetClass , thetop ,
487 XmNseparatorType , XmSINGLE_LINE ,
488 XmNleftAttachment , XmATTACH_FORM ,
489 XmNrightAttachment, XmATTACH_FORM ,
490 XmNtopAttachment , XmATTACH_WIDGET ,
491 XmNtopWidget , value_av->wrowcol ,
492 XmNtopOffset , 5 ,
493 XmNinitialResourcesPersistent , False ,
494 NULL ) ;
495
496 /*** scrolled window to hold the tag selectors ***/
497
498 scrollw =
499 XtVaCreateWidget(
500 "AFNI" , xmScrolledWindowWidgetClass , thetop ,
501 XmNscrollingPolicy , XmAUTOMATIC ,
502 XmNleftAttachment , XmATTACH_FORM ,
503 XmNrightAttachment , XmATTACH_FORM ,
504 XmNtopAttachment , XmATTACH_WIDGET ,
505 XmNbottomAttachment, XmATTACH_FORM ,
506 XmNtopWidget , wjunk ,
507 XmNtopOffset , 5 ,
508 XmNtraversalOn , True ,
509 XmNinitialResourcesPersistent , False ,
510 NULL ) ;
511
512 wframe =
513 XtVaCreateWidget(
514 "AFNI" , xmFrameWidgetClass , scrollw ,
515 XmNshadowType , XmSHADOW_ETCHED_IN ,
516 XmNshadowThickness , 5 ,
517 XmNtraversalOn , True ,
518 XmNinitialResourcesPersistent , False ,
519 NULL ) ;
520
521 workwin =
522 XtVaCreateWidget(
523 "AFNI" , xmRowColumnWidgetClass , wframe ,
524 XmNpacking , XmPACK_COLUMN ,
525 XmNnumColumns , 1 ,
526 XmNorientation , XmVERTICAL ,
527 XmNtraversalOn , True ,
528 XmNinitialResourcesPersistent , False ,
529 NULL ) ;
530
531 XtVaGetValues( workwin , XmNforeground , &fg_pix , NULL ) ;
532
533 XtVaSetValues( workwin ,
534 XmNradioBehavior , True ,
535 XmNradioAlwaysOne , False ,
536 XmNspacing , 1 ,
537 XmNmarginHeight , 0 ,
538 XmNmarginWidth , 0 ,
539 NULL ) ;
540
541 /*** array of toggles for each possible tag ***/
542
543 tagtog = (Widget *) XtMalloc( sizeof(Widget) * MAX_TAG_NUM ) ;
544 toginv = (int *) XtMalloc( sizeof(int) * MAX_TAG_NUM ) ;
545
546 for( ii=0 ; ii < MAX_TAG_NUM ; ii++ ){
547 sprintf(tlab,"Tag #%d",ii) ;
548 xstr = XmStringCreateLtoR( tlab , XmFONTLIST_DEFAULT_TAG ) ;
549
550 tagtog[ii] =
551 XtVaCreateWidget(
552 "dialog" , xmToggleButtonWidgetClass , workwin ,
553 XmNlabelString , xstr ,
554 XmNvisibleWhenOff , True ,
555 XmNmarginHeight , 0 ,
556 XmNmarginWidth , 0 ,
557 #if 0
558 XmNselectColor , fg_pix ,
559 #endif
560 XmNtraversalOn , True ,
561 XmNinitialResourcesPersistent , False ,
562 NULL ) ;
563
564 XmStringFree(xstr) ;
565 toginv[ii] = 0 ;
566 XtAddCallback( tagtog[ii] , XmNdisarmCallback , TAG_tog_CB , NULL ) ;
567
568 if( ii < tognum ) XtManageChild( tagtog[ii] ) ;
569
570 mytagset->tag[ii].set = 0 ;
571 mytagset->tag[ii].ti = 0 ;
572 mytagset->tag[ii].x = 0.0 ;
573 mytagset->tag[ii].y = 0.0 ;
574 mytagset->tag[ii].z = 0.0 ;
575 mytagset->tag[ii].val = 0.0 ;
576 strcpy( mytagset->tag[ii].label , tlab ) ;
577 }
578 mytagset->num = tognum ;
579 strcpy( mytagset->label , "Tar-Palantir" ) ;
580
581 /*** that's almost all ***/
582
583 XtManageChild( workwin ) ;
584 XtManageChild( wframe ) ;
585 XtManageChild( scrollw ) ;
586 XtManageChild( thetop ) ;
587
588 XtRealizeWidget( shell ) ; NI_sleep(1) ; /* will not be mapped */
589
590 /** set up widths and heights **/
591
592 { XmFontList xflist=(XmFontList)NULL ;
593
594 for( ii=0 ; ii < MAX_TAG_LABEL-1 ; ii++ ) tlab[ii] = 'X' ;
595 tlab[MAX_TAG_LABEL-1] = '\0' ;
596
597 xstr = XmStringCreateLtoR( tlab , XmFONTLIST_DEFAULT_TAG ) ;
598
599 XtVaGetValues( thetop , XmNbuttonFontList , &xflist , NULL ) ;
600 hh = XmStringHeight( xflist , xstr ) ;
601 ww = XmStringWidth ( xflist , xstr ) ;
602 XmStringFree(xstr) ;
603 }
604
605 XtVaSetValues( shell ,
606 XmNminWidth , ww+19*hh , /* semi-empirical numbers; */
607 XmNwidth , ww+23*hh , /* all primes (for luck) */
608 XmNminHeight , 23*hh ,
609 XmNheight , 29*hh ,
610 NULL ) ;
611
612 TAG_columnize() ;
613 return ;
614 }
615
616 /*--------------------------------------------------------------------------*/
617
TAG_redraw(void)618 static void TAG_redraw(void)
619 {
620 if( dset == NULL ) return ;
621
622 if( dset->tagset == NULL ) dset->tagset = myXtNew(THD_usertaglist) ;
623
624 *(dset->tagset) = *mytagset ; /* copy all data in one swell foop */
625
626 PLUTO_dset_redisplay_mode( dset , REDISPLAY_OVERLAY ) ;
627 return ;
628 }
629
630 /*--------------------------------------------------------------------------*/
631
TAG_quit_CB(Widget w,XtPointer client_data,XtPointer call_data)632 static void TAG_quit_CB( Widget w, XtPointer client_data, XtPointer call_data )
633 {
634 if( editor_open ){
635 if( dset != NULL && dset->tagset != NULL ){
636 *(dset->tagset) = *oldtagset ;
637 if( dset->tagset->num == 0 ) myXtFree(dset->tagset) ;
638 PLUTO_dset_redisplay_mode( dset , REDISPLAY_OVERLAY ) ;
639 }
640 XtUnmapWidget( shell ) ; editor_open = 0 ; dset = NULL ;
641 oldtagset->num = 0 ;
642 }
643 return ;
644 }
645
646 /*--------------------------------------------------------------------------*/
647
TAG_value_CB(MCW_arrowval * av,XtPointer cd)648 static void TAG_value_CB( MCW_arrowval * av , XtPointer cd )
649 {
650 value_int = av->ival ;
651 value_float = av->fval ;
652
653 if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
654 return ;
655 }
656
657 /*--------------------------------------------------------------------------*/
658
TAG_columnize(void)659 static void TAG_columnize(void)
660 {
661 int nc = (tognum < 21) ? 1 : 2 ;
662 XtVaSetValues( workwin , XmNnumColumns , nc , NULL ) ;
663 return ;
664 }
665
666 /*--------------------------------------------------------------------------*/
667
668 #define UNSET(j) \
669 do{ XmToggleButtonSetState( tagtog[(j)] , 0 , False ) ; \
670 mytagset->tag[(j)].set = 0 ; \
671 if( active_tog == (j) ) active_tog = -1 ; \
672 if( toginv[(j)] ){ toginv[(j)] = 0; MCW_invert_widget( tagtog[(j)] ); } \
673 } while(0)
674
675 /*--------------------------------------------------------------------------*/
676
TAG_add_CB(Widget w,XtPointer client_data,XtPointer call_data)677 static void TAG_add_CB( Widget w, XtPointer client_data, XtPointer call_data )
678 {
679 if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
680
681 if( tognum >= MAX_TAG_NUM ){
682 char buf[64] ;
683 sprintf(buf,"Maximum number of\nallowed tags is %d",MAX_TAG_NUM) ;
684 POPUP_MESG(buf) ; BEEPIT ;
685 return ;
686 }
687
688 UNSET(tognum) ;
689 XtManageChild( tagtog[tognum] ) ;
690 tognum++ ; mytagset->num = tognum ; TAG_columnize() ; DSET_OFF ;
691 return ;
692 }
693
694 /*--------------------------------------------------------------------------*/
695
TAG_delete_CB(Widget w,XtPointer client_data,XtPointer call_data)696 static void TAG_delete_CB( Widget w, XtPointer client_data, XtPointer call_data )
697 {
698 if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
699
700 if( tognum <= 1 ){
701 POPUP_MESG("You can't delete the\nonly remaining tag!") ;
702 BEEPIT ; return ;
703 }
704
705 UNSET(tognum-1) ;
706 XtUnmanageChild( tagtog[tognum-1] ) ;
707 tognum-- ; mytagset->num = tognum ; TAG_columnize() ;
708 TAG_redraw() ; DSET_OFF ;
709 return ;
710 }
711
712 /*--------------------------------------------------------------------------*/
713
TAG_set_CB(Widget w,XtPointer client_data,XtPointer call_data)714 static void TAG_set_CB( Widget w, XtPointer client_data, XtPointer call_data )
715 {
716 int ii = active_tog ;
717
718 if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
719
720 if( ii < 0 || ii >= tognum ){
721 BEEPIT ;
722 POPUP_MESG( "Can't set a tag\nuntil one is selected" ) ;
723 return ;
724 }
725
726 mytagset->tag[ii].set = 1 ;
727 mytagset->tag[ii].ti = im3d->vinfo->time_index ;
728 mytagset->tag[ii].x = im3d->vinfo->xi ;
729 mytagset->tag[ii].y = im3d->vinfo->yj ;
730 mytagset->tag[ii].z = im3d->vinfo->zk ;
731 mytagset->tag[ii].val = value_float ;
732
733 if( !toginv[ii] ){ toginv[ii] = 1 ; MCW_invert_widget( tagtog[ii] ) ; }
734
735 DSET_OFF ; TAG_redraw() ;
736 return ;
737 }
738
739 /*--------------------------------------------------------------------------*/
740
TAG_clear_CB(Widget w,XtPointer client_data,XtPointer call_data)741 static void TAG_clear_CB( Widget w, XtPointer client_data, XtPointer call_data )
742 {
743 int ii=active_tog , oldset ;
744
745 if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
746
747 if( ii < 0 || ii >= tognum ){
748 BEEPIT ;
749 POPUP_MESG( "Can't clear a tag\nuntil one is selected" ) ;
750 return ;
751 }
752
753 oldset = mytagset->tag[ii].set ;
754 mytagset->tag[ii].set = 0 ;
755
756 if( toginv[ii] ){ toginv[ii] = 0 ; MCW_invert_widget( tagtog[ii] ) ; }
757
758 if( oldset ){ TAG_redraw() ; DSET_OFF ; }
759 return ;
760 }
761
762 /*--------------------------------------------------------------------------*/
763
TAG_clearall_CB(Widget w,XtPointer client_data,XtPointer call_data)764 static void TAG_clearall_CB( Widget w, XtPointer client_data, XtPointer call_data )
765 {
766 int ii , oldset=0 ;
767
768 if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
769
770 if( tognum < 1 ){ BEEPIT ; return ; } /* should not occur */
771
772 for( ii=0 ; ii < tognum ; ii++ ){
773 if( mytagset->tag[ii].set ) oldset++ ;
774 mytagset->tag[ii].set = 0 ;
775 if( toginv[ii] ){ toginv[ii] = 0 ; MCW_invert_widget( tagtog[ii] ) ; }
776 }
777
778 if( oldset ){ TAG_redraw() ; DSET_OFF ; }
779 return ;
780 }
781
782 /*--------------------------------------------------------------------------*/
783
TAG_relabel_CB(Widget w,XtPointer client_data,XtPointer call_data)784 static void TAG_relabel_CB( Widget w, XtPointer client_data, XtPointer call_data )
785 {
786 char * str=get_PLUGIN_strval(label_strav) ;
787 int ii=active_tog , ll,kk,nn ;
788 XmString xstr ;
789
790 if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
791
792 if( str == NULL ){ BEEPIT ; return ; } /* should not occur */
793
794 if( str[0] == '\0' || ii < 0 || ii >= tognum ){
795 BEEPIT; XtFree(str);
796 POPUP_MESG( "Can't relabel a tag unless\n"
797 "one is selected AND a new\n"
798 "label is typed in" ) ;
799 return;
800 }
801
802 ll = strlen(str) ;
803 if( ll >= MAX_TAG_LABEL ){ str[MAX_TAG_LABEL-1] = '\0'; ll = strlen(str); }
804 for( kk=nn=0 ; kk < ll ; kk++ ) if( isspace(str[kk]) ) nn++ ;
805 if( nn == ll ){
806 BEEPIT; XtFree(str);
807 POPUP_MESG( "Can't relabel a\ntag to all blanks!" ) ;
808 return ;
809 }
810
811 xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
812 XtVaSetValues( tagtog[ii] , XmNlabelString , xstr , NULL ) ;
813 XmStringFree(xstr) ;
814
815 strcpy( mytagset->tag[ii].label , str ) ;
816 XtFree(str) ; DSET_OFF ;
817 return ;
818 }
819
820 /*--------------------------------------------------------------------------*/
821
TAG_tog_CB(Widget w,XtPointer client_data,XtPointer call_data)822 static void TAG_tog_CB( Widget w, XtPointer client_data, XtPointer call_data )
823 {
824 int ii ;
825
826 if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
827
828 for( ii=0 ; ii < tognum ; ii++ ){
829 if( XmToggleButtonGetState( tagtog[ii] ) ){ /* found it */
830 active_tog = ii ;
831 if( mytagset->tag[ii].set ){ /* if already set */
832 AFNI_jumpto_dicom( im3d , mytagset->tag[ii].x ,
833 mytagset->tag[ii].y , mytagset->tag[ii].z ) ;
834
835 AV_assign_fval( value_av , mytagset->tag[ii].val ) ;
836 value_int = value_av->ival ;
837 value_float = value_av->fval ;
838 }
839 return ;
840 }
841 }
842
843 active_tog = -1 ; return ; /* found nothing */
844 }
845
846 /*--------------------------------------------------------------------------*/
847
TAG_write_CB(Widget w,XtPointer client_data,XtPointer call_data)848 static void TAG_write_CB( Widget w, XtPointer client_data, XtPointer call_data )
849 {
850 char * str=get_PLUGIN_strval(file_strav) , * cpt ;
851 int ii , jj , ltop ;
852 FILE * fp ;
853
854 if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
855
856 if( str == NULL ){ BEEPIT ; return ; } /* should not occur */
857
858 if( str[0] == '\0' || tognum < 1 ){
859 XtFree(str) ; BEEPIT ;
860 POPUP_MESG( "Can't write tags to a file\n"
861 "until a filename is typed in" ) ;
862 return ;
863 }
864
865 cpt = strstr( str , ".tag" ) ;
866 if( cpt == NULL ){
867 ii = strlen(str) ;
868 cpt = XtMalloc(ii+8) ;
869 strcpy(cpt,str) ;
870 if( cpt[ii-1] != '.' ) strcat( cpt , "." ) ;
871 strcat( cpt , "tag" ) ;
872 XtFree(str) ;
873 str = cpt ;
874 }
875
876 if( !THD_filename_ok(str) ){
877 XtFree(str) ; BEEPIT ;
878 POPUP_MESG( "The filename you entered\nhas illegal characters!" ) ;
879 return ;
880 }
881
882 fp = fopen( str , "w" ) ;
883 if( fp == NULL ){
884 XtFree(str) ; BEEPIT ;
885 POPUP_MESG( "Can't open output file!\n" ) ;
886 return ;
887 }
888
889 ltop = 6 ;
890 for( ii=0 ; ii < tognum ; ii++ ){
891 jj = strlen( mytagset->tag[ii].label ) ;
892 ltop = MAX( jj , ltop ) ;
893 }
894
895 cpt = XtMalloc( MAX_TAG_LABEL+256 ) ;
896
897 strcpy(cpt,"# Label") ;
898 for( jj=strlen(cpt) ; jj < ltop+2 ; jj++ )
899 strcat( cpt , "_" ) ;
900 strcat(cpt," ") ;
901 strcat(cpt," _____x_____ _____y_____ _____z_____ ____val____ _t_") ;
902 fprintf(fp,"%s\n",cpt) ;
903
904 for( ii=0 ; ii < tognum ; ii++ ){
905 strcpy( cpt , "'" ) ;
906 strcat( cpt , mytagset->tag[ii].label ) ;
907 strcat( cpt , "'" ) ;
908
909 if( mytagset->tag[ii].set ){
910 for( jj=strlen(cpt) ; jj < ltop+4 ; jj++ )
911 strcat( cpt , " " ) ;
912
913 fprintf(fp , "%s %11.4g %11.4g %11.4g %11.4g %3d\n" ,
914 cpt, mytagset->tag[ii].x, mytagset->tag[ii].y, mytagset->tag[ii].z,
915 mytagset->tag[ii].val, mytagset->tag[ii].ti ) ;
916 } else {
917 fprintf(fp , "%s\n" , cpt ) ;
918 }
919 }
920
921 fclose(fp) ; XtFree(cpt) ;
922 fprintf(stderr,"Wrote tag file %s\n",str) ;
923 XtFree(str) ; return ;
924 }
925
926 /*--------------------------------------------------------------------------*/
927
TAG_reset_widgets(void)928 static void TAG_reset_widgets(void)
929 {
930 int ii ;
931 XmString xstr ;
932
933 XtUnmanageChild(wframe) ;
934
935 for( ii=0 ; ii < tognum ; ii++ ){
936
937 XtManageChild( tagtog[ii] ) ;
938 XmToggleButtonSetState( tagtog[ii] , 0 , False ) ;
939
940 if( mytagset->tag[ii].set && !toginv[ii] ){
941 toginv[ii] = 1; MCW_invert_widget( tagtog[ii] );
942 } else if( !mytagset->tag[ii].set && toginv[ii] ){
943 toginv[ii] = 0; MCW_invert_widget( tagtog[ii] );
944 }
945
946 xstr = XmStringCreateLtoR( mytagset->tag[ii].label , XmFONTLIST_DEFAULT_TAG ) ;
947 XtVaSetValues( tagtog[ii] , XmNlabelString , xstr , NULL ) ;
948 XmStringFree(xstr) ;
949 }
950
951 for( ; ii < MAX_TAG_NUM ; ii++ ){
952 UNSET(ii) ;
953 XtUnmanageChild( tagtog[ii] ) ;
954 }
955
956 TAG_columnize() ; XtManageChild(wframe) ;
957 active_tog = -1 ; return ;
958 }
959
960 /*--------------------------------------------------------------------------*/
961
TAG_read_CB(Widget w,XtPointer client_data,XtPointer call_data)962 static void TAG_read_CB( Widget w, XtPointer client_data, XtPointer call_data )
963 {
964 char * str=get_PLUGIN_strval(file_strav) , * cpt , buf[256] , quote ;
965 int ii , jj , ntog , lbuf , kk ;
966 FILE * fp ;
967 char new_label[MAX_TAG_LABEL] ;
968 float new_x , new_y , new_z , new_val ;
969 int new_ti , new_set ;
970 XmString xstr ;
971
972 /*-- sanity checks --*/
973
974 if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
975
976 if( str == NULL ){ BEEPIT ; return ; } /* should not happen */
977
978 if( str[0] == '\0' ){
979 XtFree(str) ; BEEPIT ;
980 POPUP_MESG( "Can't read a tagset until\nyou type in a filename" ) ;
981 return ;
982 }
983
984 /*-- check for suffix on filename --*/
985
986 cpt = strstr( str , ".tag" ) ;
987 if( cpt == NULL ){
988 ii = strlen(str) ;
989 cpt = XtMalloc(ii+8) ;
990 strcpy(cpt,str) ;
991 if( cpt[ii-1] != '.' ) strcat( cpt , "." ) ;
992 strcat( cpt , "tag" ) ;
993 XtFree(str) ;
994 str = cpt ;
995 }
996
997 /*-- open file --*/
998
999 fp = fopen( str , "r" ) ;
1000 if( fp == NULL ){
1001 XtFree(str) ; BEEPIT ;
1002 POPUP_MESG( "Can't open input file!" ) ;
1003 return ;
1004 }
1005
1006 /*-- scan each line for a tag definition --*/
1007
1008 ntog = 0 ;
1009 while( ntog < MAX_TAG_NUM ){
1010 cpt = afni_fgets( buf , 256 , fp ); /* read line from disk */
1011 if( cpt == NULL ) break ; /* nothing => exit */
1012 if( buf[0] == '#' ) continue ; /* comment => skip this line */
1013 if( buf[0] == '\n' ) continue ;
1014 if( buf[0] == '\0' ) continue ;
1015
1016 lbuf = strlen(buf) ; /* skip whitespace at start */
1017 jj = 0 ;
1018 while( jj < lbuf && isspace(buf[jj]) ) jj++ ;
1019 if( jj == lbuf ) continue ; /* was a blank line => skip */
1020 if( buf[jj] == '#' ) continue ; /* comment */
1021
1022 /* scan for new label */
1023
1024 if( buf[jj] == '\'' || buf[jj] == '\"' ){ /* scan to matching quote */
1025 quote = buf[jj] ; jj++ ; kk = jj ;
1026 while( kk < lbuf && buf[kk] != quote ) kk++ ;
1027 if( kk == lbuf ) kk-- ;
1028 } else { /* scan to nonblank */
1029 kk = jj+1 ;
1030 while( kk < lbuf && !isspace(buf[kk]) ) kk++ ;
1031 }
1032 for( ii=0 ; ii < MAX_TAG_LABEL-1 && jj < kk ; ii++,jj++ )
1033 new_label[ii] = buf[jj] ;
1034 new_label[ii] = '\0' ;
1035 if( strlen(new_label) == 0 ) continue ; /* error => skip */
1036 jj = kk+1 ;
1037
1038 /* scan for x y z val ti */
1039
1040 new_set = new_ti = 0 ;
1041 new_x = new_y = new_z = new_val = 0.0 ;
1042 if( jj < lbuf-4 ){
1043 kk = sscanf( buf+jj , "%f %f %f %f %d" ,
1044 &new_x , &new_y , &new_z , &new_val , &new_ti ) ;
1045 if( kk >= 3 ) new_set = 1 ; /* got x y z, at least */
1046 }
1047
1048 /* set values */
1049
1050 strcpy( mytagset->tag[ntog].label , new_label ) ;
1051 mytagset->tag[ntog].set = new_set ;
1052 mytagset->tag[ntog].ti = new_ti ;
1053 mytagset->tag[ntog].x = new_x ;
1054 mytagset->tag[ntog].y = new_y ;
1055 mytagset->tag[ntog].z = new_z ;
1056 mytagset->tag[ntog].val = new_val ;
1057 ntog++ ;
1058 }
1059
1060 fclose(fp) ; /* done with file */
1061
1062 if( ntog == 0 ){ /* no tags ==> error */
1063 sprintf(buf,"Couldn't read tagset from\n"
1064 "file %s" , str ) ;
1065 POPUP_MESG( buf ) ;
1066 BEEPIT ; XtFree(str) ; return ;
1067 }
1068
1069 /*-- now reset the widgets --*/
1070
1071 tognum = mytagset->num = ntog ;
1072 TAG_reset_widgets() ;
1073 TAG_redraw() ; DSET_OFF ; XtFree(str) ;
1074 return ;
1075 }
1076
1077 /*--------------------------------------------------------------------------*/
1078
TAG_get_dset_CB(int num,THD_3dim_dataset ** dslist,void * cd)1079 static void TAG_get_dset_CB( int num, THD_3dim_dataset ** dslist, void * cd )
1080 {
1081 char str[256] , * tnam ;
1082 XmString xstr ;
1083
1084 /*-- sanity checks --*/
1085
1086 if( !IM3D_OPEN(im3d) || !editor_open ){
1087 BEEPIT ; POPDOWN_strlist_chooser ;
1088 TAG_quit_CB(NULL,NULL,NULL) ; return ;
1089 }
1090
1091 /* this should not occur: */
1092
1093 if( num != 1 || dslist == NULL || !ISVALID_DSET(dslist[0]) ){ BEEPIT; return; }
1094
1095 /* assign global variable */
1096
1097 dset = dslist[0] ;
1098
1099 /*-- change the informational label --*/
1100
1101 sprintf(str,"%s%s", DSET_DIRNAME(dset) , DSET_FILECODE(dset) ) ;
1102 tnam = THD_trailname( str , SESSTRAIL+1 ) ;
1103 xstr = XmStringCreateLtoR( tnam , XmFONTLIST_DEFAULT_TAG ) ;
1104 XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
1105 XmStringFree(xstr) ;
1106
1107 /*-- if the new dataset has tags, use them --*/
1108
1109 if( dset->tagset != NULL && dset->tagset->num > 0 ){
1110 *mytagset = *(dset->tagset) ; /* copy all data in one swell foop */
1111 *oldtagset = *mytagset ; /* backup copy */
1112 tognum = mytagset->num ;
1113 TAG_reset_widgets() ;
1114 } else {
1115 oldtagset->num = 0 ;
1116 if( dset->tagset == NULL ){
1117 dset->tagset = myXtNew(THD_usertaglist) ;
1118 dset->tagset->num = 0 ;
1119 }
1120 if( tognum > 0 ) TAG_clearall_CB(NULL,NULL,NULL) ;
1121 }
1122
1123 TAG_onoff( 1 ) ;
1124 return ;
1125 }
1126
1127 /*--------------------------------------------------------------------------*/
1128
TAG_check_dataset(THD_3dim_dataset * qset,void * cd)1129 static int TAG_check_dataset( THD_3dim_dataset * qset, void * cd )
1130 {
1131 #if 0
1132 return ISANAT(qset) ;
1133 #else
1134 return 1 ; /* All of them, Frank */
1135 #endif
1136 }
1137
TAG_check_copyset(THD_3dim_dataset * qset,void * cd)1138 static int TAG_check_copyset( THD_3dim_dataset * qset, void * cd )
1139 {
1140 return ( ISANAT(qset) && !EQUIV_DSETS(qset,dset) &&
1141 qset->tagset != NULL && qset->tagset->num > 0 ) ;
1142 }
1143
1144 /*--------------------------------------------------------------------------*/
1145
TAG_dset_CB(Widget w,XtPointer client_data,XtPointer call_data)1146 static void TAG_dset_CB( Widget w, XtPointer client_data, XtPointer call_data )
1147 {
1148 /*-- sanity checks --*/
1149
1150 if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
1151
1152 /*-- just show a chooser, let the user commune with the list --*/
1153
1154 PLUTO_popup_dset_chooser( help_pb , im3d->vinfo->view_type , 0 ,
1155 TAG_check_dataset , TAG_get_dset_CB , NULL ) ;
1156
1157 return ;
1158 }
1159
1160 /*--------------------------------------------------------------------------*/
1161
TAG_save_CB(Widget w,XtPointer client_data,XtPointer call_data)1162 static void TAG_save_CB( Widget w, XtPointer client_data, XtPointer call_data )
1163 {
1164 if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
1165
1166 if( dset == NULL ) return ; /* nothing to do */
1167
1168 if( dset->tagset == NULL ){
1169 dset->tagset = myXtNew(THD_usertaglist) ;
1170 ADDTO_KILL( dset->kl , dset->tagset ) ;
1171 }
1172
1173 *(dset->tagset) = *mytagset ; /* copy all data in one swell foop */
1174 *oldtagset = *mytagset ; /* backup copy is replaced */
1175
1176 putenv("AFNI_DECONFLICT=OVERWRITE") ;
1177 DSET_overwrite_header(dset) ;
1178 TAG_redraw() ; DSET_ON ;
1179 return ;
1180 }
1181
1182 /*--------------------------------------------------------------------------*/
1183
TAG_onoff(int on)1184 static void TAG_onoff( int on )
1185 {
1186 RwcBoolean sen ;
1187 int ii ;
1188
1189 sen = (RwcBoolean) on ;
1190 for( ii=0 ; onoff_wid[ii] != NULL ; ii++ )
1191 SENSITIZE( *(onoff_wid[ii]) , sen ) ; /* see xutil.h */
1192
1193 on_flag = on ;
1194 return ;
1195 }
1196
1197 /*--------------------------------------------------------------------------*/
1198
TAG_done_CB(Widget w,XtPointer client_data,XtPointer call_data)1199 static void TAG_done_CB( Widget w, XtPointer client_data, XtPointer call_data )
1200 {
1201 TAG_save_CB(NULL,NULL,NULL) ; dset = NULL ;
1202 TAG_quit_CB(NULL,NULL,NULL) ;
1203 return ;
1204 }
1205
1206 /*--------------------------------------------------------------------------*/
1207
TAG_get_copy_CB(int num,THD_3dim_dataset ** dslist,void * cd)1208 static void TAG_get_copy_CB( int num, THD_3dim_dataset ** dslist, void * cd )
1209 {
1210 char str[256] , * tnam ;
1211 THD_3dim_dataset * qset ;
1212 XmString xstr ;
1213
1214 /*-- sanity checks --*/
1215
1216 if( !IM3D_OPEN(im3d) || !editor_open ){
1217 BEEPIT ; POPDOWN_strlist_chooser ;
1218 TAG_quit_CB(NULL,NULL,NULL) ; return ;
1219 }
1220
1221 if( num != 1 || dslist == NULL || !ISVALID_DSET(dslist[0]) ){ BEEPIT; return; }
1222
1223 qset = dslist[0] ; if( qset->tagset == NULL ){ BEEPIT; return; }
1224
1225 *mytagset = *(qset->tagset) ;
1226 tognum = mytagset->num ;
1227
1228 TAG_reset_widgets() ; TAG_redraw() ; DSET_OFF ;
1229 return ;
1230 }
1231
1232 /*--------------------------------------------------------------------------*/
1233
TAG_copy_CB(Widget w,XtPointer client_data,XtPointer call_data)1234 static void TAG_copy_CB( Widget w, XtPointer client_data, XtPointer call_data )
1235 {
1236 /*-- sanity checks --*/
1237
1238 if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
1239
1240 /*-- just show a chooser, let the user commune with the list --*/
1241
1242 PLUTO_popup_dset_chooser( help_pb , im3d->vinfo->view_type , 0 ,
1243 TAG_check_copyset , TAG_get_copy_CB , NULL ) ;
1244
1245 return ;
1246 }
1247
1248 /*--------------------------------------------------------------------------*/
1249
TAG_help_CB(Widget w,XtPointer client_data,XtPointer call_data)1250 static void TAG_help_CB( Widget w, XtPointer client_data, XtPointer call_data )
1251 {
1252 (void ) new_MCW_textwin( help_pb ,
1253
1254 "This plugin can be used to attach a collection of 'tags' to an anatomical\n"
1255 "dataset. Each tag has associated with it a label, a set of (x,y,z)\n"
1256 "coordinates, and a numerical value. If a tag is 'set', then a marker will\n"
1257 "be displayed at its location when the dataset is being viewed, and when\n"
1258 "'See Markers' is enabled on the AFNI control panel. Tags that are not set\n"
1259 "are not shown and are not used for any purpose.\n"
1260
1261 "\n"
1262 "The first step in defining a set of tags for a dataset is to pick the\n"
1263 "dataset to be operated upon. Normally, this would be the dataset that\n"
1264 "you are viewing in some window (otherwise you won't see the tags).\n"
1265 "Choosing a dataset for tag operations is done with the 'Dataset' button\n"
1266 "at the top of the plugin interface. This will popup a chooser that\n"
1267 "lets you select any anatomical dataset. After you select the dataset,\n"
1268 "its existing tags (if any) are loaded into the plugin and can then\n"
1269 "be modified.\n"
1270
1271 "\n"
1272 "There are two rows of control buttons below the 'Dataset' choice button.\n"
1273 "The first row handles large operations on the whole set of tags. The\n"
1274 "second row is for retail operations on the status of individual tags.\n"
1275 "Most of the control buttons are deactivated until you select a dataset.\n"
1276 "Below these rows is a set of data entry fields, and below that a list\n"
1277 "of all the tags currently defined (whether set or not -- tags that are\n"
1278 "set are shown in inverted colors). Each entry in the tag list has a\n"
1279 "selection button. At most one tag can be selected at a given time.\n"
1280 "\n"
1281
1282 "Row 1 buttons are:\n"
1283 "-----------------\n"
1284 "'Quit': Exit the plugin without saving changes back to the dataset.\n"
1285 "\n"
1286 "'Help': Display this message.\n"
1287 "\n"
1288 "'Read': Read in a tagset description file, replacing the current tag\n"
1289 " definitions. Each line in a tagset file (extension '.tag')\n"
1290 " defines one tag. The first entry on a line is the tag label.\n"
1291 " If the label contains any blanks, it should be enclosed in\n"
1292 " quotes (either \"double\" or 'single' quotes will work).\n"
1293 " Following the label, it is legal to put three numbers, which\n"
1294 " will be interpreted as the (x,y,z) coordinates of the tag.\n"
1295 " If these numbers are present, the tag will be set and displayed.\n"
1296 "\n"
1297 "'Write': Write the current set of tags to a '.tag' file, which can\n"
1298 " later be read back in using the 'Read' button.\n"
1299 " N.B.: Tag coordinates are stored in Dicom order\n"
1300 " x = R-L coordinate (R < 0, L > 0)\n"
1301 " y = A-P coordinate (A < 0, P > 0)\n"
1302 " z = I-S coordinate (I < 0, S > 0)\n"
1303 "\n"
1304 "'Copy': Copy the set of tags from another dataset.\n"
1305 "\n"
1306 "'Save': Save the current set of tags into the dataset .HEAD file.\n"
1307 " If this is not done before 'Quit', then changes made to the\n"
1308 " tagset will not be saved.\n"
1309 "\n"
1310 "'Done': Combines the operations of 'Save' and then 'Quit'.\n"
1311 "\n"
1312
1313 "Row 2 buttons are:\n"
1314 "-----------------\n"
1315 "'Set': Sets the selected tag to be at the current crosshair location.\n"
1316 "\n"
1317 "'Clear': Un-sets the current tag.\n"
1318 "\n"
1319 "'Clr All': Un-sets all tags.\n"
1320 "\n"
1321 "'Add': Adds 1 new tag to the end of the list. There is a maximum of\n"
1322 " 100 tags allowed.\n"
1323 "\n"
1324 "'Delete': Deletes the last tag from the list.\n"
1325 "\n"
1326 "'Relabel': Changes the label of the selected tag.\n"
1327 "\n"
1328
1329 "Data entry fields are:\n"
1330 "---------------------\n"
1331 "'Tag File': You enter the name of the tagset file for 'Read' and 'Write'\n"
1332 " operations here.\n"
1333 "\n"
1334 "'Tag Label': You enter the new label for the selected tag here, for use\n"
1335 " with the 'Relabel' operation.\n"
1336 "\n"
1337 "'Tag Value': You enter the numerical value to be attached to a tag here,\n"
1338 " for use with the 'Set' operation.\n"
1339 "\n"
1340
1341 "Nota Bene\n"
1342 "---------\n"
1343 "The tag value is not used for anything yet. Any suggestions?\n"
1344 "\n"
1345 "By using the 'Add', 'Delete', and 'Relabel' buttons, it is possible to\n"
1346 "create your own collection of tag definitions. However, it is generally\n"
1347 "easier to use an external editor (e.g., 'vi') to create a .tag file and\n"
1348 "then read it in with the 'Read' button.\n"
1349 "\n"
1350 "Once you make a change to a tagset, the 'Dataset' button will be disabled\n"
1351 "until 'Save' is used. This is a safety measure to help prevent accidental\n"
1352 "loss of changes. If you want to discard the changes, use 'Quit'.\n"
1353 "\n"
1354 "The color of a dataset tag is controlled by the 'Primary Markers' color,\n"
1355 "which is set on the 'Define Markers' control panel in the main AFNI control\n"
1356 "window. The tags are displayed as a cross within a diamond.\n"
1357 "\n"
1358 "The program 3dTagalign will read the tag coordinates from one dataset and\n"
1359 "rotate/translate that dataset to match the tag coordinates from another\n"
1360 "dataset (in the least squares sense). See '3dTagalign -help' for details.\n"
1361 "\n"
1362 "============================\n"
1363 "AUTHOR: RW Cox, October 1998\n"
1364 "============================\n"
1365
1366 , TEXT_READONLY ) ;
1367 return ;
1368 }
1369
1370 /*--------------------------------------------------------------------------*/
1371
1372 #define NMSG 6
1373
TAG_beep_CB(Widget w,XtPointer client_data,XtPointer call_data)1374 static void TAG_beep_CB( Widget w, XtPointer client_data, XtPointer call_data )
1375 {
1376 static int nbeep = 0 ;
1377 static char * msg[] = { "What did you expect,\na choir of angels?" ,
1378 "Apparently some people\ncan't take a hint." ,
1379 "You aren't tired\nof this game YET?!" ,
1380 "I'm getting tired of\nthis. I'm warning you!" ,
1381 "This is the last time!\nOnce more, and you'll be sorry!" ,
1382 "You can't say I didn't warn you.\nNyah Nyah Nyah."
1383 } ;
1384
1385 POPUP_MESG( msg[nbeep] ) ; nbeep++ ; BEEPIT ;
1386
1387 if( nbeep >= NMSG ) SENSITIZE(beep_pb,False) ;
1388 return ;
1389 }
1390