implement cell set_value callback

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@497 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 1998-02-03 00:20:42 +00:00
parent d63add89bf
commit 901c8180ae
8 changed files with 236 additions and 64 deletions

View File

@ -4,6 +4,8 @@
#include "basiccell.h" #include "basiccell.h"
/* ===================================================== */
BasicCell * xaccMallocBasicCell (void) BasicCell * xaccMallocBasicCell (void)
{ {
BasicCell * cell; BasicCell * cell;
@ -12,12 +14,15 @@ BasicCell * xaccMallocBasicCell (void)
return cell; return cell;
} }
/* ===================================================== */
void xaccInitBasicCell (BasicCell *cell) void xaccInitBasicCell (BasicCell *cell)
{ {
cell->input_output = 1; cell->input_output = 1;
cell->width = 0; cell->width = 0;
cell->alignment = 0; cell->alignment = 0;
cell->value = 0x0; cell->value = 0x0;
cell->set_value = NULL;
cell->enter_cell = NULL; cell->enter_cell = NULL;
cell->modify_verify = NULL; cell->modify_verify = NULL;
cell->leave_cell = NULL; cell->leave_cell = NULL;
@ -27,10 +32,23 @@ void xaccInitBasicCell (BasicCell *cell)
cell->gui_private = NULL; cell->gui_private = NULL;
} }
/* ===================================================== */
void xaccSetBasicCellValue (BasicCell *cell, const char *val) void xaccSetBasicCellValue (BasicCell *cell, const char *val)
{ {
if (cell->value) free (cell->value); void (*cb) (struct _BasicCell *, const char *);
cell->value = strdup (val);
cb = cell->set_value;
if (cb) {
/* avoid recursion by disabling the
* callback while it'sbeing called. */
cell->set_value = NULL;
(*cb) (cell, val);
cell->set_value = cb;
} else {
if (cell->value) free (cell->value);
cell->value = strdup (val);
}
} }
/* ------------------ end of file ---------------------- */ /* ================== end of file ====================== */

View File

