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

ndk++.h

Go to the documentation of this file.
00001 // * This makes emacs happy -*-Mode: C++;-*-
00002 /****************************************************************************
00003  * Copyright (c) 2002 Fabrica de Software XXI SRL - info@lafabrica.com.ar   *
00004  * Copyright (c) 2002 RaqLink SA - info@raqlink.com                         *
00005  *                                                                          *
00006  * Permission is hereby granted, free of charge, to any person obtaining a  *
00007  * copy of this software and associated documentation files (the            *
00008  * "Software"), to deal in the Software without restriction, including      *
00009  * without limitation the rights to use, copy, modify, merge, publish,      *
00010  * distribute, distribute with modifications, sublicense, and/or sell       *
00011  * copies of the Software, and to permit persons to whom the Software is    *
00012  * furnished to do so, subject to the following conditions:                 *
00013  *                                                                          *
00014  * The above copyright notice and this permission notice shall be included  *
00015  * in all copies or substantial portions of the Software.                   *
00016  *                                                                          *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
00020  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
00021  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
00022  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
00023  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
00024  *                                                                          *
00025  * Except as contained in this notice, the name(s) of the above copyright   *
00026  * holders shall not be used in advertising or otherwise to promote the     *
00027  * sale, use or other dealings in this Software without prior written       *
00028  * authorization.                                                           *
00029  ****************************************************************************/
00030 
00031 /****************************************************************************
00032  *  Author Miguel Pinkas <miguel@lafabrica.com.ar>                          *
00033  ****************************************************************************/
00034 #if !defined(__NDK_NCURSES__)
00035 #define __NDK_NCURSES__
00036 #include <cursesapp.h>
00037 #include <cursesm.h>
00038 #include <vector>
00039 #include <string>
00040 #include <fstream>
00041 #include <typeinfo>
00042 using namespace std;
00043 
00044 #if HAVE_LIBC_H
00045 #  include <libc.h>
00046 #endif
00047 
00048 #include "dlgdefines.h"
00049 
00050 namespace NDK_XX {
00051 
00052 ofstream &get_logfile();
00053 
00054 struct BINDING;
00055 struct BINDING_MAP;
00056 
00057 /*******************************************************************
00058 *   \class Control                                                  *
00059 *   A Panel which behaves as a basic dialog control.               *
00060 *   Is the base class for all the dialog controls and dialog boxes *
00061 ********************************************************************/
00062 class Control : public NCursesPanel
00063 {
00064     friend class DialogBox;
00065 public:
00066     ///The styles a control can have
00067     enum styles{
00068         framed  =   0x0001, ///Do we have a frame?
00069         moveable=   0x0002, ///We can be moved around?
00070         editable=   0x0004, ///Is our text editable?
00071         tabstop =   0x0008, ///Can be looped thru?
00072         notify  =   0x0010, ///Do we notify our parent of events?
00073         hscroll =   0x0020, ///Can we scroll horizontally?
00074         multisel=   0x0040, ///Can select multiple items?
00075         hscrollbar= 0x0100, ///Draw horizontal scrollbar?
00076         vscrollbar= 0x0200, ///Draw vertical scrollbar?
00077         title   =   0x0400, ///Show title of this control?
00078         hidden  =   0x0800  ///Should we be seen in a window?
00079     };
00080     
00081     ///The states a control can take
00082     enum states{
00083         unknown =   0x0000,
00084         active  =   0x0001, ///aka Focused
00085         ovrwrt  =   0x0002, ///if editable==true, insert or overwrite?
00086         checked=    0x0004, ///If a selectable control, are we checked?
00087         visible =   0x0008  ///dito
00088     };
00089 
00090     /**
00091         Control Constructor
00092         @param parent:
00093             the parent window containing this control
00094         @param id
00095             a user defined const int identifying this control
00096         @param lines:
00097             height of the control
00098         @param cols
00099             width of the control
00100         @param y
00101             line where we are placed, relative to parent's top left
00102         @param x
00103             column where we are placed, relative to parent's top left
00104         @param style
00105             style indications for enabling/disabling control's capabilities
00106     */
00107     Control(Control *parent, int id
00108         ,int lines,int cols,int y, int x,int style=0)
00109         : NCursesPanel(lines,cols,parent->begy()+y,parent->begx()+x)
00110             ,pParent(parent),ctrl_id(id)
00111             ,field_style(style),field_state(unknown)
00112             ,arrow_as_tab(true)
00113     {
00114         if(has_frame()){
00115             box();
00116         }
00117         set_visible();
00118     }
00119     
00120     /**
00121         Control Constructor
00122         @param id
00123             a user defined const int identifying this control
00124         @param lines:
00125             height of the control
00126         @param cols
00127             width of the control
00128         @param y
00129             line where we are placed, absolute coord.
00130         @param x
00131             column where we are placed, absolute coord.
00132         @param style
00133             style indications for enabling/disabling control's capabilities
00134     */
00135     Control(int id
00136         ,int lines,int cols,int y, int x,int style=0)
00137         : NCursesPanel(lines,cols,y,x)
00138             ,pParent(0),ctrl_id(id)
00139             ,field_style(style),field_state(unknown)
00140             ,arrow_as_tab(true)
00141     {
00142         if(has_frame()){
00143             box();
00144         }
00145         set_visible();
00146     }
00147     ///tell me what styles this window has...
00148     styles get_style() const { return styles(field_style); }
00149     
00150     /// set all styles at once...
00151     styles set_styles(styles s);
00152     
00153     /// set/unset a style bit
00154     styles set_style(styles s,bool on=true);
00155     
00156 
00157     ///tell me what status this window is on...
00158     states get_state() const { return states(field_state); }
00159     
00160     /// set all states at once...
00161     states set_states(states s);
00162     
00163     /// set/unset a state bit
00164     states set_state(states s,bool on=true);
00165     
00166     /// if this style has been set...
00167     bool has_frame()const{return ( (field_style & framed)== framed);}
00168     
00169 
00170     /// the user can move this control?...
00171     bool is_moveable() const{ return ( (field_style & moveable)==moveable);}
00172     
00173     /// the user can edit this control's text?
00174     bool is_editable() const{ return ( (field_style & editable)==editable);}
00175     
00176     /// are we visible on the list viewport?
00177     bool is_visible() const{ return ( (field_state & visible)==visible);}
00178     
00179     /// a control always moves inside its parent boundaries,
00180     /// so make this function use only relative values...
00181     int mvwin(int y, int x);
00182     
00183     
00184     /// Usualy, a control in a dialog has some kind of text on it...
00185     virtual void set_text(const string &txt)=0;
00186     virtual string get_text()const=0 ;
00187     
00188     /// The control identifier
00189     int get_ctrl_id() const {return ctrl_id;};
00190     void set_ctrl_id(int id){ctrl_id=id;};
00191 
00192     ///Draw as active (i.e.,with bold frame)
00193     virtual void activate();
00194     
00195     ///Draw as inactive (i.e.,with normal frame)
00196     virtual void deactivate();
00197     
00198     ///show or hide
00199     void set_visible(bool new_state=true){set_state(visible,new_state);}
00200     
00201     ///Ignore /Stop ignoring us when user press tab
00202     void enable(bool t_or_f=true){ set_style(tabstop,t_or_f);}
00203 
00204     /// can make this control the active control?
00205     bool is_enabled()const{ return ( (field_style & tabstop)==tabstop);}
00206     
00207     ///Ignore /Stop ignoring us when user press tab
00208     void set_hscroll(bool t_or_f=true){ set_style(hscroll,t_or_f);}
00209 
00210     /// can make this control the active control?
00211     bool is_hscroll_set()const{ return ( (field_style & hscroll)==hscroll);}
00212 
00213     ///Allow multiple selections
00214     void set_multisel(bool t_or_f=true){ set_style(multisel,t_or_f);}
00215 
00216     /// can make this control the active control?
00217     bool is_multisel()const{ return ( (field_style & multisel)==multisel);}
00218 
00219     ///notify parent of changes
00220     void enable_notify(bool t_or_f=true){ set_style(notify,t_or_f);}
00221 
00222     /// should we notify our parent upon firing of action()?
00223     bool notify_enabled() const{ return ( (field_style & notify)==notify);}
00224     
00225     ///Set edit mode to overwrite or insert
00226     void set_overwrite(bool t_or_f=true){ set_state(ovrwrt,t_or_f);}
00227     
00228     /// the user current pos is overwritten or char is inserted?
00229     bool overwrite()const
00230         { return (is_editable() &&( (field_state & ovrwrt)==ovrwrt));}
00231         
00232 
00233     /// if this style has been set...
00234     bool has_hscrollbar()const{return ( (field_style & hscrollbar)== hscrollbar);}
00235     void set_hscrollbar(bool t_or_f=true){ set_style(hscrollbar,t_or_f);}
00236     
00237     bool has_vscrollbar()const{return ( (field_style & vscrollbar)== vscrollbar);}
00238     void set_vscrollbar(bool t_or_f=true){ set_style(vscrollbar,t_or_f);}
00239     
00240     /// Should we write the title of this control?
00241     bool has_show_title()const{return ( (field_style & title)== title);}
00242     void set_show_title(bool t_or_f=true){ set_style(title,t_or_f);}
00243     
00244     /// if set, when user presses key left or right, move to next/previous control
00245     void use_arrow_as_tab(bool t_or_f=true){arrow_as_tab=t_or_f;}
00246     bool arrow_is_tab(){return arrow_as_tab;}
00247     
00248     /// Should this control be shown at all?
00249     /// NOT same as visible/invisible, which is used to post/unpost a control
00250     /// under user actions.
00251     /// i.e.: we have two controls going to the same place, but we will show one
00252     /// and hide the other under some circumstances.
00253     bool is_hidden()const{return ( (field_style & hidden)== hidden);}
00254     void set_hidden(bool t_or_f=true){
00255         if(t_or_f==true){
00256             hide();
00257         }
00258         set_style(hidden,t_or_f);
00259     }
00260     
00261     
00262     ///call panel's show and set our state accordingly
00263     virtual void show(){
00264         if(is_hidden()) return;
00265         if(is_visible()) return;
00266         NCursesPanel::show();
00267         set_visible();
00268         enable();
00269     }
00270     
00271     ///call panel's hide and set our state accordingly
00272     virtual void hide(){
00273         if(!is_visible()) return;
00274         NCursesPanel::hide();
00275         set_visible(false);
00276         enable(false);
00277     }
00278 
00279             
00280     /// Delegation function to get the params from almost anywhere in NDK++
00281     string get_param(const string &section_name
00282                             ,const string &key_name
00283                             ,const string &val);
00284 
00285     /// Delegation function to get the params from almost anywhere in NDK++
00286     long get_param(const string &section_name
00287                             ,const string &key_name
00288                             ,long val);
00289 
00290     /// Delegation function to save the params from almost anywhere in NDK++
00291     string save_param(const string &section_name
00292                             ,const string &key_name
00293                             ,const string &val);
00294 
00295     /// Delegation function to save the params from almost anywhere in NDK++
00296     long save_param(const string &section_name
00297                             ,const string &key_name
00298                             ,long val);
00299     static ofstream &send_to_log(const string &what);
00300   /** No descriptions */
00301     virtual bool clicked_inside(int y, int x) const{
00302         return ( begy() <= y &&
00303                  begx() <= x &&
00304                  (begx() + maxx()) >= x &&
00305                  (begy() + maxy()) >= y
00306                 );
00307     }
00308 
00309 protected:
00310     Control *pParent;
00311     int ctrl_id;
00312     int field_style;
00313     int field_state;
00314     
00315     /// User can choose if using the arrows
00316     /// at left or right edges yields the
00317     /// same effect as pressing TAB/SHIFT-TAB
00318     /// default: TRUE;
00319     bool arrow_as_tab;
00320     
00321     /// get a chance at processing the key,
00322     /// before parent does
00323     virtual int driver(int key);
00324     
00325     ///
00326     /// move_left and move_right:
00327     ///
00328     /// if arrow_is_tab == true, they return
00329     /// false, so the owner can process KEY_LEFT
00330     /// and KEY_RIGHT, and properly move to
00331     /// previous or next control.
00332     virtual int move_left();
00333     virtual int move_right();
00334 
00335 private:
00336     static const BINDING _bindingEntries[];
00337 protected:
00338     static const BINDING_MAP bindingMap;
00339     virtual const BINDING_MAP* get_binding_map() const;
00340     
00341     /// this method starts with pTarget and clibs it way thru the inheritance
00342     /// tree searching for a handler for what corresponding to ctrl_id
00343     static bool process_message(Control *pTarget
00344                                     , int what, int ctrl_id, void* pExtra);
00345                                     
00346     ///Helper to find a binding for what corresponding to ctrl_id
00347     static const BINDING* get_binding(const BINDING* pEntry
00348                                             ,int what, int ctrl_id);
00349 };
00350 
00351 #include "ndk_bindings.h"
00352 
00353 /************************************************************************
00354 *   \class Label                                                            *
00355 *   A static label.                                                     *
00356 ************************************************************************/
00357 class Label : public Control
00358 {
00359 public:
00360 
00361     /**
00362         Label Constructor
00363         See parameters for class Control
00364     */
00365 
00366     Label( Control *parent,int id,const string &title
00367                     ,int lines,int cols,int y, int x
00368                     ,int style=tabstop|notify);
00369 
00370     /**
00371         Label Constructor
00372         See parameters for class Control
00373     */
00374     Label( int id,const string &title
00375                     ,int lines,int cols,int y, int x
00376                     ,int style=tabstop|notify);
00377     ~Label() {}
00378 
00379 
00380     void set_text(const string &txt);
00381     string get_text() const {return text;}
00382     
00383     void activate();
00384     void deactivate();
00385 
00386     ///Useful for scrolling labels in lists
00387     chtype operator[](int pos)const
00388     {
00389         chtype result;
00390         
00391         if(pos < 0 || pos >= text.size())
00392             result = getbkgd();
00393         else
00394             result = text[pos];
00395         
00396         return result;
00397     }
00398 
00399     
00400     ///Maximum size of contained text. (default=viewport's size)
00401     int max_len() const {return max_length;}
00402     
00403     int set_max_len(int len) {max_length = len;}
00404     
00405 protected:
00406     
00407     string text;
00408     
00409     ///Hack to manage framed/unframed windows
00410     int pos_x, pos_y;
00411     
00412     ///The maximum allowed text to enter
00413     int max_length;
00414 
00415         
00416     ///Edition viewport.
00417     ///When not framed, viewport = window;
00418     NCursesWindow *viewport;
00419     
00420     ///cursor situation
00421     int cur_x, cur_y;
00422     
00423     /// first visible char
00424     int x_start;
00425 
00426     ///Update the text we present on the viewport
00427     virtual void refresh_text(){
00428         viewport->deleteln();
00429         viewport->addstr(cur_y,0, text.c_str(), max_len());
00430     }
00431     
00432     ///Calls to the panel underneath
00433     virtual void refresh_viewport(){
00434         viewport->move(cur_y,cur_x);
00435         viewport->cursyncup();
00436         viewport->refresh();
00437     }
00438 };
00439 
00440 
00441 /************************************************************************
00442 *   \class Edit                                                         *
00443 *   A single line, editable control.                                    *
00444 ************************************************************************/
00445 class Edit : public Label
00446 {
00447 public:
00448 
00449     /**
00450         Edit Constructor
00451         See parameters for class Control
00452     */
00453     Edit( Control *parent,int id,const string &text
00454                     ,int lines,int cols,int y, int x
00455                     ,int style=framed|editable|tabstop|notify);
00456 
00457     ~Edit();
00458     
00459 protected:
00460     
00461     ///This is the specialized driver for edition
00462     virtual int edit(int key);
00463     
00464     
00465     virtual int add_or_insert_char(int key);
00466     
00467     ///In overwrite mode
00468     virtual void add_char(int key);
00469     
00470     ///In insert mode
00471     virtual void insert_char(int key);
00472     
00473     virtual void refresh_text(){
00474         viewport->deleteln();
00475         viewport->addstr(   cur_y,0
00476                             ,text.substr(x_start,viewport->width()).c_str()
00477                             ,viewport->width());
00478     
00479     }
00480     
00481     int move_right();
00482     int move_left();
00483     
00484     int driver(int key);
00485 };
00486 
00487 
00488 /************************************************************************
00489 *   \class EditNumber                                                   *
00490 *   An Edit control, constrained to digits.                     *
00491 ************************************************************************/
00492 class EditNumber : public Edit
00493 {
00494 public:
00495 
00496     /**
00497         EditNumber Constructor
00498         See parameters for class Control
00499     */
00500     EditNumber( Control *parent,int id,const string &text
00501                     ,int lines,int cols,int y, int x
00502                     ,int style=framed|editable|tabstop|notify)
00503         :Edit(parent,id,text,lines,cols,y,x,style)
00504         {}
00505 
00506     int edit(int key);
00507     
00508 };
00509 
00510 
00511 /************************************************************************
00512 *   \class EditDate                                                     *
00513 *   Actually, a primitive masked editor.                                *
00514 *   it expects a string of the form dd/mm/yyyy or mm/dd/yyyy            *
00515 *   No validation yet, but it will skip the slashes or dashes           *
00516 *   (Validation implies creating dependencies with some datetime class) *
00517 ************************************************************************/
00518 class EditDate:public EditNumber
00519 {
00520 public:
00521     
00522     /**
00523         EditDate Constructor
00524         See parameters for class Control
00525     */
00526     EditDate( Control *parent
00527                     ,int id, const string &msk
00528                     ,int y, int x
00529                     ,int style=editable|tabstop|notify|framed);
00530             
00531     EditDate( Control *parent,int id,const string &msk
00532                     ,int lines,int cols,int y, int x
00533                     ,int style=editable|tabstop|notify|framed);
00534 
00535 protected:
00536     string mask;
00537     int edit(int key);
00538     
00539 };
00540 
00541 
00542 /************************************************************************
00543 *   \class EditDouble                                                   *
00544 *   Actually, a primitive masked editor.                                *
00545 *   it expects a string of the form -99999,000 or +09999,99,etc         *
00546 *   No validation yet, but it will skip the commas and signs.           *
00547 *   (Validation implies creating dependencies with some datetime class) *
00548 ************************************************************************/
00549 class EditDouble:public EditNumber
00550 {
00551 public:
00552     
00553     /**
00554         EditDouble Constructor
00555         See parameters for class Control
00556     */
00557     EditDouble( Control *parent,int id,const string &text
00558                     ,int lines,int cols,int y, int x
00559                     ,int style=framed|editable|tabstop|notify)
00560         :EditNumber(parent,id,text,lines,cols,y,x,style)
00561         {}
00562 
00563     int edit(int key);
00564     
00565 };
00566 
00567 
00568 /************************************************************************
00569 *   \class Button                                                       *
00570 *   The base class for radio buttons, push buttons and check boxes      *
00571 ************************************************************************/
00572 class Button : public Label
00573 {
00574 public:
00575     /**
00576         Button Constructor
00577         See parameters for class Control
00578     */
00579     Button( Control *parent,int id, const string &title
00580                     ,int lines,int cols,int y, int x
00581                     ,int style=tabstop|notify);
00582 
00583     void activate();
00584     void deactivate();
00585 
00586     ///action fired when user presses Enter
00587     virtual int action()=0;
00588     
00589     ///Set this button as the default choice
00590     void set_default(bool t_or_f=true) {default_choice=t_or_f;}
00591     bool is_default()const {return default_choice;}
00592     
00593 protected:
00594     int driver(int key);
00595     bool default_choice;
00596 };
00597 
00598 
00599 /************************************************************************
00600 *   \class PushButton                                                   *
00601 ************************************************************************/
00602 class PushButton : public Button
00603 {
00604 public:
00605     /**
00606         PushButton Constructor
00607         See parameters for class Control
00608     */
00609     PushButton( Control *parent,int id, const string &title
00610                     ,int lines,int cols,int y, int x
00611                     ,int style=tabstop|notify|framed);
00612 
00613     /**
00614         PushButton Constructor
00615         See parameters for class Control
00616     */
00617     PushButton( Control *parent,int id, const string &title
00618                     ,int y, int x);
00619                     
00620     void set_text(const string &txt);
00621 
00622     int action(){
00623         process_message(pParent,0,get_ctrl_id(),0);
00624         return TRUE;
00625     }
00626 };
00627 
00628 
00629 /************************************************************************
00630 *   \class PropDlgPushButton                                                *
00631 *   A specialized push button, able to take us back to the current      *
00632 *   page on a tabbed dialog box                                         *
00633 ************************************************************************/
00634 class PropDlgPushButton : public PushButton
00635 {
00636 public:
00637     /**
00638         PropDlgPushButton Constructor
00639         See parameters for class Control
00640     */
00641     PropDlgPushButton( Control *parent,int id, const string &title
00642                     ,int lines,int cols,int y, int x
00643                     ,int style=tabstop|notify|framed)
00644                     :PushButton( parent,id,title,lines,cols,y,x,style)
00645         {}
00646 
00647     /**
00648         PropDlgPushButton Constructor
00649         See parameters for class Control
00650     */
00651     PropDlgPushButton( Control *parent,int id, const string &title
00652                     ,int y, int x)
00653                     :PushButton( parent,id,title,y,x)
00654         {}
00655         
00656 protected:
00657     int driver(int key){
00658         int result= FALSE;
00659         switch(key) {
00660             case KEY_UP:
00661                 process_message(pParent,0,(int)RETURN_TO_PAGE,0);
00662                 return TRUE;
00663             default:    result = Button::driver(key); break;
00664         }
00665         return result;
00666     }
00667 };
00668 
00669 
00670 /************************************************************************
00671 *   \class ListItemData                                                 *
00672 *   A helper object holding state and member info for a ListItem        *
00673 ************************************************************************/
00674 class ListItem; //forward reference
00675 class ListItemData
00676 {
00677 public:
00678 
00679     /**
00680         ListItemData Constructor
00681         @param txt
00682             the label of this list item
00683         @param id
00684             a user defined int identifying this item
00685         @param style
00686             style indications for enabling/disabling control's capabilities
00687         @param state
00688             what is the state of this item
00689         @param data
00690             user defined data. we save this and give it back to
00691             the user untouched and unevaluated
00692     */
00693     ListItemData(   const string &txt,int id=-1
00694                         ,int style=Control::tabstop|Control::notify
00695                         ,int state=0,void *data=0)
00696         :text(txt),ctrl_id(id),field_style(style)
00697             ,field_state(state),user_data(data)
00698         {
00699         }
00700 
00701 
00702     ListItemData &operator=(const ListItem &lha);
00703     ListItemData &operator=(const ListItemData &lha);
00704     
00705     void set_text(const string &txt){text = txt;}
00706     string get_text()const  {return text;}
00707 
00708 
00709     void set_ctrl_id(int id)        {ctrl_id = id;}
00710     int get_ctrl_id()   const   {return ctrl_id;}
00711 
00712     void set_styles(int style)  {field_style = style;}
00713     int get_style() const       {return field_style;}
00714 
00715     void set_states(int state)  {field_state = state;}
00716     int get_state() const       {return field_state;}
00717 
00718     /// set/unset a state bit
00719     int set_state(int s,bool on=true);
00720 
00721     void set_user_data(void *data)  {user_data = data;}
00722     void *get_user_data() const     {return user_data;}
00723 
00724     ///set/unset check mark
00725     void set_check(bool new_state=true){
00726         bool prev_state=is_checked();
00727         set_state((int)Control::checked,new_state);
00728     };
00729     
00730     /// is this item selected?
00731     bool is_checked() const
00732     { return ( (field_state & Control::checked)
00733                     == Control::checked);}
00734 
00735     void set_default(bool t_or_f=true) {default_choice=t_or_f;}
00736     bool is_default()const {return default_choice;}
00737     virtual int action(){return false;} 
00738     virtual int driver(int key){return false;}
00739 protected:
00740     friend class ListBox;
00741     string text;
00742     int ctrl_id;
00743     int field_style;
00744     int field_state;
00745     bool default_choice;
00746     void *user_data;
00747 };
00748 
00749 
00750 /************************************************************************
00751 *   \class ListItem                                                     *
00752 *   The base class for items contained                                  *
00753 *   on ListBox and derivatives                                          *
00754 ************************************************************************/
00755 class ListItem : public Button
00756 {
00757     friend class ListBox;
00758 public:
00759 
00760     /**
00761         ListItem Constructor
00762         See parameters for class Control
00763     */
00764     ListItem( Control *parent,int id,const string &title
00765                     ,int lines,int cols,int y, int x,int style=tabstop|notify);
00766 
00767     void set_text(const string &txt);
00768 
00769     ///set/unset check mark
00770     void set_check(bool new_state=true){
00771         bool prev_state=is_checked();
00772         set_state(checked,new_state);
00773         show_state(true);
00774         if(prev_state!=new_state && notify_enabled())
00775             process_message(pParent,LI_SEL_CHANGE,get_ctrl_id(),0);
00776     };
00777     
00778     /// is this item selected?
00779     bool is_checked() const { return ( (field_state & checked)==checked);}
00780     
00781     void set_user_data(void *data){user_data = data;}
00782     void *get_user_data() const {return user_data;}
00783     
00784     ListItem &operator=(const ListItemData &lha);
00785     
00786 protected:
00787     void *user_data;
00788 
00789     int driver(int key);
00790 
00791     ///specialized on children
00792     virtual void show_state(bool ref=false)
00793     {
00794         if(!text.empty()){
00795             if(is_checked()) addch(0,0, '*');
00796             else addch(0,0, ' ');
00797         }
00798         if(ref)refresh();
00799     }
00800     
00801     void refresh_text(){
00802         viewport->deleteln();
00803         show_state();
00804         addstr(pos_y,state_size(),text.c_str(),width()-state_size());
00805     }
00806     
00807     ///specialized on children
00808     virtual int state_size() const {return 1;};
00809 
00810     ///Hidden from public use
00811     int action() {return FALSE;}
00812 
00813 };
00814 
00815 
00816 
00817 
00818 /************************************************************************
00819 *   \class RadioButton                                                  *
00820 ************************************************************************/
00821 class RadioButton : public ListItem
00822 {
00823 public:
00824 
00825     /**
00826         RadioButton Constructor
00827         See parameters for class Control
00828     */
00829     RadioButton( Control *parent,int id, const string &title
00830                     ,int lines,int cols,int y, int x
00831                     ,int style=tabstop|notify);
00832 
00833     /**
00834         RadioButton Constructor
00835         See parameters for class Control
00836     */
00837     RadioButton( Control *parent,int id, const string &title
00838                     ,int y, int x);
00839 
00840 protected:
00841 
00842     void show_state(bool ref=false){
00843         if(!text.empty()){
00844             if(is_checked()) addstr(0,0, "(0)");
00845             else addstr(0,0, "( )");
00846         }
00847         if(ref)refresh();
00848     }
00849     
00850     int state_size() const {return 3;};
00851 };
00852 
00853 
00854 /************************************************************************
00855 *   \class CheckButton                                                  *
00856 ************************************************************************/
00857 class CheckButton : public ListItem
00858 {
00859 public:
00860     /**
00861         CheckButton Constructor
00862         See parameters for class Control
00863     */
00864     CheckButton( Control *parent,int id, const string &title
00865                     ,int lines,int cols,int y, int x
00866                     ,int style=tabstop|notify);
00867 
00868     /**
00869         CheckButton Constructor
00870         See parameters for class Control
00871     */
00872     CheckButton( Control *parent,int id, const string &title
00873                     ,int y, int x);
00874 
00875 protected:
00876 
00877     void show_state(bool ref=false){
00878         if(!text.empty()){
00879             if(is_checked()) addstr(0,0, "[x]");
00880             else addstr(0,0, "[ ]");
00881         }
00882         if(ref)refresh();
00883     }
00884     
00885     int state_size() const {return 3;};
00886 };
00887 
00888 
00889 /************************************************************************
00890 *   \class MenuItemData                                                                                          *
00891 ************************************************************************/
00892 class MenuBar;
00893 class MenuItemData : public ListItemData
00894 {
00895 public:
00896     /**
00897         MenuItemData Constructor
00898         See parameters for class ListItemData
00899     */
00900     MenuItemData(const string &txt,int id=-1
00901                         ,int style=Control::tabstop|Control::notify
00902                         ,int state=0,void *data=0)
00903         :ListItemData(txt,id,style,state,data),pMenuItem(0)
00904         {
00905         }
00906 
00907 protected:
00908     friend class MenuItem;
00909     friend class MenuBar;
00910     int action(){return false;}
00911     MenuItem *pMenuItem;
00912 };
00913 
00914 
00915 /************************************************************************
00916 *   \class MenuItem                                                 *
00917 ************************************************************************/
00918 class MenuItem : public ListItem
00919 {
00920 public:
00921     /**
00922         MenuItem Constructor
00923         See parameters for class Control
00924     */
00925     MenuItem( Control *parent,int id, const string &title
00926                     ,int lines,int cols,int y, int x
00927                     ,int style=tabstop|notify);
00928 
00929     /**
00930         MenuItem Constructor
00931         See parameters for class Control
00932     */
00933     MenuItem( Control *parent,int id, const string &title
00934                     ,int y, int x);
00935 
00936     int driver(int key);
00937     MenuItemData *pData;
00938 };
00939 
00940 
00941 /************************************************************************
00942 *   \class ClosingMarkItem                                              *
00943 *   The end marker for an items list.                                   *
00944 ************************************************************************/
00945 //class ClosingMarkItem : public MenuItem
00946 //{
00947 //protected:
00948 //public:
00949 //  ClosingMarkItem() : MenuItem() { }
00950 //  ~ClosingMarkItem(){
00951 //  }
00952 //};
00953 
00954 
00955 /************************************************************************
00956 *   \class NonImplementedItem                                           *
00957 *   A non-functional item (you can draft your menu with these).         *
00958 ************************************************************************/
00959 class NonImplementedItem : public MenuItemData {
00960 public:
00961     NonImplementedItem(const string &text) : MenuItemData(text) {
00962         field_style &=!Control::tabstop;
00963     }
00964     ~NonImplementedItem(){}
00965 
00966 };
00967 
00968 
00969 /************************************************************************
00970 *   \class ExitCmd                                                      *
00971 *   This is the one to take us off the menu.                            *
00972 ************************************************************************/
00973 class ExitCmd : public MenuItemData
00974 {
00975 public:
00976   ExitCmd(const string &text="Exit") : MenuItemData(text) { }
00977   ~ExitCmd(){}
00978   int action() { return EXIT_APP; }
00979 };
00980 
00981 
00982 /************************************************************************
00983 *   \class ListBox                                                      *
00984 *   Base class for managing lists of things                             *
00985 ************************************************************************/
00986 typedef vector<ListItem *> VisibleItems;
00987 typedef vector<ListItemData *> ListItems;
00988 typedef vector<int> IndexList;
00989 
00990 class ListBox : public Control
00991 {
00992     friend class ListItem;
00993 public:
00994     /**
00995         ListBox Constructor
00996         See parameters for class Control
00997     */
00998     ListBox( Control *parent,int id,const string &title
00999                     ,int lines,int cols,int y, int x
01000                     ,int style=tabstop|framed|notify);
01001     
01002     ListBox(int id,const string &title
01003         ,int lines,int cols,int y, int x
01004                     ,int style=tabstop|framed|notify);
01005 
01006     ~ListBox();
01007     
01008     ///You can add an item just sending in a string
01009     int add_item(const string &new_item, int pos=-1,bool is_default= false,bool make_visible=true);
01010     
01011     /// Here you are sending a full item data ptr.
01012     /// The list will own it and dispose it at destruction time
01013     int add_item(ListItemData *new_item,int pos=-1,bool make_visible=true);
01014     
01015     /// Drop an item from the list
01016     int remove_item(int pos=-1);
01017         
01018     ///Here we will manage the virtualized list
01019     int refresh();
01020 
01021 
01022         ///call panel's show and set our state accordingly
01023     void show(){
01024 //      if(is_visible()) return;
01025         for( int idx=0; idx <items.size(); idx++){
01026                 items[idx]->show();
01027         }
01028         Control::show();
01029     }
01030     
01031     ///call panel's hide and set our state accordingly
01032     void hide(){
01033 //      if(!is_visible()) return;
01034         for( int idx=0; idx <items.size(); idx++){
01035                 items[idx]->hide();
01036         }
01037         Control::hide();
01038     }
01039 
01040     void activate();
01041     void deactivate();
01042     
01043     string get_text() const {return _title;}
01044     void set_text(const string &v){
01045         _title = v;
01046         show_text(v,'l');
01047     }
01048     
01049     ///Where are we standing on the list?
01050     virtual int get_cur_pos();
01051     virtual void set_cur_pos(int pos=-1);
01052 
01053     ///The current checked item
01054     virtual int get_cur_sel();
01055     void set_cur_sel(int pos);
01056     
01057     ///On a multisel list, the list of checked items
01058     virtual void get_sel_items(IndexList &list);
01059     virtual void set_sel_items(const IndexList &list, bool t_or_f=true);
01060     
01061     ///Get tht text for the pos'th item
01062     virtual string get_item_text(int pos=-1);
01063     virtual void set_item_text(int pos,const string &txt);
01064     
01065     ///Select an item based on the given pattern, starting at pos
01066     virtual int sel_string(int pos,const string &pattern);
01067         
01068     ///Get the user data hooked on the pos'th item
01069     virtual void *get_item_data(int pos=-1);
01070     virtual void set_item_data(int pos,void *data);
01071 
01072     ///Get full info for the pos'th item
01073     virtual ListItemData *get_item(int pos=-1);
01074     virtual void set_item(int pos,ListItemData *item);
01075 
01076     ///How long is the list?
01077     virtual int get_count(){return data.size();};
01078 
01079     ///Remove all the elements
01080     void clear();
01081     int largest_name_len()const;
01082 
01083 protected:
01084     string _title;
01085     int pos_x, pos_y;
01086 
01087     VisibleItems items;
01088     ListItems data;
01089     
01090     int curr_item;
01091     int first_visible;
01092     int last_visible;
01093     int cur_sel;
01094     int driver(int key);
01095 
01096     /// Put the label text at the left (0)
01097     /// in the specified row.
01098     virtual void lefttext(int row,const char* label);
01099 
01100     /// Put the label text to the right (ending at maxx())
01101     /// in the specified row.
01102     virtual void righttext(int row,const char* label);
01103 
01104     void show_text(const string &t,char where);
01105 
01106     virtual void adjust_visible_items();
01107 
01108     virtual int move_up();  
01109     virtual int move_down();
01110     
01111     virtual void activate_item(int item_idx);
01112     virtual void deactivate_item(int item_idx);
01113 
01114     ///Copy to the buffer the full info of item_idx'th item
01115     void update_data(int item_idx);
01116     
01117     ///Copy to the visible item the full info of item_idx'th item
01118     void update_item(int item_idx);
01119     
01120     ///Refresh the visible elements
01121     void refresh_items();
01122     
01123     ///Clear (erase) the visible items
01124     void clear_items();
01125     
01126     ///Clear (erase) the full list of items
01127     void delete_data();
01128     
01129     /// If there are no elements to show, put the 'Empty' tag
01130     void show_empty();
01131     
01132     ///Draw a vertical scroll bar (just visual sugar, we don't have mouse yet)
01133     void draw_scrollbar();
01134     
01135     ///Virtualize the requested item index
01136     ListItem *&visible_item(int requested)
01137                                     {return items[requested-first_visible];}
01138 
01139     ///Do we allow multiple selection?
01140     void check_multisel(int pos, bool t_or_f);
01141     
01142     void on_sel_change(int);
01143     
01144     ///A macro for enabling message processing (see ndk_bindings.h)
01145     DECLARE_BINDINGS();
01146 };
01147 
01148 
01149 /************************************************************************
01150 *   \class SelectionBox                                                 *
01151 *   A derivation of ListBox, is a plain list selection box without      *
01152 *   radio or check buttons                                              *                                                                   *
01153 ************************************************************************/
01154 class SelectionBox : public ListBox
01155 {
01156 public:
01157     /**
01158         SelectionBox Constructor
01159         See parameters for class Control
01160     */
01161     SelectionBox( Control *parent,int id,const string &title
01162                     ,int lines,int cols,int y, int x
01163                     ,int style=tabstop|framed|notify)
01164         :ListBox( parent,id,title
01165                     ,lines,cols,y, x
01166                     ,style)
01167         {
01168             initialize_items();
01169         }
01170 
01171     /**
01172         SelectionBox Constructor
01173         See parameters for class Control
01174     */
01175     SelectionBox( int id,const string &title
01176                     ,int lines,int cols,int y, int x
01177                     ,int style=tabstop|framed|notify)
01178         :ListBox( id,title
01179                     ,lines,cols,y, x
01180                     ,style)
01181         {
01182             initialize_items();
01183         }
01184 protected:
01185     ///Load the visible components of the list
01186     void initialize_items();
01187 };
01188 
01189 
01190 /************************************************************************
01191 *   \class CheckListBox                                                 *
01192 *   A ListBox with check buttons on it (usually multiselect-enabled     *
01193 ************************************************************************/
01194 class CheckListBox : public ListBox
01195 {
01196 public:
01197     /**
01198         CheckListBox Constructor
01199         See parameters for class Control
01200     */
01201     CheckListBox( Control *parent,int id,const string &title
01202                     ,int lines,int cols,int y, int x
01203                     ,int style=tabstop|framed|notify)
01204         :ListBox( parent,id,title
01205                     ,lines,cols,y, x
01206                     ,style)
01207         {
01208             initialize_items();
01209         }
01210                     
01211 protected:
01212     ///Load the visible components of the list
01213     void initialize_items();
01214 };
01215 
01216 
01217 /************************************************************************
01218 *   \class ChoiceBox                                                        *
01219 *   A ListBox with radio buttons (usually single selectable)        *
01220 ************************************************************************/
01221 class ChoiceBox : public ListBox
01222 {
01223 public:
01224     /**
01225         CheckListBox Constructor
01226         See parameters for class Control
01227     */
01228     ChoiceBox( Control *parent,int id,const string &title
01229                     ,int lines,int cols,int y, int x
01230                     ,int style=tabstop|framed|notify)
01231         :ListBox( parent,id,title
01232                     ,lines,cols,y, x
01233                     ,style)
01234         {
01235             initialize_items();
01236         }
01237                     
01238 protected:
01239     ///Load the visible components of the list
01240     void initialize_items();
01241 };
01242 
01243 
01244 /************************************************************************
01245 *   \class MenuBar                                                  *
01246 *   A menu bar is a menu containing popup and regular items             *
01247 *   by default, it has centered top and bottom labels and               *
01248 *   wide orientation                                                    *
01249 ************************************************************************/
01250 class MenuBar : public ListBox
01251 {
01252 public:
01253     /**
01254         MenuBar Constructor
01255         @param orient (default: h)
01256             this menu bar will deploy
01257             h (horizontally) or v (vertically)
01258 
01259         other params: See parameters for class Control
01260     */
01261     MenuBar( int id,const string &title
01262                     ,int lines,int cols,int y, int x
01263                     ,char orient='h'
01264                     ,int style=hidden|tabstop|notify)
01265         :ListBox(id,title
01266                     ,lines,cols,y, x
01267                     ,style),orientation(orient),b_own_items(true),is_main_menu(false)
01268         {
01269         }
01270 
01271     ~MenuBar(){
01272         if(!b_own_items){
01273             data.clear();
01274         }
01275     }   
01276 
01277     ///we are wide-oriented or tall-oriented?
01278     char get_orientation()const{return orientation;}
01279     int execute();
01280     
01281     /// specialized add_item: a MenuBar, as oposed to a ListBox
01282     /// adds the visible item at the same time as the data item
01283     /// (implicit to this is that you should not add more data items
01284     /// than the visible ones.
01285     /// This limitation is which allows us to deploy the items each one
01286     /// at its own position. (By now, anyway.  Later we may add the ability
01287     /// to scroll items, but it's unlikely we will ever want to...)
01288     int add_item(MenuItemData *new_item){
01289         string txt(new_item->get_text());
01290         new_item->pMenuItem = new MenuItem(this,-1,txt,1,txt.size()+1,get_next_item_y(),get_next_item_x());
01291         items.push_back(new_item->pMenuItem);
01292         curr_item++;
01293         new_item->pMenuItem->pData =new_item;
01294         new_item->set_ctrl_id(data.size());
01295         return ListBox::add_item(new_item,-1,false);
01296     };
01297 
01298     /// If we get only a text, then the assumed intention
01299     /// is to place a placeholder (i.e. a non implemented yet label
01300     int add_item(const string & text){
01301         return add_item(new NonImplementedItem(text));};
01302     void items_owner(bool t_or_f=true){b_own_items=t_or_f;};
01303 
01304     /// This one si for processing of the ESC key.
01305     /// On the main menu, you MUST treat ESC as EXIT_APP, don't you...?
01306     /// This flag lets the driver know what behavior is intended
01307     bool is_main_menu;
01308 protected:
01309     bool b_own_items; ///Should we delete the added items?
01310     char orientation;
01311 
01312     string titlePos;
01313 
01314     int move_up(){
01315         if(orientation=='h')
01316             return move_left();
01317         ListBox::move_up();
01318         return false;
01319     };  
01320     int move_down(){
01321         if(orientation=='h')
01322             return execute_current_item(KEY_ENTER);
01323         ListBox::move_down();
01324         return false;
01325     };  
01326     int move_left(){
01327         if(orientation=='v')
01328             return move_up();
01329         ListBox::move_up();
01330         return false;
01331     };  
01332     int move_right(){
01333         if(orientation=='v')
01334             return move_down();
01335         ListBox::move_down();
01336         return false;
01337     };  
01338 
01339     int driver(int key);
01340     int execute_current_item(int key);
01341 
01342     /// mouse support
01343     void find_clicked();
01344 
01345     /// Calculate the position of the next item to be inserted
01346     int get_next_item_y();
01347     int get_next_item_x();
01348 };
01349 
01350 
01351 /************************************************************************
01352 *   \class FramedMenuBar                                                *
01353 *   Ok,don't need to explain what is this, right...?                    *
01354 ************************************************************************/
01355 class FramedMenuBar : public MenuBar
01356 {
01357 public:
01358 
01359     /**
01360         FramedMenuBar Constructor
01361     */
01362     FramedMenuBar(int id,const string &title
01363                     ,int lines,int cols,int y, int x
01364                     ,char orient='h'
01365                     ,int style=tabstop|framed|notify)
01366         :  MenuBar (id,title,lines+2,cols,y,x,orient,style)
01367     {
01368     }
01369 };
01370 
01371 
01372 /************************************************************************
01373 *   \class SubMenu                                                  *
01374 *   A Menu that delpoys itself relative to a popup menu item.           *
01375 ************************************************************************/
01376 class SubMenu : public MenuBar
01377 {
01378 public:
01379     /**
01380         SubMenu Constructor
01381     */
01382     SubMenu(int id,const string &title
01383                     ,int lines,int cols,int y, int x
01384                     ,char orient='h'
01385                     ,int style=tabstop|framed|notify)
01386         :  MenuBar (id,title,lines+2,cols+2+1,y,x,orient,style)
01387     {
01388     }
01389     ~SubMenu() {
01390     }
01391 
01392     int move_up(){
01393         if(orientation=='h')
01394             return true;
01395         return MenuBar::move_up();
01396     };  
01397     int move_down(){
01398         if(orientation=='h')
01399             return true;
01400         return MenuBar::move_down();
01401     };  
01402     int move_left(){
01403         if(orientation=='v')
01404             return true;
01405         return MenuBar::move_left();
01406     };  
01407     int move_right(){
01408         if(orientation=='v')
01409             return true;
01410         return MenuBar::move_right();
01411     };  
01412 };
01413 
01414 
01415 /************************************************************************
01416 *   \class PopUpMenu                                                    *
01417 *   A popup menu item which displays a submenu.                         *
01418 *   the popup menu manages the liftime of the items.                    *
01419 ************************************************************************/
01420 class PopUpMenu : public MenuItemData
01421 {
01422 public:
01423     PopUpMenu(const string &text) : MenuItemData(text),S(0),cur_sel(-1){    }
01424     ~PopUpMenu();
01425     
01426     int action();
01427     
01428     int largest_name_len()const;
01429 
01430 protected:
01431     /// So we can know the right width for the submenu
01432     string sub_menu_label;
01433     ListItems items;
01434     SubMenu *S;
01435     int cur_sel;
01436 };
01437 
01438 
01439 /************************************************************************
01440 *   \class DialogBox                                                        *
01441 *   (aka form window)
01442 ************************************************************************/
01443 typedef vector <Control *> ListOfChildren;
01444 
01445 class DialogBox: public Control
01446 {
01447 public:
01448     enum dlg_styles{
01449         info        = 0x0100,
01450         warning     = 0x0200,
01451         error       = 0x0400,
01452         okCancel    = 0x0001,
01453         yesNo       = 0x0002,
01454         yesNoCancel = 0x0004
01455     };
01456 
01457     enum Dlg_Request{
01458         DLG_LOW = PAD_HIGH + 1,
01459         REQ_DLG_REFRESH = DLG_LOW,
01460         REQ_DLG_PROCESSED,
01461         REQ_DLG_NEXT,
01462         REQ_DLG_PREV,
01463         REQ_DLG_UP,
01464         REQ_DLG_DOWN,
01465         REQ_DLG_LEFT,
01466         REQ_DLG_RIGHT,
01467         REQ_DLG_EXIT,
01468         DLG_HIGH = REQ_DLG_EXIT
01469     };
01470 
01471     /**
01472         DialogBox Constructor
01473         @param parent:
01474             the parent of this window
01475         @param id
01476             a user defined const int identifying this window
01477         @param title
01478             The title for this window
01479         @param lines:
01480             height of the window
01481         @param cols
01482             width of the window
01483         @param y
01484             line where we are placed, absolute coord.
01485         @param x
01486             column where we are placed, absolute coord.
01487         @param d_style
01488             type of window (okCancel,yesNoCancel, etc.)
01489         @param c_style
01490             style indications for enabling/disabling control's capabilities
01491     */
01492     DialogBox(Control *parent,int id, const string &title
01493                         ,int lines, int cols,int y=0, int x=0
01494                         ,int d_style=0,int c_style=0);
01495 
01496     /**
01497         DialogBox Constructor
01498         @param id
01499             a user defined const int identifying this window
01500         @param title
01501             The title for this window
01502         @param lines:
01503             height of the window
01504         @param cols
01505             width of the window
01506         @param y
01507             line where we are placed, absolute coord.
01508         @param x
01509             column where we are placed, absolute coord.
01510         @param d_style
01511             type of window (okCancel,yesNoCancel, etc.)
01512         @param c_style
01513             style indications for enabling/disabling control's capabilities
01514     */
01515     DialogBox(int id, const string &title
01516                         ,int lines, int cols,int y=0, int x=0
01517                         ,int d_style=0,int c_style=0);
01518     ~DialogBox();
01519     
01520     ///Add a control at the end of the list of this window
01521     void add_child(Control *new_child){ children.push_back(new_child);  }   
01522     
01523     ///Add a control at the given pos on the list of this window
01524     void add_child(int pos,Control *new_child);
01525     
01526     ///Add a control after the given control on the list of this window
01527     void add_child(Control *after,Control *new_child);
01528     
01529     string get_text() const {return _title;}
01530     void set_text(const string &v){
01531         _title = v;
01532         show_text(v,'c');
01533     }
01534 
01535     ///The modal loop of the dialog box
01536     virtual int do_modal();
01537     
01538     ///Hide this window and the contained controls
01539     void hide();
01540     
01541     ///Show this window and the contained controls
01542     void show();
01543     
01544     ///The standard screen  
01545     static NCursesPanel dlg_stdscr;
01546     
01547 protected:
01548     ///Allow children to touch our stuff
01549     friend Control;
01550     /// The controls we have
01551     ListOfChildren children;
01552     
01553     /// where is te focus now
01554     int curr_child;
01555     
01556     string _title;
01557     
01558     int dlg_style;
01559     
01560     ///Modal loop condition
01561     bool bContinueModal;
01562     
01563     ///So we can ask the user if she want to save
01564     bool changed;
01565     
01566     PushButton *pBtnYes;
01567     PushButton *pBtnNo;
01568     PushButton *pBtnCancel;
01569     PushButton *pBtnOk;
01570 
01571     ///this is the result of the interaction
01572     int user_request;
01573     
01574     /// A simple helper
01575     void show_text(const string &t,char where);
01576 
01577     /// When user press TAB, give me the next child
01578     void next_control();
01579 
01580     void prev_control();
01581     
01582     void find_clicked();
01583 
01584 protected:
01585     DECLARE_BINDINGS();
01586 
01587     ///called at the beggining of the modal loop
01588     virtual void on_dlg_init(){ 
01589         if(has_frame()){    
01590             frame();
01591         }
01592         if(has_show_title()){
01593             show_text(_title,'c');
01594         }
01595     }
01596         
01597     ///called at the end of the modal loop
01598     virtual void on_dlg_term(){ }
01599     
01600     ///called if user presses one of the 'exits' 
01601     virtual bool can_close();
01602     
01603     ///called when the user enters a control
01604     virtual void on_ctrl_init(Control &ctrl){
01605         ctrl.activate();
01606     }
01607     
01608     ///called when the user leaves the control
01609     virtual bool on_ctrl_term(Control &ctrl){
01610         ctrl.deactivate();
01611         return true;
01612     }
01613     
01614     /// Kind of catch-all for derived windows
01615     virtual void on_cmd(int dlg_req) {
01616     }
01617     
01618     ///called on construction of dialog
01619     virtual void create_buttons();
01620     
01621     ///The next four are used by create_buttons
01622     void add_ok();
01623     void add_ok_cancel();
01624     void add_yes_no(); 
01625     void add_yes_no_cancel(); 
01626 
01627     ///activate child at position child_idx
01628     virtual void set_focus_to(int child_idx);
01629 
01630     ///activate p_child
01631     virtual void set_focus_to(Control *p_child);
01632 
01633     int driver (int key);
01634     
01635     ///Vanilla implementation of exits
01636     virtual void on_dlg_ok()    {end_dialog(IDOK);} 
01637     virtual void on_dlg_yes()   {end_dialog(IDYES);}
01638     virtual void on_dlg_no()    {end_dialog(IDNO);}
01639     virtual void on_dlg_cancel(){
01640         if(can_close())
01641             end_dialog(IDCANCEL);
01642     }
01643 
01644     ///Break the modal loop
01645     ///and give the user a chance to cleanup/serialize/whatever
01646     int end_dialog(int request){
01647         user_request = request;
01648         bContinueModal=false;
01649         on_dlg_term();
01650     }
01651 
01652     /// Put the label text at the left (0) 
01653     /// in the specified row.
01654     virtual void lefttext(int row,const char* label);
01655 
01656     /// Put the label text to the right (ending at maxx())
01657     /// in the specified row.
01658     virtual void righttext(int row,const char* label);
01659     
01660     ///Helpers for auto-ordering the default buttons
01661     static int my_w;        ///useable width
01662     static int btn_w;       ///each button width
01663     static int btns;            ///number of buttons
01664     static int used_width;  ///total buttons width          
01665     static int spc;         ///space between buttons
01666     static int X_POS(int pos);
01667 
01668     static string lblOk;
01669     static string lblCancel;
01670     static string lblYes;   
01671     static string lblNo;
01672     static string lblApply;
01673     static string titDataChgd;
01674     static string msgAskToSave;
01675 };
01676 
01677 
01678 /************************************************************************
01679 *   \class MessageBox                                                   *
01680 *   You already know what is this... ;-)                                *
01681 ************************************************************************/
01682 class MessageBox: public DialogBox 
01683 {
01684 public:
01685     MessageBox(const string &title,const string &message,int style=info);
01686 protected:
01687 
01688     ///Prompt the user
01689     string msg;
01690 
01691     ///We redefine here so we get called on construction
01692     void on_dlg_init(); 
01693     void show_message();
01694 };
01695 
01696 
01697 /************************************************************************
01698 *   \class OkCancelBox                                                  *
01699 *   You already know what is this... ;-)                                *
01700 ************************************************************************/
01701 class OkCancelBox: public MessageBox 
01702 {
01703 public:
01704     OkCancelBox(const string &title,const string &message,int style=info)
01705         :MessageBox(title,message,style|okCancel)
01706         {};
01707 };
01708 
01709 
01710 /************************************************************************
01711 *   \class YesNoBox                                                 *
01712 *   You already know what is this... ;-)                                *
01713 ************************************************************************/
01714 class YesNoBox: public MessageBox 
01715 {
01716 public:
01717     YesNoBox(const string &title,const string &message,int style=info)
01718         :MessageBox(title,message,style|yesNo)
01719         {};
01720 };
01721 
01722 
01723 /************************************************************************
01724 *   \class YesNoBox                                                 *
01725 *   You already know what is this... ;-)                                *
01726 ************************************************************************/
01727 class YesNoCancelBox: public MessageBox 
01728 {
01729 public:
01730     YesNoCancelBox(const string &title,const string &message,int style=info)
01731         :MessageBox(title,message,style|yesNoCancel)
01732         {};
01733 };
01734 
01735 
01736 /************************************************************************
01737 *   \class PropertyPage                                                 *
01738 *   A dialog box with it's title in a tab and stacked with others...    *
01739 ************************************************************************/
01740 class PropertyDialog;
01741 class PropertyPage: public DialogBox 
01742 {
01743 public:
01744     /**
01745         DialogBox Constructor
01746         @param parent
01747             the property dialog that owns us
01748         @param id
01749             a user defined const int identifying this window
01750         @param title
01751             The title for this window
01752         @param lines:
01753             height of the window
01754         @param cols
01755             width of the window
01756         @param y
01757             line where we are placed, absolute coord.
01758         @param x
01759             column where we are placed, absolute coord.
01760     */
01761     PropertyPage(PropertyDialog *parent,int id, const string &title
01762                         ,int lines, int cols,int y=0, int x=0)
01763                         :DialogBox((Control *)parent,id,title,lines,cols,y,x,0,framed|notify)
01764                         ,pDialog(parent)
01765                         {
01766                             do_initial_update();
01767                         };
01768     ~PropertyPage(){};
01769     
01770     ///Since we have the dialogs stacked and they are not modal,
01771     ///we need to do this manually
01772     int refresh()
01773     {
01774         for( int idx=0;idx < children.size(); idx++){
01775             if(idx!=curr_child)
01776                 children[idx]->deactivate();
01777         }
01778         if(curr_child>-1 && curr_child < children.size())
01779             children[curr_child]->activate();
01780     }
01781 
01782 
01783     
01784 protected:
01785     friend class Tab;
01786     friend class PropertyDialog;
01787     
01788     ///Non-modal equivalent of do_modal()
01789     int process_key(int key);
01790     
01791     int driver(int key){ return DialogBox::driver(key);}
01792     
01793     ///Non-modal wrapper for calling on_dlg_init from the constructor
01794     void do_initial_update(){
01795         enable_notify(false);
01796         on_dlg_init();
01797         enable_notify();
01798     }
01799     
01800     ///We redefine here so we get called on construction
01801     void on_dlg_init(){
01802     }; 
01803     
01804     void on_cmd(int dlg_req);
01805 
01806     ///Called when some control change
01807     virtual void on_page_change(){
01808         if(notify_enabled())
01809             process_message(pParent,PAGE_MODIFIED,get_ctrl_id(),this);
01810     }
01811     
01812     ///called by parent when user pushes the "Apply" button
01813     virtual void on_apply(){
01814         if(notify_enabled())
01815             process_message(pParent,0,(int)CANCEL_TO_CLOSE,0);
01816     };
01817     
01818     void create_buttons(){
01819         /**Do nothing, otherwise OK shows up...*/   
01820     }
01821     
01822     PropertyDialog *pDialog;
01823 };
01824 
01825 
01826 /************************************************************************
01827 *   \class Tab                                                          *
01828 *   A specialized button used to show the                               *
01829 *   title of the PropertyPage                                           *
01830 ************************************************************************/
01831 class Tab:public Button
01832 {
01833 public:
01834 
01835     /**
01836         Tab Constructor
01837         See parameters for class Control
01838     */
01839     Tab( Control *parent,int id, const string &title
01840                     ,int lines,int cols,int y, int x
01841                     ,int style=tabstop|notify|framed);
01842 
01843     /**
01844         Tab Constructor
01845         See parameters for class Control
01846     */
01847     Tab( Control *parent,int id, const string &title
01848                     ,int y, int x);
01849 
01850     ~Tab();
01851     
01852     int driver(int key);
01853                     
01854     int action(){ return TRUE;}
01855     
01856     void activate();
01857     void deactivate();
01858     
01859     ///call panel's show and set our state accordingly
01860     void show(){
01861 //      send_to_log("show en Tab")<< pPage->get_text()<< endl;
01862         if(!is_visible()) 
01863             Control::show();
01864         pPage->show();
01865     }
01866     
01867     ///call panel's hide and set our state accordingly
01868     void hide(){
01869 //      send_to_log("hide en Tab")<< pPage->get_text()<< endl;
01870         if(is_visible())
01871             Control::hide();
01872         pPage->hide();
01873     }
01874     
01875     ///Get the page associated with this tab
01876     PropertyPage *get_page() { return pPage;}
01877     ///Set the page associated with this tab
01878     void set_page(PropertyPage *page){pPage = page;}
01879 
01880     void set_text(const string &txt);
01881     
01882 protected:
01883     ///The stacked dialog we manage
01884     PropertyPage *pPage;
01885 };
01886 
01887 
01888 /************************************************************************
01889 *   \class PropertyDialog                                               *
01890 *   A container for stacked dialogs                                     *
01891 *   No frames, no title, with three default buttons (Ok,Apply,Cancel)   *
01892 ************************************************************************/
01893 typedef vector <Tab *> ListOfPages;
01894 
01895 class PropertyDialog: public DialogBox 
01896 {
01897 public:
01898     /**
01899         PropertyDialog Constructor
01900         @param id
01901             a user defined const int identifying this window
01902         @param lines:
01903             height of the window
01904         @param cols
01905             width of the window
01906         @param y
01907             line where we are placed, absolute coord.
01908         @param x
01909             column where we are placed, absolute coord.
01910     */
01911     PropertyDialog(int id, const string &title,int lines, int cols,int y=0, int x=0);
01912     ~PropertyDialog();
01913     
01914     ///Insert a new page on this stack
01915     void add_page(PropertyPage *new_page);
01916     
01917     ///Show the selected page
01918     void set_selected_page(int page);
01919     int get_selected_page(){ return curr_page;}
01920     
01921     ///Check if page number is valid
01922     bool valid_page_number(int page){return (page < pages.size() && page > -1);}
01923     
01924     PropertyPage * get_page(int page);
01925     
01926 protected:
01927     PushButton *&pBtnApply;
01928     int curr_page;
01929     ListOfPages pages;
01930     void on_dlg_init();
01931     void reorder_pages();
01932     void create_buttons();
01933     int get_next_tab_pos();
01934     
01935     virtual void on_page_modified(int page){ 
01936         changed = true;
01937         pBtnOk->enable();
01938         pBtnNo->enable();
01939     }
01940     
01941     virtual void on_page_selected(int page){
01942         if(valid_page_number(page))
01943             curr_page = page;
01944     }
01945             
01946     virtual void on_apply(){
01947         if(valid_page_number(curr_page))
01948             pages[curr_page]->get_page()->on_apply();
01949     }
01950     
01951     void on_focus_to_buttons(){ 
01952         if(pBtnOk->is_enabled())set_focus_to(pBtnOk);
01953         else set_focus_to(pBtnCancel);
01954     }
01955     
01956     void on_return_to_page(){   
01957         if(valid_page_number(curr_page))
01958             set_focus_to(pages[curr_page]);
01959     }
01960     
01961     ///Once the user Apply, we can't cancel...
01962     virtual void cancel_to_close();
01963     
01964     DECLARE_BINDINGS();
01965 
01966 };
01967 
01968 
01969 /************************************************************************
01970 *   \class StatusBar                                                    *
01971 *   A status bar at the bottom of the application console               *
01972 ************************************************************************/
01973 class StatusBar : public Label
01974 {
01975 public:
01976 
01977     StatusBar(int lines,int cols,int y, int x,const string &text="Status bar")
01978         : Label(1000,text,lines, cols, y, x, visible)
01979     {
01980     }
01981 };
01982 
01983 
01984 /************************************************************************
01985 *   \class Application                                                  *
01986 *   Derivation of the NCursesApplication class                          *
01987 *   where we added a status bar                                         *
01988 ************************************************************************/
01989 class Application: public NCursesApplication
01990 {
01991 protected:
01992 
01993     Application(bool wantColors = FALSE)
01994         :   NCursesApplication(wantColors),pStatusBar(0)
01995     {
01996     }
01997     
01998     virtual void activateMenuBar()=0;
01999     virtual void activateStatusBar();
02000     string app_title;
02001   
02002 public:
02003 
02004     static Application *get_application(){
02005         Application *pApp = dynamic_cast<Application *>
02006                                         (NCursesApplication::getApplication());
02007         return pApp;
02008     }
02009     
02010     virtual ~Application(){
02011         delete pStatusBar;
02012     };
02013 
02014     StatusBar *getStatusBar() {return pStatusBar;}
02015     string get_title()const {return app_title;}
02016     ///Tell us what is the name of the parameters file  
02017     void set_param_file_name(const string &file_name){param_file_name = file_name;}
02018     
02019     /// Retrive the parameters file name
02020     string get_param_file_name()const {return param_file_name;}
02021     
02022     /// Find a string parameter (a la MS's .ini files)
02023     string get_param(const string &section_name
02024                         ,const string &key_name
02025                         ,const string &val);
02026 
02027     /// Find a numeric parameter (a la MS's .ini files)
02028     long get_param(const string &section_name
02029                         ,const string &key_name
02030                         ,long val);
02031 
02032     /// Save a string parameter (a la MS's .ini files)
02033     string save_param(const string &section_name
02034                         ,const string &key_name
02035                         ,const string &val){};
02036 
02037     /// Save a numeric parameter (a la MS's .ini files)
02038     long save_param(const string &section_name
02039                         ,const string &key_name
02040                         ,long val){};
02041 
02042 protected:
02043 
02044     StatusBar *pStatusBar;
02045     string param_file_name;
02046     
02047     ///Helper to check if a section given in ge/save_param functs. exists
02048     bool section_exists(ifstream &param_file,const string &section_name);
02049     
02050     ///Helper to check if a key given in ge/save_param functs. exists
02051     long find_key(ifstream &param_file,const string &section_name
02052                             ,const string &key_name,string &value);
02053 
02054 };
02055 
02056 
02057 /// Delegation function to get the params from almost anywhere in NDK++
02058 inline long Control::get_param(const string &section_name
02059                                     ,const string &key_name
02060                                     ,long val)
02061 {
02062     return  Application::get_application()->get_param(section_name,key_name,val);
02063 }
02064 
02065 
02066 /// Delegation function to get the params from almost anywhere in NDK++
02067 inline string Control::get_param(const string &section_name
02068                                     ,const string &key_name
02069                                     ,const string &val)
02070 {
02071     return  Application::get_application()->get_param(section_name,key_name,val);
02072 }
02073 
02074 
02075 /// Delegation function to set the params from almost anywhere in NDK++
02076 inline long Control::save_param(const string &section_name
02077                                     ,const string &key_name
02078                                     ,long val)
02079 {
02080     return  Application::get_application()->save_param(section_name,key_name,val);
02081 }
02082 
02083 
02084 /// Delegation function to set the params from almost anywhere in NDK++
02085 inline string Control::save_param(const string &section_name
02086                                     ,const string &key_name
02087                                     ,const string &val)
02088 {
02089     return  Application::get_application()->save_param(section_name,key_name,val);
02090 }
02091 
02092 /************************************************************************
02093 *   template \class Exception                                       *
02094 *   We use it from anywhere in NDK++ to throw using the                 *
02095 *   current context (usually the window containing the offending code)  *
02096 ************************************************************************/
02097 template<class T> class Exception : public NCursesException
02098 {
02099 public:
02100   const T* pElem;
02101 
02102   Exception (const char *msg, int err) : 
02103     NCursesException (msg, err),
02104     pElem (0)
02105     {};
02106 
02107   Exception (const T* elem,
02108              const string &msg,
02109              int err=-1) : 
02110     NCursesException (msg.c_str(), err),
02111     pElem (elem)
02112     {};
02113 
02114   Exception (int err) : 
02115     NCursesException ("NDK++ library exception", err),
02116     pElem (0)
02117     {};
02118 
02119   Exception (const T* elem,
02120              int err) : 
02121     NCursesException ("NDK++ library exception", err),
02122     pElem (elem)
02123     {};
02124 
02125   virtual const char *classname() const {
02126     return typeid(pElem).name();
02127   }
02128 
02129 };
02130 
02131 
02132 
02133 } //namespace NDK_XX
02134 
02135 
02136 
02137 
02138 #endif //!defined(__NDK_NCURSES__)

Generated on Thu Oct 10 16:02:08 2002 by doxygen1.2.17