dialog-define-names.c 8.88 KB
Newer Older
Jody Goldberg's avatar
Jody Goldberg committed
1 2 3 4
/* vim: set sw=8: */

/*
 * dialog-define-name.c: Edit named regions.
Miguel de Icaza's avatar
Miguel de Icaza committed
5 6
 *
 * Author:
Jody Goldberg's avatar
Jody Goldberg committed
7 8 9
 * 	Jody Goldberg <jgoldberg@home.com> 
 *	Michael Meeks <michael@imaginator.com>
 */
Miguel de Icaza's avatar
Miguel de Icaza committed
10 11
#include <config.h>
#include <gnome.h>
Michael Meeks's avatar
Michael Meeks committed
12
#include <glade/glade.h>
Miguel de Icaza's avatar
Miguel de Icaza committed
13
#include "dialogs.h"
14
#include "expr.h"
15
#include "str.h"
16
#include "expr-name.h"
Jody Goldberg's avatar
Jody Goldberg committed
17
#include "sheet.h"
18
#include "workbook.h"
19
#include "workbook-control.h"
20
#include "workbook-edit.h"
21
#include "gnumeric-util.h"
Miguel de Icaza's avatar
Miguel de Icaza committed
22

23 24
#define LIST_KEY "name_list_data"

Michael Meeks's avatar
Michael Meeks committed
25 26
typedef struct {
	GladeXML  *gui;
27
	GtkWidget *dialog;
28 29 30
	GtkList   *list;
	GtkEntry  *name;
	GtkEntry  *value;
31
	GtkCombo  *scope;
Michael Meeks's avatar
Michael Meeks committed
32
	GList     *expr_names;
33
	NamedExpression *cur_name;
Jody Goldberg's avatar
Jody Goldberg committed
34

35 36 37 38 39
	GtkWidget *ok_button;
	GtkWidget *add_button;
	GtkWidget *close_button;
	GtkWidget *delete_button;

40
	Sheet	  *sheet;
41 42
	Workbook  *wb;
	WorkbookControlGUI  *wbcg;
43
} NameGuruState;
Michael Meeks's avatar
Michael Meeks committed
44

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
static void
cb_scope_changed (GtkEntry *entry, NameGuruState *state)
{
	if (state->cur_name != NULL)
		puts("changed");
}

static void
name_guru_init_scope (NameGuruState *state)
{
	NamedExpression *cur = state->cur_name;
	GList *list = NULL;

	if (cur != NULL && cur->sheet) {
		list = g_list_prepend (list, _("Workbook"));
		list = g_list_prepend (list, cur->sheet->name_unquoted);
	} else {
		list = g_list_prepend (list, state->sheet->name_unquoted);
		list = g_list_prepend (list, _("Workbook"));
	}

	state->cur_name = NULL;
	gtk_combo_set_popdown_strings (state->scope, list);
	g_list_free (list);
	state->cur_name = cur;
}

72
static void
Jody Goldberg's avatar
Jody Goldberg committed
73
cb_name_guru_select_name (GtkWidget *list, NameGuruState *state)
74
{
Jody Goldberg's avatar
Jody Goldberg committed
75 76 77
	NamedExpression *expr_name;
	GList *sel = GTK_LIST(list)->selection;
	char *txt;
78 79 80 81 82 83

	if (sel == NULL)
		return;

	g_return_if_fail (sel->data != NULL);

Jody Goldberg's avatar
Jody Goldberg committed
84
	expr_name = gtk_object_get_data (GTK_OBJECT (sel->data), LIST_KEY);
85

86
	g_return_if_fail (expr_name != NULL);
Jody Goldberg's avatar
Jody Goldberg committed
87 88 89
	g_return_if_fail (expr_name->name != NULL);
	g_return_if_fail (expr_name->name->str != NULL);

90 91
	state->cur_name = expr_name;

Jody Goldberg's avatar
Jody Goldberg committed
92 93 94 95 96 97 98
	/* Display the name */
	gtk_entry_set_text (state->name, expr_name->name->str);

	/* Display the value */
	txt = expr_name_value (expr_name);
	gtk_entry_set_text (state->value, txt);
	g_free (txt);
99 100 101

	/* Init the scope combo box */
	name_guru_init_scope (state);
Michael Meeks's avatar
Michael Meeks committed
102 103 104
}

