core/vgui/vgui_grid_tableau.h
Go to the documentation of this file.
00001 // This is core/vgui/vgui_grid_tableau.h
00002 #ifndef vgui_grid_tableau_h_
00003 #define vgui_grid_tableau_h_
00004 //:
00005 // \file
00006 // \author K.Y.McGaul
00007 // \brief  A tableau which renders its child tableaux as a rectangular grid.
00008 //
00009 //  Contains classes:  vgui_grid_tableau   vgui_grid_tableau_data
00010 //
00011 // \verbatim
00012 //  Modifications
00013 //   K.Y.McGaul 20-JAN-2000 Initial version.
00014 //   K.Y.McGaul 11-FEB-2000 Added a clear_tableau to the empty grid positions.
00015 //   K.Y.McGaul 21-FEB-2002 Added comments and documentation.
00016 // \endverbatim
00017 
00018 #include <vcl_vector.h>
00019 #include <vbl/vbl_array_2d.h>
00020 #include "vgui_grid_tableau_sptr.h"
00021 #include <vgui/vgui_poly_tableau.h>
00022 #include <vgui/vgui_event_condition.h>
00023 
00024 //: Data required by each rectangle in the grid of vgui_grid_tableau.
00025 struct vgui_grid_tableau_data
00026 {
00027   //: Handle returned by poly_tableau.
00028   int handle;
00029   //: Position of our tableau in the array of tableaux (`tabs')
00030   int tab_pos;
00031   //: True if this is a default tableau (not set by the user)
00032   bool is_default;
00033   //: Time last left clicked on (-1 if not selected)
00034   int time_selected;
00035 };
00036 
00037 bool operator==(vgui_grid_tableau_data const &a,
00038                 vgui_grid_tableau_data const &b);
00039 
00040 //: A tableau which renders its child tableaux as a rectangular grid.
00041 //
00042 //  It is derived from vgui_poly_tableau but unlike vgui_poly_tableau, the
00043 //  child tableaux of vgui_grid_tableau can only be laid out in an m by n
00044 //  rectangular grid.  Rows and columns are numbered starting from 0 with
00045 //  (0,0) in the top left and (m-1,n-1) in the bottom right.
00046 //
00047 //  The default behaviour of vgui_grid is to keep a list of every tableau
00048 //  added to the grid (using add_next to add to the next free position
00049 //  or add_at to add at a specific grid position).  Users can flip through
00050 //  this list of tableaux, 'tabs', by clicking in the grid position they
00051 //  wish to change, and using PageUp and PageDown to go through the list.
00052 //  When a new tableau is added using add_at the old tableau at that position
00053 //  is kept in the 'tabs' list and can still be viewed by using PageUp and
00054 //  PageDown.  Each grid position provides a view of the deck of tableaux kept
00055 //  in 'tabs'.  A tableau will only be removed from 'tabs' by using remove_at.
00056 //
00057 //  By default, the user can make the grid larger or smaller by using
00058 //  (CTRL) + and - to add and remove (rows and) columns.
00059 //
00060 //  These default behaviours can be changed using set_uses_paging_events and
00061 //  set_grid_size_changeable.  This stops vgui_grid using the events, but
00062 //  still passes them down to the child tableaux.  By disabling PageUp and
00063 //  PageDown you can prevent users from changing the displayed tableau - this
00064 //  could also be useful if you want to show two vgui_deck tableau and so want
00065 //  the PageUp and PageDown events to pass through vgui_grid and be used by the
00066 //  child decks. Disabling plus and minus events gives a grid tableau of fixed
00067 //  size.
00068 //
00069 //  This tableau was originally written for xcv, so look at this application
00070 //  to get a better idea what it does.
00071 class vgui_grid_tableau : public vgui_poly_tableau
00072 {
00073  public:
00074   typedef vgui_grid_tableau_data grid_data;
00075 
00076   //: Returns the type name of the tableau ("vgui_grid_tableau" in this case).
00077   vcl_string type_name() const { return "vgui_grid_tableau"; }
00078 
00079   //: Constructor - don't use this, use vgui_grid_tableau_new.
00080   //  Takes the initial number of columns and rows.
00081   vgui_grid_tableau(unsigned initial_columns = 1, unsigned initial_rows = 1)
00082   { init(initial_columns, initial_rows); }
00083 
00084   //: Constructor - don't use this, use vgui_grid_tableau_new.
00085   //  This creates a bi-tab, taking the two tableaux as parameters.
00086   vgui_grid_tableau(vgui_tableau_sptr const& l, vgui_tableau_sptr const& r);
00087 
00088   //: Constructor - don't use this, use vgui_grid_tableau_new.
00089   //  This creates a tri-tab, taking the three tableau as parameters.
00090   vgui_grid_tableau(vgui_tableau_sptr const& l, vgui_tableau_sptr const& m,
00091                     vgui_tableau_sptr const& r);
00092 
00093   //: Given the column number, returns the x coord for that column.
00094   float get_x(unsigned index);
00095 
00096   //: Given the row number, returns the y coord for that row.
00097   float get_y(unsigned index);
00098 
00099   //: Get the width of each column.
00100   float get_w();
00101 
00102   //: Get the height of each row.
00103   float get_h();
00104 
00105   //: Adds a tableau to the next free space in the grid and the list of tableaux
00106   void add_next(vgui_tableau_sptr const& tab);
00107 
00108   //: Adds a tableau to the next free space and returns the grid location
00109   void add_next(vgui_tableau_sptr const& tab, unsigned& col, unsigned& row);
00110 
00111   //: Add (or replace the tableau at the given position with) the given tableau.
00112   void add_at(vgui_tableau_sptr const& tab, unsigned col_pos, unsigned row_pos);
00113 
00114   //: Removes the tableau at the given grid coordinates from the display
00115   void remove_at(unsigned col_pos, unsigned row_pos);
00116 
00117   //: Returns the number of rows in the grid.
00118   unsigned rows() const { return nb_rows; }
00119 
00120   //: Returns the number of columns in the grid.
00121   unsigned cols() const { return nb_cols; }
00122 
00123   //: Returns a pointer to the tableau at the given position.
00124   vgui_tableau_sptr get_tableau_at(unsigned col_pos, unsigned row_pos);
00125 
00126   //: Returns the list of tableaux.
00127   vcl_vector<vgui_tableau_sptr> get_tableau_list() { return tabs; }
00128 
00129   //: Returns the active tableau, this is the tableau with the mouse in.
00130   void get_active_position(unsigned* col_pos, unsigned* row_pos);
00131 
00132   //: Returns the most recently selected column and row positions.
00133   void get_last_selected_position(unsigned* col_pos, unsigned* row_pos);
00134 
00135   //: Gets the positions and times of selection of the selected tableaux.
00136   int get_selected_positions(vcl_vector<int>* col_pos, vcl_vector<int>* row_pos,
00137                              vcl_vector<int>* times);
00138 
00139   //: Select a certain tableau
00140   void set_selected(int r, int c, bool onoff = true);
00141 
00142   //: True to allow the grid size to change, false to have fixed size.
00143   void set_grid_size_changeable(bool v) {
00144     cond_row_add   .enable(v);
00145     cond_row_remove.enable(v);
00146     cond_col_add   .enable(v);
00147     cond_col_remove.enable(v);
00148     grid_size_changeable = v;
00149   }
00150 
00151   //: True to use paging events, false to ignore them.
00152   void set_uses_paging_events(bool v) {
00153     cond_flip_fwd.enable(v);
00154     cond_flip_bwd.enable(v);
00155   }
00156 
00157   //: True to use mouse down events, false to ignore them.
00158   void set_frames_selectable(bool v) {
00159     cond_select  .enable(v);
00160     cond_deselect.enable(v);
00161   }
00162 
00163   //: Only allow one grid cell to be selected at a time, others are deselected
00164   void set_unique_selected(bool u) {unique_selected_ = u;}
00165 
00166   //: Use this to emulate the deprecated bitab and tritab:
00167   void emulate_ntab() {
00168     set_grid_size_changeable(false);
00169     set_uses_paging_events(false);
00170     set_frames_selectable(false);
00171   }
00172 
00173   //: Redraw the grid keeping each tableau in its current row and column.
00174   void layout_grid();
00175 
00176   //: Redraw the grid of tableaux packing them in without gaps.
00177   //  Fill each row from top left downwards.
00178   void layout_grid2();
00179 
00180   //: Add an empty column to the RHS of the grid.
00181   void add_column();
00182 
00183   //: Remove last column on RHS of the grid.
00184   void remove_column();
00185 
00186   //: Add an empty row to the bottom of the grid.
00187   void add_row();
00188 
00189   //: Remove last row on the bottom of the grid
00190   void remove_row();
00191 
00192   //: Flip forwards through the list of tableaux.
00193   void page_up();
00194 
00195   //: Flip backwards through the list of tableaux.
00196   void page_down();
00197 
00198   //: Handle any events matching the {vgui_event_condition}s.
00199   bool handle(const vgui_event&);
00200 
00201   //: Window coordinates of the cell bounding box at col, row
00202   bool cell_bounding_box(unsigned col, unsigned row,
00203                          float& xmin, float& ymin, float& xmax, float& ymax);
00204 
00205  protected:
00206   //: Destructor - called by vgui_grid_tableau_sptr.
00207   ~vgui_grid_tableau() {}
00208 
00209  private:
00210   // The number of rows and columns can be changed.
00211   vgui_event_condition cond_row_add;     // CTRL =
00212   vgui_event_condition cond_row_remove;  // CTRL -
00213   vgui_event_condition cond_col_add;     // =
00214   vgui_event_condition cond_col_remove;  // -
00215 
00216   // One can flip through the list of tableaux.
00217   vgui_event_condition cond_flip_fwd;    // PGUP
00218   vgui_event_condition cond_flip_bwd;    // PGDN
00219 
00220   // Frames can be selected and deselected.
00221   vgui_event_condition cond_select;      // left mouse button
00222   vgui_event_condition cond_deselect;    // middle mouse button
00223 
00224   int INCREMENT_COLS;        // Amount to increase the number of columns
00225   int INCREMENT_ROWS;        // Amount to increase the number of rows.
00226 
00227   bool grid_size_changeable; // Whether the grid size is allowed to change.
00228 
00229   unsigned nb_cols;
00230   unsigned max_cols;
00231   unsigned nb_rows;
00232   unsigned max_rows;
00233   unsigned last_selected[2]; // stores col_pos, row_pos of last selected tableau
00234   bool unique_selected_;
00235   vgui_tableau_sptr default_tab;
00236 
00237   vcl_vector<vgui_tableau_sptr> tabs;
00238   vbl_array_2d<grid_data> grid_pos;
00239 
00240   //: Initialisation called by all constructors.
00241   void init(unsigned initial_cols, unsigned initial_rows);
00242 
00243   //: Adds the default tableau to the given space in the grid.
00244   //  (but not to the vcl_list of tableaux).
00245   void add_default(unsigned col_pos, unsigned row_pos);
00246 
00247   //: Make the current tableau selected by saving the current time.
00248   void select_current(int time);
00249 
00250   //: Mark the current table as deselected by setting the time to -1.
00251   void deselect_current();
00252 };
00253 
00254 //: Create a smart pointer to a vgui_grid_tableau.
00255 struct vgui_grid_tableau_new : public vgui_grid_tableau_sptr {
00256   typedef vgui_grid_tableau_sptr base;
00257   vgui_grid_tableau_new(unsigned initial_columns = 1, unsigned initial_rows = 1)
00258     : base(new vgui_grid_tableau(initial_columns,initial_rows)) {}
00259   vgui_grid_tableau_new(vgui_tableau_sptr const& l, vgui_tableau_sptr const& r)
00260     : base(new vgui_grid_tableau(l, r)) {}
00261   vgui_grid_tableau_new(vgui_tableau_sptr const& l, vgui_tableau_sptr const& m,
00262                         vgui_tableau_sptr const& r)
00263     : base(new vgui_grid_tableau(l, m, r)) {}
00264 };
00265 
00266 #endif // vgui_grid_tableau_h_