1 /********************************************************************\
2  * table-allgui.h -- 2D grid table object, embeds cells for i/o     *
3  *                                                                  *
4  * This program is free software; you can redistribute it and/or    *
5  * modify it under the terms of the GNU General Public License as   *
6  * published by the Free Software Foundation; either version 2 of   *
7  * the License, or (at your option) any later version.              *
8  *                                                                  *
9  * This program is distributed in the hope that it will be useful,  *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
12  * GNU General Public License for more details.                     *
13  *                                                                  *
14  * You should have received a copy of the GNU General Public License*
15  * along with this program; if not, contact:                        *
16  *                                                                  *
17  * Free Software Foundation           Voice:  +1-617-542-5942       *
18  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
19  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
20  *                                                                  *
21 \********************************************************************/
22 /** @addtogroup RegisterCore Register Core
23  *  @{
24  */
25 /** @addtogroup Table Table
26  * @brief The "Table" is a displayed matrix. The table
27  * is a complex object; it is @b not merely a @ref Cellblock. The table provides
28  * all of the GUI infrastructure for displaying a row-column matrix of strings.
29  *
30  * The table provides one very important function for minimizing memory usage
31  * for large matrixes - the notion of a "Cursor". The cursor is a @ref Cellblock
32  * (an array of active cells) that is moved to the location that the user is
33  * currently editing. The cursor "virtualizes" @ref Cell functions; that is, it
34  * makes it seem to the user as if all cells in the table are active, when in
35  * fact the only cell that actually needs to be active is the one that the user
36  * is currently editing.
37  *
38  * The table design allows multiple cursors to be defined. When a user enters a
39  * cell, the appropriate cursor is positioned within the table. Cursors cannot
40  * overlap: any given cell can be mapped to at most one cursor. Multiple-cursor
41  * support allows tables to be designed that have a non-uniform layout. For
42  * example, the multiple-cursor support can be used to define a tree structure
43  * of headings and sub-headings, where the layout/format of the heading is
44  * different from the sub-headings. A financial example is a table which lists
45  * splits underneath their parent transaction. This is very different from a
46  * checkbook register, where all entries are uniform, and can be handled with a
47  * single repeated cursor.
48  *
49  * Users of the table must provide a TableView object which provides an API the
50  * table uses to obtain information about the data it is displaying such as
51  * strings, colors, etc. Thus, the table represents the non-GUI portion of the
52  * View object in the Model-View-Controller paradigm.
53  * @{
54  */
55 /** @file table-allgui.h
56  *  @brief Declarations for the Table object
57  *  @author Copyright (c) 1998,1999,2000 Linas Vepstas
58  *  @author Copyright (c) 2000-2001 Dave Peticolas
59  *
60  *  @details
61  *  The Table object defines the structure and the GUI required
62  *  to display a two-dimensional grid. It provides several
63  *  important functions:
64  *  - An array of virtual cells. These cells contain:
65  *     - the cellblock handler for that virtual cell.
66  *     - a user data pointer
67  *  - Tab-traversing mechanism so that operator can tab in a
68  *     predefined order between cells.
69  *
70  *  This implements the gui-independent parts of the table
71  *  infrastructure. Additional, GUI-dependent parts are implemented
72  *  in table-gnome.c.
73  *
74  *  The following concepts apply to the rows in a table:
75  *  - a cursor is always the same size as the virt row its on,
76  *  - there is only one cursor for a given virt row.
77  *  - there is no overlap; a phys row can only belong to one virt row.
78  *
79  *  Lets say there are three cursors T(rans), S(plit), and B(lank).
80  *  Lets say that these are used to 'print' the following table layout:
81  *
82 @verbatim
83 virtual row 1   T
84 virtual row 2   S
85 virtual row 3   B
86 virtual row 4   T
87 virtual row 5   S
88 virtual row 6   S
89 virtual row 7   S
90 virtual row 8   S
91 virtual row 9   B
92 @endverbatim
93  *
94  *  You can see there is only one cursor per virtual row. There is no overlap
95  *  between cursors and virtual rows; the correspondence is one to one. Note
96  *  that the three cursors T, S and B may consist of one, or more physical rows,
97  *  e.g. B and S may be one line each, but T may be two lines. Thus, we
98  *  have the following physical layout:
99  *
100 @verbatim
101 physical row 1    virtual row 1   T
102 physical row 2    virtual row 1   T
103 physical row 3    virtual row 2   S
104 physical row 4    virtual row 3   B
105 physical row 5    virtual row 4   T
106 physical row 6    virtual row 4   T
107 physical row 7    virtual row 5   S
108 physical row 8    virtual row 6   S
109 physical row 9    virtual row 7   S
110 physical row 10   virtual row 8   S
111 physical row 11   virtual row 9   B
112 @endverbatim
113  *
114  *  This layout remains static until the next time that the table is
115  *  re-'printed'.
116  */
117 
118 #ifndef TABLE_ALLGUI_H
119 #define TABLE_ALLGUI_H
120 
121 #include <glib.h>
122 
123 #include "basiccell.h"
124 #include "cellblock.h"
125 #include "gtable.h"
126 #include "register-common.h"
127 #include "table-control.h"
128 #include "table-layout.h"
129 #include "table-model.h"
130 
131 /** holds information about each virtual cell. */
132 typedef struct
133 {
134     CellBlock *cellblock;  /** Array of physical cells */
135     gpointer   vcell_data; /** Used by higher-level code */
136 
137     /* flags */
138     unsigned int visible : 1;             /** visible in the GUI */
139     unsigned int start_primary_color : 1; /** color usage flag */
140 } VirtualCell;
141 
142 typedef struct table Table;
143 
144 typedef void (*TableCursorRefreshCB) (Table *table,
145                                       VirtualCellLocation vcell_loc,
146                                       gboolean do_scroll);
147 
148 typedef void (*TableRedrawHelpCB) (Table *table);
149 typedef void (*TableDestroyCB) (Table *table);
150 
151 typedef struct
152 {
153     TableCursorRefreshCB cursor_refresh;
154 
155     TableRedrawHelpCB redraw_help;
156     TableDestroyCB destroy;
157 } TableGUIHandlers;
158 
159 struct table
160 {
161     TableLayout  *layout;
162     TableModel   *model;
163     TableControl *control;
164 
165     int num_virt_rows;
166     int num_virt_cols;
167 
168     CellBlock *current_cursor;
169 
170     VirtualLocation current_cursor_loc;
171 
172     /* private data */
173 
174     /* The virtual cell table */
175     GTable *virt_cells;
176 
177     TableGUIHandlers gui_handlers;
178     gpointer ui_data;
179 };
180 
181 /** Color definitions used for table elements */
182 typedef enum {
183     COLOR_UNDEFINED = 0,      // 0
184     COLOR_HEADER,             // 1
185     COLOR_PRIMARY,            // 2
186     COLOR_PRIMARY_ACTIVE,     // 3
187     COLOR_SECONDARY,          // 4
188     COLOR_SECONDARY_ACTIVE,   // 5
189     COLOR_SPLIT,              // 6
190     COLOR_SPLIT_ACTIVE,       // 7
191     COLOR_NEGATIVE = 16,      // 16
192 } RegisterColor;
193 
194 
195 /** Set the default gui handlers used by new tables. */
196 void gnc_table_set_default_gui_handlers (TableGUIHandlers *gui_handlers);
197 
198 /* Functions to create and destroy Tables.  */
199 Table *     gnc_table_new (TableLayout *layout,
200                            TableModel *model,
201                            TableControl *control);
202 void        gnc_virtual_location_init (VirtualLocation *vloc);
203 
204 void        gnc_table_save_state (Table *table, const gchar *state_section);
205 void        gnc_table_destroy (Table *table);
206 
207 
208 /* Functions to work with current cursor */
209 int         gnc_table_current_cursor_changed (Table *table,
210         gboolean include_conditional);
211 
212 void        gnc_table_clear_current_cursor_changes (Table *table);
213 
214 void        gnc_table_save_current_cursor (Table *table, CursorBuffer *buffer);
215 void        gnc_table_restore_current_cursor (Table *table,
216         CursorBuffer *buffer);
217 
218 const char * gnc_table_get_current_cell_name (Table *table);
219 
220 gboolean    gnc_table_get_current_cell_location (Table *table,
221         const char *cell_name,
222         VirtualLocation *virt_loc);
223 
224 
225 /** checks the given location and returns true if it is out of bounds of the
226  * table. */
227 gboolean gnc_table_virtual_cell_out_of_bounds (Table *table,
228         VirtualCellLocation vcell_loc);
229 
230 gboolean gnc_table_virtual_location_in_header (Table *table,
231         VirtualLocation virt_loc);
232 
233 
234 /** returns the virtual cell associated with a particular virtual location. If
235  * the location is out of bounds, NULL is * returned. */
236 VirtualCell *  gnc_table_get_virtual_cell (Table *table,
237         VirtualCellLocation vcell_loc);
238 
239 const char *   gnc_table_get_entry (Table *table, VirtualLocation virt_loc);
240 
241 char *         gnc_table_get_tooltip (Table *table, VirtualLocation virt_loc);
242 
243 const char *   gnc_table_get_label (Table *table, VirtualLocation virt_loc);
244 
245 CellIOFlags    gnc_table_get_io_flags (Table *table, VirtualLocation virt_loc);
246 
247 guint32        gnc_table_get_color (Table *table, VirtualLocation virt_loc,
248                                        gboolean *hatching);
249 
250 void           gnc_table_get_borders (Table *table, VirtualLocation virt_loc,
251                                       PhysicalCellBorders *borders);
252 
253 CellAlignment  gnc_table_get_align (Table *table, VirtualLocation virt_loc);
254 
255 gboolean       gnc_table_is_popup (Table *table, VirtualLocation virt_loc);
256 
257 char *         gnc_table_get_help (Table *table);
258 
259 BasicCell *    gnc_table_get_cell (Table *table, VirtualLocation virt_loc);
260 
261 const char *   gnc_table_get_cell_name (Table *table,
262                                         VirtualLocation virt_loc);
263 const gchar *  gnc_table_get_cell_type_name (Table *table,
264         VirtualLocation virt_loc);
265 gboolean       gnc_table_get_cell_location (Table *table,
266         const char * cell_name,
267         VirtualCellLocation vcell_loc,
268         VirtualLocation *virt_loc);
269 
270 void           gnc_table_save_cells (Table *table, gpointer save_data);
271 
272 
273 /** Return the virtual cell of the header */
274 VirtualCell *  gnc_table_get_header_cell (Table *table);
275 
276 /** The gnc_table_set_size() method will resize the table to the
277  *   indicated dimensions.  */
278 void        gnc_table_set_size (Table * table, int virt_rows, int virt_cols);
279 
280 /** Indicate what handler should be used for a given virtual block */
281 void        gnc_table_set_vcell (Table *table, CellBlock *cursor,
282                                  gconstpointer vcell_data,
283                                  gboolean visible,
284                                  gboolean start_primary_color,
285                                  VirtualCellLocation vcell_loc);
286 
287 /** Set the virtual cell data for a particular location. */
288 void        gnc_table_set_virt_cell_data (Table *table,
289         VirtualCellLocation vcell_loc,
290         gconstpointer vcell_data);
291 
292 /** Set the visibility flag for a particular location. */
293 void        gnc_table_set_virt_cell_visible (Table *table,
294         VirtualCellLocation vcell_loc,
295         gboolean visible);
296 
297 /** Set the cellblock handler for a virtual cell. */
298 void        gnc_table_set_virt_cell_cursor (Table *table,
299         VirtualCellLocation vcell_loc,
300         CellBlock *cursor);
301 
302 /** will move the cursor (but not the cursor GUI) to the indicated
303  * location. This function is useful when loading the table from the cursor:
304  * data can be loaded into the cursor, then committed to the table, all
305  * without the annoying screen flashing associated with GUI redraw. */
306 void        gnc_table_move_cursor (Table *table, VirtualLocation virt_loc);
307 
308 /** will move the cursor and its GUI to the indicated location. Through a series
309  * of callbacks, all GUI elements get repositioned. */
310 void        gnc_table_move_cursor_gui (Table *table, VirtualLocation virt_loc);
311 
312 /** checks the location of the cursor with respect to a virtual location
313  * position, and if the resulting virtual location has changed, repositions
314  * the cursor and gui to the new position. Returns true if the cell cursor was
315  * repositioned. */
316 gboolean    gnc_table_verify_cursor_position (Table *table,
317         VirtualLocation virt_loc);
318 
319 /** returns the virtual cell data associated with a cursor located at the given
320  * virtual coords, or NULL if the coords are out of bounds. */
321 gpointer    gnc_table_get_vcell_data (Table *table,
322                                       VirtualCellLocation vcell_loc);
323 
324 /** Find a close valid cell. If exact_cell is true, cells that must
325  * be explicitly selected by the user (as opposed to just tabbing
326  * into), are considered valid cells. */
327 gboolean    gnc_table_find_close_valid_cell (Table *table,
328         VirtualLocation *virt_loc,
329         gboolean exact_cell);
330 
331 /** UI-specific functions *******************************/
332 
333 /** Initialize the GUI from a table */
334 void        gnc_table_init_gui (Table *table);
335 
336 void        gnc_table_realize_gui (Table *table);
337 
338 /** Refresh the current cursor gui */
339 void        gnc_table_refresh_current_cursor_gui (Table * table,
340         gboolean do_scroll);
341 
342 /** Refresh the whole GUI from the table. */
343 void        gnc_table_refresh_gui (Table *table, gboolean do_scroll);
344 
345 /** Try to show the whole range in the register. */
346 void        gnc_table_show_range (Table *table,
347                                   VirtualCellLocation start_loc,
348                                   VirtualCellLocation end_loc);
349 
350 /** Refresh the cursor in the given location. If do_scroll is TRUE,
351  * scroll the register so the location is in view. */
352 void        gnc_table_refresh_cursor_gui (Table * table,
353         VirtualCellLocation vcell_loc,
354         gboolean do_scroll);
355 
356 /* ==================================================== */
357 
358 void         gnc_table_wrap_verify_cursor_position (Table *table,
359         VirtualLocation virt_loc);
360 
361 gboolean     gnc_table_virtual_loc_valid(Table *table,
362         VirtualLocation virt_loc,
363         gboolean exact_pointer);
364 
365 gboolean     gnc_table_move_tab (Table *table,
366                                  VirtualLocation *virt_loc,
367                                  gboolean move_right);
368 
369 /** Moves away from virtual location @a virt_loc by @a phys_row_offset physical
370  *  rows. Virtual cells that are not visible are skipped over.
371  *
372  *  @param table The table
373  *
374  *  @param virt_loc The virtual location to start from. If the move succeeds,
375  *  it is updated with the new location.
376  *
377  *  @param phys_row_offset The number of physical rows to move. A positive
378  *  number moves down and a negative number moves up.
379  *
380  *  @return TRUE if the location changed, FALSE otherwise
381  */
382 gboolean     gnc_table_move_vertical_position (Table *table,
383         VirtualLocation *virt_loc,
384         int phys_row_offset);
385 
386 gboolean     gnc_table_enter_update(Table *table,
387                                     VirtualLocation virt_loc,
388                                     int *cursor_position,
389                                     int *start_selection,
390                                     int *end_selection);
391 
392 void         gnc_table_leave_update(Table *table, VirtualLocation virt_loc);
393 
394 gboolean     gnc_table_confirm_change(Table *table, VirtualLocation virt_loc);
395 
396 const char * gnc_table_modify_update(Table *table,
397                                      VirtualLocation virt_loc,
398                                      const char *change,
399                                      int change_len,
400                                      const char *newval,
401                                      int newval_len,
402                                      int *cursor_position,
403                                      int *start_selection,
404                                      int *end_selection,
405                                      gboolean *cancelled);
406 
407 gboolean     gnc_table_direct_update(Table *table,
408                                      VirtualLocation virt_loc,
409                                      char **newval_ptr,
410                                      int *cursor_position,
411                                      int *start_selection,
412                                      int *end_selection,
413                                      gpointer gui_data);
414 
415 gboolean     gnc_table_traverse_update(Table *table,
416                                        VirtualLocation virt_loc,
417                                        gncTableTraversalDir dir,
418                                        VirtualLocation *dest_loc);
419 
420 #endif /* TABLE_ALLGUI_H */
421 /** @} */
422 /** @} */
423