Make use of GtkShortcutsWindow

This commit is contained in:
Přemysl Eric Janouch 2021-12-20 14:25:59 +01:00
parent 6a61d01f4d
commit 9ba3679e89
Signed by: p
GPG Key ID: A0420B94F92B9493
1 changed files with 172 additions and 2 deletions

174
fastiv.c
View File

@ -52,6 +52,146 @@ exit_fatal(const gchar *format, ...)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// --- Help --------------------------------------------------------------------
// Fuck XML, this can be easily represented in static structures.
// Though it would be nice if the accelerators could be customized.
struct key {
const char *accelerator;
const char *title;
};
struct key_group {
const char *title;
const struct key *keys;
};
struct key_section {
const char *title;
const char *section_name;
const struct key_group *groups;
};
static struct key help_keys_general[] = {
{"F1 <control>F1", "Show this list of shortcuts"},
{"F11 f", "Toggle fullscreen view"},
{"<alt><shift>d", "Toggle dark theme variant"},
{"q <control>q", "Exit the program"},
{"Escape <control>w", "Exit the program"},
{}
};
static struct key_section help_keys[] = {
{"Browser", "browser", (struct key_group[]) {
{"General", help_keys_general},
{"View", (struct key[]) {
{"F9", "Toggle navigation sidebar"},
{}
}},
{"Navigation", (struct key[]) {
{"<control>l", "Open location..."},
{"<control>n", "Open a new window"},
{"<alt>Left", "Go back in history"},
{"<alt>Right", "Go forward in history"},
{"<alt>Up", "Go to parent directory"},
{"F5 r <control>r", "Refresh"},
{}
}},
{}
}},
{"View", "view", (struct key_group[]) {
{"General", help_keys_general},
{"View", (struct key[]) {
{"F8", "Toggle toolbar"},
{}
}},
{"Navigation", (struct key[]) {
{"<control>l", "Open location..."},
{"<control>n", "Open a new window"},
{"Left Up Page_Up", "Previous image"},
{"Right Down Page_Down", "Next image"},
{"Return <alt>Left", "Return to browser"},
{}
}},
{"Zoom", (struct key[]) {
{"<control>0", "Set zoom to 100%"},
{"1...9", "Set zoom to N:1"},
{"plus <control>plus", "Zoom in"},
{"minus <control>minus", "Zoom out"},
{}
}},
{"Orientation", (struct key[]) {
{"less", "Rotate anticlockwise"},
{"equal", "Mirror"},
{"greater", "Rotate clockwise"},
{}
}},
{"Control", (struct key[]) {
{"bracketleft", "Previous page"},
{"bracketright", "Next page"},
{"braceleft", "Previous frame"},
{"braceright", "Next frame"},
{"space", "Toggle playback"},
{}
}},
{"Configuration", (struct key[]) {
{"x", "Toggle scale to fit"},
{"i", "Toggle smooth scaling"},
{"t", "Toggle transparency highlighting"},
{}
}},
{"Tools", (struct key[]) {
{"<control>p", "Print..."},
{"<control>s", "Save page as..."},
{"<control><shift>s", "Save frame as..."},
{}
}},
{}
}},
{}
};
static GtkWidget *
make_key(const struct key *key)
{
return gtk_widget_new(GTK_TYPE_SHORTCUTS_SHORTCUT,
"title", key->title,
"shortcut-type", GTK_SHORTCUT_ACCELERATOR,
"accelerator", key->accelerator, NULL);
}
static GtkWidget *
make_key_group(const struct key_group *group)
{
GtkWidget *widget = gtk_widget_new(
GTK_TYPE_SHORTCUTS_GROUP, "title", group->title, NULL);
for (const struct key *p = group->keys; p->title; p++)
gtk_container_add(GTK_CONTAINER(widget), make_key(p));
return widget;
}
static GtkWidget *
make_key_section(const struct key_section *section)
{
GtkWidget *widget = gtk_widget_new(GTK_TYPE_SHORTCUTS_SECTION,
"title", section->title, "section-name", section->section_name, NULL);
for (const struct key_group *p = section->groups; p->title; p++)
gtk_container_add(GTK_CONTAINER(widget), make_key_group(p));
return widget;
}
static GtkWidget *
make_key_window(void)
{
GtkWidget *window = gtk_widget_new(GTK_TYPE_SHORTCUTS_WINDOW, NULL);
for (const struct key_section *p = help_keys; p->title; p++) {
GtkWidget *section = make_key_section(p);
gtk_widget_show_all(section);
gtk_container_add(GTK_CONTAINER(window), section);
}
return window;
}
// --- Main -------------------------------------------------------------------- // --- Main --------------------------------------------------------------------
// TODO(p): See if it's possible to give separators room to shrink // TODO(p): See if it's possible to give separators room to shrink
@ -535,6 +675,31 @@ on_window_state_event(G_GNUC_UNUSED GtkWidget *widget,
gtk_image_set_from_icon_name(image, name, GTK_ICON_SIZE_BUTTON); gtk_image_set_from_icon_name(image, name, GTK_ICON_SIZE_BUTTON);
} }
static void
on_help_destroyed(GtkWidget *window, GtkWidget **storage)
{
g_return_if_fail(*storage == window);
*storage = NULL;
}
static void
show_help_shortcuts(void)
{
static GtkWidget *window;
if (!window) {
window = make_key_window();
g_signal_connect(
window, "destroy", G_CALLBACK(on_help_destroyed), &window);
}
g_object_set(window, "section-name",
gtk_stack_get_visible_child(GTK_STACK(g.stack)) == g.view_box
? "view"
: "browser",
NULL);
gtk_widget_show(window);
}
// Cursor keys, e.g., simply cannot be bound through accelerators // Cursor keys, e.g., simply cannot be bound through accelerators
// (and GtkWidget::keynav-failed would arguably be an awful solution). // (and GtkWidget::keynav-failed would arguably be an awful solution).
// //
@ -579,6 +744,10 @@ on_key_press(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
case GDK_KEY_w: case GDK_KEY_w:
gtk_widget_destroy(g.window); gtk_widget_destroy(g.window);
return TRUE; return TRUE;
case GDK_KEY_F1:
show_help_shortcuts();
return TRUE;
} }
break; break;
case GDK_MOD1_MASK: case GDK_MOD1_MASK:
@ -615,13 +784,15 @@ on_key_press(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
case GDK_KEY_o: case GDK_KEY_o:
on_open(); on_open();
return TRUE; return TRUE;
case GDK_KEY_F5: case GDK_KEY_F5:
case GDK_KEY_r: case GDK_KEY_r:
// TODO(p): See the comment for C-r above. // TODO(p): See the comment for C-r above.
load_directory(NULL); load_directory(NULL);
return TRUE; return TRUE;
case GDK_KEY_F1:
show_help_shortcuts();
return TRUE;
case GDK_KEY_F9: case GDK_KEY_F9:
gtk_widget_set_visible(g.browser_sidebar, gtk_widget_set_visible(g.browser_sidebar,
!gtk_widget_is_visible(g.browser_sidebar)); !gtk_widget_is_visible(g.browser_sidebar));
@ -657,7 +828,6 @@ on_key_press_view(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
case GDK_KEY_Right: case GDK_KEY_Right:
case GDK_KEY_Down: case GDK_KEY_Down:
case GDK_KEY_Page_Down: case GDK_KEY_Page_Down:
case GDK_KEY_space:
on_next(); on_next();
return TRUE; return TRUE;