dialog-autoformat.c 22.6 KB
Newer Older
1
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 3 4
/*
 * dialog-autoformat.c : implementation of the autoformat dialog
 *
5
 * Author : Almer S. Tigelaar <almer@gnome.org>
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
23 24
 * WORKING NOTE : Once the edit dialog is ready, search for FIXME and
 * remove the disabling of new/edit/remove buttons!
25
 */
26

27
#include <gnumeric-config.h>
28
#include <glib/gi18n-lib.h>
29 30
#include <gnumeric.h>
#include "dialogs.h"
31
#include "help.h"
32 33 34 35 36

#include <gui-util.h>
#include <mstyle.h>
#include <style-border.h>
#include <value.h>
37
#include <preview-grid-impl.h>
38 39
#include <format-template.h>
#include <file-autoft.h>
Jody Goldberg's avatar
Jody Goldberg committed
40
#include <command-context.h>
41 42
#include <workbook-control.h>
#include <workbook.h>
43
#include <wbc-gtk.h>
44 45
#include <commands.h>
#include <selection.h>
46
#include <ranges.h>
47

48
#include <goffice/goffice.h>
49
#include <gtk/gtk.h>
Jody Goldberg's avatar
Jody Goldberg committed
50
#include <gsf/gsf-impl-utils.h>
51
#include <string.h>
52

53
/* Table to show for
54 55 56
 * previews, please don't make this larger than 5x5
 */
#define PREVIEW_COLS 5
57
#define PREVIEW_ROWS 5
58
#define NUM_PREVIEWS 6
59 60 61 62 63 64
#define DEFAULT_COL_WIDTH  52
#define DEFAULT_ROW_HEIGHT 17
#define BORDER	     7
#define INNER_BORDER 5
#define TOTAL_WIDTH  (DEFAULT_COL_WIDTH * PREVIEW_COLS)
#define TOTAL_HEIGHT (DEFAULT_ROW_HEIGHT * PREVIEW_ROWS)
65

66 67 68
/* Keep these strings very short.
   They are used as a sample data for a sheet, so you can put anything here
   ("One", "Two", "Three" for example) */
69
static char const *const
70
demotable[PREVIEW_ROWS][PREVIEW_COLS] = {
71
	{ N_(" ")    , N_("Jan"), N_("Feb"), N_("Mar"), N_("Total") },
72 73 74 75
	{ N_("North"),   N_("6"),  N_("13"),  N_("20"),    N_("39") },
	{ N_("South"),  N_("12"),   N_("4"),  N_("17"),    N_("33") },
	{ N_("West") ,   N_("8"),   N_("2"),   N_("0"),    N_("10") },
	{ N_("Total"),  N_("26"),  N_("19"),  N_("37"),    N_("81") }
76 77 78
};

typedef struct {
79
	Workbook           *wb;                              /* Workbook we are working on */
80
	WBCGtk *wbcg;
81 82
	GocItem		   *grid[NUM_PREVIEWS];              /* Previewgrid's */
	GocItem		   *selrect;                         /* Selection rectangle */
83
	GSList             *templates;                       /* List of GnmFormatTemplate's */
84
	GnmFormatTemplate  *selected_template;               /* The currently selected template */
85
	GList              *category_groups;                 /* List of groups of categories */
86

87
	FormatTemplateCategoryGroup *current_category_group; /* Currently selected category group */
88

89 90 91 92
	int               preview_top;       /* Top index of the previewlist */
	int               preview_index;     /* Selected canvas in previewlist */
	gboolean          previews_locked;   /* If true, the preview_free and preview_load will not function */
	gboolean          more_down;         /* If true, more was clicked and the button caption is now 'Less' */
93 94 95 96

	/*
	 * Gui elements
	 */
Jody Goldberg's avatar
Jody Goldberg committed
97
	GtkDialog      *dialog;
98

99
	GtkComboBox    *category;
100

101
	GocCanvas	 *canvas[NUM_PREVIEWS];
102
	GtkFrame         *frame[NUM_PREVIEWS];
103
	GtkScrollbar    *scroll;
104
	GtkCheckMenuItem *gridlines;
105

106
	GtkEntry       *info_name, *info_author, *info_cat;
Jody Goldberg's avatar
Jody Goldberg committed
107
	GtkTextView    *info_descr;
108

109
	GtkCheckMenuItem *number, *border, *font, *patterns, *alignment;
Morten Welinder's avatar
Morten Welinder committed
110

111 112 113 114 115 116
	struct {
		GtkCheckMenuItem *left;
		GtkCheckMenuItem *right;
		GtkCheckMenuItem *top;
		GtkCheckMenuItem *bottom;
	} edges;
Morten Welinder's avatar
Morten Welinder committed
117

118
	GtkButton      *ok, *cancel;
119
} AutoFormatState;
120

