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@842 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
24059fd35f
commit
432b61f132
@ -35,11 +35,11 @@ CFLAGS := -O2 -Wall -g -Wall -DCELL_WIDGETS=1 ${INCLPATH}
|
||||
|
||||
######################################################################
|
||||
# See Makefile.common for information about these variables.
|
||||
COMMON_SRCS := basiccell.c cellblock.c combocell.c \
|
||||
COMMON_SRCS := basiccell.c cellblock.c \
|
||||
datecell.c pricecell.c QuickFill.c quickfillcell.c \
|
||||
recncell.c register.c table-allgui.c textcell.c
|
||||
MOTIF_SRCS := table-motif.c
|
||||
GNOME_SRCS := table-gtk.c
|
||||
MOTIF_SRCS := table-motif.c combocell-motif.c
|
||||
GNOME_SRCS := table-gtk.c combocell-gtk.c
|
||||
######################################################################
|
||||
|
||||
all:
|
||||
|
@ -35,11 +35,11 @@ CFLAGS := @CFLAGS@ -DCELL_WIDGETS=1 ${INCLPATH}
|
||||
|
||||
######################################################################
|
||||
# See Makefile.common for information about these variables.
|
||||
COMMON_SRCS := basiccell.c cellblock.c combocell.c \
|
||||
COMMON_SRCS := basiccell.c cellblock.c \
|
||||
datecell.c pricecell.c QuickFill.c quickfillcell.c \
|
||||
recncell.c register.c table-allgui.c textcell.c
|
||||
MOTIF_SRCS := table-motif.c
|
||||
GNOME_SRCS := table-gtk.c
|
||||
MOTIF_SRCS := table-motif.c combocell-motif.c
|
||||
GNOME_SRCS := table-gtk.c combocell-gtk.c
|
||||
######################################################################
|
||||
|
||||
all:
|
||||
|
720
src/register/combocell-gtk.c
Normal file
720
src/register/combocell-gtk.c
Normal file
@ -0,0 +1,720 @@
|
||||
/*
|
||||
* FILE:
|
||||
* combocell.c
|
||||
*
|
||||
* FUNCTION:
|
||||
* implement motif portions of a pull-down combo widget
|
||||
* embedded in a table cell.
|
||||
*
|
||||
* HISTORY:
|
||||
* Copyright (c) 1998 Linas Vepstas
|
||||
* Copyright (c) 1998 Rob Browning <rlb@cs.utexas.edu>
|
||||
*/
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
\********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "table-allgui.h"
|
||||
#include "table-gtk.h"
|
||||
|
||||
|
||||
#include "combocell-gtk.h"
|
||||
#include "combocell-gtkP.h"
|
||||
|
||||
/* Some GUI-private date that is inappropriate for
|
||||
* the public interface. In this impelmentation,
|
||||
* it holds gtk data that we need.
|
||||
*/
|
||||
|
||||
#define SET(cell,str) { \
|
||||
if ((cell)->value) free ((cell)->value); \
|
||||
(cell)->value = strdup (str); \
|
||||
(cell)->changed = 0xffffffff; \
|
||||
}
|
||||
|
||||
typedef struct _PopBox {
|
||||
GtkCombo *combobox;
|
||||
GList *menustrings;
|
||||
Table *table;
|
||||
int currow;
|
||||
int curcol;
|
||||
} PopBox;
|
||||
|
||||
//static void selectCB (Widget w, XtPointer cd, XtPointer cb );
|
||||
|
||||
static void realizeCombo (BasicCell *bcell, void *w, int width);
|
||||
static void moveCombo (BasicCell *bcell, int phys_row, int phys_col);
|
||||
static void destroyCombo (BasicCell *bcell);
|
||||
static void setComboValue (BasicCell *bcell, const char *value);
|
||||
static const char * enterCombo (BasicCell *bcell, const char *value);
|
||||
static const char * leaveCombo (BasicCell *bcell, const char *value);
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
ComboCell *xaccMallocComboCell (void)
|
||||
{
|
||||
ComboCell * cell;
|
||||
cell = (ComboCell *) malloc (sizeof (ComboCell));
|
||||
xaccInitComboCell (cell);
|
||||
return cell;
|
||||
}
|
||||
|
||||
void xaccInitComboCell (ComboCell *cell)
|
||||
{
|
||||
xaccInitBasicCell ( &(cell->cell));
|
||||
cell->cell.realize = realizeCombo;
|
||||
cell->cell.set_value = setComboValue;
|
||||
cell->cell.destroy = destroyCombo;
|
||||
{
|
||||
PopBox *box = (PopBox *) malloc (sizeof (PopBox));
|
||||
box->table = NULL;
|
||||
box->menustrings = NULL;
|
||||
box->combobox = GTK_COMBO(gtk_combo_new());
|
||||
gtk_widget_ref(GTK_WIDGET(box->combobox));
|
||||
gtk_combo_set_value_in_list(box->combobox, 1, 0);
|
||||
gtk_widget_show(GTK_WIDGET(box->combobox));
|
||||
cell->cell.gui_private = box;
|
||||
}
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
void destroyCombo (BasicCell *bcell)
|
||||
{
|
||||
ComboCell *cell;
|
||||
|
||||
cell = (ComboCell *) bcell;
|
||||
|
||||
if (!(cell->cell.realize)) {
|
||||
PopBox *box = (PopBox *) (cell->cell.gui_private);
|
||||
gtk_container_remove(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->combobox));
|
||||
gtk_container_add(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->table->entry_widget));
|
||||
|
||||
/* allow the widget to be shown again */
|
||||
cell->cell.realize = realizeCombo;
|
||||
cell->cell.move = NULL;
|
||||
cell->cell.enter_cell = NULL;
|
||||
cell->cell.leave_cell = NULL;
|
||||
cell->cell.destroy = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
void xaccDestroyComboCell (ComboCell *cell)
|
||||
{
|
||||
PopBox *box = (PopBox *) (cell->cell.gui_private);
|
||||
|
||||
destroyCombo (&(cell->cell));
|
||||
|
||||
gtk_widget_destroy(GTK_WIDGET(box->combobox));
|
||||
gtk_widget_unref(GTK_WIDGET(box->combobox));
|
||||
|
||||
g_list_foreach(box->menustrings, (GFunc) g_free, NULL);
|
||||
g_list_free(box->menustrings);
|
||||
|
||||
free (box);
|
||||
box = NULL;
|
||||
|
||||
cell->cell.gui_private = NULL;
|
||||
cell->cell.realize = NULL;
|
||||
cell->cell.set_value = NULL;
|
||||
|
||||
xaccDestroyBasicCell ( &(cell->cell));
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
void
|
||||
xaccAddComboCellMenuItem (ComboCell *cell, char * menustr)
|
||||
{
|
||||
PopBox *box = (PopBox *) cell->cell.gui_private;
|
||||
GtkList *comboitems = GTK_LIST(box->combobox->list);
|
||||
|
||||
if (!cell) return;
|
||||
if (!menustr) return;
|
||||
|
||||
box->menustrings = g_list_append(box->menustrings, g_strdup(menustr));
|
||||
fprintf(stderr, "Adding item: %s\n", menustr);
|
||||
|
||||
gtk_combo_set_popdown_strings(box->combobox, box->menustrings);
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
/* not only do we set the cell contents, but we
|
||||
* make the gui reflect the right value too.
|
||||
*/
|
||||
|
||||
void
|
||||
xaccSetComboCellValue (ComboCell *cell, const char * str)
|
||||
{
|
||||
PopBox * box;
|
||||
|
||||
SET (&(cell->cell), str);
|
||||
box = (PopBox *) (cell->cell.gui_private);
|
||||
|
||||
if(!str) str = "";
|
||||
|
||||
gtk_entry_set_text(GTK_ENTRY(box->combobox->entry), str);
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static void
|
||||
setComboValue (BasicCell *_cell, const char *str)
|
||||
{
|
||||
ComboCell * cell = (ComboCell *) _cell;
|
||||
xaccSetComboCellValue (cell, str);
|
||||
}
|
||||
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
void realizeCombo (BasicCell *bcell, void *data, int pixel_width)
|
||||
{
|
||||
Table *table = (Table *) data;
|
||||
ComboCell *cell = (ComboCell *) bcell;
|
||||
PopBox *box = cell->cell.gui_private;
|
||||
|
||||
/* initialize gui-specific, private data */
|
||||
box->table = table;
|
||||
box->currow = -1;
|
||||
box->curcol = -1;
|
||||
|
||||
/* 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;
|
||||
|
||||
#if 0
|
||||
/* add callbacks to detect a selection */
|
||||
|
||||
XtAddCallback (combobox, XmNselectionCallback, selectCB, (XtPointer)cell);
|
||||
XtAddCallback (combobox, XmNunselectionCallback, selectCB, (XtPointer)cell);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
void moveCombo (BasicCell *bcell, int phys_row, int phys_col)
|
||||
{
|
||||
ComboCell *cell = (ComboCell *) bcell;
|
||||
PopBox *box = cell->cell.gui_private;
|
||||
box->currow = phys_row;
|
||||
box->curcol = phys_col;
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
const char * enterCombo (BasicCell *bcell, const char *value)
|
||||
{
|
||||
ComboCell *cell = (ComboCell *) bcell;
|
||||
PopBox *box = (PopBox *) (cell->cell.gui_private);
|
||||
int phys_row = box->currow;
|
||||
int phys_col = box->curcol;
|
||||
char *choice;
|
||||
|
||||
/* if the new position is valid, go to it,
|
||||
* otherwise, unmanage the widget */
|
||||
|
||||
if ((0 <= phys_row) && (0 <= phys_col)) {
|
||||
|
||||
/* Get the current cell contents, and set the
|
||||
* 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;
|
||||
|
||||
if(!choice) choice = "";
|
||||
|
||||
if(GTK_WIDGET(box->table->entry_widget)->parent ==
|
||||
box->table->entry_frame) {
|
||||
gtk_container_remove(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->table->entry_widget));
|
||||
}
|
||||
gtk_container_add(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->combobox));
|
||||
|
||||
gtk_entry_set_text(GTK_ENTRY(box->combobox->entry), choice);
|
||||
} else {
|
||||
gtk_container_remove(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->combobox));
|
||||
gtk_container_add(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->table->entry_widget));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
const char * leaveCombo (BasicCell *bcell, const char *value)
|
||||
{
|
||||
ComboCell *cell = (ComboCell *) bcell;
|
||||
PopBox *box = (PopBox *) (cell->cell.gui_private);
|
||||
gchar *text;
|
||||
|
||||
/* check for a valid mapping of the widget.
|
||||
Note that if the combo box value is set to
|
||||
a string that is not in the combo box menu
|
||||
(for example, the empty string ""), then the
|
||||
combobox will issue an XmCR_UNSELECT event.
|
||||
This typically happens while loading the array.
|
||||
We want to ignore these. */
|
||||
if ((0 > box->currow) || (0 > box->curcol)) return NULL;
|
||||
|
||||
text = gtk_entry_get_text(GTK_ENTRY(box->combobox->entry));
|
||||
|
||||
/* be sure to set the string into the matrix widget as well,
|
||||
so that we don't end up blanking out the cell when we
|
||||
unmap the combobox widget */
|
||||
gtk_clist_set_text(GTK_CLIST(box->table->table_widget),
|
||||
box->currow - 1,
|
||||
box->curcol,
|
||||
text);
|
||||
|
||||
SET (&(cell->cell), text);
|
||||
gtk_container_remove(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->combobox));
|
||||
gtk_container_add(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->table->entry_widget));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
#if 0
|
||||
static void selectCB (Widget w, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
ComboCell *cell;
|
||||
PopBox *box;
|
||||
char * choice = 0x0;
|
||||
|
||||
XmComboBoxSelectionCallbackStruct *selection =
|
||||
(XmComboBoxSelectionCallbackStruct *) cb;
|
||||
|
||||
cell = (ComboCell *) cd;
|
||||
box = (PopBox *) (cell->cell.gui_private);
|
||||
|
||||
/* check for a valid mapping of the widget.
|
||||
* Note that if the combo box value is set to
|
||||
* a string that is not in the combo box menu
|
||||
* (for example, the empty string ""), then the
|
||||
* combobox will issue an XmCR_UNSELECT event.
|
||||
* This typically happens while loading the array.
|
||||
* We want to ignore these. */
|
||||
if ((0 > box->currow) || (0 > box->curcol)) return;
|
||||
|
||||
/* check the reason, because the unslect callback
|
||||
* doesn't even have a value field! */
|
||||
if ( (XmCR_SINGLE_SELECT == selection->reason) ||
|
||||
(XmCR_BROWSE_SELECT == selection->reason) ) {
|
||||
choice = XmCvtXmStringToCT (selection->value);
|
||||
if (!choice) choice = XtNewString (""); /* null if blank/unselect */
|
||||
} else
|
||||
if (XmCR_UNSELECT == selection->reason) {
|
||||
choice = XtNewString ("");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/* be sure to set the string into the matrix widget as well,
|
||||
* so that we don't end up blanking out the cell when we
|
||||
* unmap the combobox widget */
|
||||
XbaeMatrixSetCell (box->parent, box->currow, box->curcol, choice);
|
||||
SET (&(cell->cell), choice);
|
||||
XtFree (choice);
|
||||
|
||||
/* a diffeent way of getting the user's selection ... */
|
||||
/* text = XmComboBoxGetString (ab->combobox); */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* =============== end of file =================== */
|
||||
/*
|
||||
* FILE:
|
||||
* combocell.c
|
||||
*
|
||||
* FUNCTION:
|
||||
* implement motif portions of a pull-down combo widget
|
||||
* embedded in a table cell.
|
||||
*
|
||||
* HISTORY:
|
||||
* Copyright (c) 1998 Linas Vepstas
|
||||
* Copyright (c) 1998 Rob Browning <rlb@cs.utexas.edu>
|
||||
*/
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
\********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "table-allgui.h"
|
||||
#include "table-gtk.h"
|
||||
|
||||
|
||||
#include "combocell-gtk.h"
|
||||
#include "combocell-gtkP.h"
|
||||
|
||||
/* Some GUI-private date that is inappropriate for
|
||||
* the public interface. In this impelmentation,
|
||||
* it holds gtk data that we need.
|
||||
*/
|
||||
|
||||
#define SET(cell,str) { \
|
||||
if ((cell)->value) free ((cell)->value); \
|
||||
(cell)->value = strdup (str); \
|
||||
(cell)->changed = 0xffffffff; \
|
||||
}
|
||||
|
||||
typedef struct _PopBox {
|
||||
GtkCombo *combobox;
|
||||
GList *menustrings;
|
||||
Table *table;
|
||||
int currow;
|
||||
int curcol;
|
||||
} PopBox;
|
||||
|
||||
//static void selectCB (Widget w, XtPointer cd, XtPointer cb );
|
||||
|
||||
static void realizeCombo (BasicCell *bcell, void *w, int width);
|
||||
static void moveCombo (BasicCell *bcell, int phys_row, int phys_col);
|
||||
static void destroyCombo (BasicCell *bcell);
|
||||
static void setComboValue (BasicCell *bcell, const char *value);
|
||||
static const char * enterCombo (BasicCell *bcell, const char *value);
|
||||
static const char * leaveCombo (BasicCell *bcell, const char *value);
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
ComboCell *xaccMallocComboCell (void)
|
||||
{
|
||||
ComboCell * cell;
|
||||
cell = (ComboCell *) malloc (sizeof (ComboCell));
|
||||
xaccInitComboCell (cell);
|
||||
return cell;
|
||||
}
|
||||
|
||||
void xaccInitComboCell (ComboCell *cell)
|
||||
{
|
||||
xaccInitBasicCell ( &(cell->cell));
|
||||
cell->cell.realize = realizeCombo;
|
||||
cell->cell.set_value = setComboValue;
|
||||
cell->cell.destroy = destroyCombo;
|
||||
{
|
||||
PopBox *box = (PopBox *) malloc (sizeof (PopBox));
|
||||
box->table = NULL;
|
||||
box->menustrings = NULL;
|
||||
box->combobox = GTK_COMBO(gtk_combo_new());
|
||||
gtk_widget_ref(GTK_WIDGET(box->combobox));
|
||||
gtk_combo_set_value_in_list(box->combobox, 1, 0);
|
||||
gtk_widget_show(GTK_WIDGET(box->combobox));
|
||||
cell->cell.gui_private = box;
|
||||
}
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
void destroyCombo (BasicCell *bcell)
|
||||
{
|
||||
ComboCell *cell;
|
||||
|
||||
cell = (ComboCell *) bcell;
|
||||
|
||||
if (!(cell->cell.realize)) {
|
||||
PopBox *box = (PopBox *) (cell->cell.gui_private);
|
||||
gtk_container_remove(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->combobox));
|
||||
gtk_container_add(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->table->entry_widget));
|
||||
|
||||
/* allow the widget to be shown again */
|
||||
cell->cell.realize = realizeCombo;
|
||||
cell->cell.move = NULL;
|
||||
cell->cell.enter_cell = NULL;
|
||||
cell->cell.leave_cell = NULL;
|
||||
cell->cell.destroy = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
void xaccDestroyComboCell (ComboCell *cell)
|
||||
{
|
||||
PopBox *box = (PopBox *) (cell->cell.gui_private);
|
||||
|
||||
destroyCombo (&(cell->cell));
|
||||
|
||||
gtk_widget_destroy(GTK_WIDGET(box->combobox));
|
||||
gtk_widget_unref(GTK_WIDGET(box->combobox));
|
||||
|
||||
g_list_foreach(box->menustrings, (GFunc) g_free, NULL);
|
||||
g_list_free(box->menustrings);
|
||||
|
||||
free (box);
|
||||
box = NULL;
|
||||
|
||||
cell->cell.gui_private = NULL;
|
||||
cell->cell.realize = NULL;
|
||||
cell->cell.set_value = NULL;
|
||||
|
||||
xaccDestroyBasicCell ( &(cell->cell));
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
void
|
||||
xaccAddComboCellMenuItem (ComboCell *cell, char * menustr)
|
||||
{
|
||||
PopBox *box = (PopBox *) cell->cell.gui_private;
|
||||
GtkList *comboitems = GTK_LIST(box->combobox->list);
|
||||
|
||||
if (!cell) return;
|
||||
if (!menustr) return;
|
||||
|
||||
box->menustrings = g_list_append(box->menustrings, g_strdup(menustr));
|
||||
fprintf(stderr, "Adding item: %s\n", menustr);
|
||||
|
||||
gtk_combo_set_popdown_strings(box->combobox, box->menustrings);
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
/* not only do we set the cell contents, but we
|
||||
* make the gui reflect the right value too.
|
||||
*/
|
||||
|
||||
void
|
||||
xaccSetComboCellValue (ComboCell *cell, const char * str)
|
||||
{
|
||||
PopBox * box;
|
||||
|
||||
SET (&(cell->cell), str);
|
||||
box = (PopBox *) (cell->cell.gui_private);
|
||||
|
||||
if(!str) str = "";
|
||||
|
||||
gtk_entry_set_text(GTK_ENTRY(box->combobox->entry), str);
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static void
|
||||
setComboValue (BasicCell *_cell, const char *str)
|
||||
{
|
||||
ComboCell * cell = (ComboCell *) _cell;
|
||||
xaccSetComboCellValue (cell, str);
|
||||
}
|
||||
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
void realizeCombo (BasicCell *bcell, void *data, int pixel_width)
|
||||
{
|
||||
Table *table = (Table *) data;
|
||||
ComboCell *cell = (ComboCell *) bcell;
|
||||
PopBox *box = cell->cell.gui_private;
|
||||
|
||||
/* initialize gui-specific, private data */
|
||||
box->table = table;
|
||||
box->currow = -1;
|
||||
box->curcol = -1;
|
||||
|
||||
/* 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;
|
||||
|
||||
#if 0
|
||||
/* add callbacks to detect a selection */
|
||||
|
||||
XtAddCallback (combobox, XmNselectionCallback, selectCB, (XtPointer)cell);
|
||||
XtAddCallback (combobox, XmNunselectionCallback, selectCB, (XtPointer)cell);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
void moveCombo (BasicCell *bcell, int phys_row, int phys_col)
|
||||
{
|
||||
ComboCell *cell = (ComboCell *) bcell;
|
||||
PopBox *box = cell->cell.gui_private;
|
||||
box->currow = phys_row;
|
||||
box->curcol = phys_col;
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
const char * enterCombo (BasicCell *bcell, const char *value)
|
||||
{
|
||||
ComboCell *cell = (ComboCell *) bcell;
|
||||
PopBox *box = (PopBox *) (cell->cell.gui_private);
|
||||
int phys_row = box->currow;
|
||||
int phys_col = box->curcol;
|
||||
char *choice;
|
||||
|
||||
/* if the new position is valid, go to it,
|
||||
* otherwise, unmanage the widget */
|
||||
|
||||
if ((0 <= phys_row) && (0 <= phys_col)) {
|
||||
|
||||
/* Get the current cell contents, and set the
|
||||
* 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;
|
||||
|
||||
if(!choice) choice = "";
|
||||
|
||||
if(GTK_WIDGET(box->table->entry_widget)->parent ==
|
||||
box->table->entry_frame) {
|
||||
gtk_container_remove(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->table->entry_widget));
|
||||
}
|
||||
gtk_container_add(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->combobox));
|
||||
|
||||
gtk_entry_set_text(GTK_ENTRY(box->combobox->entry), choice);
|
||||
} else {
|
||||
gtk_container_remove(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->combobox));
|
||||
gtk_container_add(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->table->entry_widget));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
const char * leaveCombo (BasicCell *bcell, const char *value)
|
||||
{
|
||||
ComboCell *cell = (ComboCell *) bcell;
|
||||
PopBox *box = (PopBox *) (cell->cell.gui_private);
|
||||
gchar *text;
|
||||
|
||||
/* check for a valid mapping of the widget.
|
||||
Note that if the combo box value is set to
|
||||
a string that is not in the combo box menu
|
||||
(for example, the empty string ""), then the
|
||||
combobox will issue an XmCR_UNSELECT event.
|
||||
This typically happens while loading the array.
|
||||
We want to ignore these. */
|
||||
if ((0 > box->currow) || (0 > box->curcol)) return NULL;
|
||||
|
||||
text = gtk_entry_get_text(GTK_ENTRY(box->combobox->entry));
|
||||
|
||||
/* be sure to set the string into the matrix widget as well,
|
||||
so that we don't end up blanking out the cell when we
|
||||
unmap the combobox widget */
|
||||
gtk_clist_set_text(GTK_CLIST(box->table->table_widget),
|
||||
box->currow - 1,
|
||||
box->curcol,
|
||||
text);
|
||||
|
||||
SET (&(cell->cell), text);
|
||||
gtk_container_remove(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->combobox));
|
||||
gtk_container_add(GTK_CONTAINER(box->table->entry_frame),
|
||||
GTK_WIDGET(box->table->entry_widget));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
#if 0
|
||||
static void selectCB (Widget w, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
ComboCell *cell;
|
||||
PopBox *box;
|
||||
char * choice = 0x0;
|
||||
|
||||
XmComboBoxSelectionCallbackStruct *selection =
|
||||
(XmComboBoxSelectionCallbackStruct *) cb;
|
||||
|
||||
cell = (ComboCell *) cd;
|
||||
box = (PopBox *) (cell->cell.gui_private);
|
||||
|
||||
/* check for a valid mapping of the widget.
|
||||
* Note that if the combo box value is set to
|
||||
* a string that is not in the combo box menu
|
||||
* (for example, the empty string ""), then the
|
||||
* combobox will issue an XmCR_UNSELECT event.
|
||||
* This typically happens while loading the array.
|
||||
* We want to ignore these. */
|
||||
if ((0 > box->currow) || (0 > box->curcol)) return;
|
||||
|
||||
/* check the reason, because the unslect callback
|
||||
* doesn't even have a value field! */
|
||||
if ( (XmCR_SINGLE_SELECT == selection->reason) ||
|
||||
(XmCR_BROWSE_SELECT == selection->reason) ) {
|
||||
choice = XmCvtXmStringToCT (selection->value);
|
||||
if (!choice) choice = XtNewString (""); /* null if blank/unselect */
|
||||
} else
|
||||
if (XmCR_UNSELECT == selection->reason) {
|
||||
choice = XtNewString ("");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/* be sure to set the string into the matrix widget as well,
|
||||
* so that we don't end up blanking out the cell when we
|
||||
* unmap the combobox widget */
|
||||
XbaeMatrixSetCell (box->parent, box->currow, box->curcol, choice);
|
||||
SET (&(cell->cell), choice);
|
||||
XtFree (choice);
|
||||
|
||||
/* a diffeent way of getting the user's selection ... */
|
||||
/* text = XmComboBoxGetString (ab->combobox); */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* =============== end of file =================== */
|
112
src/register/combocell-gtk.h
Normal file
112
src/register/combocell-gtk.h
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* FILE:
|
||||
* combocell.h
|
||||
*
|
||||
* FUNCTION:
|
||||
* The ComboCell object implements a cell handler with a
|
||||
* "combination-box" pull-down menu in it.
|
||||
*
|
||||
* On output, the currently selected menu item is displayed.
|
||||
* On input, the user can select from a list in the pull-down menu,
|
||||
* or use the keyboard to slect a menu entry by typing the first
|
||||
* few menu characters.
|
||||
*
|
||||
* METHODS:
|
||||
* The xaccAddComboCellMenuItem() method can be used to add a menu
|
||||
* item to the list.
|
||||
*
|
||||
*
|
||||
* HISTORY:
|
||||
* Created Jan 1998 Linas Vepstas
|
||||
* Copyright (c) 1998 Linas Vepstas
|
||||
*/
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
\********************************************************************/
|
||||
|
||||
#ifndef __XACC_COMBO_CELL_H__
|
||||
#define __XACC_COMBO_CELL_H__
|
||||
|
||||
#include "basiccell.h"
|
||||
|
||||
typedef struct _ComboCell ComboCell;
|
||||
|
||||
ComboCell * xaccMallocComboCell (void);
|
||||
void xaccInitComboCell (ComboCell *);
|
||||
void xaccDestroyComboCell (ComboCell *);
|
||||
|
||||
void xaccSetComboCellValue (ComboCell *, const char *);
|
||||
|
||||
void xaccAddComboCellMenuItem (ComboCell *, char * menustr);
|
||||
|
||||
#endif /* __XACC_COMBO_CELL_H__ */
|
||||
|
||||
/* --------------- end of file ---------------------- */
|
||||
/*
|
||||
* FILE:
|
||||
* combocell.h
|
||||
*
|
||||
* FUNCTION:
|
||||
* The ComboCell object implements a cell handler with a
|
||||
* "combination-box" pull-down menu in it.
|
||||
*
|
||||
* On output, the currently selected menu item is displayed.
|
||||
* On input, the user can select from a list in the pull-down menu,
|
||||
* or use the keyboard to slect a menu entry by typing the first
|
||||
* few menu characters.
|
||||
*
|
||||
* METHODS:
|
||||
* The xaccAddComboCellMenuItem() method can be used to add a menu
|
||||
* item to the list.
|
||||
*
|
||||
*
|
||||
* HISTORY:
|
||||
* Created Jan 1998 Linas Vepstas
|
||||
* Copyright (c) 1998 Linas Vepstas
|
||||
*/
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
\********************************************************************/
|
||||
|
||||
#ifndef __XACC_COMBO_CELL_H__
|
||||
#define __XACC_COMBO_CELL_H__
|
||||
|
||||
#include "basiccell.h"
|
||||
|
||||
typedef struct _ComboCell ComboCell;
|
||||
|
||||
ComboCell * xaccMallocComboCell (void);
|
||||
void xaccInitComboCell (ComboCell *);
|
||||
void xaccDestroyComboCell (ComboCell *);
|
||||
|
||||
void xaccSetComboCellValue (ComboCell *, const char *);
|
||||
|
||||
void xaccAddComboCellMenuItem (ComboCell *, char * menustr);
|
||||
|
||||
#endif /* __XACC_COMBO_CELL_H__ */
|
||||
|
||||
/* --------------- end of file ---------------------- */
|
102
src/register/combocell-gtkP.h
Normal file
102
src/register/combocell-gtkP.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* FILE:
|
||||
* combocell-gtkP.h
|
||||
*
|
||||
* FUNCTION:
|
||||
* The ComboCell object implements a cell handler with a
|
||||
* "combination-box" pull-down menu in it.
|
||||
*
|
||||
* On output, the currently selected menu item is displayed.
|
||||
* On input, the user can select from a list in the pull-down menu,
|
||||
* or use the keyboard to slect a menu entry by typing the first
|
||||
* few menu characters.
|
||||
*
|
||||
* METHODS:
|
||||
* The xaccAddComboCellMenuItem() method can be used to add a menu
|
||||
* item to the list.
|
||||
*
|
||||
*
|
||||
* HISTORY:
|
||||
* Created Jan 1998 Linas Vepstas
|
||||
* Copyright (c) 1998 Linas Vepstas
|
||||
* Copyright (c) 1998 Rob Browning <rlb@cs.utexas.edu>
|
||||
*/
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
\********************************************************************/
|
||||
|
||||
#ifndef __XACC_COMBO_CELL_P_H__
|
||||
#define __XACC_COMBO_CELL_P_H__
|
||||
|
||||
#include "basiccell.h"
|
||||
|
||||
struct _ComboCell {
|
||||
BasicCell cell;
|
||||
};
|
||||
|
||||
#endif /* __XACC_COMBO_CELL_P_H__ */
|
||||
|
||||
/* --------------- end of file ---------------------- */
|
||||
/*
|
||||
* FILE:
|
||||
* combocell-gtkP.h
|
||||
*
|
||||
* FUNCTION:
|
||||
* The ComboCell object implements a cell handler with a
|
||||
* "combination-box" pull-down menu in it.
|
||||
*
|
||||
* On output, the currently selected menu item is displayed.
|
||||
* On input, the user can select from a list in the pull-down menu,
|
||||
* or use the keyboard to slect a menu entry by typing the first
|
||||
* few menu characters.
|
||||
*
|
||||
* METHODS:
|
||||
* The xaccAddComboCellMenuItem() method can be used to add a menu
|
||||
* item to the list.
|
||||
*
|
||||
*
|
||||
* HISTORY:
|
||||
* Created Jan 1998 Linas Vepstas
|
||||
* Copyright (c) 1998 Linas Vepstas
|
||||
* Copyright (c) 1998 Rob Browning <rlb@cs.utexas.edu>
|
||||
*/
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
\********************************************************************/
|
||||
|
||||
#ifndef __XACC_COMBO_CELL_P_H__
|
||||
#define __XACC_COMBO_CELL_P_H__
|
||||
|
||||
#include "basiccell.h"
|
||||
|
||||
struct _ComboCell {
|
||||
BasicCell cell;
|
||||
};
|
||||
|
||||
#endif /* __XACC_COMBO_CELL_P_H__ */
|
||||
|
||||
/* --------------- end of file ---------------------- */
|
@ -30,11 +30,9 @@
|
||||
|
||||
#include <X11/keysym.h>
|
||||
|
||||
#ifdef MOTIF
|
||||
#include <Xm/Xm.h>
|
||||
#include <ComboBox.h>
|
||||
#include <Xbae/Matrix.h>
|
||||
#endif
|
||||
|
||||
#include "combocell.h"
|
||||
|
||||
@ -43,8 +41,6 @@
|
||||
* it holds XtMotif data that we need.
|
||||
*/
|
||||
|
||||
#ifdef MOTIF
|
||||
|
||||
typedef struct _PopBox {
|
||||
Widget combobox;
|
||||
Widget parent; /* the parent table widget */
|
||||
@ -62,27 +58,12 @@ static void setComboValue (BasicCell *bcell, const char *value);
|
||||
static const char * enterCombo (BasicCell *bcell, const char *value);
|
||||
static const char * leaveCombo (BasicCell *bcell, const char *value);
|
||||
|
||||
#endif
|
||||
|
||||
#define SET(cell,str) { \
|
||||
if ((cell)->value) free ((cell)->value); \
|
||||
(cell)->value = strdup (str); \
|
||||
(cell)->changed = 0xffffffff; \
|
||||
}
|
||||
|
||||
#ifdef GNOME
|
||||
|
||||
typedef struct _PopBox {
|
||||
int currow;
|
||||
int curcol;
|
||||
} PopBox;
|
||||
|
||||
void xaccDestroyComboCell (ComboCell *cell) { }
|
||||
void xaccAddComboCellMenuItem (ComboCell *cell, char * menustr) {}
|
||||
void xaccInitComboCell (ComboCell *cell) {}
|
||||
|
||||
#endif
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
ComboCell *xaccMallocComboCell (void)
|
||||
@ -93,8 +74,6 @@ ComboCell *xaccMallocComboCell (void)
|
||||
return cell;
|
||||
}
|
||||
|
||||
#ifndef GNOME
|
||||
|
||||
void xaccInitComboCell (ComboCell *cell)
|
||||
{
|
||||
xaccInitBasicCell ( &(cell->cell));
|
||||
@ -207,8 +186,6 @@ xaccAddComboCellMenuItem (ComboCell *cell, char * menustr)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* =============================================== */
|
||||
/* not only do we set the cell contents, but we
|
||||
* make the gui reflect the right value too.
|
||||
@ -226,7 +203,6 @@ xaccSetComboCellValue (ComboCell *cell, const char * str)
|
||||
* If so, then be sure to bail out now. */
|
||||
if (!box) return;
|
||||
|
||||
#ifndef GNOME
|
||||
if (str) {
|
||||
if (0x0 != str[0]) {
|
||||
XmString choosen;
|
||||
@ -250,7 +226,6 @@ xaccSetComboCellValue (ComboCell *cell, const char * str)
|
||||
XbaeMatrixSetCell (box->parent, box->currow, box->curcol, "");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
@ -262,8 +237,6 @@ setComboValue (BasicCell *_cell, const char *str)
|
||||
xaccSetComboCellValue (cell, str);
|
||||
}
|
||||
|
||||
#ifndef GNOME
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
@ -547,6 +520,527 @@ static void dropDownCB (Widget w, XtPointer cd, XtPointer cb )
|
||||
#endif /* USE_COMPLEX_TRAVERSAL_LOGIC */
|
||||
}
|
||||
|
||||
#endif /* #ifndef GNOME */
|
||||
/* =============== end of file =================== */
|
||||
/*
|
||||
* FILE:
|
||||
* combocell.c
|
||||
*
|
||||
* FUNCTION:
|
||||
* implement motif portions of a pull-down combo widget
|
||||
* embedded in a table cell.
|
||||
*
|
||||
* HISTORY:
|
||||
* Copyright (c) 1998 Linas Vepstas
|
||||
*/
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
\********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <X11/keysym.h>
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <ComboBox.h>
|
||||
#include <Xbae/Matrix.h>
|
||||
|
||||
#include "combocell.h"
|
||||
|
||||
/* Some GUI-private date that is inappropriate for
|
||||
* the public interface. In this impelmentation,
|
||||
* it holds XtMotif data that we need.
|
||||
*/
|
||||
|
||||
typedef struct _PopBox {
|
||||
Widget combobox;
|
||||
Widget parent; /* the parent table widget */
|
||||
int currow;
|
||||
int curcol;
|
||||
} PopBox;
|
||||
|
||||
|
||||
static void selectCB (Widget w, XtPointer cd, XtPointer cb );
|
||||
static void dropDownCB (Widget w, XtPointer cd, XtPointer cb );
|
||||
static void realizeCombo (BasicCell *bcell, void *w, int width);
|
||||
static void moveCombo (BasicCell *bcell, int phys_row, int phys_col);
|
||||
static void destroyCombo (BasicCell *bcell);
|
||||
static void setComboValue (BasicCell *bcell, const char *value);
|
||||
static const char * enterCombo (BasicCell *bcell, const char *value);
|
||||
static const char * leaveCombo (BasicCell *bcell, const char *value);
|
||||
|
||||
#define SET(cell,str) { \
|
||||
if ((cell)->value) free ((cell)->value); \
|
||||
(cell)->value = strdup (str); \
|
||||
(cell)->changed = 0xffffffff; \
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
ComboCell *xaccMallocComboCell (void)
|
||||
{
|
||||
ComboCell * cell;
|
||||
cell = (ComboCell *) malloc (sizeof (ComboCell));
|
||||
xaccInitComboCell (cell);
|
||||
return cell;
|
||||
}
|
||||
|
||||
void xaccInitComboCell (ComboCell *cell)
|
||||
{
|
||||
xaccInitBasicCell ( &(cell->cell));
|
||||
cell->cell.realize = realizeCombo;
|
||||
cell->cell.set_value = setComboValue;
|
||||
cell->cell.destroy = destroyCombo;
|
||||
cell->menuitems = (char **) malloc (sizeof (char *));
|
||||
cell->menuitems[0] = NULL;
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
void destroyCombo (BasicCell *bcell)
|
||||
{
|
||||
ComboCell *cell;
|
||||
|
||||
cell = (ComboCell *) bcell;
|
||||
|
||||
/* the realize callback will be null if the cell
|
||||
* gui has been realized. Therefore, if its null,
|
||||
* destroy the gui
|
||||
*/
|
||||
if (!(cell->cell.realize)) {
|
||||
PopBox *box;
|
||||
|
||||
box = (PopBox *) (cell->cell.gui_private);
|
||||
|
||||
if (box) {
|
||||
if (XtIsRealized(box->combobox)) {
|
||||
moveCombo (bcell, -1, -1);
|
||||
XtDestroyWidget (box->combobox);
|
||||
}
|
||||
free (box);
|
||||
}
|
||||
|
||||
/* allow the widget to be created again */
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
void xaccDestroyComboCell (ComboCell *cell)
|
||||
{
|
||||
int n = 0;
|
||||
char ** arr;
|
||||
|
||||
destroyCombo (&(cell->cell));
|
||||
|
||||
/* free malloced memory */
|
||||
arr = cell->menuitems;
|
||||
while (arr[n]) {
|
||||
free (arr[n]);
|
||||
n ++;
|
||||
}
|
||||
free (arr);
|
||||
cell->menuitems = NULL;
|
||||
|
||||
cell->cell.realize = NULL;
|
||||
cell->cell.set_value = NULL;
|
||||
|
||||
xaccDestroyBasicCell ( &(cell->cell));
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
void
|
||||
xaccAddComboCellMenuItem (ComboCell *cell, char * menustr)
|
||||
{
|
||||
int n = 0;
|
||||
char ** oldarr;
|
||||
|
||||
if (!cell) return;
|
||||
if (!menustr) return;
|
||||
|
||||
oldarr = cell->menuitems;
|
||||
while (oldarr[n]) n ++;
|
||||
|
||||
cell->menuitems = (char **) malloc ((n+2) *sizeof (char *));
|
||||
|
||||
n = 0;
|
||||
while (oldarr[n]) {
|
||||
cell->menuitems[n] = oldarr[n];
|
||||
n++;
|
||||
}
|
||||
cell->menuitems[n] = strdup (menustr);
|
||||
cell->menuitems[n+1] = NULL;
|
||||
|
||||
free (oldarr);
|
||||
|
||||
/* if we are adding the menu item to a cell that
|
||||
* is already realized, then alose add it to the
|
||||
* widget directly.
|
||||
*/
|
||||
if (!cell->cell.realize) {
|
||||
PopBox *box;
|
||||
XmString str;
|
||||
|
||||
box = (PopBox *) cell->cell.gui_private;
|
||||
str = XmStringCreateLtoR (menustr, XmSTRING_DEFAULT_CHARSET);
|
||||
XmComboBoxAddItem (box->combobox, str, 0);
|
||||
XmStringFree (str);
|
||||
}
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
/* not only do we set the cell contents, but we
|
||||
* make the gui reflect the right value too.
|
||||
*/
|
||||
|
||||
void
|
||||
xaccSetComboCellValue (ComboCell *cell, const char * str)
|
||||
{
|
||||
PopBox * box;
|
||||
|
||||
SET (&(cell->cell), str);
|
||||
box = (PopBox *) (cell->cell.gui_private);
|
||||
|
||||
/* we just might get called before the gui is initialized.
|
||||
* If so, then be sure to bail out now. */
|
||||
if (!box) return;
|
||||
|
||||
if (str) {
|
||||
if (0x0 != str[0]) {
|
||||
XmString choosen;
|
||||
/* convert String to XmString ... arghhh */
|
||||
choosen = XmCvtCTToXmString ((char *) str);
|
||||
XmComboBoxSelectItem (box->combobox, choosen, False);
|
||||
XmStringFree (choosen);
|
||||
} else {
|
||||
XmComboBoxClearItemSelection (box->combobox);
|
||||
}
|
||||
|
||||
if ((0 < box->currow) && (0 < box->curcol)) {
|
||||
/* be sure to set the string into the matrix widget as well,
|
||||
* so that we don't end up blanking out the cell when we
|
||||
* unmap the combobox widget */
|
||||
XbaeMatrixSetCell (box->parent, box->currow, box->curcol, (char *) str);
|
||||
}
|
||||
} else {
|
||||
XmComboBoxClearItemSelection (box->combobox);
|
||||
if ((0 < box->currow) && (0 < box->curcol)) {
|
||||
XbaeMatrixSetCell (box->parent, box->currow, box->curcol, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static void
|
||||
setComboValue (BasicCell *_cell, const char *str)
|
||||
{
|
||||
ComboCell * cell = (ComboCell *) _cell;
|
||||
xaccSetComboCellValue (cell, str);
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
void realizeCombo (BasicCell *bcell, void *w, int pixel_width)
|
||||
{
|
||||
ComboCell *cell;
|
||||
PopBox *box;
|
||||
Widget parent;
|
||||
Widget combobox;
|
||||
int width, drop_width;
|
||||
|
||||
parent = (Widget) w;
|
||||
cell = (ComboCell *) bcell;
|
||||
|
||||
/* initialize gui-specific, private data */
|
||||
box = (PopBox *) malloc (sizeof (PopBox));
|
||||
box->parent = parent;
|
||||
box->currow = -1;
|
||||
box->curcol = -1;
|
||||
|
||||
cell->cell.gui_private = (void *) box;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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
|
||||
("combocell", xmComboBoxWidgetClass, parent,
|
||||
XmNshadowThickness, 0, /* don't draw a shadow,
|
||||
* use bae shadows */
|
||||
XmNeditable, False, /* user can only pick from list */
|
||||
XmNsorted, False,
|
||||
XmNshowLabel, False,
|
||||
XmNmarginHeight, 0,
|
||||
XmNmarginWidth, 0,
|
||||
XmNselectionPolicy, XmSINGLE_SELECT,
|
||||
XmNvalue, "",
|
||||
XmNwidth, width,
|
||||
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);
|
||||
|
||||
/* unmap the widget by moving it to an invlid location */
|
||||
moveCombo (bcell, -1, -1);
|
||||
|
||||
/* add menu items */
|
||||
if (cell->menuitems) {
|
||||
char * menustr;
|
||||
int i=0;
|
||||
|
||||
menustr = cell->menuitems[i];
|
||||
while (menustr) {
|
||||
XmString str;
|
||||
str = XmStringCreateLtoR (menustr, XmSTRING_DEFAULT_CHARSET);
|
||||
XmComboBoxAddItem (box->combobox, str, 0);
|
||||
XmStringFree (str);
|
||||
i++;
|
||||
menustr = cell->menuitems[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
void moveCombo (BasicCell *bcell, int phys_row, int phys_col)
|
||||
{
|
||||
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);
|
||||
}
|
||||
box->currow = phys_row;
|
||||
box->curcol = phys_col;
|
||||
|
||||
XtUnmanageChild (box->combobox);
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
const char * enterCombo (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 <= phys_row) && (0 <= phys_col)) {
|
||||
|
||||
/* Get the current cell contents, and set the
|
||||
* 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. */
|
||||
if (choice) {
|
||||
if (0x0 != choice[0]) {
|
||||
/* convert String to XmString ... arghhh */
|
||||
choosen = XmCvtCTToXmString (choice);
|
||||
XmComboBoxSelectItem (box->combobox, choosen, False);
|
||||
XmStringFree (choosen);
|
||||
} else {
|
||||
XmComboBoxClearItemSelection (box->combobox);
|
||||
}
|
||||
} else {
|
||||
XmComboBoxClearItemSelection (box->combobox);
|
||||
}
|
||||
|
||||
/* set the cell widget */
|
||||
XbaeMatrixSetCellWidget (box->parent, phys_row, phys_col, box->combobox);
|
||||
|
||||
if (!XtIsManaged (box->combobox)) {
|
||||
XtManageChild (box->combobox);
|
||||
}
|
||||
|
||||
/* drop down the menu so that its ready to go. */
|
||||
XmComboBoxShowList (box->combobox);
|
||||
} else {
|
||||
XtUnmanageChild (box->combobox);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static
|
||||
const char * leaveCombo (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;
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
static void selectCB (Widget w, XtPointer cd, XtPointer cb )
|
||||
|
||||
{
|
||||
ComboCell *cell;
|
||||
PopBox *box;
|
||||
char * choice = 0x0;
|
||||
|
||||
XmComboBoxSelectionCallbackStruct *selection =
|
||||
(XmComboBoxSelectionCallbackStruct *) cb;
|
||||
|
||||
cell = (ComboCell *) cd;
|
||||
box = (PopBox *) (cell->cell.gui_private);
|
||||
|
||||
/* check for a valid mapping of the widget.
|
||||
* Note that if the combo box value is set to
|
||||
* a string that is not in the combo box menu
|
||||
* (for example, the empty string ""), then the
|
||||
* combobox will issue an XmCR_UNSELECT event.
|
||||
* This typically happens while loading the array.
|
||||
* We want to ignore these. */
|
||||
if ((0 > box->currow) || (0 > box->curcol)) return;
|
||||
|
||||
/* check the reason, because the unslect callback
|
||||
* doesn't even have a value field! */
|
||||
if ( (XmCR_SINGLE_SELECT == selection->reason) ||
|
||||
(XmCR_BROWSE_SELECT == selection->reason) ) {
|
||||
choice = XmCvtXmStringToCT (selection->value);
|
||||
if (!choice) choice = XtNewString (""); /* null if blank/unselect */
|
||||
} else
|
||||
if (XmCR_UNSELECT == selection->reason) {
|
||||
choice = XtNewString ("");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/* be sure to set the string into the matrix widget as well,
|
||||
* so that we don't end up blanking out the cell when we
|
||||
* unmap the combobox widget */
|
||||
XbaeMatrixSetCell (box->parent, box->currow, box->curcol, choice);
|
||||
SET (&(cell->cell), choice);
|
||||
XtFree (choice);
|
||||
|
||||
/* a diffeent way of getting the user's selection ... */
|
||||
/* text = XmComboBoxGetString (ab->combobox); */
|
||||
}
|
||||
|
||||
/* =============================================== */
|
||||
|
||||
/*********************************************************\
|
||||
* fix traversal by going back to the register window
|
||||
* when the pull-down menu goes away. We do NOT want to
|
||||
* go to the default next tab group, which is probably
|
||||
* some button not in the register window.
|
||||
\*********************************************************/
|
||||
|
||||
static void dropDownCB (Widget w, XtPointer cd, XtPointer cb )
|
||||
|
||||
{
|
||||
PopBox *ab = (PopBox *) cd;
|
||||
XmComboBoxDropDownCallbackStruct *ddcb =
|
||||
(XmComboBoxDropDownCallbackStruct *) cb;
|
||||
|
||||
if (XmCR_HIDE_LIST == ddcb->reason) {
|
||||
XmProcessTraversal(ab->parent, XmTRAVERSE_CURRENT);
|
||||
}
|
||||
|
||||
#ifdef USE_COMPLEX_TRAVERSAL_LOGIC
|
||||
/* continue traversal only under certain special curcumstances */
|
||||
if (XmCR_HIDE_LIST == ddcb->reason) {
|
||||
if (ddcb->event) {
|
||||
|
||||
/* don't leave if only a focus-out */
|
||||
if (FocusOut == ddcb->event->type) {
|
||||
XmProcessTraversal(ab->combobox, XmTRAVERSE_CURRENT);
|
||||
} else
|
||||
|
||||
/* if user selected something, then go to next cell */
|
||||
if (ButtonRelease == ddcb->event->type) {
|
||||
XmProcessTraversal(ab->reg, XmTRAVERSE_CURRENT);
|
||||
} else
|
||||
|
||||
/* if user hit the tab key, go to next cell */
|
||||
if ((KeyPress == ddcb->event->type) || (KeyRelease == ddcb->event->type
|
||||
)) {
|
||||
KeySym sim;
|
||||
XKeyEvent *kev = (XKeyEvent *) ddcb->event;
|
||||
sim = XLookupKeysym (kev, 0);
|
||||
if (XK_Tab == sim) { /* did the user hit the tab key ?? */
|
||||
XmProcessTraversal(ab->reg, XmTRAVERSE_CURRENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* USE_COMPLEX_TRAVERSAL_LOGIC */
|
||||
}
|
||||
|
||||
/* =============== end of file =================== */
|
@ -57,3 +57,62 @@ void xaccAddComboCellMenuItem (ComboCell *, char * menustr);
|
||||
#endif /* __XACC_COMBO_CELL_C__ */
|
||||
|
||||
/* --------------- end of file ---------------------- */
|
||||
/*
|
||||
* FILE:
|
||||
* combocell.h
|
||||
*
|
||||
* FUNCTION:
|
||||
* The ComboCell object implements a cell handler with a
|
||||
* "combination-box" pull-down menu in it.
|
||||
*
|
||||
* On output, the currently selected menu item is displayed.
|
||||
* On input, the user can select from a list in the pull-down menu,
|
||||
* or use the keyboard to slect a menu entry by typing the first
|
||||
* few menu characters.
|
||||
*
|
||||
* METHODS:
|
||||
* The xaccAddComboCellMenuItem() method can be used to add a menu
|
||||
* item to the list.
|
||||
*
|
||||
*
|
||||
* HISTORY:
|
||||
* Created Jan 1998 Linas Vepstas
|
||||
* Copyright (c) 1998 Linas Vepstas
|
||||
*/
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
\********************************************************************/
|
||||
|
||||
#ifndef __XACC_COMBO_CELL_C__
|
||||
#define __XACC_COMBO_CELL_C__
|
||||
|
||||
#include "basiccell.h"
|
||||
|
||||
typedef struct _ComboCell {
|
||||
BasicCell cell;
|
||||
char ** menuitems;
|
||||
} ComboCell;
|
||||
|
||||
ComboCell * xaccMallocComboCell (void);
|
||||
void xaccInitComboCell (ComboCell *);
|
||||
void xaccDestroyComboCell (ComboCell *);
|
||||
|
||||
void xaccSetComboCellValue (ComboCell *, const char *);
|
||||
|
||||
void xaccAddComboCellMenuItem (ComboCell *, char * menustr);
|
||||
|
||||
#endif /* __XACC_COMBO_CELL_C__ */
|
||||
|
||||
/* --------------- end of file ---------------------- */
|
103
src/register/left_arrow_small.xpm
Normal file
103
src/register/left_arrow_small.xpm
Normal file
@ -0,0 +1,103 @@
|
||||
/* XPM */
|
||||
static char * left_arrow_small_xpm[] = {
|
||||
"13 14 86 1",
|
||||
" c None",
|
||||
". c #AC9B8E",
|
||||
"+ c #8D5C3F",
|
||||
"@ c #A26A47",
|
||||
"# c #8F603E",
|
||||
"$ c #432214",
|
||||
"% c #8A4629",
|
||||
"& c #9E5A39",
|
||||
"* c #B6754F",
|
||||
"= c #8A5D42",
|
||||
"- c #974F31",
|
||||
"; c #A85D3A",
|
||||
"> c #AC603F",
|
||||
", c #B36D48",
|
||||
"' c #BA7A56",
|
||||
") c #684937",
|
||||
"! c #975135",
|
||||
"~ c #B66C48",
|
||||
"{ c #C57653",
|
||||
"] c #C27552",
|
||||
"^ c #C37650",
|
||||
"/ c #CB805C",
|
||||
"( c #C58664",
|
||||
"_ c #8F5036",
|
||||
": c #BE704D",
|
||||
"< c #CE825B",
|
||||
"[ c #D38560",
|
||||
"} c #D58761",
|
||||
"| c #D58862",
|
||||
"1 c #D78A63",
|
||||
"2 c #DE9471",
|
||||
"3 c #C98F73",
|
||||
"4 c #7F5846",
|
||||
"5 c #9D6F58",
|
||||
"6 c #C97B56",
|
||||
"7 c #D88A65",
|
||||
"8 c #DB8D67",
|
||||
"9 c #E19069",
|
||||
"0 c #E3946D",
|
||||
"a c #EA9B75",
|
||||
"b c #EBA47F",
|
||||
"c c #E59A75",
|
||||
"d c #AD6B4E",
|
||||
"e c #7D4E3A",
|
||||
"f c #E3B29A",
|
||||
"g c #D68963",
|
||||
"h c #E1916C",
|
||||
"i c #E79870",
|
||||
"j c #EA9E79",
|
||||
"k c #F0A682",
|
||||
"l c #E7A37F",
|
||||
"m c #BD7656",
|
||||
"n c #693924",
|
||||
"o c #26170F",
|
||||
"p c #040302",
|
||||
"q c #000000",
|
||||
"r c #E7B097",
|
||||
"s c #E3936A",
|
||||
"t c #ECA179",
|
||||
"u c #EFA781",
|
||||
"v c #EA9F7C",
|
||||
"w c #C77E5E",
|
||||
"x c #7E4833",
|
||||
"y c #3C2118",
|
||||
"z c #0B0604",
|
||||
"A c #E9AC90",
|
||||
"B c #EEA47F",
|
||||
"C c #EBA27D",
|
||||
"D c #BF7859",
|
||||
"E c #844830",
|
||||
"F c #402318",
|
||||
"G c #130B07",
|
||||
"H c #B09488",
|
||||
"I c #EFA685",
|
||||
"J c #CE8361",
|
||||
"K c #87462F",
|
||||
"L c #3C1F13",
|
||||
"M c #0F0805",
|
||||
"N c #E5BAA8",
|
||||
"O c #9F5E43",
|
||||
"P c #4F271B",
|
||||
"Q c #170D09",
|
||||
"R c #020100",
|
||||
"S c #684A3D",
|
||||
"T c #1B0F0A",
|
||||
"U c #050302",
|
||||
". ",
|
||||
"+@# ",
|
||||
"$%&*= ",
|
||||
" -;>,') ",
|
||||
" !~{]^/( ",
|
||||
" _:<[}|1234 ",
|
||||
" 567890abcde ",
|
||||
" fghijklmnopq",
|
||||
" rstuvwxyzqq ",
|
||||
" ABCDEFGqq ",
|
||||
"HIJKLMqq ",
|
||||
"NOPQRq ",
|
||||
"STUq ",
|
||||
" q "};
|
@ -37,16 +37,18 @@
|
||||
#define __XACC_REGISTER_H__
|
||||
|
||||
#include "basiccell.h"
|
||||
#include "combocell.h"
|
||||
#include "datecell.h"
|
||||
#include "quickfillcell.h"
|
||||
#include "pricecell.h"
|
||||
|
||||
#ifdef MOTIF
|
||||
#include "combocell-motif.h"
|
||||
#include "table-motif.h"
|
||||
#endif
|
||||
|
||||
#ifdef GNOME
|
||||
#include "combocell-gtk.h"
|
||||
#include "combocell-gtkP.h"
|
||||
#include "table-gtk.h"
|
||||
#endif
|
||||
|
||||
@ -91,7 +93,7 @@ struct _BasicRegister {
|
||||
/* the table itself that implements the underlying GUI. */
|
||||
Table * table;
|
||||
|
||||
/* the cursors that define thecurrently edited row */
|
||||
/* the cursors that define the currently edited row */
|
||||
CellBlock * cursor;
|
||||
CellBlock * header;
|
||||
|
||||
|
@ -27,9 +27,18 @@
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "cellblock.h"
|
||||
@ -37,10 +46,6 @@
|
||||
#include "table-gtk.h"
|
||||
|
||||
#if 0
|
||||
static void enterCB (GtkWidget * mw, gpointer cd, gpointer cb);
|
||||
static void leaveCB (GtkWidget * mw, gpointer cd, gpointer cb);
|
||||
static void modifyCB (GtkWidget * mw, gpointer cd, gpointer cb);
|
||||
static void traverseCB (GtkWidget * mw, gpointer cd, gpointer cb);
|
||||
|
||||
/* The XrmQuarks are used to figure out the direction of
|
||||
* traversal from cell to cell */
|
||||
@ -66,7 +71,14 @@ xaccMallocTable (void)
|
||||
void
|
||||
xaccInitTable (Table * table)
|
||||
{
|
||||
table->table_widget = 0;
|
||||
table->table_widget = NULL;
|
||||
table->entry_frame = NULL;
|
||||
table->entry_widget = NULL;
|
||||
|
||||
table->current_col = -1; /* coords ignoring header lines */
|
||||
table->current_row = -1;
|
||||
table->prev_entry_text = NULL;
|
||||
|
||||
table->next_tab_group = 0;
|
||||
|
||||
table->num_phys_rows = -1;
|
||||
@ -102,7 +114,14 @@ xaccDestroyTable (Table * table)
|
||||
xaccFreeTableEntries (table);
|
||||
|
||||
/* Let GTK know we're finished with this */
|
||||
gtk_widget_unref(table->table_widget);
|
||||
if(table->table_widget) gtk_widget_unref(table->table_widget);
|
||||
if(table->entry_frame) gtk_widget_unref(table->entry_frame);
|
||||
if(table->entry_widget) gtk_widget_unref(table->entry_widget);
|
||||
table->table_widget = NULL;
|
||||
table->entry_frame = NULL;
|
||||
table->entry_widget = NULL;
|
||||
|
||||
g_free(table->prev_entry_text); table->prev_entry_text = NULL;
|
||||
|
||||
/* intialize vars to null value so that any access is voided. */
|
||||
xaccInitTable (table);
|
||||
@ -140,107 +159,40 @@ xaccNextTabGroup (Table *table, GtkWidget * w)
|
||||
table->next_tab_group = w;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/* ==================================================== */
|
||||
/* this routine calls the individual cell callbacks */
|
||||
/* hack alert -- assumes that header is first cell */
|
||||
|
||||
static void
|
||||
cellCB (GtkWidget *mw, gpointer cd, gpointer cb)
|
||||
static int
|
||||
verify_cell_interaction_OK(Table *table, const int row, const int col)
|
||||
{
|
||||
Table *table;
|
||||
XbaeMatrixDefaultActionCallbackStruct *cbs;
|
||||
int row, col;
|
||||
int rel_row, rel_col;
|
||||
CellBlock *arr, *header;
|
||||
int invalid = 0;
|
||||
|
||||
table = (Table *) cd;
|
||||
arr = table->current_cursor;
|
||||
cbs = (XbaeMatrixDefaultActionCallbackStruct *) cb;
|
||||
|
||||
row = cbs->row;
|
||||
col = cbs->column;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* header rows cannot be modified */
|
||||
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;
|
||||
|
||||
/* check for a cell handler, but only if cell adress is valid */
|
||||
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 == (arr->cells[rel_row][rel_col])->input_output) {
|
||||
invalid = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
/* This was cellCB in a previous (Motif) life. We don't do nearly
|
||||
the checking that the Xbae code did because we presume that the
|
||||
row/column has to be valid if the user could have clicked on it.
|
||||
That's reasonable given the way that CList works. For one thing,
|
||||
header rows are handled separately. */
|
||||
|
||||
const CellBlock *arr = table->current_cursor;
|
||||
int rel_row, rel_col;
|
||||
int invalid = 0;
|
||||
|
||||
/* compute the cell location */
|
||||
rel_row = table->locators[row][col]->phys_row_offset;
|
||||
rel_col = table->locators[row][col]->phys_col_offset;
|
||||
|
||||
/* check for a cell handler, but only if cell adress is valid */
|
||||
/* GTK may not need all these checks, but they don't hurt */
|
||||
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 == (arr->cells[rel_row][rel_col])->input_output) {
|
||||
invalid = TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
invalid = TRUE;
|
||||
}
|
||||
|
||||
/* oops the callback failed for some reason ...
|
||||
* reject the enter/edit/leave and return */
|
||||
if (invalid) {
|
||||
switch (cbs->reason) {
|
||||
case XbaeEnterCellReason: {
|
||||
XbaeMatrixEnterCellCallbackStruct *ecbs;
|
||||
ecbs = (XbaeMatrixEnterCellCallbackStruct *) cbs;
|
||||
ecbs->doit = False;
|
||||
ecbs->map = False;
|
||||
break;
|
||||
}
|
||||
case XbaeModifyVerifyReason: {
|
||||
XbaeMatrixModifyVerifyCallbackStruct *mvcbs;
|
||||
mvcbs = (XbaeMatrixModifyVerifyCallbackStruct *) cbs;
|
||||
mvcbs->verify->doit = False;
|
||||
break;
|
||||
}
|
||||
case XbaeLeaveCellReason: {
|
||||
XbaeMatrixLeaveCellCallbackStruct *lcbs;
|
||||
lcbs = (XbaeMatrixLeaveCellCallbackStruct *) cbs;
|
||||
/* must set doit to true in order to be able to leave the cell */
|
||||
lcbs->doit = True;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* if we got to here, then there is a cell handler for
|
||||
* this cell. Dispatch for processing. */
|
||||
switch (cbs->reason) {
|
||||
case XbaeEnterCellReason: {
|
||||
xaccVerifyCursorPosition (table, row, col);
|
||||
enterCB (mw, cd, cb);
|
||||
break;
|
||||
}
|
||||
case XbaeModifyVerifyReason: {
|
||||
modifyCB (mw, cd, cb);
|
||||
break;
|
||||
}
|
||||
case XbaeLeaveCellReason: {
|
||||
leaveCB (mw, cd, cb);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return(!invalid);
|
||||
}
|
||||
|
||||
/* ==================================================== */
|
||||
@ -248,217 +200,285 @@ cellCB (GtkWidget *mw, gpointer cd, gpointer cb)
|
||||
* been performed. */
|
||||
|
||||
static void
|
||||
enterCB (GtkWidget * mw, gpointer cd, gpointer cb)
|
||||
cell_entered(Table *table, const int row, const int col)
|
||||
{
|
||||
Table *table;
|
||||
CellBlock *arr;
|
||||
XbaeMatrixEnterCellCallbackStruct *cbs;
|
||||
int row, col;
|
||||
int rel_row, rel_col;
|
||||
const char * (*enter) (BasicCell *, const char *);
|
||||
CellBlock *arr;
|
||||
int rel_row, rel_col;
|
||||
const char * (*enter) (BasicCell *, const char *);
|
||||
gchar *text;
|
||||
GtkCList *cl = GTK_CLIST(table->table_widget);
|
||||
|
||||
fprintf(stderr, "cell_entered: %d %d\n", row - 1, col);
|
||||
|
||||
gtk_clist_get_text(cl, row - 1, col, &text);
|
||||
text = g_strdup(text); /* This is OK and required b/c GTK kills the
|
||||
old pointer before using the one you
|
||||
give it. */
|
||||
|
||||
{
|
||||
GtkWidget *w = GTK_WIDGET(cl);
|
||||
GdkColor *background = &w->style->bg[GTK_STATE_NORMAL];
|
||||
GdkBitmap *mask;
|
||||
GdkPixmap *pm = gdk_pixmap_create_from_xpm(w->window, &mask, background,
|
||||
"/home/rlb/xacc/src/register/"
|
||||
"left_arrow_small.xpm");
|
||||
gtk_clist_set_pixtext(cl, row - 1, col, text, 2, pm, mask);
|
||||
gdk_pixmap_unref(pm);
|
||||
gdk_bitmap_unref(mask);
|
||||
}
|
||||
|
||||
gtk_frame_set_label(GTK_FRAME(table->entry_frame),
|
||||
cl->column[col].title);
|
||||
|
||||
table = (Table *) cd;
|
||||
/* Have to block and unblock here because we don't want a callback
|
||||
for this "edit" */
|
||||
{
|
||||
const guint handler_id =
|
||||
(guint) gtk_object_get_user_data(GTK_OBJECT(table->entry_widget));
|
||||
|
||||
gtk_signal_handler_block(GTK_OBJECT(table->entry_widget), handler_id);
|
||||
gtk_entry_set_text(GTK_ENTRY(table->entry_widget), text);
|
||||
gtk_signal_handler_unblock(GTK_OBJECT(table->entry_widget), handler_id);
|
||||
}
|
||||
|
||||
g_free(table->prev_entry_text);
|
||||
table->prev_entry_text = text;
|
||||
|
||||
fprintf(stderr,
|
||||
" current_cursor->phys: %d %d\n"
|
||||
" current_cursor->virt: %d %d\n"
|
||||
" text: %s\n",
|
||||
table->current_cursor_phys_row,
|
||||
table->current_cursor_phys_col,
|
||||
table->current_cursor_virt_row,
|
||||
table->current_cursor_virt_col,
|
||||
text);
|
||||
|
||||
xaccVerifyCursorPosition (table, row, col);
|
||||
|
||||
arr = table->current_cursor;
|
||||
cbs = (XbaeMatrixEnterCellCallbackStruct *) cb;
|
||||
|
||||
/* compute the cell location */
|
||||
row = cbs->row;
|
||||
col = cbs->column;
|
||||
|
||||
rel_row = table->locators[row][col]->phys_row_offset;
|
||||
rel_col = table->locators[row][col]->phys_col_offset;
|
||||
|
||||
printf ("enter %d %d \n", row, col);
|
||||
|
||||
/* since we are here, there must be a cell handler.
|
||||
* therefore, we accept entry into the cell by default,
|
||||
*/
|
||||
cbs->doit = True;
|
||||
cbs->map = True;
|
||||
|
||||
|
||||
/* 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;
|
||||
char *retval;
|
||||
|
||||
val = table->entries[row][col];
|
||||
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] = retval;
|
||||
(arr->cells[rel_row][rel_col])->changed = 0xffffffff;
|
||||
XbaeMatrixSetCell (mw, row, col, retval);
|
||||
XbaeMatrixRefreshCell (mw, row, col);
|
||||
|
||||
/* don't map a text widget */
|
||||
cbs->map = False;
|
||||
cbs->doit = False;
|
||||
}
|
||||
const char *val;
|
||||
char *retval;
|
||||
|
||||
val = table->entries[row][col];
|
||||
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] = retval;
|
||||
(arr->cells[rel_row][rel_col])->changed = 0xffffffff;
|
||||
|
||||
/* ??? Should this be setting the entry or the clist cell? */
|
||||
gtk_entry_set_text(GTK_ENTRY(table->entry_widget), retval);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* record this position as the cell that will be
|
||||
* traversed out of if a traverse even happens */
|
||||
table->prev_phys_traverse_row = row;
|
||||
table->prev_phys_traverse_col = col;
|
||||
}
|
||||
|
||||
static void
|
||||
compute_string_single_change(const gchar *a, const gchar *b, gchar **result) {
|
||||
/* Compute the change from a to b assuming that the changed region
|
||||
is contiguous. This is only a guess, the solution is
|
||||
ambiguous. */
|
||||
|
||||
const gint a_len = strlen(a);
|
||||
const gint b_len = strlen(b);
|
||||
const gchar *afptr = a, *bfptr = b;
|
||||
const gchar *arptr = a + a_len;
|
||||
const gchar *brptr = b + b_len;
|
||||
|
||||
while(*afptr && *bfptr && (*afptr == *bfptr)) {
|
||||
afptr++;
|
||||
bfptr++;
|
||||
}
|
||||
|
||||
while((arptr != afptr) && (brptr != bfptr) && (*arptr == *brptr)) {
|
||||
arptr--;
|
||||
brptr--;
|
||||
}
|
||||
if(a_len == b_len) brptr++;
|
||||
|
||||
if(bfptr == brptr) {
|
||||
/* deletion or nothing */
|
||||
*result = NULL;
|
||||
return;
|
||||
} else {
|
||||
const gint length = (brptr - bfptr);
|
||||
*result = (char *) g_malloc(length * sizeof(char) + 1);
|
||||
strncpy(*result, bfptr, length);
|
||||
(*result)[length] = '\0';
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================================================== */
|
||||
/* this routine calls the individual cell callbacks */
|
||||
|
||||
static void
|
||||
modifyCB (GtkWidget * mw, gpointer cd, gpointer cb)
|
||||
cell_modified(Table *table, const int row, const int col)
|
||||
{
|
||||
Table *table;
|
||||
CellBlock *arr;
|
||||
XbaeMatrixModifyVerifyCallbackStruct *cbs;
|
||||
int row, col;
|
||||
int rel_row, rel_col;
|
||||
const char * (*mv) (BasicCell *,
|
||||
const char *,
|
||||
const char *,
|
||||
const char *);
|
||||
const char *oldval, *change;
|
||||
char *newval;
|
||||
const char *retval;
|
||||
int len;
|
||||
|
||||
table = (Table *) cd;
|
||||
arr = table->current_cursor;
|
||||
cbs = (XbaeMatrixModifyVerifyCallbackStruct *) cb;
|
||||
CellBlock *arr;
|
||||
GtkEntry *entry = GTK_ENTRY(table->entry_widget);
|
||||
int rel_row, rel_col;
|
||||
const char * (*mv) (BasicCell *,
|
||||
const char *,
|
||||
const char *,
|
||||
const char *);
|
||||
const char *oldval, *newval, *retval, *final_text;
|
||||
gchar *change = NULL;
|
||||
|
||||
/* compute the cell location */
|
||||
row = cbs->row;
|
||||
col = cbs->column;
|
||||
rel_row = table->locators[row][col]->phys_row_offset;
|
||||
rel_col = table->locators[row][col]->phys_col_offset;
|
||||
arr = table->current_cursor;
|
||||
|
||||
/* compute the cell location */
|
||||
rel_row = table->locators[row][col]->phys_row_offset;
|
||||
rel_col = table->locators[row][col]->phys_col_offset;
|
||||
|
||||
/* accept edits by default, unless the cell handler rejects them */
|
||||
/* cbs->verify->doit = True; */
|
||||
|
||||
oldval = table->prev_entry_text;
|
||||
newval = strdup(gtk_entry_get_text(entry));
|
||||
final_text = newval;
|
||||
|
||||
if(oldval) compute_string_single_change(oldval, newval, &change);
|
||||
|
||||
/* accept edits by default, unless the cell handler rejects them */
|
||||
cbs->verify->doit = True;
|
||||
fprintf(stderr, " CHANGES: (%s -> %s) <=> [%s]\n",
|
||||
oldval, newval, change);
|
||||
|
||||
if(strcmp(newval, oldval) == 0) {
|
||||
g_free((gchar *) change);
|
||||
return;
|
||||
}
|
||||
|
||||
oldval = cbs->prev_text;
|
||||
change = cbs->verify->text->ptr;
|
||||
/* OK, if there is a callback for this cell, call it */
|
||||
mv = arr->cells[rel_row][rel_col]->modify_verify;
|
||||
|
||||
/* first, compute the newval string */
|
||||
len = 1;
|
||||
if (oldval) len += strlen (oldval);
|
||||
if (change) len += strlen (change);
|
||||
newval = (char *) malloc (len);
|
||||
|
||||
/* text may be inserted, or deleted, or replaced ... */
|
||||
newval[0] = 0;
|
||||
strncat (newval, oldval, cbs->verify->startPos);
|
||||
if (change) strcat (newval, change);
|
||||
strcat (newval, &oldval[(cbs->verify->endPos)]);
|
||||
|
||||
/* OK, if there is a callback for this cell, call it */
|
||||
mv = arr->cells[rel_row][rel_col]->modify_verify;
|
||||
if (mv) {
|
||||
retval = (*mv) (arr->cells[rel_row][rel_col], oldval, change, newval);
|
||||
|
||||
/* if the callback returned a non-null value, allow the edit */
|
||||
if (retval) {
|
||||
|
||||
/* update data. bounds check done earlier */
|
||||
free (table->entries[row][col]);
|
||||
table->entries[row][col] = (char *) retval;
|
||||
(arr->cells[rel_row][rel_col])->changed = 0xffffffff;
|
||||
|
||||
/* if the callback modified the display string,
|
||||
* update the display cell as well */
|
||||
if (retval != newval) {
|
||||
XbaeMatrixSetCell (mw, row, col, (char *) retval);
|
||||
XbaeMatrixRefreshCell (mw, row, col);
|
||||
XbaeMatrixSetCursorPosition (mw, (cbs->verify->endPos) +1);
|
||||
|
||||
/* the default update has already been overridden,
|
||||
* so don't allow Xbae to update */
|
||||
cbs->verify->doit = False;
|
||||
|
||||
/* avoid wasting memory */
|
||||
free (newval);
|
||||
}
|
||||
} else {
|
||||
/* NULL return value means the edit was rejected */
|
||||
cbs->verify->doit = False;
|
||||
|
||||
/* avoid wasting memory */
|
||||
free(newval);
|
||||
}
|
||||
} else {
|
||||
if (mv) {
|
||||
retval = (*mv) (arr->cells[rel_row][rel_col], oldval, change, newval);
|
||||
|
||||
/* if the callback returned a non-null value, allow the edit */
|
||||
if (retval) {
|
||||
|
||||
/* update data. bounds check done earlier */
|
||||
free (table->entries[row][col]);
|
||||
table->entries[row][col] = newval;
|
||||
table->entries[row][col] = (char *) retval;
|
||||
(arr->cells[rel_row][rel_col])->changed = 0xffffffff;
|
||||
}
|
||||
|
||||
/* if the callback modified the display string,
|
||||
* update the display cell as well */
|
||||
if (retval != newval) {
|
||||
{
|
||||
/* Don't want a signal for this change */
|
||||
const guint id =
|
||||
(guint) gtk_object_get_user_data(GTK_OBJECT(table->entry_widget));
|
||||
gtk_signal_handler_block(GTK_OBJECT(table->entry_widget), id);
|
||||
gtk_entry_set_text(entry, retval);
|
||||
gtk_signal_handler_unblock(GTK_OBJECT(table->entry_widget), id);
|
||||
}
|
||||
final_text = retval;
|
||||
/*XbaeMatrixSetCursorPosition (mw, (cbs->verify->endPos) +1);*/
|
||||
free((char *) newval);
|
||||
}
|
||||
} else {
|
||||
free((char *) newval);
|
||||
}
|
||||
} else {
|
||||
/* update data. bounds check done earlier */
|
||||
free (table->entries[row][col]);
|
||||
table->entries[row][col] = strdup(newval);
|
||||
(arr->cells[rel_row][rel_col])->changed = 0xffffffff;
|
||||
}
|
||||
g_free(table->prev_entry_text);
|
||||
table->prev_entry_text = g_strdup(final_text);
|
||||
g_free((gchar *) change);
|
||||
}
|
||||
|
||||
/* ==================================================== */
|
||||
|
||||
static void
|
||||
leaveCB (GtkWidget * mw, gpointer cd, gpointer cb)
|
||||
cell_left(Table *table, const int row, const int col)
|
||||
{
|
||||
Table *table;
|
||||
CellBlock *arr;
|
||||
XbaeMatrixLeaveCellCallbackStruct *cbs;
|
||||
int row, col;
|
||||
int rel_row, rel_col;
|
||||
const char * (*leave) (BasicCell *, const char *);
|
||||
char * newval;
|
||||
CellBlock *arr;
|
||||
int rel_row, rel_col;
|
||||
const char * (*leave) (BasicCell *, const char *);
|
||||
char * newval;
|
||||
const char *val;
|
||||
gchar *text;
|
||||
GdkBitmap *mask;
|
||||
GtkCList *cl = GTK_CLIST(table->table_widget);
|
||||
|
||||
table = (Table *) cd;
|
||||
arr = table->current_cursor;
|
||||
cbs = (XbaeMatrixLeaveCellCallbackStruct *) cb;
|
||||
fprintf(stderr, "cell_left: %d %d\n", row - 1, col);
|
||||
|
||||
/* compute the cell location */
|
||||
row = cbs->row;
|
||||
col = cbs->column;
|
||||
rel_row = table->locators[row][col]->phys_row_offset;
|
||||
rel_col = table->locators[row][col]->phys_col_offset;
|
||||
if(gtk_clist_get_pixtext(cl, row - 1, col, &text, NULL, NULL, &mask)) {
|
||||
/* we need to get rid of the pixmap -- this will only fail on the
|
||||
first click when there was no previous cell (but we default to
|
||||
0 0) */
|
||||
text = g_strdup(text); /* This is OK and required b/c we're about to
|
||||
kill this pointer via set_text. */
|
||||
gtk_clist_set_text(cl, row - 1, col, text);
|
||||
g_free(text);
|
||||
}
|
||||
|
||||
arr = table->current_cursor;
|
||||
|
||||
/* compute the cell location */
|
||||
rel_row = table->locators[row][col]->phys_row_offset;
|
||||
rel_col = table->locators[row][col]->phys_col_offset;
|
||||
|
||||
printf ("leave %d %d \n", row, col);
|
||||
val = gtk_entry_get_text(GTK_ENTRY(table->entry_widget));
|
||||
|
||||
/* OK, if there is a callback for this cell, call it */
|
||||
leave = arr->cells[rel_row][rel_col]->leave_cell;
|
||||
if (leave) {
|
||||
const char *retval;
|
||||
|
||||
retval = leave (arr->cells[rel_row][rel_col], val);
|
||||
|
||||
newval = (char *) retval;
|
||||
if (NULL == retval) newval = strdup (val);
|
||||
if (val == retval) newval = strdup (val);
|
||||
|
||||
/* if the leave() routine declared a new string, lets use it */
|
||||
if ( retval && (retval != val)) {
|
||||
gtk_clist_set_text(cl, row - 1, col, (gchar *) retval);
|
||||
}
|
||||
} else {
|
||||
newval = strdup(val);
|
||||
}
|
||||
|
||||
/* by default, accept whatever the final proposed edit is */
|
||||
cbs->doit = True;
|
||||
|
||||
/* OK, if there is a callback for this cell, call it */
|
||||
leave = arr->cells[rel_row][rel_col]->leave_cell;
|
||||
if (leave) {
|
||||
const char *val, *retval;
|
||||
|
||||
val = cbs->value;
|
||||
retval = leave (arr->cells[rel_row][rel_col], val);
|
||||
|
||||
newval = (char *) retval;
|
||||
if (NULL == retval) newval = strdup (val);
|
||||
if (val == retval) newval = strdup (val);
|
||||
|
||||
/* if the leave() routine declared a new string, lets use it */
|
||||
if ( retval && (retval != val)) {
|
||||
cbs->value = strdup (retval);
|
||||
}
|
||||
|
||||
} else {
|
||||
newval = strdup (cbs->value);
|
||||
}
|
||||
|
||||
/* save whatever was returned; but lets check for
|
||||
* changes to avoid roiling the cells too much */
|
||||
if (table->entries[row][col]) {
|
||||
if (strcmp (table->entries[row][col], newval)) {
|
||||
free (table->entries[row][col]);
|
||||
table->entries[row][col] = newval;
|
||||
(arr->cells[rel_row][rel_col])->changed = 0xffffffff;
|
||||
} else {
|
||||
/* leave() allocated memory, which we will not be using ... */
|
||||
free (newval);
|
||||
}
|
||||
} else {
|
||||
/* Commit the change to the clist when we leave the cell */
|
||||
gtk_clist_set_text(GTK_CLIST(table->table_widget), row - 1, col, newval);
|
||||
|
||||
/* save whatever was returned; but lets check for
|
||||
* changes to avoid roiling the cells too much */
|
||||
if (table->entries[row][col]) {
|
||||
if (strcmp (table->entries[row][col], newval)) {
|
||||
free (table->entries[row][col]);
|
||||
table->entries[row][col] = newval;
|
||||
(arr->cells[rel_row][rel_col])->changed = 0xffffffff;
|
||||
}
|
||||
} else {
|
||||
/* leave() allocated memory, which we will not be using ... */
|
||||
free(newval);
|
||||
}
|
||||
} else {
|
||||
table->entries[row][col] = newval;
|
||||
(arr->cells[rel_row][rel_col])->changed = 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/* ==================================================== */
|
||||
|
||||
@ -538,6 +558,58 @@ traverseCB (GtkWidget * mw, gpointer cd, gpointer cb)
|
||||
|
||||
#endif
|
||||
|
||||
static int counter;
|
||||
|
||||
static void
|
||||
table_edit_entry_cb(GtkEntry *entry, gpointer user_data) {
|
||||
Table *table = (Table *) user_data;
|
||||
const int row = table->current_row;
|
||||
const int col = table->current_col;
|
||||
|
||||
fprintf(stderr, "table_edit_entry_cb:\n");
|
||||
fprintf(stderr, " curpos: %d selstart %d selend %d has_select: %d\n",
|
||||
GTK_EDITABLE(entry)->current_pos,
|
||||
GTK_EDITABLE(entry)->selection_start_pos,
|
||||
GTK_EDITABLE(entry)->selection_end_pos,
|
||||
GTK_EDITABLE(entry)->has_selection
|
||||
);
|
||||
|
||||
if(!verify_cell_interaction_OK(table, row + 1, col)) return;
|
||||
|
||||
{
|
||||
const int xxx = counter++;
|
||||
printf(" cm: in %d\n", xxx);
|
||||
cell_modified(table, row + 1, col);
|
||||
printf(" cm: out %d\n", xxx);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
table_select_row_cb(GtkCList *cl, gint row, gint column, GdkEventButton *e,
|
||||
gpointer user_data) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================================================== */
|
||||
|
||||
GtkWidget *
|
||||
@ -546,12 +618,18 @@ xaccCreateTable (Table *table, GtkWidget * parent)
|
||||
CellBlock *curs;
|
||||
unsigned char * alignments;
|
||||
short * widths;
|
||||
GtkWidget * reg;
|
||||
int num_header_rows = 0;
|
||||
int i;
|
||||
|
||||
if (!table) return 0;
|
||||
|
||||
|
||||
if(table->table_widget != NULL) {
|
||||
fprintf(stderr,
|
||||
"Error: detected internal corruption in xaccCreateTable, "
|
||||
"aborting\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* if quarks have not yet been initialized for this
|
||||
* application, initialize them now. */
|
||||
@ -583,47 +661,94 @@ xaccCreateTable (Table *table, GtkWidget * parent)
|
||||
num_header_rows = 1;
|
||||
}
|
||||
|
||||
if(num_header_rows == 0) {
|
||||
reg = gtk_clist_new(table->num_phys_cols);
|
||||
} else {
|
||||
reg = gtk_clist_new_with_titles(table->num_phys_cols, table->entries[0]);
|
||||
gtk_clist_freeze(GTK_CLIST(reg));
|
||||
for(i = 0; i < table->num_phys_cols; i++) {
|
||||
{
|
||||
/* TODO: Handle unrefs in destructor */
|
||||
|
||||
/* Widths are in units of characters, not pixels, so we have
|
||||
this hack. It should be fixed later... */
|
||||
gtk_clist_set_column_width(GTK_CLIST(reg), i, widths[i] * 5);
|
||||
GtkWidget *vbox;
|
||||
GtkWidget * reg;
|
||||
|
||||
/* We don't ref this vbox because we never use it in our code again */
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
gtk_container_add(GTK_CONTAINER(parent), vbox);
|
||||
|
||||
if(num_header_rows == 0) {
|
||||
reg = gtk_clist_new(table->num_phys_cols);
|
||||
gtk_widget_ref(reg);
|
||||
} else {
|
||||
reg = gtk_clist_new_with_titles(table->num_phys_cols,
|
||||
table->entries[0]);
|
||||
gtk_widget_ref(reg);
|
||||
gtk_clist_freeze(GTK_CLIST(reg));
|
||||
for(i = 0; i < table->num_phys_cols; i++) {
|
||||
|
||||
/* Widths are in units of characters, not pixels, so we have
|
||||
this hack. It should be fixed later... */
|
||||
gtk_clist_set_column_width(GTK_CLIST(reg), i, widths[i] * 5);
|
||||
}
|
||||
gtk_clist_thaw(GTK_CLIST(reg));
|
||||
}
|
||||
|
||||
gtk_clist_freeze(GTK_CLIST(reg));
|
||||
for(i = num_header_rows; i < table->num_phys_rows; i++) {
|
||||
gtk_clist_append(GTK_CLIST(reg), table->entries[i]);
|
||||
}
|
||||
gtk_clist_set_selection_mode(GTK_CLIST(reg), GTK_SELECTION_BROWSE);
|
||||
gtk_clist_thaw(GTK_CLIST(reg));
|
||||
|
||||
/* size?
|
||||
alignments?
|
||||
grid type?
|
||||
shadow type?
|
||||
*/
|
||||
|
||||
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);
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(vbox), reg, TRUE, TRUE, 0);
|
||||
gtk_widget_show(reg);
|
||||
|
||||
table->table_widget = reg;
|
||||
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_clist_freeze(GTK_CLIST(reg));
|
||||
for(i = num_header_rows; i < table->num_phys_rows; i++) {
|
||||
gtk_clist_append(GTK_CLIST(reg), table->entries[i]);
|
||||
}
|
||||
gtk_clist_thaw(GTK_CLIST(reg));
|
||||
|
||||
/* size?
|
||||
alignments?
|
||||
grid type?
|
||||
shadow type?
|
||||
*/
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(parent), reg);
|
||||
gtk_widget_show(reg);
|
||||
|
||||
#if 0
|
||||
/* add callbacks that handle cell editing */
|
||||
|
||||
XtAddCallback (reg, XmNenterCellCallback, cellCB, (gpointer)table);
|
||||
XtAddCallback (reg, XmNleaveCellCallback, cellCB, (gpointer)table);
|
||||
XtAddCallback (reg, XmNmodifyVerifyCallback, cellCB, (gpointer)table);
|
||||
XtAddCallback (reg, XmNtraverseCellCallback, traverseCB, (gpointer)table);
|
||||
#endif
|
||||
|
||||
table->table_widget = reg;
|
||||
|
||||
#if 0
|
||||
/* ??? What does xt_realize do? */
|
||||
|
||||
/* if any of the cells have GUI specific components that need
|
||||
* initialization, initialize them now. */
|
||||
|
||||
@ -636,21 +761,20 @@ xaccCreateTable (Table *table, GtkWidget * parent)
|
||||
BasicCell *cell;
|
||||
cell = curs->cells[i][j];
|
||||
if (cell) {
|
||||
void (*xt_realize) (BasicCell *,
|
||||
void *gui,
|
||||
int pixel_width);
|
||||
void (*xt_realize) (BasicCell *, void *gui, int pixel_width);
|
||||
xt_realize = cell->realize;
|
||||
if (xt_realize) {
|
||||
int pixel_width;
|
||||
pixel_width = XbaeMatrixGetColumnPixelWidth (reg, j);
|
||||
xt_realize (cell, ((void *) reg), pixel_width);
|
||||
/* cl->column[col].width */
|
||||
/*pixel_width = XbaeMatrixGetColumnPixelWidth (reg, j);*/
|
||||
xt_realize (cell, ((void *) table), 0);
|
||||
/*xt_realize (cell, ((void *) reg), pixel_width);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return (reg);
|
||||
return (table->table_widget);
|
||||
}
|
||||
|
||||
/* ==================================================== */
|
||||
@ -672,7 +796,7 @@ xaccRefreshTableGUI (Table * table)
|
||||
reg = table->table_widget;
|
||||
|
||||
printf (" refresh numphysrows=%d numphyscols=%d \n",
|
||||
table->num_phys_rows,table->num_phys_cols);
|
||||
table->num_phys_rows, table->num_phys_cols);
|
||||
|
||||
for (i = num_header_rows; i < table->num_phys_rows; i++) {
|
||||
printf ("cell %d act:%s descr: %s \n",
|
||||
@ -682,13 +806,15 @@ xaccRefreshTableGUI (Table * table)
|
||||
|
||||
gtk_clist_freeze(GTK_CLIST(reg));
|
||||
|
||||
while(GTK_CLIST(reg)->rows < table->num_phys_rows) {
|
||||
while(GTK_CLIST(reg)->rows < (table->num_phys_rows - num_header_rows)) {
|
||||
gtk_clist_append(GTK_CLIST(reg), NULL);
|
||||
}
|
||||
|
||||
for(i = num_header_rows; i < table->num_phys_rows; i++) {
|
||||
for(i = num_header_rows; i < table->num_phys_rows; i++)
|
||||
{
|
||||
for(j = 0; j < table->num_phys_cols; j++) {
|
||||
gtk_clist_set_text(GTK_CLIST(reg), i, j, table->entries[i][j]);
|
||||
gtk_clist_set_text(GTK_CLIST(reg), i - num_header_rows, j,
|
||||
table->entries[i][j]);
|
||||
}
|
||||
}
|
||||
gtk_clist_thaw(GTK_CLIST(reg));
|
||||
@ -700,8 +826,8 @@ xaccRefreshTableGUI (Table * table)
|
||||
Local Variables:
|
||||
tab-width: 2
|
||||
indent-tabs-mode: nil
|
||||
mode: c-mode
|
||||
mode: c
|
||||
c-indentation-style: gnu
|
||||
eval: (c-set-offset 'block-open '-)
|
||||
eval: (c-set-offset 'substatement-open 0)
|
||||
End:
|
||||
*/
|
||||
|
@ -119,6 +119,16 @@ struct _Table {
|
||||
/* protected data -- vital for the implementation,
|
||||
* but not something we want to generally expose */
|
||||
GtkWidget *table_widget; /* the CList */
|
||||
GtkWidget *entry_frame; /* the editing widget frame */
|
||||
GtkWidget *entry_widget; /* the current cell editing widget */
|
||||
|
||||
/* Current editing cell */
|
||||
int current_col;
|
||||
int current_row;
|
||||
|
||||
/* snapshot of entry text -- used to detect changes in callback */
|
||||
char *prev_entry_text;
|
||||
|
||||
GtkWidget *next_tab_group; /* where to traverse in the end */
|
||||
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user