]> Pileus Git - ~andy/gtk/blob - demos/gtk-demo/appwindow.c
Remove uses of gtk_statusbar_set_has_resize_grip()
[~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 "config.h"
8 #include "demo-common.h"
9
10 static GtkWidget *window = NULL;
11 static GtkWidget *infobar = NULL;
12 static GtkWidget *messagelabel = NULL;
13
14 static void
15 activate_action (GtkAction *action)
16 {
17   const gchar *name = gtk_action_get_name (action);
18   const gchar *typename = G_OBJECT_TYPE_NAME (action);
19
20   GtkWidget *dialog;
21
22   if (g_str_equal (name, "DarkTheme"))
23     {
24       gboolean value = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
25       GtkSettings *settings = gtk_settings_get_default ();
26
27       g_object_set (G_OBJECT (settings),
28                     "gtk-application-prefer-dark-theme", value,
29                     NULL);
30       return;
31     }
32   dialog = gtk_message_dialog_new (GTK_WINDOW (window),
33                                    GTK_DIALOG_DESTROY_WITH_PARENT,
34                                    GTK_MESSAGE_INFO,
35                                    GTK_BUTTONS_CLOSE,
36                                    "You activated action: \"%s\" of type \"%s\"",
37                                     name, typename);
38
39   /* Close dialog on user response */
40   g_signal_connect (dialog,
41                     "response",
42                     G_CALLBACK (gtk_widget_destroy),
43                     NULL);
44
45   gtk_widget_show (dialog);
46 }
47
48 static void
49 activate_radio_action (GtkAction *action, GtkRadioAction *current)
50 {
51   const gchar *name = gtk_action_get_name (GTK_ACTION (current));
52   const gchar *typename = G_OBJECT_TYPE_NAME (GTK_ACTION (current));
53   gboolean active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (current));
54   gint value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (current));
55
56   if (active)
57     {
58       gchar *text;
59
60       text = g_strdup_printf ("You activated radio action: \"%s\" of type \"%s\".\n"
61                               "Current value: %d",
62                               name, typename, value);
63       gtk_label_set_text (GTK_LABEL (messagelabel), text);
64       gtk_info_bar_set_message_type (GTK_INFO_BAR (infobar), (GtkMessageType)value);
65       gtk_widget_show (infobar);
66       g_free (text);
67     }
68 }
69
70 static void
71 about_cb (GtkAction *action,
72           GtkWidget *window)
73 {
74   GdkPixbuf *pixbuf, *transparent;
75   gchar *filename;
76
77   const gchar *authors[] = {
78     "Peter Mattis",
79     "Spencer Kimball",
80     "Josh MacDonald",
81     "and many more...",
82     NULL
83   };
84
85   const gchar *documentors[] = {
86     "Owen Taylor",
87     "Tony Gale",
88     "Matthias Clasen <mclasen@redhat.com>",
89     "and many more...",
90     NULL
91   };
92
93   pixbuf = NULL;
94   transparent = NULL;
95   filename = demo_find_file ("gtk-logo-rgb.gif", NULL);
96   if (filename)
97     {
98       pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
99       g_free (filename);
100       transparent = gdk_pixbuf_add_alpha (pixbuf, TRUE, 0xff, 0xff, 0xff);
101       g_object_unref (pixbuf);
102     }
103
104   gtk_show_about_dialog (GTK_WINDOW (window),
105                          "program-name", "GTK+ Code Demos",
106                          "version", g_strdup_printf ("%s,\nRunning against GTK+ %d.%d.%d",
107                                                      PACKAGE_VERSION,
108                                                      gtk_get_major_version (),
109                                                      gtk_get_minor_version (),
110                                                      gtk_get_micro_version ()),
111                          "copyright", "(C) 1997-2009 The GTK+ Team",
112                          "license-type", GTK_LICENSE_LGPL_2_1,
113                          "website", "http://www.gtk.org",
114                          "comments", "Program to demonstrate GTK+ functions.",
115                          "authors", authors,
116                          "documenters", documentors,
117                          "logo", transparent,
118                          "title", "About GTK+ Code Demos",
119                          NULL);
120
121   g_object_unref (transparent);
122 }
123
124 typedef struct
125 {
126   GtkAction action;
127 } ToolMenuAction;
128
129 typedef struct
130 {
131   GtkActionClass parent_class;
132 } ToolMenuActionClass;
133
134 G_DEFINE_TYPE(ToolMenuAction, tool_menu_action, GTK_TYPE_ACTION)
135
136 static void
137 tool_menu_action_class_init (ToolMenuActionClass *class)
138 {
139   GTK_ACTION_CLASS (class)->toolbar_item_type = GTK_TYPE_MENU_TOOL_BUTTON;
140 }
141
142 static void
143 tool_menu_action_init (ToolMenuAction *action)
144 {
145 }
146
147 static GtkActionEntry entries[] = {
148   { "FileMenu", NULL, "_File" },               /* name, stock id, label */
149   { "OpenMenu", NULL, "_Open" },               /* name, stock id, label */
150   { "PreferencesMenu", NULL, "_Preferences" }, /* name, stock id, label */
151   { "ColorMenu", NULL, "_Color"  },            /* name, stock id, label */
152   { "ShapeMenu", NULL, "_Shape" },             /* name, stock id, label */
153   { "HelpMenu", NULL, "_Help" },               /* name, stock id, label */
154   { "New", GTK_STOCK_NEW,                      /* name, stock id */
155     "_New", "<control>N",                      /* label, accelerator */
156     "Create a new file",                       /* tooltip */
157     G_CALLBACK (activate_action) },
158   { "File1", NULL,                             /* name, stock id */
159     "File1", NULL,                             /* label, accelerator */
160     "Open first file",                         /* tooltip */
161     G_CALLBACK (activate_action) },
162   { "Save", GTK_STOCK_SAVE,                    /* name, stock id */
163     "_Save","<control>S",                      /* label, accelerator */
164     "Save current file",                       /* tooltip */
165     G_CALLBACK (activate_action) },
166   { "SaveAs", GTK_STOCK_SAVE,                  /* name, stock id */
167     "Save _As...", NULL,                       /* label, accelerator */
168     "Save to a file",                          /* tooltip */
169     G_CALLBACK (activate_action) },
170   { "Quit", GTK_STOCK_QUIT,                    /* name, stock id */
171     "_Quit", "<control>Q",                     /* label, accelerator */
172     "Quit",                                    /* tooltip */
173     G_CALLBACK (activate_action) },
174   { "About", NULL,                             /* name, stock id */
175     "_About", "<control>A",                    /* label, accelerator */
176     "About",                                   /* tooltip */
177     G_CALLBACK (about_cb) },
178   { "Logo", "demo-gtk-logo",                   /* name, stock id */
179      NULL, NULL,                               /* label, accelerator */
180     "GTK+",                                    /* tooltip */
181     G_CALLBACK (activate_action) },
182 };
183 static guint n_entries = G_N_ELEMENTS (entries);
184
185
186 static GtkToggleActionEntry toggle_entries[] = {
187   { "Bold", GTK_STOCK_BOLD,                    /* name, stock id */
188      "_Bold", "<control>B",                    /* label, accelerator */
189     "Bold",                                    /* tooltip */
190     G_CALLBACK (activate_action),
191     TRUE },                                    /* is_active */
192   { "DarkTheme", NULL,                         /* name, stock id */
193      "_Prefer Dark Theme", NULL,               /* label, accelerator */
194     "Prefer Dark Theme",                       /* tooltip */
195     G_CALLBACK (activate_action),
196     FALSE },                                   /* is_active */
197 };
198 static guint n_toggle_entries = G_N_ELEMENTS (toggle_entries);
199
200 enum {
201   COLOR_RED,
202   COLOR_GREEN,
203   COLOR_BLUE
204 };
205
206 static GtkRadioActionEntry color_entries[] = {
207   { "Red", NULL,                               /* name, stock id */
208     "_Red", "<control>R",                      /* label, accelerator */
209     "Blood", COLOR_RED },                      /* tooltip, value */
210   { "Green", NULL,                             /* name, stock id */
211     "_Green", "<control>G",                    /* label, accelerator */
212     "Grass", COLOR_GREEN },                    /* tooltip, value */
213   { "Blue", NULL,                              /* name, stock id */
214     "_Blue", "<control>B",                     /* label, accelerator */
215     "Sky", COLOR_BLUE },                       /* tooltip, value */
216 };
217 static guint n_color_entries = G_N_ELEMENTS (color_entries);
218
219 enum {
220   SHAPE_SQUARE,
221   SHAPE_RECTANGLE,
222   SHAPE_OVAL
223 };
224
225 static GtkRadioActionEntry shape_entries[] = {
226   { "Square", NULL,                            /* name, stock id */
227     "_Square", "<control>S",                   /* label, accelerator */
228     "Square",  SHAPE_SQUARE },                 /* tooltip, value */
229   { "Rectangle", NULL,                         /* name, stock id */
230     "_Rectangle", "<control>R",                /* label, accelerator */
231     "Rectangle", SHAPE_RECTANGLE },            /* tooltip, value */
232   { "Oval", NULL,                              /* name, stock id */
233     "_Oval", "<control>O",                     /* label, accelerator */
234     "Egg", SHAPE_OVAL },                       /* tooltip, value */
235 };
236 static guint n_shape_entries = G_N_ELEMENTS (shape_entries);
237
238 static const gchar *ui_info =
239 "<ui>"
240 "  <menubar name='MenuBar'>"
241 "    <menu action='FileMenu'>"
242 "      <menuitem action='New'/>"
243 "      <menuitem action='Open'/>"
244 "      <menuitem action='Save'/>"
245 "      <menuitem action='SaveAs'/>"
246 "      <separator/>"
247 "      <menuitem action='Quit'/>"
248 "    </menu>"
249 "    <menu action='PreferencesMenu'>"
250 "      <menuitem action='DarkTheme'/>"
251 "      <menu action='ColorMenu'>"
252 "       <menuitem action='Red'/>"
253 "       <menuitem action='Green'/>"
254 "       <menuitem action='Blue'/>"
255 "      </menu>"
256 "      <menu action='ShapeMenu'>"
257 "        <menuitem action='Square'/>"
258 "        <menuitem action='Rectangle'/>"
259 "        <menuitem action='Oval'/>"
260 "      </menu>"
261 "      <menuitem action='Bold'/>"
262 "    </menu>"
263 "    <menu action='HelpMenu'>"
264 "      <menuitem action='About'/>"
265 "    </menu>"
266 "  </menubar>"
267 "  <toolbar name='ToolBar'>"
268 "    <toolitem action='Open'>"
269 "      <menu action='OpenMenu'>"
270 "        <menuitem action='File1'/>"
271 "      </menu>"
272 "    </toolitem>"
273 "    <toolitem action='Quit'/>"
274 "    <separator action='Sep1'/>"
275 "    <toolitem action='Logo'/>"
276 "  </toolbar>"
277 "</ui>";
278
279
280
281 /* This function registers our custom toolbar icons, so they can be themed.
282  *
283  * It's totally optional to do this, you could just manually insert icons
284  * and have them not be themeable, especially if you never expect people
285  * to theme your app.
286  */
287 static void
288 register_stock_icons (void)
289 {
290   static gboolean registered = FALSE;
291
292   if (!registered)
293     {
294       GdkPixbuf *pixbuf;
295       GtkIconFactory *factory;
296       char *filename;
297
298       static GtkStockItem items[] = {
299         { "demo-gtk-logo",
300           "_GTK!",
301           0, 0, NULL }
302       };
303
304       registered = TRUE;
305
306       /* Register our stock items */
307       gtk_stock_add (items, G_N_ELEMENTS (items));
308
309       /* Add our custom icon factory to the list of defaults */
310       factory = gtk_icon_factory_new ();
311       gtk_icon_factory_add_default (factory);
312
313       /* demo_find_file() looks in the current directory first,
314        * so you can run gtk-demo without installing GTK, then looks
315        * in the location where the file is installed.
316        */
317       pixbuf = NULL;
318       filename = demo_find_file ("gtk-logo-rgb.gif", NULL);
319       if (filename)
320         {
321           pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
322           g_free (filename);
323         }
324
325       /* Register icon to accompany stock item */
326       if (pixbuf != NULL)
327         {
328           GtkIconSet *icon_set;
329           GdkPixbuf *transparent;
330
331           /* The gtk-logo-rgb icon has a white background, make it transparent */
332           transparent = gdk_pixbuf_add_alpha (pixbuf, TRUE, 0xff, 0xff, 0xff);
333
334           icon_set = gtk_icon_set_new_from_pixbuf (transparent);
335           gtk_icon_factory_add (factory, "demo-gtk-logo", icon_set);
336           gtk_icon_set_unref (icon_set);
337           g_object_unref (pixbuf);
338           g_object_unref (transparent);
339         }
340       else
341         g_warning ("failed to load GTK logo for toolbar");
342
343       /* Drop our reference to the factory, GTK will hold a reference. */
344       g_object_unref (factory);
345     }
346 }
347
348 static void
349 update_statusbar (GtkTextBuffer *buffer,
350                   GtkStatusbar  *statusbar)
351 {
352   gchar *msg;
353   gint row, col;
354   gint count;
355   GtkTextIter iter;
356
357   gtk_statusbar_pop (statusbar, 0); /* clear any previous message,
358                                      * underflow is allowed
359                                      */
360
361   count = gtk_text_buffer_get_char_count (buffer);
362
363   gtk_text_buffer_get_iter_at_mark (buffer,
364                                     &iter,
365                                     gtk_text_buffer_get_insert (buffer));
366
367   row = gtk_text_iter_get_line (&iter);
368   col = gtk_text_iter_get_line_offset (&iter);
369
370   msg = g_strdup_printf ("Cursor at row %d column %d - %d chars in document",
371                          row, col, count);
372
373   gtk_statusbar_push (statusbar, 0, msg);
374
375   g_free (msg);
376 }
377
378 static void
379 mark_set_callback (GtkTextBuffer     *buffer,
380                    const GtkTextIter *new_location,
381                    GtkTextMark       *mark,
382                    gpointer           data)
383 {
384   update_statusbar (buffer, GTK_STATUSBAR (data));
385 }
386
387 GtkWidget *
388 do_appwindow (GtkWidget *do_widget)
389 {
390   if (!window)
391     {
392       GtkWidget *table;
393       GtkWidget *statusbar;
394       GtkWidget *contents;
395       GtkWidget *sw;
396       GtkWidget *bar;
397       GtkTextBuffer *buffer;
398       GtkActionGroup *action_group;
399       GtkAction *open_action;
400       GtkUIManager *merge;
401       GError *error = NULL;
402
403       register_stock_icons ();
404
405       /* Create the toplevel window
406        */
407
408       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
409       gtk_window_set_screen (GTK_WINDOW (window),
410                              gtk_widget_get_screen (do_widget));
411       gtk_window_set_title (GTK_WINDOW (window), "Application Window");
412       gtk_window_set_icon_name (GTK_WINDOW (window), "document-open");
413
414       /* NULL window variable when window is closed */
415       g_signal_connect (window, "destroy",
416                         G_CALLBACK (gtk_widget_destroyed),
417                         &window);
418
419       table = gtk_table_new (1, 5, FALSE);
420
421       gtk_container_add (GTK_CONTAINER (window), table);
422
423       /* Create the menubar and toolbar
424        */
425
426       action_group = gtk_action_group_new ("AppWindowActions");
427       open_action = g_object_new (tool_menu_action_get_type (),
428                                   "name", "Open",
429                                   "label", "_Open",
430                                   "tooltip", "Open a file",
431                                   "stock-id", GTK_STOCK_OPEN,
432                                   NULL);
433       gtk_action_group_add_action (action_group, open_action);
434       g_object_unref (open_action);
435       gtk_action_group_add_actions (action_group,
436                                     entries, n_entries,
437                                     window);
438       gtk_action_group_add_toggle_actions (action_group,
439                                            toggle_entries, n_toggle_entries,
440                                            NULL);
441       gtk_action_group_add_radio_actions (action_group,
442                                           color_entries, n_color_entries,
443                                           COLOR_RED,
444                                           G_CALLBACK (activate_radio_action),
445                                           NULL);
446       gtk_action_group_add_radio_actions (action_group,
447                                           shape_entries, n_shape_entries,
448                                           SHAPE_SQUARE,
449                                           G_CALLBACK (activate_radio_action),
450                                           NULL);
451
452       merge = gtk_ui_manager_new ();
453       g_object_set_data_full (G_OBJECT (window), "ui-manager", merge,
454                               g_object_unref);
455       gtk_ui_manager_insert_action_group (merge, action_group, 0);
456       gtk_window_add_accel_group (GTK_WINDOW (window),
457                                   gtk_ui_manager_get_accel_group (merge));
458
459       if (!gtk_ui_manager_add_ui_from_string (merge, ui_info, -1, &error))
460         {
461           g_message ("building menus failed: %s", error->message);
462           g_error_free (error);
463         }
464
465       bar = gtk_ui_manager_get_widget (merge, "/MenuBar");
466       gtk_widget_show (bar);
467       gtk_table_attach (GTK_TABLE (table),
468                         bar,
469                         /* X direction */          /* Y direction */
470                         0, 1,                      0, 1,
471                         GTK_EXPAND | GTK_FILL,     0,
472                         0,                         0);
473
474       bar = gtk_ui_manager_get_widget (merge, "/ToolBar");
475       gtk_widget_show (bar);
476       gtk_table_attach (GTK_TABLE (table),
477                         bar,
478                         /* X direction */       /* Y direction */
479                         0, 1,                   1, 2,
480                         GTK_EXPAND | GTK_FILL,  0,
481                         0,                      0);
482
483       /* Create document
484        */
485
486       infobar = gtk_info_bar_new ();
487       gtk_widget_set_no_show_all (infobar, TRUE);
488       messagelabel = gtk_label_new ("");
489       gtk_widget_show (messagelabel);
490       gtk_box_pack_start (GTK_BOX (gtk_info_bar_get_content_area (GTK_INFO_BAR (infobar))),
491                           messagelabel,
492                           TRUE, TRUE, 0);
493       gtk_info_bar_add_button (GTK_INFO_BAR (infobar),
494                                GTK_STOCK_OK, GTK_RESPONSE_OK);
495       g_signal_connect (infobar, "response",
496                         G_CALLBACK (gtk_widget_hide), NULL);
497
498       gtk_table_attach (GTK_TABLE (table),
499                         infobar,
500                         /* X direction */       /* Y direction */
501                         0, 1,                   2, 3,
502                         GTK_EXPAND | GTK_FILL,  0,
503                         0,                      0);
504
505       sw = gtk_scrolled_window_new (NULL, NULL);
506
507       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
508                                       GTK_POLICY_AUTOMATIC,
509                                       GTK_POLICY_AUTOMATIC);
510
511       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
512                                            GTK_SHADOW_IN);
513
514       gtk_table_attach (GTK_TABLE (table),
515                         sw,
516                         /* X direction */       /* Y direction */
517                         0, 1,                   3, 4,
518                         GTK_EXPAND | GTK_FILL,  GTK_EXPAND | GTK_FILL,
519                         0,                      0);
520
521       gtk_window_set_default_size (GTK_WINDOW (window),
522                                    200, 200);
523
524       contents = gtk_text_view_new ();
525       gtk_widget_grab_focus (contents);
526
527       gtk_container_add (GTK_CONTAINER (sw),
528                          contents);
529
530       /* Create statusbar */
531
532       statusbar = gtk_statusbar_new ();
533       gtk_table_attach (GTK_TABLE (table),
534                         statusbar,
535                         /* X direction */       /* Y direction */
536                         0, 1,                   4, 5,
537                         GTK_EXPAND | GTK_FILL,  0,
538                         0,                      0);
539
540       /* Show text widget info in the statusbar */
541       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (contents));
542       
543       g_signal_connect_object (buffer,
544                                "changed",
545                                G_CALLBACK (update_statusbar),
546                                statusbar,
547                                0);
548
549       g_signal_connect_object (buffer,
550                                "mark_set", /* cursor moved */
551                                G_CALLBACK (mark_set_callback),
552                                statusbar,
553                                0);
554
555       update_statusbar (buffer, GTK_STATUSBAR (statusbar));
556     }
557
558   if (!gtk_widget_get_visible (window))
559     {
560       gtk_widget_show_all (window);
561     }
562   else
563     {
564       gtk_widget_destroy (window);
565       window = NULL;
566       infobar = NULL;
567       messagelabel = NULL;
568     }
569
570   return window;
571 }
572