2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2003-2007, Evan Battaglia <gtoevan@gmx.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "uibuilder.h"
23 #include "vikradiogroup.h"
24 #include "vikfileentry.h"
25 #include "vikfilelist.h"
27 GtkWidget
*a_uibuilder_new_widget ( VikLayerParam
*param
, VikLayerParamData data
)
30 switch ( param
->widget_type
)
32 case VIK_LAYER_WIDGET_COLOR
:
33 if ( param
->type
== VIK_LAYER_PARAM_COLOR
)
34 rv
= gtk_color_button_new_with_color ( &(data
.c
) );
36 case VIK_LAYER_WIDGET_CHECKBUTTON
:
37 if ( param
->type
== VIK_LAYER_PARAM_BOOLEAN
)
39 //rv = gtk_check_button_new_with_label ( //param->title );
40 rv
= gtk_check_button_new ();
42 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(rv
), TRUE
);
45 case VIK_LAYER_WIDGET_COMBOBOX
:
47 if ( param
->type
== VIK_LAYER_PARAM_UINT
&& param
->widget_data
)
49 gchar
**pstr
= param
->widget_data
;
50 rv
= gtk_combo_box_new_text ();
52 gtk_combo_box_append_text ( GTK_COMBO_BOX ( rv
), *(pstr
++) );
53 if ( param
->extra_widget_data
) /* map of alternate uint values for options */
56 for ( i
= 0; ((const char **)param
->widget_data
)[i
]; i
++ )
57 if ( ((guint
*)param
->extra_widget_data
)[i
] == data
.u
)
59 gtk_combo_box_set_active ( GTK_COMBO_BOX(rv
), i
);
63 gtk_combo_box_set_active ( GTK_COMBO_BOX ( rv
), data
.u
);
67 case VIK_LAYER_WIDGET_RADIOGROUP
:
68 /* widget_data and extra_widget_data are GList */
69 if ( param
->type
== VIK_LAYER_PARAM_UINT
&& param
->widget_data
)
71 rv
= vik_radio_group_new ( param
->widget_data
);
72 if ( param
->extra_widget_data
) /* map of alternate uint values for options */
75 int nb_elem
= g_list_length(param
->widget_data
);
76 for ( i
= 0; i
< nb_elem
; i
++ )
77 if ( (guint32
)g_list_nth_data(param
->extra_widget_data
, i
) == data
.u
)
79 vik_radio_group_set_selected ( VIK_RADIO_GROUP(rv
), i
);
83 else if ( data
.u
) /* zero is already default */
84 vik_radio_group_set_selected ( VIK_RADIO_GROUP(rv
), data
.u
);
87 case VIK_LAYER_WIDGET_RADIOGROUP_STATIC
:
88 if ( param
->type
== VIK_LAYER_PARAM_UINT
&& param
->widget_data
)
90 rv
= vik_radio_group_new_static ( (const gchar
**) param
->widget_data
);
91 if ( param
->extra_widget_data
) /* map of alternate uint values for options */
94 for ( i
= 0; ((const char **)param
->widget_data
)[i
]; i
++ )
95 if ( ((guint
*)param
->extra_widget_data
)[i
] == data
.u
)
97 vik_radio_group_set_selected ( VIK_RADIO_GROUP(rv
), i
);
101 else if ( data
.u
) /* zero is already default */
102 vik_radio_group_set_selected ( VIK_RADIO_GROUP(rv
), data
.u
);
105 case VIK_LAYER_WIDGET_SPINBUTTON
:
106 if ( (param
->type
== VIK_LAYER_PARAM_DOUBLE
|| param
->type
== VIK_LAYER_PARAM_UINT
107 || param
->type
== VIK_LAYER_PARAM_INT
) && param
->widget_data
)
109 gdouble init_val
= (param
->type
== VIK_LAYER_PARAM_DOUBLE
) ? data
.d
: (param
->type
== VIK_LAYER_PARAM_UINT
? data
.u
: data
.i
);
110 VikLayerParamScale
*scale
= (VikLayerParamScale
*) param
->widget_data
;
111 rv
= gtk_spin_button_new ( GTK_ADJUSTMENT(gtk_adjustment_new( init_val
, scale
->min
, scale
->max
, scale
->step
, scale
->step
, scale
->step
)), scale
->step
, scale
->digits
);
114 case VIK_LAYER_WIDGET_ENTRY
:
115 if ( param
->type
== VIK_LAYER_PARAM_STRING
)
117 rv
= gtk_entry_new ();
118 gtk_entry_set_text ( GTK_ENTRY(rv
), data
.s
);
121 case VIK_LAYER_WIDGET_FILEENTRY
:
122 if ( param
->type
== VIK_LAYER_PARAM_STRING
)
124 rv
= vik_file_entry_new ();
125 vik_file_entry_set_filename ( VIK_FILE_ENTRY(rv
), data
.s
);
128 case VIK_LAYER_WIDGET_FILELIST
:
129 if ( param
->type
== VIK_LAYER_PARAM_STRING_LIST
)
131 rv
= vik_file_list_new ( param
->title
);
132 vik_file_list_set_files ( VIK_FILE_LIST(rv
), data
.sl
);
135 case VIK_LAYER_WIDGET_HSCALE
:
136 if ( (param
->type
== VIK_LAYER_PARAM_DOUBLE
|| param
->type
== VIK_LAYER_PARAM_UINT
137 || param
->type
== VIK_LAYER_PARAM_INT
) && param
->widget_data
)
139 gdouble init_val
= (param
->type
== VIK_LAYER_PARAM_DOUBLE
) ? data
.d
: (param
->type
== VIK_LAYER_PARAM_UINT
? data
.u
: data
.i
);
140 VikLayerParamScale
*scale
= (VikLayerParamScale
*) param
->widget_data
;
141 rv
= gtk_hscale_new_with_range ( scale
->min
, scale
->max
, scale
->step
);
142 gtk_scale_set_digits ( GTK_SCALE(rv
), scale
->digits
);
143 gtk_range_set_value ( GTK_RANGE(rv
), init_val
);
149 VikLayerParamData
a_uibuilder_widget_get_value ( GtkWidget
*widget
, VikLayerParam
*param
)
151 VikLayerParamData rv
;
152 switch ( param
->widget_type
)
154 case VIK_LAYER_WIDGET_COLOR
:
155 gtk_color_button_get_color ( GTK_COLOR_BUTTON(widget
), &(rv
.c
) );
157 case VIK_LAYER_WIDGET_CHECKBUTTON
:
158 rv
.b
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
));
160 case VIK_LAYER_WIDGET_COMBOBOX
:
162 rv
.i
= gtk_combo_box_get_active ( GTK_COMBO_BOX(widget
) );
163 if ( rv
.i
== -1 ) rv
.i
= 0;
165 if ( param
->extra_widget_data
)
166 rv
.u
= ((guint
*)param
->extra_widget_data
)[rv
.u
];
169 case VIK_LAYER_WIDGET_RADIOGROUP
:
170 case VIK_LAYER_WIDGET_RADIOGROUP_STATIC
:
171 rv
.u
= vik_radio_group_get_selected(VIK_RADIO_GROUP(widget
));
172 if ( param
->extra_widget_data
)
173 rv
.u
= (guint32
)g_list_nth_data(param
->extra_widget_data
, rv
.u
);
175 case VIK_LAYER_WIDGET_SPINBUTTON
:
176 if ( param
->type
== VIK_LAYER_PARAM_UINT
)
177 rv
.u
= gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON(widget
) );
178 else if ( param
->type
== VIK_LAYER_PARAM_INT
)
179 rv
.i
= gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON(widget
) );
181 rv
.d
= gtk_spin_button_get_value ( GTK_SPIN_BUTTON(widget
) );
183 case VIK_LAYER_WIDGET_ENTRY
:
184 rv
.s
= gtk_entry_get_text ( GTK_ENTRY(widget
) );
186 case VIK_LAYER_WIDGET_FILEENTRY
:
187 rv
.s
= vik_file_entry_get_filename ( VIK_FILE_ENTRY(widget
) );
189 case VIK_LAYER_WIDGET_FILELIST
:
190 rv
.sl
= vik_file_list_get_files ( VIK_FILE_LIST(widget
) );
192 case VIK_LAYER_WIDGET_HSCALE
:
193 if ( param
->type
== VIK_LAYER_PARAM_UINT
)
194 rv
.u
= (guint32
) gtk_range_get_value ( GTK_RANGE(widget
) );
195 else if ( param
->type
== VIK_LAYER_PARAM_INT
)
196 rv
.i
= (gint32
) gtk_range_get_value ( GTK_RANGE(widget
) );
198 rv
.d
= gtk_range_get_value ( GTK_RANGE(widget
) );
205 gint
a_uibuilder_properties_factory ( GtkWindow
*parent
, VikLayerParam
*params
,
206 guint16 params_count
, gchar
**groups
, guint8 groups_count
,
207 gboolean (*setparam
) (gpointer
,guint16
,VikLayerParamData
,gpointer
),
208 gpointer pass_along1
, gpointer pass_along2
,
209 VikLayerParamData (*getparam
) (gpointer
,guint16
),
210 gpointer pass_along_getparam
)
211 /* pass_along1 and pass_along2 are for set_param first and last params */
213 guint16 i
, j
, widget_count
= 0;
214 gboolean must_redraw
= FALSE
;
217 return 1; /* no params == no options, so all is good */
219 for ( i
= 0; i
< params_count
; i
++ )
220 if ( params
[i
].group
!= VIK_LAYER_NOT_IN_PROPERTIES
)
223 if ( widget_count
== 0)
224 return 0; /* TODO -- should be one? */
227 /* create widgets and titles; place in table */
228 GtkWidget
*dialog
= gtk_dialog_new_with_buttons ( "Layer Properties",
230 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
231 GTK_STOCK_CANCEL
, GTK_RESPONSE_REJECT
,
232 GTK_STOCK_OK
, GTK_RESPONSE_ACCEPT
, NULL
);
236 GtkWidget
*table
= NULL
;
237 GtkWidget
**tables
= NULL
; /* for more than one group */
239 GtkWidget
*notebook
= NULL
;
240 GtkWidget
**widgets
= g_malloc ( sizeof(GtkWidget
*) * widget_count
);
242 if ( groups
&& groups_count
> 1 )
244 guint8 current_group
;
245 guint16 tab_widget_count
;
246 notebook
= gtk_notebook_new ();
247 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog
)->vbox
), notebook
, FALSE
, FALSE
, 0);
248 tables
= g_malloc ( sizeof(GtkWidget
*) * groups_count
);
249 for ( current_group
= 0; current_group
< groups_count
; current_group
++ )
251 tab_widget_count
= 0;
252 for ( j
= 0; j
< params_count
; j
++ )
253 if ( params
[j
].group
== current_group
)
256 if ( tab_widget_count
)
258 tables
[current_group
] = gtk_table_new ( tab_widget_count
, 1, FALSE
);
259 gtk_notebook_append_page ( GTK_NOTEBOOK(notebook
), tables
[current_group
], gtk_label_new(groups
[current_group
]) );
265 table
= gtk_table_new( widget_count
, 1, FALSE
);
266 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog
)->vbox
), table
, FALSE
, FALSE
, 0);
269 for ( i
= 0, j
= 0; i
< params_count
; i
++ )
271 if ( params
[i
].group
!= VIK_LAYER_NOT_IN_PROPERTIES
)
274 table
= tables
[MAX(0, params
[i
].group
)]; /* round up NOT_IN_GROUP, that's not reasonable here */
276 widgets
[j
] = a_uibuilder_new_widget ( &(params
[i
]), getparam ( pass_along_getparam
, i
) );
278 g_assert ( widgets
[j
] != NULL
);
280 gtk_table_attach ( GTK_TABLE(table
), gtk_label_new(params
[i
].title
), 0, 1, j
, j
+1, 0, 0, 0, 0 );
281 gtk_table_attach ( GTK_TABLE(table
), widgets
[j
], 1, 2, j
, j
+1, GTK_EXPAND
| GTK_FILL
, 0, 2, 2 );
286 gtk_widget_show_all ( dialog
);
288 resp
= gtk_dialog_run (GTK_DIALOG (dialog
));
289 if ( resp
== GTK_RESPONSE_ACCEPT
)
291 for ( i
= 0, j
= 0; i
< params_count
; i
++ )
293 if ( params
[i
].group
!= VIK_LAYER_NOT_IN_PROPERTIES
)
295 if ( setparam ( pass_along1
, i
,
296 a_uibuilder_widget_get_value ( widgets
[j
], &(params
[i
]) ), pass_along2
) )
302 gtk_widget_destroy ( dialog
); /* hide before redrawing. */
305 return must_redraw
? 2 : 3; /* user clicked OK */
310 gtk_widget_destroy ( dialog
);
317 static void uibuilder_run_setparam ( VikLayerParamData
*paramdatas
, guint16 i
, VikLayerParamData data
, VikLayerParam
*params
)
319 /* could have to copy it if it's a string! */
320 switch ( params
[i
].type
) {
321 case VIK_LAYER_PARAM_STRING
:
322 paramdatas
[i
].s
= g_strdup ( data
.s
);
325 paramdatas
[i
] = data
; /* string list will have to be freed by layer. anything else not freed */
329 static VikLayerParamData
uibuilder_run_getparam ( VikLayerParamData
*params_defaults
, guint16 i
)
331 return params_defaults
[i
];
335 VikLayerParamData
*a_uibuilder_run_dialog ( GtkWindow
*parent
, VikLayerParam
*params
,
336 guint16 params_count
, gchar
**groups
, guint8 groups_count
,
337 VikLayerParamData
*params_defaults
)
339 VikLayerParamData
*paramdatas
= g_new(VikLayerParamData
, params_count
);
340 if ( a_uibuilder_properties_factory ( parent
, params
, params_count
, groups
, groups_count
,
341 uibuilder_run_setparam
, paramdatas
, params
,
342 uibuilder_run_getparam
, params_defaults
) > 0 ) {
346 g_free ( paramdatas
);
350 /* frees data from last (if ness) */
351 void a_uibuilder_free_paramdatas ( VikLayerParamData
*paramdatas
, VikLayerParam
*params
, guint16 params_count
)
354 /* may have to free strings, etc. */
355 for ( i
= 0; i
< params_count
; i
++ ) {
356 switch ( params
[i
].type
) {
357 case VIK_LAYER_PARAM_STRING
:
358 g_free ( (gchar
*) paramdatas
[i
].s
);
360 case VIK_LAYER_PARAM_STRING_LIST
: {
361 /* should make a util function out of this */
362 GList
*iter
= paramdatas
[i
].sl
;
364 g_free ( iter
->data
);
367 g_list_free ( paramdatas
[i
].sl
);
372 g_free ( paramdatas
);