00001
00002
00003
00004
00005
00006
00007 #include "afni.h"
00008
00009 #ifndef ALLOW_PLUGINS
00010 # error "Plugins not properly set up -- see machdep.h"
00011 #endif
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 char * NOTES_main( PLUGIN_interface * ) ;
00022
00023 static void NOTES_make_widgets(void) ;
00024
00025 static void NOTES_done_CB ( Widget , XtPointer , XtPointer ) ;
00026 static void NOTES_help_CB ( Widget , XtPointer , XtPointer ) ;
00027 static void NOTES_quit_CB ( Widget , XtPointer , XtPointer ) ;
00028 static void NOTES_save_CB ( Widget , XtPointer , XtPointer ) ;
00029 static void NOTES_choose_CB ( Widget , XtPointer , XtPointer ) ;
00030 static void NOTES_add_CB ( Widget , XtPointer , XtPointer ) ;
00031 static void NOTES_delete_CB ( Widget , XtPointer , XtPointer ) ;
00032 static void NOTES_restore_CB( Widget , XtPointer , XtPointer ) ;
00033 static void NOTES_refit_CB ( Widget , XtPointer , XtPointer ) ;
00034
00035 static void NOTES_finalize_dset_CB( Widget , XtPointer , MCW_choose_cbs * ) ;
00036
00037 static PLUGIN_interface * plint = NULL ;
00038
00039 #define TWIDTH 75
00040 #define newstring(str) strcpy(malloc(strlen(str)+1),str)
00041 static int line_count( char * ) ;
00042
00043 #define THEIGHT 9
00044 static int max_tlines = 0 ;
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 DEFINE_PLUGIN_PROTOTYPE
00055
00056 PLUGIN_interface * PLUGIN_init( int ncall )
00057 {
00058
00059 if( ncall > 0 ) return NULL ;
00060
00061 plint = PLUTO_new_interface( "Dataset NOTES" , NULL , NULL ,
00062 PLUGIN_CALL_IMMEDIATELY , NOTES_main ) ;
00063
00064 PLUTO_add_hint( plint , "Edit/View Notes attached to dataset" ) ;
00065
00066 PLUTO_set_sequence( plint , "A:olddset:notes" ) ;
00067
00068 return plint ;
00069 }
00070
00071
00072
00073
00074
00075
00076
00077 typedef struct {
00078 Widget frame, vert_rc , horz_rc , note_label ,
00079 delete_pb , restore_pb , scrollw , textw ;
00080
00081 char * note_orig , * date_orig ;
00082 } NOTE_wind ;
00083
00084 static NOTE_wind * NOTES_make_note(void) ;
00085
00086 static Widget shell=NULL , topman , info_lab , choose_pb ;
00087 static Widget done_pb , help_pb , quit_pb , save_pb , add_pb ;
00088 static Widget notesw , noterc , refit_pb ;
00089
00090 static int text_width = 0 ;
00091 static int text_height = 0 ;
00092
00093 static NOTE_wind ** notar = NULL ;
00094 static int notar_num = 0 ;
00095 static int num_notes = 0 ;
00096
00097 static MCW_DC * dc ;
00098 static Three_D_View * im3d ;
00099 static THD_3dim_dataset * dset ;
00100 static MCW_idcode dset_idc ;
00101
00102 static int editor_open = 0 ;
00103
00104 #define NUM_DH 10
00105 static char * default_history[NUM_DH] = {
00106
00107 "The mind is its own place, and in itself\n"
00108 "Can make a Heaven of Hell, a Hell of Heaven.\n"
00109 "-- John Milton (Paradise Lost)\n" ,
00110
00111 "Those who cannot remember the past are condemned to repeat it.\n"
00112 "-- George Santayana" ,
00113
00114 "Chanter of Personality, outlining what is yet to be,\n"
00115 "I project the history of the future.\n"
00116 "-- Walt Whitman" ,
00117
00118 "I shall cheerfully bear the reproach of having descended below the\n"
00119 "dignity of history.\n"
00120 "-- Thomas Macaulay" ,
00121
00122 "There was a time - we see it in the marvellous dawn of Hellenic life -\n"
00123 "when history was distinguished neither from poetry, from mythology,\n"
00124 "nor from the first dim beginnings of science.\n"
00125 "-- Theodore Roosevelt" ,
00126
00127 "You cannot escape the responsibility of tomorrow by evading it today.\n"
00128 "-- Abraham Lincoln" ,
00129
00130 "Once you get into this great stream of history, you can't get out.\n"
00131 "-- Richard Nixon" ,
00132
00133 "History is the version of past events that people have decided to\n"
00134 "agree upon.\n"
00135 "--Napoleon" ,
00136
00137 "Ever returning Spring, trinity sure to me you bring:\n"
00138 "Lilac blooming perennial, and drooping star in the West,\n"
00139 "And thought of him I love.\n"
00140 "-- Walt Whitman" ,
00141
00142 "What has occurred in this case, must ever recur in similar cases.\n"
00143 "Human nature will not change. In any future great national trial,\n"
00144 "compared with the men of this, we shall have as weak, and as strong;\n"
00145 "as silly and as wise; as bad and good. Let us, therefore, study the\n"
00146 "incidents of this, as philosophy to learn wisdom from, and none of\n"
00147 "them as wrongs to be revenged.\n"
00148 "-- Abraham Lincoln"
00149
00150 } ;
00151
00152 static char * empty_note = "-- Empty Note Text --" ;
00153 static char * no_date = "no date" ;
00154
00155 static void scroll_topbot( Widget , int ) ;
00156
00157 char * NOTES_main( PLUGIN_interface * plint )
00158 {
00159 XmString xstr ;
00160 int ii ;
00161
00162
00163
00164 if( ! IM3D_OPEN(plint->im3d) ) return "AFNI Controller\nnot opened?!" ;
00165
00166 if( editor_open ){
00167 XtMapWidget(shell) ;
00168 XRaiseWindow( XtDisplay(shell) , XtWindow(shell) ) ;
00169 return NULL ;
00170 }
00171
00172 im3d = plint->im3d ;
00173
00174
00175
00176 if( shell == NULL ){
00177 dc = im3d->dc ;
00178 NOTES_make_widgets() ;
00179 PLUTO_set_topshell( plint , shell ) ;
00180 RWC_visibilize_widget( shell ) ;
00181 }
00182
00183
00184
00185 XtUnmanageChild( notesw ) ;
00186 XtUnmanageChild( noterc ) ;
00187 for( ii=0 ; ii < notar_num ; ii++ )
00188 XtUnmanageChild( notar[ii]->frame ) ;
00189
00190
00191
00192 { char ttl[32] ;
00193 sprintf( ttl , "AFNI Notes %s" , AFNI_controller_label(im3d) ) ;
00194 XtVaSetValues( shell , XmNtitle , ttl , NULL ) ;
00195 }
00196
00197
00198
00199 xstr = XmStringCreateLtoR( "[No dataset]" ,
00200 XmFONTLIST_DEFAULT_TAG ) ;
00201 XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
00202 XmStringFree(xstr) ;
00203
00204
00205
00206 XtMapWidget(shell) ;
00207 PLUTO_cursorize(shell) ;
00208
00209
00210
00211 dset = NULL ;
00212 editor_open = 1 ;
00213 num_notes = 0 ;
00214
00215 return NULL ;
00216 }
00217
00218
00219
00220
00221
00222
00223
00224 #define NACT 6
00225
00226 static MCW_action_item NOTES_actor[NACT] = {
00227 {"Quit",NOTES_quit_CB,NULL,
00228 "Discard edits since last\nSave and close Editor" ,
00229 "Discard edits and close",0} ,
00230
00231 {"Help",NOTES_help_CB,NULL,
00232 "Displays more help" , "Displays more help",0} ,
00233
00234 {"Add",NOTES_add_CB,NULL,
00235 "Add a new Note to the\nlist (at the end)", "Add a new Note" , 0 } ,
00236
00237 {"Refit",NOTES_refit_CB,NULL,
00238 "Resize the Notes' sub-windows\nto fit the Notes' texts." ,
00239 "Resize Notes sub-windows" , 0 } ,
00240
00241 {"Save",NOTES_save_CB,NULL,
00242 "Save edits to disk\nand continue" , "Save to disk; continue",0} ,
00243
00244 {"Done",NOTES_done_CB,NULL,
00245 "Save edits to disk\nand close Editor" , "Save and Quit",1}
00246 } ;
00247
00248 static void NOTES_make_widgets(void)
00249 {
00250 XmString xstr ;
00251 Widget twid , tsep ;
00252
00253
00254
00255 if( max_tlines < 1 ){
00256 char * cc = my_getenv("AFNI_NOTES_DLINES") ;
00257 if( cc != NULL ) max_tlines = strtol( cc , NULL , 10 ) ;
00258
00259 if( max_tlines < 1 ) max_tlines = THEIGHT ;
00260 else if( max_tlines > 99 ) max_tlines = 99 ;
00261 }
00262
00263
00264
00265 shell =
00266 XtVaAppCreateShell(
00267 "AFNI" , "AFNI" , topLevelShellWidgetClass , dc->display ,
00268
00269 XmNtitle , "Notes Editor" ,
00270 XmNiconName , "Notes" ,
00271 XmNdeleteResponse , XmDO_NOTHING ,
00272 XmNallowShellResize , True ,
00273 XmNmappedWhenManaged , False ,
00274 NULL ) ;
00275
00276 DC_yokify( shell , dc ) ;
00277
00278 if( afni48_good )
00279 XtVaSetValues( shell ,
00280 XmNiconPixmap , afni48_pixmap ,
00281 NULL ) ;
00282
00283 XmAddWMProtocolCallback(
00284 shell ,
00285 XmInternAtom( dc->display , "WM_DELETE_WINDOW" , False ) ,
00286 NOTES_quit_CB , (XtPointer) plint ) ;
00287
00288
00289
00290 topman = XtVaCreateWidget(
00291 "AFNI" , xmFormWidgetClass , shell ,
00292 XmNborderWidth , 0 ,
00293 XmNborderColor , 0 ,
00294 XmNtraversalOn , False ,
00295 NULL ) ;
00296
00297
00298
00299 twid = XtVaCreateWidget(
00300 "AFNI" , xmRowColumnWidgetClass , topman ,
00301 XmNpacking , XmPACK_TIGHT ,
00302 XmNorientation , XmHORIZONTAL ,
00303 XmNtraversalOn , False ,
00304 XmNleftAttachment , XmATTACH_FORM ,
00305 XmNrightAttachment, XmATTACH_FORM ,
00306 XmNtopAttachment , XmATTACH_FORM ,
00307 XmNtopOffset , 1 ,
00308 NULL ) ;
00309
00310
00311
00312 xstr = XmStringCreateLtoR( "Choose Dataset" , XmFONTLIST_DEFAULT_TAG ) ;
00313 choose_pb = XtVaCreateManagedWidget(
00314 "AFNI" , xmPushButtonWidgetClass , twid ,
00315 XmNlabelString , xstr ,
00316 XmNtraversalOn , False ,
00317 NULL ) ;
00318 XmStringFree(xstr) ;
00319 XtAddCallback( choose_pb, XmNactivateCallback, NOTES_choose_CB, NULL ) ;
00320 MCW_register_help( choose_pb ,
00321 "Use this to popup a\n"
00322 "'chooser' that lets\n"
00323 "you select which\n"
00324 "dataset to edit."
00325 ) ;
00326 MCW_register_hint( choose_pb , "Popup a dataset chooser" ) ;
00327
00328
00329
00330 xstr = XmStringCreateLtoR( "[No dataset]" , XmFONTLIST_DEFAULT_TAG ) ;
00331 info_lab = XtVaCreateManagedWidget(
00332 "AFNI" , xmLabelWidgetClass , twid ,
00333 XmNlabelString , xstr ,
00334 NULL ) ;
00335 XmStringFree(xstr) ;
00336 MCW_register_help( info_lab , "Shows dataset being edited" ) ;
00337 MCW_register_hint( info_lab , "Dataset being edited" ) ;
00338
00339 XtManageChild(twid) ;
00340
00341
00342
00343 tsep = XtVaCreateManagedWidget(
00344 "AFNI" , xmSeparatorWidgetClass , topman ,
00345 XmNseparatorType , XmSINGLE_LINE ,
00346 XmNleftAttachment , XmATTACH_FORM ,
00347 XmNrightAttachment , XmATTACH_FORM ,
00348 XmNtopAttachment , XmATTACH_WIDGET ,
00349 XmNtopWidget , info_lab ,
00350 XmNtopOffset , 1 ,
00351 NULL ) ;
00352
00353
00354
00355 twid = MCW_action_area( topman , NOTES_actor , NACT ) ;
00356
00357 XtVaSetValues( twid ,
00358 XmNleftAttachment , XmATTACH_FORM ,
00359 XmNrightAttachment, XmATTACH_FORM ,
00360 XmNtopAttachment , XmATTACH_WIDGET ,
00361 XmNtopWidget , tsep ,
00362 XmNtopOffset , 1 ,
00363 NULL ) ;
00364
00365 quit_pb = (Widget) NOTES_actor[0].data ;
00366 help_pb = (Widget) NOTES_actor[1].data ;
00367 add_pb = (Widget) NOTES_actor[2].data ;
00368 refit_pb = (Widget) NOTES_actor[3].data ;
00369 save_pb = (Widget) NOTES_actor[4].data ;
00370 done_pb = (Widget) NOTES_actor[5].data ;
00371
00372
00373
00374 tsep = XtVaCreateManagedWidget(
00375 "AFNI" , xmSeparatorWidgetClass , topman ,
00376 XmNseparatorType , XmSINGLE_LINE ,
00377 XmNleftAttachment , XmATTACH_FORM ,
00378 XmNrightAttachment , XmATTACH_FORM ,
00379 XmNtopAttachment , XmATTACH_WIDGET ,
00380 XmNtopWidget , twid ,
00381 XmNtopOffset , 1 ,
00382 NULL ) ;
00383
00384
00385
00386 notesw = XtVaCreateWidget(
00387 "AFNI" , xmScrolledWindowWidgetClass , topman ,
00388 XmNscrollingPolicy , XmAUTOMATIC ,
00389 XmNvisualPolicy , XmCONSTANT ,
00390 XmNshadowThickness , 0 ,
00391 XmNscrollBarDisplayPolicy , XmAS_NEEDED ,
00392 XmNscrollBarPlacement , XmTOP_LEFT ,
00393 XmNleftAttachment , XmATTACH_FORM ,
00394 XmNrightAttachment , XmATTACH_FORM ,
00395 XmNbottomAttachment, XmATTACH_FORM ,
00396 XmNtopAttachment , XmATTACH_WIDGET ,
00397 XmNtopWidget , tsep ,
00398 XmNtopOffset , 1 ,
00399 NULL ) ;
00400
00401 noterc = XtVaCreateWidget(
00402 "AFNI" , xmRowColumnWidgetClass , notesw ,
00403 XmNpacking , XmPACK_TIGHT ,
00404 XmNorientation , XmVERTICAL ,
00405 XmNmarginHeight, 0 ,
00406 XmNmarginWidth , 0 ,
00407 XmNtraversalOn , False ,
00408 NULL ) ;
00409
00410
00411
00412
00413 notar = (NOTE_wind **) malloc( sizeof(NOTE_wind *) ) ;
00414 notar[0] = NOTES_make_note() ;
00415 notar_num = 1 ;
00416
00417 XtUnmanageChild( notar[0]->delete_pb ) ;
00418 XtUnmanageChild( notar[0]->restore_pb ) ;
00419 XtVaSetValues( notar[0]->textw ,
00420 XmNautoShowCursorPosition , False ,
00421 XmNeditable , False ,
00422 XmNcursorPositionVisible , False ,
00423 NULL ) ;
00424 xstr = XmStringCreateLtoR( "----- History -----" , XmFONTLIST_DEFAULT_TAG ) ;
00425 XtVaSetValues( notar[0]->note_label , XmNlabelString , xstr , NULL ) ;
00426 MCW_register_hint( notar[0]->textw , "Dataset History; or Edifying Text" ) ;
00427
00428
00429
00430 { char cbuf[TWIDTH+8] ; int ii ;
00431 XmFontList xflist ;
00432
00433 for( ii=0; ii < TWIDTH+3; ii++ ) cbuf[ii] = 'x' ; cbuf[ii] = '\0' ;
00434 xstr = XmStringCreateLtoR( cbuf , XmFONTLIST_DEFAULT_TAG ) ;
00435 XtVaGetValues( notar[0]->textw , XmNfontList , &xflist , NULL ) ;
00436 text_width = XmStringWidth ( xflist , xstr ) + 14 ;
00437 text_height = XmStringHeight( xflist , xstr ) ;
00438 XmStringFree( xstr ) ;
00439 ii = WidthOfScreen(XtScreen(shell)) - 128 ;
00440 if( text_width > ii ) text_width = ii ;
00441 }
00442
00443
00444
00445 XtManageChild(topman) ;
00446 XtRealizeWidget(shell) ;
00447
00448 return ;
00449 }
00450
00451
00452
00453
00454
00455 static NOTE_wind * NOTES_make_note( void )
00456 {
00457 NOTE_wind * nw ;
00458 XmString xstr ;
00459
00460 nw = (NOTE_wind *) calloc( 1 , sizeof(NOTE_wind) ) ;
00461
00462 nw->frame = XtVaCreateWidget(
00463 "AFNI" , xmFrameWidgetClass , noterc ,
00464 XmNshadowType , XmSHADOW_IN ,
00465 XmNshadowThickness , 1 ,
00466 XmNtraversalOn , False ,
00467 NULL ) ;
00468
00469 nw->vert_rc = XtVaCreateWidget(
00470 "AFNI" , xmRowColumnWidgetClass , nw->frame ,
00471 XmNpacking , XmPACK_TIGHT ,
00472 XmNorientation , XmVERTICAL ,
00473 XmNtraversalOn , False ,
00474 XmNmarginHeight, 0 ,
00475 XmNmarginWidth , 0 ,
00476 NULL ) ;
00477
00478 nw->horz_rc = XtVaCreateWidget(
00479 "AFNI" , xmRowColumnWidgetClass , nw->vert_rc ,
00480 XmNpacking , XmPACK_TIGHT ,
00481 XmNorientation , XmHORIZONTAL ,
00482 XmNtraversalOn , False ,
00483 XmNmarginHeight, 0 ,
00484 XmNmarginWidth , 0 ,
00485 NULL ) ;
00486
00487 nw->note_label = XtVaCreateManagedWidget(
00488 "AFNI" , xmLabelWidgetClass , nw->horz_rc ,
00489 XmNmarginHeight, 0 ,
00490 XmNmarginWidth , 0 ,
00491 NULL ) ;
00492
00493 xstr = XmStringCreateLtoR( "Delete" , XmFONTLIST_DEFAULT_TAG ) ;
00494 nw->delete_pb = XtVaCreateManagedWidget(
00495 "AFNI" , xmPushButtonWidgetClass , nw->horz_rc ,
00496 XmNlabelString , xstr ,
00497 XmNtraversalOn , False ,
00498 XmNmarginHeight, 0 ,
00499 XmNmarginWidth , 0 ,
00500 NULL ) ;
00501 XmStringFree(xstr) ;
00502 XtAddCallback( nw->delete_pb, XmNactivateCallback, NOTES_delete_CB, NULL ) ;
00503 MCW_register_help( nw->delete_pb ,
00504 "Use this button to delete\n"
00505 "this Note from the dataset."
00506 ) ;
00507 MCW_register_hint( nw->delete_pb , "Delete this Note" ) ;
00508
00509 xstr = XmStringCreateLtoR( "Restore" , XmFONTLIST_DEFAULT_TAG ) ;
00510 nw->restore_pb = XtVaCreateManagedWidget(
00511 "AFNI" , xmPushButtonWidgetClass , nw->horz_rc ,
00512 XmNlabelString , xstr ,
00513 XmNtraversalOn , False ,
00514 XmNmarginHeight, 0 ,
00515 XmNmarginWidth , 0 ,
00516 NULL ) ;
00517 XmStringFree(xstr) ;
00518 XtAddCallback( nw->restore_pb, XmNactivateCallback, NOTES_restore_CB, NULL ) ;
00519 MCW_register_help( nw->restore_pb ,
00520 "Use this button to restore\n"
00521 "this Note to its original\n"
00522 "value (i.e., as it currently\n"
00523 "stored on in the HEAD file)."
00524 ) ;
00525 MCW_register_hint( nw->restore_pb , "Restore Note from disk" ) ;
00526
00527 XtManageChild(nw->horz_rc) ;
00528
00529 (void) XtVaCreateManagedWidget(
00530 "AFNI" , xmSeparatorWidgetClass , nw->vert_rc ,
00531 XmNseparatorType , XmSINGLE_LINE ,
00532 NULL ) ;
00533
00534 nw->scrollw = XtVaCreateManagedWidget(
00535 "AFNI" , xmScrolledWindowWidgetClass , nw->vert_rc ,
00536 XmNscrollingPolicy , XmAPPLICATION_DEFINED ,
00537 XmNvisualPolicy , XmVARIABLE ,
00538 XmNshadowThickness , 0 ,
00539 NULL ) ;
00540
00541 nw->textw = XtVaCreateManagedWidget(
00542 "AFNI" , xmTextWidgetClass , nw->scrollw ,
00543 XmNeditMode , XmMULTI_LINE_EDIT ,
00544 XmNautoShowCursorPosition , True ,
00545 XmNeditable , True ,
00546 XmNcursorPositionVisible , True ,
00547 XmNcolumns , TWIDTH ,
00548 XmNrows , 1 ,
00549 XmNwordWrap , True ,
00550 NULL ) ;
00551
00552 XtManageChild(nw->vert_rc) ;
00553
00554 nw->note_orig = nw->date_orig = NULL ;
00555 return nw ;
00556 }
00557
00558
00559
00560 static int line_count( char * msg )
00561 {
00562 char * cpt ; int nlin ;
00563 if( msg == NULL ) return 0 ;
00564 for( nlin=1,cpt=msg ; *cpt != '\0' ; cpt++ ) if( *cpt == '\n' ) nlin++ ;
00565 return nlin ;
00566 }
00567
00568
00569
00570
00571
00572 static void NOTES_done_CB( Widget w, XtPointer client_data, XtPointer call_data )
00573 {
00574 if( dset != NULL && num_notes > 0 ) NOTES_save_CB(NULL,NULL,NULL) ;
00575 NOTES_quit_CB(NULL,NULL,NULL) ;
00576 return ;
00577 }
00578
00579
00580
00581
00582
00583 static void NOTES_quit_CB( Widget w, XtPointer client_data, XtPointer call_data )
00584 {
00585 int ii ;
00586
00587 XtUnmapWidget( shell ) ; editor_open = 0 ; dset = NULL ;
00588
00589 XtUnmanageChild( notesw ) ;
00590 XtUnmanageChild( noterc ) ;
00591 for( ii=0 ; ii < notar_num ; ii++ ){
00592 XtUnmanageChild( notar[ii]->frame ) ;
00593
00594 if( notar[ii]->note_orig != NULL ){
00595 free(notar[ii]->note_orig) ; notar[ii]->note_orig = NULL ;
00596 }
00597
00598 if( notar[ii]->date_orig != NULL ){
00599 free(notar[ii]->date_orig) ; notar[ii]->date_orig = NULL ;
00600 }
00601
00602 XmTextSetString( notar[ii]->textw , "\0" ) ;
00603 }
00604
00605 return ;
00606 }
00607
00608
00609
00610
00611
00612 static void NOTES_save_CB( Widget w, XtPointer client_data, XtPointer call_data )
00613 {
00614 int ii , nnew ;
00615 char * nstr , str[256] ;
00616 XmString xstr ;
00617
00618 if( dset == NULL || num_notes == 0 ){ XBell(dc->display,100); return; }
00619
00620 MCW_invert_widget(save_pb) ;
00621
00622
00623
00624 for( nnew=0,ii=1 ; ii <= num_notes ; ii++ ){
00625 nstr = XmTextGetString( notar[ii]->textw ) ;
00626 if( strcmp(nstr,notar[ii]->note_orig) != 0 ){
00627
00628 tross_Store_Note( dset , ii , nstr ) ; nnew++ ;
00629 free( notar[ii]->note_orig ) ;
00630 notar[ii]->note_orig = newstring(nstr) ;
00631 free( notar[ii]->date_orig ) ;
00632 notar[ii]->date_orig = tross_Get_Notedate( dset , ii ) ;
00633
00634 sprintf(str,"----- NOTE %d [%s] -----",ii,notar[ii]->date_orig) ;
00635 xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
00636 XtVaSetValues( notar[ii]->note_label , XmNlabelString , xstr , NULL ) ;
00637 XmStringFree(xstr) ;
00638 }
00639 XtFree(nstr) ;
00640 }
00641
00642
00643
00644 if( nnew > 0 )
00645 DSET_write_header(dset) ;
00646 else if( w != NULL )
00647 (void) MCW_popup_message( save_pb ,
00648 " \n Nothing has changed! \n " ,
00649 MCW_USER_KILL | MCW_TIMER_KILL ) ;
00650
00651 MCW_invert_widget(save_pb) ;
00652 return ;
00653 }
00654
00655
00656
00657
00658
00659 static void NOTES_help_CB( Widget w, XtPointer client_data, XtPointer call_data )
00660 {
00661 (void ) new_MCW_textwin( choose_pb ,
00662
00663 " \n"
00664 "This plugin is used to view and edit the Notes attached to a dataset.\n"
00665 "---------------------------------------------------------------------\n"
00666 "The buttons at the top perform the following functions:\n"
00667 "\n"
00668 " Choose Dataset: Use this to select a dataset to deal with.\n"
00669 "\n"
00670 " Quit: Exit the plugin without saving any edits to Notes\n"
00671 " made since the last 'Save' button press.\n"
00672 "\n"
00673 " Help: I hope you already got the idea for this widget.\n"
00674 "\n"
00675 " Add: Add a new Note at the end of the existing notes.\n"
00676 "\n"
00677 " Refit: Resize all Notes' sub-windows to fit the number of\n"
00678 " lines of text in each Note. The maximum line count\n"
00679 " for each sub-window is set by the Unix environment\n"
00680 " variable AFNI_NOTES_DLINES; if this is not defined,\n"
00681 " the default maximum is 9.\n"
00682 "\n"
00683 " Save: Save the current Notes to the dataset .HEAD file.\n"
00684 "\n"
00685 " Done: Save then Quit.\n"
00686 "-------------------------------------------------------------------------- \n"
00687 "Below these buttons are the Notes sub-windows.\n"
00688 "\n"
00689 "The first Note sub-window shows the dataset History Note. This Note can't\n"
00690 "be edited by the user - it is created by each AFNI program as a record of\n"
00691 "the actions that led to this dataset. If no History Note is present in the\n"
00692 "dataset .HEAD file, some edifying text will be shown here instead.\n"
00693 "\n"
00694 "Each other Note sub-window shows the Note number, the date of the Note's\n"
00695 "creation (or last change), and the Note itself. These windows are\n"
00696 "editable. If you want to remove a Note from the dataset, use the\n"
00697 "Delete button for that Note. (This operation is NOT reversible - using\n"
00698 "the Quit button will not get a deleted Note back!) If you edit a note\n"
00699 "badly and want to restore it to the value saved in the dataset header,\n"
00700 "use the Restore button.\n"
00701 "\n"
00702 "Notes can also be viewed with the program 3dinfo, and with the Info\n"
00703 "buttons from the Datamode/Misc menu. The command line program 3dNotes\n"
00704 "lets you create dataset Notes in a batch script file.\n"
00705 "\n"
00706 "--- Bob Cox - September 1999\n"
00707 " (Based on ideas and some code from Tom Ross of MCW)\n"
00708
00709 , TEXT_READONLY ) ;
00710
00711 return ;
00712 }
00713
00714
00715
00716
00717
00718
00719
00720 static int ndsl = 0 ;
00721 static PLUGIN_dataset_link * dsl = NULL ;
00722
00723 static void NOTES_choose_CB( Widget w, XtPointer client_data, XtPointer call_data )
00724 {
00725 THD_session * ss = im3d->ss_now ;
00726 int vv = im3d->vinfo->view_type ;
00727 THD_3dim_dataset * qset ;
00728 int id , ltop , llen ;
00729 char qnam[THD_MAX_NAME] , label[THD_MAX_NAME] ;
00730 static char ** strlist = NULL ;
00731
00732
00733
00734 ndsl = 0 ;
00735
00736
00737
00738 for( id=0 ; id < ss->num_dsset ; id++ ){
00739 qset = ss->dsset[id][vv] ;
00740
00741 if( ! ISVALID_DSET (qset) ) continue ;
00742
00743 ndsl++ ;
00744 dsl = (PLUGIN_dataset_link *)
00745 XtRealloc( (char *) dsl , sizeof(PLUGIN_dataset_link)*ndsl ) ;
00746
00747 make_PLUGIN_dataset_link( qset , dsl + (ndsl-1) ) ;
00748 }
00749
00750
00751
00752 if( ndsl < 1 ){
00753 (void) MCW_popup_message( choose_pb ,
00754 "Didn't find any\ndatasets to edit!" ,
00755 MCW_USER_KILL | MCW_TIMER_KILL ) ;
00756 XBell( dc->display , 100 ) ;
00757 return ;
00758 }
00759
00760
00761
00762
00763 ltop = 4 ;
00764 for( id=0 ; id < ndsl ; id++ ){
00765 llen = strlen(dsl[id].title) ;
00766 ltop = MAX(ltop,llen) ;
00767 }
00768
00769 for( id=0 ; id < ndsl ; id++ ){
00770 qset = PLUTO_find_dset( &(dsl[id].idcode) ) ;
00771 if( ! ISVALID_DSET(qset) ) continue ;
00772 if( ISANAT(qset) ){
00773 if( ISANATBUCKET(qset) )
00774 sprintf(qnam,"%-*s [%s:%d]" ,
00775 ltop,dsl[id].title ,
00776 ANAT_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
00777
00778 else if( DSET_NUM_TIMES(qset) == 1 )
00779 sprintf(qnam,"%-*s [%s]" ,
00780 ltop,dsl[id].title ,
00781 ANAT_prefixstr[qset->func_type] ) ;
00782
00783 else
00784 sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
00785 ltop,dsl[id].title ,
00786 ANAT_prefixstr[qset->func_type] , DSET_NUM_TIMES(qset) ) ;
00787
00788 } else {
00789 if( ISFUNCBUCKET(qset) )
00790 sprintf(qnam,"%-*s [%s:%d]" ,
00791 ltop,dsl[id].title ,
00792 FUNC_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
00793
00794 else if( DSET_NUM_TIMES(qset) == 1 )
00795 sprintf(qnam,"%-*s [%s]" ,
00796 ltop,dsl[id].title ,
00797 FUNC_prefixstr[qset->func_type] ) ;
00798
00799 else
00800 sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
00801 ltop,dsl[id].title ,
00802 FUNC_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
00803 }
00804
00805 if( DSET_COMPRESSED(qset) ) strcat(qnam,"z") ;
00806
00807 strcpy( dsl[id].title , qnam ) ;
00808 }
00809
00810
00811
00812 POPDOWN_strlist_chooser ;
00813
00814 strlist = (char **) XtRealloc( (char *)strlist , sizeof(char *)*ndsl ) ;
00815 for( id=0 ; id < ndsl ; id++ ) strlist[id] = dsl[id].title ;
00816
00817 sprintf( label , "AFNI Dataset from\nthe %s" , VIEW_typestr[vv] ) ;
00818
00819 MCW_choose_strlist( w , label , ndsl , -1 , strlist ,
00820 NOTES_finalize_dset_CB , NULL ) ;
00821
00822 return ;
00823 }
00824
00825
00826
00827 static void NOTES_finalize_dset_CB( Widget w, XtPointer fd, MCW_choose_cbs * cbs )
00828 {
00829 int id = cbs->ival ;
00830 THD_3dim_dataset * qset ;
00831 XmString xstr ;
00832 char str[256] , * his ;
00833 int ii , nl , nltot , ww,hh,qh ;
00834
00835
00836
00837 if( ! editor_open ){ POPDOWN_strlist_chooser; XBell(dc->display,100); return; }
00838
00839 if( id < 0 || id >= ndsl ){ XBell(dc->display,100) ; return ; }
00840
00841 qset = PLUTO_find_dset( &(dsl[id].idcode) ) ;
00842
00843 if( qset == NULL ){ XBell(dc->display,100) ; return ; }
00844
00845
00846
00847 dset = qset ;
00848 dset_idc = qset->idcode ;
00849
00850
00851
00852 strcpy(str,dsl[id].title) ;
00853 xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
00854 XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
00855 XmStringFree(xstr) ;
00856
00857
00858
00859 XtUnmanageChild( notesw ) ;
00860 XtUnmanageChild( noterc ) ;
00861 for( ii=0 ; ii < notar_num ; ii++ ){
00862 XtUnmanageChild( notar[ii]->frame ) ;
00863
00864 if( notar[ii]->note_orig != NULL ){
00865 free(notar[ii]->note_orig) ; notar[ii]->note_orig = NULL ;
00866 }
00867
00868 if( notar[ii]->date_orig != NULL ){
00869 free(notar[ii]->date_orig) ; notar[ii]->date_orig = NULL ;
00870 }
00871 }
00872
00873
00874
00875 num_notes = tross_Get_Notecount( dset ) ;
00876
00877 if( notar_num < num_notes + 1 ){
00878 notar = (NOTE_wind **) realloc( notar, sizeof(NOTE_wind *)*(num_notes+1) ) ;
00879 for( ii=notar_num ; ii <= num_notes ; ii++ )
00880 notar[ii] = NOTES_make_note() ;
00881 notar_num = num_notes + 1 ;
00882 }
00883
00884
00885
00886 his = tross_Get_History( dset ) ;
00887 if( his == NULL ){
00888 ii = ( lrand48() >> 8) % NUM_DH ;
00889 notar[0]->note_orig = newstring(default_history[ii]) ;
00890 xstr = XmStringCreateLtoR( "----- EDIFYING TEXT -----" , XmFONTLIST_DEFAULT_TAG ) ;
00891 } else {
00892 notar[0]->note_orig = tross_breakup_string( his , 2*TWIDTH/3 , TWIDTH-1 ) ;
00893 free(his) ;
00894 xstr = XmStringCreateLtoR( "----- HISTORY -----" , XmFONTLIST_DEFAULT_TAG ) ;
00895 }
00896 notar[0]->date_orig = NULL ;
00897
00898 XtVaSetValues( notar[0]->note_label , XmNlabelString , xstr , NULL ) ;
00899 XmStringFree(xstr) ;
00900 XmTextSetString( notar[0]->textw , notar[0]->note_orig ) ;
00901
00902 nl = line_count( notar[0]->note_orig ) ;
00903 if( nl > max_tlines ) nl = max_tlines ;
00904 XtVaSetValues( notar[0]->textw , XmNrows , nl , NULL ) ;
00905 nltot = nl ;
00906
00907 XtManageChild( notar[0]->frame ) ;
00908
00909 for( ii=1 ; ii <= num_notes ; ii++ ){
00910 notar[ii]->note_orig = tross_Get_Note ( dset , ii ) ;
00911 notar[ii]->date_orig = tross_Get_Notedate( dset , ii ) ;
00912
00913 if( notar[ii]->note_orig == NULL )
00914 notar[ii]->note_orig = newstring( empty_note ) ;
00915
00916 if( notar[ii]->date_orig == NULL )
00917 notar[ii]->date_orig = newstring( no_date ) ;
00918
00919 sprintf(str,"----- NOTE %d [%s] -----",ii,notar[ii]->date_orig) ;
00920 xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
00921 XtVaSetValues( notar[ii]->note_label , XmNlabelString , xstr , NULL ) ;
00922 XmStringFree(xstr) ;
00923 XmTextSetString( notar[ii]->textw , notar[ii]->note_orig ) ;
00924
00925 nl = line_count( notar[ii]->note_orig ) ;
00926 if( nl > max_tlines ) nl = max_tlines ;
00927 XtVaSetValues( notar[ii]->textw , XmNrows , nl , NULL ) ;
00928 nltot += nl ;
00929
00930 XtManageChild( notar[ii]->frame ) ;
00931 }
00932
00933 XtVaSetValues( notar[0]->scrollw , XmNwidth , text_width , NULL ) ;
00934
00935 XtManageChild( noterc ) ;
00936 XtManageChild( notesw ) ;
00937
00938
00939
00940 MCW_widget_geom( noterc , &ww,&hh , NULL,NULL ) ;
00941 ww += 4 ; hh += 4 ; qh = hh ;
00942 if( ww > dc->width - 128 ) ww = dc->width - 128 ;
00943 if( hh > dc->height- 128 ) hh = dc->height- 128 ;
00944
00945 XtVaSetValues( notesw , XmNwidth,ww , XmNheight,hh , NULL ) ;
00946
00947 if( qh > hh ) scroll_topbot( notesw , 0 ) ;
00948 return ;
00949 }
00950
00951
00952
00953 static void NOTES_add_CB( Widget w, XtPointer client_data, XtPointer call_data )
00954 {
00955 int nl , hh , ii , qh ;
00956 char str[256] ;
00957 XmString xstr ;
00958
00959 if( dset == NULL ){ XBell(dc->display,100) ; return ; }
00960
00961 if( num_notes >= MAX_DSET_NOTES ){
00962 (void) MCW_popup_message( add_pb ,
00963 " \n"
00964 " Max number of notes\n"
00965 " would be exceeded!\n " ,
00966 MCW_USER_KILL | MCW_TIMER_KILL ) ;
00967 XBell(dc->display,100) ; return ;
00968 }
00969
00970 tross_Add_Note( dset , empty_note ) ;
00971
00972 num_notes ++ ;
00973
00974 if( notar_num < num_notes + 1 ){
00975 notar = (NOTE_wind **) realloc( notar, sizeof(NOTE_wind *)*(num_notes+1) ) ;
00976 for( ii=notar_num ; ii <= num_notes ; ii++ )
00977 notar[ii] = NOTES_make_note() ;
00978 notar_num = num_notes + 1 ;
00979 }
00980
00981 notar[num_notes]->note_orig = tross_Get_Note ( dset , num_notes ) ;
00982 notar[num_notes]->date_orig = tross_Get_Notedate( dset , num_notes ) ;
00983
00984 if( notar[num_notes]->note_orig == NULL )
00985 notar[num_notes]->note_orig = newstring( empty_note ) ;
00986
00987 if( notar[num_notes]->date_orig == NULL )
00988 notar[num_notes]->date_orig = newstring( no_date ) ;
00989
00990 sprintf(str,"----- NOTE %d [%s] -----",num_notes,notar[num_notes]->date_orig) ;
00991 xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
00992 XtVaSetValues( notar[num_notes]->note_label , XmNlabelString , xstr , NULL ) ;
00993 XmStringFree(xstr) ;
00994 XmTextSetString( notar[num_notes]->textw , notar[num_notes]->note_orig ) ;
00995
00996 nl = line_count( notar[num_notes]->note_orig ) ;
00997 if( nl > max_tlines ) nl = max_tlines ;
00998 XtVaSetValues( notar[num_notes]->textw , XmNrows , nl , NULL ) ;
00999
01000 XtManageChild( notar[num_notes]->frame ) ;
01001
01002
01003
01004 MCW_widget_geom( noterc , NULL,&hh , NULL,NULL ) ; hh +=4 ; qh = hh ;
01005 if( hh > dc->height- 128 ) hh = dc->height- 128 ;
01006
01007 XtVaSetValues( notesw , XmNheight,hh , NULL ) ;
01008
01009 if( qh > hh ) scroll_topbot( notesw , 1 ) ;
01010 return ;
01011 }
01012
01013
01014
01015 static void NOTES_refit_CB( Widget w, XtPointer client_data, XtPointer call_data )
01016 {
01017 int ii , hh , nl , qh ;
01018 char * ts ;
01019
01020 if( dset == NULL ){ XBell(dc->display,100) ; return ; }
01021
01022 for( ii=0 ; ii <= num_notes ; ii++ ){
01023 ts = XmTextGetString( notar[ii]->textw ) ;
01024 nl = line_count( ts ) ; XtFree( ts ) ;
01025 if( nl > max_tlines ) nl = max_tlines ;
01026 XtVaSetValues( notar[ii]->textw , XmNrows , nl , NULL ) ;
01027 }
01028
01029
01030
01031 MCW_widget_geom( noterc , NULL,&hh , NULL,NULL ) ; hh += 4 ; qh = hh ;
01032 if( hh > dc->height- 128 ) hh = dc->height- 128 ;
01033
01034 XtVaSetValues( notesw , XmNheight,hh , NULL ) ;
01035 return ;
01036 }
01037
01038
01039
01040 static void NOTES_delete_CB( Widget w, XtPointer client_data, XtPointer call_data )
01041 {
01042 int ii , kk , hh , nl ;
01043 char str[256] , * ts ;
01044 XmString xstr ;
01045
01046 if( dset == NULL ) return ;
01047
01048 for( kk=1 ; kk <= num_notes ; kk++ )
01049 if( w == notar[kk]->delete_pb ) break ;
01050
01051 if( kk > num_notes ) return ;
01052
01053 tross_Delete_Note( dset , kk ) ;
01054
01055
01056
01057 free( notar[kk]->note_orig ) ;
01058 free( notar[kk]->date_orig ) ;
01059
01060
01061
01062 for( ii=kk+1 ; ii <= num_notes ; ii++ ){
01063 notar[ii-1]->note_orig = notar[ii]->note_orig ;
01064 notar[ii-1]->date_orig = notar[ii]->date_orig ;
01065
01066 ts = XmTextGetString( notar[ii]->textw ) ;
01067 XmTextSetString( notar[ii-1]->textw , ts ) ;
01068 nl = line_count( ts ) ;
01069 if( nl > max_tlines ) nl = max_tlines ;
01070 XtVaSetValues( notar[ii-1]->textw , XmNrows , nl , NULL ) ;
01071 XtFree(ts) ;
01072
01073 sprintf(str,"----- NOTE %d [%s] -----",ii-1,notar[ii-1]->date_orig) ;
01074 xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
01075 XtVaSetValues( notar[ii-1]->note_label , XmNlabelString , xstr , NULL ) ;
01076 XmStringFree(xstr) ;
01077 }
01078
01079 notar[num_notes]->note_orig = NULL ;
01080 notar[num_notes]->date_orig = NULL ;
01081 XmTextSetString( notar[num_notes]->textw , "\0" ) ;
01082 XtUnmanageChild( notar[num_notes]->frame ) ;
01083 num_notes-- ;
01084
01085 MCW_widget_geom( noterc , NULL,&hh , NULL,NULL ) ;
01086 if( hh > dc->height- 128 ) hh = dc->height- 128 ;
01087 XtVaSetValues( notesw , XmNheight,hh , NULL ) ;
01088
01089 return ;
01090 }
01091
01092
01093
01094 static void NOTES_restore_CB( Widget w, XtPointer client_data, XtPointer call_data )
01095 {
01096 int kk ;
01097
01098 if( dset == NULL ) return ;
01099
01100 for( kk=1 ; kk <= num_notes ; kk++ )
01101 if( w == notar[kk]->restore_pb ) break ;
01102
01103 if( kk > num_notes ) return ;
01104
01105 XmTextSetString( notar[kk]->textw , notar[kk]->note_orig ) ;
01106 return ;
01107 }
01108
01109
01110
01111 static void scroll_topbot( Widget sw , int where )
01112 {
01113 Widget sb=NULL ;
01114 int val,siz,inc,pag , smin,smax ;
01115
01116 if( sw == NULL ) return ;
01117
01118 XtVaGetValues( sw ,
01119 XmNverticalScrollBar , &sb ,
01120 XmNmaximum , &smax ,
01121 XmNminimum , &smin ,
01122 NULL ) ;
01123 if( sb == NULL ) return ;
01124
01125 XmScrollBarGetValues( sb , &val,&siz,&inc,&pag ) ;
01126
01127 if( where == 0 ) val = smin ;
01128 else val = smax ;
01129
01130 XmScrollBarSetValues( sb , val,siz,inc,pag , True ) ;
01131 return ;
01132 }