dialog-cell-sort.c 32.6 KB
Newer Older
1 2 3
/*
 * dialog-cell-sort.c:  Implements Cell Sort dialog boxes.
 *
4 5
 * Authors:
 *  JP Rosevear   <jpr@arcavia.com>
6
 *  Michael Meeks <michael@ximian.com>
7
 *  Andreas J. Guelzow <aguelzow@taliesin.ca>
8
 *  Morten Welinder <terra@gnome.org>
jpekka's avatar
jpekka committed
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
 */
Jody Goldberg's avatar
Jody Goldberg committed
24

25
#include <gnumeric-config.h>
26
#include <glib/gi18n-lib.h>
27 28
#include <gnumeric.h>
#include "dialogs.h"
29
#include "help.h"
30 31 32 33 34 35 36 37 38 39 40 41

#include <workbook-view.h>
#include <gui-util.h>
#include <cell.h>
#include <expr.h>
#include <selection.h>
#include <parse-util.h>
#include <ranges.h>
#include <commands.h>
#include <workbook.h>
#include <sort.h>
#include <sheet.h>
42
#include <sheet-view.h>
43
#include <wbc-gtk.h>
44
#include <gnumeric-gconf.h>
45
#include <widgets/gnumeric-cell-renderer-toggle.h>
46
#include <widgets/gnumeric-expr-entry.h>
47
#include <value.h>
48

49
#include <gtk/gtk.h>
Jody Goldberg's avatar
Jody Goldberg committed
50
#include <gsf/gsf-impl-utils.h>
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
51
#include <gdk/gdkkeysyms.h>
52
#include <goffice/goffice.h>
53
#include <dead-kittens.h>
54

55
#define CELL_SORT_KEY "cell-sort-dialog"
56

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
57 58


59
typedef struct {
60
	WBCGtk  *wbcg;
61
	Workbook  *wb;
Jody Goldberg's avatar
Jody Goldberg committed
62 63
	SheetView *sv;
	Sheet     *sheet;
64

65
	GtkBuilder *gui;
66 67 68 69
	GtkWidget *dialog;
	GtkWidget *warning_dialog;
	GtkWidget *cancel_button;
	GtkWidget *ok_button;
70 71
	GtkWidget *up_button;
	GtkWidget *down_button;
72 73
	GtkWidget *add_button;
	GtkWidget *delete_button;
74
	GtkWidget *clear_button;
75 76
	GnmExprEntry *range_entry;
	GnmExprEntry *add_entry;
77 78
	GtkListStore  *model;
	GtkTreeView   *treeview;
79
	GtkTreeViewColumn *header_column;
80
	GtkTreeSelection   *selection;
81
	GtkWidget *cell_sort_row_rb;
82
	GtkWidget *cell_sort_col_rb;
83
	GtkWidget *cell_sort_header_check;
84
	GtkWidget *retain_format_check;
85 86
	GdkPixbuf *image_ascending;
	GdkPixbuf *image_descending;
87
	GOLocaleSel *locale_selector;
88

Jody Goldberg's avatar
Jody Goldberg committed
89
	GnmValue  *sel;
90 91
	gboolean   header;
	gboolean   is_cols;
92
	int        sort_items;
93

94 95 96
} SortFlowState;

enum {
97
	ITEM_HEADER,
98 99
	ITEM_NAME,
	ITEM_DESCENDING,
100
	ITEM_DESCENDING_IMAGE,
101 102 103 104 105 106
	ITEM_CASE_SENSITIVE,
	ITEM_SORT_BY_VALUE,
	ITEM_MOVE_FORMAT,
	ITEM_NUMBER,
	NUM_COLMNS
};
107

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
108 109 110 111 112 113 114 115 116
static const gint MAX_MENU_SIZE = 20;
typedef struct {
	gint index;
	gint start;
	gint end;
	gboolean done_submenu;
	SortFlowState *state;
} AddSortFieldMenuState;

117 118 119 120 121 122 123 124 125 126 127 128 129 130
static gchar *
header_name (Sheet *sheet, int col, int row)
{
	GnmCell *cell;
	gchar *str = NULL;

	cell = sheet_cell_get (sheet, col, row);
	if (cell)
		str = value_get_as_string (cell->value);

	return str;
}


131
static gchar *
132
col_row_name (Sheet *sheet, int col, int row, gboolean header, gboolean is_cols)
133
{
134
	GnmCell *cell;
135 136
	gchar *str = NULL;

137 138 139 140 141
	if (is_cols)
		str = g_strdup_printf (_("Column %s"), col_name (col));
	else
		str = g_strdup_printf (_("Row %s"), row_name (row));

142 143
	if (header) {
		cell = sheet_cell_get (sheet, col, row);
144
		if (cell && !gnm_cell_is_blank (cell)) {
145 146
			gchar *header_str, *generic_str = str;
			header_str = value_get_as_string (cell->value);
147
			str = g_strdup_printf (_("%s (%s)"), header_str, generic_str);
148 149
			g_free (header_str);
			g_free (generic_str);
150
		}
151 152
	}

153 154 155
	return str;
}

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
156

157
static gboolean
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
158
already_in_sort_fields(int index, SortFlowState *state)
159
{
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
160 161 162
	GtkTreeIter iter;
	int item = 0;
	gint number;
163

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
164 165 166 167 168 169 170
	/* See if index is already in the sort fields */
	while (gtk_tree_model_iter_nth_child  (GTK_TREE_MODEL (state->model),
					       &iter, NULL, item)) {
		gtk_tree_model_get (GTK_TREE_MODEL (state->model), &iter,
				    ITEM_NUMBER, &number,
				    -1);
		item++;
171

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
172 173 174
		if (number == index) {
			return TRUE;
		}
175 176
	}

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
177 178 179 180 181 182 183 184 185
	/* Here means not already in sort fields */
	return FALSE;
}

