Compare commits

...

2 Commits

Author SHA1 Message Date
9ba3679e89
Make use of GtkShortcutsWindow 2021-12-20 16:04:50 +01:00
6a61d01f4d
Bind hiding the toolbar 2021-12-20 12:15:52 +01:00
2 changed files with 181 additions and 5 deletions

184
fastiv.c
View File

@ -52,6 +52,146 @@ exit_fatal(const gchar *format, ...)
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 --------------------------------------------------------------------
// TODO(p): See if it's possible to give separators room to shrink
@ -126,6 +266,7 @@ struct {
GtkWidget *browser;
GtkWidget *view_box;
GtkWidget *view_toolbar;
GtkWidget *toolbar[TOOLBAR_COUNT];
GtkWidget *view;
} g;
@ -534,6 +675,31 @@ on_window_state_event(G_GNUC_UNUSED GtkWidget *widget,
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
// (and GtkWidget::keynav-failed would arguably be an awful solution).
//
@ -578,6 +744,10 @@ on_key_press(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
case GDK_KEY_w:
gtk_widget_destroy(g.window);
return TRUE;
case GDK_KEY_F1:
show_help_shortcuts();
return TRUE;
}
break;
case GDK_MOD1_MASK:
@ -614,13 +784,15 @@ on_key_press(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
case GDK_KEY_o:
on_open();
return TRUE;
case GDK_KEY_F5:
case GDK_KEY_r:
// TODO(p): See the comment for C-r above.
load_directory(NULL);
return TRUE;
case GDK_KEY_F1:
show_help_shortcuts();
return TRUE;
case GDK_KEY_F9:
gtk_widget_set_visible(g.browser_sidebar,
!gtk_widget_is_visible(g.browser_sidebar));
@ -642,6 +814,11 @@ on_key_press_view(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
switch (event->state & gtk_accelerator_get_default_mod_mask()) {
case 0:
switch (event->keyval) {
case GDK_KEY_F8:
gtk_widget_set_visible(g.view_toolbar,
!gtk_widget_is_visible(g.view_toolbar));
return TRUE;
case GDK_KEY_Left:
case GDK_KEY_Up:
case GDK_KEY_Page_Up:
@ -651,7 +828,6 @@ on_key_press_view(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
case GDK_KEY_Right:
case GDK_KEY_Down:
case GDK_KEY_Page_Down:
case GDK_KEY_space:
on_next();
return TRUE;
@ -1036,8 +1212,8 @@ main(int argc, char *argv[])
// Need to put the toolbar at the top, because of the horizontal scrollbar.
g.view_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
GtkWidget *view_toolbar = make_view_toolbar();
gtk_box_pack_start(GTK_BOX(g.view_box), view_toolbar, FALSE, FALSE, 0);
g.view_toolbar = make_view_toolbar();
gtk_box_pack_start(GTK_BOX(g.view_box), g.view_toolbar, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(g.view_box),
gtk_separator_new(GTK_ORIENTATION_VERTICAL), FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(g.view_box), view_scroller, TRUE, TRUE, 0);

View File

@ -816,7 +816,7 @@ fiv_view_key_press_event(GtkWidget *widget, GdkEventKey *event)
case GDK_KEY_minus:
return command(self, FIV_VIEW_COMMAND_ZOOM_OUT);
case GDK_KEY_x: // Inspired by gThumb.
case GDK_KEY_x: // Inspired by gThumb, which has more such modes.
return command(self, FIV_VIEW_COMMAND_TOGGLE_SCALE_TO_FIT);
case GDK_KEY_i:
return command(self, FIV_VIEW_COMMAND_TOGGLE_FILTER);