121 122 123 124
/********************************************************************************/

typedef struct {
	PreviewGrid base;
125
	GnmFormatTemplate *ft;
126 127
} AutoFormatGrid;
typedef PreviewGridClass AutoFormatGridClass;
128

Morten Welinder's avatar
Morten Welinder committed
129
static GnmStyle *
130
afg_get_cell_style (PreviewGrid *pg, int col, int row)
131
{
132 133 134 135
	/* If this happens to be NULL the default style
	 * will automatically be used. */
	AutoFormatGrid *ag = (AutoFormatGrid *) pg;
	return format_template_get_style (ag->ft, row, col);
136 137
}

Jody Goldberg's avatar
Jody Goldberg committed
138
static GnmValue *
139
afg_get_cell_value (G_GNUC_UNUSED PreviewGrid *pg, int col, int row)
140
{
141 142 143
	char const *text;
	char *endptr = NULL;
	double tmp;
144

145 146
	if (row >= PREVIEW_ROWS || col >= PREVIEW_COLS)
		return NULL;
147

148
	text = _(demotable[row][col]);
149
	tmp = go_strtod (text, &endptr);
150

151
	if (*endptr == '\0')
152
		return value_new_float (tmp);
153
	return value_new_string (text);
154 155
}

156 157 158 159 160 161 162 163 164 165 166
static void
auto_format_grid_class_init (PreviewGridClass *klass)
{
	klass->get_cell_style = afg_get_cell_style;
	klass->get_cell_value = afg_get_cell_value;
}

static GSF_CLASS (AutoFormatGrid, auto_format_grid,
		  auto_format_grid_class_init, NULL,
		  preview_grid_get_type())

167
static GocItem *
168
auto_format_grid_new (AutoFormatState *state, int i, GnmFormatTemplate *ft)
169
{
170 171
	GocItem *item = goc_item_new (
		goc_canvas_get_root (state->canvas[i]),
172
		auto_format_grid_get_type (),
173
		"render-gridlines",	gtk_check_menu_item_get_active (state->gridlines),
174 175 176 177 178 179 180 181
		"default-col-width",	DEFAULT_COL_WIDTH,
		"default-row-height",	DEFAULT_ROW_HEIGHT,
		"x",			0.,
		"y",			0.,
		NULL);
	((AutoFormatGrid *) item)->ft = ft;
	return item;
}
182 183 184 185 186
/********************************************************************************
 * UTILITY FUNCTIONS
 ********************************************************************************/

static void
187
templates_free (AutoFormatState *state)
188
{
189
	GSList *ptr;
190

191
	g_return_if_fail (state != NULL);
192

193 194 195 196
	for (ptr = state->templates; ptr != NULL ; ptr = ptr->next)
		format_template_free (ptr->data);
	g_slist_free (state->templates);
	state->templates = NULL;
197 198 199 200
}

/**
 * templates_load:
201
 * @state: AutoFormatState
202
 *
203
 * This function will load the templates in the currently selected
204
 * category group (it looks at state->category_groups to determine the selection)
205
 *
206 207 208
 * Return value: TRUE if all went well, FALSE otherwise.
 **/
