/* * dialog-cell-format.c: Implements the Cell Format dialog box. * * Author: * Miguel de Icaza (miguel@gnu.org) * */ #include #include #include "gnumeric.h" #include "gnumeric-util.h" #include "gnumeric-sheet.h" #include "dialogs.h" #include "format.h" #include "formats.h" #include "pattern-selector.h" /* The main dialog box */ static GtkWidget *cell_format_prop_win = 0; static int cell_format_last_page_used = 0; /* These point to the various widgets in the format/number page */ static GtkWidget *number_sample; static GtkWidget *number_input; static GtkWidget *number_cat_list; static GtkWidget *number_format_list; static GtkWidget *font_widget; /* These point to the radio groups in the format/alignment page */ static GSList *hradio_list; static GSList *vradio_list; static GtkWidget *auto_return; /* These point to the radio buttons of the coloring page */ static GSList *foreground_radio_list; static GSList *background_radio_list; static GtkWidget *foreground_cs; static GtkWidget *background_cs; /* Points to the first cell in the selection */ static Cell *first_cell; static void prop_modified (GtkWidget *widget, GnomePropertyBox *box) { gnome_property_box_changed (box); } static void make_radio_notify_change (GSList *list, GtkWidget *prop_win) { GSList *sl; for (sl = list; sl; sl = sl->next){ gtk_signal_connect (GTK_OBJECT (sl->data), "toggled", GTK_SIGNAL_FUNC (prop_modified), prop_win); } } static struct { char *name; char **formats; } cell_formats [] = { { N_("Numbers"), cell_format_numbers }, { N_("Accounting"), cell_format_accounting }, { N_("Date"), cell_format_date }, { N_("Time"), cell_format_hour }, { N_("Percent"), cell_format_percent }, { N_("Fraction"), cell_format_fraction }, { N_("Scientific"), cell_format_scientific }, { N_("Text"), cell_format_text }, { N_("Money"), cell_format_money }, { NULL, NULL } }; static void format_list_fill (int n) { GtkCList *cl = GTK_CLIST (number_format_list); char **texts; int i; g_return_if_fail (n >= 0); g_return_if_fail (cell_formats [n].name != NULL); texts = cell_formats [n].formats; gtk_clist_freeze (cl); gtk_clist_clear (cl); for (i = 0; texts [i]; i++){ gchar *t [1]; t [0] = _(texts [i]); gtk_clist_append (cl, t); } gtk_clist_thaw (cl); } /* * This routine is just used at startup to find the current * format that applies to this cell */ static int format_find (char *format) { int i, row; char **p; for (i = 0; cell_formats [i].name; i++){ p = cell_formats [i].formats; for (row = 0; *p; p++, row++){ if (strcmp (format, *p) == 0){ format_list_fill (i); gtk_clist_select_row (GTK_CLIST (number_format_list), row, 0); return 1; } } } return 0; } /* * Invoked when the user has selected a new format category */ static void format_number_select_row (GtkCList *clist, gint row, gint col, GdkEvent *event, GtkWidget *prop_win) { format_list_fill (row); gtk_clist_select_row (GTK_CLIST (number_format_list), 0, 0); gnome_property_box_changed (GNOME_PROPERTY_BOX (prop_win)); } static void render_formated_version (char *format) { if (!first_cell) gtk_label_set_text (GTK_LABEL (number_sample), ""); else { StyleFormat *style_format; Value *v = first_cell->value; char *str; style_format = style_format_new (format); str = format_value (style_format, v, NULL); gtk_label_set_text (GTK_LABEL (number_sample), str); g_free (str); style_format_unref (style_format); } } /* * Invoked when a specific format has been selected */ static void format_selected (GtkCList *clist, gint row, gint col, GdkEvent *event, GnomePropertyBox *prop_win) { char *format; gtk_clist_get_text (clist, row, col, &format); /* Set the input line to reflect the selected format */ gtk_entry_set_text (GTK_ENTRY (number_input), format); /* Notify gnome-property-box that a change has happened */ if (cell_format_prop_win) gnome_property_box_changed (prop_win); } /* * cells_get_format: * * Checks if all the cells in the list share the same format string */ static StyleFormat * cells_get_format (CellList *cells) { StyleFormat *last_format; for (last_format = NULL; cells; cells = cells->next){ Cell *cell = cells->data; if (!last_format){ last_format = cell->style->format; continue; } if (cell->style->format != last_format) return NULL; } return last_format; } /* * Creates the lists for the number display with our defaults */ static GtkWidget * my_clist_new (void) { GtkCList *cl; GdkFont *font; cl = GTK_CLIST (gtk_clist_new (1)); gtk_clist_column_titles_hide (cl); gtk_clist_set_selection_mode (cl,GTK_SELECTION_SINGLE); /* Configure the size */ font = GTK_WIDGET (cl)->style->font; gtk_widget_set_usize (GTK_WIDGET (cl), 0, 11 * (font->ascent + font->descent)); return GTK_WIDGET (cl); } static void format_code_changed (GtkEntry *entry, GnomePropertyBox *prop_win) { render_formated_version (gtk_entry_get_text (entry)); if (cell_format_prop_win) gnome_property_box_changed (prop_win); } /* * Creates the widget that represents the number format configuration page */ static GtkWidget * create_number_format_page (GtkWidget *prop_win, CellList *cells) { StyleFormat *format; GtkWidget *l, *scrolled_list; GtkTable *t, *tt; int i; enum { BOXES_LINE = 1, INPUT_LINE = 3, }; t = (GtkTable *) gtk_table_new (0, 0, 0); /* try to select the current format the user is using */ format = cells_get_format (cells); /* 1. Categories */ gtk_table_attach (t, l = gtk_label_new (_("Categories")), 0, 1, BOXES_LINE, BOXES_LINE+1, GTK_FILL | GTK_EXPAND, 0, 0, 0); gtk_misc_set_alignment (GTK_MISC (l), 0.0, 0.5); number_cat_list = my_clist_new (); scrolled_list = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_list), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add (GTK_CONTAINER (scrolled_list), number_cat_list); gtk_table_attach (t, scrolled_list, 0, 1, BOXES_LINE+1, BOXES_LINE+2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 4, 0); /* 1.1 Connect our signal handler */ gtk_signal_connect (GTK_OBJECT (number_cat_list), "select_row", GTK_SIGNAL_FUNC (format_number_select_row), prop_win); /* 1.2 Fill the category list */ gtk_clist_freeze (GTK_CLIST (number_cat_list)); for (i = 0; cell_formats [i].name; i++){ gchar *text [1]; text [0] = _(cell_formats [i].name); gtk_clist_append (GTK_CLIST (number_cat_list), text); } gtk_clist_thaw (GTK_CLIST (number_cat_list)); /* 2. Code input and sample display */ tt = GTK_TABLE (gtk_table_new (0, 0, 0)); /* 2.1 Input line */ gtk_table_attach (tt, gtk_label_new (_("Code:")), 0, 1, 0, 1, 0, 0, 2, 0); number_input = gtk_entry_new (); gtk_signal_connect (GTK_OBJECT (number_input), "changed", GTK_SIGNAL_FUNC (format_code_changed), prop_win); gtk_table_attach (tt, number_input, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 2); /* 2.2 Sample */ gtk_table_attach (tt, gtk_label_new (_("Sample:")), 0, 1, 1, 2, 0, 0, 2, 0); number_sample = gtk_label_new ("X"); gtk_misc_set_alignment (GTK_MISC (number_sample), 0.0, 0.5); gtk_table_attach (tt, number_sample, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, 0, 0, 2); gtk_table_attach (t, GTK_WIDGET (tt), 0, 2, INPUT_LINE, INPUT_LINE+1, GTK_FILL | GTK_EXPAND, 0, 0, 0); /* 3. Format codes */ number_format_list = my_clist_new (); scrolled_list = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (scrolled_list), number_format_list); gtk_table_attach (t, l = gtk_label_new (_("Format codes")), 1, 2, BOXES_LINE, BOXES_LINE+1, GTK_FILL | GTK_EXPAND, 0, 0, 0); gtk_misc_set_alignment (GTK_MISC (l), 0.0, 0.5); gtk_table_attach_defaults (t, scrolled_list, 1, 2, BOXES_LINE + 1, BOXES_LINE + 2); format_list_fill (0); /* 3.1 connect the signal handled for row selected */ gtk_signal_connect (GTK_OBJECT (number_format_list), "select_row", GTK_SIGNAL_FUNC (format_selected), prop_win); /* 3.2: Invoke the current style for the cell if possible */ if (format){ if (!format_find (format->format)) gtk_entry_set_text (GTK_ENTRY (number_input), format->format); } /* 4. finish */ gtk_widget_show_all (GTK_WIDGET (t)); return GTK_WIDGET (t); } static void apply_number_formats (Style *style, Sheet *sheet, CellList *list) { char *str = gtk_entry_get_text (GTK_ENTRY (number_input)); if (!strcmp (str, "")) return; for (;list; list = list->next){ Cell *cell = list->data; cell_set_format (cell, str); } style->valid_flags |= STYLE_FORMAT; style->format = style_format_new (str); } typedef struct { char *name; int flag; } align_def_t; static align_def_t horizontal_aligns [] = { { N_("General"), HALIGN_GENERAL }, { N_("Left"), HALIGN_LEFT }, { N_("Center"), HALIGN_CENTER }, { N_("Right"), HALIGN_RIGHT }, { N_("Fill"), HALIGN_FILL }, { N_("Justify"), HALIGN_JUSTIFY }, { NULL, 0 } }; static align_def_t vertical_aligns [] = { { N_("Top"), VALIGN_TOP }, { N_("Center"), VALIGN_CENTER }, { N_("Bottom"), VALIGN_BOTTOM }, { N_("Justify"), VALIGN_JUSTIFY }, { NULL, 0 } }; static void do_disable (GtkWidget *widget, GtkWidget *op) { int v; if (GTK_TOGGLE_BUTTON (widget)->active) v = FALSE; else v = TRUE; gtk_widget_set_sensitive (op, v); } static GtkWidget * make_radio_selection (GtkWidget *prop_win, char *title, align_def_t *array, GSList **dest_list, GtkWidget *disable) { GtkWidget *frame, *vbox; GSList *group; frame = gtk_frame_new (title); vbox = gtk_vbox_new (0, 0); gtk_container_add (GTK_CONTAINER (frame), vbox); for (group = NULL;array->name; array++){ GtkWidget *item; item = gtk_radio_button_new_with_label (group, _(array->name)); group = gtk_radio_button_group (GTK_RADIO_BUTTON (item)); gtk_box_pack_start_defaults (GTK_BOX (vbox), item); if (disable && strcmp (array->name, "Fill") == 0){ gtk_signal_connect (GTK_OBJECT (item), "toggled", GTK_SIGNAL_FUNC (do_disable), disable); } } *dest_list = group; return frame; } static GtkWidget * create_align_page (GtkWidget *prop_win, CellList *cells) { GtkTable *t; GtkWidget *w; int ha, va, autor, ok = 0; GList *l; t = (GtkTable *) gtk_table_new (0, 0, 0); /* Vertical alignment */ w = make_radio_selection (prop_win, _("Vertical"), vertical_aligns, &vradio_list, NULL); gtk_table_attach (t, w, 1, 2, 0, 1, 0, GTK_FILL, 4, 0); /* Horizontal alignment */ w = make_radio_selection (prop_win, _("Horizontal"), horizontal_aligns, &hradio_list, w); gtk_table_attach (t, w, 0, 1, 0, 2, 0, GTK_FILL, 4, 0); auto_return = gtk_check_button_new_with_label (_("Auto return")); gtk_table_attach (t, auto_return, 0, 3, 2, 3, 0, 0, 0, 0); gtk_signal_connect (GTK_OBJECT (auto_return), "toggled", GTK_SIGNAL_FUNC (prop_modified), prop_win); /* Check if all cells have the same properties */ /* * FIXME: This should check the cells *AND* the * style regions to figure out what to check and what * not, right now this is broken in that regard */ if (cells){ ha = ((Cell *) (cells->data))->style->halign; va = ((Cell *) (cells->data))->style->valign; autor = ((Cell *) (cells->data))->style->fit_in_cell; for (ok = 1, l = cells; l; l = l->next){ Cell *cell = l->data; if (cell->style->halign != ha || cell->style->valign != va || cell->style->fit_in_cell != autor){ ok = 0; break; } } /* If all the cells share the same alignment, select that on the radio boxes */ if (ok){ int n; for (n = 0; horizontal_aligns [n].name; n++) if (horizontal_aligns [n].flag == ha){ gtk_radio_button_select (hradio_list, n); break; } for (n = 0; vertical_aligns [n].name; n++) if (vertical_aligns [n].flag == va){ gtk_radio_button_select (vradio_list, n); break; } if (autor) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (auto_return), 1); } } /* Now after we *potentially* toggled the radio button above, we * connect the signals to activate the propertybox */ make_radio_notify_change (hradio_list, prop_win); make_radio_notify_change (vradio_list, prop_win); gtk_widget_show_all (GTK_WIDGET (t)); return GTK_WIDGET (t); } static void apply_align_format (Style *style, Sheet *sheet, CellList *cells) { int i; int halign, valign, autor; i = gtk_radio_group_get_selected (hradio_list); halign = horizontal_aligns [i].flag; i = gtk_radio_group_get_selected (vradio_list); valign = vertical_aligns [i].flag; autor = GTK_TOGGLE_BUTTON (auto_return)->active; for (; cells; cells = cells->next){ Cell *cell = cells->data; cell_set_alignment (cell, halign, valign, ORIENT_HORIZ, autor); } style->halign = halign; style->valign = valign; style->orientation = ORIENT_HORIZ; style->fit_in_cell = autor; style->valid_flags |= STYLE_ALIGN; } static void font_changed (GtkWidget *widget, GtkStyle *previous_style, GnomePropertyBox *prop_win) { gnome_property_box_changed (prop_win); } static GtkWidget * create_font_page (GtkWidget *prop_win, CellList *cells) { font_widget = gtk_font_selection_new (); gtk_widget_show (font_widget); gtk_signal_connect (GTK_OBJECT (GTK_FONT_SELECTION (font_widget)->preview_entry), "style_set", GTK_SIGNAL_FUNC (font_changed), prop_win); return font_widget; } static void apply_font_format (Style *style, Sheet *sheet, CellList *cells) { GtkFontSelection *font_sel = GTK_FONT_SELECTION (font_widget); GdkFont *gdk_font; GList *l; char *font_name; int height; font_name = gtk_font_selection_get_font_name (font_sel); if (!font_name) return; gdk_font = gtk_font_selection_get_font (font_sel); height = gdk_font->ascent + gdk_font->descent; /* Apply the new font to all of the cell rows */ for (; cells; cells = cells->next){ Cell *cell = cells->data; cell_set_font (cell, font_name); } /* Now apply it to every row in the selection */ for (l = sheet->selections; l; l = l->next){ SheetSelection *ss = l->data; GList *rl; /* Special case, the whole spreadsheet */ if (ss->start_row == 0 && ss->end_row == SHEET_MAX_ROWS-1) sheet_row_set_internal_height (sheet, &sheet->default_row_style, height); for (rl = sheet->rows_info; rl; rl = rl->next){ ColRowInfo *ri = rl->data; if (ri->pos < ss->start_row) break; if (ri->pos > ss->end_row) break; sheet_row_set_internal_height (sheet, ri, height); } } style->valid_flags |= STYLE_FONT; style->font = style_font_new (font_name, 10); } static void color_pick_change_notify (GnomeColorPicker *cp, guint r, guint g, guint b, guint a, GnomePropertyBox *pbox) { gnome_property_box_changed (pbox); } static void make_color_picker_notify (GtkWidget *widget, GtkWidget *prop_win) { gtk_signal_connect (GTK_OBJECT (widget), "color_set", GTK_SIGNAL_FUNC (color_pick_change_notify), prop_win); } static GtkWidget * create_foreground_radio (GtkWidget *prop_win) { GtkWidget *frame, *table, *r1, *r2, *r3; int e = GTK_FILL | GTK_EXPAND; frame = gtk_frame_new (_("Text color")); table = gtk_table_new (2, 2, 0); gtk_container_add (GTK_CONTAINER (frame), table); r1 = gtk_radio_button_new_with_label (NULL, _("None")); r2 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON (r1), _("Use this color")); r3 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON (r1), _("No change")); foreground_radio_list = GTK_RADIO_BUTTON (r3)->group; foreground_cs = gnome_color_picker_new (); make_color_picker_notify (foreground_cs, prop_win); gtk_table_attach (GTK_TABLE (table), r1, 0, 1, 0, 1, e, 0, 4, 2); gtk_table_attach (GTK_TABLE (table), r2, 0, 1, 1, 2, e, 0, 4, 2); gtk_table_attach (GTK_TABLE (table), r3, 0, 1, 2, 3, e, 0, 4, 2); gtk_table_attach (GTK_TABLE (table), foreground_cs, 1, 2, 1, 2, 0, 0, 0, 0); return frame; } static GtkWidget * create_background_radio (GtkWidget *prop_win) { GtkWidget *frame, *table, *r1, *r2, *r3, *r4, *p; int e = GTK_FILL | GTK_EXPAND; frame = gtk_frame_new (_("Background configuration")); table = gtk_table_new (2, 2, 0); gtk_container_add (GTK_CONTAINER (frame), table); gtk_container_set_border_width (GTK_CONTAINER (frame), 5); /* The radio buttons */ r1 = gtk_radio_button_new_with_label (NULL, _("None")); r2 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON (r1), _("Use solid color")); r3 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON (r1), _("Use a pattern")); r4 = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON (r1), _("No change")); background_radio_list = GTK_RADIO_BUTTON (r4)->group; /* The color selectors */ background_cs = gnome_color_picker_new (); make_color_picker_notify (background_cs, prop_win); /* Create the pattern preview */ p = pattern_selector_new (0); gtk_table_attach (GTK_TABLE (table), r1, 0, 1, 0, 1, e, 0, 4, 2); gtk_table_attach (GTK_TABLE (table), r2, 0, 1, 1, 2, e, 0, 4, 2); gtk_table_attach (GTK_TABLE (table), r3, 0, 1, 2, 3, e, 0, 4, 2); gtk_table_attach (GTK_TABLE (table), r4, 0, 1, 4, 5, e, 0, 4, 2); gtk_table_attach (GTK_TABLE (table), background_cs, 1, 2, 1, 2, 0, 0, 4, 2); gtk_table_attach (GTK_TABLE (table), p, 0, 2, 3, 4, GTK_FILL | GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0); return frame; } static GtkWidget * create_coloring_page (GtkWidget *prop_win, CellList *cells) { GtkTable *t; GtkWidget *fore, *back; int e = GTK_FILL | GTK_EXPAND; gdouble rd, gd, bd, ad; gushort fore_red, fore_green, fore_blue; gushort back_red, back_green, back_blue; GList *l; int ok_fore, ok_back, foreground_flag, background_flag; t = (GtkTable *) gtk_table_new (0, 0, 0); fore = create_foreground_radio (prop_win); back = create_background_radio (prop_win); /* Check if all cells have the same properties */ /* * FIXME: This should check the cells *AND* the * style regions to figure out what to check and what * not, right now this is broken in that regard */ if (cells){ Cell *cell = (Cell *) cells->data; fore_red = cell->style->fore_color->color.red; fore_green = cell->style->fore_color->color.green; fore_blue = cell->style->fore_color->color.blue; back_red = cell->style->back_color->color.red; back_green = cell->style->back_color->color.green; back_blue = cell->style->back_color->color.blue; /* * What follows is ugly: I believe we should use the method illustrated * in the following two lines: * foreground_flag = (((Cell *) (cells->data))->style->valid_flags & STYLE_FORE_COLOR); * background_flag = (((Cell *) (cells->data))->style->valid_flags & STYLE_BACK_COLOR); * instead of what we are using, but it just does not work (even though the * flag is being set/cleared cell by cell and style-wise in function apply_coloring_format) */ if (fore_red == 0 && fore_green == 0 && fore_blue == 0){ foreground_flag = 0; } else { foreground_flag = STYLE_FORE_COLOR; } if (back_red == 0xffff && back_green == 0xffff && back_blue == 0xffff){ background_flag = 0; } else { background_flag = STYLE_BACK_COLOR; } /* * First scan is to find out whether all cells have the same foreground color, * second one is the equivalent for background */ for (ok_fore = 1, l = cells; l; l = l->next){ Cell *cell = l->data; if (cell->style->fore_color->color.red != fore_red || cell->style->fore_color->color.green != fore_green || cell->style->fore_color->color.blue != fore_blue){ ok_fore = 0; break; } } for (ok_back = 1, l = cells; l; l = l->next){ Cell *cell = l->data; if (cell->style->back_color->color.red != back_red || cell->style->back_color->color.green != back_green || cell->style->back_color->color.blue != back_blue){ ok_back = 0; break; } } if (ok_fore != 0){ if (foreground_flag == 0){ gtk_radio_button_select (foreground_radio_list, 0); gnome_color_picker_set_d (GNOME_COLOR_PICKER (foreground_cs), 0, 0, 0, 0); } else { rd = (gdouble) fore_red / 65535; gd = (gdouble) fore_green / 65535; bd = (gdouble) fore_blue / 65535; ad = 1; gtk_radio_button_select (foreground_radio_list, 1); gnome_color_picker_set_d (GNOME_COLOR_PICKER (foreground_cs), rd, gd, bd, ad); } } else { gtk_radio_button_select (foreground_radio_list, 2); } if (ok_back != 0){ if (background_flag == 0){ gtk_radio_button_select (background_radio_list, 0); gnome_color_picker_set_d (GNOME_COLOR_PICKER (background_cs), 1, 1, 1, 1); } else { rd = (gdouble) back_red / 65535; gd = (gdouble) back_green / 65535; bd = (gdouble) back_blue / 65535; ad = 1; gtk_radio_button_select (background_radio_list, 1); gnome_color_picker_set_d (GNOME_COLOR_PICKER (background_cs), rd, gd, bd, ad); } } else { gtk_radio_button_select (background_radio_list, 3); } } make_radio_notify_change (foreground_radio_list, prop_win); make_radio_notify_change (background_radio_list, prop_win); gtk_table_attach (t, fore, 0, 1, 0, 1, e, 0, 4, 4); gtk_table_attach (t, back, 0, 1, 1, 2, e, 0, 4, 4); gtk_widget_show_all (GTK_WIDGET (t)); return GTK_WIDGET (t); } static void apply_coloring_format (Style *style, Sheet *sheet, CellList *cells) { double rd, gd, bd, ad; gushort fore_change, back_change; gushort fore_red=0, fore_green=0, fore_blue=0; gushort back_red=0xff, back_green=0xff, back_blue=0xff; CellList *cl; Cell *cell; /* * Let's check the foreground first */ switch (gtk_radio_group_get_selected (foreground_radio_list)) { /* * case 0 means no foreground */ case 0: fore_red = 0; fore_green = 0; fore_blue = 0; style->valid_flags &= ~STYLE_FORE_COLOR; fore_change = TRUE; break; /* * case 1 means colored foreground */ case 1: gnome_color_picker_get_d (GNOME_COLOR_PICKER (foreground_cs), &rd, &gd, &bd, &ad); fore_red = rd * 65535; fore_green = gd * 65535; fore_blue = bd * 65535; style->valid_flags |= STYLE_FORE_COLOR; fore_change = TRUE; break; /* * case 2 means no change */ case 2: fore_change = FALSE; break; } /* * Now, the background * FIXME: What is going on with the cell patterns? */ switch (gtk_radio_group_get_selected (background_radio_list)) { /* * case 0 means no background */ case 0: back_red = 0xffff; back_green = 0xffff; back_blue = 0xffff; style->valid_flags &= ~STYLE_BACK_COLOR; style->valid_flags &= ~STYLE_PATTERN; back_change = TRUE; break; /* * case 1 means solid color background */ case 1: gnome_color_picker_get_d (GNOME_COLOR_PICKER (background_cs), &rd, &gd, &bd, &ad); back_red = rd * 65535; back_green = gd * 65535; back_blue = bd * 65535; style->valid_flags |= STYLE_BACK_COLOR; style->valid_flags &= ~STYLE_PATTERN; back_change = TRUE; break; /* * case 2 means a pattern background */ case 2: back_red = 0xffff; back_green = 0xffff; back_blue = 0xffff; style->valid_flags &= ~STYLE_BACK_COLOR; style->valid_flags |= STYLE_PATTERN; back_change = TRUE; break; /* * case 3 means no change */ case 3: back_change = FALSE; break; } /* Apply the color to the cells */ for (; cells; cells = cells->next){ cell = cells->data; if (fore_change==TRUE) { cell_set_foreground ( cell, fore_red, fore_green, fore_blue); } if (back_change==TRUE) { cell_set_background (cell, back_red, back_green, back_blue); /* cell_set_pattern (cell, 2); */ } } if (fore_change==TRUE) { style->fore_color = style_color_new (fore_red, fore_green, fore_blue); } if (back_change==TRUE) { style->back_color = style_color_new (back_red, back_green, back_blue); } } static struct { char *title; GtkWidget *(*create_page)(GtkWidget *prop_win, CellList *cells); void (*apply_page)(Style *style, Sheet *sheet, CellList *cells); } cell_format_pages [] = { { N_("Number"), create_number_format_page, apply_number_formats }, { N_("Alignment"), create_align_page, apply_align_format }, { N_("Font"), create_font_page, apply_font_format }, { N_("Coloring"), create_coloring_page, apply_coloring_format }, { NULL, NULL, NULL } }; static void cell_properties_apply (GtkObject *w, int page, CellList *cells) { Sheet *sheet; Style *style; GList *l; int i; if (page != -1) return; sheet = (Sheet *) gtk_object_get_data (w, "Sheet"); /* Now, let each property page apply their style */ style = style_new_empty (); style->valid_flags = 0; for (l = cells; l; l = l->next){ Cell *cell = l->data; cell_queue_redraw (cell); } cell_freeze_redraws (); for (i = 0; cell_format_pages [i].title; i++) (*cell_format_pages [i].apply_page)(style, sheet, cells); cell_thaw_redraws (); /* Attach this style to all of the selections */ for (l = sheet->selections; l; l = l->next){ SheetSelection *ss = l->data; sheet_style_attach ( sheet, ss->start_col, ss->start_row, ss->end_col, ss->end_row, style); } } static void cell_properties_close (void) { GnomePropertyBox *pbox = GNOME_PROPERTY_BOX (cell_format_prop_win); gtk_main_quit (); cell_format_last_page_used = gtk_notebook_get_current_page ( GTK_NOTEBOOK (pbox->notebook)); gtk_widget_destroy (cell_format_prop_win); cell_format_prop_win = 0; } /* * Main entry point for the Cell Format dialog box */ void dialog_cell_format (Workbook *wb, Sheet *sheet) { static GnomeHelpMenuEntry help_ref = { "gnumeric", "formatting.html" }; GtkWidget *prop_win; CellList *cells; int i; g_return_if_fail (sheet != NULL); g_return_if_fail (IS_SHEET (sheet)); g_assert (cell_format_prop_win == NULL); cells = sheet_selection_to_list (sheet); prop_win = gnome_property_box_new (); gnome_dialog_set_parent (GNOME_DIALOG (prop_win), GTK_WINDOW (wb->toplevel)); if (cells) first_cell = cells->data; else first_cell = NULL; for (i = 0; cell_format_pages [i].title; i++){ GtkWidget *page; page = (*cell_format_pages [i].create_page)(prop_win, cells); gnome_property_box_append_page ( GNOME_PROPERTY_BOX (prop_win), page, gtk_label_new (_(cell_format_pages [i].title))); } gtk_signal_connect (GTK_OBJECT (prop_win), "apply", GTK_SIGNAL_FUNC (cell_properties_apply), cells); gtk_signal_connect (GTK_OBJECT (prop_win), "help", GTK_SIGNAL_FUNC (gnome_help_pbox_goto), &help_ref); gtk_object_set_data (GTK_OBJECT (prop_win), "Sheet", sheet); gtk_signal_connect (GTK_OBJECT (prop_win), "destroy", GTK_SIGNAL_FUNC (cell_properties_close), NULL); gtk_notebook_set_page ( GTK_NOTEBOOK (GNOME_PROPERTY_BOX(prop_win)->notebook), cell_format_last_page_used); gtk_widget_show (prop_win); gtk_grab_add (prop_win); cell_format_prop_win = prop_win; gtk_main (); cell_format_prop_win = NULL; g_list_free (cells); }