[Xfce4-commits] r23426 - xarchiver/branches/xarchiver-psybsd/src

Stephan Arts stephan at xfce.org
Sun Oct 15 22:18:52 UTC 2006


Author: stephan
Date: 2006-10-15 22:18:51 +0000 (Sun, 15 Oct 2006)
New Revision: 23426

Added:
   xarchiver/branches/xarchiver-psybsd/src/path_bar.c
   xarchiver/branches/xarchiver-psybsd/src/path_bar.h
Log:
Add the actual path_bar code.


Added: xarchiver/branches/xarchiver-psybsd/src/path_bar.c
===================================================================
--- xarchiver/branches/xarchiver-psybsd/src/path_bar.c	                        (rev 0)
+++ xarchiver/branches/xarchiver-psybsd/src/path_bar.c	2006-10-15 22:18:51 UTC (rev 23426)
@@ -0,0 +1,526 @@
+/*
+ *  Copyright (c) 2006 Stephan Arts <psybsd at gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gettext.h>
+#include <libxarchiver/libxarchiver.h>
+#include "archive_store.h"
+#include "navigation_bar.h"
+#include "path_bar.h"
+
+
+static void
+xa_path_bar_class_init(XAPathBarClass *archive_class);
+
+static void
+xa_path_bar_init(XAPathBar *archive);
+
+static void
+xa_path_bar_size_request(GtkWidget *widget, GtkRequisition *requisition);
+static void
+xa_path_bar_size_allocate(GtkWidget *widget, GtkAllocation *allocation);
+
+static GType
+xa_path_bar_child_type(GtkContainer *container);
+static void
+xa_path_bar_add(GtkContainer *container, GtkWidget *child);
+static void
+xa_path_bar_remove(GtkContainer *container, GtkWidget *child);
+static void
+xa_path_bar_forall(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data);
+
+static void
+cb_xa_path_bar_pwd_changed(XAArchiveStore *store, XAPathBar *bar);
+
+static void
+cb_xa_path_bar_path_button_clicked(GtkRadioButton *button, XAPathBar *path_bar);
+static void
+cb_xa_path_bar_scroll_left(GtkWidget *widget, gpointer user_data);
+static void
+cb_xa_path_bar_scroll_right(GtkWidget *widget, gpointer user_data);
+
+GType
+xa_path_bar_get_type ()
+{
+	static GType xa_path_bar_type = 0;
+
+ 	if (!xa_path_bar_type)
+	{
+ 		static const GTypeInfo xa_path_bar_info = 
+		{
+			sizeof (XAPathBarClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) xa_path_bar_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,
+			sizeof (XAPathBar),
+			0,
+			(GInstanceInitFunc) xa_path_bar_init,
+			NULL
+		};
+
+		xa_path_bar_type = g_type_register_static (XA_TYPE_NAVIGATION_BAR, "XAPathBar", &xa_path_bar_info, 0);
+	}
+	return xa_path_bar_type;
+}
+
+static void
+xa_path_bar_class_init(XAPathBarClass *path_bar_class)
+{
+	GtkWidgetClass *widget_class;
+	GtkContainerClass *container_class;
+
+	widget_class = (GtkWidgetClass*)path_bar_class;
+	container_class = (GtkContainerClass*)path_bar_class;
+
+	widget_class->size_request = xa_path_bar_size_request;
+	widget_class->size_allocate = xa_path_bar_size_allocate;
+
+	container_class->add = xa_path_bar_add;
+	container_class->remove = xa_path_bar_remove;
+	container_class->forall = xa_path_bar_forall;
+	container_class->child_type = xa_path_bar_child_type;
+
+	gtk_widget_class_install_style_property (widget_class,
+		g_param_spec_int ("spacing",
+		_("Spacing"),
+		_("The amount of space between the path buttons"),
+		0, G_MAXINT, 3,
+		G_PARAM_READABLE));
+}
+
+static void
+xa_path_bar_init(XAPathBar *path_bar)
+{
+	GtkWidget *arrow;
+	XA_NAVIGATION_BAR(path_bar)->_cb_pwd_changed = (GCallback)cb_xa_path_bar_pwd_changed;
+
+	GTK_WIDGET_SET_FLAGS(path_bar, GTK_NO_WINDOW);
+	gtk_widget_set_redraw_on_allocate(GTK_WIDGET(path_bar), FALSE);
+
+	path_bar->left_button = GTK_BUTTON(gtk_button_new());
+	g_signal_connect(G_OBJECT(path_bar->left_button), "clicked", G_CALLBACK(cb_xa_path_bar_scroll_left), path_bar);
+	gtk_container_add(GTK_CONTAINER(path_bar), GTK_WIDGET(path_bar->left_button));
+	gtk_widget_show(GTK_WIDGET(path_bar->left_button));
+	gtk_widget_ref(GTK_WIDGET(path_bar->left_button));
+
+	arrow = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_OUT);
+	gtk_container_add (GTK_CONTAINER (path_bar->left_button), arrow);
+	gtk_widget_show (arrow);
+
+	path_bar->right_button = GTK_BUTTON(gtk_button_new());
+	g_signal_connect(G_OBJECT(path_bar->right_button), "clicked", G_CALLBACK(cb_xa_path_bar_scroll_right), path_bar);
+	gtk_container_add(GTK_CONTAINER(path_bar), GTK_WIDGET(path_bar->right_button));
+	gtk_widget_show(GTK_WIDGET(path_bar->right_button));
+	gtk_widget_ref(GTK_WIDGET(path_bar->right_button));
+
+	arrow = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_OUT);
+	gtk_container_add (GTK_CONTAINER (path_bar->right_button), arrow);
+	gtk_widget_show (arrow);
+
+	path_bar->path_button = NULL;
+	path_bar->first_button = NULL;
+
+	gtk_widget_ref(GTK_WIDGET(path_bar));
+}
+
+XANavigationBar *
+xa_path_bar_new(XAArchiveStore *store)
+{
+	XANavigationBar *bar;
+
+	bar = g_object_new(XA_TYPE_PATH_BAR, NULL);
+
+	if(store)
+		xa_navigation_bar_set_store(XA_NAVIGATION_BAR(bar), store);
+
+	return bar;
+}
+
+static GType
+xa_path_bar_child_type(GtkContainer *container)
+{
+	if(!XA_PATH_BAR(container)->path_button)
+		return GTK_TYPE_WIDGET;
+	else
+		return G_TYPE_NONE;
+}
+
+static void
+xa_path_bar_add(GtkContainer *container, GtkWidget *child)
+{
+	XAPathBar *path_bar = XA_PATH_BAR(container);
+
+	g_return_if_fail(GTK_IS_WIDGET(child));
+
+	/* list is stored somewhere else */
+	gtk_widget_set_parent(child, GTK_WIDGET(path_bar));
+}
+
+static void
+xa_path_bar_remove(GtkContainer *container, GtkWidget *child)
+{
+	gboolean widget_was_visible;
+
+	g_return_if_fail(GTK_IS_WIDGET(child));
+
+	widget_was_visible = GTK_WIDGET_VISIBLE(child);
+
+	gtk_widget_unparent(child);
+
+	/* remove from list is somewhere else */
+	if(widget_was_visible)
+		gtk_widget_queue_resize(GTK_WIDGET(container));
+}
+
+static void
+xa_path_bar_forall(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data)
+{
+	XAPathBar *path_bar = XA_PATH_BAR(container);
+
+	g_return_if_fail(callback != NULL);
+
+	g_slist_foreach(path_bar->path_button, (GFunc)callback, callback_data);
+
+	if(path_bar->left_button)
+		(*callback)(GTK_WIDGET(path_bar->left_button), callback_data);
+	if(path_bar->right_button)
+		(*callback)(GTK_WIDGET(path_bar->right_button), callback_data);
+}
+
+static void
+xa_path_bar_size_request(GtkWidget *widget, GtkRequisition *requisition)
+{
+	XAPathBar *path_bar = XA_PATH_BAR(widget);
+	GSList *iter = NULL;
+	GtkRequisition child_requisition;
+	gint spacing = 0;
+	gtk_widget_style_get(widget, "spacing", &spacing, NULL);
+
+	requisition->width = 0;
+	requisition->height = 0;
+
+	/* get biggest button */
+	for(iter = path_bar->path_button; iter; iter = iter->next)
+	{
+		gtk_widget_size_request(GTK_WIDGET(iter->data), &child_requisition);
+		requisition->width = MAX(child_requisition.width, requisition->width);
+		requisition->height = MAX(child_requisition.height, requisition->height);
+	}
+
+	gtk_widget_size_request(GTK_WIDGET(path_bar->left_button), &child_requisition);
+	gtk_widget_size_request(GTK_WIDGET(path_bar->right_button), &child_requisition);
+	/* add space for scroll buttons if more then 1 button */
+	if(path_bar->path_button && path_bar->path_button->next)
+	{
+		gtk_widget_get_child_requisition(GTK_WIDGET(path_bar->left_button), &child_requisition);
+		requisition->width += child_requisition.width + spacing;
+		requisition->height = MAX(child_requisition.height, requisition->height);
+		gtk_widget_get_child_requisition(GTK_WIDGET(path_bar->right_button), &child_requisition);
+		requisition->width += child_requisition.width;
+		requisition->height = MAX(child_requisition.height, requisition->height);
+	}
+
+	requisition->width += GTK_CONTAINER(path_bar)->border_width * 2;
+	requisition->height += GTK_CONTAINER(path_bar)->border_width * 2;
+
+	widget->requisition = *requisition;
+}
+
+static void
+xa_path_bar_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
+{
+	XAPathBar *path_bar = XA_PATH_BAR(widget);
+	gint spacing = 0;
+	gint width = 0;
+	gint left_width = 0;
+	gint right_width = 0;
+	gint border_width = 0;
+	GSList *iter  = NULL;
+	GSList *first_display = NULL;
+	GtkRequisition child_requisition;
+	GtkAllocation child_allocation;
+
+	widget->allocation = *allocation;
+
+	if(!path_bar->path_button)
+		return;
+	
+	gtk_widget_style_get(widget, "spacing", &spacing, NULL);
+
+	border_width = GTK_CONTAINER(path_bar)->border_width;
+	width = border_width * 2;
+
+	iter = path_bar->path_button;
+
+	/* are the scroll arrows needed? */
+	while(iter)
+	{
+		gtk_widget_get_child_requisition(GTK_WIDGET(iter->data), &child_requisition);
+		if(width)
+			width += spacing;
+		width += child_requisition.width;
+		iter = iter->next;
+	}
+
+	first_display = g_slist_prepend(first_display, path_bar->path_button);
+	
+	/* scroll arrows are needed */
+	if(width > allocation->width)
+	{
+		gtk_widget_get_child_requisition(GTK_WIDGET(path_bar->left_button), &child_requisition);
+		left_width = child_requisition.width;
+		gtk_widget_get_child_requisition(GTK_WIDGET(path_bar->right_button), &child_requisition);
+		right_width = child_requisition.width;
+
+		width = left_width + spacing + right_width;
+
+		if(path_bar->first_button)
+		{
+			iter = path_bar->path_button;
+			while(iter != path_bar->first_button)
+			{
+				iter = iter->next;
+				first_display = g_slist_prepend(first_display, iter);
+			}
+		}
+
+		iter = (GSList*)first_display->data;
+
+		/* are there parent maps visible? */
+		while(iter)
+		{
+			gtk_widget_get_child_requisition(GTK_WIDGET(iter->data), &child_requisition);
+			width += child_requisition.width + spacing;
+			iter = iter->next;
+		}
+
+		iter = first_display->next;
+
+		/* which parent map is visible? */
+		while(iter)
+		{
+			gtk_widget_get_child_requisition(GTK_WIDGET(((GSList*)iter->data)->data), &child_requisition);
+			width += child_requisition.width + spacing;
+			if(width > allocation->width)
+				break;
+
+			first_display = g_slist_delete_link(first_display, first_display);
+			iter = first_display->next;
+		}
+		/* first_display is the first entry from the list that fits */
+	}
+
+	child_allocation.y = allocation->y + border_width;
+	child_allocation.x = allocation->x + border_width;
+	child_allocation.height = allocation->height - (border_width * 2);
+
+	/* set visible and sensitive scroll buttons */
+	if(left_width)
+	{
+		/* set visible */
+		gtk_widget_set_child_visible(GTK_WIDGET(path_bar->left_button), TRUE);
+		child_allocation.width = left_width;
+		gtk_widget_size_allocate(GTK_WIDGET(path_bar->left_button), &child_allocation);
+
+		child_allocation.x += left_width + spacing;
+		gtk_widget_set_sensitive(GTK_WIDGET(path_bar->left_button), (first_display->data == (gpointer)path_bar->path_button)?FALSE:TRUE);
+	}
+	else
+	{
+		/* set invisible */
+		gtk_widget_set_child_visible(GTK_WIDGET(path_bar->left_button), FALSE);
+	}
+
+	/* set visible for buttons */
+	iter = (GSList*)first_display->data;
+	while(iter)
+	{
+		gtk_widget_get_child_requisition(GTK_WIDGET(iter->data), &child_requisition);
+		width = child_allocation.x + child_requisition.width;
+		if(right_width)
+			width += spacing + right_width + border_width;
+		/* check to see if there is enough space */
+		if(width > allocation->width)
+			break;
+		/* set visible */
+		gtk_widget_set_child_visible(GTK_WIDGET(iter->data), TRUE);
+		child_allocation.width = child_requisition.width;
+		gtk_widget_size_allocate(GTK_WIDGET(iter->data), &child_allocation);
+
+		child_allocation.x += child_requisition.width + spacing;
+		iter = iter->next;
+	}
+
+	/* set visible and sensitive scroll buttons */
+	if(right_width)
+	{
+		/* set visible */
+		gtk_widget_set_child_visible(GTK_WIDGET(path_bar->right_button), TRUE);
+		child_allocation.x = allocation->width - right_width - border_width;
+		child_allocation.width = right_width;
+		gtk_widget_size_allocate(GTK_WIDGET(path_bar->right_button), &child_allocation);
+
+		gtk_widget_set_sensitive(GTK_WIDGET(path_bar->right_button), iter?TRUE:FALSE);
+	}
+	else
+	{
+		/* set invisible */
+		gtk_widget_set_child_visible(GTK_WIDGET(path_bar->right_button), FALSE);
+	}
+
+	/* hide all buttons that don't fit */
+	while(iter)
+	{
+		gtk_widget_set_child_visible(GTK_WIDGET(iter->data), FALSE);
+		iter = iter->next;
+	}
+
+	iter = first_display->next;
+
+	while(iter)
+	{
+		gtk_widget_set_child_visible(GTK_WIDGET(((GSList*)iter->data)->data), FALSE);
+		iter = iter->next;
+	}
+
+	g_slist_free(first_display);
+}
+
+static void
+cb_xa_path_bar_pwd_changed(XAArchiveStore *store, XAPathBar *path_bar)
+{
+	GSList *path = xa_archive_store_get_pwd_list(store);
+	GSList *iter = path;
+	GSList *buttons = path_bar->path_button;
+	GSList *lastbutton = NULL;
+	GtkRadioButton *button = NULL;
+	const gchar *label = NULL;
+	gint cmp = 0;
+
+	while(iter && buttons)
+	{
+		button = GTK_RADIO_BUTTON(buttons->data);
+		label = gtk_button_get_label(GTK_BUTTON(button));
+		cmp = strcmp(label, (gchar*)iter->data);
+		if(cmp != 0)
+		{
+			while(buttons)
+			{
+				/* it seems remove also unref de button */
+				gtk_container_remove(GTK_CONTAINER(path_bar), GTK_WIDGET(buttons->data));
+				buttons = buttons->next;
+			}
+			if(lastbutton)
+			{
+				g_slist_free(lastbutton->next);
+				lastbutton->next = NULL;
+			}
+			else
+			{
+				g_slist_free(path_bar->path_button);
+				path_bar->path_button = NULL;
+			}
+			break;
+		}
+
+		lastbutton = buttons;
+		buttons = buttons->next;
+
+		g_free(iter->data);
+		iter = iter->next;
+	}
+
+	while(iter)
+	{
+		button = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label(path_bar->path_button, (const gchar*)iter->data));
+		gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(button), FALSE);
+		path_bar->path_button = g_slist_append(path_bar->path_button, button);
+
+		g_signal_connect(G_OBJECT(button), "clicked", (GCallback)cb_xa_path_bar_path_button_clicked, path_bar);
+
+		gtk_container_add(GTK_CONTAINER(path_bar), GTK_WIDGET(button));
+		gtk_widget_show(GTK_WIDGET(button));
+
+		g_free(iter->data);
+		iter = iter->next;
+	}
+
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
+
+	g_slist_free(path);
+
+	path_bar->first_button = g_slist_last(path_bar->path_button);
+}
+
+static void
+cb_xa_path_bar_path_button_clicked(GtkRadioButton *button, XAPathBar *path_bar)
+{
+	gchar *path = g_strdup("/");
+	gchar *folder = NULL;
+	GSList *iter = path_bar->path_button;
+
+	while(iter->data != (gpointer)button)
+	{
+		iter = iter->next;
+		folder = path;
+		path = g_strconcat(path, gtk_button_get_label(GTK_BUTTON(iter->data)), "/", NULL);
+		g_free(folder);
+	}
+
+	xa_archive_store_set_pwd_silent(XA_NAVIGATION_BAR(path_bar)->store, path);
+	g_free(path);
+}
+
+static void
+cb_xa_path_bar_scroll_left(GtkWidget *widget, gpointer user_data)
+{
+	XAPathBar *path_bar = XA_PATH_BAR(user_data);
+
+	GSList *iter = path_bar->path_button;
+	GSList *prev = NULL;
+
+	while(iter)
+	{
+		if(gtk_widget_get_child_visible(GTK_WIDGET(iter->data)))
+		{
+			path_bar->first_button = prev;
+			break;
+		}
+
+		prev = iter;
+		iter = iter->next;
+	}
+}
+
+static void
+cb_xa_path_bar_scroll_right(GtkWidget *widget, gpointer user_data)
+{
+	XAPathBar *path_bar = XA_PATH_BAR(user_data);
+
+	if(!path_bar->first_button)
+		path_bar->first_button = path_bar->path_button;
+
+	if(path_bar->first_button->next)
+		path_bar->first_button = path_bar->first_button->next;
+}
+