static gboolean
209
templates_load (AutoFormatState *state)
210
{
211 212
	GSList *l;
	gint n_templates;
213

214
	g_return_val_if_fail (state != NULL, FALSE);
215

216
	if (state->category_groups == NULL)
217
		return FALSE;
218

219
	state->templates = category_group_get_templates_list (
220
		state->current_category_group, GO_CMD_CONTEXT (state->wbcg));
221
	for (l = state->templates; l != NULL; l = l->next) {
222
		GnmFormatTemplate *ft = l->data;
223 224 225 226 227
		range_init (&ft->dimension,
			0, 0, PREVIEW_COLS - 1, PREVIEW_ROWS - 1);
		ft->invalidate_hash = TRUE;
	}
	n_templates = g_slist_length (state->templates);
228 229 230 231 232 233

	/*
	 * We need to temporary lock the preview loading/freeing or
	 * else our scrollbar will trigger an event (value_changed) and create the
	 * previews. (which we don't want to happen at this moment)
	 */
234
	state->previews_locked = TRUE;
235
	{
236
		GtkAdjustment *adjustment = gtk_range_get_adjustment (GTK_RANGE (state->scroll));
237 238 239
		gtk_adjustment_configure (adjustment,
					  0, 0, n_templates / 2,
					  1, 3, 3);
240
	}
241
	state->previews_locked = FALSE;
242

243 244 245
	/*
	 * Hide the scrollbar when it's not needed
	 */
246 247
	gtk_widget_set_visible (GTK_WIDGET (state->scroll),
				n_templates > NUM_PREVIEWS);
248

249
	return TRUE;
250 251 252 253
}

/**
 * previews_free:
254
 * @state: AutoFormatState
255
 *
256
 * This function will free all previews.
257 258
 **/
static void
259
previews_free (AutoFormatState *state)
260 261 262
{
	int i;

263
	if (state->previews_locked)
264
		return;
265

266
	if (state->selrect) {
267
		goc_item_destroy (state->selrect);
268 269
		state->selrect = NULL;
	}
270

271
	for (i = 0; i < NUM_PREVIEWS; i++) {
272 273
		GocItem *item = state->grid[i];
		if (item) {
274
			goc_item_destroy (state->grid[i]);
275
			state->grid[i] = NULL;
276 277 278 279 280 281
		}
	}
}

/**
 * previews_load:
282
 * @state: AutoFormatState
283
 * @topindex: The index of the template to be displayed in the upper left corner
284
 *
285
 * This function will create grids and rects for each canvas and associate
286
 * them with the right format templates.
287
 * NOTE : if state->preview_locked is TRUE this function will do nothing,
288 289 290 291
 *        this is handy in situation where signals can cause previews_load to be
 *        called before previews_free.
 **/
static void
292
previews_load (AutoFormatState *state, int topindex)
293 294 295 296
{
	GSList *iterator, *start;
	int i, count = topindex;

297
	g_return_if_fail (state != NULL);
298

299
	if (state->previews_locked)
300 301
		return;

302
	iterator = state->templates;
303 304 305 306 307 308 309
	start = iterator;
	while (iterator && count > 0) {
		iterator = g_slist_next (iterator);
		start = iterator;
		count--;
	}

310
	for (i = 0; i < NUM_PREVIEWS; i++) {
311
		if (start == NULL) {
312 313
			gtk_widget_hide (GTK_WIDGET (state->canvas[i]));
			gtk_frame_set_shadow_type (state->frame[i], GTK_SHADOW_NONE);
314
		} else {
315
			GnmFormatTemplate *ft = start->data;
316

317
			state->grid[i] = auto_format_grid_new (state, i, ft);
318

319
			/* Are we selected? Then draw a selection rectangle */
320
			if (topindex + i == state->preview_index) {
321
				GOStyle *style;
322 323
				g_return_if_fail (state->selrect == NULL);

324 325 326 327 328 329
				state->selrect = goc_item_new (goc_canvas_get_root (state->canvas[i]),
					GOC_TYPE_RECTANGLE,
					"x", (double)(-INNER_BORDER),
					"y", (double)(-INNER_BORDER),
					"width", (double)(TOTAL_WIDTH + 2 * INNER_BORDER),
					"height", (double)(TOTAL_HEIGHT + 2 * INNER_BORDER),
330
					NULL);
331
				style = go_styled_object_get_style (GO_STYLED_OBJECT (state->selrect));
332
				style->line.width = 3.;
333
				style->line.color = GO_COLOR_RED;
334
				style->fill.pattern.back = 0;
Morten Welinder's avatar
Morten Welinder committed
335

336
				gtk_frame_set_shadow_type (state->frame[i], GTK_SHADOW_IN);
337
			} else
338
				gtk_frame_set_shadow_type (state->frame[i], GTK_SHADOW_ETCHED_IN);
339

340
			goc_canvas_scroll_to (state->canvas[i],
341
				-BORDER, -BORDER);
342

343
			gtk_widget_set_tooltip_text
344 345
				(GTK_WIDGET (state->canvas[i]),
				 _(ft->name));
346 347

			gtk_widget_show (GTK_WIDGET (state->canvas[i]));
348 349 350 351
			start = g_slist_next (start);
		}
	}

352
	state->preview_top = topindex;
353 354 355 356 357
}

