[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: xchat 1.9.4 (devel) (scrolled tabs)



On Tue, 5 Nov 2002 17:54:27 +1100
Peter Zelezny <zed@linux.com> wrote:

> ...
> * tabs can't scroll when filling the whole window
>   (use a ScrolledWindow or multiple rows?) May need help with this
>   one.
> ...

Attached is a sort of concept patch. It contains the tabs box within a
Viewport, and uses two buttons to jump left and right within the
Viewport. It's a less than ideal solution, but I think it's tidier
than a ScrolledWindow.
diff -rNu xchat-1.9.4-orig/src/fe-gtk/maingui.c xchat-1.9.4-scrolled-tabs/src/fe-gtk/maingui.c
--- xchat-1.9.4-orig/src/fe-gtk/maingui.c	2002-10-23 12:52:56.000000000 +0100
+++ xchat-1.9.4-scrolled-tabs/src/fe-gtk/maingui.c	2002-11-06 18:26:55.000000000 +0000
@@ -40,6 +40,7 @@
 #include <gtk/gtkimage.h>
 #include <gtk/gtkmessagedialog.h>
 #include <gtk/gtkradiomenuitem.h>
+#include <gtk/gtkobject.h>
 
 #include "../common/xchat.h"
 #include "../common/fe.h"
@@ -1620,25 +1621,82 @@
 		mg_show_generic_tab (active_tab);
 }
 
+/*
+ * GtkViewports request at least as much space as their children do.
+ * If we don't intervene here, the GtkViewport will be granted its
+ * request, even at the expense of resizing the top-level window.
+ */
+static void
+mg_tab_viewport_size_request (GtkWidget *widget, GtkRequisition *requisition, gpointer user_data)
+{
+	requisition->width = 10;
+}
+
+static void
+mg_tab_scroll_left_clicked (GtkWidget *widget, gpointer user_data)
+{
+	session_gui *gui = user_data;
+	GtkAdjustment *adjustment;
+	gint viewport_width;
+	gfloat new_value;
+
+	adjustment = gtk_viewport_get_hadjustment (GTK_VIEWPORT (gui->tabs_box->parent));
+	gdk_window_get_geometry (gui->tabs_box->parent->window, 0, 0, &viewport_width, 0, 0);
+	new_value = tab_search_offset (gui->tabs_box, adjustment->value, 0);
+
+	if (new_value + viewport_width > adjustment->upper)
+		new_value = adjustment->upper - viewport_width;
+
+	gtk_adjustment_set_value (adjustment, new_value);
+}
+
+static void
+mg_tab_scroll_right_clicked (GtkWidget *widget, gpointer user_data)
+{
+	session_gui *gui = user_data;
+	GtkAdjustment *adjustment;
+	gint viewport_width;
+	gfloat new_value;
+
+	adjustment = gtk_viewport_get_hadjustment (GTK_VIEWPORT (gui->tabs_box->parent));
+	gdk_window_get_geometry (gui->tabs_hbox->parent->window, 0, 0, &viewport_width, 0, 0);
+	new_value = tab_search_offset (gui->tabs_box, adjustment->value, 1);
+
+	if (new_value == 0 || new_value + viewport_width > adjustment->upper)
+		new_value = adjustment->upper - viewport_width;
+
+	gtk_adjustment_set_value (adjustment, new_value);
+}
+
 static void
 mg_create_tabs (session_gui *gui, GtkWidget *box)
 {
-/*	GtkWidget *sc;
-	GtkWidget *frame;
+	GtkWidget *hbox;
+	GtkWidget *viewport;
+	GtkWidget *button;
 
-	frame = gtk_frame_new (NULL);
-	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
-	gtk_box_pack_start (GTK_BOX (box), frame, 0, 0, 0);*/
+	hbox = gtk_hbox_new (0, 0);
+	gtk_widget_show (hbox);
+	gtk_box_pack_start (GTK_BOX (box), 0, 0, 0);
 
-	gui->tabs_box = tab_group_new (mg_switch_tab_cb);
+	viewport = gtk_viewport_new (0, 0);
+	gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE);
+	gtk_signal_connect (GTK_OBJECT (viewport), "size_request", GTK_SIGNAL_FUNC (mg_tab_viewport_size_request), 0);
+	gtk_widget_show (viewport);
+	gtk_box_pack_start (GTK_BOX (hbox), viewport, 1, 1, 0);
 