static gboolean
range_already_in_sort_criteria(gint start, gint end, SortFlowState *state)
{
	gint i;
	for (i=start; i<=end; i++) {
186
		if (!already_in_sort_fields(i, state))
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
187
			return FALSE;
188
	}
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
189 190 191 192 193
	return TRUE;
}


static void
194
build_sort_field_menu (gint start, gint end, gint index, GtkWidget *menu, SortFlowState *state, int used);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
195 196 197 198

static void
cb_sort_field_menu_activate(GtkWidget *item, AddSortFieldMenuState *menu_state)
{
199 200 201 202 203 204 205 206 207 208
	GtkWidget *menu = GTK_WIDGET (gtk_menu_item_get_submenu(GTK_MENU_ITEM (item)));

	if (menu_state->done_submenu == FALSE) {
		build_sort_field_menu(menu_state->start,
				      menu_state->end,
				      menu_state->index,
				      menu,
				      menu_state->state, 0);
		menu_state->done_submenu = TRUE;
	}
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
209 210 211
}

static void
212
set_button_sensitivity(SortFlowState *state)
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
213 214
{
	int items;
215 216 217 218 219 220

	if (state->sel == NULL) {
		gtk_widget_set_sensitive (state->ok_button, FALSE);
		return;
	}

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
221 222
	items = state->is_cols ? (state->sel->v_range.cell.b.row -
				  state->sel->v_range.cell.a.row + 1) :
223 224
		(state->sel->v_range.cell.b.col -
		 state->sel->v_range.cell.a.col + 1);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
225 226 227 228 229
	if (state->header)
		items -= 1;
	gtk_widget_set_sensitive (state->ok_button,
				  (state->sort_items != 0) &&
				  (items > 1));
230
	gtk_widget_set_sensitive (state->clear_button, state->sort_items != 0);
231 232
}

233 234 235
static void
append_data (SortFlowState *state, int i, int index)
{
236
	gchar *str, *header;
237 238
	GtkTreeIter iter;
	Sheet *sheet = state->sel->v_range.cell.a.sheet;
239
	gboolean sort_asc = gnm_conf_get_core_sort_default_ascending ();
240

241 242 243
	header = state->is_cols
		? header_name (sheet, i, index)
		: header_name (sheet, index, i);
244
	str = state->is_cols
245 246
		? col_row_name (sheet, i, index, FALSE, TRUE)
		: col_row_name (sheet, index, i, FALSE, FALSE);
247 248
	gtk_list_store_append (state->model, &iter);
	gtk_list_store_set (state->model, &iter,
249
			    ITEM_HEADER,  header,
250
			    ITEM_NAME,  str,
251
			    ITEM_DESCENDING, !sort_asc,
Morten Welinder's avatar
Morten Welinder committed
252
			    ITEM_DESCENDING_IMAGE, sort_asc ? state->image_ascending
253
			    : state->image_descending,
254
			    ITEM_CASE_SENSITIVE, gnm_conf_get_core_sort_default_by_case (),
255 256 257 258 259 260
			    ITEM_SORT_BY_VALUE, TRUE,
			    ITEM_MOVE_FORMAT, TRUE,
			    ITEM_NUMBER, i,
			    -1);
	state->sort_items++;
	g_free (str);
261
	g_free (header);
262 263
}

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
264 265 266 267 268 269 270 271
static void
cb_sort_field_selection(GtkWidget *item, AddSortFieldMenuState *menu_state)
{
	append_data(menu_state->state,
		    menu_state->start,
		    menu_state->index);
	/* Update sensitivity if this is the first sort item. */
	if (menu_state->state->sort_items == 1)
272
		set_button_sensitivity(menu_state->state);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
273 274 275
}

static void
276
build_sort_field_menu (gint start, gint end, gint index, GtkWidget *menu, SortFlowState *state, int used)
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
277 278 279 280 281 282 283 284 285 286 287
{
	Sheet *sheet = state->sel->v_range.cell.a.sheet;
	GtkWidget *item;
	GtkWidget *submenu;
	int i;
	int this_end;
	char *str;
	char *str_start;
	char *str_end;
	AddSortFieldMenuState *menu_state;
	gint menu_size;
288

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
289
	menu_size = 1 + end - start;
290 291 292
	if (MAX_MENU_SIZE < menu_size - used) {
		gint submenu_size;
		gint balanced_submenu_size;
293

294
		submenu_size = (menu_size + MAX_MENU_SIZE - 1) / MAX_MENU_SIZE;
295
		balanced_submenu_size = sqrt((double)
296 297 298 299
					     (menu_size + MAX_MENU_SIZE - 1));
		if (balanced_submenu_size > submenu_size)
			submenu_size = balanced_submenu_size;

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
300 301 302 303
		for (i = start; i <= end; i+=submenu_size) {
			this_end = i + submenu_size - 1;
			if (this_end > end)
				this_end = end;
304

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
305 306
			/* See if there are any fields in this range that aren't already
			   in the sort.
307
			*/
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
308
			if (range_already_in_sort_criteria(i, this_end, state))
309 310 311 312 313 314 315 316 317 318
				continue;

			str_start = state->is_cols
				? col_row_name (sheet, i, index, state->header, TRUE)
				: col_row_name (sheet, index, i, state->header, FALSE);

			str_end = state->is_cols
				? col_row_name (sheet, this_end, index, state->header, TRUE)
				: col_row_name (sheet, index, this_end, state->header, FALSE);

319
			str = g_strdup_printf(_("%s to %s"), str_start, str_end);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
320 321 322 323 324 325
			g_free(str_start);
			g_free(str_end);

			item = (GtkWidget *) gtk_menu_item_new_with_label(str);
			gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
			gtk_widget_show (item);
326

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
327 328 329 330 331 332 333 334 335 336 337 338 339 340
			menu_state = g_new(AddSortFieldMenuState, 1);
			menu_state->start = i;
			menu_state->end = this_end;
			menu_state->index = index;
			menu_state->state = state;
			menu_state->done_submenu = FALSE;
			submenu = gtk_menu_new();
			gtk_menu_item_set_submenu(GTK_MENU_ITEM (item), submenu);
			g_signal_connect (item, "activate",
					  G_CALLBACK (cb_sort_field_menu_activate), menu_state);
		}
	}  else {
		for (i = start; i <= end; i++) {
			if (FALSE == already_in_sort_fields(i, state)) {
341 342

				str = state->is_cols
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
343 344 345 346 347 348 349 350 351 352 353 354
					? col_row_name (sheet, i, index, state->header, TRUE)
					: col_row_name (sheet, index, i, state->header, FALSE);
				item = (GtkWidget *) gtk_menu_item_new_with_label(str);
				gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
				gtk_widget_show (item);
				menu_state = g_new(AddSortFieldMenuState, 1);
				menu_state->start = i;
				menu_state->end = i;
				menu_state->index = index;
				menu_state->state = state;
				menu_state->done_submenu = FALSE;
				g_signal_connect (item, "activate",
355
						  G_CALLBACK (cb_sort_field_selection),
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
356 357 358 359 360 361
						  menu_state);
			}
		}
	}
}