/********************************************************************************
 * SIGNAL HANDLERS
 ********************************************************************************/
358

359
static void
Morten Welinder's avatar
Morten Welinder committed
360
cb_ok_clicked (G_GNUC_UNUSED GtkButton *button,
361
	       AutoFormatState *state)
362
{
Jody Goldberg's avatar
Jody Goldberg committed
363 364
	if (state->selected_template)
		cmd_selection_autoformat (WORKBOOK_CONTROL (state->wbcg),
365
			format_template_clone (state->selected_template));
Jody Goldberg's avatar
Jody Goldberg committed
366

367
	gtk_widget_destroy (GTK_WIDGET (state->dialog));
368 369 370
}

static void
371
cb_autoformat_destroy (AutoFormatState *state)
372
{
373 374 375
	templates_free (state);
	category_group_list_free (state->category_groups);
	g_free (state);
376 377 378
}

static void
379
cb_scroll_value_changed (GtkAdjustment *adjustment, AutoFormatState *state)
380
{
381
	previews_free (state);
382
	previews_load (state, rint (gtk_adjustment_get_value (adjustment)) * 2);
383 384 385
}

static gboolean
386
cb_canvas_button_press (GocCanvas *canvas,
Morten Welinder's avatar
Morten Welinder committed
387
			G_GNUC_UNUSED GdkEventButton *event,
388
			AutoFormatState *state)
389
{
390
	GnmFormatTemplate *ft;
391
	GSList *ptr;
392
	int index = 0;
393

394
	while (canvas != state->canvas[index] && index < NUM_PREVIEWS)
395
		index++;
396

397
	g_return_val_if_fail (index < NUM_PREVIEWS, FALSE);
398

399
	state->preview_index = state->preview_top + index;
400

401 402
	previews_free (state);
	previews_load (state, state->preview_top);
403

404 405 406
	for (ptr = state->templates, index = 0; ptr != NULL ;  ptr = ptr->next, index++)
		if (index == state->preview_index)
			break;
407

408
	g_return_val_if_fail (ptr != NULL && ptr->data != NULL, FALSE);
409

410 411
	ft = ptr->data;
	state->selected_template = ft;
Jody Goldberg's avatar
Jody Goldberg committed
412
	gtk_entry_set_text (state->info_name,   _(ft->name));
413 414
	gtk_entry_set_text (state->info_author, ft->author);
	gnumeric_textview_set_text (GTK_TEXT_VIEW (state->info_descr),
Jody Goldberg's avatar
Jody Goldberg committed
415
		_(ft->description));
416

Jody Goldberg's avatar
Jody Goldberg committed
417
	gtk_entry_set_text (state->info_cat, _(ft->category->name));
418

419 420 421
	return TRUE;
}

422
static void
Morten Welinder's avatar
Morten Welinder committed
423
cb_check_item_toggled (G_GNUC_UNUSED GtkCheckMenuItem *item,
424
		       AutoFormatState *state)
