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"
/* ===================================================== */
BasicCell * xaccMallocBasicCell (void)
{
BasicCell * cell;
@ -12,12 +14,15 @@ BasicCell * xaccMallocBasicCell (void)
return cell;
}
/* ===================================================== */
void xaccInitBasicCell (BasicCell *cell)
{
cell->input_output = 1;
cell->width = 0;
cell->alignment = 0;
cell->value = 0x0;
cell->set_value = NULL;
cell->enter_cell = NULL;
cell->modify_verify = NULL;
cell->leave_cell = NULL;
@ -27,10 +32,23 @@ void xaccInitBasicCell (BasicCell *cell)
cell->gui_private = NULL;
}
/* ===================================================== */
void xaccSetBasicCellValue (BasicCell *cell, const char *val)
{
if (cell->value) free (cell->value);
cell->value = strdup (val);
void (*cb) (struct _BasicCell *, const char *);
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
*
* 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.
* Classes that provide the actual handling for different
* 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:
* The input_output member is zero if the cell is supposed
* to only display values, but not accept user input. If
* non-zero, then the callbacks below are used to when the
* cell is entered.
*
* CALLBACKS:
*
* USER CALLBACKS:
* The enter_cell() callback is called when the user first
* makes a move to enter a cell. The current value of the
* cell is passed as the argument. If the callback wishes
* to change the value of the cell, it can return a non-null
* string. Alternately, to leave the value of the cell
* unchanged, it can return NULL. If a string is returned,
* the string must be as the result of a malloc.
* makes a move to enter a cell. The current value of the
* cell is passed as the argument. If the callback wishes
* to change the value of the cell, it can return a non-null
* string. Alternately, to leave the value of the cell
* unchanged, it can return NULL. If a string is returned,
* the string must be as the result of a malloc.
*
* The leave_cell() callback is called when the user exits
* a cell. The current value of the cell is passed as the
* argument. If the callback wishes to change the value of
* the cell, it can return a non-null string. Alternately,
* to leave the value of the cell unchanged, it can return
* NULL. If a string is returned, the string must be as the
* result of a malloc.
* a cell. The current value of the cell is passed as the
* argument. If the callback wishes to change the value of
* the cell, it can return a non-null string. Alternately,
* to leave the value of the cell unchanged, it can return
* NULL. If a string is returned, the string must be as the
* result of a malloc.
*
* The modify-verify callback is called when a user
* makes a change to a cell.
* The three arguments passed in are :
* "old", the string prior to user's attempted modification,
* "add", the string the user is attemptiong to add
* (will be null if text is being deleted).
* "new", the string that would result is user's changes
* are accepted.
* It must return a string, or void if it rejects the change.
* The returned string will be used to update the cell value.
* The modify_verify() callback is called when a user makes a
* change to a cell. The three arguments passed in are :
* "old", the string prior to user's attempted modification,
* "add", the string the user is attemptiong to add
* (will be null if text is being deleted).
* "new", the string that would result is user's changes
* are accepted.
* It must return a string, or void if it rejects the change.
* The returned string will be used to update the cell value.
*
* Some memory management rules:
* (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
* 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
* to work around the fact that the combo-box requires a width
* in pixels, rather than in characters. It would be nice if
@ -74,24 +120,26 @@ typedef struct _BasicCell {
char * value; /* current value */
const char * (*enter_cell) (struct _BasicCell *,
const char * current);
/* "virtual", overloaded set-value method */
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 *old,
const char *add,
const char *new);
const char * (*leave_cell) (struct _BasicCell *,
const char * current);
const char * (*leave_cell) (struct _BasicCell *,
const char * current);
/* private, GUI-specific initializer */
/* private, GUI-specific callbacks */
void (* realize) (struct _BasicCell *,
void *gui_handle,
int pixel_width);
/* private, GUI-specific callback to move gui element */
void (* move) (struct _BasicCell *, int phys_row, int phys_col);
/* private, GUI-specific callback to detroy gui element */
void (* move) (struct _BasicCell *,
int phys_row, int phys_col);
void (* destroy) (struct _BasicCell *);
/* 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 moveCombo (struct _BasicCell *bcell, int phys_row, int phys_col);
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 * 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));
cell->cell.realize = realizeCombo;
cell->cell.set_value = setComboValue;
cell->menuitems = (char **) malloc (sizeof (char *));
cell->menuitems[0] = NULL;
}
@ -97,7 +103,7 @@ xaccSetComboCellValue (ComboCell *cell, const char * str)
{
PopBox * box;
xaccSetBasicCellValue (&(cell->cell), str);
SET (&(cell->cell), str);
box = (PopBox *) (cell->cell.gui_private);
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
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;
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
* doesn't even have a value field! */
if ( (XmCR_SINGLE_SELECT == selection->reason) ||
@ -349,9 +370,9 @@ static void selectCB (Widget w, XtPointer cd, XtPointer cb )
}
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);
xaccSetBasicCellValue (&(cell->cell), choice);
printf ("celectcb choice %s \n", choice);
SET (&(cell->cell), choice);
XtFree (choice);
/* 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 <time.h>
#include "basiccell.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 '/'
/* ================================================ */
@ -256,7 +271,9 @@ DateMV (struct _BasicCell *_cell,
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);
return datestr;
@ -279,7 +296,9 @@ DateLeave (struct _BasicCell *_cell, const char * curr)
cell->date.tm_mon+1,
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);
return retval;
}
@ -312,11 +331,12 @@ xaccInitDateCell (DateCell *cell)
cell->date = *now;
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.modify_verify = DateMV;
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;
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 ===================== */