Added: xarchiver/branches/xarchiver-psybsd/src/path_bar.h
===================================================================
--- xarchiver/branches/xarchiver-psybsd/src/path_bar.h	                        (rev 0)
+++ xarchiver/branches/xarchiver-psybsd/src/path_bar.h	2006-10-15 22:18:51 UTC (rev 23426)
@@ -0,0 +1,65 @@
+/*
+ *  Copyright (c) 2006 Stephan Arts <psybsd at gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __XARCHIVER_PATH_BAR_H__
+#define __XARCHIVER_PATH_BAR_H__
+G_BEGIN_DECLS
+
+#define XA_TYPE_PATH_BAR xa_path_bar_get_type()
+
+#define XA_PATH_BAR(obj)(                \
+		G_TYPE_CHECK_INSTANCE_CAST ((obj),  \
+			XA_TYPE_PATH_BAR,                  \
+			XAPathBar))
+
+#define XA_IS_PATH_BAR(obj)      ( \
+		G_TYPE_CHECK_INSTANCE_TYPE ((obj),    \
+			XA_TYPE_PATH_BAR))
+
+#define XA_PATH_BAR_CLASS(klass) ( \
+		G_TYPE_CHECK_CLASS_CAST ((klass),     \
+			XA_TYPE_PATH_BAR,      \
+			XAPathBarClass))
+
+#define XA_IS_PATH_BAR_CLASS(class) ( \
+		G_TYPE_CHECK_CLASS_TYPE ((class),        \
+			XA_TYPE_PATH_BAR()))	
+
+typedef struct _XAPathBar XAPathBar;
+
+struct _XAPathBar
+{
+	XANavigationBar parent;
+	GtkButton *left_button;
+	GtkButton *right_button;
+	GSList *path_button;
+	GSList *first_button;
+};
+
+typedef struct _XAPathBarClass XAPathBarClass;
+
+struct _XAPathBarClass
+{
+	XANavigationBarClass parent_class;
+};
+
+GType      xa_path_bar_get_type();
+XANavigationBar *xa_path_bar_new();
+
+G_END_DECLS
+#endif /* __XARCHIVER_PATH_BAR_H__*/



More information about the Xfce4-commits mailing list