425
{
426
	GSList *ptr;
427 428
	int i;

429
	for (ptr = state->templates; ptr != NULL ; ptr = ptr->next) {
430
		GnmFormatTemplate *ft = ptr->data;
Morten Welinder's avatar
Morten Welinder committed
431

432 433 434 435 436
		ft->number    = gtk_check_menu_item_get_active (state->number);
		ft->border    = gtk_check_menu_item_get_active (state->border);
		ft->font      = gtk_check_menu_item_get_active (state->font);
		ft->patterns  = gtk_check_menu_item_get_active (state->patterns);
		ft->alignment = gtk_check_menu_item_get_active (state->alignment);
Morten Welinder's avatar
Morten Welinder committed
437

438 439 440 441
		ft->edges.left   = gtk_check_menu_item_get_active (state->edges.left);
		ft->edges.right  = gtk_check_menu_item_get_active (state->edges.right);
		ft->edges.top    = gtk_check_menu_item_get_active (state->edges.top);
		ft->edges.bottom = gtk_check_menu_item_get_active (state->edges.bottom);
Morten Welinder's avatar
Morten Welinder committed
442

443
		ft->invalidate_hash = TRUE;
444 445 446
	}

	for (i = 0; i < NUM_PREVIEWS; i++)
447
		goc_canvas_invalidate (state->canvas [i],
Jody Goldberg's avatar
Jody Goldberg committed
448
			-2, -2, INT_MAX/2, INT_MAX/2);
449 450
}

451
static void
452
cb_category_changed (AutoFormatState *state)
453
{
454
	GList *selection = g_list_nth (state->category_groups,
455
		gtk_combo_box_get_active (state->category));
456 457
	char const *tip = NULL;

458
	state->current_category_group = (selection != NULL) ? selection->data : NULL;
459 460 461
	previews_free (state);
	templates_free (state);
	if (templates_load (state) == FALSE)
462
		g_warning ("Error while loading templates!");
463

464 465 466 467 468
	if (NULL != state->current_category_group) {
		tip = state->current_category_group->description;
		if (NULL == tip)
			tip = state->current_category_group->name;
	}
469
	gtk_widget_set_tooltip_text (GTK_WIDGET (state->category),
470
		(NULL != tip) ? _(tip) : "");
471
	previews_load (state, 0);
472
	cb_check_item_toggled (NULL, state);
473
	cb_canvas_button_press (state->canvas[0], NULL, state);
474 475 476
}

static void
Morten Welinder's avatar
Morten Welinder committed
477
cb_gridlines_item_toggled (G_GNUC_UNUSED GtkCheckMenuItem *item,
478
			   AutoFormatState *state)
479
{
480 481
	previews_free (state);
	previews_load (state, state->preview_top);
482 483 484 485 486
}

/********************************************************************************
 * MAIN
 ********************************************************************************/
487

488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
/*      Menus   */
static GtkActionEntry entries[] = {
	{ "settings", NULL, N_("_Settings"), NULL, NULL, NULL },
		{ "edges", NULL, N_("_Edges"), NULL, NULL, NULL }
};

/* Toggle items */
static GtkToggleActionEntry toggle_entries[] = {
	{ "number", NULL, N_("Apply _Number Formats"), NULL,
		NULL, G_CALLBACK (cb_check_item_toggled), TRUE},
	{ "border", NULL, N_("Apply _Borders"), NULL,
		NULL, G_CALLBACK (cb_check_item_toggled), TRUE },
	{ "font", NULL, N_("Apply _Fonts"), NULL,
		NULL, G_CALLBACK (cb_check_item_toggled), TRUE },
	{ "patterns", NULL, N_("Apply _Patterns"), NULL,
		NULL, G_CALLBACK (cb_check_item_toggled), TRUE },
	{ "alignment", NULL, N_("Apply _Alignment"), NULL,
		NULL, G_CALLBACK (cb_check_item_toggled), TRUE },
	{ "left", NULL, N_("_Left"), NULL,
		NULL, G_CALLBACK (cb_check_item_toggled), TRUE },
	{ "right", NULL, N_("_Right"), NULL,
		NULL, G_CALLBACK (cb_check_item_toggled), TRUE },
	{ "top", NULL, N_("_Top"), NULL,
		NULL, G_CALLBACK (cb_check_item_toggled), TRUE },
	{ "bottom", NULL, N_("_Bottom"), NULL,
		NULL, G_CALLBACK (cb_check_item_toggled), TRUE },
	{ "gridlines", NULL, N_("_Show Gridlines"), NULL,
		NULL, G_CALLBACK (cb_gridlines_item_toggled), FALSE }
};