View File

@ -1,11 +1,22 @@
#include <string.h>
#include "util.h"
#include "basiccell.h"
#include "pricecell.h"
static void PriceSetValue (struct _BasicCell *, const char *);
static void Set (BasicCell *, const char *);
#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
* decimal point in them */
@ -16,7 +27,7 @@ PriceMV (struct _BasicCell *_cell,
const char *change,
const char *newval)
{
BasicCell *cell = (BasicCell *) _cell;
PriceCell *cell = (PriceCell *) _cell;
/* accept the newval string if user action was delete, etc. */
if (change) {
@ -33,8 +44,9 @@ PriceMV (struct _BasicCell *_cell,
}
}
/* hack alert - should parse the float pt value */
xaccSetBasicCellValue (cell, newval);
/* parse the float pt value and store it */
cell->amount = xaccParseUSAmount (newval);
SET ((&(cell->cell)), newval);
return newval;
}
@ -57,9 +69,10 @@ xaccInitPriceCell (PriceCell *cell)
xaccInitBasicCell( &(cell->cell));
cell->amount = 0.0;
xaccSetBasicCellValue ( &(cell->cell), "0.0");
SET ( &(cell->cell), "0.0");
cell->cell.modify_verify = PriceMV;
cell->cell.set_value = PriceSetValue;
}
/* ================================================ */
@ -69,7 +82,7 @@ void xaccSetPriceCellValue (PriceCell * cell, double amt)
char buff[40];
cell->amount = 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];
cell->amount = 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) {
sprintf (buff, "%.2f", amt);
xaccSetBasicCellValue ( &(cred->cell), buff);
xaccSetBasicCellValue ( &(deb->cell), "");
SET ( &(cred->cell), buff);
SET ( &(deb->cell), "");
} else {
sprintf (buff, "%.2f", -amt);
xaccSetBasicCellValue ( &(cred->cell), "");
xaccSetBasicCellValue ( &(deb->cell), buff);
SET ( &(cred->cell), "");
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 ---------------------- */

View File

@ -4,6 +4,21 @@
#include "basiccell.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 */
@ -61,7 +76,7 @@ quick_modify (struct _BasicCell *_cell,
if (cell->qf) retval = strdup (cell->qf->text);
}
xaccSetBasicCellValue (&(cell->cell), retval);
SET (&(cell->cell), retval);
return retval;
}
@ -104,15 +119,16 @@ xaccInitQuickFillCell (QuickFillCell *cell)
cell->cell.enter_cell = quick_enter;
cell->cell.modify_verify = quick_modify;
cell->cell.leave_cell = quick_leave;
cell->cell.set_value = quick_set;
}
/* ================================================ */
void
xaccSetQuickFillCellValue (QuickFillCell *cell, char * value)
xaccSetQuickFillCellValue (QuickFillCell *cell, const char * value)
{
xaccQFInsertText (cell->qfRoot, value);
xaccSetBasicCellValue (&(cell->cell), value);
SET (&(cell->cell), value);
}
/* =============== END OF FILE ==================== */

View File

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

View File

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