362
static void
363
load_model_data (SortFlowState *state)
364 365 366 367 368
{
	int start;
	int end;
	int index;
	int i;
369
	int limit = gnm_conf_get_core_sort_dialog_max_initial_clauses ();
370 371 372

	if (state->is_cols) {
		start = state->sel->v_range.cell.a.col;
373
		end = state->sel->v_range.cell.b.col;
374 375 376
		index = state->sel->v_range.cell.a.row;
	} else {
		start = state->sel->v_range.cell.a.row;
377
		end = state->sel->v_range.cell.b.row;
378 379 380 381
		index = state->sel->v_range.cell.a.col;
	}

	gtk_list_store_clear (state->model);
382
	state->sort_items = 0;
383

384 385
	if (end >= start + limit)
		end = start + limit - 1;
386

387 388 389 390 391
	for (i = start; i <= end; i++)
		append_data (state, i, index);
}

static void
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
392
translate_range (GnmValue *range, SortFlowState *state)
393
{
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
394 395 396 397
	state->is_cols = !gtk_toggle_button_get_active (
		GTK_TOGGLE_BUTTON (state->cell_sort_row_rb));
	state->header = gtk_toggle_button_get_active (
		GTK_TOGGLE_BUTTON (state->cell_sort_header_check));
398

399
	value_release (state->sel);
400
	state->sel = range;
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
401 402 403 404 405 406 407 408 409
	load_model_data(state);
}

static void
cb_sort_header_check(SortFlowState *state)
{
	state->header = gtk_toggle_button_get_active (
		GTK_TOGGLE_BUTTON (state->cell_sort_header_check));

410
	gtk_tree_view_column_set_visible (state->header_column, state->header);
411
	set_button_sensitivity (state);
412 413 414
}

static void
415
cb_update_to_new_range (SortFlowState *state)
416
{
Jody Goldberg's avatar
Jody Goldberg committed
417
        GnmValue *range;
418

419
        range = gnm_expr_entry_parse_as_value
420
		(GNM_EXPR_ENTRY (state->range_entry), state->sheet);
421 422 423 424 425
	if (range == NULL) {
		if (state->sel != NULL) {
			value_release (state->sel);
			state->sel = NULL;
			gtk_list_store_clear (state->model);
426
			state->sort_items = 0;
427
		}
428
	} else
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
429
		translate_range (range, state);
430
	set_button_sensitivity (state);
431 432
}

433 434
static void
cb_dialog_destroy (SortFlowState  *state)
435
{
436 437
	value_release (state->sel);
	state->sel = NULL;
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
438

439 440 441
	if (state->model != NULL)
		g_object_unref (G_OBJECT (state->model));
	if (state->gui != NULL)
442 443
		g_object_unref (G_OBJECT (state->gui));

444
	wbcg_edit_finish (state->wbcg, WBC_EDIT_REJECT, NULL);
445 446 447

	state->dialog = NULL;

448 449 450 451 452
	g_object_unref (state->image_ascending);
	state->image_ascending = NULL;
	g_object_unref (state->image_descending);
	state->image_descending = NULL;

453 454 455
	g_free (state);
}

