1 /*
2  * dialog-col-width.c:  Sets the magnification factor
3  *
4  * Author:
5  *        Andreas J. Guelzow <aguelzow@taliesin.ca>
6  *
7  * (c) Copyright 2002 Andreas J. Guelzow <aguelzow@taliesin.ca>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, see <https://www.gnu.org/licenses/>.
21  */
22 #include <gnumeric-config.h>
23 #include <glib/gi18n-lib.h>
24 #include <gnumeric.h>
25 #include <dialogs/dialogs.h>
26 #include <dialogs/help.h>
27 
28 #include <gui-util.h>
29 #include <commands.h>
30 #include <workbook-control.h>
31 #include <workbook.h>
32 #include <wbc-gtk.h>
33 #include <sheet.h>
34 #include <sheet-view.h>
35 #include <application.h>
36 #include <workbook-cmd-format.h>
37 
38 
39 #define COL_WIDTH_DIALOG_KEY "col-width-dialog"
40 
41 typedef struct {
42 	WBCGtk *wbcg;
43 	Sheet              *sheet;
44 	SheetView	   *sv;
45 	GtkWidget          *dialog;
46 	GtkWidget          *ok_button;
47 	GtkWidget          *apply_button;
48 	GtkWidget          *cancel_button;
49 	GtkWidget          *default_check;
50 	GtkWidget          *description;
51 	GtkWidget          *points;
52 	GtkSpinButton      *spin;
53 
54 	gboolean           set_default_value;
55 
56 	gint               orig_value;
57 	gboolean           orig_is_default;
58 	gboolean           orig_some_default;
59 	gboolean           orig_all_equal;
60 	gboolean           adjusting;
61 } ColWidthState;
62 
63 static void
dialog_col_width_update_points(ColWidthState * state)64 dialog_col_width_update_points (ColWidthState *state)
65 {
66 	gint value = gtk_spin_button_get_value_as_int (state->spin);
67 	double size_points = value *  72./gnm_app_display_dpi_get (FALSE);
68 	gchar *pts;
69 
70 	pts = g_strdup_printf ("%.2f",size_points);
71 	gtk_label_set_text (GTK_LABEL (state->points), pts);
72 	g_free (pts);
73 }
74 
75 static void
dialog_col_width_button_sensitivity(ColWidthState * state)76 dialog_col_width_button_sensitivity (ColWidthState *state)
77 {
78 	gint value = gtk_spin_button_get_value_as_int (state->spin);
79 	gboolean use_default = gtk_toggle_button_get_active
80 		(GTK_TOGGLE_BUTTON (state->default_check));
81 	gboolean changed_info;
82 
83 	if (state->set_default_value) {
84 		changed_info = (state->orig_value != value);
85 	} else {
86 		changed_info = (((!state->orig_all_equal || (state->orig_value != value)
87 				  || state->orig_some_default) && !use_default)
88 				|| (use_default && !state->orig_is_default));
89 
90 	}
91 	gtk_widget_set_sensitive (state->ok_button, changed_info);
92 	gtk_widget_set_sensitive (state->apply_button, changed_info);
93 
94 	dialog_col_width_update_points (state);
95 }
96 
97 static void
cb_dialog_col_width_cancel_clicked(G_GNUC_UNUSED GtkWidget * button,ColWidthState * state)98 cb_dialog_col_width_cancel_clicked (G_GNUC_UNUSED GtkWidget *button,
99 				    ColWidthState *state)
100 {
101 	gtk_widget_destroy (state->dialog);
102 	return;
103 }
104 
105 
106 static gint
dialog_col_width_set_value(gint value,ColWidthState * state)107 dialog_col_width_set_value (gint value, ColWidthState *state)
108 {
109 	gint adj_value = value/state->sheet->last_zoom_factor_used + 0.5;
110 	gtk_spin_button_set_value (state->spin, adj_value);
111 	return adj_value;
112 }
113 
114 static void
dialog_col_width_load_value(ColWidthState * state)115 dialog_col_width_load_value (ColWidthState *state)
116 {
117 	GSList *l;
118 	gint value = 0;
119 	state->orig_is_default = TRUE;
120 	state->orig_some_default = FALSE;
121 	state->orig_all_equal = TRUE;
122 
123 	state->adjusting = TRUE;
124 	if (state->set_default_value) {
125 		value = sheet_col_get_default_size_pixels (state->sheet);
126 	} else {
127 		for (l = state->sv->selections; l; l = l->next){
128 			GnmRange *ss = l->data;
129 			int col;
130 
131 			for (col = ss->start.col; col <= ss->end.col; col++){
132 				ColRowInfo const *ri = sheet_col_get_info (state->sheet, col);
133 				if (ri->hard_size)
134 					state->orig_is_default = FALSE;
135 				else
136 					state->orig_some_default = TRUE;
137 				if (value == 0)
138 					value = ri->size_pixels;
139 				else if (value != ri->size_pixels){
140 					/* Values differ, so let the user enter the data */
141 					state->orig_all_equal = FALSE;
142 				}
143 			}
144 		}
145 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->default_check),
146 					      state->orig_is_default);
147 	}
148 	state->orig_value =  dialog_col_width_set_value (value, state);
149 	dialog_col_width_button_sensitivity (state);
150 	state->adjusting = FALSE;
151 }
152 
153 
154 static void
cb_dialog_col_width_value_changed(G_GNUC_UNUSED GtkSpinButton * spinbutton,ColWidthState * state)155 cb_dialog_col_width_value_changed (G_GNUC_UNUSED GtkSpinButton *spinbutton,
156 				   ColWidthState *state)
157 {
158 	if (!state->adjusting) {
159 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->default_check), FALSE);
160 		dialog_col_width_button_sensitivity (state);
161 	}
162 }
163 
164 static void
cb_dialog_col_width_default_check_toggled(GtkToggleButton * togglebutton,ColWidthState * state)165 cb_dialog_col_width_default_check_toggled (GtkToggleButton *togglebutton, ColWidthState *state)
166 {
167 	if (!state->adjusting) {
168 		if (gtk_toggle_button_get_active (togglebutton)) {
169 			state->adjusting = TRUE;
170 			dialog_col_width_set_value (sheet_col_get_default_size_pixels (state->sheet),
171 						     state);
172 			state->adjusting = FALSE;
173 		}
174 		dialog_col_width_button_sensitivity (state);
175 	}
176 }
177 
178 static void
cb_dialog_col_width_apply_clicked(G_GNUC_UNUSED GtkWidget * button,ColWidthState * state)179 cb_dialog_col_width_apply_clicked (G_GNUC_UNUSED GtkWidget *button,
180 				   ColWidthState *state)
181 {
182 	gint value = gtk_spin_button_get_value_as_int (state->spin);
183 	int size_pixels = (int)(value * state->sheet->last_zoom_factor_used + 0.5);
184 	gboolean use_default = gtk_toggle_button_get_active
185 		(GTK_TOGGLE_BUTTON (state->default_check));
186 
187 	if (state->set_default_value) {
188 		double points = value * 72./gnm_app_display_dpi_get (FALSE);
189 		cmd_colrow_std_size (GNM_WBC (state->wbcg),
190 				     state->sheet, TRUE, points);
191 		dialog_col_width_load_value (state);
192 	} else {
193 		if (use_default)
194 			size_pixels = 0;
195 
196 		workbook_cmd_resize_selected_colrow (GNM_WBC (state->wbcg),
197 			state->sheet, TRUE, size_pixels);
198 		dialog_col_width_load_value (state);
199 	}
200 
201 	return;
202 }
203 
204 static void
cb_dialog_col_width_ok_clicked(GtkWidget * button,ColWidthState * state)205 cb_dialog_col_width_ok_clicked (GtkWidget *button, ColWidthState *state)
206 {
207 	cb_dialog_col_width_apply_clicked (button, state);
208 	gtk_widget_destroy (state->dialog);
209 	return;
210 }
211 
212 
213 static void
dialog_col_width_set_mode(gboolean set_default,ColWidthState * state)214 dialog_col_width_set_mode (gboolean set_default, ColWidthState *state)
215 {
216 	state->set_default_value = set_default;
217 
218 	if (set_default) {
219 		gtk_widget_hide (state->default_check);
220 		gtk_label_set_text (GTK_LABEL (state->description),
221 				    _("Set standard/default column width"));
222 	} else {
223 		char *text;
224 		char *name = g_markup_escape_text (state->sheet->name_unquoted, -1);
225 		gtk_widget_show (state->default_check);
226 		text = g_strdup_printf (_("Set column width of selection on "
227 					  "<span style='italic' weight='bold'>%s</span>"),
228 					name);
229 		gtk_label_set_markup (GTK_LABEL (state->description), text);
230 		g_free (text);
231 		g_free (name);
232 	}
233 
234 }
235 
236 void
dialog_col_width(WBCGtk * wbcg,gboolean use_default)237 dialog_col_width (WBCGtk *wbcg, gboolean use_default)
238 {
239 	GtkBuilder *gui;
240 	ColWidthState *state;
241 
242 	g_return_if_fail (wbcg != NULL);
243 
244 	if (gnm_dialog_raise_if_exists (wbcg, COL_WIDTH_DIALOG_KEY))
245 		return;
246 	gui = gnm_gtk_builder_load ("res:ui/col-width.ui", NULL, GO_CMD_CONTEXT (wbcg));
247 	if (gui == NULL)
248 		return;
249 
250 	state = g_new (ColWidthState, 1);
251 	state->wbcg  = wbcg;
252 	state->sv = wb_control_cur_sheet_view (GNM_WBC (wbcg));
253 	state->sheet = sv_sheet (state->sv);
254 	state->adjusting = FALSE;
255 	state->dialog = go_gtk_builder_get_widget (gui, "dialog");
256 
257 	state->description = GTK_WIDGET (go_gtk_builder_get_widget (gui, "description"));
258 	state->points = GTK_WIDGET (go_gtk_builder_get_widget (gui, "pts-label"));
259 
260 	state->spin  = GTK_SPIN_BUTTON (go_gtk_builder_get_widget (gui, "spin"));
261 	gtk_adjustment_set_lower (gtk_spin_button_get_adjustment (state->spin),
262 				  GNM_COL_MARGIN + GNM_COL_MARGIN);
263 	g_signal_connect (G_OBJECT (state->spin),
264 		"value-changed",
265 		G_CALLBACK (cb_dialog_col_width_value_changed), state);
266 
267 	state->default_check  = GTK_WIDGET (go_gtk_builder_get_widget (gui, "default_check"));
268 	g_signal_connect (G_OBJECT (state->default_check),
269 		"clicked",
270 		G_CALLBACK (cb_dialog_col_width_default_check_toggled), state);
271 
272 	state->ok_button = go_gtk_builder_get_widget (gui, "ok_button");
273 	g_signal_connect (G_OBJECT (state->ok_button),
274 		"clicked",
275 		G_CALLBACK (cb_dialog_col_width_ok_clicked), state);
276 	state->apply_button = go_gtk_builder_get_widget (gui, "apply_button");
277 	g_signal_connect (G_OBJECT (state->apply_button),
278 		"clicked",
279 		G_CALLBACK (cb_dialog_col_width_apply_clicked), state);
280 
281 	state->cancel_button = go_gtk_builder_get_widget (gui, "cancel_button");
282 	g_signal_connect (G_OBJECT (state->cancel_button),
283 		"clicked",
284 		G_CALLBACK (cb_dialog_col_width_cancel_clicked), state);
285 
286 	gnm_init_help_button (
287 		go_gtk_builder_get_widget (gui, "help_button"),
288 		GNUMERIC_HELP_LINK_COL_WIDTH);
289 
290 	gnm_dialog_setup_destroy_handlers (GTK_DIALOG (state->dialog),
291 					   state->wbcg,
292 					   GNM_DIALOG_DESTROY_CURRENT_SHEET_REMOVED);
293 	dialog_col_width_set_mode (use_default, state);
294 	dialog_col_width_load_value (state);
295 
296 	wbc_gtk_attach_guru (state->wbcg, state->dialog);
297 	g_object_set_data_full (G_OBJECT (state->dialog),
298 				"state", state, (GDestroyNotify)g_free);
299 
300 	gnm_keyed_dialog (wbcg, GTK_WINDOW (state->dialog),
301 			       COL_WIDTH_DIALOG_KEY);
302 	gtk_widget_show (state->dialog);
303 	g_object_unref (gui);
304 }
305