dialog-paste-special.c 5.82 KB
Newer Older
1
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
Arturo Espinosa's avatar
Arturo Espinosa committed
2
/*
3 4
 * dialog-paste-special.c: The dialog for selecting non-standard
 *    behaviors when pasting.
Arturo Espinosa's avatar
Arturo Espinosa committed
5 6 7 8
 *
 * Author:
 *  MIguel de Icaza (miguel@gnu.org)
 */
9 10
#include <gnumeric-config.h>
#include <gnumeric.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
11 12
#include "dialogs.h"

Jody Goldberg's avatar
Jody Goldberg committed
13
#include <workbook-control-gui.h>
14 15 16 17 18 19
#include <gui-util.h>
#include <clipboard.h>
#include <eval.h>

#include <libgnome/gnome-i18n.h>

20
#define BUTTON_PASTE_LINK 0
21

22
static const struct {
23 24 25 26 27 28 29 30
	char const *name;
	gboolean allows_operations;
} paste_types [] = {
	{ N_("All"),      TRUE },
	{ N_("Content"),  TRUE },
	{ N_("As Value"), TRUE },
	{ N_("Formats"),  FALSE },
	{ NULL, FALSE }
Arturo Espinosa's avatar
Arturo Espinosa committed
31 32
};

33
static const char *paste_ops[] = {
Arturo Espinosa's avatar
Arturo Espinosa committed
34
	N_("None"),
35
	N_("Add "),
Jody Goldberg's avatar
Jody Goldberg committed
36
	N_("Subtract"),
Arturo Espinosa's avatar
Arturo Espinosa committed
37 38 39 40 41
	N_("Multiply"),
	N_("Divide"),
	NULL
};

42
typedef struct {
Jody Goldberg's avatar
Jody Goldberg committed
43
	GtkDialog       *dialog;
44
	GtkWidget	*op_frame;
45 46
	GtkToggleButton *transpose;
	GtkToggleButton *skip_blanks;
47 48
	GSList *type_group, *op_group;
	int     type,	     op;
49 50
} PasteSpecialState;

51 52 53
/* The "Paste Link" button should be grayed-out, unless type "All" is
   selected, operation "None" is selected, and "Transpose" and "Skip
   Blanks" are not selected.  */
Arturo Espinosa's avatar
Arturo Espinosa committed
54
static void
55
paste_link_set_sensitive (GtkWidget *ignored, PasteSpecialState *state)
Arturo Espinosa's avatar
Arturo Espinosa committed
56
{
57 58 59 60 61
	gboolean sensitive =
		(gtk_radio_group_get_selected (state->type_group) == 0) &&
		(gtk_radio_group_get_selected (state->op_group) == 0) &&
		!gtk_toggle_button_get_active (state->transpose) &&
		!gtk_toggle_button_get_active (state->skip_blanks);
Arturo Espinosa's avatar
Arturo Espinosa committed
62

63 64
	gtk_dialog_set_response_sensitive (state->dialog,
		BUTTON_PASTE_LINK, sensitive);
Arturo Espinosa's avatar
Arturo Espinosa committed
65 66
}

67
static void
68
cb_type_toggle (GtkWidget *ignored, PasteSpecialState *state)
69
{
70 71 72 73
	state->type = gtk_radio_group_get_selected (state->type_group);
	gtk_widget_set_sensitive (state->op_frame,
		paste_types [state->type].allows_operations);
	paste_link_set_sensitive (NULL, state);
74 75
}

76 77
static void
cb_op_toggle (GtkWidget *ignored, PasteSpecialState *state)
78
{
79 80
	state->op = gtk_radio_group_get_selected (state->op_group);
	paste_link_set_sensitive (NULL, state);
81 82 83
}

static void
84
checkbutton_toggled (GtkWidget *widget, gboolean *flag)
85
{
86
        *flag = GTK_TOGGLE_BUTTON (widget)->active;
87 88
}

