mirror of https://github.com/Gnucash/gnucash
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1857 lines
52 KiB
1857 lines
52 KiB
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
|
/*
|
|
* gog-style.c :
|
|
*
|
|
* Copyright (C) 2003-2004 Jody Goldberg (jody@gnome.org)
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of version 2 of the GNU General Public
|
|
* License as published by the Free Software Foundation.
|
|
*
|
|
* 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 <goffice/goffice-config.h>
|
|
#include <goffice/graph/gog-style.h>
|
|
#include <goffice/graph/gog-styled-object.h>
|
|
#include <goffice/utils/go-color.h>
|
|
#include <goffice/utils/go-font.h>
|
|
#include <goffice/utils/go-file.h>
|
|
#include <goffice/utils/go-line.h>
|
|
#include <goffice/utils/go-marker.h>
|
|
|
|
#include <goffice/gui-utils/go-color-palette.h>
|
|
#include <goffice/gui-utils/go-combo-color.h>
|
|
#include <goffice/gui-utils/go-combo-pixmaps.h>
|
|
|
|
// #include <src/gui-util.h>
|
|
#include <gui-util.h>
|
|
#include <glade/glade-xml.h>
|
|
#include <gtk/gtkcheckbutton.h>
|
|
#include <gtk/gtkspinbutton.h>
|
|
#include <gtk/gtklabel.h>
|
|
#include <gtk/gtkimage.h>
|
|
#include <gtk/gtktable.h>
|
|
#include <gtk/gtkvbox.h>
|
|
#include <gtk/gtkrange.h>
|
|
#include <gtk/gtkcombobox.h>
|
|
#include <gtk/gtknotebook.h>
|
|
#include <widgets/widget-font-selector.h>
|
|
#include <gui-file.h>
|
|
#include <gdk-pixbuf/gdk-pixdata.h>
|
|
|
|
#include <gsf/gsf-impl-utils.h>
|
|
#include <glib/gi18n.h>
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
|
|
|
#define HSCALE 100
|
|
#define VSCALE 120
|
|
|
|
typedef GObjectClass GogStyleClass;
|
|
|
|
static GObjectClass *parent_klass;
|
|
|
|
/**
|
|
* I would have liked to do this differently and have a tighter binding between theme element and style
|
|
* eg gog_style_new (theme_element)
|
|
* However that will not work easily in the context of xls import where we do
|
|
* not know what the type is destined for until later. This structure melds
|
|
* smoothly with both approaches at the expense of a bit of power.
|
|
**/
|
|
/*************************************************************************/
|
|
|
|
typedef struct {
|
|
GladeXML *gui;
|
|
GogStyle *style;
|
|
GogStyle *default_style;
|
|
GObject *object_with_style;
|
|
gboolean enable_edit;
|
|
gulong style_changed_handler;
|
|
struct {
|
|
struct {
|
|
GtkWidget *fore, *back, *combo;
|
|
} pattern;
|
|
struct {
|
|
GtkWidget *start, *end, *end_label, *combo;
|
|
GtkWidget *brightness, *brightness_box;
|
|
guint timer;
|
|
} gradient;
|
|
struct {
|
|
GdkPixbuf *image;
|
|
} image;
|
|
} fill;
|
|
struct {
|
|
GtkWidget *combo;
|
|
} marker;
|
|
} StylePrefState;
|
|
|
|
static void
|
|
cb_style_changed (GogStyledObject *obj, GogStyle *style, StylePrefState *state)
|
|
{
|
|
}
|
|
|
|
static void
|
|
set_style (StylePrefState const *state)
|
|
{
|
|
if (state->object_with_style != NULL) {
|
|
if (state->style_changed_handler)
|
|
g_signal_handler_block (state->object_with_style, state->style_changed_handler);
|
|
g_object_set (G_OBJECT (state->object_with_style), "style", state->style, NULL);
|
|
if (state->style_changed_handler)
|
|
g_signal_handler_unblock (state->object_with_style, state->style_changed_handler);
|
|
}
|
|
}
|
|
|
|
static GtkWidget *
|
|
create_go_combo_color (StylePrefState *state,
|
|
GOColor initial_val, GOColor default_val,
|
|
char const *group, char const *label_name,
|
|
GCallback func)
|
|
{
|
|
GtkWidget *w;
|
|
|
|
w = go_combo_color_new (NULL, _("Automatic"), default_val,
|
|
go_color_group_fetch (group, NULL));
|
|
go_combo_color_set_instant_apply (GO_COMBO_COLOR (w), FALSE);
|
|
go_combo_color_set_allow_alpha (GO_COMBO_COLOR (w), TRUE);
|
|
gtk_label_set_mnemonic_widget (
|
|
GTK_LABEL (glade_xml_get_widget (state->gui, label_name)), w);
|
|
go_combo_color_set_color (GO_COMBO_COLOR (w), initial_val);
|
|
g_signal_connect (G_OBJECT (w),
|
|
"color_changed",
|
|
G_CALLBACK (func), state);
|
|
return w;
|
|
}
|
|
|
|
static void
|
|
gog_style_set_image_preview (GdkPixbuf *pix, StylePrefState *state)
|
|
{
|
|
GdkPixbuf *scaled;
|
|
int width, height;
|
|
char *size;
|
|
GtkWidget *w;
|
|
|
|
if (state->fill.image.image != pix) {
|
|
if (state->fill.image.image != NULL)
|
|
g_object_unref (state->fill.image.image);
|
|
state->fill.image.image = pix;
|
|
if (state->fill.image.image != NULL)
|
|
g_object_ref (state->fill.image.image);
|
|
}
|
|
|
|
w = glade_xml_get_widget (state->gui, "fill_image_sample");
|
|
|
|
scaled = gnm_pixbuf_intelligent_scale (pix, HSCALE, VSCALE);
|
|
gtk_image_set_from_pixbuf (GTK_IMAGE (w), scaled);
|
|
g_object_unref (scaled);
|
|
|
|
w = glade_xml_get_widget (state->gui, "image-size-label");
|
|
width = gdk_pixbuf_get_width (pix);
|
|
height = gdk_pixbuf_get_height (pix);
|
|
|
|
size = g_strdup_printf (_("%d x %d"), width, height);
|
|
gtk_label_set_text (GTK_LABEL (w), size);
|
|
g_free (size);
|
|
}
|
|
|
|
/************************************************************************/
|
|
static void
|
|
cb_outline_dash_type_changed (GtkWidget *cc, int dash_type, StylePrefState const *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
gboolean is_auto = dash_type < 0;
|
|
|
|
if (is_auto)
|
|
dash_type = -dash_type;
|
|
style->outline.auto_dash = is_auto;
|
|
style->outline.dash_type = dash_type;
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
cb_outline_size_changed (GtkAdjustment *adj, StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
|
|
g_return_if_fail (style != NULL);
|
|
|
|
style->outline.width = rint (adj->value * 100.) / 100.;
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
cb_outline_color_changed (G_GNUC_UNUSED GOComboColor *cc, GOColor color,
|
|
G_GNUC_UNUSED gboolean is_custom,
|
|
G_GNUC_UNUSED gboolean by_user,
|
|
gboolean is_default, StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
|
|
g_return_if_fail (style != NULL);
|
|
|
|
style->outline.color = color;
|
|
style->outline.auto_color = is_default;
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
outline_init (StylePrefState *state, gboolean enable)
|
|
{
|
|
GogStyle *style = state->style;
|
|
GogStyle *default_style = state->default_style;
|
|
GtkWidget *w, *table;
|
|
|
|
if (!enable) {
|
|
gtk_widget_hide (glade_xml_get_widget (state->gui, "outline_box"));
|
|
return;
|
|
}
|
|
|
|
table = glade_xml_get_widget (state->gui, "outline_table");
|
|
|
|
/* DashType */
|
|
w = go_line_dash_selector (default_style->outline.dash_type);
|
|
gtk_table_attach (GTK_TABLE (table), w, 1, 3, 0, 1, 0, 0, 0, 0);
|
|
go_combo_pixmaps_select_id (GO_COMBO_PIXMAPS (w), style->outline.dash_type);
|
|
g_signal_connect (G_OBJECT (w),
|
|
"changed",
|
|
G_CALLBACK (cb_outline_dash_type_changed), state);
|
|
/* Size */
|
|
w = glade_xml_get_widget (state->gui, "outline_size_spin");
|
|
gtk_spin_button_set_value (GTK_SPIN_BUTTON (w), style->outline.width);
|
|
g_signal_connect (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (w)),
|
|
"value_changed",
|
|
G_CALLBACK (cb_outline_size_changed), state);
|
|
/* Color */
|
|
w = create_go_combo_color (state,
|
|
style->outline.color, default_style->outline.color,
|
|
"outline_color", "outline_color_label",
|
|
G_CALLBACK (cb_outline_color_changed));
|
|
gtk_table_attach (GTK_TABLE (table), w, 1, 2, 1, 2, 0, 0, 0, 0);
|
|
gtk_widget_show_all (table);
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
static void
|
|
cb_line_dash_type_changed (GtkWidget *cc, int dash_type, StylePrefState const *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
gboolean is_auto = dash_type < 0;
|
|
|
|
if (is_auto)
|
|
dash_type = -dash_type;
|
|
style->line.auto_dash = is_auto;
|
|
style->line.dash_type = dash_type;
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
cb_line_size_changed (GtkAdjustment *adj, StylePrefState const *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
|
|
g_return_if_fail (style != NULL);
|
|
|
|
style->line.width = rint (adj->value * 100.) / 100.;
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
cb_line_color_changed (G_GNUC_UNUSED GOComboColor *cc, GOColor color,
|
|
G_GNUC_UNUSED gboolean is_custom,
|
|
G_GNUC_UNUSED gboolean by_user,
|
|
gboolean is_default, StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
|
|
g_return_if_fail (style != NULL);
|
|
|
|
style->line.color = color;
|
|
style->line.auto_color = is_default;
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
line_init (StylePrefState *state, gboolean enable)
|
|
{
|
|
GogStyle *style = state->style;
|
|
GogStyle *default_style = state->default_style;
|
|
GtkWidget *w, *table;
|
|
|
|
if (!enable) {
|
|
gtk_widget_hide (glade_xml_get_widget (state->gui, "line_box"));
|
|
return;
|
|
}
|
|
|
|
table = glade_xml_get_widget (state->gui, "line_table");
|
|
|
|
/* DashType */
|
|
w = go_line_dash_selector (default_style->line.dash_type);
|
|
gtk_table_attach (GTK_TABLE (table), w, 1, 3, 0, 1, 0, 0, 0, 0);
|
|
go_combo_pixmaps_select_id (GO_COMBO_PIXMAPS (w), style->line.dash_type);
|
|
g_signal_connect (G_OBJECT (w),
|
|
"changed",
|
|
G_CALLBACK (cb_line_dash_type_changed), state);
|
|
|
|
/* Size */
|
|
w = glade_xml_get_widget (state->gui, "line_size_spin");
|
|
gtk_spin_button_set_value (GTK_SPIN_BUTTON (w), style->line.width);
|
|
g_signal_connect (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (w)),
|
|
"value_changed",
|
|
G_CALLBACK (cb_line_size_changed), state);
|
|
|
|
/* Colour */
|
|
w = create_go_combo_color (state,
|
|
style->line.color, default_style->line.color,
|
|
"line_color", "line_color_label",
|
|
G_CALLBACK (cb_line_color_changed));
|
|
gtk_table_attach (GTK_TABLE (table), w, 1, 2, 1, 2, 0, 0, 0, 0);
|
|
gtk_widget_show_all (table);
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
static void
|
|
cb_pattern_type_changed (GtkWidget *cc, int pattern, StylePrefState const *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
gboolean is_auto = pattern < 0;
|
|
|
|
if (is_auto)
|
|
pattern = -pattern;
|
|
style->fill.pattern.pattern = pattern;
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
populate_pattern_combo (StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
GogStyle *default_style = state->default_style;
|
|
GtkWidget *table, *combo;
|
|
GOPatternType type = GO_PATTERN_SOLID;
|
|
|
|
if (state->fill.pattern.combo != NULL)
|
|
gtk_widget_destroy (state->fill.pattern.combo);
|
|
|
|
state->fill.pattern.combo = combo = go_pattern_selector (
|
|
style->fill.pattern.fore,
|
|
style->fill.pattern.back,
|
|
default_style->fill.pattern.pattern);
|
|
|
|
table = glade_xml_get_widget (state->gui, "fill_pattern_table");
|
|
gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 0, 1, 0, 0, 0, 0);
|
|
gtk_label_set_mnemonic_widget (
|
|
GTK_LABEL (glade_xml_get_widget (state->gui, "fill_pattern_type_label")), combo);
|
|
|
|
if (style->fill.type == GOG_FILL_STYLE_PATTERN)
|
|
type = style->fill.pattern.pattern;
|
|
go_combo_pixmaps_select_id (GO_COMBO_PIXMAPS(combo), type);
|
|
g_signal_connect (G_OBJECT (combo),
|
|
"changed",
|
|
G_CALLBACK (cb_pattern_type_changed), state);
|
|
gtk_widget_show (combo);
|
|
}
|
|
|
|
static void
|
|
cb_fg_color_changed (G_GNUC_UNUSED GOComboColor *cc, GOColor color,
|
|
G_GNUC_UNUSED gboolean is_custom,
|
|
G_GNUC_UNUSED gboolean by_user,
|
|
gboolean is_default, StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
|
|
g_return_if_fail (style != NULL);
|
|
g_return_if_fail (GOG_FILL_STYLE_PATTERN == style->fill.type);
|
|
|
|
style->fill.pattern.fore = color;
|
|
style->fill.auto_fore = is_default;
|
|
set_style (state);
|
|
populate_pattern_combo (state);
|
|
}
|
|
|
|
static void
|
|
cb_bg_color_changed (G_GNUC_UNUSED GOComboColor *cc, GOColor color,
|
|
G_GNUC_UNUSED gboolean is_custom,
|
|
G_GNUC_UNUSED gboolean by_user,
|
|
gboolean is_default, StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
|
|
g_return_if_fail (style != NULL);
|
|
g_return_if_fail (GOG_FILL_STYLE_PATTERN == style->fill.type);
|
|
|
|
style->fill.pattern.back = color;
|
|
style->fill.auto_back = is_default;
|
|
set_style (state);
|
|
populate_pattern_combo (state);
|
|
}
|
|
|
|
static void
|
|
fill_pattern_init (StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
GogStyle *default_style = state->default_style;
|
|
|
|
GtkWidget *w, *table =
|
|
glade_xml_get_widget (state->gui, "fill_pattern_table");
|
|
|
|
state->fill.pattern.fore = w = create_go_combo_color (state,
|
|
style->fill.pattern.fore,
|
|
default_style->fill.pattern.fore,
|
|
"pattern_foreground", "fill_pattern_foreground_label",
|
|
G_CALLBACK (cb_fg_color_changed));
|
|
gtk_table_attach (GTK_TABLE (table), w, 1, 2, 1, 2, 0, 0, 0, 0);
|
|
|
|
state->fill.pattern.back = w = create_go_combo_color (state,
|
|
style->fill.pattern.back,
|
|
default_style->fill.pattern.back,
|
|
"pattern_background", "fill_pattern_background_label",
|
|
G_CALLBACK (cb_bg_color_changed));
|
|
gtk_table_attach (GTK_TABLE (table), w, 1, 2, 2, 3, 0, 0, 0, 0);
|
|
|
|
populate_pattern_combo (state);
|
|
gtk_widget_show_all (table);
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
static GOGradientDirection default_to_last_selected_type = GO_GRADIENT_N_TO_S;
|
|
static void
|
|
cb_gradient_type_changed (GtkWidget *cc, int id, StylePrefState const *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
style->fill.gradient.dir = default_to_last_selected_type = id;
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
populate_gradient_combo (StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
GtkWidget *combo, *table;
|
|
|
|
if (state->fill.gradient.combo != NULL)
|
|
gtk_widget_destroy (state->fill.gradient.combo);
|
|
|
|
state->fill.gradient.combo = combo = go_gradient_selector (
|
|
style->fill.pattern.back,
|
|
style->fill.pattern.fore);
|
|
gtk_label_set_mnemonic_widget (
|
|
GTK_LABEL (glade_xml_get_widget (state->gui, "fill_gradient_direction_label")), combo);
|
|
|
|
table = glade_xml_get_widget (state->gui, "fill_gradient_table");
|
|
gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 0, 1, 0, 0, 0, 0);
|
|
go_combo_pixmaps_select_id (GO_COMBO_PIXMAPS (combo),
|
|
(style->fill.type == GOG_FILL_STYLE_GRADIENT)
|
|
? style->fill.gradient.dir : default_to_last_selected_type);
|
|
|
|
g_signal_connect (G_OBJECT (combo),
|
|
"changed",
|
|
G_CALLBACK (cb_gradient_type_changed), state);
|
|
gtk_widget_show (combo);
|
|
}
|
|
|
|
static void
|
|
cb_fill_gradient_start_color (G_GNUC_UNUSED GOComboColor *cc, GOColor color,
|
|
G_GNUC_UNUSED gboolean is_custom,
|
|
G_GNUC_UNUSED gboolean by_user,
|
|
gboolean is_default, StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
style->fill.pattern.back = color;
|
|
style->fill.auto_back = is_default;
|
|
set_style (state);
|
|
populate_gradient_combo (state);
|
|
}
|
|
|
|
static gboolean
|
|
cb_delayed_gradient_combo_update (StylePrefState *state)
|
|
{
|
|
state->fill.gradient.timer = 0;
|
|
populate_gradient_combo (state);
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
cb_fill_gradient_end_color (G_GNUC_UNUSED GOComboColor *cc, GOColor color,
|
|
G_GNUC_UNUSED gboolean is_custom,
|
|
gboolean by_user,
|
|
gboolean is_default, StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
|
|
style->fill.pattern.fore = color;
|
|
style->fill.auto_fore = is_default;
|
|
set_style (state);
|
|
|
|
if (by_user)
|
|
populate_gradient_combo (state);
|
|
else {
|
|
if (state->fill.gradient.timer != 0)
|
|
g_source_remove (state->fill.gradient.timer);
|
|
state->fill.gradient.timer = g_timeout_add (100,
|
|
(GSourceFunc) cb_delayed_gradient_combo_update, state);
|
|
}
|
|
}
|
|
|
|
static void
|
|
cb_gradient_brightness_value_changed (GtkWidget *w, StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
|
|
gog_style_set_fill_brightness (style,
|
|
gtk_range_get_value (GTK_RANGE (w)));
|
|
go_combo_color_set_color (GO_COMBO_COLOR (state->fill.gradient.end),
|
|
style->fill.pattern.fore);
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
cb_gradient_style_changed (GtkWidget *w, StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
|
|
GtkWidget *val = glade_xml_get_widget (state->gui,
|
|
"fill_gradient_brightness");
|
|
GtkWidget *box = glade_xml_get_widget (state->gui,
|
|
"fill_gradient_brightness_box");
|
|
|
|
gboolean two_color = gtk_combo_box_get_active (GTK_COMBO_BOX (w)) == 0;
|
|
|
|
if (two_color) {
|
|
style->fill.gradient.brightness = -1;
|
|
gtk_widget_hide (box);
|
|
} else {
|
|
gtk_widget_show (box);
|
|
gog_style_set_fill_brightness (style,
|
|
gtk_range_get_value (GTK_RANGE (val)));
|
|
go_combo_color_set_color (GO_COMBO_COLOR (state->fill.gradient.end),
|
|
style->fill.pattern.fore);
|
|
}
|
|
g_object_set (G_OBJECT (state->fill.gradient.end), "visible", two_color, NULL);
|
|
g_object_set (G_OBJECT (state->fill.gradient.end_label), "visible", two_color, NULL);
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
fill_gradient_init (StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
GogStyle *default_style = state->default_style;
|
|
GtkWidget *w, *table = glade_xml_get_widget (state->gui, "fill_gradient_table");
|
|
GtkWidget *type = glade_xml_get_widget (state->gui, "fill_gradient_type");
|
|
|
|
state->fill.gradient.start = w = create_go_combo_color (state,
|
|
style->fill.pattern.back,
|
|
default_style->fill.pattern.back,
|
|
"gradient_start", "fill_gradient_start_label",
|
|
G_CALLBACK (cb_fill_gradient_start_color));
|
|
gtk_table_attach (GTK_TABLE (table), w, 1, 2, 2, 3, 0, 0, 0, 0);
|
|
gtk_widget_show (w);
|
|
|
|
state->fill.gradient.end = w = create_go_combo_color (state,
|
|
style->fill.pattern.fore,
|
|
default_style->fill.pattern.fore,
|
|
"gradient_end", "fill_gradient_end_label",
|
|
G_CALLBACK (cb_fill_gradient_end_color));
|
|
gtk_table_attach (GTK_TABLE (table), w, 3, 4, 2, 3, 0, 0, 0, 0);
|
|
gtk_widget_show (w);
|
|
|
|
state->fill.gradient.end_label = glade_xml_get_widget (state->gui,
|
|
"fill_gradient_end_label");
|
|
state->fill.gradient.brightness = glade_xml_get_widget (state->gui,
|
|
"fill_gradient_brightness");
|
|
state->fill.gradient.brightness_box = glade_xml_get_widget (state->gui,
|
|
"fill_gradient_brightness_box");
|
|
|
|
if ((style->fill.type != GOG_FILL_STYLE_GRADIENT) ||
|
|
(style->fill.gradient.brightness < 0)) {
|
|
gtk_combo_box_set_active (GTK_COMBO_BOX (type), 0);
|
|
gtk_widget_hide (state->fill.gradient.brightness_box);
|
|
} else {
|
|
gtk_combo_box_set_active (GTK_COMBO_BOX (type), 1);
|
|
gtk_widget_show (state->fill.gradient.brightness_box);
|
|
gtk_range_set_value (GTK_RANGE (state->fill.gradient.brightness),
|
|
style->fill.gradient.brightness);
|
|
gtk_widget_hide (state->fill.gradient.end);
|
|
gtk_widget_hide (state->fill.gradient.end_label);
|
|
}
|
|
|
|
g_signal_connect (G_OBJECT (type),
|
|
"changed",
|
|
G_CALLBACK (cb_gradient_style_changed), state);
|
|
g_signal_connect (G_OBJECT (state->fill.gradient.brightness),
|
|
"value_changed",
|
|
G_CALLBACK (cb_gradient_brightness_value_changed), state);
|
|
|
|
populate_gradient_combo (state);
|
|
gtk_widget_show (table);
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
static void
|
|
cb_image_file_select (GtkWidget *cc, StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
char *filename, *uri, *old_uri;
|
|
GtkWidget *w;
|
|
|
|
g_return_if_fail (style != NULL);
|
|
g_return_if_fail (GOG_FILL_STYLE_IMAGE == style->fill.type);
|
|
|
|
filename = style->fill.image.filename;
|
|
old_uri = filename ? go_filename_to_uri (filename) : NULL;
|
|
printf( "cb_image_file_select .. gui_image_file_select\n" );
|
|
//uri = gui_image_file_select (NULL, old_uri);
|
|
uri = "http://localhost/";
|
|
g_free (old_uri);
|
|
if (uri == NULL)
|
|
return;
|
|
filename = go_filename_from_uri (uri);
|
|
g_free (uri);
|
|
if (filename == NULL) {
|
|
g_warning ("Sorry -- cannot handle URIs here right now.");
|
|
return;
|
|
}
|
|
#ifdef GOG_WARN_TODO
|
|
#warning "Handle URIs here."
|
|
#endif
|
|
|
|
gog_style_set_fill_image_filename (style, filename);
|
|
|
|
w = glade_xml_get_widget (state->gui, "fill_image_sample");
|
|
g_object_set_data (G_OBJECT (w), "filename",
|
|
style->fill.image.filename);
|
|
|
|
gog_style_set_image_preview (style->fill.image.image, state);
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
cb_image_style_changed (GtkWidget *w, StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
g_return_if_fail (style != NULL);
|
|
g_return_if_fail (GOG_FILL_STYLE_IMAGE == style->fill.type);
|
|
style->fill.image.type = gtk_combo_box_get_active (GTK_COMBO_BOX (w));
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
fill_image_init (StylePrefState *state)
|
|
{
|
|
GtkWidget *w, *sample, *type;
|
|
GogStyle *style = state->style;
|
|
|
|
w = glade_xml_get_widget (state->gui, "fill_image_select_picture");
|
|
g_signal_connect (G_OBJECT (w),
|
|
"clicked",
|
|
G_CALLBACK (cb_image_file_select), state);
|
|
|
|
sample = glade_xml_get_widget (state->gui, "fill_image_sample");
|
|
gtk_widget_set_size_request (sample, HSCALE + 10, VSCALE + 10);
|
|
type = glade_xml_get_widget (state->gui, "fill_image_fit");
|
|
|
|
state->fill.image.image = NULL;
|
|
|
|
if (GOG_FILL_STYLE_IMAGE == style->fill.type) {
|
|
gtk_combo_box_set_active (GTK_COMBO_BOX (type),
|
|
style->fill.image.type);
|
|
gog_style_set_image_preview (style->fill.image.image, state);
|
|
state->fill.image.image = style->fill.image.image;
|
|
if (state->fill.image.image)
|
|
g_object_ref (state->fill.image.image);
|
|
g_object_set_data (G_OBJECT (sample), "filename",
|
|
style->fill.image.filename);
|
|
} else
|
|
gtk_combo_box_set_active (GTK_COMBO_BOX (type), 0);
|
|
g_signal_connect (G_OBJECT (type),
|
|
"changed",
|
|
G_CALLBACK (cb_image_style_changed), state);
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
static void
|
|
cb_fill_type_changed (GtkWidget *menu, StylePrefState *state)
|
|
{
|
|
GtkWidget *w;
|
|
|
|
state->style->fill.type = gtk_combo_box_get_active (GTK_COMBO_BOX (menu));
|
|
set_style (state);
|
|
|
|
w = glade_xml_get_widget (state->gui, "fill_notebook");
|
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (w), state->style->fill.type);
|
|
}
|
|
|
|
static void
|
|
fill_init (StylePrefState *state, gboolean enable)
|
|
{
|
|
GtkWidget *w;
|
|
|
|
if (!enable) {
|
|
gtk_widget_hide (glade_xml_get_widget (state->gui, "fill_box"));
|
|
return;
|
|
}
|
|
|
|
fill_pattern_init (state);
|
|
fill_gradient_init (state);
|
|
fill_image_init (state);
|
|
|
|
w = glade_xml_get_widget (state->gui, "fill_notebook");
|
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (w), state->style->fill.type);
|
|
w = glade_xml_get_widget (state->gui, "fill_type_menu");
|
|
gtk_combo_box_set_active (GTK_COMBO_BOX (w), state->style->fill.type);
|
|
g_signal_connect (G_OBJECT (w),
|
|
"changed",
|
|
G_CALLBACK (cb_fill_type_changed), state);
|
|
|
|
w = glade_xml_get_widget (state->gui, "fill_box");
|
|
gtk_widget_show (GTK_WIDGET (w));
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
static void
|
|
cb_marker_shape_changed (GtkWidget *cc, int shape, StylePrefState const *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
gboolean is_auto = shape < 0;
|
|
|
|
if (is_auto)
|
|
shape = -shape;
|
|
go_marker_set_shape (style->marker.mark, shape);
|
|
style->marker.auto_shape = is_auto;
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
populate_marker_combo (StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
GtkWidget *combo, *table;
|
|
|
|
if (state->marker.combo != NULL)
|
|
gtk_widget_destroy (state->marker.combo);
|
|
|
|
state->marker.combo = combo = go_marker_selector (
|
|
go_marker_get_outline_color (style->marker.mark),
|
|
go_marker_get_fill_color (style->marker.mark),
|
|
go_marker_get_shape (state->default_style->marker.mark));
|
|
gtk_label_set_mnemonic_widget (
|
|
GTK_LABEL (glade_xml_get_widget (state->gui, "marker_shape_label")), combo);
|
|
|
|
table = glade_xml_get_widget (state->gui, "marker_table");
|
|
gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 0, 1, 0, 0, 0, 0);
|
|
go_combo_pixmaps_select_id (GO_COMBO_PIXMAPS (combo),
|
|
go_marker_get_shape (style->marker.mark));
|
|
g_signal_connect (G_OBJECT (combo),
|
|
"changed",
|
|
G_CALLBACK (cb_marker_shape_changed), state);
|
|
gtk_widget_show (combo);
|
|
}
|
|
|
|
static void
|
|
cb_marker_outline_color_changed (G_GNUC_UNUSED GOComboColor *cc, GOColor color,
|
|
G_GNUC_UNUSED gboolean is_custom,
|
|
G_GNUC_UNUSED gboolean by_user,
|
|
gboolean is_auto, StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
if (is_auto)
|
|
color = go_marker_get_outline_color (state->default_style->marker.mark);
|
|
go_marker_set_outline_color (style->marker.mark, color);
|
|
style->marker.auto_outline_color = is_auto;
|
|
set_style (state);
|
|
populate_marker_combo (state);
|
|
}
|
|
|
|
static void
|
|
cb_marker_fill_color_changed (G_GNUC_UNUSED GOComboColor *cc, GOColor color,
|
|
G_GNUC_UNUSED gboolean is_custom,
|
|
G_GNUC_UNUSED gboolean by_user,
|
|
gboolean is_auto, StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
if (is_auto)
|
|
color = go_marker_get_fill_color (state->default_style->marker.mark);
|
|
go_marker_set_fill_color (style->marker.mark, color);
|
|
style->marker.auto_fill_color = is_auto;
|
|
set_style (state);
|
|
populate_marker_combo (state);
|
|
}
|
|
|
|
static void
|
|
cb_marker_size_changed (GtkAdjustment *adj, StylePrefState *state)
|
|
{
|
|
go_marker_set_size (state->style->marker.mark, adj->value);
|
|
set_style (state);
|
|
}
|
|
|
|
static void
|
|
marker_init (StylePrefState *state, gboolean enable)
|
|
{
|
|
GogStyle *style = state->style;
|
|
GogStyle *default_style = state->default_style;
|
|
GtkWidget *table, *w;
|
|
|
|
if (!enable) {
|
|
gtk_widget_hide (glade_xml_get_widget (state->gui, "marker_box"));
|
|
return;
|
|
}
|
|
|
|
populate_marker_combo (state);
|
|
table = glade_xml_get_widget (state->gui, "marker_table");
|
|
|
|
w = create_go_combo_color (state,
|
|
go_marker_get_fill_color (style->marker.mark),
|
|
go_marker_get_fill_color (default_style->marker.mark),
|
|
"pattern_foreground", "marker_fill_label",
|
|
G_CALLBACK (cb_marker_fill_color_changed));
|
|
gtk_table_attach (GTK_TABLE (table), w, 1, 2, 1, 2, 0, 0, 0, 0);
|
|
|
|
w = create_go_combo_color (state,
|
|
go_marker_get_outline_color (style->marker.mark),
|
|
go_marker_get_outline_color (default_style->marker.mark),
|
|
"pattern_foreground", "marker_outline_label",
|
|
G_CALLBACK (cb_marker_outline_color_changed));
|
|
gtk_table_attach (GTK_TABLE (table), w, 1, 2, 2, 3, 0, 0, 0, 0);
|
|
|
|
w = glade_xml_get_widget (state->gui, "marker_size_spin");
|
|
gtk_spin_button_set_value (GTK_SPIN_BUTTON (w),
|
|
go_marker_get_size (style->marker.mark));
|
|
g_signal_connect (G_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (w))),
|
|
"value_changed",
|
|
G_CALLBACK (cb_marker_size_changed), state);
|
|
|
|
gtk_widget_show_all (table);
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
#if 0 //unused
|
|
static void
|
|
cb_font_changed (FontSelector *fs, G_GNUC_UNUSED gpointer mstyle,
|
|
StylePrefState *state)
|
|
{
|
|
GogStyle *style = state->style;
|
|
PangoFontDescription *new_font = pango_font_description_copy (style->font.font->desc);
|
|
|
|
// --jsled
|
|
//font_selector_get_pango (fs, new_font);
|
|
gog_style_set_font (style, new_font);
|
|
set_style (state);
|
|
}
|
|
#endif // 0 -- unused
|
|
|
|
static void
|
|
font_init (StylePrefState *state, guint32 enable, gpointer optional_notebook)
|
|
{
|
|
GogStyle *style = state->style;
|
|
GtkWidget *box;
|
|
|
|
if (!enable)
|
|
return;
|
|
|
|
g_return_if_fail (style->font.font != NULL);
|
|
g_return_if_fail (GTK_NOTEBOOK (optional_notebook) != NULL);
|
|
|
|
box = gtk_vbox_new (FALSE, 5);
|
|
gtk_container_set_border_width (GTK_CONTAINER (box), 12);
|
|
|
|
#if 0
|
|
w = gtk_check_button_new_with_label (_("Automatic"));
|
|
gtk_box_pack_start (GTK_BOX (box), w, FALSE, TRUE, 0);
|
|
#endif
|
|
gtk_widget_show_all (box);
|
|
|
|
/* --jsled
|
|
w = font_selector_new ();
|
|
font_selector_set_from_pango (FONT_SELECTOR (w), style->font.font->desc);
|
|
g_signal_connect (G_OBJECT (w),
|
|
"font_changed",
|
|
G_CALLBACK (cb_font_changed), state);
|
|
gtk_box_pack_end (GTK_BOX (box), w, TRUE, TRUE, 0);
|
|
gtk_widget_show (w);
|
|
*/
|
|
|
|
gtk_notebook_prepend_page (GTK_NOTEBOOK (optional_notebook), box,
|
|
gtk_label_new (_("Font")));
|
|
gtk_widget_show (GTK_WIDGET (optional_notebook));
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
static void
|
|
cb_parent_is_gone (StylePrefState *state, GObject *where_the_object_was)
|
|
{
|
|
state->style_changed_handler = 0;
|
|
state->object_with_style = NULL;
|
|
}
|
|
|
|
static void
|
|
gog_style_pref_state_free (StylePrefState *state)
|
|
{
|
|
if (state->style_changed_handler) {
|
|
g_signal_handler_disconnect (state->object_with_style,
|
|
state->style_changed_handler);
|
|
g_object_weak_unref (G_OBJECT (state->object_with_style),
|
|
(GWeakNotify) cb_parent_is_gone, state);
|
|
}
|
|
g_object_unref (state->style);
|
|
g_object_unref (state->default_style);
|
|
g_object_unref (state->gui);
|
|
if (state->fill.gradient.timer != 0) {
|
|
g_source_remove (state->fill.gradient.timer);
|
|
state->fill.gradient.timer = 0;
|
|
}
|
|
if (state->fill.image.image != NULL)
|
|
g_object_unref (state->fill.image.image);
|
|
g_free (state);
|
|
}
|
|
|
|
static gpointer
|
|
style_editor (GogStyle *style,
|
|
GogStyle *default_style,
|
|
GnmCmdContext *cc,
|
|
gpointer optional_notebook,
|
|
GObject *object_with_style,
|
|
gboolean watch_for_external_change)
|
|
{
|
|
GogStyleFlag enable;
|
|
GtkWidget *w;
|
|
GladeXML *gui;
|
|
StylePrefState *state;
|
|
|
|
g_return_val_if_fail (style != NULL, NULL);
|
|
g_return_val_if_fail (default_style != NULL, NULL);
|
|
|
|
enable = style->interesting_fields;
|
|
|
|
gui = gnm_glade_xml_new (cc, "gog-style-prefs.glade", "gog_style_prefs", NULL);
|
|
if (gui == NULL)
|
|
return NULL;
|
|
|
|
g_object_ref (style);
|
|
g_object_ref (default_style);
|
|
|
|
state = g_new0 (StylePrefState, 1);
|
|
state->gui = gui;
|
|
state->style = style;
|
|
state->default_style = default_style;
|
|
state->object_with_style = object_with_style;
|
|
state->enable_edit = FALSE;
|
|
|
|
outline_init (state, enable & GOG_STYLE_OUTLINE);
|
|
line_init (state, enable & GOG_STYLE_LINE);
|
|
fill_init (state, enable & GOG_STYLE_FILL);
|
|
marker_init (state, enable & GOG_STYLE_MARKER);
|
|
font_init (state, enable & GOG_STYLE_FONT, optional_notebook);
|
|
|
|
state->enable_edit = TRUE;
|
|
|
|
if (object_with_style != NULL && watch_for_external_change) {
|
|
state->style_changed_handler = g_signal_connect (G_OBJECT (object_with_style),
|
|
"style-changed",
|
|
G_CALLBACK (cb_style_changed), state);
|
|
g_object_weak_ref (G_OBJECT (object_with_style),
|
|
(GWeakNotify) cb_parent_is_gone, state);
|
|
}
|
|
|
|
w = glade_xml_get_widget (gui, "gog_style_prefs");
|
|
g_object_set_data_full (G_OBJECT (w),
|
|
"state", state, (GDestroyNotify) gog_style_pref_state_free);
|
|
|
|
if (optional_notebook != NULL) {
|
|
gtk_notebook_prepend_page (GTK_NOTEBOOK (optional_notebook), w,
|
|
gtk_label_new (_("Style")));
|
|
return GTK_WIDGET (optional_notebook);
|
|
}
|
|
return w;
|
|
}
|
|
|
|
gpointer
|
|
gog_style_editor (GogStyle *style,
|
|
GogStyle *default_style,
|
|
GnmCmdContext *cc,
|
|
gpointer optional_notebook,
|
|
GObject *object_with_style)
|
|
{
|
|
return style_editor (style, default_style, cc, optional_notebook,
|
|
object_with_style, FALSE);
|
|
}
|
|
|
|
gpointer
|
|
gog_styled_object_editor (GogStyledObject *gso, GnmCmdContext *cc, gpointer optional_notebook)
|
|
{
|
|
GogStyle *style = gog_style_dup (gog_styled_object_get_style (gso));
|
|
GogStyle *default_style = gog_styled_object_get_auto_style (gso);
|
|
gpointer editor = style_editor (style, default_style, cc,
|
|
optional_notebook, G_OBJECT (gso), TRUE);
|
|
g_object_unref (style);
|
|
g_object_unref (default_style);
|
|
|
|
return editor;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
GogStyle *
|
|
gog_style_new (void)
|
|
{
|
|
return g_object_new (GOG_STYLE_TYPE, NULL);
|
|
}
|
|
|
|
/**
|
|
* gog_style_dup :
|
|
* @src : #GogStyle
|
|
*
|
|
**/
|
|
GogStyle *
|
|
gog_style_dup (GogStyle const *src)
|
|
{
|
|
GogStyle *dst;
|
|
|
|
g_return_val_if_fail (GOG_STYLE (src) != NULL, NULL);
|
|
|
|
dst = gog_style_new ();
|
|
gog_style_assign (dst, src);
|
|
return dst;
|
|
}
|
|
|
|
void
|
|
gog_style_assign (GogStyle *dst, GogStyle const *src)
|
|
{
|
|
if (src == dst)
|
|
return;
|
|
|
|
g_return_if_fail (GOG_STYLE (src) != NULL);
|
|
g_return_if_fail (GOG_STYLE (dst) != NULL);
|
|
|
|
if (GOG_FILL_STYLE_IMAGE == src->fill.type &&
|
|
src->fill.image.image != NULL)
|
|
g_object_ref (src->fill.image.image);
|
|
if (GOG_FILL_STYLE_IMAGE == dst->fill.type) {
|
|
if (dst->fill.image.image != NULL)
|
|
g_object_unref (dst->fill.image.image);
|
|
g_free (dst->fill.image.filename);
|
|
}
|
|
|
|
if (src->font.font != NULL)
|
|
go_font_ref (src->font.font);
|
|
if (dst->font.font != NULL)
|
|
go_font_unref (dst->font.font);
|
|
|
|
dst->outline = src->outline;
|
|
dst->fill = src->fill;
|
|
dst->line = src->line;
|
|
if (dst->marker.mark)
|
|
g_object_unref (dst->marker.mark);
|
|
dst->marker = src->marker;
|
|
dst->marker.mark = go_marker_dup (src->marker.mark);
|
|
dst->font = src->font;
|
|
dst->line = src->line;
|
|
|
|
if (GOG_FILL_STYLE_IMAGE == dst->fill.type)
|
|
dst->fill.image.filename = g_strdup (dst->fill.image.filename);
|
|
|
|
dst->interesting_fields = src->interesting_fields;
|
|
dst->disable_theming = src->disable_theming;
|
|
}
|
|
|
|
/**
|
|
* gog_style_apply_theme :
|
|
* @dst : #GogStyle
|
|
* @src : #GogStyle
|
|
*
|
|
* Merge the attributes from @src onto the elements of @dst that were not user
|
|
* assigned (is_auto)
|
|
**/
|
|
void
|
|
gog_style_apply_theme (GogStyle *dst, GogStyle const *src)
|
|
{
|
|
if (src == dst)
|
|
return;
|
|
|
|
g_return_if_fail (GOG_STYLE (src) != NULL);
|
|
g_return_if_fail (GOG_STYLE (dst) != NULL);
|
|
|
|
if (dst->outline.auto_dash)
|
|
dst->outline.dash_type = src->outline.dash_type;
|
|
if (dst->outline.auto_color)
|
|
dst->outline.color = src->outline.color;
|
|
if (dst->fill.auto_fore)
|
|
dst->fill.pattern.fore = src->fill.pattern.fore;
|
|
if (dst->fill.auto_back)
|
|
dst->fill.pattern.back = src->fill.pattern.back;
|
|
if (dst->line.auto_dash)
|
|
dst->line.dash_type = src->line.dash_type;
|
|
if (dst->line.auto_color)
|
|
dst->line.color = src->line.color;
|
|
if (dst->marker.auto_shape)
|
|
go_marker_set_shape (dst->marker.mark,
|
|
go_marker_get_shape (src->marker.mark));
|
|
if (dst->marker.auto_outline_color)
|
|
go_marker_set_outline_color (dst->marker.mark,
|
|
go_marker_get_outline_color (src->marker.mark));
|
|
if (dst->marker.auto_fill_color)
|
|
go_marker_set_fill_color (dst->marker.mark,
|
|
go_marker_get_fill_color (src->marker.mark));
|
|
|
|
#if 0
|
|
/* Fonts are not themed until we have some sort of auto mechanism
|
|
* stronger than 'auto_size' */
|
|
if (src->font.font != NULL)
|
|
go_font_ref (src->font.font);
|
|
if (dst->font.font != NULL)
|
|
go_font_unref (dst->font.font);
|
|
dst->font = src->font;
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
gog_style_finalize (GObject *obj)
|
|
{
|
|
GogStyle *style = GOG_STYLE (obj);
|
|
|
|
if (GOG_FILL_STYLE_IMAGE == style->fill.type &&
|
|
style->fill.image.image != NULL)
|
|
g_object_unref (style->fill.image.image);
|
|
|
|
if (style->font.font != NULL) {
|
|
go_font_unref (style->font.font);
|
|
style->font.font = NULL;
|
|
}
|
|
|
|
if (style->marker.mark != NULL) {
|
|
g_object_unref (style->marker.mark);
|
|
style->marker.mark = NULL;
|
|
}
|
|
|
|
(parent_klass->finalize) (obj);
|
|
}
|
|
|
|
static void
|
|
gog_style_class_init (GogStyleClass *klass)
|
|
{
|
|
GObjectClass *gobject_klass = (GObjectClass *)klass;
|
|
parent_klass = g_type_class_peek_parent (klass);
|
|
gobject_klass->finalize = gog_style_finalize;
|
|
}
|
|
|
|
static void
|
|
gog_style_init (GogStyle *style)
|
|
{
|
|
style->interesting_fields = GOG_STYLE_ALL;
|
|
style->disable_theming = 0;
|
|
gog_style_force_auto (style);
|
|
style->line.dash_type = GO_LINE_SOLID;
|
|
style->outline.dash_type = GO_LINE_SOLID;
|
|
style->outline.width = 0;
|
|
style->fill.type = GOG_FILL_STYLE_PATTERN;
|
|
style->fill.gradient.brightness = -1.;
|
|
go_pattern_set_solid (&style->fill.pattern, RGBA_BLACK);
|
|
style->font.font = go_font_new_by_index (0);
|
|
style->font.color = RGBA_BLACK;
|
|
}
|
|
|
|
static struct {
|
|
GogFillStyle fstyle;
|
|
char const *name;
|
|
} fill_names[] = {
|
|
{ GOG_FILL_STYLE_NONE, "none" },
|
|
{ GOG_FILL_STYLE_PATTERN, "pattern" },
|
|
{ GOG_FILL_STYLE_GRADIENT, "gradient" },
|
|
{ GOG_FILL_STYLE_IMAGE, "image" }
|
|
};
|
|
|
|
static gboolean
|
|
bool_prop (xmlNode *node, char const *name, gboolean *res)
|
|
{
|
|
char *str = xmlGetProp (node, name);
|
|
if (str != NULL) {
|
|
*res = g_ascii_tolower (*str) == 't' ||
|
|
g_ascii_tolower (*str) == 'y' ||
|
|
strtol (str, NULL, 0);
|
|
xmlFree (str);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static GogFillStyle
|
|
str_as_fill_style (char const *name)
|
|
{
|
|
unsigned i;
|
|
for (i = 0; i < G_N_ELEMENTS (fill_names); i++)
|
|
if (strcmp (fill_names[i].name, name) == 0)
|
|
return fill_names[i].fstyle;
|
|
return GOG_FILL_STYLE_PATTERN;
|
|
}
|
|
|
|
static char const *
|
|
fill_style_as_str (GogFillStyle fstyle)
|
|
{
|
|
unsigned i;
|
|
for (i = 0; i < G_N_ELEMENTS (fill_names); i++)
|
|
if (fill_names[i].fstyle == fstyle)
|
|
return fill_names[i].name;
|
|
return "pattern";
|
|
}
|
|
|
|
static void
|
|
gog_style_line_load (xmlNode *node, GogStyleLine *line)
|
|
{
|
|
char *str;
|
|
gboolean tmp;
|
|
|
|
str = xmlGetProp (node, "dash");
|
|
if (str != NULL) {
|
|
line->dash_type = go_line_dash_from_str (str);
|
|
xmlFree (str);
|
|
}
|
|
if (bool_prop (node, "auto-dash", &tmp))
|
|
line->auto_dash = tmp;
|
|
str = xmlGetProp (node, "width");
|
|
if (str != NULL) {
|
|
line->width = g_strtod (str, NULL);
|
|
/* For compatibility with older graphs, when dash_type
|
|
* didn't exist */
|
|
if (line->width < 0.) {
|
|
line->width = 0.;
|
|
line->dash_type = GO_LINE_NONE;
|
|
}
|
|
xmlFree (str);
|
|
}
|
|
str = xmlGetProp (node, "color");
|
|
if (str != NULL) {
|
|
line->color = go_color_from_str (str);
|
|
xmlFree (str);
|
|
}
|
|
if (bool_prop (node, "auto-color", &tmp))
|
|
line->auto_color = tmp;
|
|
}
|
|
|
|
static void
|
|
gog_style_line_dom_save (xmlNode *parent, xmlChar const *name,
|
|
GogStyleLine const *line)
|
|
{
|
|
gchar *str;
|
|
xmlNode *node = xmlNewDocNode (parent->doc, NULL, name, NULL);
|
|
|
|
xmlSetProp (node, (xmlChar const *) "dash",
|
|
go_line_dash_as_str (line->dash_type));
|
|
xmlSetProp (node, (xmlChar const *) "auto-dash",
|
|
line->auto_dash ? "true" : "false");
|
|
str = g_strdup_printf ("%f", line->width);
|
|
xmlSetProp (node, (xmlChar const *) "width", str);
|
|
g_free (str);
|
|
str = go_color_as_str (line->color);
|
|
xmlSetProp (node, (xmlChar const *) "color", str);
|
|
g_free (str);
|
|
xmlSetProp (node, (xmlChar const *) "auto-color",
|
|
line->auto_color ? "true" : "false");
|
|
xmlAddChild (parent, node);
|
|
}
|
|
static void
|
|
gog_style_line_sax_save (GsfXMLOut *output, char const *name,
|
|
GogStyleLine const *line)
|
|
{
|
|
gsf_xml_out_start_element (output, name);
|
|
gsf_xml_out_add_cstr_unchecked (output, "dash",
|
|
go_line_dash_as_str (line->dash_type));
|
|
gsf_xml_out_add_bool (output, "auto-dash", line->auto_dash);
|
|
gsf_xml_out_add_float (output, "width", line->width, 1);
|
|
go_xml_out_add_color (output, "color", line->color);
|
|
gsf_xml_out_add_bool (output, "auto-color", line->auto_color);
|
|
gsf_xml_out_end_element (output);
|
|
}
|
|
|
|
static void
|
|
gog_style_gradient_sax_save (GsfXMLOut *output, GogStyle const *style)
|
|
{
|
|
gsf_xml_out_start_element (output, "gradient");
|
|
gsf_xml_out_add_cstr_unchecked (output, "direction",
|
|
go_gradient_dir_as_str (style->fill.gradient.dir));
|
|
go_xml_out_add_color (output, "start-color",
|
|
style->fill.pattern.back);
|
|
if (style->fill.gradient.brightness >= 0.)
|
|
gsf_xml_out_add_float (output, "brightness",
|
|
style->fill.gradient.brightness, 2);
|
|
else
|
|
go_xml_out_add_color (output, "end-color",
|
|
style->fill.pattern.fore);
|
|
gsf_xml_out_end_element (output);
|
|
}
|
|
|
|
static void
|
|
gog_style_fill_sax_save (GsfXMLOut *output, GogStyle const *style)
|
|
{
|
|
gsf_xml_out_start_element (output, "fill");
|
|
gsf_xml_out_add_cstr_unchecked (output, "type",
|
|
fill_style_as_str (style->fill.type));
|
|
gsf_xml_out_add_bool (output, "is-auto",
|
|
style->fill.auto_back);
|
|
gsf_xml_out_add_bool (output, "auto-fore",
|
|
style->fill.auto_fore);
|
|
|
|
switch (style->fill.type) {
|
|
case GOG_FILL_STYLE_NONE: break;
|
|
case GOG_FILL_STYLE_PATTERN:
|
|
gsf_xml_out_start_element (output, "pattern");
|
|
gsf_xml_out_add_cstr_unchecked (output, "type",
|
|
go_pattern_as_str (style->fill.pattern.pattern));
|
|
go_xml_out_add_color (output, "fore",
|
|
style->fill.pattern.fore);
|
|
go_xml_out_add_color (output, "back",
|
|
style->fill.pattern.back);
|
|
gsf_xml_out_end_element (output);
|
|
break;
|
|
|
|
case GOG_FILL_STYLE_GRADIENT:
|
|
gog_style_gradient_sax_save (output, style);
|
|
break;
|
|
case GOG_FILL_STYLE_IMAGE:
|
|
/* FIXME: TODO */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
gsf_xml_out_end_element (output);
|
|
}
|
|
|
|
static void
|
|
gog_style_gradient_load (xmlNode *node, GogStyle *style)
|
|
{
|
|
char *str = xmlGetProp (node, "direction");
|
|
if (str != NULL) {
|
|
style->fill.gradient.dir
|
|
= go_gradient_dir_from_str (str);
|
|
xmlFree (str);
|
|
}
|
|
str = xmlGetProp (node, "start-color");
|
|
if (str != NULL) {
|
|
style->fill.pattern.back
|
|
= go_color_from_str (str);
|
|
xmlFree (str);
|
|
}
|
|
str = xmlGetProp (node, "brightness");
|
|
if (str != NULL) {
|
|
gog_style_set_fill_brightness (style, g_strtod (str, NULL));
|
|
xmlFree (str);
|
|
} else {
|
|
str = xmlGetProp (node, "end-color");
|
|
if (str != NULL) {
|
|
style->fill.pattern.fore
|
|
= go_color_from_str (str);
|
|
xmlFree (str);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
gog_style_gradient_dom_save (xmlNode *parent, GogStyle const *style)
|
|
{
|
|
gchar *str;
|
|
xmlNode *node = xmlNewDocNode (parent->doc, NULL, "gradient", NULL);
|
|
|
|
xmlSetProp (node, (xmlChar const *) "direction",
|
|
go_gradient_dir_as_str (style->fill.gradient.dir));
|
|
str = go_color_as_str (style->fill.pattern.back);
|
|
xmlSetProp (node, (xmlChar const *) "start-color", str);
|
|
g_free (str);
|
|
if (style->fill.gradient.brightness >= 0.) {
|
|
str = g_strdup_printf ("%f",
|
|
style->fill.gradient.brightness);
|
|
xmlSetProp (node, (xmlChar const *) "brightness", str);
|
|
g_free (str);
|
|
} else {
|
|
str = go_color_as_str (style->fill.pattern.fore);
|
|
xmlSetProp (node, (xmlChar const *) "end-color", str);
|
|
g_free (str);
|
|
}
|
|
xmlAddChild (parent, node);
|
|
}
|
|
|
|
static void
|
|
gog_style_fill_load (xmlNode *node, GogStyle *style)
|
|
{
|
|
xmlNode *ptr;
|
|
gboolean tmp;
|
|
char *str = xmlGetProp (node, "type");
|
|
|
|
if (str == NULL)
|
|
return;
|
|
style->fill.type = str_as_fill_style (str);
|
|
xmlFree (str);
|
|
|
|
if (bool_prop (node, "is-auto", &tmp))
|
|
style->fill.auto_back = tmp;
|
|
if (bool_prop (node, "auto-fore", &tmp))
|
|
style->fill.auto_fore = tmp;
|
|
|
|
switch (style->fill.type) {
|
|
case GOG_FILL_STYLE_PATTERN:
|
|
for (ptr = node->xmlChildrenNode ;
|
|
ptr != NULL ; ptr = ptr->next) {
|
|
if (xmlIsBlankNode (ptr) || ptr->name == NULL)
|
|
continue;
|
|
if (strcmp (ptr->name, "pattern") == 0) {
|
|
str = xmlGetProp (ptr, "type");
|
|
if (str != NULL) {
|
|
style->fill.pattern.pattern
|
|
= go_pattern_from_str (str);
|
|
xmlFree (str);
|
|
}
|
|
str = xmlGetProp (ptr, "fore");
|
|
if (str != NULL) {
|
|
style->fill.pattern.fore
|
|
= go_color_from_str (str);
|
|
xmlFree (str);
|
|
}
|
|
str = xmlGetProp (ptr, "back");
|
|
if (str != NULL) {
|
|
style->fill.pattern.back
|
|
= go_color_from_str (str);
|
|
xmlFree (str);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case GOG_FILL_STYLE_GRADIENT:
|
|
for (ptr = node->xmlChildrenNode ;
|
|
ptr != NULL ; ptr = ptr->next) {
|
|
if (xmlIsBlankNode (ptr) || ptr->name == NULL)
|
|
continue;
|
|
if (strcmp (ptr->name, "gradient") == 0)
|
|
gog_style_gradient_load (ptr, style);
|
|
}
|
|
break;
|
|
case GOG_FILL_STYLE_IMAGE:
|
|
/* FIXME: TODO */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gog_style_fill_dom_save (xmlNode *parent, GogStyle const *style)
|
|
{
|
|
gchar *str;
|
|
xmlNode *node = xmlNewDocNode (parent->doc, NULL, "fill", NULL);
|
|
xmlNode *child;
|
|
xmlSetProp (node, (xmlChar const *) "type",
|
|
fill_style_as_str (style->fill.type));
|
|
xmlSetProp (node, (xmlChar const *) "is-auto",
|
|
style->fill.auto_back ? "true" : "false");
|
|
xmlSetProp (node, (xmlChar const *) "auto-fore",
|
|
style->fill.auto_fore ? "true" : "false");
|
|
switch (style->fill.type) {
|
|
case GOG_FILL_STYLE_NONE:
|
|
break;
|
|
case GOG_FILL_STYLE_PATTERN:
|
|
child = xmlNewDocNode (parent->doc, NULL, "pattern", NULL);
|
|
xmlSetProp (child, (xmlChar const *) "type",
|
|
go_pattern_as_str (style->fill.pattern.pattern));
|
|
str = go_color_as_str (style->fill.pattern.fore);
|
|
xmlSetProp (child, (xmlChar const *) "fore", str);
|
|
g_free (str);
|
|
str = go_color_as_str (style->fill.pattern.back);
|
|
xmlSetProp (child, (xmlChar const *) "back", str);
|
|
g_free (str);
|
|
xmlAddChild (node, child);
|
|
break;
|
|
case GOG_FILL_STYLE_GRADIENT:
|
|
gog_style_gradient_dom_save (node, style);
|
|
break;
|
|
case GOG_FILL_STYLE_IMAGE:
|
|
/* FIXME: TODO */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
xmlAddChild (parent, node);
|
|
}
|
|
|
|
static void
|
|
gog_style_marker_load (xmlNode *node, GogStyle *style)
|
|
{
|
|
char *str;
|
|
GOMarker *marker = go_marker_dup (style->marker.mark);
|
|
|
|
str = xmlGetProp (node, "shape");
|
|
if (str != NULL) {
|
|
style->marker.auto_shape = TRUE;
|
|
bool_prop (node, "auto-shape", &style->marker.auto_shape);
|
|
go_marker_set_shape (marker, go_marker_shape_from_str (str));
|
|
xmlFree (str);
|
|
}
|
|
str = xmlGetProp (node, "outline-color");
|
|
if (str != NULL) {
|
|
style->marker.auto_outline_color = TRUE;
|
|
bool_prop (node, "auto-outline", &style->marker.auto_outline_color);
|
|
go_marker_set_outline_color (marker, go_color_from_str (str));
|
|
xmlFree (str);
|
|
}
|
|
str = xmlGetProp (node, "fill-color");
|
|
if (str != NULL) {
|
|
style->marker.auto_fill_color = TRUE;
|
|
bool_prop (node, "auto-fill", &style->marker.auto_fill_color);
|
|
go_marker_set_fill_color (marker, go_color_from_str (str));
|
|
xmlFree (str);
|
|
}
|
|
str = xmlGetProp (node, "size");
|
|
if (str != NULL) {
|
|
go_marker_set_size (marker, g_strtod (str, NULL));
|
|
xmlFree (str);
|
|
}
|
|
gog_style_set_marker (style, marker);
|
|
}
|
|
|
|
static void
|
|
gog_style_marker_dom_save (xmlNode *parent, GogStyle const *style)
|
|
{
|
|
gchar *str;
|
|
xmlNode *node = xmlNewDocNode (parent->doc, NULL, "marker", NULL);
|
|
|
|
xmlSetProp (node, (xmlChar const *) "auto-shape",
|
|
style->marker.auto_shape ? "true" : "false");
|
|
xmlSetProp (node, (xmlChar const *) "shape",
|
|
go_marker_shape_as_str (go_marker_get_shape (style->marker.mark)));
|
|
|
|
xmlSetProp (node, (xmlChar const *) "auto-outline",
|
|
style->marker.auto_outline_color ? "true" : "false");
|
|
str = go_color_as_str (go_marker_get_outline_color (style->marker.mark));
|
|
xmlSetProp (node, (xmlChar const *) "outline-color", str);
|
|
g_free (str);
|
|
|
|
xmlSetProp (node, (xmlChar const *) "auto-fill",
|
|
style->marker.auto_fill_color ? "true" : "false");
|
|
str = go_color_as_str (go_marker_get_fill_color (style->marker.mark));
|
|
xmlSetProp (node, (xmlChar const *) "fill-color", str);
|
|
g_free (str);
|
|
|
|
str = g_strdup_printf ("%d", go_marker_get_size (style->marker.mark));
|
|
xmlSetProp (node, (xmlChar const *) "size", str);
|
|
g_free (str);
|
|
|
|
xmlAddChild (parent, node);
|
|
}
|
|
|
|
static void
|
|
gog_style_marker_sax_save (GsfXMLOut *output, GogStyle const *style)
|
|
{
|
|
gsf_xml_out_start_element (output, "marker");
|
|
gsf_xml_out_add_bool (output, "auto-shape", style->marker.auto_shape);
|
|
gsf_xml_out_add_cstr (output, "shape",
|
|
go_marker_shape_as_str (go_marker_get_shape (style->marker.mark)));
|
|
gsf_xml_out_add_bool (output, "auto-outline",
|
|
style->marker.auto_outline_color);
|
|
go_xml_out_add_color (output, "outline-color",
|
|
go_marker_get_outline_color (style->marker.mark));
|
|
gsf_xml_out_add_bool (output, "auto-fill", style->marker.auto_fill_color);
|
|
go_xml_out_add_color (output, "fill-color",
|
|
go_marker_get_fill_color (style->marker.mark));
|
|
gsf_xml_out_add_int (output, "size",
|
|
go_marker_get_size (style->marker.mark));
|
|
gsf_xml_out_end_element (output);
|
|
}
|
|
|
|
static void
|
|
gog_style_font_load (xmlNode *node, GogStyle *style)
|
|
{
|
|
char *str;
|
|
gboolean tmp;
|
|
|
|
str = xmlGetProp (node, "color");
|
|
if (str != NULL) {
|
|
style->font.color = go_color_from_str (str);
|
|
xmlFree (str);
|
|
}
|
|
str = xmlGetProp (node, "font");
|
|
if (str != NULL) {
|
|
PangoFontDescription *desc;
|
|
|
|
desc = pango_font_description_from_string (str);
|
|
if (desc != NULL)
|
|
gog_style_set_font (style, desc);
|
|
xmlFree (str);
|
|
}
|
|
if (bool_prop (node, "auto-scale", &tmp))
|
|
style->font.auto_scale = tmp;
|
|
}
|
|
|
|
static void
|
|
gog_style_font_dom_save (xmlNode *parent, GogStyle const *style)
|
|
{
|
|
gchar *str;
|
|
xmlNode *node = xmlNewDocNode (parent->doc, NULL, "font", NULL);
|
|
|
|
str = go_color_as_str (style->font.color);
|
|
xmlSetProp (node, (xmlChar const *) "color", str);
|
|
g_free (str);
|
|
str = go_font_as_str (style->font.font);
|
|
xmlSetProp (node, (xmlChar const *) "font", str);
|
|
g_free (str);
|
|
xmlSetProp (node, (xmlChar const *) "auto-scale",
|
|
style->font.auto_scale ? "true" : "false");
|
|
|
|
xmlAddChild (parent, node);
|
|
}
|
|
static void
|
|
gog_style_font_sax_save (GsfXMLOut *output, GogStyle const *style)
|
|
{
|
|
char *str;
|
|
gsf_xml_out_start_element (output, "font");
|
|
go_xml_out_add_color (output, "color", style->font.color);
|
|
str = go_font_as_str (style->font.font);
|
|
gsf_xml_out_add_cstr_unchecked (output, "font", str);
|
|
g_free (str);
|
|
gsf_xml_out_add_bool (output, "auto-scale", style->font.auto_scale);
|
|
gsf_xml_out_end_element (output);
|
|
}
|
|
|
|
static gboolean
|
|
gog_style_persist_dom_load (GogPersist *gp, xmlNode *node)
|
|
{
|
|
GogStyle *style = GOG_STYLE (gp);
|
|
xmlNode *ptr;
|
|
|
|
/* while reloading no need to reapply settings */
|
|
for (ptr = node->xmlChildrenNode ; ptr != NULL ; ptr = ptr->next) {
|
|
if (xmlIsBlankNode (ptr) || ptr->name == NULL)
|
|
continue;
|
|
if (strcmp (ptr->name, "outline") == 0)
|
|
gog_style_line_load (ptr, &style->outline);
|
|
else if (strcmp (ptr->name, "line") == 0)
|
|
gog_style_line_load (ptr, &style->line);
|
|
else if (strcmp (ptr->name, "fill") == 0)
|
|
gog_style_fill_load (ptr, style);
|
|
else if (strcmp (ptr->name, "marker") == 0)
|
|
gog_style_marker_load (ptr, style);
|
|
else if (strcmp (ptr->name, "font") == 0)
|
|
gog_style_font_load (ptr, style);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gog_style_persist_dom_save (GogPersist const *gp, xmlNode *parent)
|
|
{
|
|
GogStyle const *style = GOG_STYLE (gp);
|
|
|
|
xmlSetProp (parent, (xmlChar const *) "type",
|
|
G_OBJECT_TYPE_NAME (style));
|
|
|
|
if (style->interesting_fields & GOG_STYLE_OUTLINE)
|
|
gog_style_line_dom_save (parent, "outline", &style->outline);
|
|
if (style->interesting_fields & GOG_STYLE_LINE)
|
|
gog_style_line_dom_save (parent, "line", &style->line);
|
|
if (style->interesting_fields & GOG_STYLE_FILL)
|
|
gog_style_fill_dom_save (parent, style);
|
|
if (style->interesting_fields & GOG_STYLE_MARKER)
|
|
gog_style_marker_dom_save (parent, style);
|
|
if (style->interesting_fields & GOG_STYLE_FONT)
|
|
gog_style_font_dom_save (parent, style);
|
|
}
|
|
|
|
static void
|
|
gog_style_persist_sax_save (GogPersist const *gp, GsfXMLOut *output)
|
|
{
|
|
GogStyle const *style = GOG_STYLE (gp);
|
|
|
|
gsf_xml_out_add_cstr_unchecked (output, "type",
|
|
G_OBJECT_TYPE_NAME (style));
|
|
|
|
if (style->interesting_fields & GOG_STYLE_OUTLINE)
|
|
gog_style_line_sax_save (output, "outline", &style->outline);
|
|
if (style->interesting_fields & GOG_STYLE_LINE)
|
|
gog_style_line_sax_save (output, "line", &style->line);
|
|
if (style->interesting_fields & GOG_STYLE_FILL)
|
|
gog_style_fill_sax_save (output, style);
|
|
if (style->interesting_fields & GOG_STYLE_MARKER)
|
|
gog_style_marker_sax_save (output, style);
|
|
if (style->interesting_fields & GOG_STYLE_FONT)
|
|
gog_style_font_sax_save (output, style);
|
|
}
|
|
|
|
static void
|
|
gog_style_persist_init (GogPersistClass *iface)
|
|
{
|
|
iface->dom_load = gog_style_persist_dom_load;
|
|
iface->dom_save = gog_style_persist_dom_save;
|
|
iface->sax_save = gog_style_persist_sax_save;
|
|
}
|
|
|
|
GSF_CLASS_FULL (GogStyle, gog_style,
|
|
gog_style_class_init, gog_style_init,
|
|
G_TYPE_OBJECT, 0,
|
|
GSF_INTERFACE (gog_style_persist_init, GOG_PERSIST_TYPE))
|
|
|
|
gboolean
|
|
gog_style_is_different_size (GogStyle const *a, GogStyle const *b)
|
|
{
|
|
if (a == NULL || b == NULL)
|
|
return TRUE;
|
|
return a->outline.dash_type != b->outline.dash_type ||
|
|
a->outline.width != b->outline.width ||
|
|
a->line.width != b->line.width ||
|
|
a->fill.type != b->fill.type ||
|
|
!go_font_eq (a->font.font, b->font.font);
|
|
}
|
|
|
|
gboolean
|
|
gog_style_is_marker_visible (GogStyle const *style)
|
|
{
|
|
#ifdef GOG_WARN_TODO
|
|
#warning TODO : make this smarter
|
|
#endif
|
|
return (style->interesting_fields & GOG_STYLE_MARKER) &&
|
|
go_marker_get_shape (style->marker.mark) != GO_MARKER_NONE;
|
|
}
|
|
|
|
gboolean
|
|
gog_style_is_outline_visible (GogStyle const *style)
|
|
{
|
|
#ifdef GOG_WARN_TODO
|
|
#warning TODO : make this smarter
|
|
#endif
|
|
return UINT_RGBA_A (style->outline.color) > 0 &&
|
|
style->outline.dash_type != GO_LINE_NONE;
|
|
}
|
|
|
|
gboolean
|
|
gog_style_is_line_visible (GogStyle const *style)
|
|
{
|
|
#ifdef GOG_WARN_TODO
|
|
#warning TODO : make this smarter
|
|
#endif
|
|
|
|
return UINT_RGBA_A (style->line.color) > 0 &&
|
|
style->line.dash_type != GO_LINE_NONE;
|
|
}
|
|
|
|
void
|
|
gog_style_force_auto (GogStyle *style)
|
|
{
|
|
|
|
if (style->marker.mark != NULL)
|
|
g_object_unref (G_OBJECT (style->marker.mark));
|
|
style->marker.mark = go_marker_new ();
|
|
style->marker.auto_shape =
|
|
style->marker.auto_outline_color =
|
|
style->marker.auto_fill_color =
|
|
style->outline.auto_dash =
|
|
style->outline.auto_color =
|
|
style->line.auto_dash =
|
|
style->line.auto_color =
|
|
style->fill.auto_fore =
|
|
style->fill.auto_back =
|
|
style->font.auto_scale = TRUE;
|
|
}
|
|
|
|
/**
|
|
* gog_style_set_marker :
|
|
* @style : #GogStyle
|
|
* @marker : #GOMarker
|
|
*
|
|
* Absorb a reference to @marker and assign it to @style.
|
|
**/
|
|
void
|
|
gog_style_set_marker (GogStyle *style, GOMarker *marker)
|
|
{
|
|
g_return_if_fail (GOG_STYLE (style) != NULL);
|
|
g_return_if_fail (GO_MARKER (marker) != NULL);
|
|
|
|
if (style->marker.mark != marker) {
|
|
if (style->marker.mark != NULL)
|
|
g_object_unref (style->marker.mark);
|
|
style->marker.mark = marker;
|
|
}
|
|
}
|
|
|
|
void
|
|
gog_style_set_font (GogStyle *style, PangoFontDescription *desc)
|
|
{
|
|
GOFont const *font;
|
|
|
|
g_return_if_fail (GOG_STYLE (style) != NULL);
|
|
|
|
font = go_font_new_by_desc (desc);
|
|
if (font != NULL) {
|
|
go_font_unref (style->font.font);
|
|
style->font.font = font;
|
|
}
|
|
}
|
|
|
|
void
|
|
gog_style_set_fill_brightness (GogStyle *style, float brightness)
|
|
{
|
|
g_return_if_fail (GOG_STYLE (style) != NULL);
|
|
g_return_if_fail (style->fill.type == GOG_FILL_STYLE_GRADIENT);
|
|
|
|
style->fill.gradient.brightness = brightness;
|
|
style->fill.pattern.fore = (brightness < 50.)
|
|
? UINT_INTERPOLATE(style->fill.pattern.back, RGBA_WHITE, 1. - brightness / 50.)
|
|
: UINT_INTERPOLATE(style->fill.pattern.back, RGBA_BLACK, brightness / 50. - 1.);
|
|
}
|
|
|
|
/**
|
|
* gog_style_set_fill_image_filename :
|
|
* @style : #GogStyle
|
|
* @filename :
|
|
*
|
|
* absorb the string and eventually free it.
|
|
**/
|
|
void
|
|
gog_style_set_fill_image_filename (GogStyle *style, char *filename)
|
|
{
|
|
g_return_if_fail (GOG_STYLE (style) != NULL);
|
|
|
|
if (style->fill.type == GOG_FILL_STYLE_IMAGE) {
|
|
if (style->fill.image.image != NULL)
|
|
g_object_unref (style->fill.image.image);
|
|
g_free (style->fill.image.filename);
|
|
} else {
|
|
style->fill.type = GOG_FILL_STYLE_IMAGE;
|
|
style->fill.image.type = GOG_IMAGE_CENTERED;
|
|
}
|
|
|
|
style->fill.image.filename = filename;
|
|
style->fill.image.image = gdk_pixbuf_new_from_file (filename, NULL);
|
|
}
|
|
|
|
static void
|
|
cb_switch_page (G_GNUC_UNUSED GtkNotebook *n, G_GNUC_UNUSED GtkNotebookPage *p,
|
|
guint page_num, guint *store_page)
|
|
{
|
|
*store_page = page_num;
|
|
}
|
|
|
|
void
|
|
gog_style_handle_notebook (gpointer notebook, guint *page)
|
|
{
|
|
g_return_if_fail (GTK_NOTEBOOK (notebook) != NULL);
|
|
g_return_if_fail (page != NULL);
|
|
|
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), *page);
|
|
g_signal_connect (G_OBJECT (notebook),
|
|
"switch_page",
|
|
G_CALLBACK (cb_switch_page), page);
|
|
}
|