static void
Jody Goldberg's avatar
Jody Goldberg committed
105
name_guru_populate_list (NameGuruState *state)
Michael Meeks's avatar
Michael Meeks committed
106 107
{
	GList *names;
Jody Goldberg's avatar
Jody Goldberg committed
108
	GtkContainer *list;
Michael Meeks's avatar
Michael Meeks committed
109

110 111
	g_return_if_fail (state != NULL);
	g_return_if_fail (state->list != NULL);
Michael Meeks's avatar
Michael Meeks committed
112

113
	state->cur_name = NULL;
114 115
	if (state->expr_names != NULL)
		g_list_free (state->expr_names);
Michael Meeks's avatar
Michael Meeks committed
116

117
	state->expr_names = expr_name_list (state->wb, state->sheet, FALSE);
118

119
	list = GTK_CONTAINER (state->list);
120
	for (names = state->expr_names ; names != NULL ; names = g_list_next (names)) {
121
		NamedExpression *expr_name = names->data;
122 123 124 125 126 127 128 129 130 131
		GtkWidget *li;

		if (expr_name->sheet != NULL) {
			char *name = g_strdup_printf ("%s!%s",
						      expr_name->sheet->name_unquoted,
						      expr_name->name->str);
			li = gtk_list_item_new_with_label (name);
			g_free (name);
		} else
			li = gtk_list_item_new_with_label (expr_name->name->str);
132
		gtk_object_set_data (GTK_OBJECT (li), LIST_KEY, expr_name);
Jody Goldberg's avatar
Jody Goldberg committed
133
		gtk_container_add (list, li);
Michael Meeks's avatar
Michael Meeks committed
134
	}
Jody Goldberg's avatar
Jody Goldberg committed
135
	gtk_widget_show_all (GTK_WIDGET (state->list));
136 137 138
}

static void
139
cb_name_guru_remove (GtkWidget *ignored, NameGuruState *state)
Michael Meeks's avatar
Michael Meeks committed
140
{
141 142
	g_return_if_fail (state != NULL);

143 144
	if (state->cur_name != NULL) {
		GList *na = g_list_remove (state->expr_names, state->cur_name);
145

Jody Goldberg's avatar
Jody Goldberg committed
146 147
		g_return_if_fail (na != NULL);
		g_return_if_fail (na->data != NULL);
148 149 150 151 152 153

		expr_name_remove (na->data);
		state->expr_names = g_list_remove (state->expr_names, na->data);

		gtk_entry_set_text (state->name, "");
		gtk_entry_set_text (state->value, "");
Jody Goldberg's avatar
Jody Goldberg committed
154
	}
155 156 157
}