@ -3,44 +3,70 @@
* basiccell.h * basiccell.h
* *
* FUNCTION: * FUNCTION:
* The BasicCell struct provides an abstract base class * The BasicCell class provides an abstract base class
* defining the handling of the editing of a cell of a table. * defining the handling of the editing of a cell of a table.
* Classes that provide the actual handling for different * Classes that provide the actual handling for different
* cell types should inherit from this class. * cell types should inherit from this class.
* *
* The BasicCell class encapsulates a single string value
* which can be set & read by the programmer, and edited
* by the "user". In the text below, the "user" is the
* person controlling the mouse and keyboard. Thus, when
* the user makes a move, it means that they have somehow
* intereacted with the cell, by clikcing with mouse or by
* typing at the keyboard. This class provides three
* callbacks which allow the programmer to understand what
* the user is doing.
*
* The programmer can create a custom GUI for editing the
* contents of the cell. There are three callbacks to allow
* a custom GUI to be created, destroyed and moved about.
*
* Since this class is implemented in C not C++, there is
* a "minor" problem with inheritance. To emulate the
* overloading of a virtual "SetValues" method, there is
* a set_value() callback, which will be called whenever
* the xaccSetBasicCellValue() subroutine is called.
*
* VIRTUAL/OVERLOADED METHODS:
* The set_value() callback will be called whenever the
* xaccSetBasicCellValue() method is called. Derived
* classes should provide a callback here if they need
* to understand special cell formats.
*
* MEMBERS: * MEMBERS:
* The input_output member is zero if the cell is supposed * The input_output member is zero if the cell is supposed
* to only display values, but not accept user input. If * to only display values, but not accept user input. If
* non-zero, then the callbacks below are used to when the * non-zero, then the callbacks below are used to when the
* cell is entered. * cell is entered.
* *
* CALLBACKS: *
* USER CALLBACKS:
* The enter_cell() callback is called when the user first * The enter_cell() callback is called when the user first
* makes a move to enter a cell. The current value of the * makes a move to enter a cell. The current value of the
* cell is passed as the argument. If the callback wishes * cell is passed as the argument. If the callback wishes
* to change the value of the cell, it can return a non-null * to change the value of the cell, it can return a non-null
* string. Alternately, to leave the value of the cell * string. Alternately, to leave the value of the cell
* unchanged, it can return NULL. If a string is returned, * unchanged, it can return NULL. If a string is returned,
* the string must be as the result of a malloc. * the string must be as the result of a malloc.
* *
* The leave_cell() callback is called when the user exits * The leave_cell() callback is called when the user exits
* a cell. The current value of the cell is passed as the * a cell. The current value of the cell is passed as the
* argument. If the callback wishes to change the value of * argument. If the callback wishes to change the value of
* the cell, it can return a non-null string. Alternately, * the cell, it can return a non-null string. Alternately,
* to leave the value of the cell unchanged, it can return * to leave the value of the cell unchanged, it can return
* NULL. If a string is returned, the string must be as the * NULL. If a string is returned, the string must be as the
* result of a malloc. * result of a malloc.
* *
* The modify-verify callback is called when a user * The modify_verify() callback is called when a user makes a
* makes a change to a cell. * change to a cell. The three arguments passed in are :
* The three arguments passed in are : * "old", the string prior to user's attempted modification,
* "old", the string prior to user's attempted modification, * "add", the string the user is attemptiong to add
* "add", the string the user is attemptiong to add * (will be null if text is being deleted).
* (will be null if text is being deleted). * "new", the string that would result is user's changes
* "new", the string that would result is user's changes * are accepted.
* are accepted. * It must return a string, or void if it rejects the change.
* It must return a string, or void if it rejects the change. * The returned string will be used to update the cell value.
* The returned string will be used to update the cell value.
* *
* Some memory management rules: * Some memory management rules:
* (1) the callback must not modify the values of old, change, new * (1) the callback must not modify the values of old, change, new
@ -51,12 +77,32 @@
* malloc the memory for a new string. It does not need * malloc the memory for a new string. It does not need
* to worry about garbage collection. * to worry about garbage collection.
* *
* GUI STUFF:
* The realize callback will be called when GUI-specific
* initalization needs to be done. For Xt/Motif, the second
* argument will be cast to the parent widget.
* *
* HACK ALERT NOTES: * GUI CALLBACKS:
* The cell may have some specific GUI elements which need
* to be initialized/positioned/etc. There are three GUI
* callbacks that allow the programmer to perform GUI-specific
* initialization & changes.
*
* The realize() callback will be called when GUI-specific
* initalization needs to be done. For Xt/Motif, the second
* argument will be cast to the parent widget. The third
* argument passes in the desired pixel-width for the GUI
* element. (Yes, the pixel-size thing is a hack that we
* allow for the moment. See below for more info.)
*
* The destroy() callback will be called when the GUI associated
* with the cell needs to be destroyed.
*
* The move() callback will be called when the GUI element needs
* to be positioned to a new location within the table grid.
* The second and third arguments are the physical (not virtual)
* row and column that the GUI elemnt should be moved to.
*
* The gui_private member may be used by the derived class to
* store any additional GUI-specific data.
*
* GUI HACK ALERT NOTES:
* The realize method takes a width argument only as a hack * The realize method takes a width argument only as a hack
* to work around the fact that the combo-box requires a width * to work around the fact that the combo-box requires a width
* in pixels, rather than in characters. It would be nice if * in pixels, rather than in characters. It would be nice if
@ -74,24 +120,26 @@ typedef struct _BasicCell {
char * value; /* current value */ char * value; /* current value */
const char * (*enter_cell) (struct _BasicCell *, /* "virtual", overloaded set-value method */
const char * current); void (*set_value) (struct _BasicCell *,
const char * new_value);
/* cell-editing callbacks */
const char * (*enter_cell) (struct _BasicCell *,
const char * current);
const char * (*modify_verify) (struct _BasicCell *, const char * (*modify_verify) (struct _BasicCell *,
const char *old, const char *old,
const char *add, const char *add,
const char *new); const char *new);
const char * (*leave_cell) (struct _BasicCell *, const char * (*leave_cell) (struct _BasicCell *,
const char * current); const char * current);
/* private, GUI-specific initializer */ /* private, GUI-specific callbacks */
void (* realize) (struct _BasicCell *, void (* realize) (struct _BasicCell *,
void *gui_handle, void *gui_handle,
int pixel_width); int pixel_width);
void (* move) (struct _BasicCell *,
/* private, GUI-specific callback to move gui element */ int phys_row, int phys_col);
void (* move) (struct _BasicCell *, int phys_row, int phys_col);
/* private, GUI-specific callback to detroy gui element */
void (* destroy) (struct _BasicCell *); void (* destroy) (struct _BasicCell *);
/* general hook for gui-private data */ /* general hook for gui-private data */

View File

@ -24,9 +24,14 @@ static void dropDownCB (Widget w, XtPointer cd, XtPointer cb );
static void realizeCombo (struct _BasicCell *bcell, void *w, int width); static void realizeCombo (struct _BasicCell *bcell, void *w, int width);
static void moveCombo (struct _BasicCell *bcell, int phys_row, int phys_col); static void moveCombo (struct _BasicCell *bcell, int phys_row, int phys_col);
static void destroyCombo (struct _BasicCell *bcell); static void destroyCombo (struct _BasicCell *bcell);
static void setComboValue (struct _BasicCell *bcell, const char *value);
static const char * enterCombo (struct _BasicCell *bcell, const char *value); static const char * enterCombo (struct _BasicCell *bcell, const char *value);
static const char * leaveCombo (struct _BasicCell *bcell, const char *value); static const char * leaveCombo (struct _BasicCell *bcell, const char *value);
#define SET(cell,str) { \
if ((cell)->value) free ((cell)->value); \
(cell)->value = strdup (str); \
}
/* =============================================== */ /* =============================================== */
@ -42,6 +47,7 @@ void xaccInitComboCell (ComboCell *cell)
{ {
xaccInitBasicCell ( &(cell->cell)); xaccInitBasicCell ( &(cell->cell));
cell->cell.realize = realizeCombo; cell->cell.realize = realizeCombo;
cell->cell.set_value = setComboValue;
cell->menuitems = (char **) malloc (sizeof (char *)); cell->menuitems = (char **) malloc (sizeof (char *));
cell->menuitems[0] = NULL; cell->menuitems[0] = NULL;
} }
@ -97,7 +103,7 @@ xaccSetComboCellValue (ComboCell *cell, const char * str)
{ {
PopBox * box; PopBox * box;
xaccSetBasicCellValue (&(cell->cell), str); SET (&(cell->cell), str);
box = (PopBox *) (cell->cell.gui_private); box = (PopBox *) (cell->cell.gui_private);
if (str) { if (str) {
@ -117,6 +123,15 @@ xaccSetComboCellValue (ComboCell *cell, const char * str)
/* =============================================== */ /* =============================================== */
static void
setComboValue (struct _BasicCell *_cell, const char *str)
{
ComboCell * cell = (ComboCell *) _cell;
xaccSetComboCellValue (cell, str);
}
/* =============================================== */
static static
void realizeCombo (struct _BasicCell *bcell, void *w, int pixel_width) void realizeCombo (struct _BasicCell *bcell, void *w, int pixel_width)
{ {
@ -341,6 +356,12 @@ static void selectCB (Widget w, XtPointer cd, XtPointer cb )
cell = (ComboCell *) cd; cell = (ComboCell *) cd;
box = (PopBox *) (cell->cell.gui_private); box = (PopBox *) (cell->cell.gui_private);
if ((0 > box->currow) || (0 > box->curcol)) {
/*
printf ("Internal Error: ComboBox: incorrect cell location \n");
return;
*/
}
/* check the reason, because the unslect callback /* check the reason, because the unslect callback
* doesn't even have a value field! */ * doesn't even have a value field! */
if ( (XmCR_SINGLE_SELECT == selection->reason) || if ( (XmCR_SINGLE_SELECT == selection->reason) ||
@ -349,9 +370,9 @@ static void selectCB (Widget w, XtPointer cd, XtPointer cb )
} }
if (!choice) choice = XtNewString (""); if (!choice) choice = XtNewString ("");
printf ("combo selectcb choice %s at %d %d \n", choice, box->currow, box->curcol);
XbaeMatrixSetCell (box->parent, box->currow, box->curcol, choice); XbaeMatrixSetCell (box->parent, box->currow, box->curcol, choice);
xaccSetBasicCellValue (&(cell->cell), choice); SET (&(cell->cell), choice);
printf ("celectcb choice %s \n", choice);
XtFree (choice); XtFree (choice);
/* a diffeent way of getting the user's selection ... */ /* a diffeent way of getting the user's selection ... */

View File

@ -1,10 +1,25 @@
/*
* FILE:
* datecell.c
*
* HISTORY:
* Copyright (c) 1998 Linas Vepstas
*/
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "basiccell.h" #include "basiccell.h"
#include "datecell.h" #include "datecell.h"
static void setDateCellValue (struct _BasicCell *, const char *);
#define SET(cell,str) { \
if ((cell)->value) free ((cell)->value); \
(cell)->value = strdup (str); \
}
#define DATE_SEP '/' #define DATE_SEP '/'
/* ================================================ */ /* ================================================ */
@ -256,7 +271,9 @@ DateMV (struct _BasicCell *_cell,
prtDate (buff, date->tm_mday, date->tm_mon+1, date->tm_year+1900); prtDate (buff, date->tm_mday, date->tm_mon+1, date->tm_year+1900);
xaccSetBasicCellValue (&(cell->cell), buff); if (cell->cell.value) free (cell->cell.value);
cell->cell.value = strdup (buff);
datestr = strdup (buff); datestr = strdup (buff);
return datestr; return datestr;
@ -279,7 +296,9 @@ DateLeave (struct _BasicCell *_cell, const char * curr)
cell->date.tm_mon+1, cell->date.tm_mon+1,
cell->date.tm_year+1900); cell->date.tm_year+1900);
xaccSetBasicCellValue (&(cell->cell), buff); if (cell->cell.value) free (cell->cell.value);
cell->cell.value = strdup (buff);
retval = strdup (buff); retval = strdup (buff);
return retval; return retval;
} }
@ -312,11 +331,12 @@ xaccInitDateCell (DateCell *cell)
cell->date = *now; cell->date = *now;
prtDate (buff, now->tm_mday, now->tm_mon+1, now->tm_year+1900); prtDate (buff, now->tm_mday, now->tm_mon+1, now->tm_year+1900);
xaccSetBasicCellValue (&(cell->cell), buff); SET (&(cell->cell), buff);
cell->cell.enter_cell = DateEnter; cell->cell.enter_cell = DateEnter;
cell->cell.modify_verify = DateMV; cell->cell.modify_verify = DateMV;
cell->cell.leave_cell = DateLeave; cell->cell.leave_cell = DateLeave;
cell->cell.set_value = setDateCellValue;
} }
/* ================================================ */ /* ================================================ */
@ -337,7 +357,27 @@ xaccSetDateCellValue (DateCell *cell, int day, int mon, int year)
cell->date.tm_year = dada.tm_year; cell->date.tm_year = dada.tm_year;
prtDate (buff, dada.tm_mday, dada.tm_mon+1, dada.tm_year+1900); prtDate (buff, dada.tm_mday, dada.tm_mon+1, dada.tm_year+1900);
xaccSetBasicCellValue (&(cell->cell), buff);
if (cell->cell.value) free (cell->cell.value);
cell->cell.value = strdup (buff);
}
/* ================================================ */
static void
setDateCellValue (struct _BasicCell *_cell, const char *str)
{
DateCell *cell = (DateCell *) _cell;
char buff[30];
xaccParseDate (&(cell->date), str);
prtDate (buff, cell->date.tm_mday,
cell->date.tm_mon+1,
cell->date.tm_year+1900);
if (cell->cell.value) free (cell->cell.value);
cell->cell.value = strdup (buff);
} }
/* ============== END OF FILE ===================== */ /* ============== END OF FILE ===================== */