static const char *ui_description =
"<ui>"
"  <menubar name='bar'>"
"    <menu action='settings'>"
"      <menuitem action='number'/>"
"      <menuitem action='border'/>"
"      <menuitem action='font'/>"
"      <menuitem action='patterns'/>"
"      <menuitem action='alignment'/>"
"      <separator name='settings-sep1'/>"
"      <menu action='edges'>"
"        <menuitem action='left'/>"
"        <menuitem action='right'/>"
"        <menuitem action='top'/>"
"        <menuitem action='bottom'/>"
"      </menu>"
"      <separator name='settings-sep2'/>"
"      <menuitem action='gridlines'/>"
"    </menu>"
"  </menubar>"
"</ui>";
539

540 541 542 543
static gboolean
cb_canvas_focus (GtkWidget *canvas, GtkDirectionType direction,
		 AutoFormatState *state)
{
544
	if (!gtk_widget_has_focus (canvas)) {
545
		gtk_widget_grab_focus (canvas);
546
		cb_canvas_button_press (GOC_CANVAS (canvas), NULL, state);
547 548 549 550 551
		return TRUE;
	}
	return FALSE;
}

552 553 554
/**
 * dialog_autoformat:
 * @wb: The Workbook
555
 *
556 557 558 559 560
 * This function will show the AutoFormatTemplate dialog and apply
 * the template the user chooses to the current selection in the active
 * sheet of the workbook if the user desires.
 **/
