/* ************************************************************************* ArmageTron -- Just another Tron Lightcycle Game in 3D. Copyright (C) 2000 Manuel Moos (manuel@moosnet.de) Copyright (C) 2004 Armagetron Advanced Team (http://sourceforge.net/projects/armagetronad/) ************************************************************************** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *************************************************************************** */ #ifndef ArmageTron_MENU_H #define ArmageTron_MENU_H #include "rFont.h" #include "tList.h" #include "tString.h" #include "tCallback.h" #include "tLocale.h" #include "rSDL.h" #ifndef DEDICATED #include #endif #include "defs.h" class uMenuItem; class uMenu{ friend class uMenuItem; protected: tList items; static FUNCPTR idle; REAL menuTop; REAL menuBot; REAL yOffset; bool exitFlag; REAL spaceBelow; REAL center; int selected; REAL YPos(int num); public: static bool wrap; static bool quickexit; static bool exitToMain; tOutput title; FUNCPTR IdleFunc(){return idle;} static void SetIdle(FUNCPTR idle_func) {idle=idle_func;} void SetCenter(REAL c) {center=c;} void SetTop(REAL t) {menuTop=t;} void SetBot(REAL b) {menuBot=b;spaceBelow=1+menuBot;} void SetSelected(int s) {selected = s;} int NumItems() {return items.Len();} uMenuItem* Item(int i) { return items[i]; } void AddItem(uMenuItem* item); void RemoveItem(uMenuItem* item); #ifdef SLOPPYLOCALE uMenu(const char *t,bool exit_item=true); #endif uMenu(const tOutput &t,bool exit_item=true); virtual ~uMenu(); // enters the menu; calls idle_func bef void Enter(); // handles a key press virtual void HandleEvent( SDL_Event event ); void ReverseItems(); // paints a nice background static void GenericBackground(); // marks the menu for exit void Exit(); void RequestSpaceBelow(REAL x){ if (spaceBelowitems.Add(this,idnum); } #ifdef SLOPPYLOCALE uMenuItem(uMenu *M,const char *help) :idnum(-1),menu(M),helpText(help){ menu->items.Add(this,idnum); } #endif virtual ~uMenuItem() { if (menu && idnum >= 0) menu->items.Remove(this,idnum); } virtual tString Help(){return static_cast(helpText);} // displays the menuitem at position x,y. set selected to true // if the item is currently under the cursor virtual void Render(REAL ,REAL ,REAL =1,bool =0){}; virtual void RenderBackground(){ menu->GenericBackground(); }; // if the user presses left/right on menuitem virtual void LeftRight(int ){}; //lr=-1:left lr=+1: right virtual void LeftRightRelease(){}; virtual void Enter(){}; // if the user presses enter/space on menu virtual bool Event(SDL_Event &){return false;} // if the key c is // pressed,mouse moved ... // while menuitem is active; return value: key was used virtual REAL SpaceRight(){return 0;} int GetID(){return idnum;} }; // ***************************************************** // Menu Exit // ***************************************************** class uMenuItemExit:public uMenuItem{ tOutput t; static const tOutput& ExitText(); static const tOutput& ExitHelp(); public: uMenuItemExit(uMenu *M, const tOutput &text = ExitText(), const tOutput &help = ExitHelp()) :uMenuItem(M,help) ,t(text){} // displays the menuitem at position x,y. set selected to true // if the item is currently under the cursor virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0){ DisplayTextSpecial(x,y,tString(t),selected,alpha); }; virtual void Enter(){menu->Exit();} // if the user presses enter/space on menu }; // ***************************************************** // Selection // ***************************************************** template class uSelectItem{ public: int idnum; tOutput description; tOutput helpText; T value; uSelectItem(const tOutput& desc,const tOutput& help,T val) :idnum(-1),description(desc),helpText(help),value(val){} }; template class uMenuItemSelection:public uMenuItem{ protected: tList > choices; tOutput title; int select; T * target; public: #ifdef SLOPPYLOCALE uMenuItemSelection(uMenu *m, const char* tit,const char *help, T &targ) :uMenuItem(m,help),title(tit),select(0),target(&targ){} #endif uMenuItemSelection(uMenu *m, const tOutput &tit,const tOutput &help, T &targ) :uMenuItem(m,help),title(tit),select(0),target(&targ){} ~uMenuItemSelection(){ Clear(); } void Clear(){ for(int i=choices.Len()-1;i>=0;i--){ uSelectItem *x=choices(i); choices.Remove(x,x->idnum); delete x; } select=0; } void NewChoice(uSelectItem *c){ choices.Add(c,c->idnum); } void NewChoice(const tOutput& desc,const tOutput& help,T val){ uSelectItem *x=new uSelectItem(desc,help,val); NewChoice(x); } virtual void LeftRight(int lr){ select+=lr; if(select>=choices.Len()) select=choices.Len()-1; if(select<0) select=0; if (choices.Len()) *target=choices(select)->value; } virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0){ for(int i=choices.Len()-1;i>=0;i--) if (choices(i)->value==*target) select=i; DisplayText(REAL(x-.02),y,title,selected,alpha,1); if (choices.Len()>0) DisplayText(REAL(x+.02),y,choices(select)->description,selected,alpha,-1); } virtual tString Help(){ tString ret; ret << helpText; ret << "\n"; ret << choices(select)->helpText; return ret; } }; template class uSelectEntry{ public: uSelectEntry(uMenuItemSelection &sel, const char *desc, const char *help,T val){ sel.NewChoice(desc,help,val); } }; // ***************************************** // Toggle // ***************************************** class uMenuItemToggle: public uMenuItemSelection{ void NewChoice(uSelectItem *c); void NewChoice(const char *desc,bool val); public: #ifdef SLOPPYLOCALE uMenuItemToggle(uMenu *m,const char *tit, const char *help,bool &targ); #endif uMenuItemToggle(uMenu *m,const tOutput& title, const tOutput& help,bool &targ); ~uMenuItemToggle(); virtual void LeftRight(int); virtual void Enter(); }; // ***************************************** // Integer Choose // ***************************************** class uMenuItemInt:public uMenuItem{ protected: tOutput title; int ⌖ int Min,Max; int Step; public: /* uMenuItemInt(uMenu *m,const char *tit, const char *help,int &targ, int mi,int ma,int step=1); */ uMenuItemInt(uMenu *m,const tOutput &title, const tOutput &help,int &targ, int mi,int ma,int step=1); ~uMenuItemInt(){}; virtual void LeftRight(int); virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0); }; // ***************************************************** // String query // ***************************************************** class uMenuItemString: public uMenuItem{ protected: tOutput description; tString *content; int cursorPos; int maxLength_; public: uMenuItemString(uMenu *M,const tOutput& desc, const tOutput& help,tString &c, int maxLength = 1024 ); virtual ~uMenuItemString(){} virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0); virtual bool Event(SDL_Event &e); uMenu *MyMenu(){return menu;} }; // ***************************************************** // Submenu // ***************************************************** class uMenuItemSubmenu: public uMenuItem{ uMenu *submenu; public: uMenuItemSubmenu(uMenu *M,uMenu *s, const tOutput& help); virtual ~uMenuItemSubmenu(){} virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0); virtual void Enter(); }; // ***************************************************** // generic action // ***************************************************** class uMenuItemAction: public uMenuItem{ public: uMenuItemAction(uMenu *M,const tOutput& name, const tOutput& help ); virtual ~uMenuItemAction(){} virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0); virtual void Enter() = 0; protected: tOutput name_; }; // ***************************************************** // Execute function // ***************************************************** class uMenuItemFunction: public uMenuItemAction{ FUNCPTR func; public: uMenuItemFunction(uMenu *M,const tOutput& name, const tOutput& help,FUNCPTR f); virtual ~uMenuItemFunction(){} virtual void Enter(); }; class uMenuItemFunctionInt: public uMenuItemAction{ INTFUNCPTR func; int arg; public: uMenuItemFunctionInt(uMenu *M,const tOutput& name, const tOutput& help,INTFUNCPTR f,int arg); virtual ~uMenuItemFunctionInt(){} virtual void Enter(); }; // ***************************************************** // File Selection (added by k) // ***************************************************** class uMenuItemFileSelection: public uMenuItemSelection { void NewChoice( uSelectItem * ); void NewChoice( char *, bool ); protected: tString dir_; tString fileSpec_; int getFilesFlag_; bool formatName_; tString defaultFileName_; tString defaultFilePath_; public: uMenuItemFileSelection( uMenu *m, char *tit, const char *help, tString& targ, const char *dir, const char *fileSpec, int getFilesFlag = 0, bool formatName = true ) :uMenuItemSelection( m, tit, help, targ ) { SetParams( dir, fileSpec, getFilesFlag, formatName, "", "" ); Reload(); } uMenuItemFileSelection( uMenu *m, char *tit, const char *help, tString& targ, const char *dir, const char *fileSpec, const char *defaultFileName, const char *defaultFilePath, int getFilesFlag = 0, bool formatName = true ) :uMenuItemSelection( m, tit, help, targ ) { SetParams( dir, fileSpec, getFilesFlag, formatName, defaultFileName, defaultFilePath ); Reload(); } virtual ~uMenuItemFileSelection() {}; void SetDir( const char *dir ) { dir_ = dir; }; const void SetFileSpec( const char *fileSpec ) { fileSpec_ = fileSpec; }; const void SetFormatName( bool formatName ) { formatName_ = formatName; }; const void SetGetFilesFlag( int getFilesFlag ) { getFilesFlag_ = getFilesFlag; } const void SetDefaultFileName( const char *defaultFileName ) { defaultFileName_ = defaultFileName; }; const void SetDefaultFilePath( const char *defaultFilePath ) { defaultFilePath_ = defaultFilePath; }; const void SetParams( const char *dir, const char *fileSpec, int getFilesFlag, bool formatName, const char *defaultFileName, const char *defaultFilePath ) { SetDir( dir ); SetFileSpec( fileSpec ); SetGetFilesFlag( getFilesFlag ); SetFormatName( formatName ); SetDefaultFileName( defaultFileName ); SetDefaultFilePath( defaultFilePath ); } void Reload(); void LoadDirectory( const char *dir, const char *fileSpec, bool formatName = true ); void AddFile( const char *fileName, const char *filePath, bool formatName = true ); }; // ***************************************************** // Menu Enter/Leave-Callback // ***************************************************** class uCallbackMenuEnter: public tCallback{ public: uCallbackMenuEnter(VOIDFUNC *f); static void MenuEnter(); }; class uCallbackMenuLeave: public tCallback{ public: uCallbackMenuLeave(VOIDFUNC *f); static void MenuLeave(); }; class uCallbackMenuBackground: public tCallback{ public: uCallbackMenuBackground(VOIDFUNC *f); static void MenuBackground(); }; inline void uMenu::AddItem(uMenuItem* item) { items.Add(item, item->idnum); } inline void uMenu::RemoveItem(uMenuItem* item) { items.Remove(item, item->idnum); } #endif