diff options
Diffstat (limited to 'src/sdgtk.c')
-rw-r--r-- | src/sdgtk.c | 144 |
1 files changed, 18 insertions, 126 deletions
diff --git a/src/sdgtk.c b/src/sdgtk.c index c104f38..3565bc6 100644 --- a/src/sdgtk.c +++ b/src/sdgtk.c @@ -1,7 +1,7 @@ /* * StarDict GTK+ UI * - * Copyright (c) 2020, Přemysl Eric Janouch <p@janouch.name> + * Copyright (c) 2020 - 2021, Přemysl Eric Janouch <p@janouch.name> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted. @@ -24,6 +24,7 @@ #include "config.h" #include "stardict.h" #include "utils.h" +#include "stardict-view.h" typedef struct dictionary Dictionary; @@ -40,7 +41,7 @@ static struct GtkWidget *window; ///< Top-level window GtkWidget *notebook; ///< Notebook with tabs GtkWidget *entry; ///< Search entry widget - GtkWidget *grid; ///< Entries container + GtkWidget *view; ///< Entries view gint dictionary; ///< Index of the current dictionary Dictionary *dictionaries; ///< All open dictionaries @@ -86,99 +87,6 @@ init (gchar **filenames, GError **e) } static void -add_row (StardictIterator *iterator, gint row, gint *height_acc) -{ - Dictionary *dict = &g.dictionaries[g.dictionary]; - - StardictEntry *entry = stardict_iterator_get_entry (iterator); - g_return_if_fail (entry != NULL); - StardictEntryField *field = entry->fields->data; - g_return_if_fail (g_ascii_islower (field->type)); - - GtkEntryBuffer *buf = gtk_entry_get_buffer (GTK_ENTRY (g.entry)); - const gchar *input_utf8 = gtk_entry_buffer_get_text (buf); - g_return_if_fail (input_utf8 != NULL); - - const gchar *word_str = stardict_iterator_get_word (iterator); - gsize common_prefix = stardict_longest_common_collation_prefix - (dict->dict, word_str, input_utf8); - gchar *pre = g_markup_escape_text (word_str, common_prefix), - *post = g_markup_escape_text (word_str + common_prefix, -1), - *marked_up = g_strdup_printf ("<u>%s</u>%s", pre, post); - - GtkWidget *word = gtk_label_new (marked_up); - gtk_label_set_use_markup (GTK_LABEL (word), TRUE); - gtk_label_set_ellipsize (GTK_LABEL (word), PANGO_ELLIPSIZE_END); - gtk_label_set_selectable (GTK_LABEL (word), TRUE); - gtk_label_set_xalign (GTK_LABEL (word), 0); - gtk_label_set_yalign (GTK_LABEL (word), 0); - // FIXME: they can't be deselected by just clicking outside of them - gtk_widget_set_can_focus (word, FALSE); - - g_free (pre); - g_free (post); - g_free (marked_up); - - GtkWidget *desc = gtk_label_new (field->data); - gtk_label_set_ellipsize (GTK_LABEL (desc), PANGO_ELLIPSIZE_END); - gtk_label_set_selectable (GTK_LABEL (desc), TRUE); - gtk_label_set_xalign (GTK_LABEL (desc), 0); - gtk_widget_set_can_focus (desc, FALSE); - - g_object_unref (entry); - - if (iterator->offset % 2 == 0) - { - GtkStyleContext *ctx; - ctx = gtk_widget_get_style_context (word); - gtk_style_context_add_class (ctx, "odd"); - ctx = gtk_widget_get_style_context (desc); - gtk_style_context_add_class (ctx, "odd"); - } - - gtk_grid_attach (GTK_GRID (g.grid), word, 0, row, 1, 1); - gtk_grid_attach (GTK_GRID (g.grid), desc, 1, row, 1, 1); - - gtk_widget_show (word); - gtk_widget_show (desc); - - gint minimum_word = 0, minimum_desc = 0; - gtk_widget_get_preferred_height (word, &minimum_word, NULL); - gtk_widget_get_preferred_height (desc, &minimum_desc, NULL); - *height_acc += MAX (minimum_word, minimum_desc); -} - -static void -reload (GtkWidget *grid) -{ - Dictionary *dict = &g.dictionaries[g.dictionary]; - - GList *children = gtk_container_get_children (GTK_CONTAINER (grid)); - for (GList *iter = children; iter != NULL; iter = g_list_next (iter)) - gtk_widget_destroy (GTK_WIDGET (iter->data)); - g_list_free (children); - - gint window_height = 0; - gtk_window_get_size (GTK_WINDOW (g.window), NULL, &window_height); - if (window_height <= 0) - return; - - StardictIterator *iterator = - stardict_iterator_new (dict->dict, dict->position); - gint row = 0, height_acc = 0; - while (stardict_iterator_is_valid (iterator)) - { - add_row (iterator, row++, &height_acc); - if (height_acc >= window_height) - break; - - stardict_iterator_next (iterator); - } - gtk_widget_show_all (grid); - g_object_unref (iterator); -} - -static void search (Dictionary *dict) { GtkEntryBuffer *buf = gtk_entry_get_buffer (GTK_ENTRY (g.entry)); @@ -188,13 +96,16 @@ search (Dictionary *dict) stardict_dict_search (dict->dict, input_utf8, NULL); dict->position = stardict_iterator_get_offset (iterator); g_object_unref (iterator); + + stardict_view_set_position (STARDICT_VIEW (g.view), + dict->dict, dict->position); + stardict_view_set_matched (STARDICT_VIEW (g.view), input_utf8); } static void on_changed (G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED gpointer data) { search (&g.dictionaries[g.dictionary]); - reload (g.grid); } static void @@ -231,7 +142,6 @@ on_switch_page (G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED GtkWidget *page, { g.dictionary = page_num; search (&g.dictionaries[g.dictionary]); - reload (g.grid); } static gboolean @@ -317,12 +227,8 @@ main (int argc, char *argv[]) if (!init (filenames, &error)) die_with_dialog (error->message); - // Some Adwaita stupidity and our own additions - const char *style = "notebook header tab { padding: 2px 8px; margin: 0; }" - "grid { border-top: 1px solid rgba(0, 0, 0, 0.2); background: white; }" - "grid label { padding: 0 5px; " - "/*border-bottom: 1px solid rgba(0, 0, 0, 0.2);*/ }" - "grid label.odd { background: rgba(0, 0, 0, 0.05); }"; + // Some Adwaita stupidity + const char *style = "notebook header tab { padding: 2px 8px; margin: 0; }"; GdkScreen *screen = gdk_screen_get_default (); GtkCssProvider *provider = gtk_css_provider_new (); @@ -330,20 +236,6 @@ main (int argc, char *argv[]) gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - g.grid = gtk_grid_new (); - gtk_grid_set_column_homogeneous (GTK_GRID (g.grid), TRUE); - - // FIXME: we'd rather like to trim the contents, not make it scrollable. - // This just limits the allocation. - // TODO: probably create a whole new custom widget, everything is text - // anyway and mostly handled by Pango, including pango_layout_xy_to_index() - // - I don't know where to get selection colour but inversion works, too - GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_NEVER, GTK_POLICY_EXTERNAL); - gtk_widget_set_can_focus (scrolled_window, FALSE); - gtk_container_add (GTK_CONTAINER (scrolled_window), g.grid); - g.notebook = gtk_notebook_new (); g_signal_connect (g.notebook, "switch-page", G_CALLBACK (on_switch_page), NULL); @@ -375,21 +267,28 @@ main (int argc, char *argv[]) // TODO: attach to the "key-press-event" signal and implement ^W at least, // though ^U is working already! Note that bindings can be done in CSS // as well, if we have any extra specially for the editor - g_signal_connect (g.entry, "changed", G_CALLBACK (on_changed), g.grid); + g_signal_connect (g.entry, "changed", G_CALLBACK (on_changed), g.view); + // TODO: make the entry have a background colour, rather than transparency gtk_entry_set_has_frame (GTK_ENTRY (g.entry), FALSE); // TODO: supposedly attach to "key-press-event" here and react to // PageUp/PageDown and up/down arrow keys... either here or in the Entry g.window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size (GTK_WINDOW (g.window), 300, 600); g_signal_connect (g.window, "destroy", G_CALLBACK (on_destroy), NULL); g_signal_connect (g.window, "key-press-event", G_CALLBACK (on_key_press), NULL); + GtkWidget *superbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1); gtk_container_add (GTK_CONTAINER (g.window), superbox); gtk_container_add (GTK_CONTAINER (superbox), g.notebook); gtk_container_add (GTK_CONTAINER (superbox), g.entry); - gtk_box_pack_end (GTK_BOX (superbox), scrolled_window, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (superbox), + gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)); + + g.view = stardict_view_new (); + gtk_box_pack_end (GTK_BOX (superbox), g.view, TRUE, TRUE, 0); for (gsize i = 0; i < g.dictionaries_len; i++) { @@ -403,13 +302,6 @@ main (int argc, char *argv[]) g_signal_connect (clipboard, "owner-change", G_CALLBACK (on_selection), NULL); - // Make sure to fill up the window with entries once we're resized - // XXX: this is rather inefficient as we rebuild everything each time - g_signal_connect (g.window, "configure-event", - G_CALLBACK (on_changed), NULL); - g_signal_connect (g.window, "map-event", - G_CALLBACK (on_changed), NULL); - gtk_widget_grab_focus (g.entry); gtk_widget_show_all (g.window); gtk_main (); |