"ssn_range" needs to be a copy of "global_ssn_range", so that it's not
[obnox/wireshark/wip.git] / gtk / layout_prefs.c
1 /* layout_prefs.c
2  * Dialog box for layout preferences
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <gtk/gtk.h>
30
31 #include "globals.h"
32 #include "layout_prefs.h"
33 #include "gtkglobals.h"
34 /*#include <epan/resolv.h>*/
35 #include <epan/prefs.h>
36 /*#include "prefs_dlg.h"*/
37 #include "ui_util.h"
38 #include "main.h"
39 #include "compat_macros.h"
40 #include "dlg_utils.h"
41
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"
48
49 #define LAYOUT_QTY (layout_type_max - 1)
50
51
52 static void layout_validate_cb(GtkWidget *w _U_, gpointer data);
53
54
55
56 typedef struct {
57     layout_type_e           type;
58     layout_pane_content_e   content[3];
59 } layout_t;
60
61
62 #define LAYOUT_TYPE_BUTTONS_KEY     "layout_type_buttons"
63
64 #define LAYOUT_NONE_RB_KEY          "layout_none_radio_button"
65 #define LAYOUT_PLIST_RB_KEY         "layout_plist_radio_button"
66 #define LAYOUT_PDETAILS_RB_KEY      "layout_pdetails_radio_button"
67 #define LAYOUT_PBYTES_RB_KEY        "layout_pbytes_radio_button"
68
69 #define LAYOUT_CONTENT1_VB_KEY      "layout_content1_vbox"
70 #define LAYOUT_CONTENT2_VB_KEY      "layout_content2_vbox"
71 #define LAYOUT_CONTENT3_VB_KEY      "layout_content3_vbox"
72
73
74 static GtkWidget *layout_content_radio_vbox(GtkWidget *main_vb, GtkTooltips *tooltips, int i, layout_pane_content_e content) {
75     GtkWidget   *radio_vb, *radio_lb;
76     GtkWidget   *radio_none_rb, *radio_plist_rb, *radio_pdetails_rb, *radio_pbytes_rb;
77     char buf[64];
78
79
80     /* radio vbox */
81     radio_vb = gtk_vbox_new(FALSE, 0);
82     gtk_container_set_border_width(GTK_CONTAINER(radio_vb), 6);
83
84     g_snprintf (buf, sizeof(buf), "Pane %d:", i);
85     radio_lb = gtk_label_new(buf);
86     gtk_misc_set_alignment(GTK_MISC(radio_lb), 0.0, 0.5);
87     gtk_container_add(GTK_CONTAINER(radio_vb), radio_lb);
88
89     radio_none_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "None", NULL);
90     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(radio_none_rb), content == layout_pane_content_none);
91     gtk_tooltips_set_tip (tooltips, radio_none_rb, "Put nothing in this pane.", NULL);
92     gtk_container_add(GTK_CONTAINER(radio_vb), radio_none_rb);
93
94     radio_plist_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(radio_none_rb, "Packet List", NULL);
95     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(radio_plist_rb), content == layout_pane_content_plist);
96     gtk_tooltips_set_tip (tooltips, radio_plist_rb, "Put the packet list in this pane.", NULL);
97     gtk_container_add(GTK_CONTAINER(radio_vb), radio_plist_rb);
98
99     radio_pdetails_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(radio_none_rb, "Packet Details", NULL);
100     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(radio_pdetails_rb), content == layout_pane_content_pdetails);
101     gtk_tooltips_set_tip (tooltips, radio_pdetails_rb, "Put the packet details tree in this pane.", NULL);
102     gtk_container_add(GTK_CONTAINER(radio_vb), radio_pdetails_rb);
103
104     radio_pbytes_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(radio_none_rb, "Packet Bytes", NULL);
105     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(radio_pbytes_rb), content == layout_pane_content_pbytes);
106     gtk_tooltips_set_tip (tooltips, radio_pbytes_rb, "Put the packet bytes hexdump in this pane.", NULL);
107     gtk_container_add(GTK_CONTAINER(radio_vb), radio_pbytes_rb);
108
109     OBJECT_SET_DATA(radio_vb, LAYOUT_NONE_RB_KEY,       radio_none_rb);
110     OBJECT_SET_DATA(radio_vb, LAYOUT_PLIST_RB_KEY,      radio_plist_rb);
111     OBJECT_SET_DATA(radio_vb, LAYOUT_PDETAILS_RB_KEY,   radio_pdetails_rb);
112     OBJECT_SET_DATA(radio_vb, LAYOUT_PBYTES_RB_KEY,     radio_pbytes_rb);
113
114     SIGNAL_CONNECT(radio_none_rb,       "toggled", layout_validate_cb, main_vb);
115     SIGNAL_CONNECT(radio_plist_rb,      "toggled", layout_validate_cb, main_vb);
116     SIGNAL_CONNECT(radio_pdetails_rb,   "toggled", layout_validate_cb, main_vb);
117     SIGNAL_CONNECT(radio_pbytes_rb,     "toggled", layout_validate_cb, main_vb);
118
119     return radio_vb;
120 }
121
122 static void
123 layout_type_changed_cb (GtkToggleButton * togglebutton, gpointer user_data)
124 {
125         GtkWidget ** layout_type_buttons = (GtkWidget**) user_data;
126         static gboolean dampen_feedback_loop = FALSE;
127
128         if (!dampen_feedback_loop) {
129                 int i;
130                 dampen_feedback_loop = TRUE;
131                 for (i=0; i<LAYOUT_QTY; ++i) {
132                         GtkToggleButton * tb = GTK_TOGGLE_BUTTON(layout_type_buttons[i]);
133                         gboolean active = togglebutton==tb;
134                         if (gtk_toggle_button_get_active(tb) != active)
135                                 gtk_toggle_button_set_active (tb, active);
136                 }
137                 dampen_feedback_loop = FALSE;
138         }
139 }
140
141
142 static layout_pane_content_e  layout_pane_get_content(GtkWidget * radio_vb) {
143
144     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_NONE_RB_KEY))))
145         return layout_pane_content_none;
146     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_PLIST_RB_KEY))))
147         return layout_pane_content_plist;
148     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_PDETAILS_RB_KEY))))
149         return layout_pane_content_pdetails;
150     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_PBYTES_RB_KEY))))
151         return layout_pane_content_pbytes;
152
153     g_assert_not_reached();
154     return -1;
155 }
156
157 static void layout_pane_set_content(GtkWidget * radio_vb, layout_pane_content_e pane_content) {
158
159
160     switch(pane_content) {
161     case(layout_pane_content_none):
162         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_NONE_RB_KEY)), TRUE);
163         break;
164     case(layout_pane_content_plist):
165         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_PLIST_RB_KEY)), TRUE);
166         break;
167     case(layout_pane_content_pdetails):
168         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_PDETAILS_RB_KEY)), TRUE);
169         break;
170     case(layout_pane_content_pbytes):
171         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(OBJECT_GET_DATA(radio_vb, LAYOUT_PBYTES_RB_KEY)), TRUE);
172         break;
173     default:
174         g_assert_not_reached();
175     }
176 }
177
178
179
180 static void layout_set(GtkWidget * main_vb, layout_t *layout) {
181     GtkWidget   *radio_vb;
182     GtkWidget ** layout_type_buttons = OBJECT_GET_DATA(main_vb, LAYOUT_TYPE_BUTTONS_KEY);
183
184     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(layout_type_buttons[layout->type - 1]), TRUE);
185
186     radio_vb = OBJECT_GET_DATA(main_vb, LAYOUT_CONTENT1_VB_KEY);
187     layout_pane_set_content(radio_vb, layout->content[0]);
188     radio_vb = OBJECT_GET_DATA(main_vb, LAYOUT_CONTENT2_VB_KEY);
189     layout_pane_set_content(radio_vb, layout->content[1]);
190     radio_vb = OBJECT_GET_DATA(main_vb, LAYOUT_CONTENT3_VB_KEY);
191     layout_pane_set_content(radio_vb, layout->content[2]);
192 }
193
194 static void layout_get(GtkWidget * main_vb, layout_t *layout_out) {
195     GtkWidget   *radio_vb;
196     GtkWidget ** layout_type_buttons = OBJECT_GET_DATA(main_vb, LAYOUT_TYPE_BUTTONS_KEY);
197     int i;
198
199     for (i=0; i<LAYOUT_QTY; ++i) {
200         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(layout_type_buttons[i]))) {
201             layout_out->type = i + 1;
202             break;
203         }
204     }
205
206     radio_vb = OBJECT_GET_DATA(main_vb, LAYOUT_CONTENT1_VB_KEY);
207     layout_out->content[0] = layout_pane_get_content(radio_vb);
208     radio_vb = OBJECT_GET_DATA(main_vb, LAYOUT_CONTENT2_VB_KEY);
209     layout_out->content[1] = layout_pane_get_content(radio_vb);
210     radio_vb = OBJECT_GET_DATA(main_vb, LAYOUT_CONTENT3_VB_KEY);
211     layout_out->content[2] = layout_pane_get_content(radio_vb);
212 }
213
214 static void layout_validate(layout_t *layout) {
215
216     if(layout->content[1] == layout->content[0]) {
217         layout->content[1] = layout_pane_content_none;
218     }
219     if(layout->content[2] == layout->content[0] || layout->content[2] == layout->content[1]) {
220         layout->content[2] = layout_pane_content_none;
221     }
222 }
223
224
225 static void layout_validate_cb(GtkWidget *w _U_, gpointer data) {
226     layout_t    layout;
227
228     layout_get(data, &layout);
229     layout_validate(&layout);
230     layout_set(data, &layout);
231 }
232
233 static void
234 layout_defaults_cb (GtkWidget * w _U_, gpointer data _U_)
235 {
236     layout_t default_layout = { 
237         layout_type_5,
238         {
239             layout_pane_content_plist,
240             layout_pane_content_pdetails,
241             layout_pane_content_pbytes
242         }
243     };
244
245     layout_set(data, &default_layout);
246 }
247
248
249 GtkWidget*
250 layout_prefs_show(void)
251 {
252 #if GTK_MAJOR_VERSION < 2
253     GtkAccelGroup *accel_group;
254 #endif
255     GtkTooltips   *tooltips;
256
257     GtkWidget   *main_vb, *button_hb, *type_tb;
258     GtkWidget   *radio_hb, *radio_vb;
259     GtkWidget   *default_vb, *default_bt;
260
261     const char ** inline_txt [LAYOUT_QTY] = {
262                 icon_layout_5_xpm, icon_layout_2_xpm, icon_layout_1_xpm,
263                 icon_layout_4_xpm, icon_layout_3_xpm, icon_layout_6_xpm };
264     GtkWidget ** layout_type_buttons = g_malloc (sizeof(GtkWidget*) * LAYOUT_QTY);
265
266     int i;
267
268
269     /* main vertical box */
270     main_vb = gtk_vbox_new(FALSE, 7);
271     gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
272
273 #if GTK_MAJOR_VERSION < 2
274     /* Accelerator group for the accelerators (or, as they're called in
275      Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
276      Ctrl+<key> is an accelerator). */
277     accel_group = gtk_accel_group_new();
278     /*gtk_window_add_accel_group(GTK_WINDOW(main_win), accel_group);*/
279 #endif
280
281     /* Enable tooltips */
282     tooltips = gtk_tooltips_new();
283
284
285     /* button hbox */
286     button_hb = gtk_hbox_new(FALSE, 0);
287     gtk_container_set_border_width(GTK_CONTAINER(button_hb), 6);
288     gtk_box_pack_start (GTK_BOX(main_vb), button_hb, FALSE, FALSE, 0);
289
290     /* pane layout */
291     for (i=0; i<LAYOUT_QTY; ++i)
292     {
293         type_tb = gtk_toggle_button_new ();
294         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(type_tb),
295             (layout_type_e)(i + 1) == prefs.gui_layout_type);
296
297         gtk_container_add (GTK_CONTAINER(type_tb), xpm_to_widget(inline_txt[i]));
298
299         SIGNAL_CONNECT(type_tb, "toggled", layout_type_changed_cb, layout_type_buttons);
300         layout_type_buttons[i] = type_tb;
301         gtk_box_pack_start (GTK_BOX(button_hb), type_tb, TRUE, FALSE, 0);
302     }
303
304     OBJECT_SET_DATA(main_vb, LAYOUT_TYPE_BUTTONS_KEY, layout_type_buttons);
305
306     /* radio hbox */
307     radio_hb = gtk_hbox_new(FALSE, 0);
308     gtk_container_set_border_width(GTK_CONTAINER(radio_hb), 6);
309     gtk_box_pack_start (GTK_BOX(main_vb), radio_hb, FALSE, FALSE, 0);
310
311     radio_vb = layout_content_radio_vbox(main_vb, tooltips, 1, prefs.gui_layout_content_1);
312     gtk_container_set_border_width(GTK_CONTAINER(radio_vb), 6);
313     gtk_box_pack_start (GTK_BOX(radio_hb), radio_vb, FALSE, FALSE, 0);
314     OBJECT_SET_DATA(main_vb, LAYOUT_CONTENT1_VB_KEY, radio_vb);
315
316     radio_vb = layout_content_radio_vbox(main_vb, tooltips, 2, prefs.gui_layout_content_2);
317     gtk_container_set_border_width(GTK_CONTAINER(radio_vb), 6);
318     gtk_box_pack_start (GTK_BOX(radio_hb), radio_vb, FALSE, FALSE, 0);
319     OBJECT_SET_DATA(main_vb, LAYOUT_CONTENT2_VB_KEY, radio_vb);
320
321     radio_vb = layout_content_radio_vbox(main_vb, tooltips, 3, prefs.gui_layout_content_3);
322     gtk_container_set_border_width(GTK_CONTAINER(radio_vb), 6);
323     gtk_box_pack_start (GTK_BOX(radio_hb), radio_vb, FALSE, FALSE, 0);
324     OBJECT_SET_DATA(main_vb, LAYOUT_CONTENT3_VB_KEY, radio_vb);
325
326     default_vb = gtk_vbox_new(FALSE, 0);
327     default_bt = gtk_button_new_with_label("Defaults");
328     gtk_tooltips_set_tip (tooltips, default_bt, "Reset the pane layout settings to default values.", NULL);
329     SIGNAL_CONNECT(default_bt, "clicked", layout_defaults_cb, main_vb);
330     gtk_box_pack_end(GTK_BOX(default_vb), default_bt, FALSE, FALSE, 0);
331     gtk_box_pack_end(GTK_BOX(radio_hb), default_vb, FALSE, FALSE, 0);
332
333     /* Show 'em what we got */
334     gtk_widget_show_all(main_vb);
335
336     return(main_vb);
337 }
338
339 void
340 layout_prefs_fetch(GtkWidget *w)
341 {
342     layout_t layout_fetched;
343
344     layout_get(w, &layout_fetched);
345
346     prefs.gui_layout_type = layout_fetched.type;
347     prefs.gui_layout_content_1 = layout_fetched.content[0];
348     prefs.gui_layout_content_2 = layout_fetched.content[1];
349     prefs.gui_layout_content_3 = layout_fetched.content[2];
350 }
351
352 void
353 layout_prefs_apply(GtkWidget *w _U_)
354 {
355     main_widgets_rearrange();
356 }
357
358 void
359 layout_prefs_destroy(GtkWidget *main_vb)
360 {
361     GtkWidget ** layout_type_buttons = OBJECT_GET_DATA(main_vb, LAYOUT_TYPE_BUTTONS_KEY);
362
363     g_free(layout_type_buttons);
364 }
365