GlsMenu  1.5.4
gls_menu_set.h
Go to the documentation of this file.
1 
41 #if !defined( GLS_MENUSET_H )
42 # define GLS_MENUSET_H
43 
44 # ifdef WIN32
45 # pragma warning( disable : 4786 )
46 # endif
47 
48 # include <FL/filename.H>
49 # include <fstream>
50 # include <string>
51 
52 # include "gls_menu_data.h"
53 # include "util.h"
54 
55 //----------------------------------------------------------------------------
64 //----------------------------------------------------------------------------
65 template<class MenuType_t, class DataFactory_t>
67 {
68 public:
69  typedef MenuType_t Menu_t;
70 
71  //------------------------------------------------------------------------
75  //------------------------------------------------------------------------
77  : _currentMenu( 0 )
78  , _menuData( data )
79  , _menus( new GlsMenuHandlerGroup_T<Menu_t>( "Menus", data, _actionHandlers ) )
80  {
81  // Register a default action called ShowMenu that chooses a
82  // particular menu to currently show. This allows to navigate
83  // a menu system from the menu script files. A script can
84  // contain an action like:
85  // ShowMenu: SUB_MENU
86  // which will navigate to a menu named SUB_MENU
88  "ShowMenu",
90 
92  "Toggle",
95  "Set",
96  GlsFunctor( *this, &GlsMenuSet_T::SetData ) );
98  "Inc",
99  GlsFunctor( *this, &GlsMenuSet_T::IncData ) );
100 
101  // Deprecated callbacks, still here for backwards support
103  "ToggleData",
106  "SetData",
107  GlsFunctor( *this, &GlsMenuSet_T::SetData ) );
109  "SetDataNoExpand",
111 
112  // Initialize the contents of a GlsMenuSet by adding attributes
113  // to its attribute dictionary. A menu set has the following
114  // "attributes", each of which are menu data:
115  // Data: this is a group of data items that are declared in the
116  // menu script and created at run-time
117  // Menus: this defines the menu structure.
118  _menuStructure.Add( new DataFactory_t( "Data", _menuData ) );
119  _menuStructure.Add( _menus );
120  }
121 
122  //------------------------------------------------------------------------
126  //------------------------------------------------------------------------
127  virtual ~GlsMenuSet_T()
128  {
129  std::map<std::string, GlsMenuAction::ActionHandler_t*>::iterator iter;
130 
131  for( iter = _actionHandlers.begin(); iter != _actionHandlers.end(); ++iter )
132  {
133  GlsMenuAction::ActionHandler_t* actionHandler = iter->second;
134  if( actionHandler )
135  {
136  delete actionHandler;
137  actionHandler = NULL;
138  }
139  }
140 
141  _actionHandlers.clear();
142  }
143 
144  //------------------------------------------------------------------------
148  //------------------------------------------------------------------------
149  Menu_t* Current() const { return _currentMenu; }
150 
151  //------------------------------------------------------------------------
162  //------------------------------------------------------------------------
164  const std::string& name,
166  {
167  _actionHandlers[ name ] = handler;
168  }
169 
170  //------------------------------------------------------------------------
176  //------------------------------------------------------------------------
177  void SelectItem( const typename Menu_t::ItemId_t& itemId )
178  {
179  if( _currentMenu )
180  _currentMenu->SelectItem( itemId );
181  }
182 
183  //------------------------------------------------------------------------
189  //------------------------------------------------------------------------
190  virtual void Show( const std::string& menuName = "" )
191  {
192  // Ensure there are no leading spaces
193  std::string::size_type start( menuName.find_first_not_of( ' ' ) );
194 
195  if( start == std::string::npos )
196  start = 0;
197 
198  // If the menu name is not empty, expand it in case it contains
199  // variables.
200  disti::AttributeName newMenuName(
201  menuName.empty() ? _showMenuName : disti::DecodeString( menuName.substr( start ) ) );
202 
203  // If there is no current menu or the current menu's name is not
204  // the desired menu to show
205  if( !_currentMenu || !( _currentMenu->Name() == newMenuName ) )
206  {
207  Menu_t* newMenu = _menus->Item( newMenuName );
208 
209  if( newMenu )
210  {
211  // Always invoke hide on the menu being hidden so its
212  // actions can be invoked if any.
213  if( _currentMenu )
214  _currentMenu->Hide();
215 
216  _currentMenu = newMenu;
217  _showMenuName = _currentMenu->Name();
218 
219  newMenu->Show();
220  }
221  }
222  }
223 
224  //------------------------------------------------------------------------
230  //------------------------------------------------------------------------
231  virtual void Read( std::istream& instr )
232  {
233  _menuStructure.Read( instr );
234  }
235 
236  //------------------------------------------------------------------------
242  //------------------------------------------------------------------------
243  void Read( const std::string& filename )
244  {
245  std::ifstream fstr;
246  fstr.open( filename.c_str() );
247 
248  if( !fstr.is_open() )
249  {
250  fprintf( stderr, "Unable to open file: %s\n", filename.c_str() );
251  perror( "Opening" );
252  return;
253  }
254 
255  Read( fstr );
256  fstr.close();
257  }
258 
259  //------------------------------------------------------------------------
267  //------------------------------------------------------------------------
269  const std::string& directory,
270  const std::string& ext = "menu" )
271  {
272  const std::string MENU_EXT( disti::Uppercase( ext ) );
273  int fileCount( 0 );
274  dirent** flist = 0;
275  std::string fileDir( directory );
276  disti::AppendTrailingSlash( fileDir );
277 
278  fileCount = fl_filename_list( fileDir.c_str(), &flist );
279 
280  // Go through the list of files looking for file
281  // of type *.{ext} regardless of capitalization.
282  for( int fileNum = 0; fileNum < fileCount; ++fileNum )
283  {
284  std::string fileExt = disti::GetExtension( flist[ fileNum ]->d_name );
285  if( !fileExt.empty() )
286  {
287  fileExt = disti::Uppercase( fileExt );
288  }
289  if( fileExt == MENU_EXT )
290  {
291  std::string menuFile( fileDir + flist[ fileNum ]->d_name );
292  Read( menuFile );
293 
294  } // end if
295  } // end for
296 
297  // Free the list of filename strings.
298  if( flist )
299  {
300  for( int i = fileCount - 1; i >= 0; --i )
301  {
302  free( (void*)( flist[ i ] ) );
303  }
304 
305  free( (void*)flist );
306  }
307  }
308 
309  //------------------------------------------------------------------------
315  //------------------------------------------------------------------------
316  void Write( std::ostream& outstr )
317  {
318  _menuStructure.Write( outstr );
319  }
320 
321  //------------------------------------------------------------------------
327  //------------------------------------------------------------------------
328  void Write( const std::string& filename )
329  {
330  std::fstream fstr;
331  fstr.open( filename.c_str(), std::ios::out );
332 
333  if( !fstr.is_open() )
334  {
335  fprintf( stderr, "Unable to open file: %s\n", filename );
336  return;
337  }
338 
339  // Set some defaults
340  fstr.setf( std::ios_base::fixed, std::ios::floatfield );
341  fstr.precision( 6 );
342 
343  Write( fstr );
344  fstr.close();
345  }
346 
347 protected:
351 
354 
357 
358  std::string _showMenuName;
359 
361  Menu_t* _currentMenu;
362 
365 
366 private:
367  //------------------------------------------------------------------------
371  //------------------------------------------------------------------------
372  void ShowMenu( std::istream& args )
373  {
374  std::string menuName;
375  std::getline( args, menuName );
376  Show( menuName );
377  }
378 
379  //------------------------------------------------------------------------
383  //------------------------------------------------------------------------
384  void ToggleData( std::istream& args ) const
385  {
386  std::string nameStr;
387  std::string val1;
388  std::string val2;
389 
390  if( GetQuoted( args, nameStr )
391  && GetQuoted( args, val1 )
392  && GetQuoted( args, val2 ) )
393  {
394  disti::AttributeName name( nameStr );
395 
396  if( _menuData.ValueString( name ) == val1 )
397  _menuData.ValueString( name, val2 );
398  else
399  _menuData.ValueString( name, val1 );
400  }
401  }
402 
403  //------------------------------------------------------------------------
407  //------------------------------------------------------------------------
408  void SetData( std::istream& args ) const
409  {
410  std::string name;
411  std::string val;
412 
413  while( GetQuoted( args, name )
414  && GetQuoted( args, val ) )
415  {
416  _menuData.ValueString(
417  disti::AttributeName( name ), val );
418  }
419  }
420 
421  //------------------------------------------------------------------------
425  //------------------------------------------------------------------------
426  void SetDataNoExpand( std::istream& args ) const
427  {
428  std::string name;
429  std::string val;
430 
431  while( GetQuoted( args, name )
432  && GetQuoted( args, val ) )
433  {
434  _menuData.ValueString(
435  disti::AttributeName( name ), val );
436  }
437  }
438 
439  //------------------------------------------------------------------------
443  //------------------------------------------------------------------------
444  void IncData( std::istream& args ) const
445  {
446  std::string name;
447 
448  if( GetQuoted( args, name ) )
449  {
450  int incBy( 1 );
451  args >> incBy;
452 
453  GlsMenuData* data = dynamic_cast<GlsMenuData*>(
454  _menuData.Get( disti::AttributeName( name ) ) );
455  if( data )
456  data->Inc( incBy );
457  }
458  }
459 
460  // = Unimplemented methods, disallow copies
461  GlsMenuSet_T( const GlsMenuSet_T& );
463 
464 }; // end GlsMenuSet_T
465 
466 #endif // GLS_MENUSET_H
This file defines all menu meta-data classes.
void RegisterAction(const std::string &name, GlsMenuAction::ActionHandler_t *handler)
Definition: gls_menu_set.h:163
virtual ~GlsMenuSet_T()
Definition: gls_menu_set.h:127
void SetDataNoExpand(std::istream &args) const
Definition: gls_menu_set.h:426
std::map< std::string, ActionHandler_t * > HandlerCont_t
Menu_t * _currentMenu
Currently displayed menu page.
Definition: gls_menu_set.h:361
bool GetQuoted(std::istream &instr, std::string &theString)
GlsMenuDictionary _menuStructure
Menu structure attribute dictionary contains structure of menu.
Definition: gls_menu_set.h:353
GlsMenuHandlerGroup_T< Menu_t > * _menus
Set of all menus.
Definition: gls_menu_set.h:364
void ShowMenu(std::istream &args)
Definition: gls_menu_set.h:372
void Write(std::ostream &outstr)
Definition: gls_menu_set.h:316
GlsMenuSet_T(GlsMenuDictionary &data)
Definition: gls_menu_set.h:76
void SelectItem(const typename Menu_t::ItemId_t &itemId)
Definition: gls_menu_set.h:177
void SetData(std::istream &args) const
Definition: gls_menu_set.h:408
std::string _showMenuName
Definition: gls_menu_set.h:358
GlsMenuDictionary & _menuData
Menu meta-data attribute dictionary contains variables and values.
Definition: gls_menu_set.h:356
void Write(const std::string &filename)
Definition: gls_menu_set.h:328
MenuType_t Menu_t
Definition: gls_menu_set.h:69
void ReadMenuFiles(const std::string &directory, const std::string &ext="menu")
Definition: gls_menu_set.h:268
void Read(const std::string &filename)
Definition: gls_menu_set.h:243
Menu_t * Current() const
Definition: gls_menu_set.h:149
GlsMenuSet_T & operator=(const GlsMenuSet_T &)
GlsMenuAction::HandlerCont_t _actionHandlers
Handlers for menu actions local to an instance of a menu set. Each menu set can have its own set of a...
Definition: gls_menu_set.h:350
virtual void Show(const std::string &menuName="")
Definition: gls_menu_set.h:190
void IncData(std::istream &args) const
Definition: gls_menu_set.h:444
void ToggleData(std::istream &args) const
Definition: gls_menu_set.h:384
GlsStaticMemberFunctor_T< T > * GlsFunctor(T(*f)())
Definition: gls_functor.h:110
virtual void Inc(long amount=1)
T * Item(const std::string &name) const
virtual void Read(std::istream &instr)
Definition: gls_menu_set.h:231