456
static void
457
cb_dialog_ok_clicked (SortFlowState *state)
458
{
459
	GnmSortData *data, *data_copy;
Jody Goldberg's avatar
Jody Goldberg committed
460
	GnmSortClause *array, *this_array_item;
461 462
	int item = 0;
	GtkTreeIter iter;
463
	gboolean descending, case_sensitive, sort_by_value, move_format;
464
	gint number;
465
	gint base;
466
	char const *text;
467

Jody Goldberg's avatar
Jody Goldberg committed
468
	array = g_new (GnmSortClause, state->sort_items);
469
	this_array_item = array;
470
	base = (state->is_cols ? state->sel->v_range.cell.a.col : state->sel->v_range.cell.a.row);
471 472 473 474 475 476 477 478 479 480 481

	while (gtk_tree_model_iter_nth_child  (GTK_TREE_MODEL (state->model),
					       &iter, NULL, item)) {
		gtk_tree_model_get (GTK_TREE_MODEL (state->model), &iter,
				    ITEM_DESCENDING,&descending,
				    ITEM_CASE_SENSITIVE, &case_sensitive,
				    ITEM_SORT_BY_VALUE, &sort_by_value,
				    ITEM_MOVE_FORMAT, &move_format,
				    ITEM_NUMBER, &number,
				    -1);
		item++;
482
		this_array_item->offset = number - base;
483
		this_array_item->asc = !!descending;
484 485 486
		this_array_item->cs = case_sensitive;
		this_array_item->val = sort_by_value;
		this_array_item++;
487 488 489
	}


Jody Goldberg's avatar
Jody Goldberg committed
490
	data = g_new (GnmSortData, 1);
491
	data->sheet = state->sel->v_range.cell.a.sheet;
Jody Goldberg's avatar
Jody Goldberg committed
492
	data->range = g_new (GnmRange, 1);
493 494
	data->range = range_init (data->range, state->sel->v_range.cell.a.col
				  + ((state->header && !state->is_cols) ? 1 : 0),
495
				  state->sel->v_range.cell.a.row
496
				  + ((state->header && state->is_cols) ? 1 : 0),
497
				  state->sel->v_range.cell.b.col,
498 499 500 501
				  state->sel->v_range.cell.b.row);
	data->num_clause = state->sort_items;
	data->clauses = array;
	data->top = state->is_cols;
502 503
	data->retain_formats = gtk_toggle_button_get_active (
		GTK_TOGGLE_BUTTON (state->retain_format_check));
504
	data->locale = go_locale_sel_get_locale (state->locale_selector);
Morten Welinder's avatar
Morten Welinder committed
505

506 507 508
	data_copy = gnm_sort_data_copy (data);
	text = gnm_expr_entry_get_text (state->range_entry);
	gnm_sheet_add_sort_setup
Morten Welinder's avatar
Morten Welinder committed
509 510
		(data->sheet,
		 g_strdup((text != NULL && text[0] != '\0') ? text : "Other"),
511
		 data_copy);
Morten Welinder's avatar
Morten Welinder committed
512

513 514 515 516 517 518
	cmd_sort (WORKBOOK_CONTROL (state->wbcg), data);

	gtk_widget_destroy (state->dialog);
	return;
}

519
static void
Morten Welinder's avatar
Morten Welinder committed
520
cb_dialog_cancel_clicked (G_GNUC_UNUSED GtkWidget *button,
521
			  SortFlowState *state)
522 523 524 525
{
	gtk_widget_destroy (state->dialog);
}

526 527 528
static void
dialog_cell_sort_load_sort_setup (SortFlowState *state, GnmSortData const *data)
{
529 530 531 532
	int i;
	GnmSortClause *this = data->clauses;
	gint base, max, index;
	Sheet *sheet = state->sel->v_range.cell.a.sheet;
533

534 535
	if (sheet == NULL)
		sheet = state->sheet;
Morten Welinder's avatar
Morten Welinder committed
536

537
	go_locale_sel_set_locale (state->locale_selector, data->locale);
Morten Welinder's avatar
Morten Welinder committed
538

539 540
	gtk_toggle_button_set_active (
		GTK_TOGGLE_BUTTON (state->retain_format_check), data->retain_formats);
Morten Welinder's avatar
Morten Welinder committed
541

542 543 544
	gtk_toggle_button_set_active (
		GTK_TOGGLE_BUTTON (state->cell_sort_row_rb), !data->top);
	state->is_cols = data->top;
545

546 547 548 549 550
	index = (data->top ? state->sel->v_range.cell.a.row : state->sel->v_range.cell.a.col);
	base = (data->top ? state->sel->v_range.cell.a.col : state->sel->v_range.cell.a.row);
	max = (data->top ? state->sel->v_range.cell.b.col : state->sel->v_range.cell.b.row);
	gtk_list_store_clear (state->model);
	state->sort_items = 0;
Morten Welinder's avatar
Morten Welinder committed
551
	for (i = 0; i < data->num_clause; i++) {
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
		if (data->clauses[i].offset <= max ) {
			GtkTreeIter iter;
			gchar *str, *header;
			int id = data->clauses[i].offset + base;

			header = state->is_cols
				? header_name (sheet, id, index)
				: header_name (sheet, index, id);
			str = col_row_name (sheet, id, id, FALSE, state->is_cols);

			gtk_list_store_append (state->model, &iter);
			gtk_list_store_set (state->model, &iter,
					    ITEM_HEADER,  header,
					    ITEM_NAME,  str,
					    ITEM_DESCENDING, data->clauses[i].asc,
Morten Welinder's avatar
Morten Welinder committed
567
					    ITEM_DESCENDING_IMAGE,
568 569 570 571 572 573 574 575 576 577 578 579
					    !data->clauses[i].asc
					    ? state->image_ascending
					    : state->image_descending,
					    ITEM_CASE_SENSITIVE, data->clauses[i].cs,
					    ITEM_SORT_BY_VALUE, data->clauses[i].val,
					    ITEM_MOVE_FORMAT, TRUE,
					    ITEM_NUMBER, id,
					    -1);
			state->sort_items++;
		}
		this++;
	}
580
	set_button_sensitivity (state);
581 582
}

583 584
static GnmRange const *
dialog_load_selection (SortFlowState *state, gboolean *col_rb)
585
{
Jody Goldberg's avatar
Jody Goldberg committed
586
	GnmRange const *first;
587
	GnmSortData const *data;
588

Jody Goldberg's avatar
Jody Goldberg committed
589
	first = selection_first_range (state->sv, NULL, NULL);
590

591
	if (first != NULL) {
592 593
		gtk_toggle_button_set_active (
			GTK_TOGGLE_BUTTON (state->cell_sort_col_rb),
594
			(*col_rb = (first->end.row - first->start.row > first->end.col - first->start.col)));
595
		gnm_expr_entry_load_from_range (state->range_entry,
596
						state->sheet, first);
597
	} else
598 599
		gtk_toggle_button_set_active (
			GTK_TOGGLE_BUTTON (state->cell_sort_col_rb),
600
			(*col_rb = TRUE));
601 602

	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->cell_sort_header_check),
Morten Welinder's avatar
Morten Welinder committed
603
				      sheet_range_has_heading
604 605
				      (state->sheet, first, *col_rb, FALSE));
	cb_sort_header_check (state);