void
561
dialog_autoformat (WBCGtk *wbcg)
562
{
563
	GtkBuilder *gui;
564
	AutoFormatState *state;
565
	int i;
566 567
	GtkUIManager *ui_manager;
	GtkActionGroup *action_group;
568

569
	gui = gnm_gtk_builder_new ("autoformat.ui", NULL, GO_CMD_CONTEXT (wbcg));
570 571
	if (gui == NULL)
		return;
572

573
	state = g_new0 (AutoFormatState, 1);
574
	state->wb              = wb_control_get_workbook (WORKBOOK_CONTROL (wbcg));
575 576 577 578
	state->wbcg            = wbcg;
	state->templates       = NULL;
	state->category_groups = NULL;
	state->selrect         = NULL;
579
	for (i = 0; i < NUM_PREVIEWS; i++)
580
		state->grid[i] = NULL;
581

582 583 584 585 586 587 588
	state->current_category_group  = NULL;
	state->preview_top       = 0;
	state->preview_index     = -1;
	state->previews_locked   = FALSE;
	state->more_down         = FALSE;
	state->selected_template = NULL;

Morten Welinder's avatar
Morten Welinder committed
589 590
	state->dialog     = GTK_DIALOG (go_gtk_builder_get_widget (gui, "dialog"));
	state->category   = GTK_COMBO_BOX (go_gtk_builder_get_widget (gui, "format_category"));
591
	state->scroll     = GTK_SCROLLBAR (go_gtk_builder_get_widget (gui, "format_scroll"));
Morten Welinder's avatar
Morten Welinder committed
592
	state->gridlines  = GTK_CHECK_MENU_ITEM  (go_gtk_builder_get_widget (gui, "format_gridlines"));
593

Morten Welinder's avatar
Morten Welinder committed
594 595 596 597
	state->info_name   = GTK_ENTRY (go_gtk_builder_get_widget (gui, "format_info_name"));
	state->info_author = GTK_ENTRY (go_gtk_builder_get_widget (gui, "format_info_author"));
	state->info_cat    = GTK_ENTRY (go_gtk_builder_get_widget (gui, "format_info_cat"));
	state->info_descr  = GTK_TEXT_VIEW (go_gtk_builder_get_widget (gui, "format_info_descr"));
598

Morten Welinder's avatar
Morten Welinder committed
599 600
	state->ok     = GTK_BUTTON (go_gtk_builder_get_widget (gui, "format_ok"));
	state->cancel = GTK_BUTTON (go_gtk_builder_get_widget (gui, "format_cancel"));
601

602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
	action_group = gtk_action_group_new ("settings-actions");
	gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
	gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries), state);
	gtk_action_group_add_toggle_actions (action_group, toggle_entries, G_N_ELEMENTS (toggle_entries), state);

	ui_manager = gtk_ui_manager_new ();
	gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
	g_object_unref (action_group);
	gtk_ui_manager_add_ui_from_string (ui_manager, ui_description, -1, NULL);
	state->number      = GTK_CHECK_MENU_ITEM  (gtk_ui_manager_get_widget (ui_manager, "/bar/settings/number"));
	state->border      = GTK_CHECK_MENU_ITEM  (gtk_ui_manager_get_widget (ui_manager, "/bar/settings/border"));
	state->font        = GTK_CHECK_MENU_ITEM  (gtk_ui_manager_get_widget (ui_manager, "/bar/settings/font"));
	state->patterns    = GTK_CHECK_MENU_ITEM  (gtk_ui_manager_get_widget (ui_manager, "/bar/settings/patterns"));
	state->alignment   = GTK_CHECK_MENU_ITEM  (gtk_ui_manager_get_widget (ui_manager, "/bar/settings/alignment"));

	state->edges.left   = GTK_CHECK_MENU_ITEM  (gtk_ui_manager_get_widget (ui_manager, "/bar/settings/edges/left"));
	state->edges.right  = GTK_CHECK_MENU_ITEM  (gtk_ui_manager_get_widget (ui_manager, "/bar/settings/edges/right"));
	state->edges.top    = GTK_CHECK_MENU_ITEM  (gtk_ui_manager_get_widget (ui_manager, "/bar/settings/edges/top"));
	state->edges.bottom = GTK_CHECK_MENU_ITEM  (gtk_ui_manager_get_widget (ui_manager, "/bar/settings/edges/bottom"));

	state->gridlines  = GTK_CHECK_MENU_ITEM  (gtk_ui_manager_get_widget (ui_manager, "/bar/settings/gridlines"));

Morten Welinder's avatar
Morten Welinder committed
624
	gtk_box_pack_start (GTK_BOX (go_gtk_builder_get_widget (gui, "category-box")),
625 626
	                    gtk_ui_manager_get_widget (ui_manager, "/bar"),
	                    FALSE, TRUE, 0);
627
	for (i = 0; i < NUM_PREVIEWS; i++) {
628 629
		char *name;

630
		name = g_strdup_printf ("format_frame%d", i+1);
Morten Welinder's avatar
Morten Welinder committed
631
		state->frame[i] = GTK_FRAME (go_gtk_builder_get_widget (gui, name));
632
		g_free (name);
633

634
		state->canvas[i] = GOC_CANVAS (g_object_new (GOC_TYPE_CANVAS, NULL));
635 636 637
		gtk_widget_set_size_request (GTK_WIDGET (state->canvas[i]),
			TOTAL_WIDTH + (2 * BORDER),
			TOTAL_HEIGHT + (2 * BORDER));
638
		gtk_container_add (GTK_CONTAINER (state->frame[i]),
Jody Goldberg's avatar
Jody Goldberg committed
639
				   GTK_WIDGET (state->canvas[i]));
640

641 642 643
		g_signal_connect (G_OBJECT (state->canvas[i]),
			"button-press-event",
			G_CALLBACK (cb_canvas_button_press), state);
644 645 646
		g_signal_connect (G_OBJECT (state->canvas[i]),
			"focus",
			G_CALLBACK (cb_canvas_focus), state);
647
	}
