2 * Dialog box for layout preferences
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (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, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include <epan/prefs.h>
33 #include "../ui_util.h"
35 #include "gtk/prefs_layout.h"
36 #include "gtk/gtkglobals.h"
37 #include "gtk/prefs_dlg.h"
38 #include "gtk/gui_utils.h"
40 #include "gtk/dlg_utils.h"
42 #include "../image/icon_layout_1.xpm"
43 #include "../image/icon_layout_2.xpm"
44 #include "../image/icon_layout_3.xpm"
45 #include "../image/icon_layout_4.xpm"
46 #include "../image/icon_layout_5.xpm"
47 #include "../image/icon_layout_6.xpm"
50 #define LAYOUT_QTY (layout_type_max - 1)
53 static void layout_validate_cb(GtkWidget *w _U_, gpointer data);
54 static gint fetch_enum_value(gpointer control, const enum_val_t *enumvals);
59 layout_pane_content_e content[3];
63 #define LAYOUT_TYPE_BUTTONS_KEY "layout_type_buttons"
65 #define LAYOUT_NONE_RB_KEY "layout_none_radio_button"
66 #define LAYOUT_PLIST_RB_KEY "layout_plist_radio_button"
67 #define LAYOUT_PDETAILS_RB_KEY "layout_pdetails_radio_button"
68 #define LAYOUT_PBYTES_RB_KEY "layout_pbytes_radio_button"
70 #define LAYOUT_CONTENT1_VB_KEY "layout_content1_vbox"
71 #define LAYOUT_CONTENT2_VB_KEY "layout_content2_vbox"
72 #define LAYOUT_CONTENT3_VB_KEY "layout_content3_vbox"
75 static GtkWidget *layout_content_radio_vbox(GtkWidget *main_vb, GtkTooltips *tooltips, int i, layout_pane_content_e content) {
76 GtkWidget *radio_vb, *radio_lb;
77 GtkWidget *radio_none_rb, *radio_plist_rb, *radio_pdetails_rb, *radio_pbytes_rb;
82 radio_vb = gtk_vbox_new(FALSE, 0);
83 gtk_container_set_border_width(GTK_CONTAINER(radio_vb), 6);
85 g_snprintf (buf, sizeof(buf), "Pane %d:", i);
86 radio_lb = gtk_label_new(buf);
87 gtk_misc_set_alignment(GTK_MISC(radio_lb), 0.0f, 0.5f);
88 gtk_container_add(GTK_CONTAINER(radio_vb), radio_lb);
90 radio_none_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "None");
91 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_none_rb), content == layout_pane_content_none);
92 gtk_tooltips_set_tip (tooltips, radio_none_rb, "Put nothing in this pane.", NULL);
93 gtk_container_add(GTK_CONTAINER(radio_vb), radio_none_rb);
95 radio_plist_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio_none_rb), "Packet List");
96 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_plist_rb), content == layout_pane_content_plist);
97 gtk_tooltips_set_tip (tooltips, radio_plist_rb, "Put the packet list in this pane.", NULL);
98 gtk_container_add(GTK_CONTAINER(radio_vb), radio_plist_rb);
100 radio_pdetails_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio_none_rb), "Packet Details");
101 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_pdetails_rb), content == layout_pane_content_pdetails);
102 gtk_tooltips_set_tip (tooltips, radio_pdetails_rb, "Put the packet details tree in this pane.", NULL);
103 gtk_container_add(GTK_CONTAINER(radio_vb), radio_pdetails_rb);
105 radio_pbytes_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio_none_rb), "Packet Bytes");
106 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_pbytes_rb), content == layout_pane_content_pbytes);
107 gtk_tooltips_set_tip (tooltips, radio_pbytes_rb, "Put the packet bytes dump in this pane.", NULL);
108 gtk_container_add(GTK_CONTAINER(radio_vb), radio_pbytes_rb);
110 g_object_set_data(G_OBJECT(radio_vb), LAYOUT_NONE_RB_KEY, radio_none_rb);
111 g_object_set_data(G_OBJECT(radio_vb), LAYOUT_PLIST_RB_KEY, radio_plist_rb);
112 g_object_set_data(G_OBJECT(radio_vb), LAYOUT_PDETAILS_RB_KEY, radio_pdetails_rb);
113 g_object_set_data(G_OBJECT(radio_vb), LAYOUT_PBYTES_RB_KEY, radio_pbytes_rb);
115 g_signal_connect(radio_none_rb, "toggled", G_CALLBACK(layout_validate_cb), main_vb);
116 g_signal_connect(radio_plist_rb, "toggled", G_CALLBACK(layout_validate_cb), main_vb);
117 g_signal_connect(radio_pdetails_rb, "toggled", G_CALLBACK(layout_validate_cb), main_vb);
118 g_signal_connect(radio_pbytes_rb, "toggled", G_CALLBACK(layout_validate_cb), main_vb);
124 layout_type_changed_cb (GtkToggleButton * togglebutton, gpointer user_data)
126 GtkWidget ** layout_type_buttons = (GtkWidget**) user_data;
127 static gboolean dampen_feedback_loop = FALSE;
129 if (!dampen_feedback_loop) {
131 dampen_feedback_loop = TRUE;
132 for (i=0; i<LAYOUT_QTY; ++i) {
133 GtkToggleButton * tb = GTK_TOGGLE_BUTTON(layout_type_buttons[i]);
134 gboolean active = togglebutton==tb;
135 if (gtk_toggle_button_get_active(tb) != active)
136 gtk_toggle_button_set_active (tb, active);
138 dampen_feedback_loop = FALSE;
143 static layout_pane_content_e layout_pane_get_content(GtkWidget * radio_vb) {
145 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(radio_vb), LAYOUT_NONE_RB_KEY))))
146 return layout_pane_content_none;
147 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(radio_vb), LAYOUT_PLIST_RB_KEY))))
148 return layout_pane_content_plist;
149 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(radio_vb), LAYOUT_PDETAILS_RB_KEY))))
150 return layout_pane_content_pdetails;
151 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(radio_vb), LAYOUT_PBYTES_RB_KEY))))
152 return layout_pane_content_pbytes;
154 g_assert_not_reached();
158 static void layout_pane_set_content(GtkWidget * radio_vb, layout_pane_content_e pane_content) {
161 switch(pane_content) {
162 case(layout_pane_content_none):
163 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(radio_vb), LAYOUT_NONE_RB_KEY)), TRUE);
165 case(layout_pane_content_plist):
166 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(radio_vb), LAYOUT_PLIST_RB_KEY)), TRUE);
168 case(layout_pane_content_pdetails):
169 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(radio_vb), LAYOUT_PDETAILS_RB_KEY)), TRUE);
171 case(layout_pane_content_pbytes):
172 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(radio_vb), LAYOUT_PBYTES_RB_KEY)), TRUE);
175 g_assert_not_reached();
181 static void layout_set(GtkWidget * main_vb, layout_t *layout) {
183 GtkWidget ** layout_type_buttons = g_object_get_data(G_OBJECT(main_vb), LAYOUT_TYPE_BUTTONS_KEY);
185 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(layout_type_buttons[layout->type - 1]), TRUE);
187 radio_vb = g_object_get_data(G_OBJECT(main_vb), LAYOUT_CONTENT1_VB_KEY);
188 layout_pane_set_content(radio_vb, layout->content[0]);
189 radio_vb = g_object_get_data(G_OBJECT(main_vb), LAYOUT_CONTENT2_VB_KEY);
190 layout_pane_set_content(radio_vb, layout->content[1]);
191 radio_vb = g_object_get_data(G_OBJECT(main_vb), LAYOUT_CONTENT3_VB_KEY);
192 layout_pane_set_content(radio_vb, layout->content[2]);
195 static void layout_get(GtkWidget * main_vb, layout_t *layout_out) {
197 GtkWidget ** layout_type_buttons = g_object_get_data(G_OBJECT(main_vb), LAYOUT_TYPE_BUTTONS_KEY);
200 for (i=0; i<LAYOUT_QTY; ++i) {
201 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(layout_type_buttons[i]))) {
202 layout_out->type = i + 1;
207 radio_vb = g_object_get_data(G_OBJECT(main_vb), LAYOUT_CONTENT1_VB_KEY);
208 layout_out->content[0] = layout_pane_get_content(radio_vb);
209 radio_vb = g_object_get_data(G_OBJECT(main_vb), LAYOUT_CONTENT2_VB_KEY);
210 layout_out->content[1] = layout_pane_get_content(radio_vb);
211 radio_vb = g_object_get_data(G_OBJECT(main_vb), LAYOUT_CONTENT3_VB_KEY);
212 layout_out->content[2] = layout_pane_get_content(radio_vb);
215 static void layout_validate(layout_t *layout) {
217 if(layout->content[1] == layout->content[0]) {
218 layout->content[1] = layout_pane_content_none;
220 if(layout->content[2] == layout->content[0] || layout->content[2] == layout->content[1]) {
221 layout->content[2] = layout_pane_content_none;
226 static void layout_validate_cb(GtkWidget *w _U_, gpointer data) {
229 layout_get(data, &layout);
230 layout_validate(&layout);
231 layout_set(data, &layout);
235 layout_defaults_cb (GtkWidget * w _U_, gpointer data)
237 layout_t default_layout = {
240 layout_pane_content_plist,
241 layout_pane_content_pdetails,
242 layout_pane_content_pbytes
246 layout_set(data, &default_layout);
249 #define SCROLLBAR_PLACEMENT_KEY "scrollbar_placement"
250 #define ALTERN_COLORS_KEY "altern_colors"
251 #define HEX_DUMP_HIGHLIGHT_STYLE_KEY "hex_dump_highlight_style"
252 #define FILTER_TOOLBAR_PLACEMENT_KEY "filter_toolbar_show_in_statusbar"
253 #define GUI_TOOLBAR_STYLE_KEY "toolbar_style"
254 #define GUI_FILTER_TOOLBAR_STYLE_KEY "filter_toolbar_style"
255 #define GUI_WINDOW_TITLE_KEY "window_title"
258 #define GUI_TABLE_ROWS 6
260 static const enum_val_t scrollbar_placement_vals[] = {
261 { "FALSE", "Left", FALSE },
262 { "TRUE", "Right", TRUE },
265 static const enum_val_t altern_colors_vals[] = {
266 { "FALSE", "No", FALSE },
267 { "TRUE", "Yes", TRUE },
270 static const enum_val_t highlight_style_vals[] = {
271 { "FALSE", "Bold", FALSE },
272 { "TRUE", "Inverse", TRUE },
275 static const enum_val_t filter_toolbar_placement_vals[] = {
276 { "FALSE", "Below the main toolbar", FALSE },
277 { "TRUE", "Insert into statusbar", TRUE },
280 static const enum_val_t toolbar_style_vals[] = {
281 { "ICONS", "Icons only", TB_STYLE_ICONS },
282 { "TEXT", "Text only", TB_STYLE_TEXT },
283 { "BOTH", "Icons & Text", TB_STYLE_BOTH },
288 layout_prefs_show(void)
290 GtkWidget *main_vb, *button_hb, *type_tb;
291 GtkWidget *pane_fr, *pane_vb;
292 GtkWidget *radio_hb, *radio_vb;
293 GtkWidget *default_vb, *default_bt;
294 GtkWidget *main_tb, *hbox;
295 GtkWidget *scrollbar_om;
296 GtkWidget *altern_colors_om;
297 GtkWidget *highlight_style_om;
298 GtkWidget *toolbar_style_om;
299 GtkWidget *filter_toolbar_style_om;
300 GtkWidget *filter_toolbar_placement_om;
301 GtkWidget *window_title_te;
303 GtkTooltips *tooltips = gtk_tooltips_new();
305 const char ** inline_txt [LAYOUT_QTY] = {
306 icon_layout_5_xpm, icon_layout_2_xpm, icon_layout_1_xpm,
307 icon_layout_4_xpm, icon_layout_3_xpm, icon_layout_6_xpm };
308 GtkWidget ** layout_type_buttons = g_malloc (sizeof(GtkWidget*) * LAYOUT_QTY);
314 /* main vertical box */
315 main_vb = gtk_vbox_new(FALSE, 7);
316 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
319 pane_fr = gtk_frame_new("Panes");
320 gtk_box_pack_start(GTK_BOX(main_vb), pane_fr, FALSE, FALSE, 0);
321 gtk_widget_show(pane_fr);
323 /* pane vertical box */
324 pane_vb = gtk_vbox_new(FALSE, 7);
325 gtk_container_set_border_width(GTK_CONTAINER(pane_vb), 5);
326 gtk_container_add(GTK_CONTAINER(pane_fr), pane_vb);
327 gtk_widget_show(pane_vb);
330 button_hb = gtk_hbox_new(FALSE, 0);
331 gtk_container_set_border_width(GTK_CONTAINER(button_hb), 6);
332 gtk_box_pack_start (GTK_BOX(pane_vb), button_hb, FALSE, FALSE, 0);
335 for (i=0; i<LAYOUT_QTY; ++i)
337 type_tb = gtk_toggle_button_new ();
338 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(type_tb),
339 (layout_type_e)(i + 1) == prefs.gui_layout_type);
341 gtk_container_add (GTK_CONTAINER(type_tb), xpm_to_widget(inline_txt[i]));
343 g_signal_connect(type_tb, "toggled", G_CALLBACK(layout_type_changed_cb), layout_type_buttons);
344 layout_type_buttons[i] = type_tb;
345 gtk_box_pack_start (GTK_BOX(button_hb), type_tb, TRUE, FALSE, 0);
348 g_object_set_data(G_OBJECT(main_vb), LAYOUT_TYPE_BUTTONS_KEY, layout_type_buttons);
351 radio_hb = gtk_hbox_new(FALSE, 0);
352 gtk_container_set_border_width(GTK_CONTAINER(radio_hb), 6);
353 gtk_box_pack_start (GTK_BOX(pane_vb), radio_hb, FALSE, FALSE, 0);
355 radio_vb = layout_content_radio_vbox(main_vb, tooltips, 1, prefs.gui_layout_content_1);
356 gtk_container_set_border_width(GTK_CONTAINER(radio_vb), 6);
357 gtk_box_pack_start (GTK_BOX(radio_hb), radio_vb, FALSE, FALSE, 0);
358 g_object_set_data(G_OBJECT(main_vb), LAYOUT_CONTENT1_VB_KEY, radio_vb);
360 radio_vb = layout_content_radio_vbox(main_vb, tooltips, 2, prefs.gui_layout_content_2);
361 gtk_container_set_border_width(GTK_CONTAINER(radio_vb), 6);
362 gtk_box_pack_start (GTK_BOX(radio_hb), radio_vb, FALSE, FALSE, 0);
363 g_object_set_data(G_OBJECT(main_vb), LAYOUT_CONTENT2_VB_KEY, radio_vb);
365 radio_vb = layout_content_radio_vbox(main_vb, tooltips, 3, prefs.gui_layout_content_3);
366 gtk_container_set_border_width(GTK_CONTAINER(radio_vb), 6);
367 gtk_box_pack_start (GTK_BOX(radio_hb), radio_vb, FALSE, FALSE, 0);
368 g_object_set_data(G_OBJECT(main_vb), LAYOUT_CONTENT3_VB_KEY, radio_vb);
370 default_vb = gtk_vbox_new(FALSE, 0);
371 default_bt = gtk_button_new_with_label("Default panes");
372 gtk_tooltips_set_tip (tooltips, default_bt,
373 "Reset the pane layout settings to default values.", NULL);
374 g_signal_connect(default_bt, "clicked", G_CALLBACK(layout_defaults_cb), main_vb);
375 gtk_box_pack_end(GTK_BOX(default_vb), default_bt, FALSE, FALSE, 0);
376 gtk_box_pack_end(GTK_BOX(radio_hb), default_vb, FALSE, FALSE, 0);
378 /* Main horizontal box */
379 /* XXX - Is there a better way to center the table? */
380 hbox = gtk_hbox_new(FALSE, 7);
381 gtk_box_pack_start (GTK_BOX(main_vb), hbox, TRUE, FALSE, 0);
384 main_tb = gtk_table_new(GUI_TABLE_ROWS, 2, FALSE);
385 gtk_box_pack_start( GTK_BOX(hbox), main_tb, FALSE, FALSE, 0 );
386 gtk_table_set_row_spacings( GTK_TABLE(main_tb), 10 );
387 gtk_table_set_col_spacings( GTK_TABLE(main_tb), 15 );
388 g_object_set_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY, tooltips);
390 /* Scrollbar placement */
391 scrollbar_om = create_preference_option_menu(main_tb, pos++,
392 "Vertical scrollbar placement:",
393 "Select where the vertical scrollbar will be displayed in the panes.",
394 scrollbar_placement_vals, prefs.gui_scrollbar_on_right);
395 g_object_set_data(G_OBJECT(main_vb), SCROLLBAR_PLACEMENT_KEY, scrollbar_om);
397 /* Alternating row colors in list and tree views */
398 altern_colors_om = create_preference_option_menu(main_tb, pos++,
399 "Alternating row colors in lists and trees:",
400 "Select whether or not the rows of lists and trees have alternating color.",
401 altern_colors_vals, prefs.gui_altern_colors);
402 g_object_set_data(G_OBJECT(main_vb), ALTERN_COLORS_KEY, altern_colors_om);
404 /* Packet Bytes Dump highlight style */
405 highlight_style_om = create_preference_option_menu(main_tb, pos++,
406 "Packet bytes highlight style:",
407 "Select the style in which the packet bytes dump will be displayed.",
408 highlight_style_vals, prefs.gui_hex_dump_highlight_style);
409 g_object_set_data(G_OBJECT(main_vb), HEX_DUMP_HIGHLIGHT_STYLE_KEY, highlight_style_om);
412 toolbar_style_om = create_preference_option_menu(main_tb, pos++,
414 "Select the style in which the toolbar will be displayed.",
415 toolbar_style_vals, prefs.gui_toolbar_main_style);
416 g_object_set_data(G_OBJECT(main_vb), GUI_TOOLBAR_STYLE_KEY, toolbar_style_om);
418 /* Filter toolbar prefs */
419 filter_toolbar_style_om = create_preference_option_menu(main_tb, pos++,
420 "Filter toolbar style:",
421 "Select the style in which the filter toolbar will be displayed.",
422 toolbar_style_vals, prefs.gui_toolbar_filter_style);
423 g_object_set_data(G_OBJECT(main_vb), GUI_FILTER_TOOLBAR_STYLE_KEY, filter_toolbar_style_om);
425 /* Placement of Filter toolbar */
426 filter_toolbar_placement_om = create_preference_option_menu(main_tb, pos++,
427 "Filter toolbar placement:",
428 "Select where the filter toolbar will be displayed.",
429 filter_toolbar_placement_vals, prefs.filter_toolbar_show_in_statusbar);
430 g_object_set_data(G_OBJECT(main_vb), FILTER_TOOLBAR_PLACEMENT_KEY, filter_toolbar_placement_om);
433 window_title_te = create_preference_entry(main_tb, pos++,
434 "Custom window title (appended to existing titles):",
435 "Enter the text to be appended to the window title.",
436 prefs.gui_window_title);
437 gtk_entry_set_text(GTK_ENTRY(window_title_te), prefs.gui_window_title);
438 g_object_set_data(G_OBJECT(main_vb), GUI_WINDOW_TITLE_KEY, window_title_te);
440 /* Show 'em what we got */
441 gtk_widget_show_all(main_vb);
447 fetch_enum_value(gpointer control, const enum_val_t *enumvals)
449 return fetch_preference_option_menu_val(GTK_WIDGET(control), enumvals);
453 layout_prefs_fetch(GtkWidget *w)
455 layout_t layout_fetched;
457 layout_get(w, &layout_fetched);
459 prefs.gui_layout_type = layout_fetched.type;
460 prefs.gui_layout_content_1 = layout_fetched.content[0];
461 prefs.gui_layout_content_2 = layout_fetched.content[1];
462 prefs.gui_layout_content_3 = layout_fetched.content[2];
464 prefs.gui_scrollbar_on_right = fetch_enum_value(
465 g_object_get_data(G_OBJECT(w), SCROLLBAR_PLACEMENT_KEY),
466 scrollbar_placement_vals);
468 prefs.gui_altern_colors = fetch_enum_value(
469 g_object_get_data(G_OBJECT(w), ALTERN_COLORS_KEY), altern_colors_vals);
470 prefs.filter_toolbar_show_in_statusbar = fetch_enum_value(
471 g_object_get_data(G_OBJECT(w), FILTER_TOOLBAR_PLACEMENT_KEY), filter_toolbar_placement_vals);
472 prefs.gui_hex_dump_highlight_style = fetch_enum_value(
473 g_object_get_data(G_OBJECT(w), HEX_DUMP_HIGHLIGHT_STYLE_KEY), highlight_style_vals);
474 prefs.gui_toolbar_main_style = fetch_enum_value(
475 g_object_get_data(G_OBJECT(w), GUI_TOOLBAR_STYLE_KEY), toolbar_style_vals);
476 prefs.gui_toolbar_filter_style = fetch_enum_value(
477 g_object_get_data(G_OBJECT(w), GUI_FILTER_TOOLBAR_STYLE_KEY), toolbar_style_vals);
479 g_free(prefs.gui_window_title);
480 prefs.gui_window_title = g_strdup(gtk_entry_get_text(
481 GTK_ENTRY(g_object_get_data(G_OBJECT(w), GUI_WINDOW_TITLE_KEY))));
485 layout_prefs_apply(GtkWidget *w _U_)
487 update_main_window_title();
488 main_widgets_rearrange();
492 layout_prefs_destroy(GtkWidget *main_vb)
494 GtkWidget ** layout_type_buttons = g_object_get_data(G_OBJECT(main_vb), LAYOUT_TYPE_BUTTONS_KEY);
496 g_free(layout_type_buttons);