Morten Welinder's avatar
Morten Welinder committed
606

Morten Welinder's avatar
Morten Welinder committed
607
	data = gnm_sheet_find_sort_setup (state->sheet,
608 609 610
					  gnm_expr_entry_get_text (state->range_entry));
	if (data != NULL)
		dialog_cell_sort_load_sort_setup (state, data);
611 612
	else
		cb_update_to_new_range (state);
Morten Welinder's avatar
Morten Welinder committed
613

614
	return first;
615 616
}

617 618
/**
 * Refreshes the buttons on a row (un)selection
619
 *
620 621
 */
static void
622
cb_sort_selection_changed (SortFlowState *state)
623
{
624
	GtkTreeIter iter, test;
625

626 627 628
	if (!gtk_tree_selection_get_selected (state->selection, NULL, &iter)) {
		gtk_widget_set_sensitive (state->up_button, FALSE);
		gtk_widget_set_sensitive (state->down_button, FALSE);
629
		gtk_widget_set_sensitive (state->delete_button, FALSE);
630 631 632
		return;
	}

633 634 635 636 637 638 639 640 641 642 643
	test = iter;
	gtk_widget_set_sensitive
		(state->up_button,
		 gnm_tree_model_iter_prev (GTK_TREE_MODEL (state->model),
					   &test));

	test = iter;
	gtk_widget_set_sensitive
		(state->down_button,
		 gtk_tree_model_iter_next (GTK_TREE_MODEL (state->model),
					   &test));
644

645
	gtk_widget_set_sensitive (state->delete_button, TRUE);
646
	set_button_sensitivity (state);
647 648 649
}

static void
650
toggled (SortFlowState *state, const gchar *path_string, int column)
651
{
652 653 654 655
	GtkTreeModel *model = GTK_TREE_MODEL (state->model);
	GtkTreeIter iter;
	GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
	gboolean value;
656

657 658 659
	if (gtk_tree_model_get_iter (model, &iter, path)) {
		gtk_tree_model_get (model, &iter, column, &value, -1);
		value = !value;
660
		gtk_list_store_set (GTK_LIST_STORE (model),
661 662 663 664
				    &iter, column, value, -1);
	} else {
		g_warning ("Did not get a valid iterator");
	}
665

666
	gtk_tree_path_free (path);
667 668 669
}

static void
670 671
move_cb (SortFlowState *state,
	 gboolean (*mover) (GtkTreeModel *, GtkTreeIter *))
672
{
673
	GtkTreeIter iter, this_iter;
674

675 676
	if (!gtk_tree_selection_get_selected (state->selection, NULL,
					      &this_iter))
677
		return;
678

679 680 681
	iter = this_iter;
	if (!mover (GTK_TREE_MODEL(state->model), &iter))
		return;
682 683 684

	gtk_list_store_swap (state->model, &this_iter, &iter);
	cb_sort_selection_changed (state);
685 686
}

687
static void
688
cb_up (SortFlowState *state)
689
{
690
	move_cb (state, gnm_tree_model_iter_prev);
691 692 693
}

static void
694
cb_down (SortFlowState *state)
695
{
696
	move_cb (state, gtk_tree_model_iter_next);
697
}
698

699
static void
Morten Welinder's avatar
Morten Welinder committed
700
cb_delete_clicked (G_GNUC_UNUSED GtkWidget *w, SortFlowState *state)
701
{
702 703 704
	GtkTreeIter iter, iter2;
	gboolean ok;

705 706
	if (!gtk_tree_selection_get_selected (state->selection, NULL, &iter))
		return;
707 708 709 710 711 712

	iter2 = iter;
	ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (state->model), &iter2);
	if (!ok) {
		iter2 = iter;
		ok = gnm_tree_model_iter_prev (GTK_TREE_MODEL (state->model), &iter2);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
713
	}
714 715 716 717 718 719

	if (ok)
		gtk_tree_selection_select_iter (state->selection, &iter2);

	gtk_list_store_remove (state->model, &iter);
	state->sort_items--;
720
	set_button_sensitivity (state);
721
}
722

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
723

724
static void
725
cb_clear_clicked (SortFlowState *state)
726 727 728
{
	state->sort_items = 0;
	gtk_list_store_clear (state->model);
729
	set_button_sensitivity (state);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
730 731 732 733 734 735 736 737 738 739
}

static GtkMenu *
build_sort_field_base_menu (SortFlowState *state)
{
	gint start;
	gint end;
	gint index;

	GtkWidget *menu = gtk_menu_new ();
740 741 742
	GList* items = NULL;

	if (state->sel != NULL) {
743 744 745 746 747 748 749 750 751 752 753 754 755 756
		if (state->is_cols) {
			start = state->sel->v_range.cell.a.col;
			end = state->sel->v_range.cell.b.col;
			index = state->sel->v_range.cell.a.row;
		} else {
			start = state->sel->v_range.cell.a.row;
			end = state->sel->v_range.cell.b.row;
			index = state->sel->v_range.cell.a.col;
		}

		build_sort_field_menu (start, end, index, menu, state,
				       state->sort_items);

		items = gtk_container_get_children (GTK_CONTAINER (menu));
757
	}
758

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
759 760
	if (items == NULL) {
		GtkWidget *item;
761
		item = (GtkWidget *) gtk_menu_item_new_with_label(state->is_cols ?
762
								  _("no available column"): _("no available row"));
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
763 764 765 766 767 768
		gtk_widget_set_sensitive( GTK_WIDGET (item), FALSE);
		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
		gtk_widget_show (item);
	}

	g_list_free (items);
769

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
770 771 772 773 774 775
	return GTK_MENU (menu);
}

static void
show_add_menu (SortFlowState *state)
{
776 777
	gnumeric_popup_menu (build_sort_field_base_menu(state),
			     NULL);
778 779
}