View File

@ -1,11 +1,22 @@
#include <string.h> #include <string.h>
#include "util.h"
#include "basiccell.h" #include "basiccell.h"
#include "pricecell.h" #include "pricecell.h"
static void PriceSetValue (struct _BasicCell *, const char *);
static void Set (BasicCell *, const char *);
#define DECIMAL_PT '.' #define DECIMAL_PT '.'
#define SET(cell,str) { \
if ((cell)->value) free ((cell)->value); \
(cell)->value = strdup (str); \
}
/* ================================================ */ /* ================================================ */
/* This callback only allows numbers with a single /* This callback only allows numbers with a single
* decimal point in them */ * decimal point in them */
@ -16,7 +27,7 @@ PriceMV (struct _BasicCell *_cell,
const char *change, const char *change,
const char *newval) const char *newval)
{ {
BasicCell *cell = (BasicCell *) _cell; PriceCell *cell = (PriceCell *) _cell;
/* accept the newval string if user action was delete, etc. */ /* accept the newval string if user action was delete, etc. */
if (change) { if (change) {
@ -33,8 +44,9 @@ PriceMV (struct _BasicCell *_cell,
} }
} }
/* hack alert - should parse the float pt value */ /* parse the float pt value and store it */
xaccSetBasicCellValue (cell, newval); cell->amount = xaccParseUSAmount (newval);
SET ((&(cell->cell)), newval);
return newval; return newval;
} }
@ -57,9 +69,10 @@ xaccInitPriceCell (PriceCell *cell)
xaccInitBasicCell( &(cell->cell)); xaccInitBasicCell( &(cell->cell));
cell->amount = 0.0; cell->amount = 0.0;
xaccSetBasicCellValue ( &(cell->cell), "0.0"); SET ( &(cell->cell), "0.0");
cell->cell.modify_verify = PriceMV; cell->cell.modify_verify = PriceMV;
cell->cell.set_value = PriceSetValue;
} }
/* ================================================ */ /* ================================================ */
@ -69,7 +82,7 @@ void xaccSetPriceCellValue (PriceCell * cell, double amt)
char buff[40]; char buff[40];
cell->amount = amt; cell->amount = amt;
sprintf (buff, "%.3f", amt); sprintf (buff, "%.3f", amt);
xaccSetBasicCellValue ( &(cell->cell), buff); SET ( &(cell->cell), buff);
} }
/* ================================================ */ /* ================================================ */
@ -79,7 +92,7 @@ void xaccSetAmountCellValue (PriceCell * cell, double amt)
char buff[40]; char buff[40];
cell->amount = amt; cell->amount = amt;
sprintf (buff, "%.2f", amt); sprintf (buff, "%.2f", amt);
xaccSetBasicCellValue ( &(cell->cell), buff); SET ( &(cell->cell), buff);
} }
/* ================================================ */ /* ================================================ */
@ -93,13 +106,29 @@ void xaccSetDebCredCellValue (PriceCell * deb,
if (0.0 <= amt) { if (0.0 <= amt) {
sprintf (buff, "%.2f", amt); sprintf (buff, "%.2f", amt);
xaccSetBasicCellValue ( &(cred->cell), buff); SET ( &(cred->cell), buff);
xaccSetBasicCellValue ( &(deb->cell), ""); SET ( &(deb->cell), "");
} else { } else {
sprintf (buff, "%.2f", -amt); sprintf (buff, "%.2f", -amt);
xaccSetBasicCellValue ( &(cred->cell), ""); SET ( &(cred->cell), "");
xaccSetBasicCellValue ( &(deb->cell), buff); SET ( &(deb->cell), buff);
} }
} }
/* ================================================ */
static void
PriceSetValue (struct _BasicCell *_cell, const char *str)
{
char buff[40];
PriceCell *cell = (PriceCell *) _cell;
SET (((BasicCell *)_cell), str);
cell->amount = xaccParseUSAmount (str);
sprintf (buff, "%.2f", cell->amount);
SET ( &(cell->cell), buff);
}
/* --------------- end of file ---------------------- */ /* --------------- end of file ---------------------- */