648

649
	g_signal_connect (G_OBJECT (gtk_range_get_adjustment (GTK_RANGE (state->scroll))),
650 651 652 653 654 655 656 657
		"value_changed",
		G_CALLBACK (cb_scroll_value_changed), state);
	g_signal_connect (G_OBJECT (state->gridlines),
		"toggled",
		G_CALLBACK (cb_gridlines_item_toggled), state);
	g_signal_connect (G_OBJECT (state->ok),
		"clicked",
		G_CALLBACK (cb_ok_clicked), state);
658
	g_signal_connect_swapped (G_OBJECT (state->cancel), "clicked",
659
		G_CALLBACK (gtk_widget_destroy), state->dialog);
660

661
	/* Fill category list */
662 663 664
	state->category_groups =
		g_list_sort (category_group_list_get (),  category_group_cmp);

665
	if (state->category_groups == NULL) {
666 667 668 669 670 671 672 673
		GtkWidget *dialog;

		dialog = gtk_message_dialog_new (GTK_WINDOW (state->dialog),
				GTK_DIALOG_DESTROY_WITH_PARENT,
				GTK_MESSAGE_WARNING,
				GTK_BUTTONS_CLOSE,
				_("An error occurred while reading the category list"));
		gtk_dialog_run (GTK_DIALOG (dialog));
674
	} else {
675 676
		unsigned i, select = 0;
		GList *ptr = state->category_groups;
677 678 679 680
		GtkListStore* store = gtk_list_store_new (1, G_TYPE_STRING);
		GtkTreeIter iter;
		GtkCellRenderer *renderer = (GtkCellRenderer*) gtk_cell_renderer_text_new();
		gtk_combo_box_set_model (state->category, GTK_TREE_MODEL (store));
Morten Welinder's avatar
Morten Welinder committed
681
		g_object_unref (store);
682 683
		gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (state->category), renderer, TRUE);
		gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (state->category), renderer,
Morten Welinder's avatar
Morten Welinder committed
684 685
						"text", 0,
						NULL);
686 687 688

		for (i = 0 ; ptr != NULL ; ptr = ptr->next, i++) {
			FormatTemplateCategoryGroup *group = ptr->data;
Jody Goldberg's avatar
Jody Goldberg committed
689
			if (!strcmp (group->name,   "General" ))
690
				select = i;
691 692
			gtk_list_store_append (store, &iter);
			gtk_list_store_set (store, &iter,
Jody Goldberg's avatar
Jody Goldberg committed
693
						0, _(group->name),
694
						-1);
695
		}
696

697 698 699
		g_signal_connect_swapped (G_OBJECT (state->category),
			"changed",
			G_CALLBACK (cb_category_changed), state);
700
		gtk_combo_box_set_active (GTK_COMBO_BOX (state->category), select);
701
		gtk_widget_show_all (GTK_WIDGET (state->category));
702
	}
703

704
	gnumeric_init_help_button (
Morten Welinder's avatar
Morten Welinder committed
705
		go_gtk_builder_get_widget (gui, "help_button"),
706
		GNUMERIC_HELP_LINK_AUTOFORMAT);
707

708
	gtk_dialog_set_default_response (state->dialog, GTK_RESPONSE_OK);
Morten Welinder's avatar
Morten Welinder committed
709

710
	/* a candidate for merging into attach guru */
Jody Goldberg's avatar
Jody Goldberg committed
711
	go_gtk_nonmodal_dialog (wbcg_toplevel (state->wbcg),
712
				   GTK_WINDOW (state->dialog));
713 714 715 716
	wbc_gtk_attach_guru (state->wbcg, GTK_WIDGET (state->dialog));
	g_object_set_data_full (G_OBJECT (state->dialog),
		"state", state, (GDestroyNotify)cb_autoformat_destroy);

717 718
	/* not show all or the scrollbars will appear */
	gtk_widget_show (GTK_WIDGET (state->dialog));
719 720
	g_object_unref (gui);
	g_object_unref (ui_manager);
721
}