[goffice] Allow the frame around a chart label to rotate with the text. [647147]
- From: Jean BrÃfort <jbrefort src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Allow the frame around a chart label to rotate with the text. [647147]
- Date: Sat, 6 Aug 2011 12:46:25 +0000 (UTC)
commit dd77e3de884f00951a8fcca60f0c28b144204d19
Author: Jean Brefort <jean brefort normalesup org>
Date: Sat Aug 6 14:50:52 2011 +0200
Allow the frame around a chart label to rotate with the text. [647147]
ChangeLog | 15 ++++
NEWS | 1 +
goffice/graph/gog-label.c | 177 ++++++++++++++++++++++++++++++++-------
goffice/graph/gog-label.h | 2 +
goffice/graph/gog-renderer.c | 74 ++++++++++++++++
goffice/graph/gog-renderer.h | 1 +
goffice/utils/go-style-prefs.ui | 13 ++-
7 files changed, 249 insertions(+), 34 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index ceff0d1..0acd7fb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2011-08-06 Jean Brefort <jean brefort normalesup org>
+
+ * goffice/graph/gog-label.c (gog_text_set_property),
+ (gog_text_get_property), (gog_text_class_init), (rotate_frame_cb),
+ (rotate_bg_cb), (allow_markup_cb), (gog_label_populate_editor),
+ (gog_label_class_init), (gog_text_view_size_request),
+ (gog_text_view_render): allow rotation of the frame along with the text.
+ [#647147]
+ * goffice/graph/gog-label.h:
+ * goffice/graph/gog-renderer.c (_draw_rotated_shape),
+ (gog_renderer_fill_rectangle), (_draw_rotated_rectangle),
+ (gog_renderer_draw_rotated_rectangle):
+ * goffice/graph/gog-renderer.h:
+ * goffice/utils/go-style-prefs.ui:
+
2011-08-05 Jean Brefort <jean brefort normalesup org>
* goffice/graph/goffice-graph.h: add support for rich text in legends.
diff --git a/NEWS b/NEWS
index bb707eb..b9e0f2a 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,7 @@ Andreas:
Jean:
* Port to gtk+-3.0.
* Add a plugin directory for extern plugins, independent from micro version.
+ * Allow the frame around a chart label to rotate with the text. [647147]
Morten:
* Recognize scientific formats with longer exponents.
diff --git a/goffice/graph/gog-label.c b/goffice/graph/gog-label.c
index ba85966..07ea47a 100644
--- a/goffice/graph/gog-label.c
+++ b/goffice/graph/gog-label.c
@@ -38,7 +38,9 @@ static GType gog_text_view_get_type (void);
enum {
TEXT_PROP_0,
- TEXT_PROP_ALLOW_MARKUP
+ TEXT_PROP_ALLOW_MARKUP,
+ TEXT_PROP_ROTATE_FRAME,
+ TEXT_PROP_ROTATE_BG
};
static GObjectClass *text_parent_klass;
@@ -53,6 +55,12 @@ gog_text_set_property (GObject *obj, guint param_id,
case TEXT_PROP_ALLOW_MARKUP :
text->allow_markup = g_value_get_boolean (value);
break;
+ case TEXT_PROP_ROTATE_FRAME:
+ text->rotate_frame = g_value_get_boolean (value);
+ break;
+ case TEXT_PROP_ROTATE_BG:
+ text->rotate_bg = g_value_get_boolean (value);
+ break;
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
return; /* NOTE : RETURN */
@@ -70,6 +78,12 @@ gog_text_get_property (GObject *obj, guint param_id,
case TEXT_PROP_ALLOW_MARKUP :
g_value_set_boolean (value, text->allow_markup);
break;
+ case TEXT_PROP_ROTATE_FRAME:
+ g_value_set_boolean (value, text->rotate_frame);
+ break;
+ case TEXT_PROP_ROTATE_BG:
+ g_value_set_boolean (value, text->rotate_bg);
+ break;
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
break;
@@ -115,7 +129,20 @@ gog_text_class_init (GogTextClass *klass)
g_param_spec_boolean ("allow-markup",
_("Allow markup"),
_("Support basic html-ish markup"),
- TRUE,
+ FALSE,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE | GO_PARAM_PERSISTENT));
+
+ g_object_class_install_property (gobject_klass, TEXT_PROP_ROTATE_FRAME,
+ g_param_spec_boolean ("rotate-frame",
+ _("Rotate the frame with the text"),
+ _("Whether the frame should be rotated with the text"),
+ FALSE,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE | GO_PARAM_PERSISTENT));
+ g_object_class_install_property (gobject_klass, TEXT_PROP_ROTATE_BG,
+ g_param_spec_boolean ("rotate-bg",
+ _("Rotate the background with the text"),
+ _("Whether the background should be rotated with the text"),
+ FALSE,
GSF_PARAM_STATIC | G_PARAM_READWRITE | GO_PARAM_PERSISTENT));
gog_klass->view_type = gog_text_view_get_type ();
@@ -169,12 +196,35 @@ struct _GogLabel {
GogDatasetElement text;
};
+enum {
+ LABEL_PROP_0,
+};
+
typedef GogTextClass GogLabelClass;
static GObjectClass *label_parent_klass;
#ifdef GOFFICE_WITH_GTK
+
+static void
+rotate_frame_cb (GtkToggleButton *btn, GObject *obj)
+{
+ g_object_set (obj, "rotate-frame", gtk_toggle_button_get_active (btn), NULL);
+}
+
+static void
+rotate_bg_cb (GtkToggleButton *btn, GObject *obj)
+{
+ g_object_set (obj, "rotate-bg", gtk_toggle_button_get_active (btn), NULL);
+}
+
+static void
+allow_markup_cb (GtkToggleButton *btn, GObject *obj)
+{
+ g_object_set (obj, "allow-markup", gtk_toggle_button_get_active (btn), NULL);
+}
+
static void
gog_label_populate_editor (GogObject *gobj,
GOEditor *editor,
@@ -182,21 +232,39 @@ gog_label_populate_editor (GogObject *gobj,
GOCmdContext *cc)
{
static guint label_pref_page = 0;
- GtkWidget *hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
- GtkWidget *alignment = gtk_alignment_new (0, 0, 1, 0);
+ GtkWidget *grid = gtk_grid_new ();
GtkWidget *editor_widget =
GTK_WIDGET
(gog_data_allocator_editor (dalloc, GOG_DATASET (gobj),
0, GOG_DATA_SCALAR));
+ GtkWidget *w;
- gtk_container_set_border_width (GTK_CONTAINER (alignment), 12);
- gtk_box_pack_start (GTK_BOX (hbox),
- gtk_label_new_with_mnemonic (_("_Text:")), FALSE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (hbox), editor_widget, TRUE, TRUE, 0);
- gtk_container_add (GTK_CONTAINER (alignment), hbox);
- gtk_widget_show_all (alignment);
-
- go_editor_add_page (editor, alignment, _("Data"));
+ g_object_set (G_OBJECT (grid),
+ "margin", 12,
+ "row-spacing", 12,
+ "column-spacing", 6,
+ NULL);
+ g_object_set (G_OBJECT (editor_widget), "hexpand", TRUE, NULL);
+
+ gtk_grid_attach (GTK_GRID (grid),
+ gtk_label_new_with_mnemonic (_("_Text:")), 0, 0, 1, 1);
+ gtk_grid_attach (GTK_GRID (grid), editor_widget, 1, 0, 1, 1);
+ w = gtk_check_button_new_with_label (_("Rotate frame with text"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), GOG_TEXT (gobj)->rotate_frame);
+ g_signal_connect (w, "toggled", G_CALLBACK (rotate_frame_cb), gobj);
+ gtk_grid_attach (GTK_GRID (grid), w, 0, 1, 2, 1);
+ w = gtk_check_button_new_with_label (_("Rotate background with text"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), GOG_TEXT (gobj)->rotate_bg);
+ g_signal_connect (w, "toggled", G_CALLBACK (rotate_bg_cb), gobj);
+ gtk_grid_attach (GTK_GRID (grid), w, 0, 2, 2, 1);
+ w = gtk_check_button_new_with_label (_("Interpret text as markup"));
+ gtk_widget_set_tooltip_text (w, _("Interpret the text as an html like markup as described at http://developer.gnome.org/pango/stable/PangoMarkupFormat.html"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), GOG_TEXT (gobj)->allow_markup);
+ g_signal_connect (w, "toggled", G_CALLBACK (allow_markup_cb), gobj);
+ gtk_grid_attach (GTK_GRID (grid), w, 0, 3, 2, 1);
+ gtk_widget_show_all (grid);
+
+ go_editor_add_page (editor, grid, _("Details"));
(GOG_OBJECT_CLASS(label_parent_klass)->populate_editor) (gobj, editor, dalloc, cc);
go_editor_set_store_page (editor, &label_pref_page);
@@ -245,11 +313,11 @@ gog_label_class_init (GogLabelClass *klass)
GogObjectClass *gog_klass = (GogObjectClass *) klass;
gog_klass->populate_editor = gog_label_populate_editor;
#endif
-
label_parent_klass = g_type_class_peek_parent (klass);
- gobject_klass->finalize = gog_label_finalize;
- got_klass->get_str = gog_label_get_str;
- got_klass->get_markup = gog_label_get_markup;
+ gobject_klass->finalize = gog_label_finalize;
+
+ got_klass->get_str = gog_label_get_str;
+ got_klass->get_markup = gog_label_get_markup;
}
static void
@@ -465,15 +533,34 @@ gog_text_view_size_request (GogView *v,
{
GogText *text = GOG_TEXT (v->model);
char *str = gog_text_get_str (text);
+ PangoAttrList *pl = text->allow_markup? NULL: gog_text_get_markup (text);
GOGeometryAABR aabr;
req->w = req->h = 0.;
if (str != NULL) {
- gog_renderer_push_style (v->renderer, text->base.base.style);
- gog_renderer_get_text_AABR (v->renderer, str, FALSE, &aabr);
+ GOString *gostr = pl? go_string_new_rich (str, -1, FALSE,
+ gog_text_get_markup (text),
+ NULL): NULL;
+ GOStyle *style = go_style_dup (text->base.base.style);
+ double rot = fabs (style->text_layout.angle / 180 * M_PI);
+ if (text->rotate_frame)
+ style->text_layout.angle = 0.;
+ gog_renderer_push_style (v->renderer, style);
+ if (gostr) {
+ gog_renderer_get_gostring_AABR (v->renderer, gostr, &aabr);
+ go_string_unref (gostr);
+ } else
+ gog_renderer_get_text_AABR (v->renderer, str, text->allow_markup, &aabr);
gog_renderer_pop_style (v->renderer);
- req->w = aabr.w;
- req->h = aabr.h;
+ g_object_unref (style);
+ if (text->rotate_frame) {
+ req->w = aabr.w * cos (rot) + aabr.h * sin (rot);
+ req->h = aabr.w * sin (rot) + aabr.h * cos (rot);
+ } else {
+ req->w = aabr.w;
+ req->h = aabr.h;
+ }
+ go_string_unref (gostr);
g_free (str);
}
text_view_parent_klass->size_request (v, available, req);
@@ -486,28 +573,56 @@ gog_text_view_render (GogView *view, GogViewAllocation const *bbox)
GogOutlinedObject *goo = GOG_OUTLINED_OBJECT (text);
GOStyle *style = text->base.base.style;
char *str = gog_text_get_str (text);
+ PangoAttrList *pl = text->allow_markup? NULL: gog_text_get_markup (text);
gog_renderer_push_style (view->renderer, style);
if (str != NULL) {
- GOString *gostr = go_string_new_rich (str, -1, FALSE,
- gog_label_get_markup (text),
- NULL);
+ GOString *gostr = pl? go_string_new_rich (str, -1, FALSE,
+ gog_text_get_markup (text),
+ NULL): NULL;
double outline = gog_renderer_line_size (view->renderer,
goo->base.style->line.width);
if (style->fill.type != GO_STYLE_FILL_NONE || outline > 0.) {
GogViewAllocation rect;
GOGeometryAABR aabr;
+ GOStyle *rect_style = NULL;
double pad_x = gog_renderer_pt2r_x (view->renderer, goo->padding_pts);
double pad_y = gog_renderer_pt2r_y (view->renderer, goo->padding_pts);
- gog_renderer_get_gostring_AABR (view->renderer, gostr, &aabr);
- rect = view->allocation;
- rect.w = aabr.w + 2. * outline + pad_x;
- rect.h = aabr.h + 2. * outline + pad_y;
- gog_renderer_draw_rectangle (view->renderer, &rect);
+ double rot = style->text_layout.angle / 180 * M_PI;
+ if (text->rotate_frame) {
+ rect_style = go_style_dup (text->base.base.style);
+ rect_style->text_layout.angle = 0.;
+ gog_renderer_push_style (view->renderer, rect_style);
+ }
+ if (gostr)
+ gog_renderer_get_gostring_AABR (view->renderer, gostr, &aabr);
+ else
+ gog_renderer_get_text_AABR (view->renderer, str, text->allow_markup, &aabr);
+ if (text->rotate_frame) {
+ rect = view->allocation;
+ rect.w = aabr.w + 2. * outline + pad_x;
+ rect.h = aabr.h + 2. * outline + pad_y;
+ if (rot > 0.)
+ rect.y += rect.w * sin (rot);
+ else
+ rect.x -= rect.h * sin (rot);
+ gog_renderer_pop_style (view->renderer);
+ g_object_unref (rect_style);
+ } else {
+ rect = view->allocation;
+ rect.w = aabr.w + 2. * outline + pad_x;
+ rect.h = aabr.h + 2. * outline + pad_y;
+ }
+ gog_renderer_draw_rotated_rectangle (view->renderer, &rect, text->rotate_bg);
}
- gog_renderer_draw_gostring (view->renderer, gostr,
- &view->residual, GO_ANCHOR_NW);
- go_string_unref (gostr);
+ if (gostr) {
+ gog_renderer_draw_gostring (view->renderer, gostr,
+ &view->residual, GO_ANCHOR_NW);
+ go_string_unref (gostr);
+ } else
+ gog_renderer_draw_text (view->renderer, str,
+ &view->residual, GO_ANCHOR_NW,
+ text->allow_markup);
g_free (str);
}
gog_renderer_pop_style (view->renderer);
diff --git a/goffice/graph/gog-label.h b/goffice/graph/gog-label.h
index 63378b7..813e0f3 100644
--- a/goffice/graph/gog-label.h
+++ b/goffice/graph/gog-label.h
@@ -30,6 +30,8 @@ typedef struct {
GogOutlinedObject base;
gboolean allow_markup;
+ gboolean rotate_frame;
+ gboolean rotate_bg;
} GogText;
typedef struct {
diff --git a/goffice/graph/gog-renderer.c b/goffice/graph/gog-renderer.c
index c391b1f..7ea33d9 100644
--- a/goffice/graph/gog-renderer.c
+++ b/goffice/graph/gog-renderer.c
@@ -487,6 +487,41 @@ gog_renderer_fill_shape (GogRenderer *renderer, GOPath const *path)
_draw_shape (renderer, path, TRUE, FALSE);
}
+static void
+_draw_rotated_shape (GogRenderer *renderer, GOPath const *path, gboolean fill, gboolean stroke, gboolean rotate_bg)
+{
+ GOStyle const *style;
+ GOPathOptions line_options;
+ double width;
+
+ g_return_if_fail (GOG_IS_RENDERER (renderer));
+ g_return_if_fail (renderer->cur_style != NULL);
+ g_return_if_fail (GO_IS_PATH (path));
+
+ style = renderer->cur_style;
+
+ line_options = go_path_get_options (path);
+ width = stroke ? _grc_line_size (renderer, style->line.width,
+ line_options & GO_PATH_OPTIONS_SNAP_WIDTH) : 0;
+
+ cairo_save (renderer->cairo);
+ cairo_rotate (renderer->cairo, -renderer->cur_style->text_layout.angle *M_PI / 180.);
+ path_interpret (renderer, path, width);
+
+ if (fill) {
+ if (rotate_bg) {
+ emit_fill (renderer, stroke);
+ cairo_restore (renderer->cairo);
+ } else {
+ cairo_restore (renderer->cairo);
+ emit_fill (renderer, stroke);
+ }
+ }
+
+ if (stroke)
+ emit_line (renderer, FALSE, go_path_get_options (path));
+}
+
/*****************************************************************************/
/**
@@ -661,6 +696,45 @@ gog_renderer_fill_rectangle (GogRenderer *rend, GogViewAllocation const *rect)
_draw_rectangle (rend, rect, TRUE, FALSE);
}
+static void
+_draw_rotated_rectangle (GogRenderer *rend, GogViewAllocation const *rect, gboolean fill, gboolean stroke, gboolean rotate_bg)
+{
+ GOStyle const *style;
+ GOPath *path;
+ gboolean narrow = (rect->w < 3.) || (rect->h < 3.);
+ double o, o_2;
+
+ g_return_if_fail (GOG_IS_RENDERER (rend));
+ g_return_if_fail (GO_IS_STYLE (rend->cur_style));
+
+ style = rend->cur_style;
+ narrow |= !go_style_is_outline_visible (style);
+
+ path = go_path_new ();
+ go_path_set_options (path, GO_PATH_OPTIONS_SHARP);
+
+ if (!narrow) {
+ o = gog_renderer_line_size (rend, style->line.width);
+ o_2 = o / 2.;
+ } else
+ o = o_2 = 0.;
+
+ go_path_rectangle (path, 0., 0., rect->w - o, rect->h - o);
+
+ cairo_save (rend->cairo);
+ cairo_translate (rend->cairo, rect->x - o_2, rect->y - o_2);
+ _draw_rotated_shape (rend, path, fill, stroke && !narrow, rotate_bg);
+ cairo_restore (rend->cairo);
+
+ go_path_free (path);
+}
+
+void
+gog_renderer_draw_rotated_rectangle (GogRenderer *rend, GogViewAllocation const *rect, gboolean rotate_bg)
+{
+ _draw_rotated_rectangle (rend, rect, TRUE, TRUE, rotate_bg);
+}
+
/**
* gog_renderer_draw_grip:
* @renderer : #GogRenderer
diff --git a/goffice/graph/gog-renderer.h b/goffice/graph/gog-renderer.h
index 9dfd1e7..2e31e6b 100644
--- a/goffice/graph/gog-renderer.h
+++ b/goffice/graph/gog-renderer.h
@@ -72,6 +72,7 @@ void gog_renderer_stroke_circle (GogRenderer *rend, double x, double y, double
void gog_renderer_fill_circle (GogRenderer *rend, double x, double y, double r);
void gog_renderer_draw_rectangle (GogRenderer *rend, GogViewAllocation const *rect);
+void gog_renderer_draw_rotated_rectangle (GogRenderer *rend, GogViewAllocation const *rect, gboolean rotate_bg);
void gog_renderer_stroke_rectangle (GogRenderer *rend, GogViewAllocation const *rect);
void gog_renderer_fill_rectangle (GogRenderer *rend, GogViewAllocation const *rect);
diff --git a/goffice/utils/go-style-prefs.ui b/goffice/utils/go-style-prefs.ui
index b6e5eae..f8ef3df 100644
--- a/goffice/utils/go-style-prefs.ui
+++ b/goffice/utils/go-style-prefs.ui
@@ -572,6 +572,13 @@
<object class="GtkComboBoxText" id="fill-type-menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <items>
+ <item translatable="yes">None</item>
+ <item translatable="yes">Pattern</item>
+ <item translatable="yes">Bicolor gradient</item>
+ <item translatable="yes">Unicolor gradient</item>
+ <item translatable="yes">Image</item>
+ </items>
</object>
<packing>
<property name="expand">False</property>
@@ -918,9 +925,6 @@
</packing>
</child>
<child>
- <placeholder/>
- </child>
- <child>
<object class="GtkComboBoxText" id="fill-image-fit">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -935,6 +939,9 @@
<property name="right_attach">2</property>
</packing>
</child>
+ <child>
+ <placeholder/>
+ </child>
</object>
<packing>
<property name="position">2</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]