mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
patches from rob browning
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@1654 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
e49a23fd58
commit
237e65d447
@ -705,4 +705,92 @@ xaccGetUserData (Table *table, int phys_row, int phys_col)
|
|||||||
return (table->user_data[virt_row][virt_col]);
|
return (table->user_data[virt_row][virt_col]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
wrapVerifyCursorPosition (Table *table, int row, int col)
|
||||||
|
{
|
||||||
|
CellBlock *save_curs = table->current_cursor;
|
||||||
|
int save_phys_row = table->current_cursor_phys_row;
|
||||||
|
int save_phys_col = table->current_cursor_phys_col;
|
||||||
|
|
||||||
|
/* VerifyCursor will do all sorts of gui-independent machinations */
|
||||||
|
xaccVerifyCursorPosition (table, row, col);
|
||||||
|
|
||||||
|
if ((save_phys_row != table->current_cursor_phys_row) ||
|
||||||
|
(save_phys_col != table->current_cursor_phys_col))
|
||||||
|
{
|
||||||
|
/* make sure *both* the old and the new cursor rows get redrawn */
|
||||||
|
xaccRefreshCursorGUI (table);
|
||||||
|
doRefreshCursorGUI (table, save_curs, save_phys_row, save_phys_col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccRefreshCursorGUI (Table * table)
|
||||||
|
{
|
||||||
|
doRefreshCursorGUI (table, table->current_cursor,
|
||||||
|
table->current_cursor_phys_row,
|
||||||
|
table->current_cursor_phys_col);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
gnc_register_cell_valid(Table *table, const int row, const int col) {
|
||||||
|
int invalid = 0;
|
||||||
|
int rel_row, rel_col;
|
||||||
|
CellBlock *arr, *header;
|
||||||
|
|
||||||
|
/* can't edit outside of the physical space */
|
||||||
|
invalid = (0 > row) || (0 > col) ;
|
||||||
|
invalid = invalid || (row >= table->num_phys_rows);
|
||||||
|
invalid = invalid || (col >= table->num_phys_cols);
|
||||||
|
|
||||||
|
/* gtksheet may call cell_changed after table has been destroyed.
|
||||||
|
Are we papering over a real bug here?
|
||||||
|
This is probably a good check anyway. */
|
||||||
|
if(!table->handlers) return TRUE;
|
||||||
|
|
||||||
|
/* header rows cannot be modified */
|
||||||
|
/* hack alert -- assumes that header is first cell */
|
||||||
|
/* if 0,0 is not a headr row, then trouble ... */
|
||||||
|
header = table->handlers[0][0];
|
||||||
|
invalid = invalid || (row < header->numRows);
|
||||||
|
|
||||||
|
/* If row or col is invalid, then the next bits could segfault... */
|
||||||
|
if(invalid) return TRUE;
|
||||||
|
|
||||||
|
/* compute the cell location */
|
||||||
|
rel_row = table->locators[row][col]->phys_row_offset;
|
||||||
|
rel_col = table->locators[row][col]->phys_col_offset;
|
||||||
|
|
||||||
|
/* verify that cursor offsets are valid. This may occur if
|
||||||
|
* the app that is using the table has a paritally initialized
|
||||||
|
* cursor. (probably due to a prograing error, but maybe they
|
||||||
|
* meant to do this). */
|
||||||
|
invalid = invalid || (0 > rel_row);
|
||||||
|
invalid = invalid || (0 > rel_col);
|
||||||
|
|
||||||
|
/* check for a cell handler, but only if cell adress is valid */
|
||||||
|
arr = table->current_cursor;
|
||||||
|
if (arr && !invalid) {
|
||||||
|
if (! (arr->cells[rel_row][rel_col])) {
|
||||||
|
invalid = TRUE;
|
||||||
|
} else {
|
||||||
|
/* if cell is marked as output-only,
|
||||||
|
* then don't call callbacks */
|
||||||
|
if (0 == (XACC_CELL_ALLOW_INPUT &
|
||||||
|
((arr->cells[rel_row][rel_col])->input_output)))
|
||||||
|
{
|
||||||
|
invalid = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
invalid = TRUE;
|
||||||
|
}
|
||||||
|
return(!invalid);
|
||||||
|
}
|
||||||
|
|
||||||
/* ================== end of file ======================= */
|
/* ================== end of file ======================= */
|
||||||
|
@ -250,6 +250,24 @@ xaccVerifyCursorPosition (Table *table, int phys_row, int phys_col);
|
|||||||
|
|
||||||
void * xaccGetUserData (Table *table, int phys_row, int phys_col);
|
void * xaccGetUserData (Table *table, int phys_row, int phys_col);
|
||||||
|
|
||||||
|
|
||||||
|
/* ==================================================== */
|
||||||
|
/* these are used internally by table-{motif,gtk}.c
|
||||||
|
perhaps these should go in a table-allguiP.h
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
wrapVerifyCursorPosition (Table *table, int row, int col);
|
||||||
|
|
||||||
|
int
|
||||||
|
gnc_register_cell_valid(Table *table, const int row, const int col);
|
||||||
|
|
||||||
|
void
|
||||||
|
doRefreshCursorGUI (Table * table, CellBlock *curs, int from_row, int from_col);
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccRefreshCursorGUI (Table * table);
|
||||||
|
|
||||||
|
|
||||||
/* ==================================================== */
|
/* ==================================================== */
|
||||||
/*
|
/*
|
||||||
* In C, we don't have things like C++ templates.
|
* In C, we don't have things like C++ templates.
|
||||||
|
@ -27,13 +27,6 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
|
|
||||||
/*
|
|
||||||
TODO:
|
|
||||||
|
|
||||||
Everywhere I use row + 1, it should be row + num_header_rows
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -418,76 +411,7 @@ cell_left(Table *table, const int row, const int col) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
traverseCB (GtkWidget * mw, gpointer cd, gpointer cb) {
|
traverseCB (GtkWidget * mw, gpointer cd, gpointer cb) {
|
||||||
|
/* see table-motif.c for appropriate code... */
|
||||||
Table *table;
|
|
||||||
CellBlock *arr;
|
|
||||||
XbaeMatrixTraverseCellCallbackStruct *cbs;
|
|
||||||
int row, col;
|
|
||||||
int rel_row, rel_col;
|
|
||||||
|
|
||||||
table = (Table *) cd;
|
|
||||||
arr = table->current_cursor;
|
|
||||||
cbs = (XbaeMatrixTraverseCellCallbackStruct *) cb;
|
|
||||||
|
|
||||||
row = cbs->row;
|
|
||||||
col = cbs->column;
|
|
||||||
|
|
||||||
/* If the quark is zero, then it is likely that we are
|
|
||||||
* here because we traversed out of a cell that had a
|
|
||||||
* ComboBox in it. The ComboCell is clever enough to put
|
|
||||||
* us back into the register after tabing out of it.
|
|
||||||
* However, its not (cannot be) clever enough to pretend
|
|
||||||
* that it was a tab group in the register. Thus,
|
|
||||||
* we will emulate that we left a tab group in the register
|
|
||||||
* to get here. To put it more simply, we just set the
|
|
||||||
* row and column to that of the ComboCell, which we had
|
|
||||||
* previously recorded, and continue on as if nothing
|
|
||||||
* happened.
|
|
||||||
* BTW -- note that we are emulating a normal, right-moving tab.
|
|
||||||
* Backwards tabs are broken.
|
|
||||||
*/
|
|
||||||
if (NULLQUARK == cbs->qparam) {
|
|
||||||
if ((0==row) && (0==col)) {
|
|
||||||
if ((0 <= table->prev_phys_traverse_row) &&
|
|
||||||
(0 <= table->prev_phys_traverse_col)) {
|
|
||||||
cbs->qparam = QRight;
|
|
||||||
row = table->prev_phys_traverse_row;
|
|
||||||
col = table->prev_phys_traverse_col;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xaccVerifyCursorPosition (table, row, col);
|
|
||||||
|
|
||||||
/* compute the cell location */
|
|
||||||
rel_row = table->locators[row][col]->phys_row_offset;
|
|
||||||
rel_col = table->locators[row][col]->phys_col_offset;
|
|
||||||
|
|
||||||
/* process right-moving traversals */
|
|
||||||
if (QRight == cbs->qparam) {
|
|
||||||
int next_row = arr->right_traverse_r[rel_row][rel_col];
|
|
||||||
int next_col = arr->right_traverse_c[rel_row][rel_col];
|
|
||||||
|
|
||||||
/* if we are at the end of the traversal chain,
|
|
||||||
* hop out of this tab group, and into the next.
|
|
||||||
*/
|
|
||||||
if ((0 > next_row) || (0 > next_col)) {
|
|
||||||
/* reverse the sign of next_row, col to be positive. */
|
|
||||||
cbs->next_row = row - rel_row - next_row -1;
|
|
||||||
cbs->next_column = col - rel_col - next_col -1;
|
|
||||||
cbs->qparam = NULLQUARK;
|
|
||||||
if (table->next_tab_group) {
|
|
||||||
XmProcessTraversal (table->next_tab_group,
|
|
||||||
XmTRAVERSE_CURRENT);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cbs->next_row = row - rel_row + next_row;
|
|
||||||
cbs->next_column = col - rel_col + next_col;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
table->prev_phys_traverse_row = cbs->next_row;
|
|
||||||
table->prev_phys_traverse_col = cbs->next_column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -495,21 +419,99 @@ traverseCB (GtkWidget * mw, gpointer cd, gpointer cb) {
|
|||||||
/* ==================================================== */
|
/* ==================================================== */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
table_activate_cell_cb(GtkSheet *s, gint row, gint column, gpointer data) {
|
table_deactivate_cell_cb(GtkSheet *s,
|
||||||
|
const gint row,
|
||||||
|
const gint column,
|
||||||
|
gpointer data) {
|
||||||
|
Table *table = (Table *) data;
|
||||||
|
int valid_cell = gnc_register_cell_valid(table, row, column);
|
||||||
|
|
||||||
|
if(!valid_cell) {
|
||||||
|
/* Undo anything that wasn't OK */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PINFO("deactivate_cell %d %d\n", row, column);
|
||||||
|
|
||||||
|
/* stuff */
|
||||||
|
|
||||||
|
wrapVerifyCursorPosition (table,
|
||||||
|
table->reverify_phys_row,
|
||||||
|
table->reverify_phys_col);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
table_activate_cell_cb(GtkSheet *s,
|
||||||
|
const gint row,
|
||||||
|
const gint column,
|
||||||
|
gpointer data) {
|
||||||
|
Table *table = (Table *) data;
|
||||||
|
int valid_cell;
|
||||||
|
|
||||||
|
/* If we are entering this cell, make sure that we've moved the
|
||||||
|
* cursor, and that any subsidiary GUI elements are properly
|
||||||
|
* positioned. Do this *before* we examine the value of the
|
||||||
|
* "current cursor". Note that this check could suck up massive
|
||||||
|
* cpu, as potentially it may trigger a redraw of the entire
|
||||||
|
* register.
|
||||||
|
*
|
||||||
|
* Hmmm ... actually, theoretically, this is not neeeded. Before
|
||||||
|
* we get to here, we *should* have gone through a traverse
|
||||||
|
* callback the determine which cell to enter, and then, after the
|
||||||
|
* leavecell, the cursor should have been automagically
|
||||||
|
* repositioned. This, the call below should always no-op out.
|
||||||
|
* However, if/when things go berzerk, the call below does at least
|
||||||
|
* a partial butt-save for us, so lets leave it in for now. */
|
||||||
|
|
||||||
|
/* Actually it seems to be necessary for the GNOME register, at
|
||||||
|
least right now. Try taking it out, and see if it's fixed. */
|
||||||
|
|
||||||
|
wrapVerifyCursorPosition (table, row, column);
|
||||||
|
|
||||||
|
valid_cell = gnc_register_cell_valid(table, row, column);
|
||||||
|
|
||||||
|
if(!valid_cell) {
|
||||||
|
/* Undo anything that wasn't OK */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(table->current_col != -1) {
|
||||||
|
table_deactivate_cell_cb(s, table->current_row, table->current_col,
|
||||||
|
(gpointer) table);
|
||||||
|
}
|
||||||
|
|
||||||
PINFO("activate_cell %d %d\n", row, column);
|
PINFO("activate_cell %d %d\n", row, column);
|
||||||
|
|
||||||
|
table->current_col = column;
|
||||||
|
table->current_row = row;
|
||||||
|
|
||||||
|
/* Stuff */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
table_set_cell_cb(GtkSheet *s, gint row, gint column, gpointer data) {
|
table_set_cell_cb(GtkSheet *s, gint row, gint column, gpointer data) {
|
||||||
|
Table *table = (Table *) data;
|
||||||
|
int valid_cell = gnc_register_cell_valid(table, row, column);
|
||||||
|
|
||||||
|
if(!valid_cell) {
|
||||||
|
/* Undo anything that wasn't OK */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PINFO("set_cell %d %d\n", row, column);
|
PINFO("set_cell %d %d\n", row, column);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
table_changed_cb(GtkSheet *s, gint row, gint column, gpointer data) {
|
table_changed_cb(GtkSheet *s, gint row, gint column, gpointer data) {
|
||||||
|
Table *table = (Table *) data;
|
||||||
|
int valid_cell = gnc_register_cell_valid(table, row, column);
|
||||||
|
|
||||||
|
if(!valid_cell) {
|
||||||
|
/* Undo anything that wasn't OK */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PINFO("changed %d %d\n", row, column);
|
PINFO("changed %d %d\n", row, column);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,39 +549,6 @@ table_edit_entry_cb(GtkEntry *entry, gpointer user_data) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
table_select_row_cb(GtkCList *cl, gint row, gint column, GdkEventButton *e,
|
|
||||||
gpointer user_data) {
|
|
||||||
|
|
||||||
#if OLD_CLIST_REG
|
|
||||||
|
|
||||||
Table *table = (Table *) user_data;
|
|
||||||
|
|
||||||
fprintf(stderr, "table_select_row_cb: %d %d\n", row, column);
|
|
||||||
|
|
||||||
//gtk_clist_unselect_row(cl, row, column);
|
|
||||||
|
|
||||||
if(!verify_cell_interaction_OK(table, row + 1, column)) return;
|
|
||||||
|
|
||||||
if(table->current_col != -1) {
|
|
||||||
cell_left(table, table->current_row + 1, table->current_col);
|
|
||||||
}
|
|
||||||
|
|
||||||
table->current_col = column;
|
|
||||||
table->current_row = row;
|
|
||||||
|
|
||||||
{
|
|
||||||
const int xxx = counter++;
|
|
||||||
printf(" ce: in %d\n", xxx);
|
|
||||||
cell_entered(table, row + 1, column);
|
|
||||||
printf(" ce: out %d\n", xxx);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ==================================================== */
|
/* ==================================================== */
|
||||||
@ -590,7 +559,6 @@ xaccCreateTable (Table *table, GtkWidget *parent) {
|
|||||||
CellBlock *curs;
|
CellBlock *curs;
|
||||||
unsigned char * alignments;
|
unsigned char * alignments;
|
||||||
short * widths;
|
short * widths;
|
||||||
int num_header_rows = 0;
|
|
||||||
|
|
||||||
if (!table) return 0;
|
if (!table) return 0;
|
||||||
|
|
||||||
@ -602,23 +570,13 @@ xaccCreateTable (Table *table, GtkWidget *parent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The 0'th row of the handlers is defined as the header */
|
/* The 0'th row of the handlers is defined as the header */
|
||||||
alignments = NULL;
|
|
||||||
widths = NULL;
|
|
||||||
curs = table->handlers[0][0];
|
curs = table->handlers[0][0];
|
||||||
alignments = curs->alignments;
|
alignments = curs->alignments;
|
||||||
widths = curs->widths;
|
widths = curs->widths;
|
||||||
num_header_rows = curs->numRows;
|
|
||||||
|
|
||||||
/* copy header data into entries cache */
|
/* copy header data into entries cache */
|
||||||
xaccRefreshHeader (table);
|
xaccRefreshHeader (table);
|
||||||
|
|
||||||
/* create the matrix widget */
|
|
||||||
if(num_header_rows > 1) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"gnucash: GTK implementation only supports one header row.\n");
|
|
||||||
num_header_rows = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
/* TODO: Handle unrefs in destructor */
|
/* TODO: Handle unrefs in destructor */
|
||||||
|
|
||||||
@ -629,21 +587,27 @@ xaccCreateTable (Table *table, GtkWidget *parent) {
|
|||||||
vbox = gtk_vbox_new(FALSE, 0);
|
vbox = gtk_vbox_new(FALSE, 0);
|
||||||
gtk_container_add(GTK_CONTAINER(parent), vbox);
|
gtk_container_add(GTK_CONTAINER(parent), vbox);
|
||||||
|
|
||||||
reg = gtk_sheet_new(table->num_phys_rows - num_header_rows,
|
reg = gtk_sheet_new(table->num_phys_rows,
|
||||||
table->num_phys_cols,
|
table->num_phys_cols,
|
||||||
"THE REGISTER");
|
"THE REGISTER");
|
||||||
gtk_sheet_hide_row_titles(GTK_SHEET(reg));
|
gtk_sheet_hide_row_titles(GTK_SHEET(reg));
|
||||||
gtk_sheet_show_column_titles(GTK_SHEET(reg));
|
gtk_sheet_hide_column_titles(GTK_SHEET(reg));
|
||||||
gtk_widget_ref(reg);
|
gtk_widget_ref(reg);
|
||||||
|
|
||||||
gtk_sheet_freeze(GTK_SHEET(reg));
|
gtk_sheet_freeze(GTK_SHEET(reg));
|
||||||
|
{
|
||||||
/* Set the column titles */
|
/* Set the column titles as read-only */
|
||||||
if(num_header_rows == 1) {
|
/* The 0'th row of the handlers is defined as the header */
|
||||||
int col;
|
const int num_header_rows = curs->numRows;
|
||||||
for(col = 0; col < table->num_phys_cols; col++) {
|
const int num_header_cols = curs->numCols;
|
||||||
gtk_sheet_set_column_title(GTK_SHEET(reg), col, table->entries[0][col]);
|
GtkSheetRange r;
|
||||||
}
|
|
||||||
|
r.row0 = 0;
|
||||||
|
r.col0 = 0;
|
||||||
|
r.rowi = num_header_rows - 1;
|
||||||
|
r.coli = num_header_cols - 1;
|
||||||
|
|
||||||
|
gtk_sheet_range_set_editable(GTK_SHEET(reg), r, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -665,7 +629,7 @@ xaccCreateTable (Table *table, GtkWidget *parent) {
|
|||||||
/* GTK_SHEET_SET_FLAGS(reg, GTK_SHEET_FLAGS(reg) & SHEET_AUTORESIZE); */
|
/* GTK_SHEET_SET_FLAGS(reg, GTK_SHEET_FLAGS(reg) & SHEET_AUTORESIZE); */
|
||||||
|
|
||||||
/* Set the cell contents */
|
/* Set the cell contents */
|
||||||
for(row = num_header_rows; row < table->num_phys_rows; row++) {
|
for(row = 0; row < table->num_phys_rows; row++) {
|
||||||
for(col = 0; col < table->num_phys_cols; col++) {
|
for(col = 0; col < table->num_phys_cols; col++) {
|
||||||
gtk_sheet_set_cell(GTK_SHEET(reg),
|
gtk_sheet_set_cell(GTK_SHEET(reg),
|
||||||
row, col,
|
row, col,
|
||||||
@ -683,58 +647,19 @@ xaccCreateTable (Table *table, GtkWidget *parent) {
|
|||||||
table->table_widget = reg;
|
table->table_widget = reg;
|
||||||
|
|
||||||
|
|
||||||
|
/* Supposed to be: enter, leave, modify, and traverse */
|
||||||
|
|
||||||
gtk_signal_connect (GTK_OBJECT (reg), "activate_cell",
|
gtk_signal_connect (GTK_OBJECT (reg), "activate_cell",
|
||||||
GTK_SIGNAL_FUNC (table_activate_cell_cb),
|
GTK_SIGNAL_FUNC (table_activate_cell_cb),
|
||||||
(gpointer) table);
|
(gpointer) table);
|
||||||
|
/* For now we'll fake deactivate ourselves... */
|
||||||
|
|
||||||
gtk_signal_connect (GTK_OBJECT (reg), "set_cell",
|
gtk_signal_connect (GTK_OBJECT (reg), "set_cell",
|
||||||
GTK_SIGNAL_FUNC (table_set_cell_cb),
|
GTK_SIGNAL_FUNC (table_set_cell_cb),
|
||||||
(gpointer) table);
|
(gpointer) table);
|
||||||
gtk_signal_connect (GTK_OBJECT (reg), "changed",
|
gtk_signal_connect (GTK_OBJECT (reg), "changed",
|
||||||
GTK_SIGNAL_FUNC (table_changed_cb),
|
GTK_SIGNAL_FUNC (table_changed_cb),
|
||||||
(gpointer) table);
|
(gpointer) table);
|
||||||
|
|
||||||
#if OLD_CLIST_REG
|
|
||||||
|
|
||||||
gtk_signal_connect (GTK_OBJECT (reg), "select_row",
|
|
||||||
GTK_SIGNAL_FUNC (table_select_row_cb),
|
|
||||||
(gpointer) table);
|
|
||||||
|
|
||||||
// unselect is mostly useless for us since it doesn't get called when
|
|
||||||
// you click on a different cell in the same row.
|
|
||||||
//gtk_signal_connect (GTK_OBJECT (reg), "unselect_row",
|
|
||||||
// GTK_SIGNAL_FUNC (table_unselect_row_cb),
|
|
||||||
// (gpointer) table);
|
|
||||||
|
|
||||||
{
|
|
||||||
GtkWidget *entry_frame = NULL;
|
|
||||||
GtkWidget *entry_widget = NULL;
|
|
||||||
|
|
||||||
entry_frame = gtk_frame_new("<none>");
|
|
||||||
gtk_widget_ref(entry_frame);
|
|
||||||
entry_widget = gtk_entry_new();
|
|
||||||
gtk_widget_ref(entry_widget);
|
|
||||||
|
|
||||||
gtk_container_add(GTK_CONTAINER(entry_frame), entry_widget);
|
|
||||||
gtk_box_pack_start(GTK_BOX(vbox), entry_frame, FALSE, FALSE, 0);
|
|
||||||
|
|
||||||
{
|
|
||||||
const guint handler_id =
|
|
||||||
gtk_signal_connect (GTK_OBJECT(entry_widget), "changed",
|
|
||||||
GTK_SIGNAL_FUNC(table_edit_entry_cb),
|
|
||||||
(gpointer) table);
|
|
||||||
|
|
||||||
gtk_object_set_user_data(GTK_OBJECT(entry_widget),
|
|
||||||
(gpointer) handler_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_widget_show(entry_widget);
|
|
||||||
gtk_widget_show(entry_frame);
|
|
||||||
|
|
||||||
gtk_widget_show(vbox);
|
|
||||||
table->entry_frame = entry_frame;
|
|
||||||
table->entry_widget = entry_widget;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize any cell gui elements now, if any */
|
/* initialize any cell gui elements now, if any */
|
||||||
@ -752,25 +677,24 @@ xaccCreateTable (Table *table, GtkWidget *parent) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
xaccCreateCursor (Table * table, CellBlock *curs)
|
xaccCreateCursor (Table * table, CellBlock *curs) {
|
||||||
{
|
|
||||||
int i,j;
|
int i,j;
|
||||||
|
GtkWidget *reg;
|
||||||
if (!curs || !table) return;
|
if (!curs || !table) return;
|
||||||
|
|
||||||
|
reg = table->table_widget;
|
||||||
|
if (!reg) return;
|
||||||
|
|
||||||
for (i=0; i<curs->numRows; i++) {
|
for (i=0; i<curs->numRows; i++) {
|
||||||
for (j=0; j<curs->numCols; j++) {
|
for (j=0; j<curs->numCols; j++) {
|
||||||
BasicCell *cell;
|
BasicCell *cell;
|
||||||
cell = curs->cells[i][j];
|
cell = curs->cells[i][j];
|
||||||
if (cell) {
|
if (cell) {
|
||||||
void (*gtk_realize) (BasicCell *, void *gui, int pixel_width);
|
void (*gtk_realize) (BasicCell *, void *gui, int pixel_width);
|
||||||
gtk_realize = cell->realize;
|
gtk_realize = cell->realize;
|
||||||
if (gtk_realize) {
|
if (gtk_realize) {
|
||||||
/* int pixel_width; */
|
int pixel_width = GTK_SHEET(reg)->column[j].width;
|
||||||
/* cl->column[col].width */
|
gtk_realize (cell, ((void *) table), pixel_width);
|
||||||
/*pixel_width = XbaeMatrixGetColumnPixelWidth (reg, j);*/
|
|
||||||
/*gtk_realize (cell, ((void *) reg), pixel_width);*/
|
|
||||||
gtk_realize (cell, ((void *) table), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -817,8 +741,69 @@ set_cell_color(GtkSheet *reg, Table *table, guint row, guint col,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_cell(GtkSheet *reg, Table *table, const gint row, const gint col) {
|
||||||
|
|
||||||
|
gtk_sheet_set_cell(reg, row, col, GTK_JUSTIFY_LEFT,
|
||||||
|
table->entries[row][col]);
|
||||||
|
|
||||||
|
|
||||||
|
/* You might be able to make this *much* faster by caching
|
||||||
|
colors. */
|
||||||
|
set_cell_color(reg, table, row, col,
|
||||||
|
table->bg_colors[row][col],
|
||||||
|
gtk_sheet_range_set_background);
|
||||||
|
|
||||||
|
set_cell_color(reg, table, row, col,
|
||||||
|
table->fg_colors[row][col],
|
||||||
|
gtk_sheet_range_set_foreground);
|
||||||
|
|
||||||
|
set_cell_color(reg, table, row, col,
|
||||||
|
/* this really should be win->default_style->black */
|
||||||
|
0,
|
||||||
|
gtk_sheet_range_set_border_color);
|
||||||
|
|
||||||
|
/* Turn on all the borders */
|
||||||
|
{
|
||||||
|
GtkSheetRange r;
|
||||||
|
r.row0 = row;
|
||||||
|
r.rowi = row + 1;
|
||||||
|
r.col0 = col;
|
||||||
|
r.coli = col + 1;
|
||||||
|
|
||||||
|
gtk_sheet_range_set_border(reg, r,
|
||||||
|
CELL_TOP_BORDER | CELL_BOTTOM_BORDER |
|
||||||
|
CELL_LEFT_BORDER | CELL_RIGHT_BORDER,
|
||||||
|
1, GDK_LINE_SOLID);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* This is more efficient than the above, but it won't work
|
||||||
|
unless gtksheet changes its semantics */
|
||||||
|
|
||||||
|
/* Turn on all the borders */
|
||||||
|
for(row = 0; row <= reg->maxrow; row++) {
|
||||||
|
GtkSheetRange r;
|
||||||
|
r.row0 = row;
|
||||||
|
r.rowi = row + 1;
|
||||||
|
r.col0 = 0;
|
||||||
|
r.coli = reg->maxcol;
|
||||||
|
|
||||||
|
PINFO("Setting border for (%d %d) (%d %d)\n",
|
||||||
|
r.row0, r.rowi, r.col0, r.coli);
|
||||||
|
gtk_sheet_range_set_border(reg, r, CELL_TOP_BORDER, 1, GDK_LINE_SOLID);
|
||||||
|
}
|
||||||
|
for(col = 0; col <= reg->maxcol; col++) {
|
||||||
|
GtkSheetRange r;
|
||||||
|
r.row0 = 0;
|
||||||
|
r.rowi = reg->maxrow;
|
||||||
|
r.col0 = col;
|
||||||
|
r.coli = col + 1;
|
||||||
|
|
||||||
|
gtk_sheet_range_set_border(reg, r, CELL_LEFT_BORDER, 1, GDK_LINE_SOLID);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
xaccRefreshTableGUI (Table * table) {
|
xaccRefreshTableGUI (Table * table) {
|
||||||
@ -840,17 +825,14 @@ xaccRefreshTableGUI (Table * table) {
|
|||||||
{
|
{
|
||||||
/* The 0'th row of the handlers is defined as the header */
|
/* The 0'th row of the handlers is defined as the header */
|
||||||
GtkSheet *reg = GTK_SHEET(table->table_widget);
|
GtkSheet *reg = GTK_SHEET(table->table_widget);
|
||||||
CellBlock *curs = table->handlers[0][0];
|
|
||||||
int num_header_rows = curs->numRows;
|
|
||||||
|
|
||||||
gtk_sheet_freeze(reg);
|
gtk_sheet_freeze(reg);
|
||||||
|
|
||||||
/* Adjust table to have the right number of rows */
|
/* Adjust table to have the right number of rows */
|
||||||
{
|
{
|
||||||
/* maxrow is actually the maximum index, not the total number of rows */
|
/* maxrow is actually the maximum index, not the total number of rows */
|
||||||
glong diffrows =
|
const glong diffrows = (reg->maxrow + 1) - table->num_phys_rows;
|
||||||
(reg->maxrow + 1) - (table->num_phys_rows - num_header_rows);
|
gint row, col;
|
||||||
gint table_row, row, col;
|
|
||||||
|
|
||||||
if(diffrows > 0) {
|
if(diffrows > 0) {
|
||||||
gtk_sheet_add_row(reg, diffrows);
|
gtk_sheet_add_row(reg, diffrows);
|
||||||
@ -859,85 +841,94 @@ xaccRefreshTableGUI (Table * table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set the per-cell contents, colors, etc. */
|
/* Set the per-cell contents, colors, etc. */
|
||||||
for(table_row = num_header_rows, row = 0;
|
for(row = 0; row < table->num_phys_rows; row++) {
|
||||||
table_row < table->num_phys_rows;
|
|
||||||
table_row++, row++) {
|
|
||||||
for(col = 0; col < table->num_phys_cols; col++) {
|
for(col = 0; col < table->num_phys_cols; col++) {
|
||||||
|
update_cell(reg, table, row, col);
|
||||||
gtk_sheet_set_cell(reg, row, col, GTK_JUSTIFY_LEFT,
|
|
||||||
table->entries[table_row][col]);
|
|
||||||
|
|
||||||
|
|
||||||
/* You might be able to make this *much* faster by caching
|
|
||||||
colors. */
|
|
||||||
set_cell_color(reg, table, row, col,
|
|
||||||
table->bg_colors[table_row][col],
|
|
||||||
gtk_sheet_range_set_background);
|
|
||||||
|
|
||||||
set_cell_color(reg, table, row, col,
|
|
||||||
table->fg_colors[table_row][col],
|
|
||||||
gtk_sheet_range_set_foreground);
|
|
||||||
|
|
||||||
set_cell_color(reg, table, row, col,
|
|
||||||
/* this really should be win->default_style->black */
|
|
||||||
0,
|
|
||||||
gtk_sheet_range_set_border_color);
|
|
||||||
|
|
||||||
/* Turn on all the borders */
|
|
||||||
{
|
|
||||||
GtkSheetRange r;
|
|
||||||
r.row0 = row;
|
|
||||||
r.rowi = row + 1;
|
|
||||||
r.col0 = col;
|
|
||||||
r.coli = col + 1;
|
|
||||||
|
|
||||||
gtk_sheet_range_set_border(reg, r,
|
|
||||||
CELL_TOP_BORDER | CELL_BOTTOM_BORDER |
|
|
||||||
CELL_LEFT_BORDER | CELL_RIGHT_BORDER,
|
|
||||||
1, GDK_LINE_SOLID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* This is more efficient than the above, but it won't work
|
|
||||||
unless gtksheet changes its semantics */
|
|
||||||
|
|
||||||
/* Turn on all the borders */
|
|
||||||
for(row = 0; row <= reg->maxrow; row++) {
|
|
||||||
GtkSheetRange r;
|
|
||||||
r.row0 = row;
|
|
||||||
r.rowi = row + 1;
|
|
||||||
r.col0 = 0;
|
|
||||||
r.coli = reg->maxcol;
|
|
||||||
|
|
||||||
L("Setting border for (%d %d) (%d %d)\n",
|
|
||||||
r.row0, r.rowi, r.col0, r.coli);
|
|
||||||
gtk_sheet_range_set_border(reg, r, CELL_TOP_BORDER, 1, GDK_LINE_SOLID);
|
|
||||||
}
|
|
||||||
for(col = 0; col <= reg->maxcol; col++) {
|
|
||||||
GtkSheetRange r;
|
|
||||||
r.row0 = 0;
|
|
||||||
r.rowi = reg->maxrow;
|
|
||||||
r.col0 = col;
|
|
||||||
r.coli = col + 1;
|
|
||||||
|
|
||||||
gtk_sheet_range_set_border(reg, r, CELL_LEFT_BORDER, 1, GDK_LINE_SOLID);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
gtk_sheet_thaw(reg);
|
gtk_sheet_thaw(reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
doRefreshCursorGUI (Table * table, CellBlock *curs, int from_row, int from_col)
|
||||||
|
{
|
||||||
|
int phys_row, phys_col;
|
||||||
|
int to_row, to_col;
|
||||||
|
int i,j;
|
||||||
|
|
||||||
|
/* if the current cursor is undefined, there is nothing to do. */
|
||||||
|
if (!curs) return;
|
||||||
|
if ((0 > from_row) || (0 > from_col)) return;
|
||||||
|
|
||||||
|
/* compute the physical bounds of the current cursor */
|
||||||
|
phys_row = from_row;
|
||||||
|
phys_col = from_col;
|
||||||
|
from_row -= table->locators[phys_row][phys_col]->phys_row_offset;
|
||||||
|
from_col -= table->locators[phys_row][phys_col]->phys_col_offset;
|
||||||
|
to_row = from_row + curs->numRows;
|
||||||
|
to_col = from_col + curs->numCols;
|
||||||
|
|
||||||
|
{
|
||||||
|
GtkSheet *reg = GTK_SHEET(table->table_widget);
|
||||||
|
|
||||||
|
gtk_sheet_freeze(reg);
|
||||||
|
|
||||||
|
/* cycle through, cell by cell, copying our values to the widget */
|
||||||
|
for (i=from_row; i<to_row; i++) {
|
||||||
|
for (j=from_col; j<to_col; j++) {
|
||||||
|
update_cell(reg, table, i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gtk_sheet_thaw(reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ================== end of file ======================= */
|
/* ================== end of file ======================= */
|
||||||
|
|
||||||
/*
|
|
||||||
Local Variables:
|
#if OLD_CLIST_REG
|
||||||
tab-width: 2
|
|
||||||
indent-tabs-mode: nil
|
gtk_signal_connect (GTK_OBJECT (reg), "select_row",
|
||||||
mode: c
|
GTK_SIGNAL_FUNC (table_select_row_cb),
|
||||||
c-indentation-style: gnu
|
(gpointer) table);
|
||||||
eval: (c-set-offset 'substatement-open 0)
|
|
||||||
End:
|
// unselect is mostly useless for us since it doesn't get called when
|
||||||
*/
|
// you click on a different cell in the same row.
|
||||||
|
//gtk_signal_connect (GTK_OBJECT (reg), "unselect_row",
|
||||||
|
// GTK_SIGNAL_FUNC (table_unselect_row_cb),
|
||||||
|
// (gpointer) table);
|
||||||
|
|
||||||
|
{
|
||||||
|
GtkWidget *entry_frame = NULL;
|
||||||
|
GtkWidget *entry_widget = NULL;
|
||||||
|
|
||||||
|
entry_frame = gtk_frame_new("<none>");
|
||||||
|
gtk_widget_ref(entry_frame);
|
||||||
|
entry_widget = gtk_entry_new();
|
||||||
|
gtk_widget_ref(entry_widget);
|
||||||
|
|
||||||
|
gtk_container_add(GTK_CONTAINER(entry_frame), entry_widget);
|
||||||
|
gtk_box_pack_start(GTK_BOX(vbox), entry_frame, FALSE, FALSE, 0);
|
||||||
|
|
||||||
|
{
|
||||||
|
const guint handler_id =
|
||||||
|
gtk_signal_connect (GTK_OBJECT(entry_widget), "changed",
|
||||||
|
GTK_SIGNAL_FUNC(table_edit_entry_cb),
|
||||||
|
(gpointer) table);
|
||||||
|
|
||||||
|
gtk_object_set_user_data(GTK_OBJECT(entry_widget),
|
||||||
|
(gpointer) handler_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_show(entry_widget);
|
||||||
|
gtk_widget_show(entry_frame);
|
||||||
|
|
||||||
|
gtk_widget_show(vbox);
|
||||||
|
table->entry_frame = entry_frame;
|
||||||
|
table->entry_widget = entry_widget;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -43,7 +43,6 @@ static void enterCB (Widget mw, XtPointer cd, XtPointer cb);
|
|||||||
static void leaveCB (Widget mw, XtPointer cd, XtPointer cb);
|
static void leaveCB (Widget mw, XtPointer cd, XtPointer cb);
|
||||||
static void modifyCB (Widget mw, XtPointer cd, XtPointer cb);
|
static void modifyCB (Widget mw, XtPointer cd, XtPointer cb);
|
||||||
static void traverseCB (Widget mw, XtPointer cd, XtPointer cb);
|
static void traverseCB (Widget mw, XtPointer cd, XtPointer cb);
|
||||||
static void doRefreshCursorGUI (Table * table, CellBlock *curs, int row, int col);
|
|
||||||
|
|
||||||
/* The XrmQuarks are used to figure out the direction of
|
/* The XrmQuarks are used to figure out the direction of
|
||||||
* traversal from cell to cell */
|
* traversal from cell to cell */
|
||||||
@ -62,26 +61,6 @@ xaccNextTabGroup (Table *table, Widget w)
|
|||||||
table->next_tab_group = w;
|
table->next_tab_group = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==================================================== */
|
|
||||||
|
|
||||||
static void
|
|
||||||
wrapVerifyCursorPosition (Table *table, int row, int col)
|
|
||||||
{
|
|
||||||
CellBlock *save_curs = table->current_cursor;
|
|
||||||
int save_phys_row = table->current_cursor_phys_row;
|
|
||||||
int save_phys_col = table->current_cursor_phys_col;
|
|
||||||
|
|
||||||
/* VerifyCursor will do all sorts of gui-independent machinations */
|
|
||||||
xaccVerifyCursorPosition (table, row, col);
|
|
||||||
|
|
||||||
if ((save_phys_row != table->current_cursor_phys_row) ||
|
|
||||||
(save_phys_col != table->current_cursor_phys_col))
|
|
||||||
{
|
|
||||||
/* make sure *both* the old and the new cursor rows get redrawn */
|
|
||||||
xaccRefreshCursorGUI (table);
|
|
||||||
doRefreshCursorGUI (table, save_curs, save_phys_row, save_phys_col);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ==================================================== */
|
/* ==================================================== */
|
||||||
/* this routine calls the individual cell callbacks */
|
/* this routine calls the individual cell callbacks */
|
||||||
@ -92,8 +71,6 @@ cellCB (Widget mw, XtPointer cd, XtPointer cb)
|
|||||||
Table *table;
|
Table *table;
|
||||||
XbaeMatrixDefaultActionCallbackStruct *cbs;
|
XbaeMatrixDefaultActionCallbackStruct *cbs;
|
||||||
int row, col;
|
int row, col;
|
||||||
int rel_row, rel_col;
|
|
||||||
CellBlock *arr, *header;
|
|
||||||
int invalid = 0;
|
int invalid = 0;
|
||||||
|
|
||||||
table = (Table *) cd;
|
table = (Table *) cd;
|
||||||
@ -116,50 +93,13 @@ cellCB (Widget mw, XtPointer cd, XtPointer cb)
|
|||||||
* repositioned. Thus, the call below should always no-op out.
|
* repositioned. Thus, the call below should always no-op out.
|
||||||
* However, if/when things go berzerk, the call below does at least
|
* However, if/when things go berzerk, the call below does at least
|
||||||
* a partial butt-save for us, so lets leave it in for now. */
|
* a partial butt-save for us, so lets leave it in for now. */
|
||||||
|
|
||||||
if (XbaeEnterCellReason == cbs->reason)
|
if (XbaeEnterCellReason == cbs->reason)
|
||||||
{
|
{
|
||||||
wrapVerifyCursorPosition (table, row, col);
|
wrapVerifyCursorPosition (table, row, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* can't edit outside of the physical space */
|
invalid = ! gnc_register_cell_valid(table, row, col);
|
||||||
invalid = (0 > row) || (0 > col) ;
|
|
||||||
invalid = invalid || (row >= table->num_phys_rows);
|
|
||||||
invalid = invalid || (col >= table->num_phys_cols);
|
|
||||||
|
|
||||||
/* header rows cannot be modified */
|
|
||||||
/* hack alert -- assumes that header is first cell */
|
|
||||||
/* if 0,0 is not a headr row, then trouble ... */
|
|
||||||
header = table->handlers[0][0];
|
|
||||||
invalid = invalid || (row < header->numRows);
|
|
||||||
|
|
||||||
/* compute the cell location */
|
|
||||||
rel_row = table->locators[row][col]->phys_row_offset;
|
|
||||||
rel_col = table->locators[row][col]->phys_col_offset;
|
|
||||||
|
|
||||||
/* verify that cursor offsets are valid. This may occur if
|
|
||||||
* the app that is using the table has a paritally initialized
|
|
||||||
* cursor. (probably due to a prograing error, but maybe they
|
|
||||||
* meant to do this). */
|
|
||||||
invalid = invalid || (0 > rel_row);
|
|
||||||
invalid = invalid || (0 > rel_col);
|
|
||||||
|
|
||||||
/* check for a cell handler, but only if cell adress is valid */
|
|
||||||
arr = table->current_cursor;
|
|
||||||
if (arr && !invalid) {
|
|
||||||
if (! (arr->cells[rel_row][rel_col])) {
|
|
||||||
invalid = TRUE;
|
|
||||||
} else {
|
|
||||||
/* if cell is marked as output-only,
|
|
||||||
* then don't call callbacks */
|
|
||||||
if (0 == (XACC_CELL_ALLOW_INPUT & ((arr->cells[rel_row][rel_col])->input_output)))
|
|
||||||
{
|
|
||||||
invalid = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
invalid = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* oops the callback failed for some reason ...
|
/* oops the callback failed for some reason ...
|
||||||
* reject the enter/edit/leave and return */
|
* reject the enter/edit/leave and return */
|
||||||
@ -888,7 +828,7 @@ xaccRefreshTableGUI (Table * table)
|
|||||||
|
|
||||||
/* ==================================================== */
|
/* ==================================================== */
|
||||||
|
|
||||||
static void
|
void
|
||||||
doRefreshCursorGUI (Table * table, CellBlock *curs, int from_row, int from_col)
|
doRefreshCursorGUI (Table * table, CellBlock *curs, int from_row, int from_col)
|
||||||
{
|
{
|
||||||
int phys_row, phys_col;
|
int phys_row, phys_col;
|
||||||
@ -933,14 +873,4 @@ doRefreshCursorGUI (Table * table, CellBlock *curs, int from_row, int from_col)
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==================================================== */
|
|
||||||
|
|
||||||
void
|
|
||||||
xaccRefreshCursorGUI (Table * table)
|
|
||||||
{
|
|
||||||
doRefreshCursorGUI (table, table->current_cursor,
|
|
||||||
table->current_cursor_phys_row,
|
|
||||||
table->current_cursor_phys_col);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ================== end of file ======================= */
|
/* ================== end of file ======================= */
|
||||||
|
Loading…
Reference in New Issue
Block a user