780
static void
781
cb_add_clicked (SortFlowState *state)
782
{
Jody Goldberg's avatar
Jody Goldberg committed
783
        GnmValue *range_add;
784
	GnmSheetRange grange_sort, grange_add;
Jody Goldberg's avatar
Jody Goldberg committed
785
	GnmRange intersection;
786 787 788 789
	int start;
	int end;
	int index;
	int i;
790
	gboolean had_items = (state->sort_items > 0);
791 792

        range_add = gnm_expr_entry_parse_as_value
793
		(GNM_EXPR_ENTRY (state->add_entry), state->sheet);
794

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
795 796 797 798 799
	if (range_add == NULL) {
		show_add_menu (state);
		return;
	}

800
	g_return_if_fail (range_add != NULL && state->sel != NULL);
Morten Welinder's avatar
Morten Welinder committed
801

802 803
	gnm_sheet_range_from_value (&grange_sort, state->sel);
	gnm_sheet_range_from_value (&grange_add, range_add);
804

805 806
	value_release (range_add);

807
	if (range_intersection (&intersection, &grange_sort.range, &grange_add.range)) {
808 809 810

		if (state->is_cols) {
			start = intersection.start.col;
811
			end = intersection.end.col;
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
812
			index = state->sel->v_range.cell.a.row;
813 814
		} else {
			start = intersection.start.row;
815
			end = intersection.end.row;
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
816
			index = state->sel->v_range.cell.a.col;
817
		}
Morten Welinder's avatar
Morten Welinder committed
818

819
		for (i = start; i <= end; i++) {
Morten Welinder's avatar
Morten Welinder committed
820

821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836
			int item = 0;
			GtkTreeIter iter;
			gboolean found = FALSE;
			gint number;

			while (gtk_tree_model_iter_nth_child  (GTK_TREE_MODEL (state->model),
							       &iter, NULL, item)) {
				gtk_tree_model_get (GTK_TREE_MODEL (state->model), &iter,
						    ITEM_NUMBER, &number,
						    -1);
				item++;
				if (number == i) {
					found = TRUE;
					break;
				}
			}
Morten Welinder's avatar
Morten Welinder committed
837

838 839 840
			if (!found) {
				append_data (state, i, index);
			}
Morten Welinder's avatar
Morten Welinder committed
841
		}
842
		if (!had_items && (state->sort_items > 0))
843
			set_button_sensitivity(state);
844
	} else
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
845 846 847 848 849 850 851 852 853
		show_add_menu (state);
	gnm_expr_entry_load_from_text (GNM_EXPR_ENTRY (state->add_entry), "");
}

static gint
cb_treeview_button_press(GtkWidget *w, GdkEvent *event, SortFlowState *state)
{
	if ((event->type == GDK_BUTTON_PRESS) &&
	    (event->button.button == 3)) {
854
		gnumeric_popup_menu (build_sort_field_base_menu(state),
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
855 856 857
				     &(event->button));
		return TRUE;
	}
858

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
859 860 861 862 863 864 865 866 867
	return FALSE;
}

static gint
cb_treeview_keypress (G_GNUC_UNUSED GtkWidget *w, GdkEventKey *event,
		      SortFlowState *state)
{
	gboolean ctrl = (event->state & GDK_CONTROL_MASK);
	GtkTreeIter iter;
868

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
869
	switch (event->keyval) {
870 871
	case GDK_KEY_Delete:
	case GDK_KEY_KP_Delete:
872
		cb_delete_clicked (w, state);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
873
		return TRUE;
874 875
	case GDK_KEY_KP_Up:
	case GDK_KEY_Up:
876 877 878
		if (ctrl) {
			cb_up (state);
			return TRUE;
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
879
		}
880 881 882 883 884

		if (gtk_tree_selection_get_selected (state->selection, NULL, &iter) &&
		    gnm_tree_model_iter_prev (GTK_TREE_MODEL (state->model), &iter))
			gtk_tree_selection_select_iter (state->selection,
							&iter);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
885 886
		return TRUE;

887 888
	case GDK_KEY_KP_Down:
	case GDK_KEY_Down:
889 890 891
		if (ctrl) {
			cb_down (state);
			return TRUE;
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
892
		}
893 894 895 896 897

		if (gtk_tree_selection_get_selected (state->selection, NULL, &iter) &&
		    gtk_tree_model_iter_next (GTK_TREE_MODEL (state->model), &iter))
			gtk_tree_selection_select_iter (state->selection,
							&iter);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
898
		return TRUE;
899
	}
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
900
	return FALSE;
901 902
}

903
static void
Morten Welinder's avatar
Morten Welinder committed
904
cb_toggled_descending (G_GNUC_UNUSED GtkCellRendererToggle *cell,
905 906
		       const gchar *path_string,
		       SortFlowState *state)
907
{
908 909 910 911
	GtkTreeModel *model = GTK_TREE_MODEL (state->model);
	GtkTreeIter iter;
	GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
	gboolean value;
912

913 914 915
	if (gtk_tree_model_get_iter (model, &iter, path)) {
		gtk_tree_model_get (model, &iter, ITEM_DESCENDING, &value, -1);
		if (value) {
916
			gtk_list_store_set (GTK_LIST_STORE (model), &iter,
917
					    ITEM_DESCENDING, FALSE,
918
					    ITEM_DESCENDING_IMAGE, state->image_ascending,
919 920
					    -1);
		} else {
921
			gtk_list_store_set (GTK_LIST_STORE (model), &iter,
922
					    ITEM_DESCENDING, TRUE,
923
					    ITEM_DESCENDING_IMAGE, state->image_descending,
924 925
					    -1);
		}
926
	} else {
927
		g_warning ("Did not get a valid iterator");
928
	}
929
	gtk_tree_path_free (path);
930 931
}

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
932 933
#if 0
/* We are currently not supporting `by-value' vs not. */
934 935
static void
cb_toggled_sort_by_value (GtkCellRendererToggle *cell,
936 937
			  const gchar *path_string,
			  SortFlowState *state)
