GUI: Move .ui files from goffice resources to glib resources
[gnumeric.git] / src / dialogs / dialog-sheetobject-size.c
blobb96f7dfdeab8daa9b0d4f2595569978877a78d99
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /**
3 * dialog-sheetobject-size.c:
5 * Author:
6 * Andreas J. Guelzow <aguelzow@pyrshep.ca>
8 * (c) Copyright 2009 Andreas J. Guelzow <aguelzow@pyrshep.ca>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <https://www.gnu.org/licenses/>.
23 #include <gnumeric-config.h>
24 #include <glib/gi18n-lib.h>
25 #include <gnumeric.h>
26 #include <string.h>
27 #include "dialogs.h"
28 #include "help.h"
30 #include <gui-util.h>
31 #include <commands.h>
32 #include <workbook-control.h>
33 #include <workbook.h>
34 #include <wbc-gtk.h>
35 #include <sheet.h>
36 #include <sheet-view.h>
37 #include <application.h>
38 #include <workbook-cmd-format.h>
39 #include <sheet-object-widget.h>
40 #include <sheet-object-impl.h>
41 #include <sheet-control-gui.h>
42 #include <widgets/gnm-so-anchor-mode-chooser.h>
44 #include <gtk/gtk.h>
46 #define SO_SIZE_DIALOG_KEY "so-size-dialog"
48 typedef struct {
49 GtkBuilder *gui;
50 WBCGtk *wbcg;
51 Sheet *sheet;
52 SheetView *sv;
53 SheetControlGUI *scg;
54 GtkWidget *dialog;
55 GtkWidget *ok_button;
56 GtkWidget *apply_button;
57 GtkWidget *cancel_button;
58 GtkWidget *wpoints;
59 GtkSpinButton *wspin;
60 GtkWidget *hpoints;
61 GtkSpinButton *hspin;
62 GtkWidget *xpoints;
63 GtkSpinButton *xspin;
64 GtkWidget *ypoints;
65 GtkSpinButton *yspin;
66 GtkEntry *nameentry;
67 GtkWidget *print_check;
68 GnmSOAnchorModeChooser *modecombo;
70 SheetObject *so;
71 SheetObjectAnchor *old_anchor;
72 SheetObjectAnchor *active_anchor;
73 double coords[4];
74 gchar *old_name;
75 gboolean so_size_needs_restore;
76 gboolean so_pos_needs_restore;
77 gboolean so_name_changed;
78 gboolean so_print_check_changed;
79 gboolean so_mode_changed;
80 } SOSizeState;
82 static void
83 cb_dialog_so_size_value_changed_update_points (GtkSpinButton *spinbutton,
84 GtkLabel *points)
86 gint value = gtk_spin_button_get_value_as_int (spinbutton);
87 double size_points = value * 72./gnm_app_display_dpi_get (FALSE);
88 gchar *pts = g_strdup_printf ("%.2f",size_points);
89 gtk_label_set_text (points, pts);
90 g_free (pts);
93 static void
94 dialog_so_size_button_sensitivity (SOSizeState *state)
96 gboolean sensitive = state->so_size_needs_restore ||
97 state->so_pos_needs_restore ||
98 state->so_name_changed ||
99 state->so_print_check_changed ||
100 state->so_mode_changed;
101 gtk_widget_set_sensitive
102 (state->ok_button, sensitive);
103 gtk_widget_set_sensitive
104 (state->apply_button, sensitive);
107 static void
108 cb_dialog_so_size_destroy (SOSizeState *state)
110 if (state->so_size_needs_restore || state->so_pos_needs_restore)
111 sheet_object_set_anchor (state->so, state->old_anchor);
112 g_free (state->old_anchor);
113 g_free (state->active_anchor);
114 g_free (state->old_name);
115 if (state->so!= NULL)
116 g_object_unref (state->so);
117 if (state->gui != NULL)
118 g_object_unref (state->gui);
119 g_free (state);
122 static void
123 cb_dialog_so_size_cancel_clicked (G_GNUC_UNUSED GtkWidget *button,
124 SOSizeState *state)
126 gtk_widget_destroy (state->dialog);
127 return;
130 static void
131 cb_dialog_so_size_value_changed (G_GNUC_UNUSED GtkSpinButton *spinbutton,
132 SOSizeState *state)
134 int width, height;
135 int new_width, new_height;
136 int dx, dy;
138 width = state->coords[2] - state->coords[0];
139 height = state->coords[3] - state->coords[1];
140 if (width < 0) width = - width;
141 if (height < 0) height = - height;
143 new_width = gtk_spin_button_get_value_as_int (state->wspin);
144 new_height = gtk_spin_button_get_value_as_int (state->hspin);
145 dx = gtk_spin_button_get_value_as_int (state->xspin);
146 dy = gtk_spin_button_get_value_as_int (state->yspin);
148 state->so_size_needs_restore = (new_width != width) || (new_height != height);
149 state->so_pos_needs_restore = (dx != 0) || (dy != 0);
151 *(state->active_anchor) = *(state->old_anchor);
153 if (state->so_size_needs_restore || state->so_pos_needs_restore) {
154 gdouble new_coords[4];
156 new_coords[0] = state->coords[0] + dx;
157 new_coords[1] = state->coords[1] + dy;
158 new_coords[2] = state->coords[2] + dx;
159 new_coords[3] = state->coords[3] + dy;
160 if (new_coords[0] < new_coords[2])
161 new_coords[2] = new_coords[0] + new_width;
162 else
163 new_coords[0] = new_coords[2] + new_width;
164 if (new_coords[1] < new_coords[3])
165 new_coords[3] = new_coords[1] + new_height;
166 else
167 new_coords[1] = new_coords[3] + new_height;
169 scg_object_coords_to_anchor (state->scg, new_coords,
170 state->active_anchor);
173 sheet_object_set_anchor (state->so, state->active_anchor);
175 dialog_so_size_button_sensitivity (state);
178 static void
179 dialog_so_size_load (SOSizeState *state)
181 g_free (state->old_anchor);
182 state->old_anchor = sheet_object_anchor_dup
183 (sheet_object_get_anchor (state->so));
184 scg_object_anchor_to_coords (state->scg,
185 state->old_anchor,
186 state->coords);
187 state->so_size_needs_restore = FALSE;
188 state->so_pos_needs_restore = FALSE;
191 static GOUndo *
192 set_params (SheetObject *so, char *name)
194 return go_undo_binary_new
195 (g_object_ref (so), name,
196 (GOUndoBinaryFunc)sheet_object_set_name,
197 g_object_unref, g_free);
200 static GOUndo *
201 set_print_flag (SheetObject *so, gboolean print)
203 gboolean *p_print = g_new (gboolean, 1);
205 *p_print = print;
206 return go_undo_binary_new
207 (g_object_ref (so), p_print,
208 (GOUndoBinaryFunc)sheet_object_set_print_flag,
209 g_object_unref, g_free);
212 static GOUndo *
213 set_mode (SheetObject *so, GnmSOAnchorMode mode)
215 GnmSOAnchorMode *p_mode = g_new (GnmSOAnchorMode, 1);
217 *p_mode = mode;
218 return go_undo_binary_new
219 (g_object_ref (so), p_mode,
220 (GOUndoBinaryFunc)sheet_object_set_anchor_mode,
221 g_object_unref, g_free);
224 static void
225 cb_dialog_so_size_apply_clicked (G_GNUC_UNUSED GtkWidget *button,
226 SOSizeState *state)
228 char const *name;
229 GOUndo *undo = NULL, *redo = NULL;
230 char const *undo_name = NULL;
231 int cnt = 0;
233 if (state->so_size_needs_restore || state->so_pos_needs_restore) {
234 char const *label = state->so_pos_needs_restore ?
235 _("Move Object") : _("Resize Object");
236 sheet_object_set_anchor (state->so, state->old_anchor);
237 if (!cmd_objects_move (GNM_WBC (state->wbcg),
238 g_slist_prepend (NULL, state->so),
239 g_slist_prepend
240 (NULL, sheet_object_anchor_dup
241 (state->active_anchor)),
242 FALSE, label))
243 dialog_so_size_load (state);
246 name = gtk_entry_get_text (state->nameentry);
247 if (name == NULL)
248 name = "";
249 if (strcmp (name, state->old_name) != 0) {
250 char *old_name, *new_name;
252 g_object_get (G_OBJECT (state->so), "name", &old_name, NULL);
253 undo = go_undo_combine (undo, set_params (state->so, old_name));
255 new_name = (*name == '\0') ? NULL : g_strdup (name);
256 redo = go_undo_combine (redo, set_params (state->so, new_name));
258 undo_name = _("Set Object Name");
259 cnt++;
261 if (state->so_print_check_changed) {
262 gboolean val = ((state->so->flags & SHEET_OBJECT_PRINT) != 0);
263 undo = go_undo_combine (undo, set_print_flag
264 (state->so, val));
265 redo = go_undo_combine (redo, set_print_flag
266 (state->so, !val));
267 undo_name = _("Set Object Print Property");
268 cnt++;
270 if (state->so_mode_changed) {
271 int new_mode = gnm_so_anchor_mode_chooser_get_mode (state->modecombo);
272 int old_mode = state->so->anchor.mode;
273 undo = go_undo_combine (undo, set_mode (state->so, old_mode));
274 redo = go_undo_combine (redo, set_mode (state->so, new_mode));
275 undo_name = _("Set Object Anchor Mode");
276 cnt++;
279 if (cnt > 0) {
280 if (cnt > 1)
281 undo_name = _("Set Object Properties");
282 state->so_name_changed = state->so_print_check_changed = state->so_mode_changed =
283 cmd_generic (GNM_WBC (state->wbcg),
284 undo_name, undo, redo);
286 dialog_so_size_button_sensitivity (state);
288 return;
291 static void
292 cb_dialog_so_size_ok_clicked (GtkWidget *button, SOSizeState *state)
294 cb_dialog_so_size_apply_clicked (button, state);
295 if (!state->so_size_needs_restore && !state->so_pos_needs_restore &&
296 !state->so_name_changed && !state->so_print_check_changed)
297 gtk_widget_destroy (state->dialog);
298 return;
301 static gboolean
302 cb_dialog_so_size_name_changed (GtkEntry *entry,
303 GdkEventFocus *event,
304 SOSizeState *state)
306 char const *name = gtk_entry_get_text (entry);
307 if (name == NULL)
308 name = "";
309 state->so_name_changed
310 = (strcmp (name, state->old_name) != 0);
311 dialog_so_size_button_sensitivity (state);
312 return FALSE;
315 static void
316 cb_dialog_so_size_print_check_toggled (GtkToggleButton *togglebutton,
317 SOSizeState *state)
319 gboolean new_print = !gtk_toggle_button_get_active (togglebutton);
320 gboolean old_print = ((state->so->flags & SHEET_OBJECT_PRINT) != 0);
322 state->so_print_check_changed
323 = (new_print != old_print);
324 dialog_so_size_button_sensitivity (state);
325 return;
328 static void
329 cb_dialog_so_size_mode_changed (GnmSOAnchorModeChooser *chooser, SOSizeState *state)
331 GnmSOAnchorMode new_mode = gnm_so_anchor_mode_chooser_get_mode (chooser);
332 GnmSOAnchorMode old_mode = state->so->anchor.mode;
333 double coords[4];
335 scg_object_anchor_to_coords (state->scg, state->active_anchor, coords);
336 state->active_anchor->mode = new_mode;
337 scg_object_coords_to_anchor (state->scg, coords, state->active_anchor);
338 state->so_mode_changed = new_mode != old_mode;
339 dialog_so_size_button_sensitivity (state);
342 void
343 dialog_so_size (WBCGtk *wbcg, GObject *so)
345 GtkBuilder *gui;
346 SOSizeState *state;
347 GtkGrid *grid;
348 int width, height;
350 g_return_if_fail (wbcg != NULL);
352 if (gnm_dialog_raise_if_exists (wbcg, SO_SIZE_DIALOG_KEY))
353 return;
354 gui = gnm_gtk_builder_load ("res:ui/sheetobject-size.ui", NULL, GO_CMD_CONTEXT (wbcg));
355 if (gui == NULL)
356 return;
358 state = g_new (SOSizeState, 1);
359 state->wbcg = wbcg;
360 state->sv = wb_control_cur_sheet_view (GNM_WBC (wbcg));
361 state->sheet = sv_sheet (state->sv);
362 state->scg = wbcg_get_nth_scg (wbcg, state->sheet->index_in_wb);
363 state->gui = gui;
364 state->dialog = go_gtk_builder_get_widget (state->gui, "object-size");
366 state->so = GNM_SO (so);
367 g_object_ref (so);
369 state->nameentry = GTK_ENTRY (go_gtk_builder_get_widget (state->gui, "name-entry"));
370 state->old_anchor = NULL;
371 state->old_name = NULL;
372 g_object_get (so, "name", &state->old_name, NULL);
373 if (state->old_name == NULL)
374 state->old_name = g_strdup ("");
375 gtk_entry_set_text (state->nameentry, state->old_name);
376 state->so_name_changed = FALSE;
377 g_signal_connect (G_OBJECT (state->nameentry),
378 "focus-out-event",
379 G_CALLBACK (cb_dialog_so_size_name_changed),
380 state);
381 state->so_print_check_changed = FALSE;
383 state->wpoints = GTK_WIDGET (go_gtk_builder_get_widget (state->gui, "w-pts-label"));
384 state->wspin = GTK_SPIN_BUTTON (go_gtk_builder_get_widget (state->gui, "w-spin"));
385 state->hpoints = GTK_WIDGET (go_gtk_builder_get_widget (state->gui, "h-pts-label"));
386 state->hspin = GTK_SPIN_BUTTON (go_gtk_builder_get_widget (state->gui, "h-spin"));
387 state->xpoints = GTK_WIDGET (go_gtk_builder_get_widget (state->gui, "x-pts-label"));
388 state->xspin = GTK_SPIN_BUTTON (go_gtk_builder_get_widget (state->gui, "x-spin"));
389 state->ypoints = GTK_WIDGET (go_gtk_builder_get_widget (state->gui, "y-pts-label"));
390 state->yspin = GTK_SPIN_BUTTON (go_gtk_builder_get_widget (state->gui, "y-spin"));
391 state->print_check = GTK_WIDGET (go_gtk_builder_get_widget (state->gui,
392 "print-check"));
393 state->modecombo = GNM_SO_ANCHOR_MODE_CHOOSER (gnm_so_anchor_mode_chooser_new (sheet_object_can_resize (state->so)));
394 dialog_so_size_load (state);
395 state->active_anchor = sheet_object_anchor_dup (sheet_object_get_anchor
396 (state->so));
397 width = state->coords[2] - state->coords[0];
398 height = state->coords[3] - state->coords[1];
400 gtk_spin_button_set_value (state->wspin, (width < 0) ? - width : width);
401 gtk_spin_button_set_value (state->hspin, (height < 0) ? - height : height);
402 gtk_spin_button_set_value (state->xspin, 0.);
403 gtk_spin_button_set_value (state->yspin, 0.);
404 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->print_check),
405 !(state->so->flags & SHEET_OBJECT_PRINT));
406 gnm_so_anchor_mode_chooser_set_mode (state->modecombo,
407 state->so->anchor.mode);
408 grid = GTK_GRID (gtk_builder_get_object (state->gui, "main-grid"));
409 gtk_grid_insert_row (grid, 7);
410 gtk_grid_attach (grid, GTK_WIDGET (state->modecombo), 0, 7, 2, 1);
411 gtk_widget_set_halign (GTK_WIDGET (state->modecombo), GTK_ALIGN_START);
412 gtk_widget_show (GTK_WIDGET (state->modecombo));
413 g_signal_connect (G_OBJECT (state->wspin),
414 "value-changed",
415 G_CALLBACK (cb_dialog_so_size_value_changed_update_points),
416 state->wpoints);
417 g_signal_connect (G_OBJECT (state->hspin),
418 "value-changed",
419 G_CALLBACK (cb_dialog_so_size_value_changed_update_points),
420 state->hpoints);
421 g_signal_connect (G_OBJECT (state->xspin),
422 "value-changed",
423 G_CALLBACK (cb_dialog_so_size_value_changed_update_points),
424 state->xpoints);
425 g_signal_connect (G_OBJECT (state->yspin),
426 "value-changed",
427 G_CALLBACK (cb_dialog_so_size_value_changed_update_points),
428 state->ypoints);
429 g_signal_connect (G_OBJECT (state->print_check),
430 "toggled",
431 G_CALLBACK (cb_dialog_so_size_print_check_toggled),
432 state);
434 cb_dialog_so_size_value_changed_update_points (state->wspin, GTK_LABEL (state->wpoints));
435 cb_dialog_so_size_value_changed_update_points (state->hspin, GTK_LABEL (state->hpoints));
436 cb_dialog_so_size_value_changed_update_points (state->xspin, GTK_LABEL (state->xpoints));
437 cb_dialog_so_size_value_changed_update_points (state->yspin, GTK_LABEL (state->ypoints));
440 g_signal_connect (G_OBJECT (state->wspin),
441 "value-changed",
442 G_CALLBACK (cb_dialog_so_size_value_changed), state);
443 g_signal_connect (G_OBJECT (state->hspin),
444 "value-changed",
445 G_CALLBACK (cb_dialog_so_size_value_changed), state);
446 g_signal_connect (G_OBJECT (state->xspin),
447 "value-changed",
448 G_CALLBACK (cb_dialog_so_size_value_changed), state);
449 g_signal_connect (G_OBJECT (state->yspin),
450 "value-changed",
451 G_CALLBACK (cb_dialog_so_size_value_changed), state);
453 g_signal_connect (G_OBJECT (state->modecombo),
454 "changed",
455 G_CALLBACK (cb_dialog_so_size_mode_changed), state);
457 state->ok_button = go_gtk_builder_get_widget (state->gui, "ok_button");
458 g_signal_connect (G_OBJECT (state->ok_button),
459 "clicked",
460 G_CALLBACK (cb_dialog_so_size_ok_clicked), state);
461 state->apply_button = go_gtk_builder_get_widget (state->gui, "apply_button");
462 g_signal_connect (G_OBJECT (state->apply_button),
463 "clicked",
464 G_CALLBACK (cb_dialog_so_size_apply_clicked), state);
466 state->cancel_button = go_gtk_builder_get_widget (state->gui, "cancel_button");
467 g_signal_connect (G_OBJECT (state->cancel_button),
468 "clicked",
469 G_CALLBACK (cb_dialog_so_size_cancel_clicked), state);
471 gnm_init_help_button (
472 go_gtk_builder_get_widget (state->gui, "help_button"),
473 GNUMERIC_HELP_LINK_SO_SIZE);
475 gnm_dialog_setup_destroy_handlers (GTK_DIALOG (state->dialog),
476 state->wbcg,
477 GNM_DIALOG_DESTROY_CURRENT_SHEET_REMOVED);
479 wbc_gtk_attach_guru (state->wbcg, state->dialog);
480 g_object_set_data_full (G_OBJECT (state->dialog),
481 "state", state, (GDestroyNotify) cb_dialog_so_size_destroy);
483 gnm_keyed_dialog (wbcg, GTK_WINDOW (state->dialog),
484 SO_SIZE_DIALOG_KEY);
485 dialog_so_size_button_sensitivity (state);
486 gtk_widget_show (state->dialog);