[gnumeric] xlsx: improve axis cleanup.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] xlsx: improve axis cleanup.
- Date: Mon, 9 Mar 2015 02:29:49 +0000 (UTC)
commit e1c230494a68805640f4066e89c15b1985744865
Author: Morten Welinder <terra gnome org>
Date: Sun Mar 8 22:29:13 2015 -0400
xlsx: improve axis cleanup.
plugins/excel/xlsx-read-drawing.c | 213 ++++++++++++++++++++----------------
plugins/excel/xlsx-write-drawing.c | 22 +++-
2 files changed, 139 insertions(+), 96 deletions(-)
---
diff --git a/plugins/excel/xlsx-read-drawing.c b/plugins/excel/xlsx-read-drawing.c
index 47a16c3..57fcc1a 100644
--- a/plugins/excel/xlsx-read-drawing.c
+++ b/plugins/excel/xlsx-read-drawing.c
@@ -2671,6 +2671,38 @@ GSF_XML_IN_NODE_END
/***********************************************************************/
+static int
+cb_by_id (gconstpointer a, gconstpointer b)
+{
+ return gog_object_get_id (a) - gog_object_get_id (b);
+}
+
+static GSList *
+xlsx_get_axes (GogObject *chart)
+{
+ GSList *children, *waste = NULL, *axes = NULL;
+
+ children = gog_object_get_children (chart, NULL);
+
+ while (children) {
+ GSList *next = children->next;
+ GogObject *obj = children->data;
+
+ if (GOG_IS_AXIS (obj)) {
+ children->next = axes;
+ axes = children;
+ } else {
+ children->next = waste;
+ waste = children;
+ }
+
+ children = next;
+ }
+
+ g_slist_free (waste);
+ return g_slist_sort (axes, cb_by_id);
+}
+
static void
cb_axis_set_position (GObject *axis, XLSXAxisInfo *info,
XLSXReadState *state)
@@ -2702,56 +2734,6 @@ cb_axis_set_position (GObject *axis, XLSXAxisInfo *info,
g_printerr ("Axis %s has invalid cross-axis id %s\n",
info->id, info->cross_id);
}
-
- if (info->deleted) {
- GSList *l = gog_chart_get_axes (state->chart, gog_axis_get_atype (GOG_AXIS (axis))), *cur;
- GogAxis *visible = NULL;
-
- for (cur = l; cur; cur = cur->next) {
- GogAxis *axis = GOG_AXIS (cur->data);
- gboolean invisible;
- g_object_get (axis, "invisible", &invisible, NULL);
- if (!invisible) {
- visible = axis;
- break;
- }
- }
- g_slist_free (l);
-
-#ifdef DEBUG_AXIS
- g_printerr ("Axis %s is marked as deleted; visible=%p\n",
- gog_object_get_name (GOG_OBJECT (axis)),
- visible);
-#endif
-
- if (visible) {
- GSList *l1, *cur1;
-
- if (obj)
- g_object_set (obj, "cross-axis-id", gog_object_get_id (GOG_OBJECT (visible)),
NULL);
- l1 = g_slist_copy ((GSList *) gog_axis_contributors (GOG_AXIS (axis)));
- for (cur1 = l1; cur1; cur1 = cur1->next) {
- if (GOG_IS_PLOT (cur1->data))
- gog_plot_set_axis (GOG_PLOT (cur1->data), visible);
- }
- g_slist_free (l1);
- /* now reparent the children of the hidden axis */
- l1 = gog_object_get_children (GOG_OBJECT (axis), NULL);
- for (cur1 = l1; cur1; cur1 = cur1->next) {
- GogObject *obj = GOG_OBJECT (cur1->data);
- GogObjectRole const *role = obj->role;
- gog_object_clear_parent (obj);
- gog_object_set_parent (obj, GOG_OBJECT (visible), role, obj->id);
- }
- g_slist_free (l1);
- }
- }
-}
-
-static int
-cb_by_id (gconstpointer a, gconstpointer b)
-{
- return gog_object_get_id (a) - gog_object_get_id (b);
}
/*
@@ -2760,21 +2742,14 @@ cb_by_id (gconstpointer a, gconstpointer b)
* own numbering.
*/
static void
-xlsx_rename_axes (XLSXReadState *state)
+xlsx_axes_rename (XLSXReadState *state)
{
GogObject *chart = GOG_OBJECT (state->chart);
- GSList *children, *axes, *l, *l2;
+ GSList *axes, *l, *l2;
GHashTable *role_to_id = g_hash_table_new (NULL, NULL);
- children = gog_object_get_children (chart, NULL);
- for (axes = NULL, l = children; l; l = l->next) {
- GogObject *c = l->data;
- if (GOG_IS_AXIS (c))
- axes = g_slist_prepend (axes, c);
- }
- g_slist_free (children);
+ axes = xlsx_get_axes (chart);
- axes = g_slist_sort (axes, cb_by_id);
for (l = axes; l; l = l->next) {
GogObject *axis = l->data;
GogObjectRole const *role = axis->role;
@@ -2808,63 +2783,110 @@ xlsx_rename_axes (XLSXReadState *state)
g_object_set (axis2, "cross-axis-id", new_id, NULL);
}
}
+
g_slist_free (axes);
g_hash_table_destroy (role_to_id);
}
-
static void
-xlsx_axis_cleanup (XLSXReadState *state)
+xlsx_axes_redirect_deleted (XLSXReadState *state)
{
- GSList *list, *ptr;
+ GogObject *chart = GOG_OBJECT (state->chart);
+ GSList *l, *axes = xlsx_get_axes (chart);
- /* clean out axes that were auto created */
- list = gog_object_get_children (GOG_OBJECT (state->chart), NULL);
- for (ptr = list; ptr != NULL ; ptr = ptr->next) {
- GogAxis *axis = ptr->data;
+ for (l = axes; l; l = l->next) {
+ GogAxis *axis = l->data;
XLSXAxisInfo *info;
- gboolean may_delete;
+ GogAxisType atype;
+ GSList *l2, *plots, *children;
+ GogAxis *visible = NULL;
- if (!GOG_IS_AXIS (axis))
+ info = g_hash_table_lookup (state->axis.by_obj, axis);
+ if (!info || !info->deleted)
continue;
- info = g_hash_table_lookup (state->axis.by_obj, axis);
- if (info)
+ /* Find a visible alternative for the deleted axis. */
+ atype = gog_axis_get_atype (GOG_AXIS (axis));
+ for (l2 = axes; l2; l2 = l2->next) {
+ GogAxis *axis2 = GOG_AXIS (l2->data);
+ if (gog_axis_get_atype (GOG_AXIS (axis2)) == atype &&
+ !gnm_object_get_bool (axis2, "invisible")) {
+ visible = axis2;
+ break;
+ }
+ }
+ if (!visible)
continue;
- may_delete = gog_object_is_deletable (GOG_OBJECT (axis));
+ /* Make all plots use the new, visible axis. */
+ plots = g_slist_copy ((GSList *) gog_axis_contributors (GOG_AXIS (axis)));
+ for (l2 = plots; l2; l2 = l2->next) {
+ GogPlot *plot = l2->data;
+ if (GOG_IS_PLOT (plot))
+ gog_plot_set_axis (plot, visible);
+ }
+ g_slist_free (plots);
+
+ /* Reparent the children of the deleted axis */
+ children = gog_object_get_children (GOG_OBJECT (axis), NULL);
+ for (l2 = children; l2; l2 = l2->next) {
+ GogObject *obj = l2->data;
+ GogObjectRole const *role = obj->role;
+ gog_object_clear_parent (obj);
+ gog_object_set_parent (obj, GOG_OBJECT (visible), role, obj->id);
+ }
+ g_slist_free (children);
+ }
+
+ g_slist_free (axes);
+}
+
+static void
+xlsx_axes_remove_deleted (XLSXReadState *state)
+{
+ GHashTableIter hiter;
+ gpointer key, val;
+
+ g_hash_table_iter_init (&hiter, state->axis.by_obj);
+ while (g_hash_table_iter_next (&hiter, &key, &val)) {
+ GogAxis *axis = key;
+ XLSXAxisInfo *info = val;
+ if (info->deleted) {
+ gboolean may_delete =
+ gog_object_is_deletable (GOG_OBJECT (axis));
#ifdef DEBUG_AXIS
- g_printerr ("Would like to delete auto axis %p (%s): %s\n",
- axis, gog_object_get_name (GOG_OBJECT (axis)),
- may_delete ? "allowed" : "not allowed");
+ g_printerr ("Would like to delete file axis %p (%s): %s\n",
+ axis,
+ gog_object_get_name (GOG_OBJECT (axis)),
+ may_delete ? "allowed" : "not allowed");
#endif
- if (may_delete) {
- gog_object_clear_parent (GOG_OBJECT (axis));
- g_object_unref (axis);
+ if (may_delete) {
+ gog_object_clear_parent (GOG_OBJECT (axis));
+ g_object_unref (axis);
+ }
}
}
- g_slist_free (list);
+}
- g_hash_table_foreach (state->axis.by_obj,
- (GHFunc)cb_axis_set_position, state);
+static void
+xlsx_axis_cleanup (XLSXReadState *state)
+{
+ GSList *axes, *l;
- /* Clean out file axes marked "deleted". */
- list = gog_object_get_children (GOG_OBJECT (state->chart), NULL);
- for (ptr = list; ptr != NULL ; ptr = ptr->next) {
- GogAxis *axis = ptr->data;
+ /* clean out axes that were auto created */
+ axes = xlsx_get_axes (GOG_OBJECT (state->chart));
+ for (l = axes; l; l = l->next) {
+ GogAxis *axis = l->data;
XLSXAxisInfo *info;
gboolean may_delete;
- if (!GOG_IS_AXIS (axis))
- continue;
-
info = g_hash_table_lookup (state->axis.by_obj, axis);
- if (!info || !info->deleted)
+ if (info)
continue;
may_delete = gog_object_is_deletable (GOG_OBJECT (axis));
#ifdef DEBUG_AXIS
- g_printerr ("Would like to delete file axis %p (%s): %s\n",
+ g_printerr ("Would like to delete auto axis %p (%s): %s\n",
axis, gog_object_get_name (GOG_OBJECT (axis)),
may_delete ? "allowed" : "not allowed");
#endif
@@ -2873,13 +2895,20 @@ xlsx_axis_cleanup (XLSXReadState *state)
g_object_unref (axis);
}
}
- g_slist_free (list);
+ g_slist_free (axes);
+
+ xlsx_axes_redirect_deleted (state);
+
+ g_hash_table_foreach (state->axis.by_obj,
+ (GHFunc)cb_axis_set_position, state);
+
+ xlsx_axes_remove_deleted (state);
g_hash_table_destroy (state->axis.by_obj);
g_hash_table_destroy (state->axis.by_id);
state->axis.by_obj = state->axis.by_id = NULL;
- xlsx_rename_axes (state);
+ xlsx_axes_rename (state);
}
static void
diff --git a/plugins/excel/xlsx-write-drawing.c b/plugins/excel/xlsx-write-drawing.c
index 0b81b14..b86a091 100644
--- a/plugins/excel/xlsx-write-drawing.c
+++ b/plugins/excel/xlsx-write-drawing.c
@@ -667,6 +667,11 @@ xlsx_write_axis (XLSXWriteState *state, GsfXMLOut *xml, GogPlot *plot, GogAxis *
gog_axis_is_discrete (axis));
#endif
+ g_object_get (G_OBJECT (axis),
+ "pos", &pos,
+ "map-name", &map_name,
+ NULL);
+
if (gog_axis_is_discrete (axis))
gsf_xml_out_start_element (xml, "c:catAx");
else
@@ -674,7 +679,6 @@ xlsx_write_axis (XLSXWriteState *state, GsfXMLOut *xml, GogPlot *plot, GogAxis *
xlsx_write_chart_uint (xml, "c:axId", xlsx_get_axid (state, axis));
gsf_xml_out_start_element (xml, "c:scaling");
- g_object_get (axis, "map-name", &map_name, NULL);
if (g_strcmp0 (map_name, "Log") == 0) {
double base = 10;
xlsx_write_chart_float (xml, "c:logBase", base);
@@ -689,8 +693,19 @@ xlsx_write_axis (XLSXWriteState *state, GsfXMLOut *xml, GogPlot *plot, GogAxis *
gsf_xml_out_end_element (xml);
xlsx_write_chart_uint (xml, "c:delete", 0);
- /* FIXME position might be "t" or "r" */
- xlsx_write_chart_cstr_unchecked (xml, "c:axPos", (at == GOG_AXIS_X || at == GOG_AXIS_CIRCULAR)? "b":
"l");
+
+ /*
+ * It is unclear what this is good for. The information is in the
+ * crossing location.
+ */
+ {
+ const char * const axpos[4] = { "l", "r", "b", "t" };
+ gboolean tb = (at == GOG_AXIS_X || at == GOG_AXIS_CIRCULAR);
+ gboolean tr = (pos == GOG_AXIS_AT_HIGH);
+ xlsx_write_chart_cstr_unchecked (xml,
+ "c:axPos",
+ axpos[2 * tb + tr]);
+ }
/* grids */
grid = gog_axis_get_grid_line (axis, TRUE);
@@ -742,7 +757,6 @@ xlsx_write_axis (XLSXWriteState *state, GsfXMLOut *xml, GogPlot *plot, GogAxis *
xlsx_write_go_style (xml, state, go_styled_object_get_style (GO_STYLED_OBJECT (axis)));
xlsx_write_chart_int (xml, "c:crossAx", xlsx_get_axid (state, crossed));
- g_object_get (G_OBJECT (axis), "pos", &pos, NULL);
switch (pos) {
default:
case GOG_AXIS_AT_LOW:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]