diff --git a/demos/gtk-demo/Makefile.am b/demos/gtk-demo/Makefile.am index e15a8c66e2..3396a99cc9 100644 --- a/demos/gtk-demo/Makefile.am +++ b/demos/gtk-demo/Makefile.am @@ -6,6 +6,7 @@ democodedir=$(datadir)/gtk-$(GTK_API_VERSION)/demo ## These should be in the order you want them to appear in the ## demo app, which means alphabetized by demo title, not filename demos = \ + application.c \ appwindow.c \ assistant.c \ builder.c \ @@ -65,13 +66,17 @@ LDADDS = \ $(GTK_DEP_LIBS) \ -lm -bin_PROGRAMS = gtk3-demo +bin_PROGRAMS = gtk3-demo gtk3-demo-application -BUILT_SOURCES = demos.h +BUILT_SOURCES = demos.h application_resources.c EXTRA_DIST += \ $(IMAGEFILES) \ - demo.ui + demo.ui \ + application.gresource.xml \ + application.ui \ + gtk-logo-24.png \ + gtk-logo-48.png demos.h: @REBUILD@ $(demos) geninclude.pl $(AM_V_GEN) (here=`pwd` ; cd $(srcdir) && $(PERL) $$here/geninclude.pl $(demos)) > demos.h @@ -86,8 +91,17 @@ gtk3_demo_DEPENDENCIES = $(DEPS) gtk3_demo_LDADD = $(LDADDS) gtk3_demo_LDFLAGS = -export-dynamic +gtk3_demo_application_SOURCES = \ + application-standalone.c \ + application_resources.c + +gtk3_demo_application_LDADD = $(LDADDS) + +application_resources.c: application.gresource.xml gtk-logo-24.png gtk-logo-48.png application.ui + glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source $(srcdir)/application.gresource.xml + IMAGEFILES= alphatest.png \ - apple-red.png \ + apple-red.png \ background.jpg \ floppybuddy.gif \ gnome-applets.png \ diff --git a/demos/gtk-demo/application.c b/demos/gtk-demo/application.c new file mode 100644 index 0000000000..fc27dec686 --- /dev/null +++ b/demos/gtk-demo/application.c @@ -0,0 +1,461 @@ +/* Application class + * + * Demonstrates a simple application. + * + * This examples uses GtkApplication, GtkApplicationWindow, GtkBuilder + * as well as GMenu and GResource. Due to the way GtkApplication is structured, + * it is run as a separate process. + */ + +#include "config.h" + +#include + +#ifdef STANDALONE + +static void +show_action_dialog (GSimpleAction *action) +{ + const gchar *name; + GtkWidget *dialog; + + name = g_action_get_name (G_ACTION (action)); + + dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, + "You activated action: \"%s\"", + name); + + g_signal_connect (dialog, "response", + G_CALLBACK (gtk_widget_destroy), NULL); + + gtk_widget_show (dialog); +} + +static void +show_action_infobar (GSimpleAction *action, + GVariant *parameter, + gpointer window) +{ + GtkWidget *infobar; + GtkWidget *message; + gchar *text; + const gchar *name; + const gchar *value; + + name = g_action_get_name (G_ACTION (action)); + value = g_variant_get_string (parameter, NULL); + + message = g_object_get_data (G_OBJECT (window), "message"); + infobar = g_object_get_data (G_OBJECT (window), "infobar"); + text = g_strdup_printf ("You activated radio action: \"%s\".\n" + "Current value: %s", name, value); + gtk_label_set_text (GTK_LABEL (message), text); + gtk_widget_show (infobar); + g_free (text); +} + +static void +activate_action (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + show_action_dialog (action); +} + +static void +activate_toggle (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + GVariant *state; + + show_action_dialog (action); + + state = g_action_get_state (G_ACTION (action)); + g_action_change_state (G_ACTION (action), g_variant_new_boolean (!g_variant_get_boolean (state))); + g_variant_unref (state); +} + +static void +activate_radio (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + show_action_infobar (action, parameter, user_data); + + g_action_change_state (G_ACTION (action), parameter); +} + +static void +activate_about (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + GtkWidget *window = user_data; + GdkPixbuf *pixbuf; + GInputStream *stream; + + const gchar *authors[] = { + "Peter Mattis", + "Spencer Kimball", + "Josh MacDonald", + "and many more...", + NULL + }; + + const gchar *documentors[] = { + "Owen Taylor", + "Tony Gale", + "Matthias Clasen ", + "and many more...", + NULL + }; + + stream = g_resources_open_stream ("/logos/gtk-logo-48.png", 0, NULL); + pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL); + g_object_unref (stream); + + gtk_show_about_dialog (GTK_WINDOW (window), + "program-name", "GTK+ Code Demos", + "version", g_strdup_printf ("%s,\nRunning against GTK+ %d.%d.%d", + PACKAGE_VERSION, + gtk_get_major_version (), + gtk_get_minor_version (), + gtk_get_micro_version ()), + "copyright", "(C) 1997-2009 The GTK+ Team", + "license-type", GTK_LICENSE_LGPL_2_1, + "website", "http://www.gtk.org", + "comments", "Program to demonstrate GTK+ functions.", + "authors", authors, + "documenters", documentors, + "logo", pixbuf, + "title", "About GTK+ Code Demos", + NULL); + g_object_unref (pixbuf); +} + +static void +activate_quit (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + GtkApplication *app = user_data; + GtkWidget *win; + GList *list, *next; + + list = gtk_application_get_windows (app); + while (list) + { + win = list->data; + next = list->next; + + gtk_widget_destroy (GTK_WIDGET (win)); + + list = next; + } +} + +static void +register_stock_icons (void) +{ + static gboolean registered = FALSE; + + if (!registered) + { + GdkPixbuf *pixbuf; + GtkIconFactory *factory; + GtkIconSet *icon_set; + GInputStream *stream; + + static GtkStockItem items[] = { + { "demo-gtk-logo", "_GTK!", 0, 0, NULL } + }; + + registered = TRUE; + + gtk_stock_add (items, G_N_ELEMENTS (items)); + + factory = gtk_icon_factory_new (); + gtk_icon_factory_add_default (factory); + + stream = g_resources_open_stream ("/logos/gtk-logo-24.png", 0, NULL); + pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL); + g_object_unref (stream); + + icon_set = gtk_icon_set_new_from_pixbuf (pixbuf); + gtk_icon_factory_add (factory, "demo-gtk-logo", icon_set); + gtk_icon_set_unref (icon_set); + g_object_unref (pixbuf); + + /* Drop our reference to the factory, GTK will hold a reference. */ + g_object_unref (factory); + } +} + +static void +update_statusbar (GtkTextBuffer *buffer, + GtkStatusbar *statusbar) +{ + gchar *msg; + gint row, col; + gint count; + GtkTextIter iter; + + /* clear any previous message, underflow is allowed */ + gtk_statusbar_pop (statusbar, 0); + + count = gtk_text_buffer_get_char_count (buffer); + + gtk_text_buffer_get_iter_at_mark (buffer, + &iter, + gtk_text_buffer_get_insert (buffer)); + + row = gtk_text_iter_get_line (&iter); + col = gtk_text_iter_get_line_offset (&iter); + + msg = g_strdup_printf ("Cursor at row %d column %d - %d chars in document", + row, col, count); + + gtk_statusbar_push (statusbar, 0, msg); + + g_free (msg); +} + +static void +mark_set_callback (GtkTextBuffer *buffer, + const GtkTextIter *new_location, + GtkTextMark *mark, + gpointer data) +{ + update_statusbar (buffer, GTK_STATUSBAR (data)); +} + +static void +change_theme_state (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + GtkSettings *settings = gtk_settings_get_default (); + + g_object_set (G_OBJECT (settings), + "gtk-application-prefer-dark-theme", + g_variant_get_boolean (state), + NULL); + + g_simple_action_set_state (action, state); +} + +static void +change_titlebar_state (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + GtkWindow *window = user_data; + + gtk_window_set_hide_titlebar_when_maximized (GTK_WINDOW (window), + g_variant_get_boolean (state)); + + g_simple_action_set_state (action, state); +} + +static void +change_radio_state (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + g_simple_action_set_state (action, state); +} + +static GActionEntry app_entries[] = { + { "new", activate_action, NULL, NULL, NULL }, + { "open", activate_action, NULL, NULL, NULL }, + { "save", activate_action, NULL, NULL, NULL }, + { "save-as", activate_action, NULL, NULL, NULL }, + { "quit", activate_quit, NULL, NULL, NULL }, + { "dark", activate_toggle, NULL, "false", change_theme_state } +}; + +static GActionEntry win_entries[] = { + { "titlebar", activate_toggle, NULL, "false", change_titlebar_state }, + { "color", activate_radio, "s", "'red'", change_radio_state }, + { "shape", activate_radio, "s", "'oval'", change_radio_state }, + { "bold", activate_toggle, NULL, "false", NULL }, + { "about", activate_about, NULL, NULL, NULL }, + { "logo", activate_action, NULL, NULL, NULL } +}; + +static void +clicked_cb (GtkWidget *widget, GtkWidget *info) +{ + gtk_widget_hide (info); +} + +static void +activate (GApplication *app) +{ + GtkBuilder *builder; + GtkWidget *window; + GtkWidget *grid; + GtkWidget *contents; + GtkWidget *status; + GtkWidget *message; + GtkWidget *button; + GtkWidget *infobar; + GtkTextBuffer *buffer; + GMenuModel *appmenu, *menubar; + GBytes *bytes; + const gchar *data; + gsize size; + + window = gtk_application_window_new (GTK_APPLICATION (app)); + gtk_window_set_title (GTK_WINDOW (window), "Application Class"); + gtk_window_set_icon_name (GTK_WINDOW (window), "document-open"); + gtk_window_set_default_size (GTK_WINDOW (window), 200, 200); + + g_action_map_add_action_entries (G_ACTION_MAP (window), + win_entries, G_N_ELEMENTS (win_entries), + window); + + builder = gtk_builder_new (); + + bytes = g_resources_lookup_data ("/ui/application.ui", 0, NULL); + data = g_bytes_get_data (bytes, &size); + gtk_builder_add_from_string (builder, data, size, NULL); + g_bytes_unref (bytes); + + grid = (GtkWidget *)gtk_builder_get_object (builder, "grid"); + appmenu = (GMenuModel *)gtk_builder_get_object (builder, "appmenu"); + menubar = (GMenuModel *)gtk_builder_get_object (builder, "menubar"); + contents = (GtkWidget *)gtk_builder_get_object (builder, "contents"); + status = (GtkWidget *)gtk_builder_get_object (builder, "status"); + message = (GtkWidget *)gtk_builder_get_object (builder, "message"); + button = (GtkWidget *)gtk_builder_get_object (builder, "button"); + infobar = (GtkWidget *)gtk_builder_get_object (builder, "infobar"); + + g_object_set_data (G_OBJECT (window), "message", message); + g_object_set_data (G_OBJECT (window), "infobar", infobar); + + gtk_container_add (GTK_CONTAINER (window), grid); + gtk_application_set_app_menu (GTK_APPLICATION (app), appmenu); + gtk_application_set_menubar (GTK_APPLICATION (app), menubar); + + gtk_widget_grab_focus (contents); + g_signal_connect (button, "clicked", G_CALLBACK (clicked_cb), infobar); + + /* Show text widget info in the statusbar */ + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (contents)); + g_signal_connect_object (buffer, "changed", + G_CALLBACK (update_statusbar), status, 0); + g_signal_connect_object (buffer, "mark-set", + G_CALLBACK (mark_set_callback), status, 0); + + update_statusbar (buffer, GTK_STATUSBAR (status)); + + gtk_widget_show_all (window); +} + +int +main (int argc, char *argv[]) +{ + GtkApplication *app; + + gtk_init (NULL, NULL); + + register_stock_icons (); + + app = gtk_application_new ("org.gtk.Demo", 0); + + g_action_map_add_action_entries (G_ACTION_MAP (app), + app_entries, G_N_ELEMENTS (app_entries), + app); + + g_signal_connect (app, "activate", G_CALLBACK (activate), NULL); + + g_application_run (G_APPLICATION (app), 0, NULL); + + return 0; +} + +#else /* !STANDALONE */ + +static gboolean name_seen; +static GtkWidget *placeholder; + +static void +on_name_appeared (GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + name_seen = TRUE; +} + +static void +on_name_vanished (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + if (!name_seen) + return; + + if (placeholder) + { + gtk_widget_destroy (placeholder); + g_object_unref (placeholder); + placeholder = NULL; + } +} + +GtkWidget * +do_application (GtkWidget *toplevel) +{ + static guint watch = 0; + + if (watch == 0) + watch = g_bus_watch_name (G_BUS_TYPE_SESSION, + "org.gtk.Demo", + 0, + on_name_appeared, + on_name_vanished, + NULL, NULL); + + if (placeholder == NULL) + { + const gchar *command; + GError *error = NULL; + + if (g_file_test ("./gtk3-demo-application", G_FILE_TEST_IS_EXECUTABLE)) + command = "./gtk3-demo-application"; + else + command = "gtk3-demo-application"; + + if (!g_spawn_command_line_async (command, &error)) + { + g_warning ("%s", error->message); + g_error_free (error); + } + + placeholder = gtk_label_new (""); + g_object_ref_sink (placeholder); + } + else + { + g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL), + "org.gtk.Demo", + "/org/gtk/Demo", + "org.gtk.Actions", + "Activate", + g_variant_new ("(sava{sv})", "quit", NULL, NULL), + NULL, + 0, + G_MAXINT, + NULL, NULL); + } + + return placeholder; +} + +#endif diff --git a/demos/gtk-demo/application.gresource.xml b/demos/gtk-demo/application.gresource.xml new file mode 100644 index 0000000000..80fcc47d46 --- /dev/null +++ b/demos/gtk-demo/application.gresource.xml @@ -0,0 +1,10 @@ + + + + gtk-logo-24.png + gtk-logo-48.png + + + application.ui + + diff --git a/demos/gtk-demo/application.ui b/demos/gtk-demo/application.ui new file mode 100644 index 0000000000..0dcee007bc --- /dev/null +++ b/demos/gtk-demo/application.ui @@ -0,0 +1,150 @@ + + + + + + horizontal + fill + True + + + gtk-open + + + + + True + File1 + + + + + + + + + gtk-quit + app.quit + + + + + + + + + + + + 0 + 0 + + + + + True + fill + True + + + + + True + True + fill + + + + + + + + + True + center + gtk-ok + True + + + + + + + 0 + 1 + + + + + in + + + fill + fill + True + True + + + + + 0 + 2 + + + + + fill + True + True + + + 0 + 3 + + + + +
+ + + + +
+
+ +
+
+ +
+ +
+ + + +
+ + + +
+
+ +
+ + + +
+
+ +
+
+ +
+ +
+
+
+
+
diff --git a/demos/gtk-demo/appwindow.c b/demos/gtk-demo/appwindow.c index 583a2bbc6a..648c2ab102 100644 --- a/demos/gtk-demo/appwindow.c +++ b/demos/gtk-demo/appwindow.c @@ -1,6 +1,8 @@ -/* Application main window +/* Application window * * Demonstrates a typical application window with menubar, toolbar, statusbar. + * + * This example uses GtkUIManager and GtkActionGroup. */ #include diff --git a/demos/gtk-demo/gtk-logo-24.png b/demos/gtk-demo/gtk-logo-24.png new file mode 100644 index 0000000000..54e3ba0d64 Binary files /dev/null and b/demos/gtk-demo/gtk-logo-24.png differ diff --git a/demos/gtk-demo/gtk-logo-48.png b/demos/gtk-demo/gtk-logo-48.png new file mode 100644 index 0000000000..5fed8f6f7f Binary files /dev/null and b/demos/gtk-demo/gtk-logo-48.png differ diff --git a/demos/gtk-demo/main.c b/demos/gtk-demo/main.c index 19c32c9e18..9ae6c4183d 100644 --- a/demos/gtk-demo/main.c +++ b/demos/gtk-demo/main.c @@ -782,7 +782,7 @@ create_tree (void) GtkTreeIter iter; GtkWidget *box, *label, *scrolled_window; - Demo *d = testgtk_demos; + Demo *d = gtk_demos; model = gtk_tree_store_new (NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT); tree_view = gtk_tree_view_new (); @@ -936,10 +936,8 @@ main (int argc, char **argv) * these few lines, which are just a hack so gtk-demo will work * in the GTK tree without installing it. */ - if (g_file_test ("../../gdk-pixbuf/libpixbufloader-pnm.la", - G_FILE_TEST_EXISTS)) + if (g_file_test ("../../modules/input/immodules.cache", G_FILE_TEST_EXISTS)) { - g_setenv ("GDK_PIXBUF_MODULE_FILE", "../../gdk-pixbuf/loaders.cache", TRUE); g_setenv ("GTK_IM_MODULE_FILE", "../../modules/input/immodules.cache", TRUE); } /* -- End of hack -- */ @@ -1002,7 +1000,7 @@ main (int argc, char **argv) gtk_window_set_default_size (GTK_WINDOW (window), 600, 400); gtk_widget_show_all (window); - load_file (testgtk_demos[0].filename); + load_file (gtk_demos[0].filename); gtk_main ();