View File

@ -4,6 +4,21 @@
#include "basiccell.h" #include "basiccell.h"
#include "quickfillcell.h" #include "quickfillcell.h"
#define SET(cell,str) { \
if ((cell)->value) free ((cell)->value); \
(cell)->value = strdup (str); \
}
/* ================================================ */
static void
quick_set (struct _BasicCell *_cell,
const char *val)
{
QuickFillCell *cell = (QuickFillCell *) _cell;
xaccSetQuickFillCellValue (cell, val);
}
/* ================================================ */ /* ================================================ */
/* when entering new cell, reset pointer to root */ /* when entering new cell, reset pointer to root */
@ -61,7 +76,7 @@ quick_modify (struct _BasicCell *_cell,
if (cell->qf) retval = strdup (cell->qf->text); if (cell->qf) retval = strdup (cell->qf->text);
} }
xaccSetBasicCellValue (&(cell->cell), retval); SET (&(cell->cell), retval);
return retval; return retval;
} }
@ -104,15 +119,16 @@ xaccInitQuickFillCell (QuickFillCell *cell)
cell->cell.enter_cell = quick_enter; cell->cell.enter_cell = quick_enter;
cell->cell.modify_verify = quick_modify; cell->cell.modify_verify = quick_modify;
cell->cell.leave_cell = quick_leave; cell->cell.leave_cell = quick_leave;
cell->cell.set_value = quick_set;
} }
/* ================================================ */ /* ================================================ */
void void
xaccSetQuickFillCellValue (QuickFillCell *cell, char * value) xaccSetQuickFillCellValue (QuickFillCell *cell, const char * value)
{ {
xaccQFInsertText (cell->qfRoot, value); xaccQFInsertText (cell->qfRoot, value);
xaccSetBasicCellValue (&(cell->cell), value); SET (&(cell->cell), value);
} }
/* =============== END OF FILE ==================== */ /* =============== END OF FILE ==================== */

View File

@ -32,7 +32,7 @@ typedef struct _QuickFillCell {
QuickFillCell * xaccMallocQuickFillCell (void); QuickFillCell * xaccMallocQuickFillCell (void);
void xaccInitQuickFillCell (QuickFillCell *); void xaccInitQuickFillCell (QuickFillCell *);
void xaccSetQuickFillCellValue (QuickFillCell *, char *); void xaccSetQuickFillCellValue (QuickFillCell *, const char *);
#endif /* __XACC_FILL_CELL_C__ */ #endif /* __XACC_FILL_CELL_C__ */

View File

@ -473,7 +473,7 @@ table->current_cursor_col,
virt_row, virt_col); virt_row, virt_col);
/* before leaving, the current virtual position, /* before leaving, the current virtual position,
* commit any aedits that have been accumulated * commit any edits that have been accumulated
* in the cursor */ * in the cursor */
xaccCommitCursor (table); xaccCommitCursor (table);
xaccMoveCursorGUI (table, virt_row, virt_col); xaccMoveCursorGUI (table, virt_row, virt_col);