Arturo Espinosa's avatar
Arturo Espinosa committed
89
int
90
dialog_paste_special (WorkbookControlGUI *wbcg)
Arturo Espinosa's avatar
Arturo Espinosa committed
91
{
92
	GtkWidget *hbox, *vbox;
93
	GtkWidget *f1, *f1v, *op_box, *first_button = NULL;
Arturo Espinosa's avatar
Arturo Espinosa committed
94
	int result, i;
95
	int v;
96
	gboolean do_transpose = FALSE;
97
	gboolean do_skip_blanks = FALSE;
98
	PasteSpecialState state;
99
	GtkWidget *tmp;
100

Jody Goldberg's avatar
Jody Goldberg committed
101 102 103 104 105
	tmp = gtk_dialog_new_with_buttons (_("Paste special"),
		wbcg_toplevel (wbcg),
		GTK_DIALOG_DESTROY_WITH_PARENT,
		_("Paste Link"),	BUTTON_PASTE_LINK,
		GTK_STOCK_CANCEL,	GTK_RESPONSE_CANCEL,
106
		GTK_STOCK_OK,		GTK_RESPONSE_OK,
Jody Goldberg's avatar
Jody Goldberg committed
107
		NULL);
108 109
	state.dialog = GTK_DIALOG (tmp);
	gtk_dialog_set_default_response (state.dialog, GTK_RESPONSE_CANCEL);
Jody Goldberg's avatar
Jody Goldberg committed
110

Arturo Espinosa's avatar
Arturo Espinosa committed
111 112 113 114
	f1  = gtk_frame_new (_("Paste type"));
	f1v = gtk_vbox_new (TRUE, 0);
	gtk_container_add (GTK_CONTAINER (f1), f1v);

115 116 117
	state.op_frame  = gtk_frame_new (_("Operation"));
	op_box = gtk_vbox_new (TRUE, 0);
	gtk_container_add (GTK_CONTAINER (state.op_frame), op_box);
Arturo Espinosa's avatar
Arturo Espinosa committed
118

119 120
	state.type = 0;
	state.type_group = NULL;
Morten Welinder's avatar
Morten Welinder committed
121
	for (i = 0; paste_types[i].name; i++){
122 123 124
		GtkWidget *r = gtk_radio_button_new_with_label (state.type_group,
			_(paste_types[i].name));
		state.type_group = GTK_RADIO_BUTTON (r)->group;
Jody Goldberg's avatar
Jody Goldberg committed
125 126
		g_signal_connect (G_OBJECT (r),
			"toggled",
127
			G_CALLBACK (cb_type_toggle), &state);
Arturo Espinosa's avatar
Arturo Espinosa committed
128
		gtk_box_pack_start_defaults (GTK_BOX (f1v), r);
129 130
		if (i == 0)
			first_button = r;
Arturo Espinosa's avatar
Arturo Espinosa committed
131 132
	}

133 134
	state.op = 0;
	state.op_group = NULL;
Morten Welinder's avatar
Morten Welinder committed
135
	for (i = 0; paste_ops[i]; i++){
136 137 138
		GtkWidget *r = gtk_radio_button_new_with_label (state.op_group,
			_(paste_ops[i]));
		state.op_group = GTK_RADIO_BUTTON (r)->group;
Jody Goldberg's avatar
Jody Goldberg committed
139 140
		g_signal_connect (G_OBJECT (r),
			"toggled",
141 142
			G_CALLBACK (cb_op_toggle), &state);
		gtk_box_pack_start_defaults (GTK_BOX (op_box), r);
Arturo Espinosa's avatar
Arturo Espinosa committed
143
	}
144

145 146
	vbox = gtk_vbox_new (TRUE, 0);

147 148
	state.transpose = GTK_TOGGLE_BUTTON (gtk_check_button_new_with_label (_("Transpose")));
	g_signal_connect (G_OBJECT (state.transpose),
Jody Goldberg's avatar
Jody Goldberg committed
149 150
		"toggled",
		G_CALLBACK (checkbutton_toggled), &do_transpose);
151
	g_signal_connect (G_OBJECT (state.transpose),
Jody Goldberg's avatar
Jody Goldberg committed
152
		"toggled",
153 154
		G_CALLBACK (paste_link_set_sensitive), &state);
	gtk_box_pack_start_defaults (GTK_BOX (vbox), GTK_WIDGET (state.transpose));
155

156 157
	state.skip_blanks = GTK_TOGGLE_BUTTON (gtk_check_button_new_with_label (_("Skip Blanks")));
	g_signal_connect (G_OBJECT (state.skip_blanks),
Jody Goldberg's avatar
Jody Goldberg committed
158 159
		"toggled",
		G_CALLBACK (checkbutton_toggled), &do_skip_blanks);
160
	g_signal_connect (G_OBJECT (state.skip_blanks),
Jody Goldberg's avatar
Jody Goldberg committed
161
		"toggled",
162 163
		G_CALLBACK (paste_link_set_sensitive), &state);
	gtk_box_pack_start_defaults (GTK_BOX (vbox), GTK_WIDGET (state.skip_blanks));
164

Arturo Espinosa's avatar
Arturo Espinosa committed
165 166
	hbox = gtk_hbox_new (TRUE, 0);
	gtk_box_pack_start_defaults (GTK_BOX (hbox), f1);
167
	gtk_box_pack_start_defaults (GTK_BOX (hbox), state.op_frame);
168
	gtk_box_pack_start_defaults (GTK_BOX (hbox), vbox);
Arturo Espinosa's avatar
Arturo Espinosa committed
169

170
	gtk_box_pack_start (GTK_BOX (state.dialog->vbox), hbox, TRUE, TRUE, 0);
Arturo Espinosa's avatar
Arturo Espinosa committed
171
	gtk_widget_show_all (hbox);
Jody Goldberg's avatar
Jody Goldberg committed
172
	gtk_widget_grab_focus (first_button);
Arturo Espinosa's avatar
Arturo Espinosa committed
173 174

	/* Run the dialog */
175 176
	gtk_window_set_modal (GTK_WINDOW (state.dialog), TRUE);
	v = gnumeric_dialog_run (wbcg, state.dialog);
Arturo Espinosa's avatar
Arturo Espinosa committed
177

178 179 180
	/* If closed with the window manager, cancel */
	if (v == -1)
		return 0;
181 182

	result = 0;
183

184
	/* Fetch the results */
Jody Goldberg's avatar
Jody Goldberg committed
185
	if (v == GTK_RESPONSE_OK) {
186
		result = 0;
187

188 189 190 191 192
		switch (state.type) {
		case 0: result = PASTE_ALL_TYPES;	break;
		case 1: result = PASTE_CONTENT;		break;
		case 2: result = PASTE_AS_VALUES;	break;
		case 3: result = PASTE_FORMATS;		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
193
		}
194

195
		/* If it was not just formats, check operation */
196 197 198 199 200 201
		if (result != PASTE_FORMATS) {
			switch (state.op) {
			case 1 : result |= PASTE_OPER_ADD;  break;
			case 2 : result |= PASTE_OPER_SUB;  break;
			case 3 : result |= PASTE_OPER_MULT; break;
			case 4 : result |= PASTE_OPER_DIV;  break;
202 203
			}
		}
204 205
		if (do_transpose)
			result |= PASTE_TRANSPOSE;
206 207
		if (do_skip_blanks)
			result |= PASTE_SKIP_BLANKS;
208
	} else if (v == BUTTON_PASTE_LINK)
209
		result = PASTE_LINK;
Arturo Espinosa's avatar
Arturo Espinosa committed
210 211
	return result;
}