From ebda03f4d53b24d1af3de9fd7dcbbf448401d5a9 Mon Sep 17 00:00:00 2001 From: John Darrington Date: Mon, 6 Apr 2009 10:21:01 +0800 Subject: [PATCH] Merge psppire-axis and psppire-axis-impl There's only one implementation of psppire-axis now, and having the implementation seperated from the interface in a brige configuration just adds too much complexity. --- lib/gtk-contrib/psppire-sheet.c | 4 +- src/ui/gui/psppire-data-editor.c | 44 +-- src/ui/gui/psppire-data-editor.h | 6 +- src/ui/gui/psppire-var-sheet.c | 8 +- src/ui/gui/sheet/automake.mk | 2 - src/ui/gui/sheet/psppire-axis-impl.c | 470 --------------------------- src/ui/gui/sheet/psppire-axis-impl.h | 89 ----- src/ui/gui/sheet/psppire-axis.c | 450 ++++++++++++++++++++----- src/ui/gui/sheet/psppire-axis.h | 58 ++-- 9 files changed, 416 insertions(+), 715 deletions(-) delete mode 100644 src/ui/gui/sheet/psppire-axis-impl.c delete mode 100644 src/ui/gui/sheet/psppire-axis-impl.h diff --git a/lib/gtk-contrib/psppire-sheet.c b/lib/gtk-contrib/psppire-sheet.c index ad1cf78a..4119037d 100644 --- a/lib/gtk-contrib/psppire-sheet.c +++ b/lib/gtk-contrib/psppire-sheet.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2006, 2008 Free Software Foundation + Copyright (C) 2006, 2008, 2009 Free Software Foundation 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 @@ -69,7 +69,9 @@ #include "psppire-sheet.h" #include #include +#include #include + #include /* sheet flags */ diff --git a/src/ui/gui/psppire-data-editor.c b/src/ui/gui/psppire-data-editor.c index ab3b2128..be911ba6 100644 --- a/src/ui/gui/psppire-data-editor.c +++ b/src/ui/gui/psppire-data-editor.c @@ -23,7 +23,7 @@ #include #include "psppire-data-store.h" -#include +#include #include "helper.h" #include @@ -220,8 +220,8 @@ new_data_callback (PsppireDataStore *ds, gpointer data) for (i = 0; i < 2; ++i) { - psppire_axis_impl_clear (de->vaxis[i]); - psppire_axis_impl_append_n (de->vaxis[i], n_cases, DEFAULT_ROW_HEIGHT); + psppire_axis_clear (de->vaxis[i]); + psppire_axis_append_n (de->vaxis[i], n_cases, DEFAULT_ROW_HEIGHT); } } @@ -232,7 +232,7 @@ case_inserted_callback (PsppireDataStore *ds, gint before, gpointer data) PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data); for (i = 0; i < 2; ++i) - psppire_axis_impl_insert (de->vaxis[i], before, DEFAULT_ROW_HEIGHT); + psppire_axis_insert (de->vaxis[i], before, DEFAULT_ROW_HEIGHT); } @@ -243,7 +243,7 @@ cases_deleted_callback (PsppireDataStore *ds, gint first, gint n_cases, gpointer PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data); for (i = 0; i < 2; ++i) - psppire_axis_impl_delete (de->vaxis[0], first, n_cases); + psppire_axis_delete (de->vaxis[0], first, n_cases); } @@ -288,22 +288,22 @@ new_variables_callback (PsppireDict *dict, gpointer data) PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data); gint m_width = width_of_m (GTK_WIDGET (de)); - PsppireAxisImpl *vaxis; + PsppireAxis *vaxis; g_object_get (de->var_sheet, "vertical-axis", &vaxis, NULL); - psppire_axis_impl_clear (vaxis); - psppire_axis_impl_append_n (vaxis, 1 + psppire_dict_get_var_cnt (dict), DEFAULT_ROW_HEIGHT); + psppire_axis_clear (vaxis); + psppire_axis_append_n (vaxis, 1 + psppire_dict_get_var_cnt (dict), DEFAULT_ROW_HEIGHT); g_signal_connect_swapped (de->haxis, "resize-unit", G_CALLBACK (rewidth_variable), de); - psppire_axis_impl_clear (de->haxis); + psppire_axis_clear (de->haxis); for (v = 0 ; v < psppire_dict_get_var_cnt (dict); ++v) { const struct variable *var = psppire_dict_get_variable (dict, v); - psppire_axis_impl_append (de->haxis, m_width * var_get_display_width (var)); + psppire_axis_append (de->haxis, m_width * var_get_display_width (var)); } } @@ -314,16 +314,16 @@ insert_variable_callback (PsppireDict *dict, gint x, gpointer data) gint m_width = width_of_m (GTK_WIDGET (de)); - PsppireAxisImpl *var_vaxis; + PsppireAxis *var_vaxis; const struct variable *var = psppire_dict_get_variable (dict, x); g_object_get (de->var_sheet, "vertical-axis", &var_vaxis, NULL); - psppire_axis_impl_insert (var_vaxis, x, DEFAULT_ROW_HEIGHT); + psppire_axis_insert (var_vaxis, x, DEFAULT_ROW_HEIGHT); - psppire_axis_impl_insert (de->haxis, x, m_width * var_get_display_width (var)); + psppire_axis_insert (de->haxis, x, m_width * var_get_display_width (var)); } @@ -333,12 +333,12 @@ delete_variable_callback (PsppireDict *dict, gint posn, { PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data); - PsppireAxisImpl *var_vaxis; + PsppireAxis *var_vaxis; g_object_get (de->var_sheet, "vertical-axis", &var_vaxis, NULL); - psppire_axis_impl_delete (var_vaxis, posn, 1); + psppire_axis_delete (var_vaxis, posn, 1); - psppire_axis_impl_delete (de->haxis, posn, 1); + psppire_axis_delete (de->haxis, posn, 1); } @@ -356,7 +356,7 @@ rewidth_variable_callback (PsppireDict *dict, gint posn, gpointer data) if ( var_width < 1 ) var_width = 1; - psppire_axis_impl_resize (de->haxis, posn, m_width * var_width); + psppire_axis_resize (de->haxis, posn, m_width * var_width); } @@ -822,8 +822,8 @@ on_map (GtkWidget *w) static void init_sheet (PsppireDataEditor *de, int i, GtkAdjustment *hadj, GtkAdjustment *vadj, - PsppireAxisImpl *vaxis, - PsppireAxisImpl *haxis + PsppireAxis *vaxis, + PsppireAxis *haxis ) { de->sheet_bin[i] = gtk_scrolled_window_new (hadj, vadj); @@ -859,12 +859,12 @@ init_data_sheet (PsppireDataEditor *de) GtkAdjustment *vadj1, *hadj1; GtkWidget *sheet ; - de->vaxis[0] = psppire_axis_impl_new (); - de->vaxis[1] = psppire_axis_impl_new (); + de->vaxis[0] = psppire_axis_new (); + de->vaxis[1] = psppire_axis_new (); /* There's only one horizontal axis, since the column widths are parameters of the variables */ - de->haxis = psppire_axis_impl_new (); + de->haxis = psppire_axis_new (); de->split = TRUE; de->paned = gtk_xpaned_new (); diff --git a/src/ui/gui/psppire-data-editor.h b/src/ui/gui/psppire-data-editor.h index ee95a03c..b5b3f360 100644 --- a/src/ui/gui/psppire-data-editor.h +++ b/src/ui/gui/psppire-data-editor.h @@ -22,7 +22,7 @@ #include #include -#include +#include #include "psppire-var-store.h" #include "psppire-data-store.h" @@ -59,11 +59,11 @@ struct _PsppireDataEditor GtkWidget *paned; gboolean split; - PsppireAxisImpl *vaxis[2]; + PsppireAxis *vaxis[2]; /* There's only one horizontal axis, since the column widths are parameters of the variables */ - PsppireAxisImpl *haxis; + PsppireAxis *haxis; }; diff --git a/src/ui/gui/psppire-var-sheet.c b/src/ui/gui/psppire-var-sheet.c index 517a61e0..696bab21 100644 --- a/src/ui/gui/psppire-var-sheet.c +++ b/src/ui/gui/psppire-var-sheet.c @@ -16,7 +16,7 @@ #include #include "psppire-var-sheet.h" -#include +#include #include "helper.h" @@ -550,13 +550,13 @@ GtkWidget* psppire_var_sheet_new (void) { gint i; - PsppireAxisImpl *ha = psppire_axis_impl_new (); - PsppireAxisImpl *va = psppire_axis_impl_new (); + PsppireAxis *ha = psppire_axis_new (); + PsppireAxis *va = psppire_axis_new (); GtkWidget *w = g_object_new (psppire_var_sheet_get_type (), NULL); for (i = 0 ; i < 10 ; ++i) - psppire_axis_impl_append (ha, column_def[i].width); + psppire_axis_append (ha, column_def[i].width); g_object_set (va, "default-size", 25, diff --git a/src/ui/gui/sheet/automake.mk b/src/ui/gui/sheet/automake.mk index 640f02e0..b95de451 100644 --- a/src/ui/gui/sheet/automake.mk +++ b/src/ui/gui/sheet/automake.mk @@ -7,8 +7,6 @@ src_ui_gui_sheet_libsheet_la_CFLAGS = $(GTK_CFLAGS) src_ui_gui_sheet_libsheet_la_SOURCES = \ src/ui/gui/sheet/psppire-axis.c \ src/ui/gui/sheet/psppire-axis.h \ - src/ui/gui/sheet/psppire-axis-impl.c \ - src/ui/gui/sheet/psppire-axis-impl.h \ src/ui/gui/sheet/psppire-sheetmodel.c \ src/ui/gui/sheet/psppire-sheetmodel.h diff --git a/src/ui/gui/sheet/psppire-axis-impl.c b/src/ui/gui/sheet/psppire-axis-impl.c deleted file mode 100644 index d1297863..00000000 --- a/src/ui/gui/sheet/psppire-axis-impl.c +++ /dev/null @@ -1,470 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2008 Free Software Foundation - - 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 3 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, see . */ - -#include -#include -#include - -#include -#include -#include "psppire-axis-impl.h" -#include - - -/* --- prototypes --- */ -static void psppire_axis_impl_class_init (PsppireAxisImplClass *class); -static void psppire_axis_impl_init (PsppireAxisImpl *axis); -static void psppire_axis_impl_finalize (GObject *object); - - -/* --- variables --- */ -static GObjectClass *parent_class = NULL; - - -struct axis_node -{ - struct tower_node pixel_node; - struct tower_node unit_node; -}; - -void -psppire_axis_impl_dump (const PsppireAxisImpl *a) -{ - struct tower_node *n = tower_first (&a->unit_tower); - - g_debug ("Axis %p", a); - while (n) - { - const struct axis_node *an = tower_data (n, struct axis_node, unit_node); - const struct tower_node *pn = &an->pixel_node; - g_debug ("%ld units of height %g", - n->size, pn->size / (gdouble) n->size); - - n = tower_next (&a->unit_tower, n); - } - g_debug ("\n"); -} - -static gint -unit_at_pixel (const PsppireAxis *axis, glong pixel) -{ - PsppireAxisImpl *a = PSPPIRE_AXIS_IMPL (axis); - - unsigned long int start; - struct tower_node *n; - struct axis_node *an; - gdouble fraction; - - g_return_val_if_fail (pixel >= 0, -1); - - n = tower_lookup (&a->pixel_tower, pixel, &start); - an = tower_data (n, struct axis_node, pixel_node); - - fraction = (pixel - start) / (gdouble) tower_node_get_size (&an->pixel_node); - - return tower_node_get_level (&an->unit_node) - + fraction * tower_node_get_size (&an->unit_node); -} - - -static gint -unit_count (const PsppireAxis *axis) -{ - PsppireAxisImpl *a = PSPPIRE_AXIS_IMPL (axis); - - return tower_height (&a->unit_tower); -} - - -/* Returns the pixel at the start of UNIT */ -static glong -start_pixel (const PsppireAxis *axis, gint unit) -{ - gdouble fraction; - PsppireAxisImpl *a = PSPPIRE_AXIS_IMPL (axis); - struct tower_node *n ; - struct axis_node *an; - - unsigned long int start; - - if ( unit < 0) - return -1; - - if ( unit >= unit_count (axis)) - return -1; - - n = tower_lookup (&a->unit_tower, unit, &start); - - an = tower_data (n, struct axis_node, unit_node); - - fraction = (unit - start) / (gdouble) tower_node_get_size (&an->unit_node); - - return tower_node_get_level (&an->pixel_node) + - nearbyint (fraction * tower_node_get_size (&an->pixel_node)); -} - - -static gint -unit_size (const PsppireAxis *axis, gint unit) -{ - PsppireAxisImpl *a = PSPPIRE_AXIS_IMPL (axis); - struct tower_node *n ; - struct axis_node *an; - - unsigned long int start; - - if ( unit < 0) - return 0; - - if ( unit >= unit_count (axis)) - return 0; - - n = tower_lookup (&a->unit_tower, unit, &start); - - an = tower_data (n, struct axis_node, unit_node); - - return nearbyint (tower_node_get_size (&an->pixel_node) - / (gdouble) tower_node_get_size (&an->unit_node)); -} - - -static glong -total_size (const PsppireAxis *axis) -{ - PsppireAxisImpl *a = PSPPIRE_AXIS_IMPL (axis); - - return tower_height (&a->pixel_tower); -} - - -static void resize (PsppireAxis *axis, gint posn, glong size); - - - -static void -psppire_impl_iface_init (PsppireAxisIface *iface) -{ - iface->unit_size = unit_size; - iface->unit_count = unit_count; - iface->start_pixel = start_pixel; - iface->unit_at_pixel = unit_at_pixel; - iface->total_size = total_size; - iface->resize = resize; -} - -/* --- functions --- */ -/** - * psppire_axis_impl_get_type: - * @returns: the type ID for accelerator groups. - */ -GType -psppire_axis_impl_get_type (void) -{ - static GType object_type = 0; - - if (!object_type) - { - static const GTypeInfo object_info = { - sizeof (PsppireAxisImplClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) psppire_axis_impl_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (PsppireAxisImpl), - 0, /* n_preallocs */ - (GInstanceInitFunc) psppire_axis_impl_init, - }; - - static const GInterfaceInfo interface_info = - { - (GInterfaceInitFunc) psppire_impl_iface_init, - NULL, - NULL - }; - - object_type = g_type_register_static (G_TYPE_PSPPIRE_AXIS, - "PsppireAxisImpl", - &object_info, 0); - - g_type_add_interface_static (object_type, - PSPPIRE_TYPE_AXIS_IFACE, - &interface_info); - } - - return object_type; -} - -static void -psppire_axis_impl_class_init (PsppireAxisImplClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (class); - parent_class = g_type_class_peek_parent (class); - - object_class->finalize = psppire_axis_impl_finalize; -} - - -static void -psppire_axis_impl_init (PsppireAxisImpl *axis) -{ - tower_init (&axis->pixel_tower); - tower_init (&axis->unit_tower); - - axis->pool = pool_create (); -} - - -static void -psppire_axis_impl_finalize (GObject *object) -{ - PsppireAxisImpl *a = PSPPIRE_AXIS_IMPL (object); - pool_destroy (a->pool); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -/** - * psppire_axis_impl_new: - * @returns: a new #PsppireAxisImpl object - * - * Creates a new #PsppireAxisImpl. - */ -PsppireAxisImpl* -psppire_axis_impl_new (void) -{ - return g_object_new (G_TYPE_PSPPIRE_AXIS_IMPL, NULL); -} - - - - -void -psppire_axis_impl_append (PsppireAxisImpl *a, gint size) -{ - psppire_axis_impl_append_n (a, 1, size); -} - - -void -psppire_axis_impl_append_n (PsppireAxisImpl *a, gint n_units, gint size) -{ - struct axis_node *node; - - if (n_units == 0) - return; - - node = pool_malloc (a->pool, sizeof *node); - - tower_insert (&a->unit_tower, n_units, &node->unit_node, NULL); - tower_insert (&a->pixel_tower, size * n_units, &node->pixel_node, NULL); -} - - -/* Split the node of both towers at POSN */ -static void -split (PsppireAxisImpl *a, gint posn) -{ - unsigned long int existing_unit_size; - unsigned long int existing_pixel_size; - unsigned long int start; - gdouble fraction; - struct axis_node *new_node ; - struct tower_node *n; - struct axis_node *existing_node; - - g_return_if_fail (posn <= tower_height (&a->unit_tower)); - - /* Nothing needs to be done */ - if ( posn == 0 || posn == tower_height (&a->unit_tower)) - return; - - n = tower_lookup (&a->unit_tower, posn, &start); - - existing_node = tower_data (n, struct axis_node, unit_node); - - /* Nothing needs to be done, if the range element is already split here */ - if ( posn - start == 0) - return; - - existing_unit_size = tower_node_get_size (&existing_node->unit_node); - existing_pixel_size = tower_node_get_size (&existing_node->pixel_node); - - fraction = (posn - start) / (gdouble) existing_unit_size; - - new_node = pool_malloc (a->pool, sizeof (*new_node)); - - tower_resize (&a->unit_tower, &existing_node->unit_node, posn - start); - - tower_resize (&a->pixel_tower, &existing_node->pixel_node, - nearbyintf (fraction * existing_pixel_size)); - - tower_insert (&a->unit_tower, - existing_unit_size - (posn - start), - &new_node->unit_node, - tower_next (&a->unit_tower, &existing_node->unit_node)); - - - tower_insert (&a->pixel_tower, - nearbyintf (existing_pixel_size * (1 - fraction)), - &new_node->pixel_node, - tower_next (&a->pixel_tower, &existing_node->pixel_node)); -} - - -/* Insert a new unit of size SIZE before POSN */ -void -psppire_axis_impl_insert (PsppireAxisImpl *a, gint posn, gint size) -{ - struct axis_node *before = NULL; - struct axis_node *new_node; - - g_return_if_fail ( posn >= 0); - g_return_if_fail ( posn <= tower_height (&a->unit_tower)); - - if ( posn < tower_height (&a->unit_tower)) - { - unsigned long int start = 0; - struct tower_node *n; - - split (a, posn); - - n = tower_lookup (&a->unit_tower, posn, &start); - g_assert (posn == start); - - before = tower_data (n, struct axis_node, unit_node); - } - - new_node = pool_malloc (a->pool, sizeof (*new_node)); - - tower_insert (&a->unit_tower, - 1, - &new_node->unit_node, - before ? &before->unit_node : NULL); - - tower_insert (&a->pixel_tower, - size, - &new_node->pixel_node, - before ? &before->pixel_node : NULL); -} - - -/* Make the element at POSN singular. - Return a pointer to the node for this element */ -static struct axis_node * -make_single (PsppireAxisImpl *a, gint posn) -{ - unsigned long int start; - struct tower_node *n; - - g_return_val_if_fail (posn < tower_height (&a->unit_tower), NULL); - - n = tower_lookup (&a->unit_tower, posn, &start); - - if ( 1 != tower_node_get_size (n)) - { - split (a, posn + 1); - n = tower_lookup (&a->unit_tower, posn, &start); - - if ( 1 != tower_node_get_size (n)) - { - split (a, posn); - n = tower_lookup (&a->unit_tower, posn, &start); - } - } - - g_assert (1 == tower_node_get_size (n)); - - return tower_data (n, struct axis_node, unit_node); -} - - -static void -resize (PsppireAxis *axis, gint posn, glong size) -{ - PsppireAxisImpl *a = PSPPIRE_AXIS_IMPL (axis); - - struct axis_node *an; - g_return_if_fail (posn >= 0); - g_return_if_fail (size > 0); - - /* Silently ignore this request if the position is greater than the number of - units in the axis */ - if (posn >= tower_height (&a->unit_tower)) - return ; - - an = make_single (a, posn); - - tower_resize (&a->pixel_tower, &an->pixel_node, size); -} - - -void -psppire_axis_impl_resize (PsppireAxisImpl *a, gint posn, gint size) -{ - resize (PSPPIRE_AXIS (a), posn, size); -} - - - - -void -psppire_axis_impl_clear (PsppireAxisImpl *a) -{ - pool_destroy (a->pool); - a->pool = pool_create (); - - tower_init (&a->pixel_tower); - tower_init (&a->unit_tower); -} - - - -void -psppire_axis_impl_delete (PsppireAxisImpl *a, gint first, gint n_units) -{ - gint units_to_delete = n_units; - unsigned long int start; - struct tower_node *unit_node ; - g_return_if_fail (first + n_units <= tower_height (&a->unit_tower)); - - split (a, first); - split (a, first + n_units); - - unit_node = tower_lookup (&a->unit_tower, first, &start); - g_assert (start == first); - - while (units_to_delete > 0) - { - struct tower_node *next_unit_node; - struct axis_node *an = tower_data (unit_node, - struct axis_node, unit_node); - - g_assert (unit_node == &an->unit_node); - g_assert (unit_node->size <= n_units); - - units_to_delete -= unit_node->size; - - next_unit_node = tower_next (&a->unit_tower, unit_node); - - tower_delete (&a->unit_tower, unit_node); - tower_delete (&a->pixel_tower, &an->pixel_node); - - pool_free (a->pool, an); - - unit_node = next_unit_node; - } -} diff --git a/src/ui/gui/sheet/psppire-axis-impl.h b/src/ui/gui/sheet/psppire-axis-impl.h deleted file mode 100644 index 84193ae4..00000000 --- a/src/ui/gui/sheet/psppire-axis-impl.h +++ /dev/null @@ -1,89 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2008 Free Software Foundation - - 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 3 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, see . */ - - -#ifndef PSPPIRE_AXIS_IMPL_H__ -#define PSPPIRE_AXIS_IMPL_H__ - - -#include -#include - -#include "psppire-axis.h" -#include - -G_BEGIN_DECLS - - -/* --- type macros --- */ -#define G_TYPE_PSPPIRE_AXIS_IMPL (psppire_axis_impl_get_type ()) -#define PSPPIRE_AXIS_IMPL(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_PSPPIRE_AXIS_IMPL, PsppireAxisImpl)) -#define PSPPIRE_AXIS_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_PSPPIRE_AXIS_IMPL, PsppireAxisImplClass)) -#define PSPPIRE_IS_AXIS_IMPL(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), G_TYPE_PSPPIRE_AXIS_IMPL)) -#define PSPPIRE_IS_AXIS_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_PSPPIRE_AXIS_IMPL)) -#define PSPPIRE_AXIS_IMPL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_PSPPIRE_AXIS_IMPL, PsppireAxisImplClass)) - - - -/* --- typedefs & structures --- */ -typedef struct _PsppireAxisImpl PsppireAxisImpl; -typedef struct _PsppireAxisImplClass PsppireAxisImplClass; - -struct pool; - -struct _PsppireAxisImpl -{ - PsppireAxis parent; - - struct tower pixel_tower; - struct tower unit_tower; - - struct pool *pool; -}; - -struct _PsppireAxisImplClass -{ - PsppireAxisClass parent_class; -}; - -GType psppire_axis_impl_get_type (void); - -PsppireAxisImpl* psppire_axis_impl_new (void); - - -/* Interface between axis and model */ - - - -void psppire_axis_impl_insert (PsppireAxisImpl *a, gint posn, gint size); - -void psppire_axis_impl_append (PsppireAxisImpl *a, gint size); - - -void psppire_axis_impl_append_n (PsppireAxisImpl *a, gint n_units, gint size); - -void psppire_axis_impl_resize (PsppireAxisImpl *a, gint posn, gint size); - -void psppire_axis_impl_clear (PsppireAxisImpl *); - - -void psppire_axis_impl_delete (PsppireAxisImpl *, gint first, gint n_cases); - - - -G_END_DECLS - -#endif /* PSPPIRE_AXIS_IMPL_H__ */ diff --git a/src/ui/gui/sheet/psppire-axis.c b/src/ui/gui/sheet/psppire-axis.c index 3aeea7c4..5ae84d00 100644 --- a/src/ui/gui/sheet/psppire-axis.c +++ b/src/ui/gui/sheet/psppire-axis.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2008 Free Software Foundation + Copyright (C) 2008, 2009 Free Software Foundation 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 @@ -18,13 +18,12 @@ #include #include +#include #include #include -#include #include "psppire-axis.h" -#include -#include - +#include +#include /* Signals */ @@ -36,52 +35,182 @@ enum static guint signals[n_signals] ; +/* --- prototypes --- */ +static void psppire_axis_class_init (PsppireAxisClass *class); +static void psppire_axis_init (PsppireAxis *axis); +static void psppire_axis_finalize (GObject *object); -#define PSPPIRE_AXIS_GET_IFACE(obj) \ - (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PSPPIRE_TYPE_AXIS_IFACE, PsppireAxisIface)) -GType -psppire_axis_iface_get_type (void) +/* --- variables --- */ +static GObjectClass *parent_class = NULL; + + +struct axis_node +{ + struct tower_node pixel_node; + struct tower_node unit_node; +}; + +void +psppire_axis_dump (const PsppireAxis *a) { - static GType psppire_axis_iface_type = 0; + struct tower_node *n = tower_first (&a->unit_tower); - if (! psppire_axis_iface_type) + g_debug ("Axis %p", a); + while (n) { - static const GTypeInfo psppire_axis_iface_info = - { - sizeof (PsppireAxisIface), /* class_size */ - NULL, /* base init */ - NULL, /* base_finalize */ - NULL, - NULL, /* class_finalize */ - NULL, /* class_data */ - 0, - 0, /* n_preallocs */ - NULL - }; + const struct axis_node *an = tower_data (n, struct axis_node, unit_node); + const struct tower_node *pn = &an->pixel_node; + g_debug ("%ld units of height %g", + n->size, pn->size / (gdouble) n->size); + + n = tower_next (&a->unit_tower, n); + } + g_debug ("\n"); +} + +/* Return the unit covered by PIXEL */ +gint +psppire_axis_unit_at_pixel (const PsppireAxis *a, glong pixel) +{ + unsigned long int start; + struct tower_node *n; + struct axis_node *an; + gdouble fraction; + + glong size = tower_height (&a->pixel_tower); + + g_return_val_if_fail (pixel >= 0, -1); - psppire_axis_iface_type = - g_type_register_static (G_TYPE_INTERFACE, "PsppireAxisIface", - &psppire_axis_iface_info, 0); + if (pixel >= size) + { + gint n_items = tower_height (&a->unit_tower); + glong extra = pixel - size; + + return n_items - 1 + DIV_RND_UP (extra, a->default_size); } - return psppire_axis_iface_type; + + n = tower_lookup (&a->pixel_tower, pixel, &start); + an = tower_data (n, struct axis_node, pixel_node); + + fraction = (pixel - start) / (gdouble) tower_node_get_size (&an->pixel_node); + + return tower_node_get_level (&an->unit_node) + + fraction * tower_node_get_size (&an->unit_node); } -G_DEFINE_ABSTRACT_TYPE(PsppireAxis, psppire_axis, G_TYPE_OBJECT); +gint +psppire_axis_unit_count (const PsppireAxis *a) +{ + glong padding = 0; + glong actual_size; + actual_size = tower_height (&a->pixel_tower); -/* --- prototypes --- */ -static void psppire_axis_class_init (PsppireAxisClass *class); -static void psppire_axis_init (PsppireAxis *axis); -static void psppire_axis_finalize (GObject *object); + if ( actual_size < a->min_extent ) + padding = DIV_RND_UP (a->min_extent - actual_size, a->default_size); + return tower_height (&a->unit_tower) + padding; +} -/* --- variables --- */ -static GObjectClass *parent_class = NULL; +/* Return the starting pixel of UNIT */ +glong +psppire_axis_start_pixel (const PsppireAxis *a, gint unit) +{ + gdouble fraction; + struct tower_node *n ; + struct axis_node *an; + + unsigned long int start; + + gint the_count, size ; + + the_count = tower_height (&a->unit_tower); + size = tower_height (&a->pixel_tower); + + if ( unit >= the_count) + { + return size + (unit - the_count) * a->default_size; + } + + if ( unit < 0) + return -1; + + if ( unit >= tower_height (&a->unit_tower)) + return -1; + + n = tower_lookup (&a->unit_tower, unit, &start); + + an = tower_data (n, struct axis_node, unit_node); + + fraction = (unit - start) / (gdouble) tower_node_get_size (&an->unit_node); + + return tower_node_get_level (&an->pixel_node) + + nearbyint (fraction * tower_node_get_size (&an->pixel_node)); +} + +gint +psppire_axis_unit_size (const PsppireAxis *axis, gint unit) +{ + struct tower_node *n ; + struct axis_node *an; + + unsigned long int start; + + if (unit >= tower_height (&axis->unit_tower)) + return axis->default_size; + + if ( unit < 0) + return 0; + + if ( unit >= tower_height (&axis->unit_tower)) + return 0; + + n = tower_lookup (&axis->unit_tower, unit, &start); + + an = tower_data (n, struct axis_node, unit_node); + + return nearbyint (tower_node_get_size (&an->pixel_node) + / (gdouble) tower_node_get_size (&an->unit_node)); +} + + + +/* --- functions --- */ +/** + * psppire_axis_get_type: + * @returns: the type ID for accelerator groups. + */ +GType +psppire_axis_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = { + sizeof (PsppireAxisClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) psppire_axis_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PsppireAxis), + 0, /* n_preallocs */ + (GInstanceInitFunc) psppire_axis_init, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "PsppireAxis", + &object_info, 0); + + } + return object_type; +} enum { @@ -136,16 +265,22 @@ psppire_axis_set_property (GObject *object, }; } + static void psppire_axis_class_init (PsppireAxisClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); + + GParamSpec *min_extent_spec; GParamSpec *default_size_spec; + parent_class = g_type_class_peek_parent (class); + object_class->set_property = psppire_axis_set_property; object_class->get_property = psppire_axis_get_property; + min_extent_spec = g_param_spec_long ("minimum-extent", "Minimum Extent", @@ -172,10 +307,6 @@ psppire_axis_class_init (PsppireAxisClass *class) PROP_DEFAULT_SIZE, default_size_spec); - parent_class = g_type_class_peek_parent (class); - - object_class->finalize = psppire_axis_finalize; - signals[RESIZE_UNIT] = g_signal_new ("resize-unit", @@ -189,113 +320,254 @@ psppire_axis_class_init (PsppireAxisClass *class) G_TYPE_INT, G_TYPE_LONG ); + + + object_class->finalize = psppire_axis_finalize; } static void psppire_axis_init (PsppireAxis *axis) { + tower_init (&axis->pixel_tower); + tower_init (&axis->unit_tower); + + axis->pool = pool_create (); } static void psppire_axis_finalize (GObject *object) { + PsppireAxis *a = PSPPIRE_AXIS (object); + pool_destroy (a->pool); + G_OBJECT_CLASS (parent_class)->finalize (object); } -gint -psppire_axis_unit_size (const PsppireAxis *a, gint unit) +/** + * psppire_axis_new: + * @returns: a new #PsppireAxis object + * + * Creates a new #PsppireAxis. + */ +PsppireAxis* +psppire_axis_new (void) +{ + return g_object_new (G_TYPE_PSPPIRE_AXIS, NULL); +} + + + + +void +psppire_axis_append (PsppireAxis *a, gint size) { - g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1); + psppire_axis_append_n (a, 1, size); +} + - g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_size, -1); +void +psppire_axis_append_n (PsppireAxis *a, gint n_units, gint size) +{ + struct axis_node *node; + if (n_units == 0) + return; - if (unit >= PSPPIRE_AXIS_GET_IFACE (a)->unit_count(a)) - return a->default_size; + node = pool_malloc (a->pool, sizeof *node); - return PSPPIRE_AXIS_GET_IFACE (a)->unit_size (a, unit); + tower_insert (&a->unit_tower, n_units, &node->unit_node, NULL); + tower_insert (&a->pixel_tower, size * n_units, &node->pixel_node, NULL); } -gint -psppire_axis_unit_count (const PsppireAxis *a) + +/* Split the node of both towers at POSN */ +static void +split (PsppireAxis *a, gint posn) { - glong padding = 0; - glong actual_size; + unsigned long int existing_unit_size; + unsigned long int existing_pixel_size; + unsigned long int start; + gdouble fraction; + struct axis_node *new_node ; + struct tower_node *n; + struct axis_node *existing_node; - g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1); - g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_count, -1); + g_return_if_fail (posn <= tower_height (&a->unit_tower)); - actual_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a); + /* Nothing needs to be done */ + if ( posn == 0 || posn == tower_height (&a->unit_tower)) + return; + + n = tower_lookup (&a->unit_tower, posn, &start); + + existing_node = tower_data (n, struct axis_node, unit_node); + + /* Nothing needs to be done, if the range element is already split here */ + if ( posn - start == 0) + return; + + existing_unit_size = tower_node_get_size (&existing_node->unit_node); + existing_pixel_size = tower_node_get_size (&existing_node->pixel_node); + + fraction = (posn - start) / (gdouble) existing_unit_size; + + new_node = pool_malloc (a->pool, sizeof (*new_node)); + + tower_resize (&a->unit_tower, &existing_node->unit_node, posn - start); + + tower_resize (&a->pixel_tower, &existing_node->pixel_node, + nearbyintf (fraction * existing_pixel_size)); + + tower_insert (&a->unit_tower, + existing_unit_size - (posn - start), + &new_node->unit_node, + tower_next (&a->unit_tower, &existing_node->unit_node)); - if ( actual_size < a->min_extent ) - padding = DIV_RND_UP (a->min_extent - actual_size, a->default_size); - return PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a) + padding; + tower_insert (&a->pixel_tower, + nearbyintf (existing_pixel_size * (1 - fraction)), + &new_node->pixel_node, + tower_next (&a->pixel_tower, &existing_node->pixel_node)); } -/* Return the starting pixel of UNIT */ -glong -psppire_axis_start_pixel (const PsppireAxis *a, gint unit) +/* Insert a new unit of size SIZE before POSN */ +void +psppire_axis_insert (PsppireAxis *a, gint posn, gint size) { - gint the_count, total_size ; - g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1); + struct axis_node *before = NULL; + struct axis_node *new_node; - the_count = PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a); - total_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a); + g_return_if_fail ( posn >= 0); + g_return_if_fail ( posn <= tower_height (&a->unit_tower)); - if ( unit >= the_count) + if ( posn < tower_height (&a->unit_tower)) { - return total_size + (unit - the_count) * a->default_size; + unsigned long int start = 0; + struct tower_node *n; + + split (a, posn); + + n = tower_lookup (&a->unit_tower, posn, &start); + g_assert (posn == start); + + before = tower_data (n, struct axis_node, unit_node); } - return PSPPIRE_AXIS_GET_IFACE (a)->start_pixel (a, unit); -} + new_node = pool_malloc (a->pool, sizeof (*new_node)); + tower_insert (&a->unit_tower, + 1, + &new_node->unit_node, + before ? &before->unit_node : NULL); -/* Return the unit covered by PIXEL */ -gint -psppire_axis_unit_at_pixel (const PsppireAxis *a, glong pixel) -{ - glong total_size; + tower_insert (&a->pixel_tower, + size, + &new_node->pixel_node, + before ? &before->pixel_node : NULL); +} - g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1); - g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a), -1); +/* Make the element at POSN singular. + Return a pointer to the node for this element */ +static struct axis_node * +make_single (PsppireAxis *a, gint posn) +{ + unsigned long int start; + struct tower_node *n; - g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_at_pixel, -1); + g_return_val_if_fail (posn < tower_height (&a->unit_tower), NULL); - total_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a); + n = tower_lookup (&a->unit_tower, posn, &start); - if (pixel >= total_size) + if ( 1 != tower_node_get_size (n)) { - gint n_items = PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a); - glong extra = pixel - total_size; - - return n_items - 1 + DIV_RND_UP (extra, a->default_size); + split (a, posn + 1); + n = tower_lookup (&a->unit_tower, posn, &start); + + if ( 1 != tower_node_get_size (n)) + { + split (a, posn); + n = tower_lookup (&a->unit_tower, posn, &start); + } } - return PSPPIRE_AXIS_GET_IFACE (a)->unit_at_pixel (a, pixel); + g_assert (1 == tower_node_get_size (n)); + + return tower_data (n, struct axis_node, unit_node); } -/* Set UNIT to size SIZE */ void -psppire_axis_resize (PsppireAxis *a, gint unit, glong size) +psppire_axis_resize (PsppireAxis *axis, gint posn, glong size) { - g_return_if_fail (PSPPIRE_IS_AXIS (a)); + struct axis_node *an; + g_return_if_fail (posn >= 0); + g_return_if_fail (size > 0); + + /* Silently ignore this request if the position is greater than the number of + units in the axis */ + if (posn >= tower_height (&axis->unit_tower)) + return ; + + an = make_single (axis, posn); + + tower_resize (&axis->pixel_tower, &an->pixel_node, size); + + g_signal_emit (axis, signals[RESIZE_UNIT], 0, posn, size); +} - g_return_if_fail (PSPPIRE_AXIS_GET_IFACE (a)); - g_return_if_fail (size > 0); - if (PSPPIRE_AXIS_GET_IFACE (a)->resize) - PSPPIRE_AXIS_GET_IFACE (a)->resize (a, unit, size); - g_signal_emit (a, signals [RESIZE_UNIT], 0, unit, size); + +void +psppire_axis_clear (PsppireAxis *a) +{ + pool_destroy (a->pool); + a->pool = pool_create (); + + tower_init (&a->pixel_tower); + tower_init (&a->unit_tower); } + +void +psppire_axis_delete (PsppireAxis *a, gint first, gint n_units) +{ + gint units_to_delete = n_units; + unsigned long int start; + struct tower_node *unit_node ; + g_return_if_fail (first + n_units <= tower_height (&a->unit_tower)); + + split (a, first); + split (a, first + n_units); + + unit_node = tower_lookup (&a->unit_tower, first, &start); + g_assert (start == first); + + while (units_to_delete > 0) + { + struct tower_node *next_unit_node; + struct axis_node *an = tower_data (unit_node, + struct axis_node, unit_node); + + g_assert (unit_node == &an->unit_node); + g_assert (unit_node->size <= n_units); + + units_to_delete -= unit_node->size; + + next_unit_node = tower_next (&a->unit_tower, unit_node); + + tower_delete (&a->unit_tower, unit_node); + tower_delete (&a->pixel_tower, &an->pixel_node); + + pool_free (a->pool, an); + + unit_node = next_unit_node; + } +} diff --git a/src/ui/gui/sheet/psppire-axis.h b/src/ui/gui/sheet/psppire-axis.h index 3836ecf0..cfba37b2 100644 --- a/src/ui/gui/sheet/psppire-axis.h +++ b/src/ui/gui/sheet/psppire-axis.h @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2008 Free Software Foundation + Copyright (C) 2008, 2009 Free Software Foundation 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 @@ -21,11 +21,11 @@ #include #include +#include G_BEGIN_DECLS - /* --- type macros --- */ #define G_TYPE_PSPPIRE_AXIS (psppire_axis_get_type ()) #define PSPPIRE_AXIS(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_PSPPIRE_AXIS, PsppireAxis)) @@ -35,13 +35,21 @@ G_BEGIN_DECLS #define PSPPIRE_AXIS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_PSPPIRE_AXIS, PsppireAxisClass)) + /* --- typedefs & structures --- */ typedef struct _PsppireAxis PsppireAxis; typedef struct _PsppireAxisClass PsppireAxisClass; +struct pool; + struct _PsppireAxis { - GObject parent; + GObject parent; + + struct tower pixel_tower; + struct tower unit_tower; + + struct pool *pool; glong min_extent; gint default_size; @@ -52,52 +60,32 @@ struct _PsppireAxisClass GObjectClass parent_class; }; - GType psppire_axis_get_type (void); +PsppireAxis* psppire_axis_new (void); +/* Interface between axis and model */ -GType psppire_axis_iface_get_type (void); - -#define PSPPIRE_TYPE_AXIS_IFACE (psppire_axis_iface_get_type ()) - -typedef struct _PsppireAxisIface PsppireAxisIface; - -struct _PsppireAxisIface -{ - GTypeInterface g_iface; - +void psppire_axis_insert (PsppireAxis *a, gint posn, gint size); - /* Virtual Table */ +void psppire_axis_append (PsppireAxis *a, gint size); - gint (*unit_size) (const PsppireAxis *a, gint unit); - gint (*unit_count) (const PsppireAxis *a); +void psppire_axis_append_n (PsppireAxis *a, gint n_units, gint size); - glong (*start_pixel) (const PsppireAxis *a, gint unit); +void psppire_axis_resize (PsppireAxis *a, gint posn, glong size); - gint (*unit_at_pixel) (const PsppireAxis *a, glong pixel); +void psppire_axis_clear (PsppireAxis *); - glong (*total_size) (const PsppireAxis *a); +void psppire_axis_delete (PsppireAxis *, gint first, gint n_cases); + - void (*resize) (PsppireAxis *a, gint unit, glong pixels); -}; - - -/* Interface between sheet and axis */ - -gint psppire_axis_unit_size (const PsppireAxis *a, gint unit); - -gint psppire_axis_unit_count (const PsppireAxis *a); - +gint psppire_axis_unit_count (const PsppireAxis *); glong psppire_axis_start_pixel (const PsppireAxis *a, gint unit); - -gint psppire_axis_unit_at_pixel (const PsppireAxis *a, glong pixel); - - -void psppire_axis_resize (PsppireAxis *a, gint unit, glong size); +gint psppire_axis_unit_size (const PsppireAxis *a, gint unit); +gint psppire_axis_unit_at_pixel (const PsppireAxis *a, glong pixel); G_END_DECLS -- 2.30.2