00001
00002
00003
00004
00005 #ifndef WIN32 // stupid to prevent compilation in windows
00006
00007 #include "MotifGUI.h"
00008 #include "Xostream.h"
00009 #include "XScene.h"
00010
00011 #include "gui/Command.h"
00012
00013 #include <Xm/Xm.h>
00014 #include <Xm/Form.h>
00015 #include <Xm/RowColumn.h>
00016 #include <Xm/CascadeB.h>
00017 #include <Xm/PushB.h>
00018 #include <Xm/DrawingA.h>
00019 #include <Xm/FileSB.h>
00020 #include <Xm/MessageB.h>
00021 #include <Xm/SelectioB.h>
00022 #include <Xm/Text.h>
00023 #include <Xm/ToggleB.h>
00024 #include <Xm/Separator.h>
00025
00026
00027 #include <strstream>
00028 #include <iostream>
00029 #include <cstdio>
00030 #include <cassert>
00031
00032
00033
00034 static XtAppContext app;
00035 static Widget top;
00036 static Widget menubar;
00037 static Widget currentMenu;
00038
00039 static Widget darea=0;
00040 static GUI* theGUI=0;
00041 static Arg arglist[5];
00042
00043
00044 namespace gui {
00045 GUI* GUI::createGUI(const char* nameOfApp, const char* title)
00046 {
00047 if( theGUI) return theGUI;
00048 theGUI =new MotifGUI(nameOfApp, title);
00049 GUI::instance(theGUI);
00050 GUI::s_instance = theGUI;
00051 return theGUI;
00052 }
00053 bool GUI::running=false;
00054
00055 }
00056
00057
00058
00059 static void XmLabelSetString (Widget,char*);
00060 Pixel XWidgetStringPixel (Widget,char*);
00061 char* XmStringToString ( XmString a_cps,int a_number);
00062
00063
00064
00065 MotifGUI::MotifGUI(const char* , const char* title)
00066 :GUI(title), m_scene(0)
00067 {
00068 static int argc=0;
00069 static char** argv;
00070
00071
00072 XtSetArg (arglist[0],XtNtitle,(char*)title);
00073 top = XtAppInitialize(&app,"MotifoGUI", NULL,0, &argc,argv,NULL,arglist,1);
00074 if(!top) exit(-1);
00075
00076
00077 Widget form = XmCreateForm(top,"form",arglist,0);
00078 XtManageChild (form);
00079
00080
00081 menubar = XmCreateMenuBar(form,"menubar",arglist,0);
00082 XtManageChild (menubar);
00083
00084 currentMenu = menubar;
00085
00086
00087 XtSetArg (arglist[0],XmNwidth, 500);
00088 XtSetArg (arglist[1],XmNheight,500);
00089 XtSetArg (arglist[2],XmNbackground,XWidgetStringPixel (top,"lightgrey"));
00090 darea = XmCreateDrawingArea (form,"darea",arglist,3);
00091 XtManageChild (darea);
00092
00093
00094 XtSetArg (arglist[0],XmNtopAttachment,XmATTACH_FORM);
00095 XtSetArg (arglist[1],XmNleftAttachment,XmATTACH_FORM);
00096 XtSetArg (arglist[2],XmNrightAttachment,XmATTACH_FORM);
00097 XtSetValues (menubar,arglist,3);
00098
00099 XtSetArg (arglist[0],XmNtopAttachment,XmATTACH_WIDGET);
00100 XtSetArg (arglist[1],XmNtopWidget,menubar);
00101 XtSetArg (arglist[2],XmNleftAttachment,XmATTACH_FORM);
00102 XtSetArg (arglist[3],XmNrightAttachment,XmATTACH_FORM);
00103 XtSetArg (arglist[4],XmNbottomAttachment,XmATTACH_FORM);
00104 XtSetValues (darea,arglist,5);
00105
00106 }
00107
00108
00109 void MotifGUI::setTitle(const char* newtitle)
00110 {
00111 XtSetArg (arglist[0],XtNtitle,(char*)newtitle);
00112 XtSetValues (top, arglist,1);
00113 }
00114
00115
00116
00117
00118 static void ButtonCallback(Widget , XtPointer clientData, XtPointer )
00119 {
00120 Command* cmd = (Command*)clientData;
00121 cmd->execute();
00122 }
00123
00124 GUI::Menu*
00125 MotifGUI::beginPullDownMenu(const char * menuName, GUI::Menu* parent)
00126 {
00127
00128 Widget pmen = parent? (Widget)parent : menubar;
00129 Widget casc = XmCreateCascadeButton(pmen,"casc",arglist,0);
00130 XtManageChild (casc);
00131
00132 Widget pull = XmCreatePulldownMenu (pmen,"pull",arglist,0);
00133 XtSetArg (arglist[0], "subMenuId", pull);
00134 XtSetValues (casc,arglist,1);
00135 XmLabelSetString (casc,(char*)menuName);
00136
00137
00138 XtSetArg( arglist[0], XmNtearOffModel, XmTEAR_OFF_ENABLED);
00139 XtSetValues( pull, arglist, 1);
00140
00141 currentMenu = pull;
00142 return (GUI::Menu*) pull;
00143 }
00144
00145 void MotifGUI::restorePullDownMenu(GUI::Menu* m)
00146 {
00147 currentMenu = (Widget)m;
00148 }
00149
00150 void MotifGUI::addToMenu(const char* buttonName, Command* cmd)
00151 {
00152
00153 if( currentMenu == menubar ) {
00154
00155 beginPullDownMenu(buttonName);
00156 addToMenu(buttonName, cmd);
00157 endPullDownMenu();
00158 return;
00159 }
00160
00161 Widget button = XmCreatePushButton (currentMenu, "button", arglist,0);
00162
00163 XtManageChild (button);
00164 XtAddCallback (button, XmNactivateCallback, ButtonCallback,(XtPointer)cmd);
00165 XmLabelSetString (button,(char*)buttonName);
00166
00167 }
00168
00169 class MotifGUI::Toggle : public GUI::Toggle
00170
00171 {
00172 public:
00173 Toggle( Command* cmd1, Command* cmd2 ,bool state, Widget button)
00174 : m_set_cmd(cmd1)
00175 , m_unset_cmd(cmd2)
00176 , m_state(state)
00177 , m_button(button)
00178 {}
00179 void execute() {
00180 if( m_state){
00181 m_unset_cmd->execute(); m_state=false;
00182 }
00183 else {
00184 m_set_cmd->execute(); m_state=true;
00185 }
00186
00187 XtSetArg(arglist[0], XmNset, m_state );
00188 XtSetValues(m_button, arglist, 1);
00189 }
00190 bool state()const{return m_state;}
00191 private:
00192 Command *m_set_cmd, *m_unset_cmd;
00193 bool m_state;
00194 Widget m_button;
00195 };
00196
00197 GUI::Toggle* MotifGUI::addToggleToMenu(const char* title, bool state, Command* set, Command* unset)
00198 {
00199 XtSetArg(arglist[0], XmNset, state );
00200 Widget button = XmCreateToggleButton(currentMenu, "button", arglist,1);
00201 XtManageChild (button);
00202 GUI::Toggle* t = new Toggle(set,unset,state,button);
00203 XtAddCallback (button, XmNvalueChangedCallback, ButtonCallback, (XtPointer)t);
00204 XmLabelSetString (button, (char*)title);
00205 return t;
00206
00207 }
00208
00209 void MotifGUI::menuSeparator()
00210 {
00211 XtManageChild(
00212 XmCreateSeparator(currentMenu, "separator", arglist, 0));
00213 }
00214
00215 void MotifGUI::endPullDownMenu()
00216 {
00217 currentMenu = menubar;
00218 }
00219
00220
00221
00222
00223 static void TimerCallback ( XtPointer a_data, XtIntervalId* timer )
00224 {
00225 GUI::running = false;
00226 }
00227
00228 void MotifGUI::run(int pause_interval)
00229 {
00230 static bool first = true;
00231 if (first) {
00232 XtRealizeWidget(top);
00233 first = false;
00234 }
00235 if( pause_interval ==0 ) return;
00236 XtIntervalId timer=0;
00237 XtPointer client_data=0;
00238
00239 if( pause_interval>0) {
00240 timer = XtAppAddTimeOut(app, pause_interval, &TimerCallback, client_data);
00241 }
00242 running = true;
00243
00244
00245 while( running){
00246
00247 #if 0
00248 XEvent event;
00249 XtAppNextEvent(app, &event);
00250 XtDispatchEvent(&event);
00251 #endif
00252 XtAppProcessEvent (app, XtIMAll);
00253 }
00254 if( timer!=0) XtRemoveTimeOut(timer);
00255 running = true;
00256
00257 }
00258
00259 void MotifGUI::quit()
00260 {
00261 running = false;
00262 }
00263
00264 void MotifGUI::processMessages()
00265 {
00266 while( XtAppPending(app) & XtIMXEvent) {
00267 XEvent event;
00268 XtAppNextEvent(app, &event);
00269 XtDispatchEvent(&event);
00270 }
00271 }
00272
00273
00274
00275
00276 SceneControl* MotifGUI::graphicsWindow(float size, int initial_view)
00277 {
00278 Widget drawWidget = darea;
00279 m_scene = new XScene(size, initial_view, drawWidget);
00280
00281 return m_scene;
00282 }
00283
00284
00285
00286
00287 std::ostream* MotifGUI::textWindow(const char* name)
00288 {
00289 return new Xostream( name ) ;
00290 }
00291
00292
00293
00294 static int messageAck;
00295 static Widget fileDialog=0;
00296 char* chosenFile;
00297 static void OkCallback ( Widget w ,XtPointer , XtPointer a_data )
00298 {
00299 XmFileSelectionBoxCallbackStruct *data
00300 = (XmFileSelectionBoxCallbackStruct*)a_data;
00301 chosenFile = XmStringToString (data->value,0);
00302 XtUnmanageChild(w);
00303 messageAck=1;
00304 }
00305
00306
00307 char * MotifGUI::askForFileName(const char* , const char* label,
00308 const char* )
00309 {
00310 if( !fileDialog ){
00311
00312 XtSetArg (arglist[0],XmNautoUnmanage,True);
00313 fileDialog = XmCreateFileSelectionDialog (top,"fileDialog",arglist,1);
00314 XtAddCallback (fileDialog,XmNokCallback ,OkCallback,(XtPointer)0);
00315 }
00316 XtSetArg (arglist[0],XtNtitle,(char*)label);
00317 XtSetValues (fileDialog, arglist, 1);
00318
00319 messageAck=0;
00320 XtManageChild(fileDialog);
00321
00322 while( !messageAck) {
00323 XEvent event;
00324 XtAppNextEvent(app, &event);
00325 XtDispatchEvent(&event);
00326 }
00327
00328
00329 return chosenFile;
00330 }
00331
00332
00333
00334 static Widget messageDialog=0;
00335 static void MessageCB(Widget w, XtPointer ,
00336 XmAnyCallbackStruct * )
00337 {
00338 XtUnmanageChild(w);
00339 messageAck=1;
00340 }
00341 void
00342 MotifGUI::inform(const char* msg)
00343 {
00344 if( !messageDialog ) {
00345 messageDialog=XmCreateMessageDialog(top,"dialog",arglist,0);
00346 XtAddCallback(messageDialog,XmNokCallback,(XtCallbackProc)MessageCB,NULL);
00347 XtUnmanageChild(XmMessageBoxGetChild(messageDialog,XmDIALOG_CANCEL_BUTTON));
00348 XtUnmanageChild(XmMessageBoxGetChild(messageDialog,XmDIALOG_HELP_BUTTON));
00349 }
00350 XtSetArg(arglist[0], XmNmessageString,
00351 XmStringCreateLtoR((char*)msg,XmSTRING_DEFAULT_CHARSET));
00352 XtSetValues (messageDialog,arglist,1);
00353 messageAck=0;
00354 XtManageChild(messageDialog);
00355
00356 while( !messageAck ) {
00357 XEvent event;
00358 XtAppNextEvent(app, &event);
00359 XtDispatchEvent(&event);
00360 }
00361
00362
00363 }
00364
00365
00366
00367 static Widget promptDialog=0;
00368 static char* answer;
00369
00370 static void PromptCB(Widget w, XtPointer ,
00371 XmSelectionBoxCallbackStruct *call_data)
00372 {
00373 if( call_data->reason==XmCR_OK )
00374 XmStringGetLtoR(call_data->value,XmSTRING_DEFAULT_CHARSET,&answer);
00375 messageAck=1;
00376 XtUnmanageChild(w);
00377 }
00378
00379 char*
00380 MotifGUI::askUser(const char* promptString,const char* defaultString)
00381 {
00382 if( !promptDialog ) {
00383 promptDialog=XmCreatePromptDialog(top,"dialog",arglist,0);
00384
00385 XtAddCallback(promptDialog,XmNokCallback,(XtCallbackProc)PromptCB,NULL);
00386 XtAddCallback(promptDialog,XmNcancelCallback,(XtCallbackProc)PromptCB,NULL);
00387
00388
00389
00390 }
00391 XtSetArg(arglist[0], XmNselectionLabelString,
00392 XmStringCreateLtoR((char*)promptString,XmSTRING_DEFAULT_CHARSET));
00393 XtSetArg(arglist[1], XmNtextString,
00394 XmStringCreateLtoR((char*)defaultString,XmSTRING_DEFAULT_CHARSET));
00395 XtSetValues (promptDialog,arglist,2);
00396
00397 XtManageChild(promptDialog);
00398 messageAck=0;
00399 while( !messageAck ) {
00400 XEvent event;
00401 XtAppNextEvent(app, &event);
00402 XtDispatchEvent(&event);
00403 }
00404
00405
00406 return answer;
00407 }
00408
00409
00410 static void XmLabelSetString (
00411 Widget This
00412 , char* a_string
00413 )
00414
00416 {
00417 Arg arglist[1];
00418 XmString cps;
00419
00420 if(!This) return;
00421 if(!a_string) return;
00422 cps = XmStringLtoRCreate(a_string,XmSTRING_DEFAULT_CHARSET);
00423 XtSetArg (arglist[0],XmNlabelString,cps);
00424 XtSetValues (This,arglist,1);
00425 XmStringFree (cps);
00426 }
00427
00428 Pixel XWidgetStringPixel (
00429 Widget This
00430 ,char* a_string
00431 )
00432
00434 {
00435 XrmValue from,to;
00436
00437 if(!This) return (Pixel)NULL;
00438 if(!a_string || !(*a_string)) return (Pixel)NULL;
00439 from.size = strlen(a_string)+1;
00440 from.addr = (caddr_t)a_string;
00441 XtConvert (This,XtRString,&from,XtRPixel,&to);
00442 if(!to.addr) return (Pixel)NULL;
00443 return (*((Pixel*)to.addr));
00444 }
00445
00446 char* XmStringToString (
00447 XmString a_cps
00448 ,int a_number
00449 )
00450
00452 {
00453 char* string;
00454 register int icount;
00455 XmStringContext context;
00456 Boolean done;
00457
00458 if(!a_cps) return 0;
00459 string = 0;
00460 XmStringInitContext (&context,a_cps);
00461 icount = 0;
00462 done = False;
00463 while(!done)
00464 { char* text = 0;
00465 XmStringCharSet charset = 0;
00466 XmStringDirection direct;
00467 Boolean sep;
00468 if(XmStringGetNextSegment (context,&text,&charset,&direct,&sep))
00469 {
00470 XtFree (charset);
00471 if(sep) done = True;
00472 if(icount==a_number)
00473 {
00474 string = text;
00475 break;
00476 }
00477 icount ++;
00478 XtFree (text);
00479 }
00480 else
00481 done = True;
00482 }
00483 XmStringFreeContext (context);
00484 return string;
00485 }
00486
00487
00488 #endif // of NT_MSVCPP