1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * dialog-sheetobject-size.c:
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>
32 #include <workbook-control.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>
46 #define SO_SIZE_DIALOG_KEY "so-size-dialog"
56 GtkWidget
*apply_button
;
57 GtkWidget
*cancel_button
;
67 GtkWidget
*print_check
;
68 GnmSOAnchorModeChooser
*modecombo
;
71 SheetObjectAnchor
*old_anchor
;
72 SheetObjectAnchor
*active_anchor
;
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
;
83 cb_dialog_so_size_value_changed_update_points (GtkSpinButton
*spinbutton
,
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
);
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
);
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
);
123 cb_dialog_so_size_cancel_clicked (G_GNUC_UNUSED GtkWidget
*button
,
126 gtk_widget_destroy (state
->dialog
);
131 cb_dialog_so_size_value_changed (G_GNUC_UNUSED GtkSpinButton
*spinbutton
,
135 int new_width
, new_height
;
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
;
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
;
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
);
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
,
187 state
->so_size_needs_restore
= FALSE
;
188 state
->so_pos_needs_restore
= FALSE
;
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
);
201 set_print_flag (SheetObject
*so
, gboolean print
)
203 gboolean
*p_print
= g_new (gboolean
, 1);
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
);
213 set_mode (SheetObject
*so
, GnmSOAnchorMode mode
)
215 GnmSOAnchorMode
*p_mode
= g_new (GnmSOAnchorMode
, 1);
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
);
225 cb_dialog_so_size_apply_clicked (G_GNUC_UNUSED GtkWidget
*button
,
229 GOUndo
*undo
= NULL
, *redo
= NULL
;
230 char const *undo_name
= NULL
;
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
),
240 (NULL
, sheet_object_anchor_dup
241 (state
->active_anchor
)),
243 dialog_so_size_load (state
);
246 name
= gtk_entry_get_text (state
->nameentry
);
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");
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
265 redo
= go_undo_combine (redo
, set_print_flag
267 undo_name
= _("Set Object Print Property");
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");
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
);
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
);
302 cb_dialog_so_size_name_changed (GtkEntry
*entry
,
303 GdkEventFocus
*event
,
306 char const *name
= gtk_entry_get_text (entry
);
309 state
->so_name_changed
310 = (strcmp (name
, state
->old_name
) != 0);
311 dialog_so_size_button_sensitivity (state
);
316 cb_dialog_so_size_print_check_toggled (GtkToggleButton
*togglebutton
,
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
);
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
;
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
);
343 dialog_so_size (WBCGtk
*wbcg
, GObject
*so
)
350 g_return_if_fail (wbcg
!= NULL
);
352 if (gnm_dialog_raise_if_exists (wbcg
, SO_SIZE_DIALOG_KEY
))
354 gui
= gnm_gtk_builder_load ("sheetobject-size.ui", NULL
, GO_CMD_CONTEXT (wbcg
));
358 state
= g_new (SOSizeState
, 1);
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
);
364 state
->dialog
= go_gtk_builder_get_widget (state
->gui
, "object-size");
366 state
->so
= GNM_SO (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
),
379 G_CALLBACK (cb_dialog_so_size_name_changed
),
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
,
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
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
),
415 G_CALLBACK (cb_dialog_so_size_value_changed_update_points
),
417 g_signal_connect (G_OBJECT (state
->hspin
),
419 G_CALLBACK (cb_dialog_so_size_value_changed_update_points
),
421 g_signal_connect (G_OBJECT (state
->xspin
),
423 G_CALLBACK (cb_dialog_so_size_value_changed_update_points
),
425 g_signal_connect (G_OBJECT (state
->yspin
),
427 G_CALLBACK (cb_dialog_so_size_value_changed_update_points
),
429 g_signal_connect (G_OBJECT (state
->print_check
),
431 G_CALLBACK (cb_dialog_so_size_print_check_toggled
),
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
),
442 G_CALLBACK (cb_dialog_so_size_value_changed
), state
);
443 g_signal_connect (G_OBJECT (state
->hspin
),
445 G_CALLBACK (cb_dialog_so_size_value_changed
), state
);
446 g_signal_connect (G_OBJECT (state
->xspin
),
448 G_CALLBACK (cb_dialog_so_size_value_changed
), state
);
449 g_signal_connect (G_OBJECT (state
->yspin
),
451 G_CALLBACK (cb_dialog_so_size_value_changed
), state
);
453 g_signal_connect (G_OBJECT (state
->modecombo
),
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
),
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
),
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
),
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
),
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
),
485 dialog_so_size_button_sensitivity (state
);
486 gtk_widget_show (state
->dialog
);