Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

MotifGUI.cxx

Go to the documentation of this file.
00001 //     $Header: /nfs/slac/g/glast/ground/cvs/gui/src/MotifGUI.cxx,v 1.4 2001/10/06 04:22:14 burnett Exp $
00002 //  Author: G. Barrand, T. Burnett
00003 // Motif MotifGUI implementation
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 //          File-scope variables (could be class or object variables)
00034 static XtAppContext app;
00035 static Widget top;      //top level widget
00036 static Widget menubar;  // the menu bar
00037 static Widget currentMenu; // either the menu bar or a pull-down menu
00038 
00039 static Widget darea=0;
00040 static GUI* theGUI=0;   // pointer to the only allowed instance
00041 static Arg arglist[5];  // use to set args
00042 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00043 //    Implement the GUI-creator of the GUI superclass
00044 namespace gui {
00045 GUI* GUI::createGUI(const char* nameOfApp, const char* title)
00046 {
00047     if( theGUI) return theGUI; // ensures only one instance
00048     theGUI =new MotifGUI(nameOfApp, title);
00049     GUI::instance(theGUI);
00050     GUI::s_instance = theGUI; //(don't know if needed)
00051     return theGUI;
00052 }
00053 bool GUI::running=false;
00054 
00055 }//namespace gui
00056 
00057 // forward declaration of  local utilities
00058 
00059 static void  XmLabelSetString   (Widget,char*);
00060 Pixel XWidgetStringPixel (Widget,char*);
00061 char* XmStringToString ( XmString a_cps,int a_number);
00062 
00063 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00064 //              constructor
00065 MotifGUI::MotifGUI(const char* /*nameOfApp*/, const char* title)
00066 :GUI(title), m_scene(0)
00067 {
00068     static int argc=0;
00069     static char** argv; // connect to startup?
00070 
00071     //   create toplevel widget, set app context
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     // create a form that will hold the menubar and drawing area
00077     Widget form          = XmCreateForm(top,"form",arglist,0);
00078     XtManageChild (form);
00079 
00080     // Create the menu bar, which will contain pull-down menus, or simple commands
00081     menubar  = XmCreateMenuBar(form,"menubar",arglist,0);
00082     XtManageChild (menubar);
00083 
00084     currentMenu = menubar;
00085 
00086     // Create a drawing area
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     // Glue menubar and drawing area in the form.
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 //              Menu creation
00117 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00118 static void ButtonCallback(Widget , XtPointer clientData, XtPointer /*callData*/)
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     //if parent is there, use it.
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     // allow to be torn off?
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     // kluge to allow single button menu??? (hard to debug otherwise)
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 // private class handles toggle button
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         // should just set correct widget state if not called from X 
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;  // reset, so next command will go directly to menu bar
00218 }
00219 
00220 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00221 //                     commands
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; // no loop
00236         XtIntervalId timer=0;
00237         XtPointer client_data=0;
00238   
00239         if( pause_interval>0) { // set up a timer
00240                 timer = XtAppAddTimeOut(app, pause_interval, &TimerCallback, client_data);
00241         }
00242         running = true;
00243         // the following is equivalent to    XtAppMainLoop(app);
00244         // execpt that it can exit
00245     while( running){
00246                 //processMessages();
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); // in case resume by hand
00255     running = true; //if this is a secondary loop, so that the main loop doesn't exit 
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 //                     graphics
00275 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00276 SceneControl* MotifGUI::graphicsWindow(float size, int initial_view)
00277 {
00278     Widget drawWidget = darea;  // see what is happening
00279     m_scene = new XScene(size, initial_view, drawWidget);
00280 
00281     return  m_scene;
00282 }
00283 
00284 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00285 //                    text output
00286 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00287 std::ostream* MotifGUI::textWindow(const char* name)
00288 {
00289     return  new Xostream(  name ) ;
00290 }
00291 
00292 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00293 //                    file dialog
00294 static int messageAck;
00295 static Widget fileDialog=0;
00296 char* chosenFile; // communicate file chooser result
00297 static void OkCallback (  Widget w ,XtPointer /*a_tag*/, 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* /*startDir*/ , const char* label,
00308                                 const char* /*boxLabel*/)
00309 {
00310     if( !fileDialog ){
00311         // Create a File chooser
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 //   XtAddGrab(fileDialog, True, False);
00322     while( !messageAck)   {
00323         XEvent event;
00324         XtAppNextEvent(app, &event);
00325         XtDispatchEvent(&event);
00326     }
00327     //?? XtRemoveGrab(fileDialog);
00328 
00329     return chosenFile;
00330 }
00331 
00332 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00333 //                            message dialog
00334 static Widget messageDialog=0;
00335 static void MessageCB(Widget w, XtPointer /* client_data */,
00336                       XmAnyCallbackStruct * /*call_data*/)
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  //  XtAddGrab(messageDialog, True, False);
00356     while( !messageAck )   {
00357         XEvent event;
00358         XtAppNextEvent(app, &event);
00359         XtDispatchEvent(&event);
00360     }
00361     //?? XtRemoveGrab(messageDialog);
00362 
00363 }
00364 
00365 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00366 //                    prompt dialog
00367 static Widget promptDialog=0;
00368 static char* answer;
00369 
00370 static void PromptCB(Widget w, XtPointer /*client_data */,
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         //doesn't work? XtUnmanageChild(XmMessageBoxGetChild(promptDialog,XmDIALOG_HELP_BUTTON));
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     //  XtAddGrab(promptDialog, True, False);
00397     XtManageChild(promptDialog);
00398     messageAck=0;
00399     while( !messageAck )   {
00400         XEvent event;
00401         XtAppNextEvent(app, &event);
00402         XtDispatchEvent(&event);
00403     }
00404     //?? XtRemoveGrab(promptDialog);
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

Generated at Wed Nov 21 12:20:55 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000