diff --git a/src/register/actioncell.c b/src/register/actioncell.c index 81a937c858..ef9d2a8530 100644 --- a/src/register/actioncell.c +++ b/src/register/actioncell.c @@ -1,7 +1,7 @@ #include "actioncell.h" -static void realizeAction (struct _BasicCell *bcell, void *w); +static void realizeAction (struct _BasicCell *bcell, void *w, int width); static void destroyAction (struct _BasicCell *bcell); /* =============================================== */ @@ -24,14 +24,14 @@ void xaccInitActionCell (ActionCell *cell) /* =============================================== */ static -void realizeAction (struct _BasicCell *bcell, void *w) +void realizeAction (struct _BasicCell *bcell, void *w, int width) { ActionCell *cell = (ActionCell *) bcell; /* first, call the combobox realize */ cell->cell.cell.realize = cell->chain_realize; if (cell->chain_realize) { - (cell->chain_realize) (bcell, w); + (cell->chain_realize) (bcell, w, width); } /* now, install our destroy */ diff --git a/src/register/actioncell.h b/src/register/actioncell.h index 0e1860c09f..7068eee81a 100644 --- a/src/register/actioncell.h +++ b/src/register/actioncell.h @@ -17,7 +17,9 @@ typedef struct _ActionCell { ComboCell cell; - void (* chain_realize) (struct _BasicCell *, void *gui_handle); + void (* chain_realize) (struct _BasicCell *, + void *gui_handle, + int pixel_width); void (* chain_destroy) (struct _BasicCell *); } ActionCell; diff --git a/src/register/basiccell.h b/src/register/basiccell.h index e49c5b4b6a..76f44033a2 100644 --- a/src/register/basiccell.h +++ b/src/register/basiccell.h @@ -55,6 +55,12 @@ * 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: + * 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 + * ComboBox supported the XmNunits resource, but it doesn't. */ #ifndef __XACC_BASIC_CELL_H__ @@ -78,7 +84,9 @@ typedef struct _BasicCell { const char * current); /* private, GUI-specific initializer */ - void (* realize) (struct _BasicCell *, void *gui_handle); + 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); diff --git a/src/register/combocell.c b/src/register/combocell.c index da9ba21765..053ec121f6 100644 --- a/src/register/combocell.c +++ b/src/register/combocell.c @@ -21,9 +21,12 @@ typedef struct _PopBox { static void selectCB (Widget w, XtPointer cd, XtPointer cb ); static void dropDownCB (Widget w, XtPointer cd, XtPointer cb ); -static void realizeCombo (struct _BasicCell *bcell, void *w); +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 const char * enterCombo (struct _BasicCell *bcell, const char *value); +static const char * leaveCombo (struct _BasicCell *bcell, const char *value); + /* =============================================== */ @@ -60,7 +63,7 @@ xaccAddComboCellMenuItem (ComboCell *cell, char * menustr) /* =============================================== */ static -void realizeCombo (struct _BasicCell *bcell, void *w) +void realizeCombo (struct _BasicCell *bcell, void *w, int pixel_width) { ComboCell *cell; PopBox *box; @@ -82,11 +85,18 @@ void realizeCombo (struct _BasicCell *bcell, void *w) /* to mark cell as realized, remove the realize method */ cell->cell.realize = NULL; cell->cell.move = moveCombo; + cell->cell.enter_cell = enterCombo; + cell->cell.leave_cell = leaveCombo; cell->cell.destroy = destroyCombo; - /* heuristic to increase the size of the drop-down box */ - width = cell->cell.width; - drop_width = (int) (1.2 * ((float) width)); + /* the combobox wants width in pixels, not in chars. + * It would be nice if ComboBox supported the XmNunits + * resource, but it doesn't. Also, while we are at it, + * increase the size of the drop-down box as well. + */ + width = pixel_width; + drop_width = (int) (1.3 * ((float) width)); + if (15 > drop_width) drop_width = 15; /* create the pop GUI */ combobox = XtVaCreateManagedWidget @@ -101,20 +111,17 @@ void realizeCombo (struct _BasicCell *bcell, void *w) XmNselectionPolicy, XmSINGLE_SELECT, XmNvalue, "", XmNwidth, width, + XmNdropDownWidth, drop_width, NULL); box->combobox = combobox; - if (10 < drop_width) { - XtVaSetValues (combobox, XmNdropDownWidth, drop_width, NULL); - } - - box->combobox = combobox; - /* add callbacks to detect a selection */ XtAddCallback (combobox, XmNselectionCallback, selectCB, (XtPointer)cell); XtAddCallback (combobox, XmNunselectionCallback, selectCB, (XtPointer)cell); XtAddCallback (combobox, XmNdropDownCallback, dropDownCB, (XtPointer)box); + + moveCombo (bcell, -1, -1); } /* =============================================== */ @@ -124,8 +131,6 @@ void moveCombo (struct _BasicCell *bcell, int phys_row, int phys_col) { ComboCell *cell; PopBox *box; - String choice; - XmString choosen; cell = (ComboCell *) bcell; box = (PopBox *) (cell->cell.gui_private); @@ -133,6 +138,12 @@ void moveCombo (struct _BasicCell *bcell, int phys_row, int phys_col) /* if the drop-down menu is showing, hide it now */ XmComboBoxHideList (box->combobox); +printf ("move from %d %d to %d %d \n", + box->currow, + box->curcol, + phys_row, + phys_col); + /* if there is an old widget, remove it */ if ((0 <= box->currow) && (0 <= box->curcol)) { XbaeMatrixSetCellWidget (box->parent, box->currow, box->curcol, NULL); @@ -140,12 +151,34 @@ void moveCombo (struct _BasicCell *bcell, int phys_row, int phys_col) box->currow = phys_row; box->curcol = phys_col; + XtUnmanageChild (box->combobox); +} + +/* =============================================== */ + +static +const char * enterCombo (struct _BasicCell *bcell, const char *value) +{ + int phys_row, phys_col; + String choice; + XmString choosen; + ComboCell *cell; + PopBox *box; + + cell = (ComboCell *) bcell; + box = (PopBox *) (cell->cell.gui_private); + + phys_row = box->currow; + phys_col = box->curcol; + /* if the new position is valid, go to it, * otherwise, unmanage the widget */ - if ((0 <= box->currow) && (0 <= box->curcol)) { + if ((0 <= phys_row) && (0 <= phys_col)) { /* Get the current cell contents, and set the - * combobox menu selction to match the contents */ + * combobox menu selection to match the contents. + * We could use the value passed in, but things should + * be consitent, so we don't need it. */ choice = cell->cell.value; /* do a menu selection only if the cell ain't empty. */ @@ -170,10 +203,37 @@ void moveCombo (struct _BasicCell *bcell, int phys_row, int phys_col) } /* drop down the menu so that its ready to go. */ - XmComboBoxShowList (box->combobox); + XmComboBoxShowList (box->combobox); +printf ("show at %d %d \n", phys_row, phys_col); } else { XtUnmanageChild (box->combobox); } + + return NULL; +} + +/* =============================================== */ + +static +const char * leaveCombo (struct _BasicCell *bcell, const char *value) +{ + ComboCell *cell; + PopBox *box; + + cell = (ComboCell *) bcell; + box = (PopBox *) (cell->cell.gui_private); + + /* if the drop-down menu is showing, hide it now */ + XmComboBoxHideList (box->combobox); + + /* if there is an old widget, remove it */ + if ((0 <= box->currow) && (0 <= box->curcol)) { + XbaeMatrixSetCellWidget (box->parent, box->currow, box->curcol, NULL); + } + + XtUnmanageChild (box->combobox); + + return NULL; } /* =============================================== */ @@ -196,6 +256,8 @@ void destroyCombo (struct _BasicCell *bcell) cell->cell.gui_private = NULL; cell->cell.realize = realizeCombo; cell->cell.move = NULL; + cell->cell.enter_cell = NULL; + cell->cell.leave_cell = NULL; cell->cell.destroy = NULL; } @@ -222,6 +284,7 @@ static void selectCB (Widget w, XtPointer cd, XtPointer cb ) } if (!choice) choice = XtNewString (""); +printf ("select %s \n", choice); XbaeMatrixSetCell (box->parent, box->currow, box->curcol, choice); xaccSetBasicCellValue (&(cell->cell), choice); XtFree (choice); diff --git a/src/register/table.c b/src/register/table.c index af66f2724e..0a21f6c72c 100644 --- a/src/register/table.c +++ b/src/register/table.c @@ -129,6 +129,36 @@ void xaccMoveCursor (Table *table, int virt_row, int virt_col) table->current_cursor_row = virt_row; table->current_cursor_col = virt_col; + /* update the cell values to reflect the new position */ + /* also, move the cell GUI, if needed */ + for (i=0; itile_height; i++) { + iphys = i + table->current_cursor_row * table->tile_height; + iphys += table->num_header_rows; + for (j=0; jtile_width; j++) { + + cell = table->cursor->cells[i][j]; + if (cell) { + jphys = j + table->current_cursor_col * table->tile_width; + xaccSetBasicCellValue (cell, table->entries[iphys][jphys]); + } + } + } +} + +/* ==================================================== */ + +void xaccMoveCursorGUI (Table *table, int virt_row, int virt_col) +{ + int i,j; + int iphys,jphys; + BasicCell *cell; + + if ((0 > virt_row) || (0 > virt_col)) return; + if (virt_row >= table->num_rows) return; + if (virt_col >= table->num_cols) return; + table->current_cursor_row = virt_row; + table->current_cursor_col = virt_col; + /* update the cell values to reflect the new position */ /* also, move the cell GUI, if needed */ for (i=0; itile_height; i++) { @@ -141,7 +171,7 @@ void xaccMoveCursor (Table *table, int virt_row, int virt_col) jphys = j + table->current_cursor_col * table->tile_width; xaccSetBasicCellValue (cell, table->entries[iphys][jphys]); - /* be sure to allow the GUI to move too */ + /* if a cell has a GUI, move that too */ if (cell->move) { (cell->move) (cell, iphys, jphys); } @@ -175,6 +205,36 @@ void xaccCommitEdits (Table *table) } } +/* ==================================================== */ +/* verifyCursorPosition checks the location of the cursor + * with respect to a row/column position, and repositions + * the cursor if necessary. + */ + +static void +verifyCursorPosition (Table *table, int phys_row, int phys_col) +{ + int virt_row, virt_col; + + /* compute the virtual position */ + virt_row = phys_row; + virt_row -= table->num_header_rows; + virt_row /= table->tile_height; + + virt_col = phys_col; + virt_col /= table->tile_width; + + if ((virt_row != table->current_cursor_row) || + (virt_col != table->current_cursor_col)) { + + /* before leaving, the current virtual position, + * commit any aedits that have been accumulated + * in the cursor */ + xaccCommitEdits (table); + xaccMoveCursorGUI (table, virt_row, virt_col); + } +} + /* ==================================================== */ /* hack alert -- will core dump if numrows has changed, etc. */ @@ -303,6 +363,7 @@ cellCB (Widget mw, XtPointer cd, XtPointer cb) * this cell. Dispatch for processing. */ switch (cbs->reason) { case XbaeEnterCellReason: { + verifyCursorPosition (table, row, col); enterCB (mw, cd, cb); break; } @@ -315,6 +376,7 @@ cellCB (Widget mw, XtPointer cd, XtPointer cb) break; } case XbaeTraverseCellReason: { + verifyCursorPosition (table, row, col); traverseCB (mw, cd, cb); break; } @@ -358,14 +420,16 @@ enterCB (Widget mw, XtPointer cd, XtPointer cb) /* OK, if there is a callback for this cell, call it */ enter = arr->cells[rel_row][rel_col]->enter_cell; if (enter) { - const char *val, *retval; + const char *val; + char *retval; val = table->entries[row][col]; - retval = enter (arr->cells[rel_row][rel_col], val); + retval = (char *) enter (arr->cells[rel_row][rel_col], val); + if (NULL == retval) retval = (char *) val; if (val != retval) { if (table->entries[row][col]) free (table->entries[row][col]); - table->entries[row][col] = (char *) retval; - XbaeMatrixSetCell (mw, row, col, (char *) retval); + table->entries[row][col] = retval; + XbaeMatrixSetCell (mw, row, col, retval); XbaeMatrixRefreshCell (mw, row, col); /* don't map a text widget */ @@ -505,8 +569,8 @@ leaveCB (Widget mw, XtPointer cd, XtPointer cb) retval = leave (arr->cells[rel_row][rel_col], val); newval = (char *) retval; - if (val == retval) newval = strdup (retval); - if (NULL == retval) newval = strdup (""); + if (val == retval) newval = strdup (val); + if (NULL == retval) newval = strdup (val); /* save whatever was returned */ if (table->entries[row][col]) free (table->entries[row][col]); @@ -648,10 +712,15 @@ xaccCreateTable (Table *table, Widget parent, char * name) BasicCell *cell; cell = curs->cells[i][j]; if (cell) { - void (*xt_realize) (struct _BasicCell *, void *gui); + void (*xt_realize) (struct _BasicCell *, + void *gui, + int pixel_width); xt_realize = cell->realize; if (xt_realize) { - xt_realize (((struct _BasicCell *) cell), ((void *) reg)); + int pixel_width; + pixel_width = XbaeMatrixGetColumnPixelWidth (reg, j); + xt_realize (((struct _BasicCell *) cell), + ((void *) reg), pixel_width); } } } diff --git a/src/register/table.h b/src/register/table.h index 40f337c53b..8f9267190f 100644 --- a/src/register/table.h +++ b/src/register/table.h @@ -67,9 +67,12 @@ void xaccRefreshTable (Table *); /* Make the indicated cell block be the cursor for this table */ void xaccSetCursor (Table *, CellBlock *); -/* move the cursor to the indicated location. */ +/* move the cursor (but not the GUI) to the indicated location. */ void xaccMoveCursor (Table *, int virt_row, int virt_col); +/* move the cursor GUI to the indicated location. */ +void xaccMoveCursorGUI (Table *, int virt_row, int virt_col); + /* copy text in the cursor cells to the table */ void xaccCommitEdits (Table *);