mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-27 14:10:30 +00:00
58f27de927
This is not done automatically, so unset needs-attention when the page becomes current.
449 lines
13 KiB
C
449 lines
13 KiB
C
/* widget-factory: a collection of widgets in a single page, for easy
|
|
* theming
|
|
*
|
|
* Copyright (C) 2011 Canonical Ltd
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Authored by Andrea Cimitan <andrea.cimitan@canonical.com>
|
|
*
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include <gtk/gtk.h>
|
|
|
|
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
|
|
activate_search (GSimpleAction *action,
|
|
GVariant *parameter,
|
|
gpointer user_data)
|
|
{
|
|
GtkWidget *window = user_data;
|
|
GtkWidget *searchbar;
|
|
|
|
searchbar = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "searchbar"));
|
|
gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (searchbar), TRUE);
|
|
}
|
|
|
|
static void
|
|
activate_delete (GSimpleAction *action,
|
|
GVariant *parameter,
|
|
gpointer user_data)
|
|
{
|
|
GtkWidget *window = user_data;
|
|
GtkWidget *infobar;
|
|
|
|
infobar = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "infobar"));
|
|
gtk_widget_show (infobar);
|
|
}
|
|
|
|
static void
|
|
activate_about (GSimpleAction *action,
|
|
GVariant *parameter,
|
|
gpointer user_data)
|
|
{
|
|
GtkApplication *app = user_data;
|
|
const gchar *authors[] = {
|
|
"Andrea Cimitan",
|
|
"Cosimo Cecchi",
|
|
NULL
|
|
};
|
|
gchar *version;
|
|
|
|
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 ());
|
|
|
|
gtk_show_about_dialog (GTK_WINDOW (gtk_application_get_active_window (app)),
|
|
"program-name", "GTK+ Widget Factory",
|
|
"version", version,
|
|
"copyright", "(C) 1997-2013 The GTK+ Team",
|
|
"license-type", GTK_LICENSE_LGPL_2_1,
|
|
"website", "http://www.gtk.org",
|
|
"comments", "Program to demonstrate GTK+ themes and widgets",
|
|
"authors", authors,
|
|
"logo-icon-name", "gtk3-widget-factory",
|
|
"title", "About GTK+ Widget Factory",
|
|
NULL);
|
|
|
|
g_free (version);
|
|
}
|
|
|
|
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
|
|
spin_value_changed (GtkAdjustment *adjustment, GtkWidget *label)
|
|
{
|
|
GtkWidget *w;
|
|
gint v;
|
|
gchar *text;
|
|
|
|
v = (int)gtk_adjustment_get_value (adjustment);
|
|
|
|
if ((v % 3) == 0)
|
|
{
|
|
text = g_strdup_printf ("%d is a multiple of 3", v);
|
|
gtk_label_set_label (GTK_LABEL (label), text);
|
|
g_free (text);
|
|
}
|
|
|
|
w = gtk_widget_get_ancestor (label, GTK_TYPE_REVEALER);
|
|
gtk_revealer_set_reveal_child (GTK_REVEALER (w), (v % 3) == 0);
|
|
}
|
|
|
|
static void
|
|
dismiss (GtkWidget *button)
|
|
{
|
|
GtkWidget *w;
|
|
|
|
w = gtk_widget_get_ancestor (button, GTK_TYPE_REVEALER);
|
|
gtk_revealer_set_reveal_child (GTK_REVEALER (w), FALSE);
|
|
}
|
|
|
|
static gint pulse_time = 250;
|
|
static gint pulse_entry_mode = 0;
|
|
|
|
static gboolean
|
|
pulse_it (GtkWidget *widget)
|
|
{
|
|
guint pulse_id;
|
|
|
|
if (GTK_IS_ENTRY (widget))
|
|
gtk_entry_progress_pulse (GTK_ENTRY (widget));
|
|
else
|
|
gtk_progress_bar_pulse (GTK_PROGRESS_BAR (widget));
|
|
|
|
pulse_id = g_timeout_add (pulse_time, (GSourceFunc)pulse_it, widget);
|
|
g_object_set_data (G_OBJECT (widget), "pulse_id", GUINT_TO_POINTER (pulse_id));
|
|
|
|
return G_SOURCE_REMOVE;
|
|
}
|
|
|
|
static void
|
|
update_pulse_time (GtkAdjustment *adjustment, GtkWidget *widget)
|
|
{
|
|
gdouble value;
|
|
guint pulse_id;
|
|
|
|
value = gtk_adjustment_get_value (adjustment);
|
|
|
|
pulse_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget), "pulse_id"));
|
|
|
|
/* vary between 50 and 450 */
|
|
pulse_time = 50 + 4 * value;
|
|
|
|
if (value == 100)
|
|
{
|
|
if (pulse_id != 0)
|
|
{
|
|
g_source_remove (pulse_id);
|
|
g_object_set_data (G_OBJECT (widget), "pulse_id", NULL);
|
|
}
|
|
}
|
|
else if (value < 100)
|
|
{
|
|
if (pulse_id == 0 && (GTK_IS_PROGRESS_BAR (widget) || pulse_entry_mode % 3 == 2))
|
|
{
|
|
pulse_id = g_timeout_add (pulse_time, (GSourceFunc)pulse_it, widget);
|
|
g_object_set_data (G_OBJECT (widget), "pulse_id", GUINT_TO_POINTER (pulse_id));
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
on_entry_icon_release (GtkEntry *entry,
|
|
GtkEntryIconPosition icon_pos,
|
|
GdkEvent *event,
|
|
gpointer user_data)
|
|
{
|
|
guint pulse_id;
|
|
|
|
if (icon_pos != GTK_ENTRY_ICON_SECONDARY)
|
|
return;
|
|
|
|
pulse_entry_mode++;
|
|
|
|
if (pulse_entry_mode % 3 == 0)
|
|
{
|
|
pulse_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (entry), "pulse_id"));
|
|
if (pulse_id != 0)
|
|
{
|
|
g_source_remove (pulse_id);
|
|
g_object_set_data (G_OBJECT (entry), "pulse_id", NULL);
|
|
}
|
|
gtk_entry_set_progress_fraction (entry, 0);
|
|
}
|
|
else if (pulse_entry_mode % 3 == 1)
|
|
gtk_entry_set_progress_fraction (entry, 0.25);
|
|
else if (pulse_entry_mode % 3 == 2)
|
|
{
|
|
if (pulse_time - 50 < 400)
|
|
{
|
|
gtk_entry_set_progress_pulse_step (entry, 0.1);
|
|
pulse_it (GTK_WIDGET (entry));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
startup (GApplication *app)
|
|
{
|
|
GtkBuilder *builder;
|
|
GMenuModel *appmenu;
|
|
|
|
builder = gtk_builder_new ();
|
|
gtk_builder_add_from_resource (builder, "/ui/widget-factory.ui", NULL);
|
|
|
|
appmenu = (GMenuModel *)gtk_builder_get_object (builder, "appmenu");
|
|
|
|
gtk_application_set_app_menu (GTK_APPLICATION (app), appmenu);
|
|
|
|
g_object_unref (builder);
|
|
}
|
|
|
|
static void
|
|
update_header (GtkListBoxRow *row,
|
|
GtkListBoxRow *before,
|
|
gpointer data)
|
|
{
|
|
if (before != NULL &&
|
|
gtk_list_box_row_get_header (row) == NULL)
|
|
{
|
|
GtkWidget *separator;
|
|
|
|
separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
|
|
gtk_widget_show (separator);
|
|
gtk_list_box_row_set_header (row, separator);
|
|
}
|
|
}
|
|
|
|
static void
|
|
info_bar_response (GtkWidget *infobar, gint response_id)
|
|
{
|
|
if (response_id == GTK_RESPONSE_CLOSE)
|
|
gtk_widget_hide (infobar);
|
|
}
|
|
|
|
static void
|
|
show_dialog (GtkWidget *button, GtkWidget *dialog)
|
|
{
|
|
gtk_widget_show (dialog);
|
|
}
|
|
|
|
static void
|
|
close_dialog (GtkWidget *dialog)
|
|
{
|
|
gtk_widget_hide (dialog);
|
|
}
|
|
|
|
static void
|
|
set_needs_attention (GtkWidget *page, gboolean needs_attention)
|
|
{
|
|
GtkWidget *stack;
|
|
|
|
stack = gtk_widget_get_parent (page);
|
|
gtk_container_child_set (GTK_CONTAINER (stack), page,
|
|
"needs-attention", needs_attention,
|
|
NULL);
|
|
}
|
|
|
|
static gboolean
|
|
demand_attention (gpointer stack)
|
|
{
|
|
GtkWidget *page;
|
|
|
|
page = gtk_stack_get_child_by_name (GTK_STACK (stack), "page3");
|
|
set_needs_attention (page, TRUE);
|
|
|
|
return G_SOURCE_REMOVE;
|
|
}
|
|
|
|
static void
|
|
action_dialog_button_clicked (GtkButton *button, GtkWidget *page)
|
|
{
|
|
g_timeout_add (1000, demand_attention, page);
|
|
}
|
|
|
|
static void
|
|
page_changed_cb (GtkWidget *stack, GParamSpec *pspec, gpointer data)
|
|
{
|
|
const gchar *name;
|
|
GtkWidget *page;
|
|
|
|
name = gtk_stack_get_visible_child_name (GTK_STACK (stack));
|
|
if (g_str_equal (name, "page3"))
|
|
{
|
|
page = gtk_stack_get_visible_child (GTK_STACK (stack));
|
|
set_needs_attention (GTK_WIDGET (page), FALSE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
activate (GApplication *app)
|
|
{
|
|
GtkBuilder *builder;
|
|
GtkWindow *window;
|
|
GtkWidget *widget;
|
|
GtkWidget *stack;
|
|
GtkWidget *dialog;
|
|
GtkAdjustment *adj;
|
|
static GActionEntry win_entries[] = {
|
|
{ "dark", NULL, NULL, "false", change_theme_state },
|
|
{ "search", activate_search, NULL, NULL, NULL },
|
|
{ "delete", activate_delete, NULL, NULL, NULL }
|
|
};
|
|
|
|
builder = gtk_builder_new_from_resource ("/ui/widget-factory.ui");
|
|
gtk_builder_add_callback_symbol (builder, "on_entry_icon_release", (GCallback)on_entry_icon_release);
|
|
gtk_builder_connect_signals (builder, NULL);
|
|
|
|
window = (GtkWindow *)gtk_builder_get_object (builder, "window");
|
|
gtk_application_add_window (GTK_APPLICATION (app), window);
|
|
g_action_map_add_action_entries (G_ACTION_MAP (window),
|
|
win_entries, G_N_ELEMENTS (win_entries),
|
|
window);
|
|
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "statusbar");
|
|
gtk_statusbar_push (GTK_STATUSBAR (widget), 0, "All systems are operating normally.");
|
|
g_action_map_add_action (G_ACTION_MAP (window),
|
|
G_ACTION (g_property_action_new ("statusbar", widget, "visible")));
|
|
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbar");
|
|
g_action_map_add_action (G_ACTION_MAP (window),
|
|
G_ACTION (g_property_action_new ("toolbar", widget, "visible")));
|
|
|
|
adj = (GtkAdjustment *)gtk_builder_get_object (builder, "adjustment1");
|
|
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "progressbar3");
|
|
g_signal_connect (adj, "value-changed", G_CALLBACK (update_pulse_time), widget);
|
|
update_pulse_time (adj, widget);
|
|
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "entry1");
|
|
g_signal_connect (adj, "value-changed", G_CALLBACK (update_pulse_time), widget);
|
|
update_pulse_time (adj, widget);
|
|
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "page2dismiss");
|
|
g_signal_connect (widget, "clicked", G_CALLBACK (dismiss), NULL);
|
|
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "page2note");
|
|
adj = (GtkAdjustment *) gtk_builder_get_object (builder, "adjustment2");
|
|
g_signal_connect (adj, "value-changed", G_CALLBACK (spin_value_changed), widget);
|
|
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "listbox");
|
|
gtk_list_box_set_header_func (GTK_LIST_BOX (widget), update_header, NULL, NULL);
|
|
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbar");
|
|
g_object_set_data (G_OBJECT (window), "toolbar", widget);
|
|
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "searchbar");
|
|
g_object_set_data (G_OBJECT (window), "searchbar", widget);
|
|
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "infobar");
|
|
g_signal_connect (widget, "response", G_CALLBACK (info_bar_response), NULL);
|
|
g_object_set_data (G_OBJECT (window), "infobar", widget);
|
|
|
|
dialog = (GtkWidget *)gtk_builder_get_object (builder, "info_dialog");
|
|
g_signal_connect (dialog, "response", G_CALLBACK (close_dialog), NULL);
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "info_dialog_button");
|
|
g_signal_connect (widget, "clicked", G_CALLBACK (show_dialog), dialog);
|
|
|
|
dialog = (GtkWidget *)gtk_builder_get_object (builder, "action_dialog");
|
|
g_signal_connect (dialog, "response", G_CALLBACK (close_dialog), NULL);
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "action_dialog_button");
|
|
g_signal_connect (widget, "clicked", G_CALLBACK (show_dialog), dialog);
|
|
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "act_action_dialog");
|
|
stack = (GtkWidget *)gtk_builder_get_object (builder, "toplevel_stack");
|
|
g_signal_connect (widget, "clicked", G_CALLBACK (action_dialog_button_clicked), stack);
|
|
g_signal_connect (stack, "notify::visible-child-name", G_CALLBACK (page_changed_cb), NULL);
|
|
|
|
dialog = (GtkWidget *)gtk_builder_get_object (builder, "preference_dialog");
|
|
g_signal_connect (dialog, "response", G_CALLBACK (close_dialog), NULL);
|
|
widget = (GtkWidget *)gtk_builder_get_object (builder, "preference_dialog_button");
|
|
g_signal_connect (widget, "clicked", G_CALLBACK (show_dialog), dialog);
|
|
|
|
gtk_widget_show_all (GTK_WIDGET (window));
|
|
|
|
g_object_unref (builder);
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
GtkApplication *app;
|
|
static GActionEntry app_entries[] = {
|
|
{ "about", activate_about, NULL, NULL, NULL },
|
|
{ "quit", activate_quit, NULL, NULL, NULL },
|
|
|
|
{ "main", NULL, "s", "'steak'", NULL },
|
|
{ "wine", NULL, NULL, "false", NULL },
|
|
{ "beer", NULL, NULL, "false", NULL },
|
|
{ "water", NULL, NULL, "true", NULL },
|
|
{ "dessert", NULL, "s", "'bars'", NULL },
|
|
{ "pay", NULL, "s", NULL, NULL }
|
|
|
|
};
|
|
gint status;
|
|
|
|
app = gtk_application_new ("org.gtk.WidgetFactory", 0);
|
|
|
|
g_action_map_add_action_entries (G_ACTION_MAP (app),
|
|
app_entries, G_N_ELEMENTS (app_entries),
|
|
app);
|
|
|
|
g_signal_connect (app, "startup", G_CALLBACK (startup), NULL);
|
|
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
|
|
|
|
status = g_application_run (G_APPLICATION (app), argc, argv);
|
|
g_object_unref (app);
|
|
|
|
return status;
|
|
}
|