938
{
939
	toggled (state, path_string, ITEM_SORT_BY_VALUE);
940
}
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
941
#endif
942 943 944

static void
cb_toggled_case_sensitive (GtkCellRendererToggle *cell,
945 946
			   const gchar           *path_string,
			   SortFlowState *state)
947
{
948
	toggled (state, path_string, ITEM_CASE_SENSITIVE);
949 950
}

Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
951

952
static void
953 954 955 956 957
dialog_init (SortFlowState *state)
{
	GtkTable *table;
	GtkWidget *scrolled;
	GtkTreeViewColumn *column;
958
	GtkCellRenderer *renderer;
959 960
	gboolean col_rb;
	GnmRange const *range;
961

Morten Welinder's avatar
Morten Welinder committed
962
	table = GTK_TABLE (go_gtk_builder_get_widget (state->gui, "cell_sort_options_table"));
963
	/* setup range entry */
964
	state->range_entry = gnm_expr_entry_new (state->wbcg, TRUE);
965
	gnm_expr_entry_set_flags (state->range_entry,
966 967
				  GNM_EE_SINGLE_RANGE,
				  GNM_EE_MASK);
968
	gtk_table_attach (table, GTK_WIDGET (state->range_entry),
Jody Goldberg's avatar
Jody Goldberg committed
969
			  2, 3, 1, 2,
970 971
			  GTK_EXPAND | GTK_FILL, 0,
			  0, 0);
972
	gnumeric_editable_enters (GTK_WINDOW (state->dialog),
973
				  GTK_WIDGET (state->range_entry));
974
	gnm_expr_entry_set_update_policy (state->range_entry, GTK_UPDATE_DISCONTINUOUS);
975
	gtk_widget_show (GTK_WIDGET (state->range_entry));
976
	g_signal_connect_swapped (G_OBJECT (state->range_entry),
977
				  "changed",
978
				  G_CALLBACK (cb_update_to_new_range), state);
979

980 981 982 983 984 985
	state->locale_selector = GO_LOCALE_SEL (go_locale_sel_new ());
	gtk_widget_show_all (GTK_WIDGET (state->locale_selector));
	gtk_table_attach (table, GTK_WIDGET (state->locale_selector),
			  2, 3, 5, 6,
			  GTK_EXPAND | GTK_FILL, 0,
			  0, 0);
986

Morten Welinder's avatar
Morten Welinder committed
987
	table = GTK_TABLE (go_gtk_builder_get_widget (state->gui, "cell_sort_spec_table"));
988
	/* setup add entry */
989
	state->add_entry = gnm_expr_entry_new (state->wbcg, TRUE);
990
	gnm_expr_entry_set_flags (state->add_entry,
991 992
				  GNM_EE_SINGLE_RANGE,
				  GNM_EE_MASK);
993
	gtk_table_attach (table, GTK_WIDGET (state->add_entry),
994
			  1, 2, 2, 3,
995 996
			  GTK_EXPAND | GTK_FILL, 0,
			  0, 0);
997
	gnumeric_editable_enters (GTK_WINDOW (state->dialog),
998 999 1000
				  GTK_WIDGET (state->add_entry));
	gtk_widget_show (GTK_WIDGET (state->add_entry));

1001
	/* Set-up tree view */
Morten Welinder's avatar
Morten Welinder committed
1002
	scrolled = go_gtk_builder_get_widget (state->gui, "scrolled_cell_sort_list");
1003 1004
	state->model = gtk_list_store_new (NUM_COLMNS, G_TYPE_STRING,
					   G_TYPE_STRING, G_TYPE_BOOLEAN,
1005
					   GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN,
1006
					   G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
1007
					   G_TYPE_INT);
1008 1009 1010 1011
	state->treeview = GTK_TREE_VIEW (
		gtk_tree_view_new_with_model (GTK_TREE_MODEL (state->model)));
	state->selection = gtk_tree_view_get_selection (state->treeview);
	gtk_tree_selection_set_mode (state->selection, GTK_SELECTION_BROWSE);
1012
	g_signal_connect_swapped (state->selection,
1013 1014
				  "changed",
				  G_CALLBACK (cb_sort_selection_changed), state);
1015

1016
	state->header_column = gtk_tree_view_column_new_with_attributes (_("Header"),
1017 1018
									 gtk_cell_renderer_text_new (),
									 "text", ITEM_HEADER, NULL);
1019 1020
	gtk_tree_view_append_column (state->treeview, state->header_column);

1021
	column = gtk_tree_view_column_new_with_attributes (_("Row/Column"),
1022 1023 1024 1025
							   gtk_cell_renderer_text_new (),
							   "text", ITEM_NAME, NULL);
	gtk_tree_view_append_column (state->treeview, column);

1026
	renderer = gnumeric_cell_renderer_toggle_new ();
1027
	g_signal_connect (G_OBJECT (renderer),
1028 1029
			  "toggled",
			  G_CALLBACK (cb_toggled_descending), state);
1030
	column = gtk_tree_view_column_new_with_attributes ("",
1031
							   renderer,
Morten Welinder's avatar
Morten Welinder committed
1032
							   "active", ITEM_DESCENDING,
1033 1034
							   "pixbuf", ITEM_DESCENDING_IMAGE,
							   NULL);
1035 1036
	gtk_tree_view_append_column (state->treeview, column);

1037
	renderer = gtk_cell_renderer_toggle_new ();
1038
	g_signal_connect (G_OBJECT (renderer),
1039 1040
			  "toggled",
			  G_CALLBACK (cb_toggled_case_sensitive), state);
1041
	column = gtk_tree_view_column_new_with_attributes (_("Case Sensitive"),
1042 1043 1044 1045
							   renderer,
							   "active", ITEM_CASE_SENSITIVE, NULL);
	gtk_tree_view_append_column (state->treeview, column);

Jody Goldberg's avatar
Jody Goldberg committed
1046
	gtk_tree_view_columns_autosize (state->treeview);
1047 1048


Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
1049
	g_signal_connect (G_OBJECT (state->treeview),
1050 1051
			  "key_press_event",
			  G_CALLBACK (cb_treeview_keypress), state);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
1052
	g_signal_connect (G_OBJECT (state->treeview),
1053 1054
			  "button_press_event",
			  G_CALLBACK (cb_treeview_button_press), state);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
1055 1056
#if 0
	/* We are currently not supporting `by-value' vs not. */
1057
	renderer = gtk_cell_renderer_toggle_new ();
1058
	g_signal_connect (G_OBJECT (renderer),
1059 1060
			  "toggled",
			  G_CALLBACK (cb_toggled_sort_by_value), state);
1061
	column = gtk_tree_view_column_new_with_attributes (_("By Value"),
1062 1063 1064
							   renderer,
							   "active", ITEM_SORT_BY_VALUE, NULL);
	gtk_tree_view_append_column (state->treeview, column);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
1065
#endif
1066

1067 1068
	gtk_tree_view_set_reorderable (state->treeview,TRUE);

1069 1070 1071
	gtk_container_add (GTK_CONTAINER (scrolled), GTK_WIDGET (state->treeview));
	gtk_widget_show (GTK_WIDGET (state->treeview));

1072
	/* Set-up other widgets */
Morten Welinder's avatar
Morten Welinder committed
1073 1074
	state->cell_sort_row_rb = go_gtk_builder_get_widget (state->gui, "cell_sort_row_rb");
	state->cell_sort_col_rb = go_gtk_builder_get_widget (state->gui, "cell_sort_col_rb");
1075
	g_signal_connect_swapped (G_OBJECT (state->cell_sort_row_rb),
1076
				  "toggled",
1077
				  G_CALLBACK (cb_update_to_new_range), state);
1078

Morten Welinder's avatar
Morten Welinder committed
1079
	state->cell_sort_header_check = go_gtk_builder_get_widget (state->gui,
1080
							      "cell_sort_header_check");
1081
	g_signal_connect_swapped (G_OBJECT (state->cell_sort_header_check),
1082 1083
				  "toggled",
				  G_CALLBACK (cb_sort_header_check), state);
1084

Morten Welinder's avatar
Morten Welinder committed
1085
	state->retain_format_check = go_gtk_builder_get_widget (state->gui,
1086
							   "retain_format_button");
1087
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->retain_format_check),
1088
				      gnm_conf_get_core_sort_default_retain_formats ());
