gtk/tests/testheaderbar.c
Matthias Clasen 386b63b85d scrolledwindow: Don't take adjustments in new()
In 99.9% of all cases, these are just NULL, NULL.
So just do away with these arguments, people can
use the setters for the rare cases where they want
the scrolled window to use a different adjustment.
2020-06-24 11:25:09 -04:00

576 lines
18 KiB
C

#include <gtk/gtk.h>
static void
unset_title (GtkWidget *window)
{
GtkWidget *box;
g_assert (GTK_IS_WINDOW (window));
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_hide (box);
gtk_window_set_titlebar (GTK_WINDOW (window), box);
}
static void
load_css (GtkWidget *widget,
const char *css)
{
GtkCssProvider *provider;
GtkStyleContext *context;
context = gtk_widget_get_style_context (widget);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider, css, -1);
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider), 800);
}
static void
create_regular (GtkApplication *app)
{
GtkWidget *window, *label;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Regular window");
label = gtk_label_new ("This window has no titlebar set");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_window_set_child (GTK_WINDOW (window), label);
gtk_widget_show (window);
}
static void
create_headerbar_as_titlebar (GtkApplication *app)
{
GtkWidget *window, *header, *label;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Headerbar as titlebar");
header = gtk_header_bar_new ();
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
label = gtk_label_new ("This window has a headerbar set as a titlebar");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_window_set_child (GTK_WINDOW (window), label);
gtk_widget_show (window);
}
static void
create_headerbar_inside_window (GtkApplication *app)
{
GtkWidget *window, *box, *header, *label;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Headerbar inside window");
unset_title (window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_window_set_child (GTK_WINDOW (window), box);
header = gtk_header_bar_new ();
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
gtk_box_append (GTK_BOX (box), header);
label = gtk_label_new ("This window has a headerbar inside the window and no titlebar");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_widget_set_vexpand (label, TRUE);
gtk_box_append (GTK_BOX (box), label);
gtk_widget_show (window);
}
static void
create_headerbar_overlay (GtkApplication *app)
{
GtkWidget *window, *overlay, *sw, *box, *header, *label;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Headerbar overlaying content");
unset_title (window);
overlay = gtk_overlay_new ();
gtk_window_set_child (GTK_WINDOW (window), overlay);
header = gtk_header_bar_new ();
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
gtk_widget_set_valign (header, GTK_ALIGN_START);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), header);
load_css (header, "headerbar { background: alpha(shade(@theme_bg_color, .9), .8); }");
sw = gtk_scrolled_window_new ();
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_widget_set_size_request (sw, 300, 250);
gtk_overlay_set_child (GTK_OVERLAY (overlay), sw);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), box);
gtk_widget_set_size_request (sw, 300, 250);
label = gtk_label_new ("Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
"Nulla innn urna ac dui malesuada ornare. Nullam dictum "
"tempor mi et tincidunt. Aliquam metus nulla, auctor "
"vitae pulvinar nec, egestas at mi. Class aptent taciti "
"sociosqu ad litora torquent per conubia nostra, per "
"inceptos himenaeos. Aliquam sagittis, tellus congue "
"cursus congue, diam massa mollis enim, sit amet gravida "
"magna turpis egestas sapien. Aenean vel molestie nunc. "
"In hac habitasse platea dictumst. Suspendisse lacinia"
"mi eu ipsum vestibulum in venenatis enim commodo. "
"Vivamus non malesuada ligula.");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_box_append (GTK_BOX (box), label);
label = gtk_label_new ("This window has a headerbar inside an overlay, so the text is visible underneath it");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_widget_set_vexpand (label, TRUE);
gtk_box_append (GTK_BOX (box), label);
gtk_widget_show (window);
}
static void
create_hiding_headerbar (GtkApplication *app)
{
GtkWidget *window, *box, *revealer, *header, *label, *hbox, *toggle;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Hiding headerbar");
unset_title (window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_window_set_child (GTK_WINDOW (window), box);
revealer = gtk_revealer_new ();
gtk_box_append (GTK_BOX (box), revealer);
header = gtk_header_bar_new ();
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
gtk_revealer_set_child (GTK_REVEALER (revealer), header);
label = gtk_label_new ("This window's headerbar can be shown and hidden with animation");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_widget_set_vexpand (label, TRUE);
gtk_box_append (GTK_BOX (box), label);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
gtk_widget_set_halign (hbox, GTK_ALIGN_CENTER);
gtk_widget_set_margin_top (hbox, 12);
gtk_widget_set_margin_bottom (hbox, 12);
gtk_widget_set_margin_start (hbox, 12);
gtk_widget_set_margin_end (hbox, 12);
gtk_box_append (GTK_BOX (box), hbox);
toggle = gtk_switch_new ();
gtk_switch_set_active (GTK_SWITCH (toggle), TRUE);
gtk_box_append (GTK_BOX (hbox), toggle);
g_object_bind_property (toggle, "active",
revealer, "reveal-child",
G_BINDING_SYNC_CREATE);
label = gtk_label_new ("Show headerbar");
gtk_box_append (GTK_BOX (hbox), label);
gtk_widget_show (window);
}
static void
create_fake_headerbar (GtkApplication *app)
{
GtkWidget *window, *handle, *box, *center_box, *controls, *label;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Fake headerbar");
unset_title (window);
handle = gtk_window_handle_new ();
gtk_window_set_child (GTK_WINDOW (window), handle);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_window_handle_set_child (GTK_WINDOW_HANDLE (handle), box);
center_box = gtk_center_box_new ();
gtk_box_append (GTK_BOX (box), center_box);
label = gtk_label_new ("Fake headerbar");
gtk_center_box_set_center_widget (GTK_CENTER_BOX (center_box), label);
controls = gtk_window_controls_new (GTK_PACK_START);
gtk_center_box_set_start_widget (GTK_CENTER_BOX (center_box), controls);
controls = gtk_window_controls_new (GTK_PACK_END);
gtk_center_box_set_end_widget (GTK_CENTER_BOX (center_box), controls);
label = gtk_label_new ("This window's titlebar is just a centerbox with a label and window controls.\nThe whole window is draggable.");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_widget_set_vexpand (label, TRUE);
gtk_box_append (GTK_BOX (box), label);
gtk_widget_show (window);
}
/* split headerbar */
static void
split_decorations (GtkSettings *settings,
GParamSpec *pspec,
GtkBuilder *builder)
{
GtkWidget *sheader, *mheader;
gchar *layout, *p1, *p2;
gchar **p;
sheader = (GtkWidget *)gtk_builder_get_object (builder, "sidebar-header");
mheader = (GtkWidget *)gtk_builder_get_object (builder, "main-header");
g_object_get (settings, "gtk-decoration-layout", &layout, NULL);
p = g_strsplit (layout, ":", -1);
p1 = g_strconcat ("", p[0], ":", NULL);
if (g_strv_length (p) >= 2)
p2 = g_strconcat (":", p[1], NULL);
else
p2 = g_strdup ("");
gtk_header_bar_set_decoration_layout (GTK_HEADER_BAR (sheader), p1);
gtk_header_bar_set_decoration_layout (GTK_HEADER_BAR (mheader), p2);
g_free (p1);
g_free (p2);
g_strfreev (p);
g_free (layout);
}
static void
create_split_headerbar (GtkApplication *app)
{
GtkBuilder *builder;
GtkSettings *settings;
GtkWidget *win;
GtkWidget *entry;
GtkWidget *check;
GtkWidget *header;
const char *ui = "tests/testsplitheaders.ui";
if (!g_file_test (ui, G_FILE_TEST_EXISTS))
{
g_warning ("Can't find %s", ui);
return;
}
builder = gtk_builder_new_from_file (ui);
win = (GtkWidget *)gtk_builder_get_object (builder, "window");
gtk_window_set_application (GTK_WINDOW (win), app);
settings = gtk_widget_get_settings (win);
g_signal_connect (settings, "notify::gtk-decoration-layout",
G_CALLBACK (split_decorations), builder);
split_decorations (settings, NULL, builder);
entry = (GtkWidget *)gtk_builder_get_object (builder, "layout-entry");
g_object_bind_property (settings, "gtk-decoration-layout",
entry, "text",
G_BINDING_BIDIRECTIONAL|G_BINDING_SYNC_CREATE);
check = (GtkWidget *)gtk_builder_get_object (builder, "decorations");
header = (GtkWidget *)gtk_builder_get_object (builder, "sidebar-header");
g_object_bind_property (check, "active",
header, "show-title-buttons",
G_BINDING_DEFAULT);
header = (GtkWidget *)gtk_builder_get_object (builder, "main-header");
g_object_bind_property (check, "active",
header, "show-title-buttons",
G_BINDING_DEFAULT);
gtk_window_present (GTK_WINDOW (win));
}
/* stacked headers */
static void
back_to_main (GtkButton *button,
GtkWidget *win)
{
GtkWidget *header_stack;
GtkWidget *page_stack;
header_stack = GTK_WIDGET (g_object_get_data (G_OBJECT (win), "header-stack"));
page_stack = GTK_WIDGET (g_object_get_data (G_OBJECT (win), "page-stack"));
gtk_stack_set_visible_child_name (GTK_STACK (header_stack), "main");
gtk_stack_set_visible_child_name (GTK_STACK (page_stack), "page1");
}
static void
go_to_secondary (GtkButton *button,
GtkWidget *win)
{
GtkWidget *header_stack;
GtkWidget *page_stack;
header_stack = GTK_WIDGET (g_object_get_data (G_OBJECT (win), "header-stack"));
page_stack = GTK_WIDGET (g_object_get_data (G_OBJECT (win), "page-stack"));
gtk_stack_set_visible_child_name (GTK_STACK (header_stack), "secondary");
gtk_stack_set_visible_child_name (GTK_STACK (page_stack), "secondary");
}
static void
create_stacked_headerbar (GtkApplication *app)
{
GtkBuilder *builder;
GtkWidget *win;
GtkWidget *new_btn;
GtkWidget *back_btn;
GtkWidget *header_stack;
GtkWidget *page_stack;
const char *ui = "tests/teststackedheaders.ui";
if (!g_file_test (ui, G_FILE_TEST_EXISTS))
{
g_warning ("Can't find %s", ui);
return;
}
builder = gtk_builder_new ();
gtk_builder_add_from_file (builder, ui, NULL);
win = (GtkWidget *)gtk_builder_get_object (builder, "window");
gtk_window_set_application (GTK_WINDOW (win), app);
header_stack = (GtkWidget *)gtk_builder_get_object (builder, "header_stack");
page_stack = (GtkWidget *)gtk_builder_get_object (builder, "page_stack");
g_object_set_data (G_OBJECT (win), "header-stack", header_stack);
g_object_set_data (G_OBJECT (win), "page-stack", page_stack);
new_btn = (GtkWidget *)gtk_builder_get_object (builder, "new_btn");
back_btn = (GtkWidget *)gtk_builder_get_object (builder, "back_btn");
g_signal_connect (new_btn, "clicked", G_CALLBACK (go_to_secondary), win);
g_signal_connect (back_btn, "clicked", G_CALLBACK (back_to_main), win);
gtk_window_present (GTK_WINDOW (win));
}
/* technorama */
static const gchar css[] =
".main.background { "
" background-image: linear-gradient(to bottom, red, blue);"
" border-width: 0px; "
"}"
".titlebar.backdrop { "
" background-image: none; "
" background-color: @bg_color; "
" border-radius: 10px 10px 0px 0px; "
"}"
".titlebar { "
" background-image: linear-gradient(to bottom, white, @bg_color);"
" border-radius: 10px 10px 0px 0px; "
"}";
static void
on_bookmark_clicked (GtkButton *button, gpointer data)
{
GtkWindow *window = GTK_WINDOW (data);
GtkWidget *chooser;
chooser = gtk_file_chooser_dialog_new ("File Chooser Test",
window,
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Close",
GTK_RESPONSE_CLOSE,
NULL);
g_signal_connect (chooser, "response",
G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (chooser);
}
static void
toggle_fullscreen (GtkButton *button, gpointer data)
{
GtkWidget *window = GTK_WIDGET (data);
static gboolean fullscreen = FALSE;
if (fullscreen)
{
gtk_window_unfullscreen (GTK_WINDOW (window));
fullscreen = FALSE;
}
else
{
gtk_window_fullscreen (GTK_WINDOW (window));
fullscreen = TRUE;
}
}
static void
change_header (GtkButton *button, gpointer data)
{
GtkWidget *window = GTK_WIDGET (data);
GtkWidget *label;
GtkWidget *widget;
GtkWidget *image;
GtkWidget *header;
if (button && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
{
header = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_widget_add_css_class (header, "titlebar");
gtk_widget_add_css_class (header, "header-bar");
gtk_widget_set_margin_start (header, 10);
gtk_widget_set_margin_end (header, 10);
gtk_widget_set_margin_top (header, 10);
gtk_widget_set_margin_bottom (header, 10);
label = gtk_label_new ("Label");
gtk_box_append (GTK_BOX (header), label);
widget = gtk_level_bar_new ();
gtk_level_bar_set_value (GTK_LEVEL_BAR (widget), 0.4);
gtk_widget_set_hexpand (widget, TRUE);
gtk_box_append (GTK_BOX (header), widget);
}
else
{
header = gtk_header_bar_new ();
gtk_widget_add_css_class (header, "titlebar");
widget = gtk_button_new_with_label ("_Close");
gtk_button_set_use_underline (GTK_BUTTON (widget), TRUE);
gtk_widget_add_css_class (widget, "suggested-action");
g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_window_destroy), window);
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), widget);
widget= gtk_button_new ();
image = gtk_image_new_from_icon_name ("bookmark-new-symbolic");
g_signal_connect (widget, "clicked", G_CALLBACK (on_bookmark_clicked), window);
gtk_button_set_child (GTK_BUTTON (widget), image);
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), widget);
}
gtk_window_set_titlebar (GTK_WINDOW (window), header);
}
static void
create_technorama (GtkApplication *app)
{
GtkWidget *window;
GtkWidget *box;
GtkWidget *footer;
GtkWidget *button;
GtkWidget *content;
GtkCssProvider *provider;
window = gtk_window_new ();
gtk_window_set_application (GTK_WINDOW (window), app);
gtk_widget_add_css_class (window, "main");
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider, css, -1);
gtk_style_context_add_provider_for_display (gtk_widget_get_display (window),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
change_header (NULL, window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_window_set_child (GTK_WINDOW (window), box);
content = gtk_image_new_from_icon_name ("start-here-symbolic");
gtk_image_set_pixel_size (GTK_IMAGE (content), 512);
gtk_widget_set_vexpand (content, TRUE);
gtk_box_append (GTK_BOX (box), content);
footer = gtk_action_bar_new ();
gtk_action_bar_set_center_widget (GTK_ACTION_BAR (footer), gtk_check_button_new_with_label ("Middle"));
button = gtk_toggle_button_new_with_label ("Custom");
g_signal_connect (button, "clicked", G_CALLBACK (change_header), window);
gtk_action_bar_pack_start (GTK_ACTION_BAR (footer), button);
button = gtk_button_new_with_label ("Fullscreen");
gtk_action_bar_pack_end (GTK_ACTION_BAR (footer), button);
g_signal_connect (button, "clicked", G_CALLBACK (toggle_fullscreen), window);
gtk_box_append (GTK_BOX (box), footer);
gtk_widget_show (window);
}
struct {
const gchar *name;
void (*cb) (GtkApplication *app);
} buttons[] =
{
{ "Regular window", create_regular },
{ "Headerbar as titlebar", create_headerbar_as_titlebar },
{ "Headerbar inside window", create_headerbar_inside_window },
{ "Headerbar overlaying content", create_headerbar_overlay },
{ "Hiding headerbar", create_hiding_headerbar },
{ "Fake headerbar", create_fake_headerbar },
{ "Split headerbar", create_split_headerbar },
{ "Stacked headerbar", create_stacked_headerbar },
{ "Technorama", create_technorama },
};
int n_buttons = sizeof (buttons) / sizeof (buttons[0]);
static void
app_activate_cb (GtkApplication *app)
{
GtkWidget *window, *box;
int i;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Headerbar test");
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_halign (box, GTK_ALIGN_CENTER);
gtk_widget_set_valign (box, GTK_ALIGN_CENTER);
gtk_widget_add_css_class (box, "linked");
gtk_window_set_child (GTK_WINDOW (window), box);
for (i = 0; i < n_buttons; i++)
{
GtkWidget *btn;
btn = gtk_button_new_with_label (buttons[i].name);
g_signal_connect_object (btn,
"clicked",
G_CALLBACK (buttons[i].cb),
app,
G_CONNECT_SWAPPED);
gtk_box_append (GTK_BOX (box), btn);
}
gtk_widget_show (window);
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
app = gtk_application_new ("org.gtk.Test.headerbar2", 0);
g_signal_connect (app,
"activate",
G_CALLBACK (app_activate_cb),
NULL);
g_application_run (G_APPLICATION (app), argc, argv);
return 0;
}