[gnumeric] Make graphs (and images) not resize with cells by default. [#684450]
- From: Jean Bréfort <jbrefort src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Make graphs (and images) not resize with cells by default. [#684450]
- Date: Mon, 30 Mar 2015 15:02:37 +0000 (UTC)
commit a57d6d8ccf7783813775be632de589942613cc2d
Author: Jean Brefort <jean brefort normalesup org>
Date: Mon Mar 30 17:00:54 2015 +0200
Make graphs (and images) not resize with cells by default. [#684450]
ChangeLog | 17 ++
NEWS | 2 +
plugins/excel/ChangeLog | 15 ++
plugins/excel/ms-chart.c | 2 +-
plugins/excel/ms-escher.c | 10 ++
plugins/excel/ms-excel-read.c | 20 ++-
plugins/excel/ms-excel-write.c | 12 ++-
plugins/excel/xlsx-read-drawing.c | 83 +++++++++--
plugins/excel/xlsx-read.c | 1 +
plugins/excel/xlsx-write-drawing.c | 40 +++++-
plugins/openoffice/ChangeLog | 7 +
plugins/openoffice/openoffice-read.c | 118 ++++++++++------
plugins/openoffice/openoffice-write.c | 93 ++++++++----
src/dialogs/ChangeLog | 7 +
src/dialogs/dialog-sheetobject-size.c | 57 +++++++-
src/graph.h | 1 +
src/item-grid.c | 2 +-
src/sheet-control-gui.c | 96 +++++++++----
src/sheet-filter.c | 2 +-
src/sheet-object-cell-comment.c | 2 +-
src/sheet-object-component.c | 21 +--
src/sheet-object-graph.c | 11 +-
src/sheet-object-image.c | 1 +
src/sheet-object.c | 234 ++++++++++++++++++++++++------
src/sheet-object.h | 13 ++-
src/tools/ChangeLog | 6 +
src/tools/dao.c | 3 +-
src/widgets/ChangeLog | 5 +
src/widgets/Makefile.am | 2 +
src/widgets/gnm-so-anchor-mode-chooser.c | 97 ++++++++++++
src/widgets/gnm-so-anchor-mode-chooser.h | 42 ++++++
src/workbook-view.c | 2 +-
src/xml-sax-read.c | 17 ++-
src/xml-sax-write.c | 7 +-
34 files changed, 848 insertions(+), 200 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 9fce848..232941d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2015-03-30 Jean Brefort <jean brefort normalesup org>
+
+ * src/graph.h: add support for absolute anchoring of sheet objects.
+ * src/item-grid.c: ditto.
+ * src/sheet-control-gui.c: ditto.
+ * src/sheet-filter.c: ditto.
+ * src/sheet-object-cell-comment.c: ditto.
+ * src/sheet-object-component.c: ditto.
+ * src/sheet-object-graph.c: ditto and make graphs not anymore resize with
+ cells by default. [#684450]
+ * src/sheet-object-image.c: make images don't resize with cells by default.
+ * src/sheet-object.c : add support for absolute anchoring of sheet objects.
+ * src/sheet-object.h: ditto.
+ * src/workbook-view.c: ditto.
+ * src/xml-sax-read.c: ditto.
+ * src/xml-sax-write.c: ditto.
+
2015-03-30 Morten Welinder <terra gnome org>
* src/xml-sax-read.c (grammar): Use new libgsf check for "2nd".
diff --git a/NEWS b/NEWS
index 95c1ea8..a89be5e 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,8 @@ Andreas:
Jean:
* Fix signal handling while running Python. [#744638]
+ * Implement absolute anchoring for sheet objects.
+ * Make graphs (and images) not resize with cells by default. [#684450]
Morten:
* xlsx import/export of log axis.
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index c9280da..3798843 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -1,3 +1,18 @@
+2015-03-30 Jean Brefort <jean brefort normalesup org>
+
+ * ms-chart.c (ms_excel_chart_read): support absolute sheet object anchoring.
+ * ms-escher.c (ms_escher_clientanchor): ditto.
+ * ms-excel-read.c (ms_sheet_obj_anchor_to_pos),
+ (ms_sheet_realize_obj): ditto.
+ * ms-excel-write.c (excel_write_autofilter_objs),
+ (excel_write_other_v8): ditto.
+ * xlsx-read-drawing.c (xlsx_draw_anchor_start),
+ (xlsx_drawing_twoCellAnchor_end), (xlsx_drawing_oneCellAnchor_end),
+ (xlsx_drawing_absoluteAnchor_end), (xlsx_drawing_anchor_pos),
+ (xlsx_vml_client_data_end): ditto.
+ * xlsx-read.c: ditto.
+ * xlsx-write-drawing.c (xlsx_write_drawing_objects): ditto.
+
2015-03-28 Morten Welinder <terra gnome org>
* xlsx-read-drawing.c (xlsx_axis_crossax): Improve parsing. Take
diff --git a/plugins/excel/ms-chart.c b/plugins/excel/ms-chart.c
index 31dab39..e90d9e5 100644
--- a/plugins/excel/ms-chart.c
+++ b/plugins/excel/ms-chart.c
@@ -3825,7 +3825,7 @@ ms_excel_chart_read (BiffQuery *q, MSContainer *container,
static GnmRange const fixed_size = { { 1, 1 }, { 12, 32 } };
SheetObjectAnchor anchor;
sheet_object_anchor_init (&anchor, &fixed_size, NULL,
- GOD_ANCHOR_DIR_DOWN_RIGHT);
+ GOD_ANCHOR_DIR_DOWN_RIGHT, GNM_SO_ANCHOR_TWO_CELLS);
sheet_object_set_anchor (sog, &anchor);
sheet_object_set_sheet (sog, full_page);
g_object_unref (sog);
diff --git a/plugins/excel/ms-escher.c b/plugins/excel/ms-escher.c
index 379b092..a265dca 100644
--- a/plugins/excel/ms-escher.c
+++ b/plugins/excel/ms-escher.c
@@ -2373,6 +2373,16 @@ ms_escher_clientanchor (GString *buf, SheetObjectAnchor const *anchor)
guint8 *p = tmp + 10;
GSF_LE_SET_GUINT32 (tmp + 4, sizeof (tmp) - 8);
+ switch (anchor->mode) {
+ case GNM_SO_ANCHOR_ONE_CELL:
+ tmp[8] = 2;
+ break;
+ case GNM_SO_ANCHOR_ABSOLUTE:
+ tmp[8] = 3;
+ break;
+ default:
+ break;
+ }
GSF_LE_SET_GUINT16 (p + 0, anchor->cell_bound.start.col);
GSF_LE_SET_GUINT16 (p + 2, (guint16)(anchor->offset[0]*1024. + .5));
GSF_LE_SET_GUINT16 (p + 4, anchor->cell_bound.start.row);
diff --git a/plugins/excel/ms-excel-read.c b/plugins/excel/ms-excel-read.c
index 4b54323..b547de2 100644
--- a/plugins/excel/ms-excel-read.c
+++ b/plugins/excel/ms-excel-read.c
@@ -391,7 +391,7 @@ static gboolean
ms_sheet_obj_anchor_to_pos (Sheet const * sheet,
G_GNUC_UNUSED MsBiffVersion const ver,
guint8 const *raw_anchor,
- GnmRange *range, double offset[4])
+ GnmRange *range, double offset[4], GnmSOAnchorMode *mode)
{
/* NOTE :
* gnm_float const row_denominator = (ver >= MS_BIFF_V8) ? 256. : 1024.;
@@ -407,6 +407,17 @@ ms_sheet_obj_anchor_to_pos (Sheet const * sheet,
gsf_mem_dump (raw_anchor, 18);
});
+ switch (raw_anchor[0]) {
+ case 2:
+ *mode = GNM_SO_ANCHOR_ONE_CELL;
+ break;
+ case 3:
+ *mode = GNM_SO_ANCHOR_ABSOLUTE;
+ break;
+ default:
+ *mode = GNM_SO_ANCHOR_TWO_CELLS;
+ break;
+ }
/* Ignore the first 2 bytes. What are they ? */
/* Dec/1/2000 JEG: I have not researched it, but this may have some
* flags indicating whether or not the object is anchored to the cell
@@ -494,6 +505,7 @@ ms_sheet_realize_obj (MSContainer *container, MSObj *obj)
SheetObjectAnchor anchor;
SheetObject *so;
GOStyle *style;
+ GnmSOAnchorMode mode = GNM_SO_ANCHOR_TWO_CELLS;
if (obj == NULL)
return TRUE;
@@ -518,7 +530,7 @@ ms_sheet_realize_obj (MSContainer *container, MSObj *obj)
}
if (ms_sheet_obj_anchor_to_pos (esheet->sheet, container->importer->ver,
- attr->v.v_ptr, &range, offsets))
+ attr->v.v_ptr, &range, offsets, &mode))
return TRUE;
flip_h = ms_obj_attr_bag_lookup (obj->attrs, MS_OBJ_ATTR_FLIP_H);
@@ -527,10 +539,12 @@ ms_sheet_realize_obj (MSContainer *container, MSObj *obj)
((flip_h == NULL) ? GOD_ANCHOR_DIR_RIGHT : 0) |
((flip_v == NULL) ? GOD_ANCHOR_DIR_DOWN : 0);
- sheet_object_anchor_init (&anchor, &range, offsets, direction);
+ sheet_object_anchor_init (&anchor, &range, offsets, direction, GNM_SO_ANCHOR_TWO_CELLS);
sheet_object_set_anchor (so, &anchor);
}
sheet_object_set_sheet (so, esheet->sheet);
+ if (mode != GNM_SO_ANCHOR_TWO_CELLS)
+ sheet_object_set_anchor_mode (so, &mode);
{
gpointer label;
diff --git a/plugins/excel/ms-excel-write.c b/plugins/excel/ms-excel-write.c
index 7daf59b..cc2ab5c 100644
--- a/plugins/excel/ms-excel-write.c
+++ b/plugins/excel/ms-excel-write.c
@@ -4251,7 +4251,7 @@ excel_write_autofilter_objs (ExcelWriteSheet *esheet)
r.end.col = 1 + (r.start.col = filter->r.start.col + i);
sheet_object_anchor_init (&anchor, &r, NULL,
- GOD_ANCHOR_DIR_DOWN_RIGHT);
+ GOD_ANCHOR_DIR_DOWN_RIGHT, GNM_SO_ANCHOR_TWO_CELLS);
if (bp->version >= MS_BIFF_V8) {
guint32 id = excel_write_start_drawing (esheet);
memcpy (buf, obj_v8, sizeof obj_v8);
@@ -4615,6 +4615,14 @@ excel_write_other_v8 (ExcelWriteSheet *esheet,
? g_hash_table_lookup (esheet->widget_macroname, so)
: NULL;
+ if (anchor.mode != GNM_SO_ANCHOR_TWO_CELLS) {
+ double pts[4];
+ GnmSOAnchorMode mode = anchor.mode;
+ sheet_object_anchor_to_pts (&anchor, esheet->gnum_sheet, pts);
+ anchor.mode = GNM_SO_ANCHOR_TWO_CELLS;
+ sheet_object_pts_to_anchor (&anchor, esheet->gnum_sheet, pts);
+ anchor.mode = mode; /* this anchor is not valid for gnumeric but is what we need there */
+ }
if (GNM_IS_CELL_COMMENT (so)) {
static double const offset[4] = { .5, .5, .5, .5 };
GnmRange r;
@@ -4625,7 +4633,7 @@ excel_write_other_v8 (ExcelWriteSheet *esheet,
r.end.col = r.start.col + 2;
r.end.row = r.start.row + 4;
sheet_object_anchor_init (&anchor, &r, offset,
- GOD_ANCHOR_DIR_DOWN_RIGHT);
+ GOD_ANCHOR_DIR_DOWN_RIGHT, GNM_SO_ANCHOR_TWO_CELLS);
type = MSOT_COMMENT;
flags = 0x4011; /* not autofilled */
do_textbox = TRUE;
diff --git a/plugins/excel/xlsx-read-drawing.c b/plugins/excel/xlsx-read-drawing.c
index 887ab8e..d557e7e 100644
--- a/plugins/excel/xlsx-read-drawing.c
+++ b/plugins/excel/xlsx-read-drawing.c
@@ -3116,6 +3116,7 @@ xlsx_draw_anchor_start (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
memset ((gpointer)state->drawing_pos, 0, sizeof (state->drawing_pos));
state->drawing_pos_flags = 0;
state->so_direction = GOD_ANCHOR_DIR_DOWN_RIGHT;
+ state->so_anchor_mode = GNM_SO_ANCHOR_TWO_CELLS;
}
static void
@@ -3135,7 +3136,7 @@ xlsx_drawing_twoCellAnchor_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
GnmRange r;
double coords[4];
double size;
- int i;
+ int i, max;
range_init (&r,
state->drawing_pos[COL | FROM],
@@ -3143,19 +3144,34 @@ xlsx_drawing_twoCellAnchor_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
state->drawing_pos[COL | TO],
state->drawing_pos[ROW | TO]);
+ switch (state->so_anchor_mode) {
+ default:
+ case GNM_SO_ANCHOR_TWO_CELLS:
+ max = 8;
+ break;
+ case GNM_SO_ANCHOR_ONE_CELL:
+ max = 4;
+ break;
+ case GNM_SO_ANCHOR_ABSOLUTE:
+ max = 0;
+ break;
+ }
for (i = 0; i < 8; i+=2) {
ColRowInfo const *cri;
- if (i & 2) {
- cri = sheet_row_get (state->sheet, state->drawing_pos[i]);
- size = cri? cri->size_pts: sheet_row_get_default_size_pts (state->sheet);
- } else {
- cri = sheet_col_get (state->sheet, state->drawing_pos[i]);
- /* FIXME: scaling horizontally just like in xlsx_CT_Col */
- size = (cri? cri->size_pts: sheet_col_get_default_size_pts (state->sheet)) *
1.16191275167785;
- }
- coords[i / 2] = (double) state->drawing_pos[i + 1] / 12700. / size;
+ if (i < max) {
+ if (i & 2) {
+ cri = sheet_row_get (state->sheet, state->drawing_pos[i]);
+ size = cri? cri->size_pts: sheet_row_get_default_size_pts
(state->sheet);
+ } else {
+ cri = sheet_col_get (state->sheet, state->drawing_pos[i]);
+ /* FIXME: scaling horizontally just like in xlsx_CT_Col */
+ size = (cri? cri->size_pts: sheet_col_get_default_size_pts
(state->sheet)) * 1.16191275167785;
+ }
+ coords[i / 2] = (double) state->drawing_pos[i + 1] / 12700. / size;
+ } else
+ coords[i / 2] = (double) state->drawing_pos[i + 1] / 12700.;
}
- sheet_object_anchor_init (&anchor, &r, coords, state->so_direction);
+ sheet_object_anchor_init (&anchor, &r, coords, state->so_direction, state->so_anchor_mode);
sheet_object_set_anchor (state->so, &anchor);
if (state->cur_style &&
g_object_class_find_property (G_OBJECT_GET_CLASS (state->so), "style"))
@@ -3177,13 +3193,36 @@ xlsx_drawing_oneCellAnchor_end (GsfXMLIn *xin, GsfXMLBlob *blob)
{
XLSXReadState *state = (XLSXReadState *)xin->user_state;
- state->drawing_pos[COL | TO] = state->drawing_pos[COL | FROM] + 5;
- state->drawing_pos[ROW | TO] = state->drawing_pos[ROW | FROM] + 5;
+ state->drawing_pos[COL | TO] = state->drawing_pos[COL | FROM];
+ state->drawing_pos[ROW | TO] = state->drawing_pos[ROW | FROM];
state->drawing_pos_flags |= ((1 << (COL | TO)) | (1 << (ROW | TO)));
+ state->so_anchor_mode = GNM_SO_ANCHOR_ONE_CELL;
+ xlsx_drawing_twoCellAnchor_end (xin, blob);
+}
+
+static void
+xlsx_drawing_absoluteAnchor_end (GsfXMLIn *xin, GsfXMLBlob *blob)
+{
+ XLSXReadState *state = (XLSXReadState *)xin->user_state;
+
+ state->drawing_pos_flags |= ((1 << (COL | TO)) | (1 << (ROW | TO)) |
+ (1 << (COL | FROM)) | (1 << (ROW | FROM)));
+ state->so_anchor_mode = GNM_SO_ANCHOR_ABSOLUTE;
xlsx_drawing_twoCellAnchor_end (xin, blob);
}
static void
+xlsx_drawing_anchor_pos (GsfXMLIn *xin, xmlChar const **attrs)
+{
+ XLSXReadState *state = (XLSXReadState *)xin->user_state;
+ for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
+ if (attr_int64 (xin, attrs, "x", state->drawing_pos + (COL | FROM | OFFSET)))
+ state->drawing_pos_flags |= (1 << (COL | FROM | OFFSET));
+ else if (attr_int64 (xin, attrs, "y", state->drawing_pos + (ROW | FROM | OFFSET)))
+ state->drawing_pos_flags |= (1 << (ROW | FROM | OFFSET));
+}
+
+static void
xlsx_drawing_ext (GsfXMLIn *xin, xmlChar const **attrs)
{
XLSXReadState *state = (XLSXReadState *)xin->user_state;
@@ -3500,6 +3539,22 @@ GSF_XML_IN_NODE_FULL (START, DRAWING, XL_NS_SS_DRAW, "wsDr", GSF_XML_NO_CONTENT,
GSF_XML_IN_NODE (ONE_CELL, ONE_CELL_EXT, XL_NS_SS_DRAW, "ext", GSF_XML_NO_CONTENT, &xlsx_drawing_ext,
NULL),
GSF_XML_IN_NODE (ONE_CELL, CLIENT_DATA, XL_NS_SS_DRAW, "clientData", GSF_XML_NO_CONTENT, NULL, NULL),
/* 2nd Def */
GSF_XML_IN_NODE (ONE_CELL, GRAPHIC_FRAME, XL_NS_SS_DRAW, "graphicFrame", GSF_XML_NO_CONTENT, NULL,
NULL), /* 2nd Def */
+ GSF_XML_IN_NODE (ONE_CELL, SHAPE, XL_NS_SS_DRAW, "sp", GSF_XML_NO_CONTENT, NULL, NULL), /*
2nd Def */
+ GSF_XML_IN_NODE (ONE_CELL, CLIENT_DATA, XL_NS_SS_DRAW, "clientData", GSF_XML_NO_CONTENT, NULL, NULL),
/* 2nd Def */
+ GSF_XML_IN_NODE (ONE_CELL, CONTENT_PART, XL_NS_SS_DRAW, "contentPart", GSF_XML_NO_CONTENT, NULL, NULL),
/* 2nd Def */
+ GSF_XML_IN_NODE (ONE_CELL, CXN_SP, XL_NS_SS_DRAW, "cxnSp", GSF_XML_NO_CONTENT, NULL, NULL),
/* 2nd Def */
+ GSF_XML_IN_NODE (ONE_CELL, PICTURE, XL_NS_SS_DRAW, "pic", GSF_XML_NO_CONTENT, NULL, NULL), /*
2nd Def */
+ GSF_XML_IN_NODE (DRAWING, ABSOLUTE, XL_NS_SS_DRAW, "absoluteAnchor", GSF_XML_NO_CONTENT,
+ &xlsx_draw_anchor_start, &xlsx_drawing_absoluteAnchor_end),
+ GSF_XML_IN_NODE (ABSOLUTE, ABSOLUTE_POS, XL_NS_SS_DRAW, "pos", GSF_XML_NO_CONTENT,
&xlsx_drawing_anchor_pos, NULL),
+ GSF_XML_IN_NODE (ABSOLUTE, ONE_CELL_EXT, XL_NS_SS_DRAW, "ext", GSF_XML_NO_CONTENT, NULL, NULL),
/* 2nd Def */
+ GSF_XML_IN_NODE (ABSOLUTE, CLIENT_DATA, XL_NS_SS_DRAW, "clientData", GSF_XML_NO_CONTENT, NULL, NULL),
/* 2nd Def */
+ GSF_XML_IN_NODE (ABSOLUTE, GRAPHIC_FRAME, XL_NS_SS_DRAW, "graphicFrame", GSF_XML_NO_CONTENT, NULL,
NULL), /* 2nd Def */
+ GSF_XML_IN_NODE (ABSOLUTE, SHAPE, XL_NS_SS_DRAW, "sp", GSF_XML_NO_CONTENT, NULL, NULL), /*
2nd Def */
+ GSF_XML_IN_NODE (ABSOLUTE, CLIENT_DATA, XL_NS_SS_DRAW, "clientData", GSF_XML_NO_CONTENT, NULL, NULL),
/* 2nd Def */
+ GSF_XML_IN_NODE (ABSOLUTE, CONTENT_PART, XL_NS_SS_DRAW, "contentPart", GSF_XML_NO_CONTENT, NULL, NULL),
/* 2nd Def */
+ GSF_XML_IN_NODE (ABSOLUTE, CXN_SP, XL_NS_SS_DRAW, "cxnSp", GSF_XML_NO_CONTENT, NULL, NULL),
/* 2nd Def */
+ GSF_XML_IN_NODE (ABSOLUTE, PICTURE, XL_NS_SS_DRAW, "pic", GSF_XML_NO_CONTENT, NULL, NULL), /*
2nd Def */
GSF_XML_IN_NODE_END
};
@@ -3796,7 +3851,7 @@ xlsx_vml_client_data_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
}
r.end.row = pos;
coords[3] = (state->chart_pos[3] - sum) / size;
- sheet_object_anchor_init (&anchor, &r, coords, state->so_direction);
+ sheet_object_anchor_init (&anchor, &r, coords, state->so_direction, state->so_anchor_mode);
sheet_object_set_anchor (state->so, &anchor);
if (GNM_IS_SOW_LIST (state->so) ||
GNM_IS_SOW_COMBO (state->so))
diff --git a/plugins/excel/xlsx-read.c b/plugins/excel/xlsx-read.c
index 33708e4..61ef640 100644
--- a/plugins/excel/xlsx-read.c
+++ b/plugins/excel/xlsx-read.c
@@ -196,6 +196,7 @@ typedef struct {
gint64 drawing_pos[8];
int drawing_pos_flags;
GODrawingAnchorDir so_direction;
+ GnmSOAnchorMode so_anchor_mode;
GnmExprTop const *link_texpr;
/* Legacy drawing state */
diff --git a/plugins/excel/xlsx-write-drawing.c b/plugins/excel/xlsx-write-drawing.c
index da6bd6d..e64ab84 100644
--- a/plugins/excel/xlsx-write-drawing.c
+++ b/plugins/excel/xlsx-write-drawing.c
@@ -1359,11 +1359,41 @@ xlsx_write_drawing_objects (XLSXWriteState *state, GsfOutput *sheet_part,
sheet_object_anchor_to_offset_pts (anchor, state->sheet, res_pts);
- gsf_xml_out_start_element (xml, "xdr:twoCellAnchor");
- xlsx_write_object_anchor (xml, &anchor->cell_bound.start, "xdr:from",
- res_pts[0], res_pts[1]);
- xlsx_write_object_anchor (xml, &anchor->cell_bound.end, "xdr:to",
- res_pts[2], res_pts[3]);
+ switch (anchor->mode) {
+ case GNM_SO_ANCHOR_TWO_CELLS:
+ gsf_xml_out_start_element (xml, "xdr:twoCellAnchor");
+ xlsx_write_object_anchor (xml, &anchor->cell_bound.start, "xdr:from",
+ res_pts[0], res_pts[1]);
+ xlsx_write_object_anchor (xml, &anchor->cell_bound.end, "xdr:to",
+ res_pts[2], res_pts[3]);
+ break;
+ case GNM_SO_ANCHOR_ONE_CELL:
+ gsf_xml_out_start_element (xml, "xdr:oneCellAnchor");
+ xlsx_write_object_anchor (xml, &anchor->cell_bound.start, "xdr:from",
+ res_pts[0], res_pts[1]);
+ gsf_xml_out_start_element (xml, "xdr:ext");
+ gsf_xml_out_add_int (xml, "cx",
+ xlsx_pts_to_emu (anchor->offset[2]));
+ gsf_xml_out_add_int (xml, "cy",
+ xlsx_pts_to_emu (anchor->offset[3]));
+ gsf_xml_out_end_element (xml);
+ break;
+ case GNM_SO_ANCHOR_ABSOLUTE:
+ gsf_xml_out_start_element (xml, "xdr:absoluteAnchor");
+ gsf_xml_out_start_element (xml, "xdr:pos");
+ gsf_xml_out_add_int (xml, "x",
+ xlsx_pts_to_emu (anchor->offset[0]));
+ gsf_xml_out_add_int (xml, "y",
+ xlsx_pts_to_emu (anchor->offset[1]));
+ gsf_xml_out_end_element (xml);
+ gsf_xml_out_start_element (xml, "xdr:ext");
+ gsf_xml_out_add_int (xml, "cx",
+ xlsx_pts_to_emu (anchor->offset[2]));
+ gsf_xml_out_add_int (xml, "cy",
+ xlsx_pts_to_emu (anchor->offset[3]));
+ gsf_xml_out_end_element (xml);
+ break;
+ }
if (GNM_IS_SO_GRAPH (so)) {
char *tmp;
diff --git a/plugins/openoffice/ChangeLog b/plugins/openoffice/ChangeLog
index c3801af..fd4d9f1 100644
--- a/plugins/openoffice/ChangeLog
+++ b/plugins/openoffice/ChangeLog
@@ -1,3 +1,10 @@
+2015-03-30 Jean Brefort <jean brefort normalesup org>
+
+ * openoffice-read.c (odf_shapes), (odf_shapes_end), (oo_table_end),
+ (od_draw_frame_start), (odf_line): support absolute sheet object anchoring.
+ * openoffice-write.c (odf_write_frame_size), (odf_write_line),
+ (odf_sheet_objects_get), (odf_write_content): ditto.
+
2015-03-22 Andreas J. Guelzow <aguelzow pyrshep ca>
* openoffice-write.c (-odf_write_circle_axes_styles): deleted
diff --git a/plugins/openoffice/openoffice-read.c b/plugins/openoffice/openoffice-read.c
index 0712a62..a36d27b 100644
--- a/plugins/openoffice/openoffice-read.c
+++ b/plugins/openoffice/openoffice-read.c
@@ -2475,6 +2475,20 @@ oo_table_start (GsfXMLIn *xin, xmlChar const **attrs)
}
static void
+odf_shapes (GsfXMLIn *xin, xmlChar const **attrs)
+{
+ OOParseState *state = (OOParseState *)xin->user_state;
+ state->pos.eval.col = -1; /* we use that to know that objects have absolute anchors */
+}
+
+static void
+odf_shapes_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
+{
+ OOParseState *state = (OOParseState *)xin->user_state;
+ state->pos.eval.col = 0;
+}
+
+static void
odf_init_pp (GnmParsePos *pp, GsfXMLIn *xin, gchar const *base)
{
OOParseState *state = (OOParseState *)xin->user_state;
@@ -2969,7 +2983,6 @@ odf_validation_help_message_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
odf_pop_text_p (state);
}
-
static void
odf_adjust_offsets_col (OOParseState *state, int *col, double *x, gboolean absolute)
{
@@ -3185,12 +3198,16 @@ oo_table_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
SheetObjectAnchor const *old = sheet_object_get_anchor (ob_off->so);
GnmRange cell_base = *sheet_object_get_range (ob_off->so);
- odf_adjust_offsets (state, &cell_base.start, &ob_off->frame_offset[0],
- &ob_off->frame_offset[1], ob_off->absolute_distance);
- odf_adjust_offsets (state, &cell_base.end, &ob_off->frame_offset[2],
- &ob_off->frame_offset[3], ob_off->absolute_distance);
+ if (old->mode != GNM_SO_ANCHOR_ABSOLUTE) {
+ odf_adjust_offsets (state, &cell_base.start, &ob_off->frame_offset[0],
+ &ob_off->frame_offset[1], ob_off->absolute_distance);
+ if (old->mode == GNM_SO_ANCHOR_TWO_CELLS)
+ odf_adjust_offsets (state, &cell_base.end, &ob_off->frame_offset[2],
+ &ob_off->frame_offset[3], ob_off->absolute_distance);
+ }
sheet_object_anchor_init (&new, &cell_base, ob_off->frame_offset,
- old->base.direction);
+ old->base.direction,
+ old->mode);
sheet_object_set_anchor (ob_off->so, &new);
sheet_object_set_sheet (ob_off->so, state->pos.sheet);
@@ -7933,9 +7950,9 @@ od_draw_frame_start (GsfXMLIn *xin, xmlChar const **attrs)
GnmRange cell_base;
double frame_offset[4];
gdouble height = 0., width = 0., x = 0., y = 0., end_x = 0., end_y = 0.;
- ColRowInfo const *col, *row;
GnmExprTop const *texpr = NULL;
int z = -1;
+ GnmSOAnchorMode mode;
height = width = x = y = 0.;
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2){
@@ -7964,39 +7981,43 @@ od_draw_frame_start (GsfXMLIn *xin, xmlChar const **attrs)
;
}
- cell_base.start.col = cell_base.end.col = state->pos.eval.col;
- cell_base.start.row = cell_base.end.row = state->pos.eval.row;
-
- col = sheet_col_get_info (state->pos.sheet, state->pos.eval.col);
- row = sheet_row_get_info (state->pos.sheet, state->pos.eval.row);
-
frame_offset[0] = x;
frame_offset[1] = y;
+ if (state->pos.eval.col >= 0) {
+ cell_base.start.col = cell_base.end.col = state->pos.eval.col;
+ cell_base.start.row = cell_base.end.row = state->pos.eval.row;
+
+ if (texpr == NULL || (GNM_EXPR_GET_OPER (texpr->expr) != GNM_EXPR_OP_CELLREF)) {
+ cell_base.end.col = cell_base.start.col;
+ cell_base.end.row = cell_base.start.row;
+ frame_offset[2] = width;
+ frame_offset[3] = height;
+ mode = GNM_SO_ANCHOR_ONE_CELL;
- if (texpr == NULL || (GNM_EXPR_GET_OPER (texpr->expr) != GNM_EXPR_OP_CELLREF)) {
- frame_offset[2] = x+width;
- frame_offset[3] = y+height;
+ } else {
+ GnmCellRef const *ref = &texpr->expr->cellref.ref;
+ cell_base.end.col = ref->col;
+ cell_base.end.row = ref->row;
+ frame_offset[2] = end_x;
+ frame_offset[3] = end_y ;
+ mode = GNM_SO_ANCHOR_TWO_CELLS;
+ }
+ if (texpr)
+ gnm_expr_top_unref (texpr);
} else {
- GnmCellRef const *ref = &texpr->expr->cellref.ref;
- cell_base.end.col = ref->col;
- cell_base.end.row = ref->row;
- frame_offset[2] = end_x;
- frame_offset[3] = end_y ;
+ cell_base.end.col = cell_base.start.col =
+ cell_base.end.row = cell_base.start.row = 0; /* actually not needed */
+ frame_offset[2] = width;
+ frame_offset[3] = height;
+ mode = GNM_SO_ANCHOR_ABSOLUTE;
}
odf_draw_frame_store_location (state, frame_offset,
(height > 0) ? height : go_nan,
(width > 0) ? width : go_nan);
- frame_offset[0] /= col->size_pts;
- frame_offset[1] /= row->size_pts;
- frame_offset[2] /= col->size_pts;
- frame_offset[3] /= row->size_pts;
-
- if (texpr)
- gnm_expr_top_unref (texpr);
sheet_object_anchor_init (&state->chart.anchor, &cell_base, frame_offset,
- GOD_ANCHOR_DIR_DOWN_RIGHT);
+ GOD_ANCHOR_DIR_DOWN_RIGHT, mode);
state->chart.so = NULL;
state->chart.z_index = z;
}
@@ -10496,16 +10517,16 @@ odf_line (GsfXMLIn *xin, xmlChar const **attrs)
{
OOParseState *state = (OOParseState *)xin->user_state;
gnm_float x1 = 0., x2 = 0., y1 = 0., y2 = 0.;
- ColRowInfo const *col, *row;
GODrawingAnchorDir direction;
GnmRange cell_base;
double frame_offset[4];
char const *style_name = NULL;
gdouble height, width;
int z = -1;
-
- cell_base.start.col = cell_base.end.col = state->pos.eval.col;
- cell_base.start.row = cell_base.end.row = state->pos.eval.row;
+ GnmSOAnchorMode mode;
+ cell_base.start.col = state->pos.eval.col;
+ cell_base.start.row = state->pos.eval.row;
+ cell_base.end.col = cell_base.end.row = -1;
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]),
@@ -10567,20 +10588,31 @@ odf_line (GsfXMLIn *xin, xmlChar const **attrs)
height = y1 - y2;
}
+ if (state->pos.eval.col >= 0) {
+ if (cell_base.end.col >= 0) {
+ mode = GNM_SO_ANCHOR_TWO_CELLS;
+ } else {
+ cell_base.end.col = cell_base.start.col;
+ cell_base.end.row = cell_base.start.row;
+ frame_offset[2] = width;
+ frame_offset[3] = height;
+ mode = GNM_SO_ANCHOR_ONE_CELL;
+ }
+ } else {
+ cell_base.end.col = cell_base.start.col =
+ cell_base.end.row = cell_base.start.row = 0; /* actually not needed */
+ frame_offset[2] = width;
+ frame_offset[3] = height;
+ mode = GNM_SO_ANCHOR_ABSOLUTE;
+ }
+
odf_draw_frame_store_location (state, frame_offset,
height, width);
- col = sheet_col_get_info (state->pos.sheet, cell_base.start.col);
- row = sheet_row_get_info (state->pos.sheet, cell_base.start.row);
- frame_offset[0] /= col->size_pts;
- frame_offset[1] /= row->size_pts;
- frame_offset[2] /= col->size_pts;
- frame_offset[3] /= row->size_pts;
-
-
sheet_object_anchor_init (&state->chart.anchor, &cell_base,
frame_offset,
- direction);
+ direction,
+ mode);
state->chart.so = g_object_new (GNM_SO_LINE_TYPE, NULL);
if (style_name != NULL) {
@@ -11954,7 +11986,7 @@ static GsfXMLInNode const opendoc_content_dtd [] =
GSF_XML_IN_NODE (TABLE, SHEET_SELECTIONS, OO_GNUM_NS_EXT, "selections", GSF_XML_NO_CONTENT,
&odf_selection, &odf_selection_end),
GSF_XML_IN_NODE (SHEET_SELECTIONS, SELECTION, OO_GNUM_NS_EXT, "selection",
GSF_XML_NO_CONTENT, &odf_selection_range, NULL),
GSF_XML_IN_NODE (TABLE, TABLE_SOURCE, OO_NS_TABLE, "table-source", GSF_XML_NO_CONTENT, NULL,
NULL),
- GSF_XML_IN_NODE (TABLE, TABLE_SHAPES, OO_NS_TABLE, "shapes", GSF_XML_NO_CONTENT, NULL, NULL),
+ GSF_XML_IN_NODE (TABLE, TABLE_SHAPES, OO_NS_TABLE, "shapes", GSF_XML_NO_CONTENT, &odf_shapes,
&odf_shapes_end),
GSF_XML_IN_NODE (TABLE_SHAPES, DRAW_FRAME, OO_NS_DRAW, "frame", GSF_XML_NO_CONTENT,
&od_draw_frame_start, &od_draw_frame_end),
GSF_XML_IN_NODE (TABLE_SHAPES, DRAW_CAPTION, OO_NS_DRAW, "caption", GSF_XML_NO_CONTENT,
&odf_caption, &od_draw_text_frame_end),
GSF_XML_IN_NODE (DRAW_CAPTION, TEXT_CONTENT, OO_NS_TEXT, "p", GSF_XML_NO_CONTENT, NULL,
NULL), /* 2nd def */
diff --git a/plugins/openoffice/openoffice-write.c b/plugins/openoffice/openoffice-write.c
index a1e5c4d..ad6e316 100644
--- a/plugins/openoffice/openoffice-write.c
+++ b/plugins/openoffice/openoffice-write.c
@@ -2840,25 +2840,40 @@ odf_write_frame_size (GnmOOExport *state, SheetObject *so)
sheet_object_anchor_to_offset_pts (anchor, state->sheet, res_pts);
- odf_add_pt (state->xml, SVG "x", res_pts[0]);
- odf_add_pt (state->xml, SVG "y", res_pts[1]);
- odf_add_pt (state->xml, TABLE "end-x", res_pts[2]);
- odf_add_pt (state->xml, TABLE "end-y", res_pts[3]);
-
- /* The next 3 lines should not be needed, but older versions of Gnumeric used the */
- /* width and height. */
- sheet_object_anchor_to_pts (anchor, state->sheet, res_pts);
- odf_add_pt (state->xml, SVG "width", res_pts[2] - res_pts[0]);
- odf_add_pt (state->xml, SVG "height", res_pts[3] - res_pts[1]);
-
- gnm_cellref_init (&ref, (Sheet *) state->sheet, r->end.col, r->end.row, TRUE);
- texpr = gnm_expr_top_new (gnm_expr_new_cellref (&ref));
- parse_pos_init_sheet (&pp, state->sheet);
- formula = gnm_expr_top_as_string (texpr, &pp, state->conv);
- gnm_expr_top_unref (texpr);
- gsf_xml_out_add_cstr (state->xml, TABLE "end-cell-address",
- odf_strip_brackets (formula));
- g_free (formula);
+ switch (anchor->mode) {
+ case GNM_SO_ANCHOR_TWO_CELLS:
+ odf_add_pt (state->xml, SVG "x", res_pts[0]);
+ odf_add_pt (state->xml, SVG "y", res_pts[1]);
+ odf_add_pt (state->xml, TABLE "end-x", res_pts[2]);
+ odf_add_pt (state->xml, TABLE "end-y", res_pts[3]);
+ /* The next 3 lines should not be needed, but older versions of Gnumeric used the */
+ /* width and height. */
+ sheet_object_anchor_to_pts (anchor, state->sheet, res_pts);
+ odf_add_pt (state->xml, SVG "width", res_pts[2] - res_pts[0]);
+ odf_add_pt (state->xml, SVG "height", res_pts[3] - res_pts[1]);
+
+ gnm_cellref_init (&ref, (Sheet *) state->sheet, r->end.col, r->end.row, TRUE);
+ texpr = gnm_expr_top_new (gnm_expr_new_cellref (&ref));
+ parse_pos_init_sheet (&pp, state->sheet);
+ formula = gnm_expr_top_as_string (texpr, &pp, state->conv);
+ gnm_expr_top_unref (texpr);
+ gsf_xml_out_add_cstr (state->xml, TABLE "end-cell-address",
+ odf_strip_brackets (formula));
+ g_free (formula);
+ break;
+ case GNM_SO_ANCHOR_ONE_CELL:
+ odf_add_pt (state->xml, SVG "x", res_pts[0]);
+ odf_add_pt (state->xml, SVG "y", res_pts[1]);
+ odf_add_pt (state->xml, SVG "width", anchor->offset[2]);
+ odf_add_pt (state->xml, SVG "height", anchor->offset[3]);
+ break;
+ case GNM_SO_ANCHOR_ABSOLUTE:
+ odf_add_pt (state->xml, SVG "x", anchor->offset[0]);
+ odf_add_pt (state->xml, SVG "y", anchor->offset[1]);
+ odf_add_pt (state->xml, SVG "width", anchor->offset[2]);
+ odf_add_pt (state->xml, SVG "height", anchor->offset[3]);
+ break;
+ }
sheet = sheet_object_get_sheet (so);
if (sheet) {
@@ -3186,9 +3201,6 @@ odf_write_line (GnmOOExport *state, SheetObject *so)
sheet_object_get_stacking (so);
gsf_xml_out_add_int (state->xml, DRAW "z-index", z);
- sheet_object_anchor_to_offset_pts (anchor, state->sheet, res_pts);
- odf_add_pt (state->xml, TABLE "end-x", res_pts[2]);
- odf_add_pt (state->xml, TABLE "end-y", res_pts[3]);
sheet_object_anchor_to_pts (anchor, state->sheet, res_pts);
switch (anchor->base.direction) {
@@ -3225,14 +3237,20 @@ odf_write_line (GnmOOExport *state, SheetObject *so)
odf_add_pt (state->xml, SVG "x2", x2);
odf_add_pt (state->xml, SVG "y2", y2);
- gnm_cellref_init (&ref, (Sheet *) state->sheet, r->end.col, r->end.row, TRUE);
- texpr = gnm_expr_top_new (gnm_expr_new_cellref (&ref));
- parse_pos_init_sheet (&pp, state->sheet);
- formula = gnm_expr_top_as_string (texpr, &pp, state->conv);
- gnm_expr_top_unref (texpr);
- gsf_xml_out_add_cstr (state->xml, TABLE "end-cell-address",
- odf_strip_brackets (formula));
- g_free (formula);
+ if (anchor->mode == GNM_SO_ANCHOR_TWO_CELLS) {
+ sheet_object_anchor_to_offset_pts (anchor, state->sheet, res_pts);
+ odf_add_pt (state->xml, TABLE "end-x", res_pts[2]);
+ odf_add_pt (state->xml, TABLE "end-y", res_pts[3]);
+
+ gnm_cellref_init (&ref, (Sheet *) state->sheet, r->end.col, r->end.row, TRUE);
+ texpr = gnm_expr_top_new (gnm_expr_new_cellref (&ref));
+ parse_pos_init_sheet (&pp, state->sheet);
+ formula = gnm_expr_top_as_string (texpr, &pp, state->conv);
+ gnm_expr_top_unref (texpr);
+ gsf_xml_out_add_cstr (state->xml, TABLE "end-cell-address",
+ odf_strip_brackets (formula));
+ g_free (formula);
+ }
gsf_xml_out_end_element (state->xml); /* DRAW "line" */
}
@@ -3710,7 +3728,10 @@ odf_sheet_objects_get (Sheet const *sheet, GnmCellPos const *pos)
for (ptr = sheet->sheet_objects; ptr != NULL ; ptr = ptr->next ) {
SheetObject *so = GNM_SO (ptr->data);
SheetObjectAnchor const *anchor = sheet_object_get_anchor (so);
- if (gnm_cellpos_equal (&anchor->cell_bound.start, pos))
+ if (anchor->mode == GNM_SO_ANCHOR_ABSOLUTE) {
+ if (pos == NULL)
+ res = g_slist_prepend (res, so);
+ } else if (pos && gnm_cellpos_equal (&anchor->cell_bound.start, pos))
res = g_slist_prepend (res, so);
}
return res;
@@ -4855,6 +4876,7 @@ odf_write_content (GnmOOExport *state, GsfOutput *child)
int graph_n = 1;
int image_n = 1;
gboolean has_autofilters = FALSE;
+ GSList *objects;
state->xml = create_new_xml_child (state, child);
gsf_xml_out_set_doc_type (state->xml, "\n");
@@ -4939,6 +4961,15 @@ odf_write_content (GnmOOExport *state, GsfOutput *child)
g_free (formula);
}
+ /* writing shapes with absolute anchors */
+ objects = odf_sheet_objects_get (sheet, NULL);
+ if (objects != NULL) {
+ gsf_xml_out_start_element (state->xml, TABLE "shapes");
+ odf_write_objects (state, objects);
+ gsf_xml_out_end_element (state->xml);
+ g_slist_free (objects);
+ }
+
odf_write_sheet_controls (state);
odf_write_sheet (state);
if (state->odf_version > 101 && sheet->names) {
diff --git a/src/dialogs/ChangeLog b/src/dialogs/ChangeLog
index 35dd15b..17d1c7c 100644
--- a/src/dialogs/ChangeLog
+++ b/src/dialogs/ChangeLog
@@ -1,3 +1,10 @@
+2015-03-30 Jean Brefort <jean brefort normalesup org>
+
+ * dialog-sheetobject-size.c (dialog_so_size_button_sensitivity),
+ (set_mode), (cb_dialog_so_size_apply_clicked),
+ (cb_dialog_so_size_mode_changed), (dialog_so_size): support relative and
+ absolute anchoring.
+
2015-03-04 Morten Welinder <terra gnome org>
* Release 1.12.21
diff --git a/src/dialogs/dialog-sheetobject-size.c b/src/dialogs/dialog-sheetobject-size.c
index d083356..b7a980c 100644
--- a/src/dialogs/dialog-sheetobject-size.c
+++ b/src/dialogs/dialog-sheetobject-size.c
@@ -40,6 +40,7 @@
#include <sheet-object-widget.h>
#include <sheet-object-impl.h>
#include <sheet-control-gui.h>
+#include <widgets/gnm-so-anchor-mode-chooser.h>
#include <gtk/gtk.h>
@@ -65,6 +66,7 @@ typedef struct {
GtkSpinButton *yspin;
GtkEntry *nameentry;
GtkWidget *print_check;
+ GnmSOAnchorModeChooser *modecombo;
SheetObject *so;
SheetObjectAnchor *old_anchor;
@@ -75,6 +77,7 @@ typedef struct {
gboolean so_pos_needs_restore;
gboolean so_name_changed;
gboolean so_print_check_changed;
+ gboolean so_mode_changed;
} SOSizeState;
static void
@@ -94,7 +97,8 @@ dialog_so_size_button_sensitivity (SOSizeState *state)
gboolean sensitive = state->so_size_needs_restore ||
state->so_pos_needs_restore ||
state->so_name_changed ||
- state->so_print_check_changed;
+ state->so_print_check_changed ||
+ state->so_mode_changed;
gtk_widget_set_sensitive
(state->ok_button, sensitive);
gtk_widget_set_sensitive
@@ -206,6 +210,18 @@ set_print_flag (SheetObject *so, gboolean print)
g_object_unref, g_free);
}
+static GOUndo *
+set_mode (SheetObject *so, GnmSOAnchorMode mode)
+{
+ GnmSOAnchorMode *p_mode = g_new (GnmSOAnchorMode, 1);
+
+ *p_mode = mode;
+ return go_undo_binary_new
+ (g_object_ref (so), p_mode,
+ (GOUndoBinaryFunc)sheet_object_set_anchor_mode,
+ g_object_unref, g_free);
+}
+
static void
cb_dialog_so_size_apply_clicked (G_GNUC_UNUSED GtkWidget *button,
SOSizeState *state)
@@ -252,11 +268,19 @@ cb_dialog_so_size_apply_clicked (G_GNUC_UNUSED GtkWidget *button,
undo_name = _("Set Object Print Property");
cnt++;
}
+ if (state->so_mode_changed) {
+ int new_mode = gnm_so_anchor_mode_chooser_get_mode (state->modecombo);
+ int old_mode = state->so->anchor.mode;
+ undo = go_undo_combine (undo, set_mode (state->so, old_mode));
+ redo = go_undo_combine (redo, set_mode (state->so, new_mode));
+ undo_name = _("Set Object Anchor Mode");
+ cnt++;
+ }
if (cnt > 0) {
if (cnt > 1)
undo_name = _("Set Object Properties");
- state->so_name_changed = state->so_print_check_changed =
+ state->so_name_changed = state->so_print_check_changed = state->so_mode_changed =
cmd_generic (GNM_WBC (state->wbcg),
undo_name, undo, redo);
}
@@ -302,11 +326,26 @@ cb_dialog_so_size_print_check_toggled (GtkToggleButton *togglebutton,
return;
}
+static void
+cb_dialog_so_size_mode_changed (GnmSOAnchorModeChooser *chooser, SOSizeState *state)
+{
+ GnmSOAnchorMode new_mode = gnm_so_anchor_mode_chooser_get_mode (chooser);
+ GnmSOAnchorMode old_mode = state->so->anchor.mode;
+ double coords[4];
+
+ scg_object_anchor_to_coords (state->scg, state->active_anchor, coords);
+ state->active_anchor->mode = new_mode;
+ scg_object_coords_to_anchor (state->scg, coords, state->active_anchor);
+ state->so_mode_changed = new_mode != old_mode;
+ dialog_so_size_button_sensitivity (state);
+}
+
void
dialog_so_size (WBCGtk *wbcg, GObject *so)
{
GtkBuilder *gui;
SOSizeState *state;
+ GtkGrid *grid;
int width, height;
g_return_if_fail (wbcg != NULL);
@@ -352,6 +391,7 @@ dialog_so_size (WBCGtk *wbcg, GObject *so)
state->yspin = GTK_SPIN_BUTTON (go_gtk_builder_get_widget (state->gui, "y-spin"));
state->print_check = GTK_WIDGET (go_gtk_builder_get_widget (state->gui,
"print-check"));
+ state->modecombo = GNM_SO_ANCHOR_MODE_CHOOSER (gnm_so_anchor_mode_chooser_new
(sheet_object_can_resize (state->so)));
dialog_so_size_load (state);
state->active_anchor = sheet_object_anchor_dup (sheet_object_get_anchor
(state->so));
@@ -364,6 +404,13 @@ dialog_so_size (WBCGtk *wbcg, GObject *so)
gtk_spin_button_set_value (state->yspin, 0.);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->print_check),
!(state->so->flags & SHEET_OBJECT_PRINT));
+ gnm_so_anchor_mode_chooser_set_mode (state->modecombo,
+ state->so->anchor.mode);
+ grid = GTK_GRID (gtk_builder_get_object (state->gui, "main-grid"));
+ gtk_grid_insert_row (grid, 7);
+ gtk_grid_attach (grid, GTK_WIDGET (state->modecombo), 0, 7, 2, 1);
+ gtk_widget_set_halign (GTK_WIDGET (state->modecombo), GTK_ALIGN_START);
+ gtk_widget_show (GTK_WIDGET (state->modecombo));
g_signal_connect (G_OBJECT (state->wspin),
"value-changed",
G_CALLBACK (cb_dialog_so_size_value_changed_update_points),
@@ -404,7 +451,11 @@ dialog_so_size (WBCGtk *wbcg, GObject *so)
"value-changed",
G_CALLBACK (cb_dialog_so_size_value_changed), state);
- state->ok_button = go_gtk_builder_get_widget (state->gui, "ok_button");
+ g_signal_connect (G_OBJECT (state->modecombo),
+ "changed",
+ G_CALLBACK (cb_dialog_so_size_mode_changed), state);
+
+ state->ok_button = go_gtk_builder_get_widget (state->gui, "ok_button");
g_signal_connect (G_OBJECT (state->ok_button),
"clicked",
G_CALLBACK (cb_dialog_so_size_ok_clicked), state);
diff --git a/src/graph.h b/src/graph.h
index 35e47f4..0fa2c86 100644
--- a/src/graph.h
+++ b/src/graph.h
@@ -45,6 +45,7 @@ typedef struct {
gboolean share_x, new_sheet;
GObject *obj;
GogDataAllocator *dalloc;
+ GnmSOAnchorMode anchor_mode;
} GnmGraphDataClosure;
G_END_DECLS
diff --git a/src/item-grid.c b/src/item-grid.c
index 9afe91f..ecf321d 100644
--- a/src/item-grid.c
+++ b/src/item-grid.c
@@ -885,7 +885,7 @@ ig_obj_create_begin (GnmItemGrid *ig, int button, gint64 x, gint64 y)
coords[0] = coords[2] = x;
coords[1] = coords[3] = y;
- sheet_object_anchor_init (&anchor, NULL, NULL, GOD_ANCHOR_DIR_DOWN_RIGHT);
+ sheet_object_anchor_init (&anchor, NULL, NULL, GOD_ANCHOR_DIR_DOWN_RIGHT, so->anchor.mode);
scg_object_coords_to_anchor (ig->scg, coords, &anchor);
sheet_object_set_anchor (so, &anchor);
sheet_object_set_sheet (so, scg_sheet (ig->scg));
diff --git a/src/sheet-control-gui.c b/src/sheet-control-gui.c
index 08aa88f..1e01bfb 100644
--- a/src/sheet-control-gui.c
+++ b/src/sheet-control-gui.c
@@ -2853,6 +2853,7 @@ cb_collect_objects_to_commit (SheetObject *so, double *coords, CollectObjectsDat
SheetObjectAnchor *anchor = sheet_object_anchor_dup (
sheet_object_get_anchor (so));
if (!sheet_object_can_resize (so)) {
+ /* FIXME: that code should be invalid */
double scale = goc_canvas_get_pixels_per_unit (GOC_CANVAS (data->scg->pane[0])) / 72.;
sheet_object_default_size (so, coords + 2, coords + 3);
coords[2] *= gnm_app_display_dpi_get (TRUE) * scale;
@@ -2960,6 +2961,7 @@ void
scg_object_coords_to_anchor (SheetControlGUI const *scg,
double const *coords, SheetObjectAnchor *in_out)
{
+ Sheet *sheet = scg_sheet (scg);
/* pane 0 always exists and the others are always use the same basis */
GnmPane *pane = scg_pane ((SheetControlGUI *)scg, 0);
double tmp[4];
@@ -2984,14 +2986,36 @@ scg_object_coords_to_anchor (SheetControlGUI const *scg,
in_out->base.direction |= GOD_ANCHOR_DIR_DOWN;
}
- in_out->cell_bound.start.col = calc_obj_place (pane, tmp[0], TRUE,
- in_out->offset + 0);
- in_out->cell_bound.start.row = calc_obj_place (pane, tmp[1], FALSE,
- in_out->offset + 1);
- in_out->cell_bound.end.col = calc_obj_place (pane, tmp[2], TRUE,
- in_out->offset + 2);
- in_out->cell_bound.end.row = calc_obj_place (pane, tmp[3], FALSE,
- in_out->offset + 3);
+ switch (in_out->mode) {
+ case GNM_SO_ANCHOR_TWO_CELLS:
+ in_out->cell_bound.start.col = calc_obj_place (pane, tmp[0], TRUE,
+ in_out->offset + 0);
+ in_out->cell_bound.start.row = calc_obj_place (pane, tmp[1], FALSE,
+ in_out->offset + 1);
+ in_out->cell_bound.end.col = calc_obj_place (pane, tmp[2], TRUE,
+ in_out->offset + 2);
+ in_out->cell_bound.end.row = calc_obj_place (pane, tmp[3], FALSE,
+ in_out->offset + 3);
+ break;
+ case GNM_SO_ANCHOR_ONE_CELL:
+ in_out->cell_bound.start.col = calc_obj_place (pane, tmp[0], TRUE,
+ in_out->offset + 0);
+ in_out->cell_bound.start.row = calc_obj_place (pane, tmp[1], FALSE,
+ in_out->offset + 1);
+ in_out->offset[2] = (tmp[2] - tmp[0]) / colrow_compute_pixel_scale (sheet, TRUE);
+ in_out->offset[3] = (tmp[3] - tmp[1]) / colrow_compute_pixel_scale (sheet, FALSE);
+ break;
+ case GNM_SO_ANCHOR_ABSOLUTE: {
+ double h, v;
+ h = colrow_compute_pixel_scale (sheet, TRUE);
+ v = colrow_compute_pixel_scale (sheet, FALSE);
+ in_out->offset[0] = tmp[0] / h;
+ in_out->offset[1] = tmp[1] / v;
+ in_out->offset[2] = (tmp[2] - tmp[0]) / h;
+ in_out->offset[3] = (tmp[3] - tmp[1]) / v;
+ break;
+ }
+ }
}
static double
@@ -3016,21 +3040,41 @@ scg_object_anchor_to_coords (SheetControlGUI const *scg,
g_return_if_fail (coords != NULL);
r = &anchor->cell_bound;
- pixels[0] = scg_colrow_distance_get (scg, TRUE, 0, r->start.col);
- pixels[2] = pixels[0] + scg_colrow_distance_get (scg, TRUE,
- r->start.col, r->end.col);
- pixels[1] = scg_colrow_distance_get (scg, FALSE, 0, r->start.row);
- pixels[3] = pixels[1] + scg_colrow_distance_get (scg, FALSE,
- r->start.row, r->end.row);
- /* add .5 to offsets so that the rounding is optimal */
- pixels[0] += cell_offset_calc_pixel (sheet, r->start.col,
- TRUE, anchor->offset[0]) + .5;
- pixels[1] += cell_offset_calc_pixel (sheet, r->start.row,
- FALSE, anchor->offset[1]) + .5;
- pixels[2] += cell_offset_calc_pixel (sheet, r->end.col,
- TRUE, anchor->offset[2]) + .5;
- pixels[3] += cell_offset_calc_pixel (sheet, r->end.row,
- FALSE, anchor->offset[3]) + .5;
+ if (anchor->mode != GNM_SO_ANCHOR_ABSOLUTE) {
+ pixels[0] = scg_colrow_distance_get (scg, TRUE, 0, r->start.col);
+ pixels[1] = scg_colrow_distance_get (scg, FALSE, 0, r->start.row);
+ if (anchor->mode == GNM_SO_ANCHOR_TWO_CELLS) {
+ pixels[2] = pixels[0] + scg_colrow_distance_get (scg, TRUE,
+ r->start.col, r->end.col);
+ pixels[3] = pixels[1] + scg_colrow_distance_get (scg, FALSE,
+ r->start.row, r->end.row);
+ /* add .5 to offsets so that the rounding is optimal */
+ pixels[0] += cell_offset_calc_pixel (sheet, r->start.col,
+ TRUE, anchor->offset[0]) + .5;
+ pixels[1] += cell_offset_calc_pixel (sheet, r->start.row,
+ FALSE, anchor->offset[1]) + .5;
+ pixels[2] += cell_offset_calc_pixel (sheet, r->end.col,
+ TRUE, anchor->offset[2]) + .5;
+ pixels[3] += cell_offset_calc_pixel (sheet, r->end.row,
+ FALSE, anchor->offset[3]) + .5;
+ } else {
+ /* add .5 to offsets so that the rounding is optimal */
+ pixels[0] += cell_offset_calc_pixel (sheet, r->start.col,
+ TRUE, anchor->offset[0]) + .5;
+ pixels[1] += cell_offset_calc_pixel (sheet, r->start.row,
+ FALSE, anchor->offset[1]) + .5;
+ pixels[2] = pixels[0] + go_fake_floor (anchor->offset[2] * colrow_compute_pixel_scale
(sheet, TRUE) + .5);
+ pixels[3] = pixels[1] + go_fake_floor (anchor->offset[3] * colrow_compute_pixel_scale
(sheet, TRUE) + .5);
+ }
+ } else {
+ double h, v;
+ h = colrow_compute_pixel_scale (sheet, TRUE);
+ v = colrow_compute_pixel_scale (sheet, FALSE);
+ pixels[0] = go_fake_floor (anchor->offset[0] * h);
+ pixels[1] = go_fake_floor (anchor->offset[1] * v);
+ pixels[2] = go_fake_floor ((anchor->offset[0] + anchor->offset[2]) * h);
+ pixels[3] = go_fake_floor ((anchor->offset[1] + anchor->offset[3]) * v);
+ }
direction = anchor->base.direction;
if (direction == GOD_ANCHOR_DIR_UNKNOWN)
@@ -3957,7 +4001,7 @@ scg_paste_image (SheetControlGUI *scg, GnmRange *where,
SheetObjectAnchor anchor;
sheet_object_anchor_init (&anchor, where, NULL,
- GOD_ANCHOR_DIR_DOWN_RIGHT);
+ GOD_ANCHOR_DIR_DOWN_RIGHT, GNM_SO_ANCHOR_TWO_CELLS);
scg_image_create (scg, &anchor, data, len);
}
@@ -3969,7 +4013,7 @@ scg_drag_receive_img_data (SheetControlGUI *scg, double x, double y,
SheetObjectAnchor anchor;
sheet_object_anchor_init (&anchor, NULL, NULL,
- GOD_ANCHOR_DIR_DOWN_RIGHT);
+ GOD_ANCHOR_DIR_DOWN_RIGHT, GNM_SO_ANCHOR_TWO_CELLS);
coords[0] = coords[2] = x;
coords[1] = coords[3] = y;
scg_object_coords_to_anchor (scg, coords, &anchor);
@@ -4037,7 +4081,7 @@ scg_paste_cellregion (SheetControlGUI *scg, double x, double y,
double coords[4];
sheet_object_anchor_init (&anchor, NULL, NULL,
- GOD_ANCHOR_DIR_DOWN_RIGHT);
+ GOD_ANCHOR_DIR_DOWN_RIGHT, GNM_SO_ANCHOR_TWO_CELLS);
coords[0] = coords[2] = x;
coords[1] = coords[3] = y;
scg_object_coords_to_anchor (scg, coords, &anchor);
diff --git a/src/sheet-filter.c b/src/sheet-filter.c
index 056eebc..3db6529 100644
--- a/src/sheet-filter.c
+++ b/src/sheet-filter.c
@@ -635,7 +635,7 @@ gnm_filter_add_field (GnmFilter *filter, int i)
tmp.start.row = tmp.end.row = filter->r.start.row;
tmp.start.col = tmp.end.col = filter->r.start.col + i;
sheet_object_anchor_init (&anchor, &tmp, a_offsets,
- GOD_ANCHOR_DIR_DOWN_RIGHT);
+ GOD_ANCHOR_DIR_DOWN_RIGHT, GNM_SO_ANCHOR_TWO_CELLS);
sheet_object_set_anchor (GNM_SO (fcombo), &anchor);
sheet_object_set_sheet (GNM_SO (fcombo), filter->sheet);
diff --git a/src/sheet-object-cell-comment.c b/src/sheet-object-cell-comment.c
index 0023094..51c3e0f 100644
--- a/src/sheet-object-cell-comment.c
+++ b/src/sheet-object-cell-comment.c
@@ -443,7 +443,7 @@ cell_comment_set_pos (GnmComment *cc, GnmCellPos const *pos)
r.start = r.end = *pos;
sheet_object_anchor_init (&anchor, &r, a_offsets,
- GOD_ANCHOR_DIR_DOWN_RIGHT);
+ GOD_ANCHOR_DIR_DOWN_RIGHT, GNM_SO_ANCHOR_TWO_CELLS);
sheet_object_set_anchor (GNM_SO (cc), &anchor);
}
diff --git a/src/sheet-object-component.c b/src/sheet-object-component.c
index f1c0a80..c9f14f7 100644
--- a/src/sheet-object-component.c
+++ b/src/sheet-object-component.c
@@ -481,7 +481,6 @@ sheet_object_component_set_component (SheetObject *so, GOComponent *component)
{
SheetObjectComponent *soc;
GList *l = so->realized_list;
- GnmPane *pane = (l && l->data)? GNM_PANE (GOC_ITEM (l->data)->canvas): NULL;
g_return_if_fail (GNM_IS_SO_COMPONENT (so));
soc = GNM_SO_COMPONENT (so);
@@ -503,26 +502,14 @@ sheet_object_component_set_component (SheetObject *so, GOComponent *component)
go_component_stop_editing (component);
if (go_component_is_resizable (component))
so->flags |= SHEET_OBJECT_CAN_RESIZE;
- else
- so->flags &= ~SHEET_OBJECT_CAN_RESIZE;
+ else {
+ so->flags &= ~(SHEET_OBJECT_CAN_RESIZE | SHEET_OBJECT_SIZE_WITH_CELLS);
+ so->anchor.mode = GNM_SO_ANCHOR_ONE_CELL;
+ }
if (go_component_is_editable (component))
so->flags |= SHEET_OBJECT_CAN_EDIT;
else
so->flags &= ~SHEET_OBJECT_CAN_EDIT;
- if (pane != NULL && !(so->flags & SHEET_OBJECT_CAN_RESIZE)) {
- SheetControlGUI *scg = pane->simple.scg;
- double coords[4], w, h;
- SheetObjectAnchor anchor;
- /* the size must be updated */
- scg_object_anchor_to_coords (scg, sheet_object_get_anchor (so), coords);
- coords[0] = MIN (coords [0], coords[2]);
- coords[1] = MIN (coords [1], coords[3]);
- go_component_get_size (component, &w, &h);
- coords[2] = coords[0] + w * gnm_app_display_dpi_get (TRUE);
- coords[3] = coords[1] + h * gnm_app_display_dpi_get (FALSE);
- scg_object_coords_to_anchor (scg, coords, &anchor);
- sheet_object_set_anchor (so, &anchor);
- }
}
}
diff --git a/src/sheet-object-graph.c b/src/sheet-object-graph.c
index 58e9517..7436808 100644
--- a/src/sheet-object-graph.c
+++ b/src/sheet-object-graph.c
@@ -622,9 +622,13 @@ GSF_CLASS_FULL (SheetObjectGraph, sheet_object_graph,
SheetObject *
sheet_object_graph_new (GogGraph *graph)
{
- SheetObjectGraph *sog = g_object_new (GNM_SO_GRAPH_TYPE, NULL);
- sheet_object_graph_set_gog (GNM_SO (sog), graph);
- return GNM_SO (sog);
+ SheetObject *sog = g_object_new (GNM_SO_GRAPH_TYPE, NULL);
+ GnmGraphDataClosure *data = (GnmGraphDataClosure *) g_object_get_data (G_OBJECT (graph),
"data-closure");
+ sheet_object_graph_set_gog (sog, graph);
+ if (data != NULL)
+ sog->anchor.mode = data->anchor_mode;
+
+ return sog;
}
/**
@@ -776,6 +780,7 @@ sheet_object_graph_guru (WBCGtk *wbcg, GogGraph *graph,
g_signal_connect (G_OBJECT (w), "toggled", G_CALLBACK (cb_sheet_target_changed), data);
gtk_grid_attach (GTK_GRID (custom), w, 0, 2, 2, 1);
data->obj = G_OBJECT (custom);
+ data->anchor_mode = GNM_SO_ANCHOR_ONE_CELL; /* don't resize graphs with cells, see # */
gog_guru_add_custom_widget (dialog, custom);
object = (GObject*) g_object_get_data (data->obj, "graph");
if (object)
diff --git a/src/sheet-object-image.c b/src/sheet-object-image.c
index 8857226..258c973 100644
--- a/src/sheet-object-image.c
+++ b/src/sheet-object-image.c
@@ -597,6 +597,7 @@ gnm_soi_init (GObject *obj)
so = GNM_SO (obj);
so->anchor.base.direction = GOD_ANCHOR_DIR_DOWN_RIGHT;
+ so->anchor.mode = GNM_SO_ANCHOR_ONE_CELL;
}
static void
diff --git a/src/sheet-object.c b/src/sheet-object.c
index 4704ea3..a857813 100644
--- a/src/sheet-object.c
+++ b/src/sheet-object.c
@@ -1,5 +1,3 @@
-/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
/*
* sheet-object.c: Implements the sheet object manipulation for Gnumeric
*
@@ -477,22 +475,37 @@ sheet_object_update_bounds (SheetObject *so, GnmCellPos const *pos)
so->anchor.cell_bound.end.row < pos->row)
return;
- /* Are all cols hidden ? */
- end = so->anchor.cell_bound.end.col;
- i = so->anchor.cell_bound.start.col;
- while (i <= end && is_hidden)
- is_hidden &= sheet_col_is_hidden (so->sheet, i++);
-
- /* Are all rows hidden ? */
- if (!is_hidden) {
- is_hidden = TRUE;
- end = so->anchor.cell_bound.end.row;
- i = so->anchor.cell_bound.start.row;
+ switch (so->anchor.mode) {
+ default:
+ case GNM_SO_ANCHOR_TWO_CELLS:
+ /* Are all cols hidden ? */
+ end = so->anchor.cell_bound.end.col;
+ i = so->anchor.cell_bound.start.col;
while (i <= end && is_hidden)
- is_hidden &= sheet_row_is_hidden (so->sheet, i++);
- so->flags |= SHEET_OBJECT_IS_VISIBLE;
- } else
+ is_hidden &= sheet_col_is_hidden (so->sheet, i++);
+
+ /* Are all rows hidden ? */
+ if (!is_hidden) {
+ is_hidden = TRUE;
+ end = so->anchor.cell_bound.end.row;
+ i = so->anchor.cell_bound.start.row;
+ while (i <= end && is_hidden)
+ is_hidden &= sheet_row_is_hidden (so->sheet, i++);
+ }
+ break;
+ case GNM_SO_ANCHOR_ONE_CELL:
+ /* Should we really hide if the row or column is hidden? */
+ is_hidden = sheet_col_is_hidden (so->sheet, so->anchor.cell_bound.start.col) ||
+ sheet_row_is_hidden (so->sheet, so->anchor.cell_bound.start.row);
+ break;
+ case GNM_SO_ANCHOR_ABSOLUTE:
+ is_hidden = FALSE;
+ break;
+ }
+ if (is_hidden)
so->flags &= ~SHEET_OBJECT_IS_VISIBLE;
+ else
+ so->flags |= SHEET_OBJECT_IS_VISIBLE;
g_signal_emit (so, signals [BOUNDS_CHANGED], 0);
}
@@ -863,23 +876,137 @@ sheet_object_anchor_to_pts (SheetObjectAnchor const *anchor,
r = &anchor->cell_bound;
- res_pts [0] = sheet_col_get_distance_pts (sheet, 0,
- r->start.col);
- res_pts [2] = res_pts [0] + sheet_col_get_distance_pts (sheet,
- r->start.col, r->end.col);
- res_pts [1] = sheet_row_get_distance_pts (sheet, 0,
- r->start.row);
- res_pts [3] = res_pts [1] + sheet_row_get_distance_pts (sheet,
- r->start.row, r->end.row);
-
- res_pts [0] += cell_offset_calc_pt (sheet, r->start.col,
- TRUE, anchor->offset [0]);
- res_pts [1] += cell_offset_calc_pt (sheet, r->start.row,
- FALSE, anchor->offset [1]);
- res_pts [2] += cell_offset_calc_pt (sheet, r->end.col,
- TRUE, anchor->offset [2]);
- res_pts [3] += cell_offset_calc_pt (sheet, r->end.row,
- FALSE, anchor->offset [3]);
+ if (anchor->mode != GNM_SO_ANCHOR_ABSOLUTE) {
+ res_pts [0] = sheet_col_get_distance_pts (sheet, 0,
+ r->start.col);
+ res_pts [1] = sheet_row_get_distance_pts (sheet, 0,
+ r->start.row);
+ if (anchor->mode == GNM_SO_ANCHOR_TWO_CELLS) {
+ res_pts [2] = res_pts [0] + sheet_col_get_distance_pts (sheet,
+ r->start.col, r->end.col);
+ res_pts [3] = res_pts [1] + sheet_row_get_distance_pts (sheet,
+ r->start.row, r->end.row);
+
+ res_pts [0] += cell_offset_calc_pt (sheet, r->start.col,
+ TRUE, anchor->offset [0]);
+ res_pts [1] += cell_offset_calc_pt (sheet, r->start.row,
+ FALSE, anchor->offset [1]);
+ res_pts [2] += cell_offset_calc_pt (sheet, r->end.col,
+ TRUE, anchor->offset [2]);
+ res_pts [3] += cell_offset_calc_pt (sheet, r->end.row,
+ FALSE, anchor->offset [3]);
+ } else {
+ res_pts [0] += cell_offset_calc_pt (sheet, r->start.col,
+ TRUE, anchor->offset [0]);
+ res_pts [1] += cell_offset_calc_pt (sheet, r->start.row,
+ FALSE, anchor->offset [1]);
+ res_pts[2] = res_pts [0] + anchor->offset [2];
+ res_pts[3] = res_pts [1] + anchor->offset [3];
+ }
+ } else {
+ res_pts [0] = anchor->offset [0];
+ res_pts [1] = anchor->offset [1];
+ res_pts[2] = res_pts [0] + anchor->offset [2];
+ res_pts[3] = res_pts [1] + anchor->offset [3];
+ }
+}
+
+void
+sheet_object_pts_to_anchor (SheetObjectAnchor *anchor,
+ Sheet const *sheet, double const *res_pts)
+{
+ int col, row;
+ double x, y, tmp = 0;
+ ColRowInfo const *ci;
+ if (anchor->mode == GNM_SO_ANCHOR_ABSOLUTE) {
+ anchor->cell_bound.start.col = 0;
+ anchor->cell_bound.start.row = 0;
+ anchor->cell_bound.end.col = 0;
+ anchor->cell_bound.end.row = 0;
+ anchor->offset[0] = res_pts[0];
+ anchor->offset[1] = res_pts[1];
+ anchor->offset[2] = res_pts[2] - res_pts[0];
+ anchor->offset[3] = res_pts[3] - res_pts[1];
+ return;
+ }
+ /* find end column */
+ col = x = 0;
+ do {
+ ci = sheet_col_get_info (sheet, col);
+ if (ci->visible) {
+ tmp = ci->size_pts;
+ if (res_pts[0] <= x + tmp)
+ break;
+ x += tmp;
+ }
+ } while (++col < gnm_sheet_get_last_col (sheet));
+ if (col == gnm_sheet_get_last_col (sheet)) {
+ /* not sure this will occur */
+ col--;
+ x -= tmp;
+ }
+ anchor->cell_bound.start.col = col;
+ anchor->offset[0] = (res_pts[0] - x) / tmp;
+ /* find start row */
+ row = y = 0;
+ do {
+ ci = sheet_row_get_info (sheet, row);
+ if (ci->visible) {
+ tmp = ci->size_pts;
+ if (res_pts[1] <= y + tmp)
+ break;
+ y += tmp;
+ }
+ } while (++row < gnm_sheet_get_last_row (sheet));
+ if (row == gnm_sheet_get_last_row (sheet)) {
+ /* not sure this will occur */
+ row--;
+ y -= tmp;
+ }
+ anchor->cell_bound.start.row = row;
+ anchor->offset[1] = (res_pts[1] - y) / tmp;
+ if (anchor->mode == GNM_SO_ANCHOR_ONE_CELL) {
+ anchor->cell_bound.end.col = col;
+ anchor->cell_bound.end.row = row;
+ anchor->offset[2] = res_pts[2] - res_pts[0];
+ anchor->offset[3] = res_pts[3] - res_pts[1];
+ return;
+ }
+
+ /* find end column */
+ do {
+ ci = sheet_col_get_info (sheet, col);
+ if (ci->visible) {
+ tmp = ci->size_pts;
+ if (res_pts[2] <= x + tmp)
+ break;
+ x += tmp;
+ }
+ } while (++col < gnm_sheet_get_last_col (sheet));
+ if (col == gnm_sheet_get_last_col (sheet)) {
+ /* not sure this will occur */
+ col--;
+ x -= tmp;
+ }
+ anchor->cell_bound.end.col = col;
+ anchor->offset[2] = (res_pts[2] - x) / tmp;
+ /* find end row */
+ do {
+ ci = sheet_row_get_info (sheet, row);
+ if (ci->visible) {
+ tmp = ci->size_pts;
+ if (res_pts[3] <= y + tmp)
+ break;
+ y += tmp;
+ }
+ } while (++row < gnm_sheet_get_last_row (sheet));
+ if (row == gnm_sheet_get_last_row (sheet)) {
+ /* not sure this will occur */
+ row--;
+ y -= tmp;
+ }
+ anchor->cell_bound.end.row = row;
+ anchor->offset[3] = (res_pts[3] - y) / tmp;
}
void
@@ -892,14 +1019,18 @@ sheet_object_anchor_to_offset_pts (SheetObjectAnchor const *anchor,
r = &anchor->cell_bound;
- res_pts [0] = cell_offset_calc_pt (sheet, r->start.col,
- TRUE, anchor->offset [0]);
- res_pts [1] = cell_offset_calc_pt (sheet, r->start.row,
- FALSE, anchor->offset [1]);
- res_pts [2] = cell_offset_calc_pt (sheet, r->end.col,
- TRUE, anchor->offset [2]);
- res_pts [3] = cell_offset_calc_pt (sheet, r->end.row,
- FALSE, anchor->offset [3]);
+ if (anchor->mode != GNM_SO_ANCHOR_ABSOLUTE) {
+ res_pts [0] = cell_offset_calc_pt (sheet, r->start.col,
+ TRUE, anchor->offset [0]);
+ res_pts [1] = cell_offset_calc_pt (sheet, r->start.row,
+ FALSE, anchor->offset [1]);
+ if (anchor->mode == GNM_SO_ANCHOR_TWO_CELLS) {
+ res_pts [2] = cell_offset_calc_pt (sheet, r->end.col,
+ TRUE, anchor->offset [2]);
+ res_pts [3] = cell_offset_calc_pt (sheet, r->end.row,
+ FALSE, anchor->offset [3]);
+ }
+ }
}
static void
@@ -965,7 +1096,8 @@ sheet_objects_relocate (GnmExprRelocateInfo const *rinfo, gboolean update,
GnmRange r = so->anchor.cell_bound;
next = ptr->next;
- if (update && 0 == (so->flags & SHEET_OBJECT_MOVE_WITH_CELLS))
+ if ((so->anchor.mode == GNM_SO_ANCHOR_ABSOLUTE) ||
+ (update && 0 == (so->flags & SHEET_OBJECT_MOVE_WITH_CELLS)))
continue;
if (range_contains (&rinfo->origin, r.start.col, r.start.row)) {
/* FIXME : just moving the range is insufficent for all anchor types */
@@ -1178,6 +1310,7 @@ sheet_object_rubber_band_directly (G_GNUC_UNUSED SheetObject const *so)
* @cell_bound: #GnmRange
* @offsets: double[4]
* @direction: #GODrawingAnchorDir
+ * @mode: #GnmSOAnchorMode
*
* A utility routine to initialize an anchor. Useful in case we change fields
* in the future and want to ensure that everything is initialized.
@@ -1185,7 +1318,8 @@ sheet_object_rubber_band_directly (G_GNUC_UNUSED SheetObject const *so)
void
sheet_object_anchor_init (SheetObjectAnchor *anchor,
GnmRange const *r, const double *offsets,
- GODrawingAnchorDir direction)
+ GODrawingAnchorDir direction,
+ GnmSOAnchorMode mode)
{
int i;
@@ -1203,6 +1337,7 @@ sheet_object_anchor_init (SheetObjectAnchor *anchor,
anchor->offset[i] = offsets [i];
anchor->base.direction = direction;
+ anchor->mode = mode;
/* TODO : add sanity checking to handle offsets past edges of col/row */
}
@@ -1266,6 +1401,19 @@ sheet_object_adjust_stacking (SheetObject *so, gint offset)
return cur - i;
}
+void
+sheet_object_set_anchor_mode (SheetObject *so, GnmSOAnchorMode const *mode)
+{
+ /* FIXME: adjust offsets according to the old and new modes */
+ double pts[4];
+
+ if (so->anchor.mode == *mode)
+ return;
+ sheet_object_anchor_to_pts (&so->anchor, so->sheet, pts);
+ so->anchor.mode = *mode;
+ sheet_object_pts_to_anchor (&so->anchor, so->sheet, pts);
+}
+
/*****************************************************************************/
static GObjectClass *view_parent_class;
diff --git a/src/sheet-object.h b/src/sheet-object.h
index 245d90c..4d035bf 100644
--- a/src/sheet-object.h
+++ b/src/sheet-object.h
@@ -17,11 +17,18 @@ typedef enum {
GNM_SO_RESIZE_NONE /* can't be resized like some sheet components */
} GnmSOResizeMode;
+typedef enum {
+ GNM_SO_ANCHOR_TWO_CELLS, /* move and size (if sizeable) with cells) */
+ GNM_SO_ANCHOR_ONE_CELL, /* move with cells */
+ GNM_SO_ANCHOR_ABSOLUTE /* anchored to the sheet */
+} GnmSOAnchorMode;
+
struct _SheetObjectAnchor {
GODrawingAnchor base;
GnmRange cell_bound; /* cellpos containing corners */
double offset[4]; /* offsets from the top left (in LTR of cell_bound) */
+ GnmSOAnchorMode mode;
};
GType sheet_object_anchor_get_type (void); /* Boxed type */
@@ -99,6 +106,7 @@ void sheet_objects_dup (Sheet const *src, Sheet *dst, GnmRange *range);
void sheet_object_direction_set (SheetObject *so, gdouble const *coords);
gboolean sheet_object_rubber_band_directly (SheetObject const *so);
+void sheet_object_set_anchor_mode (SheetObject *so, GnmSOAnchorMode const *mode);
/* Anchor utilities */
void sheet_object_anchor_to_pts (SheetObjectAnchor const *anchor,
@@ -108,7 +116,10 @@ void sheet_object_anchor_to_offset_pts (SheetObjectAnchor const *anchor,
void sheet_object_anchor_init (SheetObjectAnchor *anchor,
GnmRange const *cell_bound,
const double *offsets,
- GODrawingAnchorDir direction);
+ GODrawingAnchorDir direction,
+ GnmSOAnchorMode mode);
+void sheet_object_pts_to_anchor (SheetObjectAnchor *anchor,
+ Sheet const *sheet, double const *res_pts);
SheetObjectAnchor *
sheet_object_anchor_dup (SheetObjectAnchor const *src);
diff --git a/src/tools/ChangeLog b/src/tools/ChangeLog
index dec458b..f548e7e 100644
--- a/src/tools/ChangeLog
+++ b/src/tools/ChangeLog
@@ -1,3 +1,9 @@
+2015-03-30 Jean Brefort <jean brefort normalesup org>
+
+ reviewed by: <delete if not using a buddy>
+
+ * dao.c (dao_set_sheet_object):
+
2015-03-04 Morten Welinder <terra gnome org>
* Release 1.12.21
diff --git a/src/tools/dao.c b/src/tools/dao.c
index 7381be9..7e45cee 100644
--- a/src/tools/dao.c
+++ b/src/tools/dao.c
@@ -1183,7 +1183,8 @@ dao_set_sheet_object (data_analysis_output_t *dao, int col, int row, SheetObject
dao->start_col + ((dao->cols < 5) ? dao->cols : 5),
dao->start_row + ((dao->rows < 20) ? dao->rows : 20));
- sheet_object_anchor_init (&anchor, &anchor_r, NULL, GOD_ANCHOR_DIR_UNKNOWN);
+ sheet_object_anchor_init (&anchor, &anchor_r, NULL, GOD_ANCHOR_DIR_UNKNOWN,
+ GNM_SO_ANCHOR_TWO_CELLS);
sheet_object_set_anchor (so, &anchor);
sheet_object_set_sheet (so, dao->sheet);
diff --git a/src/widgets/ChangeLog b/src/widgets/ChangeLog
index 74edf4d..f69ae07 100644
--- a/src/widgets/ChangeLog
+++ b/src/widgets/ChangeLog
@@ -1,3 +1,8 @@
+2015-03-30 Jean Brefort <jean brefort normalesup org>
+
+ * Makefile.am: new widget for sheet objects anchor mode support.
+ * gnm-so-anchor-mode-chooser.[c,h]: ditto.
+
2015-03-04 Morten Welinder <terra gnome org>
* Release 1.12.21
diff --git a/src/widgets/Makefile.am b/src/widgets/Makefile.am
index b10b823..07a3dc2 100644
--- a/src/widgets/Makefile.am
+++ b/src/widgets/Makefile.am
@@ -27,6 +27,8 @@ libwidgets_la_SOURCES = \
gnm-validation-combo-view.h \
gnm-sheet-slicer-combo-view.c \
gnm-sheet-slicer-combo-view.h \
+ gnm-so-anchor-mode-chooser.c \
+ gnm-so-anchor-mode-chooser.h \
gnumeric-cell-renderer-text.c \
gnumeric-cell-renderer-text.h \
gnumeric-cell-renderer-expr-entry.c \
diff --git a/src/widgets/gnm-so-anchor-mode-chooser.c b/src/widgets/gnm-so-anchor-mode-chooser.c
new file mode 100644
index 0000000..9ec8a99
--- /dev/null
+++ b/src/widgets/gnm-so-anchor-mode-chooser.c
@@ -0,0 +1,97 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gnm-so-anchor-mode-chooser.c
+ *
+ * Copyright (C) 2015 Jean Bréfort <jean brefort normalesup org>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <gnumeric-config.h>
+#include <gtk/gtk.h>
+#include "gnm-so-anchor-mode-chooser.h"
+#include <gsf/gsf-impl-utils.h>
+#include <glib/gi18n-lib.h>
+
+struct _GnmSOAnchorModeChooser{
+ GtkComboBox parent;
+};
+typedef GtkComboBoxClass GnmSOAnchorModeChooserClass;
+
+
+GtkWidget *
+gnm_so_anchor_mode_chooser_new (gboolean resize)
+{
+ GtkWidget *widget = g_object_new (GNM_SO_ANCHOR_MODE_CHOOSER_TYPE, NULL);
+ GtkListStore *model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
+ GtkCellRenderer *cell = gtk_cell_renderer_text_new ();
+ GtkTreeIter iter;
+ gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (model));
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), cell, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget), cell,
+ "text", 0, NULL);
+ if (resize) {
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter, 0, _("Move and resize with cells"), 1,
GNM_SO_ANCHOR_TWO_CELLS, -1);
+ }
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter, 0, _("Move with cells"), 1, GNM_SO_ANCHOR_ONE_CELL, -1);
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter, 0, _("Absolute size and position"), 1, GNM_SO_ANCHOR_ABSOLUTE, -1);
+ return widget;
+}
+
+void
+gnm_so_anchor_mode_chooser_set_mode (GnmSOAnchorModeChooser *chooser,
+ GnmSOAnchorMode mode)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkComboBox *combo;
+ GnmSOAnchorMode cur;
+ g_return_if_fail (GNM_IS_SO_ANCHOR_MODE_CHOOSER (chooser));
+
+ combo = GTK_COMBO_BOX (chooser);
+ model = gtk_combo_box_get_model (combo);
+ if (!gtk_tree_model_get_iter_first (model, &iter))
+ return;
+ do {
+ gtk_tree_model_get (model, &iter, 1, &cur, -1);
+ if (cur == mode) {
+ gtk_combo_box_set_active_iter (combo, &iter);
+ return;
+ }
+ } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+GnmSOAnchorMode
+gnm_so_anchor_mode_chooser_get_mode (GnmSOAnchorModeChooser const *chooser)
+{
+ GtkTreeIter iter;
+ GtkComboBox *combo;
+ GnmSOAnchorMode mode;
+ g_return_val_if_fail (GNM_IS_SO_ANCHOR_MODE_CHOOSER (chooser), GNM_SO_ANCHOR_ONE_CELL);
+
+ combo = GTK_COMBO_BOX (chooser);
+ if (!gtk_combo_box_get_active_iter (combo, &iter))
+ return GNM_SO_ANCHOR_ONE_CELL;
+ gtk_tree_model_get (gtk_combo_box_get_model (combo), &iter, 1, &mode, -1);
+ return mode;
+}
+
+GSF_CLASS (GnmSOAnchorModeChooser, gnm_so_anchor_mode_chooser,
+ NULL, NULL,
+ GTK_TYPE_COMBO_BOX)
diff --git a/src/widgets/gnm-so-anchor-mode-chooser.h b/src/widgets/gnm-so-anchor-mode-chooser.h
new file mode 100644
index 0000000..d32cea4
--- /dev/null
+++ b/src/widgets/gnm-so-anchor-mode-chooser.h
@@ -0,0 +1,42 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gnm-so-anchor-mode-chooser.h
+ *
+ * Copyright (C) 2015 Jean Bréfort <jean brefort normalesup org>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef GNM_SO_ANCHOR_MODE_CHOOSER_H
+#define GNM_SO_ANCHOR_MODE_CHOOSER_H
+
+#include "gnumeric.h"
+#include "sheet-object.h"
+#include <glib-object.h>
+
+typedef struct _GnmSOAnchorModeChooser GnmSOAnchorModeChooser;
+
+#define GNM_SO_ANCHOR_MODE_CHOOSER_TYPE (gnm_so_anchor_mode_chooser_get_type ())
+#define GNM_SO_ANCHOR_MODE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),
GNM_SO_ANCHOR_MODE_CHOOSER_TYPE, GnmSOAnchorModeChooser))
+#define GNM_IS_SO_ANCHOR_MODE_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_TYPE((o),
GNM_SO_ANCHOR_MODE_CHOOSER_TYPE))
+GType gnm_so_anchor_mode_chooser_get_type (void);
+
+GtkWidget *gnm_so_anchor_mode_chooser_new (gboolean resize);
+void gnm_so_anchor_mode_chooser_set_mode (GnmSOAnchorModeChooser *chooser,
+ GnmSOAnchorMode mode);
+GnmSOAnchorMode gnm_so_anchor_mode_chooser_get_mode (GnmSOAnchorModeChooser const *chooser);
+
+#endif /* GNM_SO_ANCHOR_MODE_CHOOSER_H */
diff --git a/src/workbook-view.c b/src/workbook-view.c
index d439b9d..d9ba25c 100644
--- a/src/workbook-view.c
+++ b/src/workbook-view.c
@@ -341,7 +341,7 @@ wb_view_style_feedback (WorkbookView *wbv)
GnmRange const *r;
if (NULL == (r = gnm_sheet_merge_contains_pos (sv->sheet, &sv->edit_pos)))
r = range_init_cellpos (&corner, &sv->edit_pos);
- sheet_object_anchor_init (&anchor, r, a_offsets, GOD_ANCHOR_DIR_DOWN_RIGHT);
+ sheet_object_anchor_init (&anchor, r, a_offsets, GOD_ANCHOR_DIR_DOWN_RIGHT,
GNM_SO_ANCHOR_TWO_CELLS);
sheet_object_set_anchor (wbv->in_cell_combo, &anchor);
sheet_object_set_sheet (wbv->in_cell_combo, sv->sheet);
}
diff --git a/src/xml-sax-read.c b/src/xml-sax-read.c
index acf6d44..8f334b7 100644
--- a/src/xml-sax-read.c
+++ b/src/xml-sax-read.c
@@ -2327,6 +2327,7 @@ xml_sax_read_obj (GsfXMLIn *xin, gboolean needs_cleanup,
SheetObjectClass *klass;
GnmRange anchor_r;
GODrawingAnchorDir anchor_dir;
+ GnmSOAnchorMode anchor_mode;
SheetObjectAnchor anchor;
double f_tmp[4], *anchor_offset = NULL;
@@ -2390,13 +2391,25 @@ xml_sax_read_obj (GsfXMLIn *xin, gboolean needs_cleanup,
state->so = so;
anchor_dir = GOD_ANCHOR_DIR_UNKNOWN;
+ anchor_mode = GNM_SO_ANCHOR_TWO_CELLS;
/* Provide a default. */
anchor_r = sheet_object_get_anchor (so)->cell_bound;
for (i = 0; attrs != NULL && attrs[i] && attrs[i + 1] ; i += 2) {
if (attr_eq (attrs[i], "Name"))
sheet_object_set_name (so, CXML2C (attrs[i + 1]));
- else if (attr_eq (attrs[i], "ObjectBound"))
+ else if (!strcmp (attrs[i], "AnchorMode")) {
+ if (!strcmp (attrs[i+1], "one cell"))
+ anchor_mode = GNM_SO_ANCHOR_ONE_CELL;
+ else if (!strcmp (attrs[i+1], "absolute") )
+ anchor_mode = GNM_SO_ANCHOR_ABSOLUTE;
+ else {
+ char *str = g_strdup_printf (_("Unknown object anchor mode '%s'"),
+ attrs[i+1]);
+ go_io_warning_unsupported_feature (state->context, str);
+ g_free (str);
+ }
+ } else if (attr_eq (attrs[i], "ObjectBound"))
range_parse (&anchor_r, CXML2C (attrs[i + 1]), gnm_sheet_get_size (state->sheet));
else if (attr_eq (attrs[i], "ObjectOffset") &&
4 == sscanf (CXML2C (attrs[i + 1]), "%lg %lg %lg %lg",
@@ -2416,7 +2429,7 @@ xml_sax_read_obj (GsfXMLIn *xin, gboolean needs_cleanup,
if (G_OBJECT_TYPE (so) == GNM_CELL_COMMENT_TYPE)
anchor_r.end = anchor_r.start;
- sheet_object_anchor_init (&anchor, &anchor_r, anchor_offset, anchor_dir);
+ sheet_object_anchor_init (&anchor, &anchor_r, anchor_offset, anchor_dir, anchor_mode);
sheet_object_set_anchor (so, &anchor);
if (NULL != klass->prep_sax_parser)
diff --git a/src/xml-sax-write.c b/src/xml-sax-write.c
index 5055b8f..1a5ead0 100644
--- a/src/xml-sax-write.c
+++ b/src/xml-sax-write.c
@@ -1263,7 +1263,12 @@ xml_write_objects (GnmOutputXML *state, GSList *objects)
gsf_xml_out_start_element (state->output, tmp);
if (so->name)
gsf_xml_out_add_cstr (state->output, "Name", so->name);
- gsf_xml_out_add_cstr (state->output, "ObjectBound", range_as_string (&so->anchor.cell_bound));
+ if (so->anchor.mode != GNM_SO_ANCHOR_ABSOLUTE)
+ gsf_xml_out_add_cstr (state->output, "ObjectBound", range_as_string
(&so->anchor.cell_bound));
+ if (so->anchor.mode != GNM_SO_ANCHOR_TWO_CELLS)
+ gsf_xml_out_add_cstr_unchecked (state->output, "AnchorMode",
+ (so->anchor.mode == GNM_SO_ANCHOR_ONE_CELL)?
+ "one cell": "absolute");
snprintf (buffer, sizeof (buffer), "%.3g %.3g %.3g %.3g",
so->anchor.offset [0], so->anchor.offset [1],
so->anchor.offset [2], so->anchor.offset [3]);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]