1089 1090


1091
	/* Set-up buttons */
Morten Welinder's avatar
Morten Welinder committed
1092
	state->up_button = go_gtk_builder_get_widget (state->gui, "up_button");
1093 1094 1095
	g_signal_connect_swapped (G_OBJECT (state->up_button),
				  "clicked",
				  G_CALLBACK (cb_up), state);
Morten Welinder's avatar
Morten Welinder committed
1096
	state->down_button = go_gtk_builder_get_widget (state->gui, "down_button");
1097 1098 1099
	g_signal_connect_swapped (G_OBJECT (state->down_button),
				  "clicked",
				  G_CALLBACK (cb_down), state);
Morten Welinder's avatar
Morten Welinder committed
1100
	state->add_button = go_gtk_builder_get_widget (state->gui, "add_button");
1101 1102 1103
	g_signal_connect_swapped (G_OBJECT (state->add_button),
				  "clicked",
				  G_CALLBACK (cb_add_clicked), state);
Andreas J. Guelzow's avatar
Andreas J. Guelzow committed
1104
	gtk_widget_set_sensitive (state->add_button, TRUE);
Morten Welinder's avatar
Morten Welinder committed
1105
	state->delete_button = go_gtk_builder_get_widget (state->gui, "delete_button");
Jody Goldberg's avatar
Jody Goldberg committed
1106
	g_signal_connect (G_OBJECT (state->delete_button),
1107 1108
			  "clicked",
			  G_CALLBACK (cb_delete_clicked), state);
1109 1110
	gtk_widget_set_sensitive (state->delete_button, FALSE);

Morten Welinder's avatar
Morten Welinder committed
1111
	state->clear_button = go_gtk_builder_get_widget (state->gui, "clear_button");
1112 1113 1114
	g_signal_connect_swapped (G_OBJECT (state->clear_button),
				  "clicked",
				  G_CALLBACK (cb_clear_clicked), state);
1115 1116
	gtk_widget_set_sensitive (state->clear_button, FALSE);

1117 1118 1119 1120 1121
	gtk_button_set_alignment (GTK_BUTTON (state->up_button), 0., .5);
	gtk_button_set_alignment (GTK_BUTTON (state->down_button), 0., .5);
	gtk_button_set_alignment (GTK_BUTTON (state->add_button), 0., .5);
	gtk_button_set_alignment (GTK_BUTTON (state->delete_button), 0., .5);
	gtk_button_set_alignment (GTK_BUTTON (state->clear_button), 0., .5);
1122
	gnumeric_init_help_button (
Morten Welinder's avatar
Morten Welinder committed
1123
		go_gtk_builder_get_widget (state->gui, "help_button"),
1124
		GNUMERIC_HELP_LINK_CELL_SORT);
1125

Morten Welinder's avatar
Morten Welinder committed
1126
	state->ok_button = go_gtk_builder_get_widget (state->gui, "ok_button");
1127 1128 1129
	g_signal_connect_swapped (G_OBJECT (state->ok_button),
				  "clicked",
				  G_CALLBACK (cb_dialog_ok_clicked), state);
Morten Welinder's avatar
Morten Welinder committed
1130
	state->cancel_button = go_gtk_builder_get_widget (state->gui, "cancel_button");
1131