static gboolean
158
cb_name_guru_add (NameGuruState *state)
159
{
160
	NamedExpression     *expr_name;
Jody Goldberg's avatar
Jody Goldberg committed
161 162 163
	ExprTree     *expr;
	gchar        *name, *value, *error;
	ParsePos      pos, *pp;
164 165 166 167 168 169 170 171

	g_return_val_if_fail (state != NULL, FALSE);

	value = gtk_entry_get_text (state->value);
	name  = gtk_entry_get_text (state->name);

	if (!name || (name[0] == '\0'))
		return TRUE;
172

Jody Goldberg's avatar
Jody Goldberg committed
173 174 175 176 177 178 179
	/* FIXME : Need to be able to control scope.
	 *        1) sheet
	 *        2) workbook
	 *        3) global
	 *
	 * default to workbook for now.
	 */
180 181 182
	pp = parse_pos_init (&pos, state->wb, state->sheet,
			     state->sheet->cursor.edit_pos.col,
			     state->sheet->cursor.edit_pos.row);
Jody Goldberg's avatar
Jody Goldberg committed
183 184 185 186 187

	expr_name = expr_name_lookup (pp, name);

	expr = expr_parse_string (value, pp, NULL, &error);

Jody Goldberg's avatar
Jody Goldberg committed
188 189
	/* If the expression is invalid */
	if (expr == NULL) {
190
		gnumeric_notice (state->wbcg, GNOME_MESSAGE_BOX_ERROR, error);
Jody Goldberg's avatar
Jody Goldberg committed
191 192
		return FALSE;

Jody Goldberg's avatar
Jody Goldberg committed
193
	/* If name already exists replace the its content */
Jody Goldberg's avatar
Jody Goldberg committed
194
	} else if (expr_name) {
Jody Goldberg's avatar
Jody Goldberg committed
195 196 197 198
		if (!expr_name->builtin) {
			expr_tree_unref (expr_name->t.expr_tree);
			expr_name->t.expr_tree = expr;
		} else
199
			gnumeric_notice (state->wbcg, GNOME_MESSAGE_BOX_ERROR,
Morten Welinder's avatar
Morten Welinder committed
200
					 _("You cannot redefine a builtin name."));
Jody Goldberg's avatar
Jody Goldberg committed
201 202
	} else
		expr_name = expr_name_add (state->wb, NULL, name, expr, &error);
203

Jody Goldberg's avatar
Jody Goldberg committed
204
	g_return_val_if_fail (expr_name != NULL, FALSE);
205

206
	gtk_list_clear_items (state->list, 0, -1);
Jody Goldberg's avatar
Jody Goldberg committed
207
	name_guru_populate_list (state);
208 209 210 211

	return TRUE;
}

Jody Goldberg's avatar
Jody Goldberg committed
212 213 214
static void
cb_name_guru_value_focus (GtkWidget *w, GdkEventFocus *ev, NameGuruState *state)
{
Jody Goldberg's avatar
Jody Goldberg committed
215 216
	GtkEntry *entry = GTK_ENTRY (w);
	if (entry == state->value) {
217 218
		workbook_set_entry (state->wbcg, state->value);
		workbook_edit_select_absolute (state->wbcg);
Jody Goldberg's avatar
Jody Goldberg committed
219
	} else
220
		workbook_set_entry (state->wbcg, NULL);
Jody Goldberg's avatar
Jody Goldberg committed
221 222
}

223
static void
224
cb_name_guru_clicked (GtkWidget *button, NameGuruState *state)
225
{
226 227 228
	if (state->dialog == NULL)
		return;

229
	workbook_set_entry (state->wbcg, NULL);
Jody Goldberg's avatar
Jody Goldberg committed
230

231
	if (button == state->delete_button) {
232
		cb_name_guru_remove (NULL, state);
233 234 235 236
		return;
	}

	if (button == state->add_button || button == state->ok_button)
Jody Goldberg's avatar
Jody Goldberg committed
237 238 239
		/* If adding the name failed do not exit */
		if (!cb_name_guru_add (state))
			return;
240 241 242

	if (button == state->close_button || button == state->ok_button)
		gtk_widget_destroy (state->dialog);
243 244
}

245 246
static GtkWidget *
name_guru_init_button (NameGuruState *state, char const *name)
247
{
248 249 250 251 252
	GtkWidget *tmp = glade_xml_get_widget (state->gui, name);
	gtk_signal_connect (GTK_OBJECT (tmp), "clicked",
			    GTK_SIGNAL_FUNC (cb_name_guru_clicked),
			    state);
	return tmp;
253 254
}

255 256
static gboolean
cb_name_guru_destroy (GtkObject *w, NameGuruState *state)
257
{
258 259 260
	g_return_val_if_fail (w != NULL, FALSE);
	g_return_val_if_fail (state != NULL, FALSE);

261
	workbook_edit_detach_guru (state->wbcg);
262 263 264 265 266 267 268 269 270

	if (state->gui != NULL) {
		gtk_object_unref (GTK_OBJECT (state->gui));
		state->gui = NULL;
	}

	/* Handle window manger closing the dialog.
	 * This will be ignored if we are being destroyed differently.
	 */
271
	workbook_finish_editing (state->wbcg, FALSE);
272 273 274 275 276

	state->dialog = NULL;

	g_free (state);
	return FALSE;
277 278
}

