1 /* hf_creation_dialog.c - height field creation interface functions
2  *
3  * Copyright (C) 2001, 2006 Patrice St-Gelais
4  *         patrstg@users.sourceforge.net
5  *         http://geomorph.sourceforge.net
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 
22 #include "hf_creation_dialog.h"
23 #include "render.h"
24 #include "hf.h"
25 #include "hf_wrapper.h"
26 #include "gl_preview.h"
27 
28 #define NBSIZES 6
29 void size_callb (gpointer data,GtkWidget *wdg);
30 
31 omenu_list_type sizes_list[NBSIZES] = {
32 	{NULL,128,NULL,"128",size_callb},
33 	{NULL,256,NULL,"256",size_callb},
34 	{NULL,512,NULL,"512",size_callb},
35 	{NULL,1024,NULL,"1024",size_callb},
36 	{NULL,2048,NULL,"2048",size_callb},
37 	{NULL,4096,NULL,"4096",size_callb},
38 };
39 
40 // Toolbar icons for HF creation algorithm
41 #define NBHFTYPES 4
42 #include "../icons/uniform.xpm"
43 #include "../icons/subdiv1.xpm"
44 #include "../icons/subdiv2.xpm"
45 // #include "../icons/waves.xpm"
46 // #include "../icons/waves1.xpm"
47 #include "../icons/surfadd.xpm"
48 
49 extern gchar* DEFAULT_TERRAIN;
50 
51 command_item_struct hftypes[NBHFTYPES] = {
52 {"Type", "Uniform", "Uniform color",0, (gchar **) uniform_xpm, GDK_LEFT_PTR, hfuniform_callb, NULL, NULL,TRUE},
53 {"Type", "Subdiv1", "Subdivision 1",0, (gchar **) subdiv1_xpm, GDK_LEFT_PTR, hfsubdiv1_callb,NULL, NULL,FALSE},
54 {"Type", "Subdiv2", "Subdivision 2",0, (gchar **) subdiv2_xpm, GDK_LEFT_PTR, hfsubdiv2_callb, NULL, NULL,FALSE},
55 {"Type", "SurfSum", "Progressive sum of surfaces",0, (gchar **) surfadd_xpm, GDK_LEFT_PTR, hfsurfadd_callb, NULL, NULL,FALSE}
56 };
57 
58 /***************************************************************************/
59 
set_size_menu_from_size(gpointer hfo_ptr,gint size)60 void set_size_menu_from_size (gpointer hfo_ptr, gint size) {
61 	hf_options_struct *hfo = (hf_options_struct *) hfo_ptr;
62 	static gchar label[5];
63 	if (hfo->creation_widgets && hfo->creation_widgets->size_menu) {
64 		sprintf(label, "%-4u", (guint) size);
65 //		printf("LABEL: %s\n",label);
66 		set_option_menu_from_label (hfo->creation_widgets->size_menu->omenu_ptr, label);
67 	}
68 }
69 
size_callb(gpointer data,GtkWidget * wdg)70 void size_callb (gpointer data,GtkWidget *wdg) {
71 	// Sets size when creating a new HF
72 	gint hf_size;
73 	static gchar area_label[12];
74 	omenu_struct_type *opt_menu;
75 	hf_wrapper_struct *hfw;
76 	hf_options_struct *hfo;
77 	opt_menu = (omenu_struct_type *) data;
78 //	printf("DATA in SIZE_CALLB: %d;\n",data);
79 	hfo = (hf_options_struct *) opt_menu->data;
80 //	printf("HFO in SIZE_CALLB: %d;\n",hfo);
81 	if (!hfo)
82 		return;
83 
84 	hfw = (hf_wrapper_struct *) * (hf_wrapper_struct **)  hfo->hfw_ptr_ptr;
85 
86 	hf_size = opt_menu->list[opt_menu->current_index].num;
87 	if (!hfw)
88 		return;
89 	if (!hfw->hf_struct)
90 		return;
91 	if (hf_size == hfw->hf_struct->max_x)
92 		//	No change!
93 		return;
94 
95 	sprintf(area_label, "%d x %d", hf_size, hf_size);
96 	gtk_frame_set_label(GTK_FRAME(hfw->draw_area_frame), area_label);
97 
98 	hf_free(hfw->hf_struct);
99 	hfw->hf_options->hf_size = hf_size;
100 	hfw->hf_struct = (hf_struct_type *) hf_new(hf_size);
101 	hfw->display_scale = get_display_scale(hf_size);
102 	hfw->hf_buf8 = (unsigned char *) x_malloc((RIGHT_SHIFT(hf_size, hfw->display_scale)) * (RIGHT_SHIFT(hf_size,hfw->display_scale))*sizeof(unsigned char), "unsigned char (hfw->buf8 in size_callb)");
103 	hfw->if_rgb = FALSE;
104 	hfw->area_size = RIGHT_SHIFT(hf_size,hfw->display_scale);
105 	set_current_button (hfw->sbs, hfw->display_scale);
106 	hfw->size_change_request = TRUE;
107 
108 	gtk_widget_set_size_request (hfw->draw_area_frame, hfw->area_size+SCALE_PAD, hfw->area_size+SCALE_PAD);
109 
110 //	printf("SIZE_CALLB: HFW: %d; HF_SIZE: %d; DISPLAY_SCALE: %d; AREA_SIZE: %d\n", hfw, hf_size, hfw->display_scale, hfw->area_size);
111 
112 	init_render_struct(hfw->hf_options->render_str,
113 		hfw->dirname,
114 		hfw->filename,
115 		&hfw->creation_mode,
116 		hfw->if_modified,
117 		hfw->gl_preview,
118 		hfw->hf_struct->hf_buf,
119 		hfw->hf_struct->max_x,
120 		hfw->hf_struct->max_y);
121 
122 	gl_set_input_grid (hfw->gl_preview, hfw->hf_struct->hf_buf, hfw->hf_struct->max_x, hfw->hf_struct->max_y, HF_TYPE_ID);
123 	gl_update_details_display (hfw->gl_preview);
124 	gtk_drawing_area_size(GTK_DRAWING_AREA(hfw->area),
125 		hfw->area_size, hfw->area_size);
126 }
127 
hf_types_toolbar_new(GtkWidget * window,GtkTooltips * tooltips,GtkWidget ** tb_widget,gpointer hf_options_ptr)128 GtkWidget *hf_types_toolbar_new(GtkWidget *window, GtkTooltips *tooltips,
129 		GtkWidget** tb_widget, gpointer hf_options_ptr) {
130 	GtkWidget *hbox;
131 	GtkWidget *tb;
132 	hbox = gtk_hbox_new(FALSE, 0);
133 	gtk_widget_show(GTK_WIDGET(hbox));
134 	define_label_in_box("Type", hbox, FALSE, FALSE, DEF_PAD*0.5);
135 	tb = standard_toolbar_new(NBHFTYPES,
136 		hftypes,
137 		tooltips,
138 		window,
139 		hf_options_ptr,
140 		GTK_ORIENTATION_HORIZONTAL,
141 		GTK_TOOLBAR_ICONS,
142 		TRUE);
143 	gtk_box_pack_start(GTK_BOX(hbox), tb, FALSE, FALSE, DEF_PAD*0.5);
144 	if (tb_widget)
145 		*tb_widget = tb;
146 	return hbox;
147 }
148 
hf_creation_dialog_new(GtkWidget * window,GtkTooltips * tooltips,gpointer hf_options_ptr,gpointer widget_list_ptr)149 GtkWidget * hf_creation_dialog_new(GtkWidget *window, GtkTooltips *tooltips,
150 		gpointer hf_options_ptr, gpointer widget_list_ptr) {
151 	// Initializes the dialog for creating height fields
152 	// Four parts, from top to bottom:
153 	//	1. Kind / type of HF
154 	//	2. Shape filters
155 	//	3. Generic options (size...)
156 	//	4. Options for the current HF
157 	// Returns a vbox container, allowing to add / substract particular controls
158 	// "window" only needed for heritance of characteristics in child toolbar(s)
159 	// "tooltips" needed for packing tooltips, could have only one for the whole app.
160 	// gpointer hf_options_ptr_pgtr:  is normally the address of the current hf_options pointer
161 	// (hf_options_struct **)
162 
163 	GtkWidget *dialog, *hbox, *vbox, *frame;
164 	gint default_hf_size;
165 	omenu_struct_type *opt_menu;
166 	hf_creation_wdg_struct *wdg_str;
167 //	printf("HFO PTR in HF_CREATION_DIALOG_NEW: %d - %x\n",hf_options_ptr, hf_options_ptr);
168 	wdg_str = (hf_creation_wdg_struct *) x_calloc(sizeof(hf_creation_wdg_struct),1, "hf_creation_wdg_struct");
169 	*((hf_creation_wdg_struct **) widget_list_ptr) = wdg_str;
170 
171 	((hf_options_struct *)hf_options_ptr)->creation_widgets = wdg_str;
172 
173 	frame = options_frame_new("HeightField");
174 
175 	vbox = gtk_vbox_new(FALSE, 0);
176 	gtk_widget_show(vbox);
177 
178 	//	1st generic option:  HF size - a power of 2
179 	//	Default:  some % of screen width
180 
181 	hbox = gtk_hbox_new(FALSE, DEF_PAD);
182 	gtk_widget_show(hbox);
183 	define_label_in_box("Size", hbox, FALSE, FALSE, DEF_PAD);
184 
185 	default_hf_size = hf_default_size();
186 
187 	create_omenu_with_callb_data (&opt_menu, sizes_list,
188 		NBSIZES,
189 		find_omenu_num(sizes_list, default_hf_size, NBSIZES),
190 		hf_options_ptr);
191 	gtk_box_pack_start(GTK_BOX(hbox), opt_menu->omenu_ptr, FALSE, FALSE, 0);
192 
193 	wdg_str->size_menu = opt_menu;
194 
195  	gtk_box_pack_start (GTK_BOX (hbox), create_render_bar (window, tooltips, ((hf_options_struct *)hf_options_ptr)->render_str), FALSE, FALSE, 0);
196 
197 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
198 
199 	gtk_box_pack_start(GTK_BOX(vbox),
200 		hf_types_toolbar_new(window, tooltips, &wdg_str->hf_types_toolbar,hf_options_ptr), FALSE, FALSE, 0);
201 
202 	//	Other generic options ?
203 
204 	gtk_container_add(GTK_CONTAINER(frame), vbox);
205 	dialog = gtk_vbox_new(FALSE,0);
206 	gtk_box_pack_start(GTK_BOX(dialog), frame, FALSE, FALSE, 0);
207 	gtk_widget_show(dialog);
208 
209 	return dialog;
210 }
211 
hf_commit_creation(gpointer data)212 void hf_commit_creation (gpointer data) {
213 //	Commit the filter
214 	filter_dialog_struct *fds;
215 	hf_wrapper_struct *hfw;
216 	hfw = (hf_wrapper_struct *) data;
217 //	printf("HFW, HFW->creation_mode in hf_commit_creation: %d, %d\n",data,hfw->creation_mode);
218 // printf("HFW->window->window: %d->%d\n",hfw->window,hfw->window->window);
219 	hfw->creation_mode = FALSE;  // Supposed to be done in hf_wrapper_copy...
220 //	hfw->hf_options->current_calculation = NULL;
221 	hfw->apply_filter = FALSE;
222 
223 //	Backup the filter definition and nullify it - we 1st commit the HF without the filter
224 	if (hfw->hf_options->fd_struct) {
225 		set_filter_defaults (hfw->hf_options->fd_struct);
226 	}
227 
228 	record_action(hfw, hfw->hf_options->last_creation_action);
229 	if (hfw->hf_options->fd_struct) {
230 		fds = hfw->hf_options->fd_struct;
231 		if (fds->current_filter) {
232 		    filter_apply(hfw->hf_struct,
233 			fds->current_filter,
234 			hfw->hf_options->dist_matrix,
235 			fds->revert_filter,
236 			fds->filter_level,
237 			fds->merge_oper);
238 //	Now we commit the HF with the filter
239 		record_action(hfw,_("Shape filter"));
240 
241 		}
242 	}
243 //	If we are in the shape filter subdialog in the tools dialog:
244 	if (hfw->hf_options->img)
245 		hfw->hf_options->fd_struct = hfw->hf_options->img->fd_struct;
246 	else
247 		hfw->hf_options->fd_struct = NULL;
248 
249 //	"expose_event" seems required to display the cursor ?
250 	emit_expose_event(hfw->area);
251 }
252 
253 // HF creation
254 
hfuniform_callb(GtkWidget * wdg,gpointer hf_options_ptr)255 void hfuniform_callb(GtkWidget *wdg, gpointer hf_options_ptr) {
256 	// Display / connect callback for uniform hf (a simple scale from 0 to 0xFFFF)
257 
258 	hf_wrapper_struct *hfw;
259 	hf_options_struct *hfo = (hf_options_struct *) hf_options_ptr;
260 
261 	if (!hfo)
262 		return;
263 	if (wdg)
264 		if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wdg)))
265 			return;
266 
267 // printf("IN hfuniform_callb:  hfo: %d;\n", hfo);
268 
269 	//  Options dialog
270 	if (!hfo->uniform_dialog) {
271 		// NB hfw->hf_options->uniform_value allocated in hf_options_new()
272 		hfo->uniform_dialog = uniform_dialog_new(hfo,
273 			*hfo->uniform_value);
274 		gtk_box_pack_start(GTK_BOX(hfo->creation_container), hfo->uniform_dialog, FALSE, FALSE, 0);
275 	}
276 	if (hfo->current_dialog && GTK_IS_WIDGET(hfo->current_dialog))
277 		gtk_widget_hide(hfo->current_dialog);
278 	gtk_widget_show(hfo->uniform_dialog);
279 	hfo->last_creation_action = _("Uniform");
280 	hfo->current_dialog = hfo->uniform_dialog;
281 	hfo->current_calculation = (gpointer) uniform;
282 	hfo->current_callb = hfuniform_callb;
283 	hfo->current_options = (gpointer) hfo->uniform_value;
284 	hfo->flag_uniform_done = FALSE;
285 	if (hfo->hfw_ptr_ptr) {
286 		hfw = (hf_wrapper_struct *) * (hf_wrapper_struct **) hfo->hfw_ptr_ptr;
287 		if (hfw)
288 			gener_hf(hfw);
289 	}
290 }
291 
hfsubdiv1_callb(GtkWidget * wdg,gpointer hf_options_ptr)292 void hfsubdiv1_callb(GtkWidget *wdg, gpointer hf_options_ptr) {
293 	// Display / connect callback
294 	// Simple subdivision, square / diamond dots
295 
296 	hf_wrapper_struct *hfw;
297 	hf_options_struct *hfo = (hf_options_struct *) hf_options_ptr;
298 	if (!hfo)
299 		return;
300 	if (wdg)
301 		if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wdg)))
302 			return;
303 
304 // printf("IN hfsubdiv1_callb:  hfo: %d;\n", hfo);
305 
306 	//  Options dialog - we create it at the 1st pass
307 	if (!hfo->subdiv1_dialog) {
308 	//	We create the struct which will receive the data
309 		hfo->subdiv1_options = subdiv1_opt_new();
310 	//	Dialog creation (with some defaults from subdiv1_opt_new())
311 		hfo->subdiv1_dialog = subdiv1_dialog_new(hfo);
312 		gtk_box_pack_start(GTK_BOX(hfo->creation_container), hfo->subdiv1_dialog, FALSE, FALSE, 0);
313 	}
314 	if (hfo->current_dialog && GTK_IS_WIDGET(hfo->current_dialog))
315 		gtk_widget_hide(hfo->current_dialog);
316 	gtk_widget_show(hfo->subdiv1_dialog);
317 	hfo->last_creation_action = _("Subdiv1");
318 	hfo->current_dialog= hfo->subdiv1_dialog;
319 	hfo->current_calculation = (gpointer) subdiv1;
320 	hfo->current_callb = hfsubdiv1_callb;
321 	hfo->current_options = (gpointer) hfo->subdiv1_options;
322 	if (hfo->hfw_ptr_ptr) {
323 		hfw = (hf_wrapper_struct *) * (hf_wrapper_struct **) hfo->hfw_ptr_ptr;
324 		if (hfw)
325 			gener_hf(hfw);
326 	}
327 }
328 
hfsubdiv2_callb(GtkWidget * wdg,gpointer hf_options_ptr)329 void hfsubdiv2_callb(GtkWidget *wdg, gpointer hf_options_ptr) {
330 	// Display / connect callback
331 	// Simple subdivision, square / diamond dots
332 
333 	static gint frq = 50;
334 	hf_wrapper_struct *hfw;
335 	hf_options_struct *hfo = (hf_options_struct *) hf_options_ptr;
336 	if (!hfo)
337 		return;
338 	if (wdg)
339 		if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wdg)))
340 			return;
341 
342 // printf("IN hfsubdiv2_callb:  hfo: %d;\n", hfo);
343 
344 	//  Options dialog - we create it at the 1st pass
345 	if (!hfo->subdiv2_dialog) {
346 	//	We create the struct which will receive the data
347 		hfo->subdiv2_options = subdiv2_opt_new(&frq,1);
348 	//	Dialog creation (with some defaults from subdiv2_opt_new())
349 		hfo->subdiv2_dialog = subdiv2_dialog_new(hfo);
350 		gtk_box_pack_start(GTK_BOX(hfo->creation_container), hfo->subdiv2_dialog, FALSE, FALSE, 0);
351 	}
352 	if (hfo->current_dialog && GTK_IS_WIDGET(hfo->current_dialog))
353 		gtk_widget_hide(hfo->current_dialog);
354 	gtk_widget_show(hfo->subdiv2_dialog);
355 	hfo->last_creation_action = _("Subdiv2");
356 	hfo->current_dialog = hfo->subdiv2_dialog;
357 	hfo->current_calculation = (gpointer) subdiv2;
358 	hfo->current_callb = hfsubdiv2_callb;
359 	hfo->current_options = (gpointer) hfo->subdiv2_options;
360 	if (hfo->hfw_ptr_ptr) {
361 		hfw = (hf_wrapper_struct *) * (hf_wrapper_struct **) hfo->hfw_ptr_ptr;
362 		if (hfw)
363 			gener_hf(hfw);
364 	}
365 }
366 
hfsurfadd_callb(GtkWidget * wdg,gpointer hf_options_ptr)367 void hfsurfadd_callb(GtkWidget *wdg, gpointer hf_options_ptr) {
368 	// Progressive addition of surfaces
369 
370 	hf_wrapper_struct *hfw;
371 	hf_options_struct *hfo = (hf_options_struct *) hf_options_ptr;
372 	if (!hfo)
373 		return;
374 
375 	if (wdg)
376 		if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wdg)))
377 			return;
378 
379 // printf("IN hfsurfadd_callb:  hfo: %d;\n", hfo);
380 
381 	//  Options dialog - we create it at the 1st pass
382 	if (!hfo->surfadd_dialog) {
383 	//	We create the struct which will receive the data
384 		hfo->surfadd_options = surfadd_opt_new();
385 		hfo->surfadd_options->dist_matrix = hfo->dist_matrix;
386 	//	Dialog creation (with some defaults from surfadd_opt_new())
387 		hfo->surfadd_dialog = surfadd_dialog_new(hfo);
388 		hfo->surfadd_options->current_filter =
389 			&((hf_wrapper_struct *)hfo->primit_surf)->hf_options->fd_struct->current_filter;
390 		hfo->surfadd_options->revert_filter =
391 			&((hf_wrapper_struct *)hfo->primit_surf)->hf_options->fd_struct->revert_filter;
392 		hfo->surfadd_options->filter_merge =
393 			&((hf_wrapper_struct *)hfo->primit_surf)->hf_options->fd_struct->merge_oper;
394 		hfo->surfadd_options->filter_level =
395 			&((hf_wrapper_struct *)hfo->primit_surf)->hf_options->fd_struct->filter_level;
396 		gtk_container_add(GTK_CONTAINER(hfo->creation_container),
397 			hfo->surfadd_dialog);
398 	}
399 	if (hfo->current_dialog && GTK_IS_WIDGET(hfo->current_dialog))
400 		gtk_widget_hide(hfo->current_dialog);
401 	gtk_widget_show(hfo->surfadd_dialog);
402 	hfo->last_creation_action = _("SurfSum");
403 	hfo->current_dialog = hfo->surfadd_dialog;
404 	hfo->current_calculation = (gpointer) surfadd;
405 	hfo->current_callb = hfsurfadd_callb;
406 	hfo->current_options = (gpointer) hfo->surfadd_options;
407 
408 	if (hfo->hfw_ptr_ptr) {
409 		hfw = (hf_wrapper_struct *) * (hf_wrapper_struct **) hfo->hfw_ptr_ptr;
410 		if (hfw)
411 			gener_hf(hfw);
412 	}
413 }
414