-/*	sc = gtk_scrolled_window_new (0, 0);
-	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sc),
-											  GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
-	gtk_scrolled_window_add_with_viewport (sc, gui->tabs_box);*/
+	gui->tabs_box = tab_group_new (mg_switch_tab_cb);
+	gtk_container_add (GTK_CONTAINER (viewport), gui->tabs_box);
 
-	gtk_box_pack_start (GTK_BOX (box), gui->tabs_box, 0, 0, 0);
-/*	gtk_container_add (GTK_CONTAINER (frame), gui->tabs_box);*/
+	button = gtk_button_new_with_label ("<");
+	gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (mg_tab_scroll_left_clicked), gui);
+	gtk_widget_show (button);
+	gtk_box_pack_start (GTK_BOX (hbox), button, 0, 0, 0);
+
+	button = gtk_button_new_with_label (">");
+	gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (mg_tab_scroll_right_clicked), gui);
+	gtk_widget_show (button);
+	gtk_box_pack_start (GTK_BOX (hbox), button, 0, 0, 0);
 }
 
 static gboolean
diff -rNu xchat-1.9.4-orig/src/fe-gtk/tabs.c xchat-1.9.4-scrolled-tabs/src/fe-gtk/tabs.c
--- xchat-1.9.4-orig/src/fe-gtk/tabs.c	2002-10-23 12:42:45.000000000 +0100
+++ xchat-1.9.4-scrolled-tabs/src/fe-gtk/tabs.c	2002-11-06 18:20:29.000000000 +0000
@@ -335,3 +335,41 @@
 		tab_group_switch (group, 0, FALSE);
 	}
 }
+
+gint
+tab_search_offset (GtkWidget *group, gint start_offset, gboolean forward)
+{
+	GList *boxes;
+	GList *tabs;
+	GtkWidget *box;
+	GtkWidget *button;
+
+	boxes = GTK_BOX (group)->children;
+	if (!forward && boxes)
+		boxes = g_list_last (boxes);
+
+	while (boxes)
+	{
+		box = ((GtkBoxChild *)boxes->data)->widget;
+		boxes = (forward ? boxes->next : boxes->prev);
+
+		tabs = GTK_BOX (box)->children;
+		if (!forward && tabs)
+			tabs = g_list_last (tabs);
+
+		while (tabs)
+		{
+			button = ((GtkBoxChild *)tabs->data)->widget;
+			tabs = (forward ? tabs->next : tabs->prev);
+
+			if (!GTK_IS_TOGGLE_BUTTON (button))
+				continue;
+
+			if ((forward && button->allocation.x > start_offset) ||
+			    (!forward && button->allocation.x < start_offset))
+				return button->allocation.x;
+		}
+	}
+
+	return 0;
+}
diff -rNu xchat-1.9.4-orig/src/fe-gtk/tabs.h xchat-1.9.4-scrolled-tabs/src/fe-gtk/tabs.h
--- xchat-1.9.4-orig/src/fe-gtk/tabs.h	2002-05-04 07:44:48.000000000 +0100
+++ xchat-1.9.4-scrolled-tabs/src/fe-gtk/tabs.h	2002-11-06 18:27:18.000000000 +0000
@@ -5,3 +5,4 @@
 void tab_rename (GtkWidget *tab, char *new_name);
 void tab_remove (GtkWidget *tab);
 void tab_style (GtkWidget *tab, GtkStyle *style);
+gint tab_search_offset (GtkWidget *group, gint start_offset, gboolean forward);