summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McDermott <pj@pehjota.net>2017-10-17 01:01:37 (EDT)
committer Patrick McDermott <pj@pehjota.net>2017-10-17 02:49:22 (EDT)
commitcd8dbba39302c957d62a754e7b84b99d7e2aa91e (patch)
tree0ca21d4ea68c3bea9272b5868e01253d968affc4
parent3e47b6181418e1df3efe964b7f1d5874c120b508 (diff)
downloadmarquee-cd8dbba39302c957d62a754e7b84b99d7e2aa91e.zip
marquee-cd8dbba39302c957d62a754e7b84b99d7e2aa91e.tar.gz
marquee-cd8dbba39302c957d62a754e7b84b99d7e2aa91e.tar.bz2
MqTab: Use MqTabLabel
-rw-r--r--src/tab.c407
-rw-r--r--src/tab.h11
2 files changed, 34 insertions, 384 deletions
diff --git a/src/tab.c b/src/tab.c
index 917e1e3..318d40b 100644
--- a/src/tab.c
+++ b/src/tab.c
@@ -25,6 +25,7 @@
#include <gtk/gtk.h>
+#include "tab-label.h"
#include "toolbars/find-toolbar.h"
#include "toolbars/navigation-toolbar.h"
#include "web-view.h"
@@ -39,35 +40,13 @@ foreach_tab(MqTab *node, void (*cb)(MqTab *node))
}
static void
-update_tab_image(MqTab *tab, GdkPixbuf *favicon)
-{
- if (favicon) {
- gtk_image_set_from_pixbuf(GTK_IMAGE(tab->tab_image), favicon);
- } else {
- gtk_image_set_from_icon_name(GTK_IMAGE(tab->tab_image),
- "text-x-generic", GTK_ICON_SIZE_BUTTON);
- }
-}
-
-static void
-update_tab_label(MqTab *tab)
-{
- const gchar *title;
- gchar *label;
-
- title = tab->scrolling ? tab->scrolled_title : tab->title;
- label = g_strdup_printf("%d. %s", tab->position, title);
- gtk_label_set_text(GTK_LABEL(tab->tab_label), label);
- gtk_widget_set_tooltip_text(tab->tab, label);
- g_free(label);
-}
-
-static void
update_positions(MqTab *node, gint step)
{
if (node) {
node->position += step;
- update_tab_label(node);
+ if (node->tab) {
+ mq_tab_label_set_position(node->tab, node->position);
+ }
if (node->next) {
update_positions(node->next, step);
} else if (node->parent && node->parent->next) {
@@ -125,294 +104,10 @@ append_sibling(MqTab *new_node, MqTab *prev_sibling)
}
static void
-reload_tab_clicked_cb(GtkWidget G_GNUC_UNUSED *button, MqTab *tab)
-{
- webkit_web_view_reload(tab->web_view);
- gtk_widget_hide(tab->popover);
-}
-
-static void
-new_tab_clicked_cb(GtkWidget G_GNUC_UNUSED *button, MqTab *tab)
-{
- mq_tab_new(NULL, tab);
- gtk_widget_hide(tab->popover);
-}
-
-static void
-new_window_clicked_cb(GtkWidget G_GNUC_UNUSED *button, MqTab *tab)
-{
- mq_application_add_window(tab->application, NULL);
- gtk_widget_hide(tab->popover);
-}
-
-static void
-tab_list_button_toggled_cb(GtkToggleButton *toggle_button, GtkWidget *tab_list)
-{
- if (gtk_toggle_button_get_active(toggle_button)) {
- gtk_widget_show(tab_list);
- } else {
- gtk_widget_hide(tab_list);
- }
-}
-
-static void
-create_tree_model_recurse(MqTab *node, GtkTreeStore *tree_store,
- GtkTreeIter *parent_tree_iter)
-{
- GtkTreeIter tree_iter;
-
- for (; node; node = node->next) {
- gtk_tree_store_append(tree_store, &tree_iter, parent_tree_iter);
- gtk_tree_store_set(tree_store, &tree_iter, 0, node->title, -1);
- create_tree_model_recurse(node->first_child, tree_store,
- &tree_iter);
- }
-}
-
-static GtkTreeModel *
-create_tree_model(MqTab *tab)
-{
- GtkTreeStore *tree_store;
-
- tree_store = gtk_tree_store_new(1, G_TYPE_STRING);
-
- create_tree_model_recurse(tab->root->first_child, tree_store, NULL);
-
- return GTK_TREE_MODEL(tree_store);
-}
-
-static void
-row_activated_cb(GtkTreeView G_GNUC_UNUSED *tree_view, GtkTreePath *tree_path,
- GtkTreeViewColumn G_GNUC_UNUSED *tree_view_column, MqTab *tab)
-{
- gint *indices;
- gint depth;
-
- indices = gtk_tree_path_get_indices_with_depth(tree_path, &depth);
- g_assert(depth == 1);
- mq_window_set_current_tab(tab->window, indices[0] + 1);
- gtk_widget_hide(tab->popover);
-}
-
-static GtkWidget *
-create_tab_list(MqTab *tab)
-{
- GtkWidget *tree_view;
- GtkTreeSelection *tree_selection;
- GtkCellRenderer *cell_renderer;
- GtkWidget *scrolled_window;
-
- tree_view = gtk_tree_view_new_with_model(create_tree_model(tab));
- tree_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
- gtk_tree_selection_set_mode(tree_selection, GTK_SELECTION_BROWSE);
- gtk_tree_selection_select_path(tree_selection,
- gtk_tree_path_new_from_indices(
- mq_window_get_current_tab(tab->window) - 1, -1));
- gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE);
- gtk_tree_view_set_activate_on_single_click(GTK_TREE_VIEW(tree_view),
- TRUE);
- gtk_tree_view_expand_all(GTK_TREE_VIEW(tree_view));
- gtk_tree_view_set_reorderable(GTK_TREE_VIEW(tree_view), TRUE);
- gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(tree_view), TRUE);
- g_signal_connect(tree_view, "row-activated",
- G_CALLBACK(row_activated_cb), tab);
-
- cell_renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(tree_view),
- -1, NULL, cell_renderer, "text", 0, NULL);
-
- scrolled_window = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_min_content_width(
- GTK_SCROLLED_WINDOW(scrolled_window), 400);
- gtk_scrolled_window_set_min_content_height(
- GTK_SCROLLED_WINDOW(scrolled_window), 200);
- gtk_container_add(GTK_CONTAINER(scrolled_window), tree_view);
-
- return scrolled_window;
-}
-
-#define BUTTON_ROWS 2
-#define BUTTON_COLS 4
-#define NEW_BUTTON(Y, X, ICON, TOOLTIP) \
- do { \
- buttons[Y * BUTTON_COLS + X] = gtk_button_new_from_icon_name(\
- ICON, GTK_ICON_SIZE_BUTTON); \
- gtk_widget_set_tooltip_text(buttons[Y * BUTTON_COLS + X], \
- TOOLTIP); \
- gtk_widget_set_can_focus(buttons[Y * BUTTON_COLS + X], FALSE); \
- gtk_grid_attach(GTK_GRID(button_grid), \
- buttons[Y * BUTTON_COLS + X], X, Y, 1, 1); \
- } while (0)
-#define NEW_TOGGLE(Y, X, ICON, TOOLTIP) \
- do { \
- buttons[Y * BUTTON_COLS + X] = gtk_toggle_button_new(); \
- gtk_button_set_image(GTK_BUTTON(buttons[Y * BUTTON_COLS + X]), \
- gtk_image_new_from_icon_name(ICON, \
- GTK_ICON_SIZE_BUTTON)); \
- gtk_widget_set_tooltip_text(buttons[Y * BUTTON_COLS + X], \
- TOOLTIP); \
- gtk_widget_set_can_focus(buttons[Y * BUTTON_COLS + X], FALSE); \
- gtk_grid_attach(GTK_GRID(button_grid), \
- buttons[Y * BUTTON_COLS + X], X, Y, 1, 1); \
- } while (0)
-#define CLICKED_CB(Y, X, CB) \
- g_signal_connect(buttons[Y * BUTTON_COLS + X], "clicked", CB, tab)
-
-static void
-create_tab_popover(GtkWidget *widget, MqTab *tab)
-{
- GtkWidget *button_grid;
- GtkWidget *buttons[BUTTON_ROWS * BUTTON_COLS];
- GtkWidget *tab_list;
- GtkWidget *tab_list_scrolled_window;
- GtkWidget *box;
-
- /* Set up button grid. */
- button_grid = gtk_grid_new();
- gtk_widget_set_halign(button_grid, GTK_ALIGN_CENTER);
-
- /* Set up buttons. */
- NEW_BUTTON(0, 0, "view-refresh", "Reload tab");
- NEW_BUTTON(0, 1, "edit-copy", "Duplicate tab");
- NEW_BUTTON(0, 2, "window-new", "Move tab to new window");
- NEW_BUTTON(0, 3, "window-close", "Close tab");
- NEW_BUTTON(1, 0, "tab-new-symbolic", "New tab");
- NEW_BUTTON(1, 1, "window-new", "New window");
- NEW_BUTTON(1, 2, "edit-undo", "Undo close tab");
- NEW_TOGGLE(1, 3, "view-list-symbolic", "Tab list...");
-
- CLICKED_CB(0, 0, G_CALLBACK(reload_tab_clicked_cb));
- CLICKED_CB(1, 0, G_CALLBACK(new_tab_clicked_cb));
- CLICKED_CB(1, 1, G_CALLBACK(new_window_clicked_cb));
-
- /* Set up the tab list. */
- tab_list = create_tab_list(tab);
-
- /* Set up the tab list scrolled window.
- *
- * The following GtkScrolledWindow widget has a hardcoded minimum size,
- * because there seems to be (in GTK+ versions before 3.22) no way to
- * set the natural size of GtkScrolledWindow and its GtkViewport.
- *
- * See tab-chrome.c for more information. */
- tab_list_scrolled_window = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_min_content_width(
- GTK_SCROLLED_WINDOW(tab_list_scrolled_window), 400);
- gtk_scrolled_window_set_min_content_height(
- GTK_SCROLLED_WINDOW(tab_list_scrolled_window), 200);
- gtk_container_add(GTK_CONTAINER(tab_list_scrolled_window), tab_list);
-
- /* Add tab list toggle button handler. */
- g_signal_connect(buttons[1 * BUTTON_COLS + 3], "toggled",
- G_CALLBACK(tab_list_button_toggled_cb),
- tab_list_scrolled_window);
-
- /* Set up the button rows box. */
- box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- gtk_box_pack_start(GTK_BOX(box), button_grid,
- TRUE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(box), tab_list_scrolled_window,
- TRUE, FALSE, 0);
-
- /* Set up the popover. */
- tab->popover = gtk_popover_new(widget);
- gtk_container_add(GTK_CONTAINER(tab->popover), box);
-
- /* NB: gtk_popover_popup() is new in GTK+ 3.22. */
- gtk_widget_show_all(tab->popover);
- gtk_widget_hide(tab_list_scrolled_window);
-}
-
-#undef BUTTON_ROWS
-#undef BUTTON_COLS
-#undef NEW_BUTTON
-#undef NEW_TOGGLE
-#undef CLICKED_CB
-
-static gboolean
-tab_label_button_press_cb(GtkWidget *widget, GdkEventButton *event, MqTab *tab)
-{
- /* Create a popover menu on right click. */
- if (event->button == 3) {
- create_tab_popover(widget, tab);
- }
-
- return FALSE;
-}
-
-static void
-mq_tab_populate_tab(MqTab *tab)
-{
- GtkWidget *close_button;
- GtkWidget *box;
-
- tab->title = "New tab";
-
- /* Set up tab image. */
- tab->tab_image = gtk_image_new_from_icon_name("text-x-generic",
- GTK_ICON_SIZE_BUTTON);
-
- /* Set up tab label. */
- tab->tab_label = gtk_label_new(NULL);
- gtk_label_set_ellipsize(GTK_LABEL(tab->tab_label),
- PANGO_ELLIPSIZE_END);
- gtk_widget_set_hexpand(tab->tab_label, TRUE);
- gtk_widget_set_size_request(tab->tab_label, 50, 1);
-
- /* Set up close button. */
- close_button = gtk_button_new_from_icon_name("window-close",
- GTK_ICON_SIZE_BUTTON);
- gtk_widget_set_tooltip_text(close_button, "Close tab");
-
- /* Pack tab box. */
- box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_box_pack_start(GTK_BOX(box), tab->tab_image, FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(box), tab->tab_label, TRUE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(box), close_button, FALSE, FALSE, 0);
- gtk_widget_show_all(box);
-
- /* Set up event box. */
- tab->tab = gtk_event_box_new();
- g_signal_connect(tab->tab, "button-press-event",
- G_CALLBACK(tab_label_button_press_cb), tab);
- gtk_event_box_set_visible_window(GTK_EVENT_BOX(tab->tab),
- FALSE);
- gtk_container_add(GTK_CONTAINER(tab->tab), box);
-}
-
-static void
-favicon_cb(WebKitWebView G_GNUC_UNUSED *web_view,
- GParamSpec G_GNUC_UNUSED *param_spec, MqTab *tab)
-{
- cairo_surface_t *surface;
- GdkPixbuf *pixbuf;
- GdkPixbuf *scaled_pixbuf;
-
- surface = webkit_web_view_get_favicon(tab->web_view);
- scaled_pixbuf = NULL;
- if (surface) {
- pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0,
- cairo_image_surface_get_width(surface),
- cairo_image_surface_get_height(surface));
- if (pixbuf) {
- scaled_pixbuf = gdk_pixbuf_scale_simple(pixbuf, 16, 16,
- GDK_INTERP_BILINEAR);
- g_object_unref(pixbuf);
- }
- }
-
- update_tab_image(tab, scaled_pixbuf);
-}
-
-static void
title_cb(WebKitWebView G_GNUC_UNUSED *web_view,
GParamSpec G_GNUC_UNUSED *param_spec, MqTab *tab)
{
tab->title = webkit_web_view_get_title(tab->web_view);
- if (tab->scrolling) {
- tab->scrolled_title = g_strdup_printf("%s ", tab->title);
- }
- update_tab_label(tab);
mq_window_update_tab_title(tab->window, tab->position, tab->title);
}
@@ -429,18 +124,17 @@ init_non_root(const gchar *uri, MqTab *source)
tab->next = NULL;
tab->first_child = tab->last_child = NULL;
tab->tree_size = 1;
+ tab->title = "New tab";
tab->window = source->window;
tab->application = mq_window_get_application(tab->window);
- mq_tab_populate_tab(tab);
-
tab->web_view = WEBKIT_WEB_VIEW(mq_web_view_new(tab, uri));
- g_signal_connect(tab->web_view, "notify::favicon",
- G_CALLBACK(favicon_cb), tab);
g_signal_connect(tab->web_view, "notify::title",
G_CALLBACK(title_cb), tab);
+ tab->tab = mq_tab_label_new(tab, MQ_WEB_VIEW(tab->web_view));
+
find_toolbar = mq_find_toolbar_new(MQ_WEB_VIEW(tab->web_view));
/* FIXME: Replace tab->window->config */
@@ -458,56 +152,6 @@ init_non_root(const gchar *uri, MqTab *source)
return tab;
}
-static void
-scroll_tab_label(MqTab *tab)
-{
- gchar c[5]; /* Up to 4 bytes for a UTF-8 character, plus NUL */
- guint i;
- guint j;
-
- /* Save the first (possibly multibyte) character. */
- c[0] = tab->scrolled_title[0];
- for (i = 1; tab->scrolled_title[i] & 0x80; ++i) {
- c[i] = tab->scrolled_title[i];
- }
- c[i] = '\0';
-
- /* Shift all characters. */
- for (j = 0; tab->scrolled_title[i]; ++i, ++j) {
- tab->scrolled_title[j] = tab->scrolled_title[i];
- }
-
- /* Set the last (possibly multibyte) character. */
- for (--j, i = 0; c[i]; ++i, ++j) {
- tab->scrolled_title[j] = c[i];
- }
-
- update_tab_label(tab);
-}
-
-static void
-begin_scrolling_tab_label(MqTab *tab)
-{
- PangoFontDescription *font_desc;
-
- tab->scrolling = TRUE;
- tab->scrolled_title = g_strdup_printf("%s ", tab->title);
-
- font_desc = pango_font_description_new();
- pango_font_description_set_family_static(font_desc, "monospace");
- gtk_widget_override_font(tab->tab_label, font_desc);
-}
-
-static void
-end_scrolling_tab_label(MqTab *tab)
-{
- tab->scrolling = FALSE;
-
- gtk_widget_override_font(tab->tab_label, NULL);
-
- update_tab_label(tab);
-}
-
MqTab *
mq_tab_new(const gchar *uri, MqTab *source)
{
@@ -516,9 +160,7 @@ mq_tab_new(const gchar *uri, MqTab *source)
tab = init_non_root(uri, source);
if (mq_application_marquee_mode_on(tab->application)) {
- begin_scrolling_tab_label(tab);
- } else {
- tab->scrolling = FALSE;
+ mq_tab_label_begin_scrolling(MQ_TAB_LABEL(tab->tab));
}
append_sibling(tab, source);
@@ -537,9 +179,7 @@ mq_tab_new_relative(const gchar *uri, MqTab *source)
tab = init_non_root(uri, source);
if (mq_application_marquee_mode_on(tab->application)) {
- begin_scrolling_tab_label(tab);
- } else {
- tab->scrolling = FALSE;
+ mq_tab_label_begin_scrolling(MQ_TAB_LABEL(tab->tab));
}
append_child(tab, source);
@@ -590,7 +230,7 @@ void
mq_tab_update_position(MqTab *tab, guint position)
{
tab->position = position;
- update_tab_label(tab);
+ mq_tab_label_set_position(tab->tab, position);
}
guint
@@ -634,19 +274,34 @@ mq_tab_seek(MqTab *node, guint position)
}
void
-mq_tab_scroll_tab_labels(MqTab *root)
+mq_tab_scroll_tab_labels(MqTab *node)
{
- foreach_tab(root->first_child, scroll_tab_label);
+ for (; node; node = node->next) {
+ if (node->tab) {
+ mq_tab_label_scroll(MQ_TAB_LABEL(node->tab));
+ }
+ mq_tab_scroll_tab_labels(node->first_child);
+ }
}
void
-mq_tab_begin_scrolling_tab_labels(MqTab *root)
+mq_tab_begin_scrolling_tab_labels(MqTab *node)
{
- foreach_tab(root->first_child, begin_scrolling_tab_label);
+ for (; node; node = node->next) {
+ if (node->tab) {
+ mq_tab_label_begin_scrolling(MQ_TAB_LABEL(node->tab));
+ }
+ mq_tab_begin_scrolling_tab_labels(node->first_child);
+ }
}
void
-mq_tab_end_scrolling_tab_labels(MqTab *root)
+mq_tab_end_scrolling_tab_labels(MqTab *node)
{
- foreach_tab(root->first_child, end_scrolling_tab_label);
+ for (; node; node = node->next) {
+ if (node->tab) {
+ mq_tab_label_end_scrolling(MQ_TAB_LABEL(node->tab));
+ }
+ mq_tab_end_scrolling_tab_labels(node->first_child);
+ }
}
diff --git a/src/tab.h b/src/tab.h
index 648290e..83eed19 100644
--- a/src/tab.h
+++ b/src/tab.h
@@ -44,13 +44,8 @@ struct MqTab {
MqWindow *window;
GtkWidget *container;
GtkWidget *tab;
- GtkWidget *tab_image;
- GtkWidget *tab_label;
const gchar *title;
WebKitWebView *web_view;
- GtkWidget *popover;
- gboolean scrolling;
- gchar *scrolled_title;
};
MqTab *
@@ -87,12 +82,12 @@ MqTab *
mq_tab_seek(MqTab *node, guint position);
void
-mq_tab_scroll_tab_labels(MqTab *root);
+mq_tab_scroll_tab_labels(MqTab *node);
void
-mq_tab_begin_scrolling_tab_labels(MqTab *root);
+mq_tab_begin_scrolling_tab_labels(MqTab *node);
void
-mq_tab_end_scrolling_tab_labels(MqTab *root);
+mq_tab_end_scrolling_tab_labels(MqTab *node);
#endif