279
static gboolean
280
name_guru_init (NameGuruState *state, WorkbookControlGUI *wbcg)
281
{
282 283 284 285 286 287
	Workbook *wb = wb_control_workbook (WORKBOOK_CONTROL (wbcg));

	state->wbcg  = wbcg;
	state->wb   = wb;
	state->sheet = wb_control_cur_sheet (WORKBOOK_CONTROL (wbcg));
	state->gui = gnumeric_glade_xml_new (state->wbcg, "names.glade");
288 289 290
        if (state->gui == NULL)
                return TRUE;

291
	state->dialog = glade_xml_get_widget (state->gui, "NameGuru");
292 293
	state->name  = GTK_ENTRY (glade_xml_get_widget (state->gui, "name"));
	state->value = GTK_ENTRY (glade_xml_get_widget (state->gui, "value"));
294
	state->scope = GTK_COMBO (glade_xml_get_widget (state->gui, "scope_combo"));
295 296
	state->list  = GTK_LIST  (glade_xml_get_widget (state->gui, "name_list"));
	state->expr_names = NULL;
297 298 299 300 301 302
	state->cur_name   = NULL;

	/* Init the scope combo box */
	name_guru_init_scope (state);
	gtk_signal_connect (GTK_OBJECT (state->scope->entry), "changed",
			    GTK_SIGNAL_FUNC (cb_scope_changed), state);
303 304 305 306 307 308 309

	state->ok_button = name_guru_init_button (state, "ok_button");
	state->close_button = name_guru_init_button (state, "close_button");
	state->add_button = name_guru_init_button (state, "add_button");
	state->delete_button = name_guru_init_button (state, "delete_button");

	gtk_signal_connect (GTK_OBJECT (state->list), "selection_changed",
310
			    GTK_SIGNAL_FUNC (cb_name_guru_select_name), state);
Jody Goldberg's avatar
Jody Goldberg committed
311 312 313 314
	gtk_signal_connect (GTK_OBJECT (state->name), "focus-in-event",
			    GTK_SIGNAL_FUNC (cb_name_guru_value_focus), state);
	gtk_signal_connect (GTK_OBJECT (state->value), "focus-in-event",
			    GTK_SIGNAL_FUNC (cb_name_guru_value_focus), state);
315
	gtk_signal_connect (GTK_OBJECT (state->dialog), "destroy",
Jody Goldberg's avatar
Jody Goldberg committed
316
			    GTK_SIGNAL_FUNC (cb_name_guru_destroy), state);
317

Jody Goldberg's avatar
Jody Goldberg committed
318 319 320 321
 	gnumeric_editable_enters (GTK_WINDOW (state->dialog),
				  GTK_EDITABLE(state->name));
 	gnumeric_editable_enters (GTK_WINDOW (state->dialog),
				  GTK_EDITABLE (state->value));
322 323
	gnumeric_combo_enters (GTK_WINDOW (state->dialog),
			       state->scope);
324
	gnumeric_non_modal_dialog (state->wbcg, GTK_WINDOW (state->dialog));
325

326
	workbook_edit_attach_guru (state->wbcg, state->dialog);
327 328

	return FALSE;
Michael Meeks's avatar
Michael Meeks committed
329 330
}

Miguel de Icaza's avatar
Miguel de Icaza committed
331
void
332
dialog_define_names (WorkbookControlGUI *wbcg)
Miguel de Icaza's avatar
Miguel de Icaza committed
333
{
334
	NameGuruState *state;
Michael Meeks's avatar
Michael Meeks committed
335

336
	g_return_if_fail (wbcg != NULL);
Michael Meeks's avatar
Michael Meeks committed
337

338
	state = g_new (NameGuruState, 1);
339
	if (name_guru_init (state, wbcg)) {
340
		g_free (state);
Michael Meeks's avatar
Michael Meeks committed
341 342 343
		return;
	}

Jody Goldberg's avatar
Jody Goldberg committed
344
	name_guru_populate_list (state);
345
	gtk_widget_show (state->dialog);
Miguel de Icaza's avatar
Miguel de Icaza committed
346
}