]> Pileus Git - ~andy/gtk/blob - demos/gtk-demo/appwindow.c
Hide the resize grip when maximized or fullscreen.
[~andy/gtk] / demos / gtk-demo / appwindow.c
1 /* Application main window
2  *
3  * Demonstrates a typical application window, with menubar, toolbar, statusbar.
4  */
5
6 #include <gtk/gtk.h>
7 #include "demo-common.h"
8
9 static GtkWidget *window = NULL;
10
11
12 static void
13 menuitem_cb (gpointer             callback_data,
14              guint                callback_action,
15              GtkWidget           *widget)
16 {
17   GtkWidget *dialog;
18   
19   dialog = gtk_message_dialog_new (GTK_WINDOW (callback_data),
20                                    GTK_DIALOG_DESTROY_WITH_PARENT,
21                                    GTK_MESSAGE_INFO,
22                                    GTK_BUTTONS_CLOSE,
23                                    "You selected or toggled the menu item: \"%s\"",
24                                     gtk_item_factory_path_from_widget (widget));
25
26   /* Close dialog on user response */
27   g_signal_connect (dialog,
28                     "response",
29                     G_CALLBACK (gtk_widget_destroy),
30                     NULL);
31   
32   gtk_widget_show (dialog);
33 }
34
35
36 static GtkItemFactoryEntry menu_items[] =
37 {
38   { "/_File",            NULL,         0,                     0, "<Branch>" },
39   { "/File/_New",        "<control>N", menuitem_cb,       0, "<StockItem>", GTK_STOCK_NEW },
40   { "/File/_Open",       "<control>O", menuitem_cb,       0, "<StockItem>", GTK_STOCK_OPEN },
41   { "/File/_Save",       "<control>S", menuitem_cb,       0, "<StockItem>", GTK_STOCK_SAVE },
42   { "/File/Save _As...", NULL,         menuitem_cb,       0, "<StockItem>", GTK_STOCK_SAVE },
43   { "/File/sep1",        NULL,         menuitem_cb,       0, "<Separator>" },
44   { "/File/_Quit",       "<control>Q", menuitem_cb,       0, "<StockItem>", GTK_STOCK_QUIT },
45
46   { "/_Preferences",                    NULL, 0,               0, "<Branch>" },
47   { "/_Preferences/_Color",             NULL, 0,               0, "<Branch>" },
48   { "/_Preferences/Color/_Red",         NULL, menuitem_cb, 0, "<RadioItem>" },
49   { "/_Preferences/Color/_Green",       NULL, menuitem_cb, 0, "/Preferences/Color/Red" },
50   { "/_Preferences/Color/_Blue",        NULL, menuitem_cb, 0, "/Preferences/Color/Red" },
51   { "/_Preferences/_Shape",             NULL, 0,               0, "<Branch>" },
52   { "/_Preferences/Shape/_Square",      NULL, menuitem_cb, 0, "<RadioItem>" },
53   { "/_Preferences/Shape/_Rectangle",   NULL, menuitem_cb, 0, "/Preferences/Shape/Square" },
54   { "/_Preferences/Shape/_Oval",        NULL, menuitem_cb, 0, "/Preferences/Shape/Rectangle" },
55
56   /* If you wanted this to be right justified you would use "<LastBranch>", not "<Branch>".
57    * Right justified help menu items are generally considered a bad idea now days.
58    */
59   { "/_Help",            NULL,         0,                     0, "<Branch>" },
60   { "/Help/_About",      NULL,         menuitem_cb,       0 },
61 };
62
63 static void
64 toolbar_cb (GtkWidget *button,
65             gpointer   data)
66 {
67   GtkWidget *dialog;
68   
69   dialog = gtk_message_dialog_new (GTK_WINDOW (data),
70                                    GTK_DIALOG_DESTROY_WITH_PARENT,
71                                    GTK_MESSAGE_INFO,
72                                    GTK_BUTTONS_CLOSE,
73                                    "You selected a toolbar button");
74
75   /* Close dialog on user response */
76   g_signal_connect (dialog,
77                     "response",
78                     G_CALLBACK (gtk_widget_destroy),
79                     NULL);
80   
81   gtk_widget_show (dialog);
82 }
83
84 /* This function registers our custom toolbar icons, so they can be themed.
85  *
86  * It's totally optional to do this, you could just manually insert icons
87  * and have them not be themeable, especially if you never expect people
88  * to theme your app.
89  */
90 static void
91 register_stock_icons (void)
92 {
93   static gboolean registered = FALSE;
94   
95   if (!registered)
96     {
97       GdkPixbuf *pixbuf;
98       GtkIconFactory *factory;
99       char *filename;
100
101       static GtkStockItem items[] = {
102         { "demo-gtk-logo",
103           "_GTK!",
104           0, 0, NULL }
105       };
106       
107       registered = TRUE;
108
109       /* Register our stock items */
110       gtk_stock_add (items, G_N_ELEMENTS (items));
111       
112       /* Add our custom icon factory to the list of defaults */
113       factory = gtk_icon_factory_new ();
114       gtk_icon_factory_add_default (factory);
115
116       /* demo_find_file() looks in the the current directory first,
117        * so you can run gtk-demo without installing GTK, then looks
118        * in the location where the file is installed.
119        */
120       pixbuf = NULL;
121       filename = demo_find_file ("gtk-logo-rgb.gif", NULL);
122       if (filename)
123         {
124           pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
125           g_free (filename);
126         }
127
128       /* Register icon to accompany stock item */
129       if (pixbuf != NULL)
130         {
131           GtkIconSet *icon_set;
132           GdkPixbuf *transparent;
133
134           /* The gtk-logo-rgb icon has a white background, make it transparent */
135           transparent = gdk_pixbuf_add_alpha (pixbuf, TRUE, 0xff, 0xff, 0xff);
136           
137           icon_set = gtk_icon_set_new_from_pixbuf (transparent);
138           gtk_icon_factory_add (factory, "demo-gtk-logo", icon_set);
139           gtk_icon_set_unref (icon_set);
140           g_object_unref (pixbuf);
141           g_object_unref (transparent);
142         }
143       else
144         g_warning ("failed to load GTK logo for toolbar");
145       
146       /* Drop our reference to the factory, GTK will hold a reference. */
147       g_object_unref (factory);
148     }
149 }
150
151 static void
152 update_statusbar (GtkTextBuffer *buffer,
153                   GtkStatusbar  *statusbar)
154 {
155   gchar *msg;
156   gint row, col;
157   gint count;
158   GtkTextIter iter;
159   
160   gtk_statusbar_pop (statusbar, 0); /* clear any previous message, underflow is allowed */
161
162   count = gtk_text_buffer_get_char_count (buffer);
163
164   gtk_text_buffer_get_iter_at_mark (buffer,
165                                     &iter,
166                                     gtk_text_buffer_get_insert (buffer));
167
168   row = gtk_text_iter_get_line (&iter);
169   col = gtk_text_iter_get_line_offset (&iter);
170
171   msg = g_strdup_printf ("Cursor at row %d column %d - %d chars in document",
172                          row, col, count);
173
174   gtk_statusbar_push (statusbar, 0, msg);
175
176   g_free (msg);
177 }
178
179 static void
180 mark_set_callback (GtkTextBuffer     *buffer,
181                    const GtkTextIter *new_location,
182                    GtkTextMark       *mark,
183                    gpointer           data)
184 {
185   update_statusbar (buffer, GTK_STATUSBAR (data));
186 }
187
188 static void
189 update_resize_grip (GtkWidget           *widget,
190                     GdkEventWindowState *event,
191                     GtkStatusbar        *statusbar)
192 {
193   if (event->changed_mask & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN))
194     gtk_statusbar_set_has_resize_grip (statusbar, !(event->new_window_state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)));
195 }
196                     
197
198 GtkWidget *
199 do_appwindow (void)
200 {  
201   if (!window)
202     {
203       GtkWidget *table;
204       GtkWidget *toolbar;
205       GtkWidget *statusbar;
206       GtkWidget *contents;
207       GtkWidget *sw;
208       GtkTextBuffer *buffer;
209       GtkAccelGroup *accel_group;      
210       GtkItemFactory *item_factory;
211
212       register_stock_icons ();
213       
214       /* Create the toplevel window
215        */
216       
217       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
218       gtk_window_set_title (GTK_WINDOW (window), "Application Window");
219
220       /* NULL window variable when window is closed */
221       g_signal_connect (window, "destroy",
222                         G_CALLBACK (gtk_widget_destroyed),
223                         &window);
224
225       table = gtk_table_new (1, 4, FALSE);
226       
227       gtk_container_add (GTK_CONTAINER (window), table);
228       
229       /* Create the menubar
230        */
231       
232       accel_group = gtk_accel_group_new ();
233       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
234       g_object_unref (accel_group);
235       
236       item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group);
237
238       /* Set up item factory to go away with the window */
239       g_object_ref (item_factory);
240       gtk_object_sink (GTK_OBJECT (item_factory));
241       g_object_set_data_full (G_OBJECT (window),
242                               "<main>",
243                               item_factory,
244                               (GDestroyNotify) g_object_unref);
245
246       /* create menu items */
247       gtk_item_factory_create_items (item_factory, G_N_ELEMENTS (menu_items),
248                                      menu_items, window);
249
250       gtk_table_attach (GTK_TABLE (table),
251                         gtk_item_factory_get_widget (item_factory, "<main>"),
252                         /* X direction */          /* Y direction */
253                         0, 1,                      0, 1,
254                         GTK_EXPAND | GTK_FILL,     0,
255                         0,                         0);
256
257       /* Create the toolbar
258        */
259       toolbar = gtk_toolbar_new ();
260
261       gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
262                                 GTK_STOCK_OPEN,
263                                 "This is a demo button with an 'open' icon",
264                                 NULL,
265                                 G_CALLBACK (toolbar_cb),
266                                 window, /* user data for callback */
267                                 -1);  /* -1 means "append" */
268
269       gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
270                                 GTK_STOCK_QUIT,
271                                 "This is a demo button with a 'quit' icon",
272                                 NULL,
273                                 G_CALLBACK (toolbar_cb),
274                                 window, /* user data for callback */
275                                 -1);  /* -1 means "append" */
276
277       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
278
279       gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
280                                 "demo-gtk-logo",
281                                 "This is a demo button with a 'gtk' icon",
282                                 NULL,
283                                 G_CALLBACK (toolbar_cb),
284                                 window, /* user data for callback */
285                                 -1);  /* -1 means "append" */
286
287       gtk_table_attach (GTK_TABLE (table),
288                         toolbar,
289                         /* X direction */       /* Y direction */
290                         0, 1,                   1, 2,
291                         GTK_EXPAND | GTK_FILL,  0,
292                         0,                      0);
293
294       /* Create document
295        */
296
297       sw = gtk_scrolled_window_new (NULL, NULL);
298
299       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
300                                       GTK_POLICY_AUTOMATIC,
301                                       GTK_POLICY_AUTOMATIC);
302
303       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
304                                            GTK_SHADOW_IN);
305       
306       gtk_table_attach (GTK_TABLE (table),
307                         sw,
308                         /* X direction */       /* Y direction */
309                         0, 1,                   2, 3,
310                         GTK_EXPAND | GTK_FILL,  GTK_EXPAND | GTK_FILL,
311                         0,                      0);
312
313       gtk_window_set_default_size (GTK_WINDOW (window),
314                                    200, 200);
315       
316       contents = gtk_text_view_new ();
317
318       gtk_container_add (GTK_CONTAINER (sw),
319                          contents);
320
321       /* Create statusbar */
322
323       statusbar = gtk_statusbar_new ();
324       gtk_table_attach (GTK_TABLE (table),
325                         statusbar,
326                         /* X direction */       /* Y direction */
327                         0, 1,                   3, 4,
328                         GTK_EXPAND | GTK_FILL,  0,
329                         0,                      0);
330
331       /* Show text widget info in the statusbar */
332       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (contents));
333       
334       g_signal_connect_object (buffer,
335                                "changed",
336                                G_CALLBACK (update_statusbar),
337                                statusbar,
338                                0);
339
340       g_signal_connect_object (buffer,
341                                "mark_set", /* cursor moved */
342                                G_CALLBACK (mark_set_callback),
343                                statusbar,
344                                0);
345
346       g_signal_connect_object (window, 
347                                "window_state_event", 
348                                G_CALLBACK (update_resize_grip),
349                                statusbar,
350                                0);
351       
352       update_statusbar (buffer, GTK_STATUSBAR (statusbar));
353     }
354
355   if (!GTK_WIDGET_VISIBLE (window))
356     {
357       gtk_widget_show_all (window);
358     }
359   else
360     {    
361       gtk_widget_destroy (window);
362       window = NULL;
363     }
364
365   return window;
366 }
367