MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Tools/Graphical/uMS/ScopeGrid.cpp
Go to the documentation of this file.
00001 
00002 //
00003 //   MOOS - Mission Oriented Operating Suite
00004 //
00005 //   A suit of Applications and Libraries for Mobile Robotics Research
00006 //   Copyright (C) 2001-2005 Massachusetts Institute of Technology and
00007 //   Oxford University.
00008 //
00009 //   This software was written by Paul Newman at MIT 2001-2002 and Oxford
00010 //   University 2003-2005. email: pnewman@robots.ox.ac.uk.
00011 //
00012 //   This file is part of a  MOOS Utility Component.
00013 //
00014 //   This program is free software; you can redistribute it and/or
00015 //   modify it under the terms of the GNU General Public License as
00016 //   published by the Free Software Foundation; either version 2 of the
00017 //   License, or (at your option) any later version.
00018 //
00019 //   This program is distributed in the hope that it will be useful,
00020 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00022 //   General Public License for more details.
00023 //
00024 //   You should have received a copy of the GNU General Public License
00025 //   along with this program; if not, write to the Free Software
00026 //   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00027 //   02111-1307, USA.
00028 //
00030 // ScopeGrid.cpp: implementation of the CScopeGrid class.
00031 
00032 
00033 #ifdef _WIN32
00034 #pragma warning(disable : 4786)
00035 #endif
00036 
00037 #include <string>
00038 #include "ScopeGrid.h"
00039 #include <FL/fl_draw.H>
00040 #include <MOOSGenLib/MOOSGenLibGlobalHelper.h>
00041 #include <FLTKVW/MOOSFLTKUI.h>
00042 #include <FL/Fl_Input.H>
00043 #include <FL/Fl_Menu_Button.H>
00044 #include <FL/Fl_Button.H>
00045 #include <FL/Fl_Round_Button.H>
00046 #include <FL/fl_ask.H>
00047 
00048 
00049 //this is a file scope utitlity class - used for poking the MOOS
00050 class CPokeDlg : public CMOOSFLTKUI
00051 {
00052     typedef CMOOSFLTKUI BASE;
00053 public:
00054 
00055     enum{OK,CANCEL,STRING,NUMERIC,POKE};
00056     std::string m_sVal,m_sType,m_sName;
00057     double m_dfVal;
00058     bool m_bGood;
00059     bool IsGood(){return m_bGood;};
00060     bool IsDouble(){return m_sType=="D";};
00061     bool IsString(){return m_sType=="$";};
00062     std::string GetName(){return m_sName;};
00063     std::string GetString(){return m_sVal;};
00064     double GetDouble(){return m_dfVal;};
00065 
00066 
00067     CPokeDlg(int x,int y, int w, int h, const char * Name=NULL):BASE(x,y,w,h,Name)
00068     {
00069         m_bGood = false;
00070         Fl_Input* pValue = new  Fl_Input(10,20,w-20,20);
00071         SetID(pValue,POKE);
00072         pValue->align(FL_ALIGN_TOP);
00073         Fl_Button* pOK = new Fl_Button(w-70,h-30,60,20,"OK");
00074         Fl_Button* pQuit = new Fl_Button(10,h-30,60,20,"Cancel");
00075         SetID(pOK,OK);
00076         SetID(pQuit,CANCEL);
00077     }
00078 
00079     void Configure(std::string sType, std::string sVal,std::string sName)
00080     {
00081         m_sVal = sVal;
00082         m_sName =sName;
00083 
00084         ((Fl_Input*)GetByID(POKE))->value(m_sVal.c_str());
00085 
00086         if(sType=="*" || sType=="?")
00087         {
00088             if(sType=="*")
00089             {
00090                 //this is a new variable - better ask for a name
00091                 const char * pStr = fl_input("Enter name for new variable");
00092                 if(pStr==NULL)
00093                 {
00094                     return;
00095                 }
00096                 m_sName = std::string(pStr);
00097             }
00098 
00099             int nChoice = fl_choice("Variable is ","cancel","numeric","string");
00100 
00101             switch(nChoice)
00102             {
00103             case 1: m_sType = "D"; break;
00104             case 2: m_sType = "$"; break;
00105             default : return;
00106             }
00107 
00108         }
00109         else
00110         {
00111             m_sType = sType;
00112         }
00113 
00114         static char Name[1024];
00115         sprintf(Name,"new value for %s is....",m_sName.c_str());
00116         ((Fl_Input*)GetByID(POKE))->label(Name);
00117 
00118     }
00119 
00120     void OnControlWidget(Fl_Widget * pW,int nID)
00121     {
00122         switch(nID)
00123         {
00124         case OK:
00125             {
00126                 std::string sVal = ((Fl_Input*)GetByID(POKE))->value();
00127 
00128                 if(m_sType=="$"  )
00129                 {
00130                     if(!MOOSIsNumeric(sVal) || sVal.empty())
00131                         m_sVal = sVal;
00132                     else
00133                     {
00134                         fl_alert("must be string - this looks like a number");
00135                         return;
00136                     }
00137                 }
00138                 else if(m_sType=="D")
00139                 {
00140                     if(MOOSIsNumeric(sVal) && !sVal.empty() )
00141                         m_dfVal = atof(sVal.c_str());
00142                     else
00143                     {
00144                         fl_alert("must be double - this looks like a string");
00145                         return;
00146                     }
00147                 }
00148 
00149                 //and we are all done!
00150                 m_bGood = true;
00151                 GetRootWindow()->hide();
00152             }
00153             break;
00154         case CANCEL:
00155             GetRootWindow()->hide();
00156             break;
00157 
00158         }
00159     }
00160 
00161 };
00162 
00163 
00164 
00166 
00167 
00168 CScopeGrid::CScopeGrid( int X, int Y, int W, int H, const char *l ) :        Flv_Table(X,Y,W,H,l)
00169 {
00170     m_pDBImage = NULL;
00171     m_nCount = 0;
00172     m_pComms = NULL;
00173     //default size
00174     rows(500);
00175     cols(7);
00176     feature(FLVF_HEADERS|FLVF_DIVIDERS|FLVF_MULTI_SELECT|FLVF_FULL_RESIZE);
00177     feature_remove(FLVF_MULTI_SELECT | FLVF_COL_HEADER  );
00178 
00179     //fonts etc for headers
00180     Flv_Style s;
00181     Flv_Table::get_style(s,-1,0);
00182     row_style[-1].align(FL_ALIGN_CLIP);
00183     row_style[-1].font( (Fl_Font)(s.font()+FL_BOLD));
00184     col_style[1].align(FL_ALIGN_CENTER);
00185     col_style[2].align(FL_ALIGN_CENTER);
00186     col_style[3].align(FL_ALIGN_CENTER);
00187     col_style[4].align(FL_ALIGN_CENTER);
00188     col_style[5].align(FL_ALIGN_CENTER);
00189     col_style[6].align(FL_ALIGN_TOP_LEFT);
00190 
00191     global_style.font_size(12);
00192     //set up callbacks
00193     callback_when( FLVEcb_CLICKED );
00194     callback((Fl_Callback*)GridCallback);
00195     max_clicks(2);
00196 
00197     //set up hint window for veiwing data
00198     Fl_Group *save = Fl_Group::current();   // save current widget..
00199     m_pTW = new CTipWindow();                  // ..because this trashes it
00200     m_pTW->hide();
00201     Fl_Group::current(save);                // ..then back to previous.
00202 
00203     strcpy(m_csTitle,"Not connected");
00204     label(m_csTitle);
00205 
00206     // remove mouseover <-> on column/row separators
00207     // as these should not be adjustable
00208     for(int i = 0; i < 7; ++i)
00209     {col_resizable(false , i);}
00210 };
00211 
00212 
00213 
00214 void CScopeGrid::SetTitle(std::string sTitle)
00215 {
00216     strncpy(m_csTitle,sTitle.c_str(),sizeof(m_csTitle));
00217 }
00218 
00219 
00220 std::string CScopeGrid::GetDataValue(int R,int C)
00221 {
00222     CDBImage::CVar Var;
00223     if(m_pDBImage!=NULL)
00224     {
00225         if(m_pDBImage->Get(Var,R))
00226         {
00227             switch(C)
00228             {
00229             case 0:
00230                 return Var.GetName();
00231                 break;
00232             case 1:
00233                 return Var.GetTime();
00234                 break;
00235             case 2:
00236                 return Var.GetType();
00237                 break;
00238             case 3:
00239                 return Var.GetFrequency();
00240             case 4:
00241                 return Var.GetSource();
00242             case 5:
00243                 return Var.GetCommunity();
00244             case 6:
00245                 return Var.GetValue();
00246                 break;
00247             }
00248         }
00249     }
00250     return "";
00251 }
00252 
00253 
00254 bool CScopeGrid::PokeMOOS(CDBImage::CVar & Var,bool bNew)
00255 {
00256 
00257     Fl_Window W(20,20,400,100,"Poke the MOOS");
00258     CPokeDlg D(0,0,400,100,"Poke the MOOS");
00259 
00260     if(bNew)
00261     {
00262         //user has clicked on empty cell - wanting to make a new variable
00263         D.Configure("*","","");
00264     }
00265     else
00266     {
00267         D.Configure(Var.GetType(),Var.GetValue(),Var.GetName());
00268     }
00269 
00270     W.show();
00271     while(W.shown())
00272         Fl::wait();
00273 
00274     if(D.IsGood())
00275     {
00276         if(m_pComms  && m_pComms->IsConnected())
00277         {
00278             if(D.IsDouble())
00279             {
00280                 m_pComms->Notify(D.GetName(),D.GetDouble());
00281             }
00282             if(D.IsString())
00283             {
00284                 m_pComms->Notify(D.GetName(),D.GetString());
00285             }
00286         }
00287     }
00288 
00289     return true;
00290 
00291 
00292 }
00293 
00294 void CScopeGrid::OnGridCallBack()
00295 {
00296     if(why_event()==FLVE_CLICKED)
00297     {
00298         //this is a double click
00299         int c = select_start_col();
00300         int r = select_start_row();
00301         std::string sVal = GetDataValue(r,c);
00302 
00303         if(c==6)
00304         {
00305             m_pTW->value(sVal);
00306         }
00307         else
00308         {
00309             m_pTW->hide();
00310             if(c==0)
00311             {
00312                 //hold control down to poke...
00313                 if((Fl::event_key(FL_Control_L)||Fl::event_key(FL_Control_R)))
00314                 {
00315                     CDBImage::CVar Var;
00316                     if(m_pDBImage->Get(Var,r))
00317                     {
00318                         PokeMOOS(Var,false);
00319                     }
00320                     else
00321                     {
00322                         PokeMOOS(Var,true);
00323                     }
00324                 }
00325             }
00326         }
00327     }
00328 }
00329 
00330 
00331 
00332 
00333 
00334 void CScopeGrid::redraw()
00335 {
00336     int c = select_start_col();
00337     int r = select_start_row();
00338     if(c==6)
00339     {
00340         std::string sVal = GetDataValue(r,c);
00341         m_pTW->value(sVal);
00342     }
00343 
00344     BASE::redraw();
00345 }
00346 
00347 int CScopeGrid::handle(int e)
00348 {
00349     switch(e)
00350     {
00351     case FL_PUSH:
00352         // XXX: if offscreen, move tip ABOVE mouse instead
00353         m_pTW->position(Fl::event_x_root(), Fl::event_y_root());
00354         m_pTW->show();
00355         break;
00356     case FL_HIDE:       // valuator goes away
00357     case FL_RELEASE:    // release mouse
00358     case FL_LEAVE:      // leave focus
00359         // Make sure tipwin closes when app closes
00360         m_pTW->hide();
00361         break;
00362     }
00363     return(BASE::handle(e));
00364 }
00365 
00366 
00367 void CScopeGrid::draw_cell( int Offset, int &X, int &Y, int &W, int &H, int R, int C )
00368 {
00369     Flv_Style s;
00370     get_style(s, R, C);
00371 
00372 
00373     Flv_Table::draw_cell(Offset,X,Y,W,H,R,C);
00374 
00375     if(R==-1)
00376     {
00377         //this is the header:
00378         const char * ColumnNames[] = {"Name","Time","Type","Freq","Source","Community","Value"};
00379         const char * pStr = C<sizeof(ColumnNames) ? ColumnNames[C] : "";
00380         fl_draw(pStr, X-Offset, Y, W, H, s.align() );
00381     }
00382     else
00383     {
00384         //FIX for FLTK escaping of "@" PMN May 2005
00385         std::string sStr = GetDataValue(R,C).c_str();
00386         std::string sFLTK;
00387         while(!sStr.empty())
00388         {
00389             sFLTK += MOOSChomp(sStr,"@");
00390             if(!sStr.empty())
00391                 sFLTK+="@@";
00392         }
00393         fl_draw(sFLTK.c_str(), X-Offset, Y, W, H, s.align() );
00394     }
00395 }
00396 
00397 
00398 void CScopeGrid::get_style( Flv_Style &s, int R, int C )
00399 {
00400     Flv_Table::get_style(s,R,C);                    //    Get standard style
00401     if(R%2==0)
00402     {
00403         s.background( (Fl_Color)(FL_GRAY_RAMP+22) );
00404     }
00405     if(C==6 && m_pDBImage->HasChanged(R))
00406     {
00407         s.foreground( (Fl_Color)(FL_RED) );
00408     }
00409 }
00410 
00411 
00412 
00413 int CScopeGrid::col_width( int C )
00414 {
00415     static int LW=-1;
00416     static int cw[7];
00417     int scrollbar_width = (scrollbar.visible()?scrollbar.w():0);
00418     int W = w()- scrollbar_width-1;
00419     int ww, t;
00420 
00421     //    Either always calculate or be sure to check that width
00422     //    hasn't changed.
00423     if (W!=LW)                            //    Width change, recalculate
00424     {
00425         //char * ColumnNames[] = {"Name","Time","Type","Freq","Source","Community","Value"};
00426         cw[0] = (W*20)/100;        //    30        Name
00427         cw[1] = (W*10)/100;        //    10        Time
00428         cw[2] = (W*4)/100;        //    15%        Type
00429         cw[3] = (W*6)/100;        //     8%        Freq
00430         cw[4] = (W*10)/100;        //    15%        Src
00431         cw[5] = (W*10)/100;        //    15%        Comm
00432         cw[6] = (W*30)/100;        //    15%        Val
00433 
00434 
00435         for (ww=0, t=0;    t<6;    t++ )
00436         {
00437             ww += cw[t];
00438         }
00439         cw[6] = W-ww-1;                     //    ~30% +/- previous rounding errors
00440         LW = W;
00441     }
00442     return cw[C];
00443 
00444 }
00445 
00446 void CScopeGrid::SetDBImage(CDBImage *pDBImage)
00447 {
00448     m_pDBImage = pDBImage;
00449 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines