gedit r6770 - in trunk: . gedit



Author: jessevdk
Date: Wed Dec 31 12:13:00 2008
New Revision: 6770
URL: http://svn.gnome.org/viewvc/gedit?rev=6770&view=rev

Log:
	* gedit/gedit-window.c:
	* gedit/gedit-window-private.h:
	* gedit/gedit-status-combo-box.c:
	* gedit/gedit-status-combo-box.h:
	* gedit/Makefile.am:
	
	Implemented new GeditStatusComboBox which displays a combo box like
	widget for use in the statusbar. It is currently used in the newly
	implemented drop downs for language and tab width selection.


Added:
   trunk/gedit/gedit-status-combo-box.c
   trunk/gedit/gedit-status-combo-box.h
Modified:
   trunk/ChangeLog
   trunk/gedit/Makefile.am
   trunk/gedit/gedit-window-private.h
   trunk/gedit/gedit-window.c

Modified: trunk/gedit/Makefile.am
==============================================================================
--- trunk/gedit/Makefile.am	(original)
+++ trunk/gedit/Makefile.am	Wed Dec 31 12:13:00 2008
@@ -104,6 +104,7 @@
 	gedit-prefs-manager.h		\
 	gedit-progress-message-area.h	\
 	gedit-statusbar.h		\
+	gedit-status-combo-box.h	\
 	gedit-tab.h 			\
 	gedit-utils.h 			\
 	gedit-view.h 			\
@@ -173,6 +174,7 @@
 	gedit-session.c			\
 	gedit-spinner.c			\
 	gedit-statusbar.c		\
+	gedit-status-combo-box.c	\
 	gedit-style-scheme-manager.c	\
 	gedit-tab.c 			\
 	gedit-utils.c 			\

Added: trunk/gedit/gedit-status-combo-box.c
==============================================================================
--- (empty file)
+++ trunk/gedit/gedit-status-combo-box.c	Wed Dec 31 12:13:00 2008
@@ -0,0 +1,441 @@
+/*
+ * gedit-status-combo-box.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2008 - Jesse van den Kieboom
+ *
+ * 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 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 "gedit-status-combo-box.h"
+
+#define COMBO_BOX_TEXT_DATA "GeditStatusComboBoxTextData"
+
+#define GEDIT_STATUS_COMBO_BOX_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_STATUS_COMBO_BOX, GeditStatusComboBoxPrivate))
+
+struct _GeditStatusComboBoxPrivate
+{
+	GtkWidget *frame;
+	GtkWidget *hbox;
+	GtkWidget *label;
+	GtkWidget *item;
+	GtkWidget *arrow;
+	
+	GtkWidget *menu;
+	GtkWidget *current_item;
+};
+
+/* Signals */
+enum
+{
+	CHANGED,
+	NUM_SIGNALS
+};
+
+/* Properties */
+enum 
+{
+	PROP_0,
+	
+	PROP_LABEL
+};
+
+static guint signals[NUM_SIGNALS] = { 0 };
+
+static void menu_position_func 		(GtkMenu	     *menu,
+	            			 gint		     *x,
+		    			 gint		     *y,
+		    			 gboolean	     *push_in,
+					 GeditStatusComboBox *combo);
+static gboolean button_press_event 	(GtkWidget           *widget,
+					 GdkEventButton      *event);
+static void item_activated 		(GtkMenuItem         *item,
+					 GeditStatusComboBox *combo);
+
+G_DEFINE_TYPE(GeditStatusComboBox, gedit_status_combo_box, GTK_TYPE_EVENT_BOX)
+
+static void
+gedit_status_combo_box_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (gedit_status_combo_box_parent_class)->finalize (object);
+}
+
+static void
+gedit_status_combo_box_get_property (GObject    *object,
+			             guint       prop_id,
+			             GValue     *value,
+			             GParamSpec *pspec)
+{
+	GeditStatusComboBox *obj = GEDIT_STATUS_COMBO_BOX (object);
+
+	switch (prop_id)
+	{
+		case PROP_LABEL:
+			g_value_set_string (value, gedit_status_combo_box_get_label (obj));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+gedit_status_combo_box_set_property (GObject      *object,
+			             guint         prop_id,
+			             const GValue *value,
+			             GParamSpec   *pspec)
+{
+	GeditStatusComboBox *obj = GEDIT_STATUS_COMBO_BOX (object);
+
+	switch (prop_id)
+	{
+		case PROP_LABEL:
+			gedit_status_combo_box_set_label (obj, g_value_get_string (value));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+gedit_status_combo_box_changed (GeditStatusComboBox *combo,
+				GtkMenuItem         *item)
+{
+	const gchar *text;
+	
+	text = g_object_get_data (G_OBJECT (item), COMBO_BOX_TEXT_DATA);
+
+	if (text != NULL)
+	{
+		gtk_label_set_markup (GTK_LABEL (combo->priv->item), text);
+		combo->priv->current_item = GTK_WIDGET (item);
+	}
+}
+
+static gboolean
+expose_event (GtkWidget      *widget,
+	    GdkEventExpose *event)
+{
+	GtkAllocation *allocation;
+	gboolean ret = FALSE;
+	
+	if (GTK_WIDGET_CLASS (gedit_status_combo_box_parent_class)->expose_event)
+		ret = GTK_WIDGET_CLASS (gedit_status_combo_box_parent_class)->expose_event (widget, event);
+
+	if (GTK_WIDGET_STATE (widget) != GTK_STATE_PRELIGHT)
+		return ret;
+	
+	if (!GDK_IS_WINDOW (widget->window))
+		return ret;
+
+	allocation = &(widget->allocation);
+	gtk_paint_shadow (widget->style,
+		        widget->window,
+		        GTK_WIDGET_STATE (widget),
+		        GTK_SHADOW_ETCHED_OUT,
+		        &(event->area),
+		        widget,
+		        NULL,
+		        0,
+		        0,
+		        allocation->width,
+		        allocation->height);
+		     
+	return TRUE;
+}
+
+static gboolean
+leave_notify_event (GtkWidget        *widget,
+		GdkEventCrossing *event)
+{
+	gboolean ret = FALSE;
+	
+	if (GTK_WIDGET_CLASS (gedit_status_combo_box_parent_class)->leave_notify_event)
+		ret = GTK_WIDGET_CLASS (gedit_status_combo_box_parent_class)->leave_notify_event (widget, event);
+	
+	gtk_widget_set_state (widget, GTK_STATE_NORMAL);
+	return ret;
+}
+
+static gboolean
+enter_notify_event (GtkWidget        *widget,
+		GdkEventCrossing *event)
+{
+	gboolean ret = FALSE;
+	
+	if (GTK_WIDGET_CLASS (gedit_status_combo_box_parent_class)->enter_notify_event)
+		ret = GTK_WIDGET_CLASS (gedit_status_combo_box_parent_class)->enter_notify_event (widget, event);
+	
+	gtk_widget_set_state (widget, GTK_STATE_PRELIGHT);
+	return ret;
+}
+
+static void
+gedit_status_combo_box_class_init (GeditStatusComboBoxClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+	
+	object_class->finalize = gedit_status_combo_box_finalize;
+	object_class->get_property = gedit_status_combo_box_get_property;
+	object_class->set_property = gedit_status_combo_box_set_property;
+	
+	klass->changed = gedit_status_combo_box_changed;
+
+	widget_class->button_press_event = button_press_event;
+	widget_class->expose_event = expose_event;
+	widget_class->enter_notify_event = enter_notify_event;
+	widget_class->leave_notify_event = leave_notify_event;
+
+	signals[CHANGED] =
+	    g_signal_new ("changed",
+			  G_OBJECT_CLASS_TYPE (object_class),
+			  G_SIGNAL_RUN_LAST,
+			  G_STRUCT_OFFSET (GeditStatusComboBoxClass,
+					   changed), NULL, NULL,
+			  g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
+			  GTK_TYPE_MENU_ITEM);
+			  
+	g_object_class_install_property (object_class, PROP_LABEL,
+					 g_param_spec_string ("label",
+					 		      "LABEL",
+					 		      "The label",
+					 		      NULL,
+					 		      G_PARAM_READWRITE));
+
+	g_type_class_add_private (object_class, sizeof(GeditStatusComboBoxPrivate));
+}
+
+static void
+gedit_status_combo_box_init (GeditStatusComboBox *self)
+{
+	GtkShadowType shadow_type;
+	GtkWidget *statusbar;
+
+	self->priv = GEDIT_STATUS_COMBO_BOX_GET_PRIVATE (self);
+
+	gtk_event_box_set_visible_window (GTK_EVENT_BOX (self), TRUE);
+
+	self->priv->frame = gtk_frame_new (NULL);
+	gtk_widget_show (self->priv->frame);
+	
+	/* This is a hack needed to use the shadow type of a statusbar */
+	statusbar = gtk_statusbar_new ();
+	gtk_widget_ensure_style (statusbar);
+
+	gtk_widget_style_get (statusbar, "shadow-type", &shadow_type, NULL);
+	gtk_frame_set_shadow_type (GTK_FRAME (self->priv->frame), shadow_type);
+
+	gtk_widget_destroy (statusbar);
+	
+	self->priv->hbox = gtk_hbox_new (FALSE, 1);
+	gtk_widget_show (self->priv->hbox);
+	
+	gtk_container_add (GTK_CONTAINER (self), self->priv->frame);
+	gtk_container_add (GTK_CONTAINER (self->priv->frame), self->priv->hbox);
+	
+	self->priv->label = gtk_label_new ("");
+	gtk_widget_show (self->priv->label);
+	
+	gtk_label_set_single_line_mode (GTK_LABEL (self->priv->label), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (self->priv->label), 0.0, 0.5);
+	
+	gtk_box_pack_start (GTK_BOX (self->priv->hbox), self->priv->label, FALSE, TRUE, 0);
+	
+	self->priv->item = gtk_label_new ("");
+	gtk_widget_show (self->priv->item);
+	
+	gtk_label_set_single_line_mode (GTK_LABEL (self->priv->item), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (self->priv->item), 1.0, 0.5);
+	gtk_label_set_ellipsize (GTK_LABEL (self->priv->item), PANGO_ELLIPSIZE_MIDDLE);
+	
+	gtk_box_pack_start (GTK_BOX (self->priv->hbox), self->priv->item, TRUE, TRUE, 0);
+	
+	self->priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
+	gtk_widget_show (self->priv->arrow);
+	gtk_misc_set_alignment (GTK_MISC (self->priv->arrow), 0.5, 0.5);
+	
+	gtk_box_pack_start (GTK_BOX (self->priv->hbox), self->priv->arrow, FALSE, TRUE, 0);
+	
+	self->priv->menu = gtk_menu_new ();
+	g_object_ref_sink (self->priv->menu);
+}
+
+/* public functions */
+GtkWidget *
+gedit_status_combo_box_new (const gchar *label)
+{
+	return g_object_new (GEDIT_TYPE_STATUS_COMBO_BOX, "label", label, NULL);
+}
+
+void
+gedit_status_combo_box_set_label (GeditStatusComboBox *combo, 
+				  const gchar         *label)
+{
+	g_return_if_fail (GEDIT_IS_STATUS_COMBO_BOX (combo));
+	gchar *text;
+	
+	text = g_strconcat ("  ", label, ": ", NULL);
+	gtk_label_set_markup (GTK_LABEL (combo->priv->label), text);
+	g_free (text);
+}
+
+const gchar *
+gedit_status_combo_box_get_label (GeditStatusComboBox *combo)
+{
+	g_return_val_if_fail (GEDIT_IS_STATUS_COMBO_BOX (combo), NULL);
+
+	return gtk_label_get_label (GTK_LABEL (combo->priv->label));
+}
+
+void
+gedit_status_combo_box_add_item (GeditStatusComboBox *combo,
+				 GtkMenuItem         *item,
+				 const gchar         *text)
+{
+	g_return_if_fail (GEDIT_IS_STATUS_COMBO_BOX (combo));
+	g_return_if_fail (GTK_IS_MENU_ITEM (item));
+
+	gtk_menu_shell_append (GTK_MENU_SHELL (combo->priv->menu), GTK_WIDGET (item));
+	
+	gedit_status_combo_box_set_item_text (combo, item, text);
+	g_signal_connect (item, "activate", G_CALLBACK (item_activated), combo);
+}
+
+GList *
+gedit_status_combo_box_get_items (GeditStatusComboBox *combo)
+{
+	g_return_val_if_fail (GEDIT_IS_STATUS_COMBO_BOX (combo), NULL);
+
+	return gtk_container_get_children (GTK_CONTAINER (combo->priv->menu));
+}
+
+const gchar *
+gedit_status_combo_box_get_item_text (GeditStatusComboBox *combo,
+				      GtkMenuItem	  *item)
+{
+	const gchar *ret = NULL;
+	
+	g_return_val_if_fail (GEDIT_IS_STATUS_COMBO_BOX (combo), NULL);
+	g_return_val_if_fail (GTK_IS_MENU_ITEM (item), NULL);
+	
+	ret = g_object_get_data (G_OBJECT (item), COMBO_BOX_TEXT_DATA);
+	
+	return ret;
+}
+
+void 
+gedit_status_combo_box_set_item_text (GeditStatusComboBox *combo,
+				      GtkMenuItem	  *item,
+				      const gchar         *text)
+{
+	g_return_if_fail (GEDIT_IS_STATUS_COMBO_BOX (combo));
+	g_return_if_fail (GTK_IS_MENU_ITEM (item));
+
+	g_object_set_data_full (G_OBJECT (item), 
+				COMBO_BOX_TEXT_DATA,
+				g_strdup (text),
+				(GDestroyNotify)g_free);
+}
+
+void
+gedit_status_combo_box_set_item (GeditStatusComboBox *combo,
+				 GtkMenuItem         *item)
+{
+	g_return_if_fail (GEDIT_IS_STATUS_COMBO_BOX (combo));
+	g_return_if_fail (GTK_IS_MENU_ITEM (item));
+
+	g_signal_emit (combo, signals[CHANGED], 0, item, NULL);
+}
+
+GtkLabel *
+gedit_status_combo_box_get_item_label (GeditStatusComboBox *combo)
+{
+	g_return_val_if_fail (GEDIT_IS_STATUS_COMBO_BOX (combo), NULL);
+	
+	return GTK_LABEL (combo->priv->item);
+}
+
+/* callbacks */
+static gboolean
+button_press_event (GtkWidget      *widget,
+		    GdkEventButton *event)
+{
+	GeditStatusComboBox *combo = GEDIT_STATUS_COMBO_BOX (widget);
+	GtkRequisition request;
+	gint max_height;
+	
+	gtk_widget_size_request (combo->priv->menu, &request);
+
+	/* do something relative to our own height here, maybe we can do better */
+	max_height = widget->allocation.height * 20;
+	
+	if (request.height > max_height)
+	{
+		gtk_widget_set_size_request (combo->priv->menu, -1, max_height);
+		gtk_widget_set_size_request (gtk_widget_get_toplevel (combo->priv->menu), -1, max_height);
+	}
+	
+	gtk_menu_popup (GTK_MENU (combo->priv->menu), 
+			NULL, 
+			NULL, 
+			(GtkMenuPositionFunc)menu_position_func, 
+			combo, 
+			event->button, 
+			event->time);
+
+	if (combo->priv->current_item)
+	{
+		gtk_menu_shell_select_item (GTK_MENU_SHELL (combo->priv->menu), 
+					    combo->priv->current_item);
+	}
+
+	return TRUE;
+}
+
+static void
+menu_position_func (GtkMenu		*menu,
+	            gint		*x,
+		    gint		*y,
+		    gboolean		*push_in,
+		    GeditStatusComboBox *combo)
+{
+	GtkRequisition request;
+	
+	*push_in = FALSE;
+	
+	gtk_widget_size_request (gtk_widget_get_toplevel (GTK_WIDGET (menu)), &request);
+	
+	/* use the label here to get the origin... */
+	gdk_window_get_origin (GTK_WIDGET (combo)->window, x, y);
+
+	/* make the menu as wide as the widget */
+	if (request.width < GTK_WIDGET (combo)->allocation.width)
+	{
+		gtk_widget_set_size_request (GTK_WIDGET (menu), GTK_WIDGET (combo)->allocation.width, -1);
+	}
+	
+	/* position it above the widget */
+	*y -= request.height;
+}
+
+static void
+item_activated (GtkMenuItem         *item,
+		GeditStatusComboBox *combo)
+{
+	gedit_status_combo_box_set_item (combo, item);
+}

Added: trunk/gedit/gedit-status-combo-box.h
==============================================================================
--- (empty file)
+++ trunk/gedit/gedit-status-combo-box.h	Wed Dec 31 12:13:00 2008
@@ -0,0 +1,80 @@
+/*
+ * gedit-status-combo-box.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2008 - Jesse van den Kieboom
+ *
+ * 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 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 __GEDIT_STATUS_COMBO_BOX_H__
+#define __GEDIT_STATUS_COMBO_BOX_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_STATUS_COMBO_BOX		(gedit_status_combo_box_get_type ())
+#define GEDIT_STATUS_COMBO_BOX(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_STATUS_COMBO_BOX, GeditStatusComboBox))
+#define GEDIT_STATUS_COMBO_BOX_CONST(obj)	(G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_STATUS_COMBO_BOX, GeditStatusComboBox const))
+#define GEDIT_STATUS_COMBO_BOX_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_STATUS_COMBO_BOX, GeditStatusComboBoxClass))
+#define GEDIT_IS_STATUS_COMBO_BOX(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_STATUS_COMBO_BOX))
+#define GEDIT_IS_STATUS_COMBO_BOX_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_STATUS_COMBO_BOX))
+#define GEDIT_STATUS_COMBO_BOX_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_STATUS_COMBO_BOX, GeditStatusComboBoxClass))
+
+typedef struct _GeditStatusComboBox		GeditStatusComboBox;
+typedef struct _GeditStatusComboBoxClass	GeditStatusComboBoxClass;
+typedef struct _GeditStatusComboBoxPrivate	GeditStatusComboBoxPrivate;
+
+struct _GeditStatusComboBox {
+	GtkEventBox parent;
+	
+	GeditStatusComboBoxPrivate *priv;
+};
+
+struct _GeditStatusComboBoxClass {
+	GtkEventBoxClass parent_class;
+	
+	void (*changed) (GeditStatusComboBox *combo,
+			 GtkMenuItem         *item);
+};
+
+GType gedit_status_combo_box_get_type 			(void) G_GNUC_CONST;
+GtkWidget *gedit_status_combo_box_new			(const gchar 		*label);
+
+const gchar *gedit_status_combo_box_get_label 		(GeditStatusComboBox 	*combo);
+void gedit_status_combo_box_set_label 			(GeditStatusComboBox 	*combo,
+							 const gchar         	*label);
+
+void gedit_status_combo_box_add_item 			(GeditStatusComboBox 	*combo,
+							 GtkMenuItem         	*item,
+							 const gchar         	*text);
+
+GList *gedit_status_combo_box_get_items			(GeditStatusComboBox    *combo);
+const gchar *gedit_status_combo_box_get_item_text 	(GeditStatusComboBox	*combo,
+							 GtkMenuItem		*item);
+void gedit_status_combo_box_set_item_text 		(GeditStatusComboBox	*combo,
+							 GtkMenuItem		*item,
+							 const gchar            *text);
+
+void gedit_status_combo_box_set_item			(GeditStatusComboBox	*combo,
+							 GtkMenuItem		*item);
+
+GtkLabel *gedit_status_combo_box_get_item_label		(GeditStatusComboBox	*combo);
+
+G_END_DECLS
+
+#endif /* __GEDIT_STATUS_COMBO_BOX_H__ */

Modified: trunk/gedit/gedit-window-private.h
==============================================================================
--- trunk/gedit/gedit-window-private.h	(original)
+++ trunk/gedit/gedit-window-private.h	Wed Dec 31 12:13:00 2008
@@ -49,12 +49,18 @@
 	GtkWidget      *hpaned;
 	GtkWidget      *vpaned;
 	
+	GtkWidget      *tab_width_combo;
+	GtkWidget      *language_combo;
+	
 	GeditMessageBus *message_bus;	
 
 	/* statusbar and context ids for statusbar messages */
 	GtkWidget      *statusbar;	
 	guint           generic_message_cid;
 	guint           tip_message_cid;
+	guint 		tab_width_id;
+	guint 		spaces_instead_of_tabs_id;
+	guint 		language_changed_id;
 
 	/* Menus & Toolbars */
 	GtkUIManager   *manager;

Modified: trunk/gedit/gedit-window.c
==============================================================================
--- trunk/gedit/gedit-window.c	(original)
+++ trunk/gedit/gedit-window.c	Wed Dec 31 12:13:00 2008
@@ -55,9 +55,12 @@
 #include "gedit-plugins-engine.h"
 #include "gedit-enum-types.h"
 #include "gedit-dirs.h"
+#include "gedit-status-combo-box.h"
 
 #define LANGUAGE_NONE (const gchar *)"LangNone"
 #define GEDIT_UIFILE "gedit-ui.xml"
+#define TAB_WIDTH_DATA "GeditWindowTabWidthData"
+#define LANGUAGE_DATA "GeditWindowLanguageData"
 
 #define GEDIT_WINDOW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object),\
 					 GEDIT_TYPE_WINDOW,                    \
@@ -1696,9 +1699,162 @@
 }
 
 static void
+tab_width_combo_changed (GeditStatusComboBox *combo,
+			 GtkMenuItem         *item,
+			 GeditWindow         *window)
+{
+	GeditView *view;
+	guint width_data = 0;
+	
+	view = gedit_window_get_active_view (window);
+	
+	if (!view)
+		return;
+	
+	width_data = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), TAB_WIDTH_DATA));
+	
+	if (width_data == 0)
+		return;
+	
+	g_signal_handler_block (view, window->priv->tab_width_id);
+	gtk_source_view_set_tab_width (GTK_SOURCE_VIEW (view), width_data);
+	g_signal_handler_unblock (view, window->priv->tab_width_id);
+}
+
+static void
+use_spaces_toggled (GtkCheckMenuItem *item,
+		    GeditWindow      *window)
+{
+	GeditView *view;
+	
+	view = gedit_window_get_active_view (window);
+	
+	g_signal_handler_block (view, window->priv->spaces_instead_of_tabs_id);
+	gtk_source_view_set_insert_spaces_instead_of_tabs (
+			GTK_SOURCE_VIEW (view),
+			gtk_check_menu_item_get_active (item));
+	g_signal_handler_unblock (view, window->priv->spaces_instead_of_tabs_id);
+}
+
+static void
+language_combo_changed (GeditStatusComboBox *combo,
+			GtkMenuItem         *item,
+			GeditWindow         *window)
+{
+	GeditDocument *doc;
+	GtkSourceLanguage *language;
+	
+	doc = gedit_window_get_active_document (window);
+	
+	if (!doc)
+		return;
+	
+	language = GTK_SOURCE_LANGUAGE (g_object_get_data (G_OBJECT (item), LANGUAGE_DATA));
+	
+	g_signal_handler_block (doc, window->priv->language_changed_id);
+	gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (doc), language);
+	g_signal_handler_unblock (doc, window->priv->language_changed_id);
+}
+
+typedef struct
+{
+	const gchar *label;
+	const gchar *text;
+	guint width;
+} TabWidthDefinition;
+	 
+static void
+fill_tab_width_combo (GeditWindow *window)
+{
+	static TabWidthDefinition defs[] = {
+		{"2", "2", 2},
+		{"4", "4", 4},
+		{"8", "8", 8},
+		{N_("Other"), NULL, 0},
+		{NULL, NULL, 0}
+	};
+	
+	GeditStatusComboBox *combo = GEDIT_STATUS_COMBO_BOX (window->priv->tab_width_combo);
+	guint i = 0;
+	GtkWidget *item;
+	
+	while (defs[i].label != NULL)
+	{
+		item = gtk_menu_item_new_with_label (_(defs[i].label));
+		g_object_set_data (G_OBJECT (item), TAB_WIDTH_DATA, GINT_TO_POINTER (defs[i].width));
+		gtk_widget_show (item);
+		
+		gedit_status_combo_box_add_item (combo,
+						 GTK_MENU_ITEM (item),
+						 defs[i].text);
+
+		if (defs[i].width == 0)
+			gtk_widget_set_sensitive (item, FALSE);
+
+		++i;
+	}
+	
+	item = gtk_separator_menu_item_new ();
+	gedit_status_combo_box_add_item (combo, GTK_MENU_ITEM (item), NULL);
+	gtk_widget_show (item);
+	
+	item = gtk_check_menu_item_new_with_label (_("Use spaces"));
+	gedit_status_combo_box_add_item (combo, GTK_MENU_ITEM (item), NULL);
+	gtk_widget_show (item);
+	
+	g_signal_connect (item, 
+			  "toggled", 
+			  G_CALLBACK (use_spaces_toggled), 
+			  window);
+}
+
+static void
+fill_language_combo (GeditWindow *window)
+{
+	GtkSourceLanguageManager *manager;
+	GSList *languages;
+	GSList *item;
+	GtkWidget *menu_item;
+	const gchar *name;
+	
+	manager = gedit_get_language_manager ();
+	languages = gedit_language_manager_list_languages_sorted (manager, FALSE);
+
+	name = _("Plain Text");
+	menu_item = gtk_menu_item_new_with_label (name);
+	gtk_widget_show (menu_item);
+	
+	g_object_set_data (G_OBJECT (menu_item), LANGUAGE_DATA, NULL);
+	gedit_status_combo_box_add_item (GEDIT_STATUS_COMBO_BOX (window->priv->language_combo),
+					 GTK_MENU_ITEM (menu_item),
+					 name);
+
+	for (item = languages; item; item = item->next)
+	{
+		GtkSourceLanguage *lang = GTK_SOURCE_LANGUAGE (item->data);
+		
+		name = gtk_source_language_get_name (lang);
+		menu_item = gtk_menu_item_new_with_label (name);
+		gtk_widget_show (menu_item);
+		
+		g_object_set_data_full (G_OBJECT (menu_item),
+				        LANGUAGE_DATA,		
+					g_object_ref (lang),
+					(GDestroyNotify)g_object_unref);
+
+		gedit_status_combo_box_add_item (GEDIT_STATUS_COMBO_BOX (window->priv->language_combo),
+						 GTK_MENU_ITEM (menu_item),
+						 name);
+	}
+	
+	g_slist_free (languages);
+}
+
+static void
 create_statusbar (GeditWindow *window, 
 		  GtkWidget   *main_box)
 {
+	GtkLabel *label;
 	gedit_debug (DEBUG_WINDOW);
 
 	window->priv->statusbar = gedit_statusbar_new ();
@@ -1714,6 +1870,41 @@
 			  TRUE, 
 			  0);
 
+	window->priv->tab_width_combo = gedit_status_combo_box_new (_("Tab width"));
+	gtk_widget_show (window->priv->tab_width_combo);
+	gtk_box_pack_end (GTK_BOX (window->priv->statusbar),
+			  window->priv->tab_width_combo,
+			  FALSE,
+			  TRUE,
+			  0);
+
+	label = gedit_status_combo_box_get_item_label (GEDIT_STATUS_COMBO_BOX (window->priv->tab_width_combo));
+	gtk_label_set_width_chars (label, 2);
+	fill_tab_width_combo (window);
+
+	g_signal_connect (G_OBJECT (window->priv->tab_width_combo),
+			  "changed",
+			  G_CALLBACK (tab_width_combo_changed),
+			  window);
+			  
+	window->priv->language_combo = gedit_status_combo_box_new (NULL);
+	gtk_widget_show (window->priv->language_combo);
+	gtk_box_pack_end (GTK_BOX (window->priv->statusbar),
+			  window->priv->language_combo,
+			  FALSE,
+			  TRUE,
+			  0);
+
+	label = gedit_status_combo_box_get_item_label (GEDIT_STATUS_COMBO_BOX (window->priv->language_combo));
+	gtk_label_set_width_chars (label, 12);
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	fill_language_combo (window);
+
+	g_signal_connect (G_OBJECT (window->priv->language_combo),
+			  "changed",
+			  G_CALLBACK (language_combo_changed),
+			  window);
+
 	g_signal_connect_after (G_OBJECT (window->priv->statusbar),
 				"show",
 				G_CALLBACK (statusbar_visibility_changed),
@@ -1952,6 +2143,134 @@
 
 #undef MAX_TITLE_LENGTH
 
+static void
+set_tab_width_item_blocked (GeditWindow *window,
+			    GtkMenuItem *item)
+{
+	g_signal_handlers_block_by_func (window->priv->tab_width_combo, 
+					 tab_width_combo_changed, 
+					 window);
+	
+	gedit_status_combo_box_set_item (GEDIT_STATUS_COMBO_BOX (window->priv->tab_width_combo),
+					 item);
+	
+	g_signal_handlers_unblock_by_func (window->priv->tab_width_combo, 
+					   tab_width_combo_changed, 
+					   window);
+}
+
+static void
+spaces_instead_of_tabs_changed (GObject     *object,
+		   		GParamSpec  *pspec,
+		 		GeditWindow *window)
+{
+	GeditView *view = GEDIT_VIEW (object);
+	gboolean active = gtk_source_view_get_insert_spaces_instead_of_tabs (
+			GTK_SOURCE_VIEW (view));
+	GList *children = gedit_status_combo_box_get_items (
+			GEDIT_STATUS_COMBO_BOX (window->priv->tab_width_combo));
+	GtkCheckMenuItem *item;
+	
+	item = GTK_CHECK_MENU_ITEM (g_list_last (children)->data);
+	
+	gtk_check_menu_item_set_active (item, active);
+	
+	g_list_free (children);	
+}
+
+static void
+tab_width_changed (GObject     *object,
+		   GParamSpec  *pspec,
+		   GeditWindow *window)
+{
+	GList *items;
+	GList *item;
+	GeditStatusComboBox *combo = GEDIT_STATUS_COMBO_BOX (window->priv->tab_width_combo);
+	guint new_tab_width;
+
+	items = gedit_status_combo_box_get_items (combo);
+
+	new_tab_width = gtk_source_view_get_tab_width (GTK_SOURCE_VIEW (object));
+	
+	for (item = items; item; item = item->next)
+	{
+		guint tab_width = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item->data), TAB_WIDTH_DATA));
+		
+		if (tab_width == new_tab_width)
+		{
+			set_tab_width_item_blocked (window, GTK_MENU_ITEM (item->data));
+
+			break;
+		}
+		
+		if (GTK_IS_SEPARATOR_MENU_ITEM (item->next->data))
+		{
+			/* Set for the last item the custom thing */
+			gchar *text;
+			
+			text = g_strdup_printf ("<i>%u</i>", new_tab_width);
+			gedit_status_combo_box_set_item_text (combo, 
+							      GTK_MENU_ITEM (item->data),
+							      text);
+			g_free (text);
+			
+			text = g_strdup_printf ("Other <i>(%u)</i>", new_tab_width);
+			gtk_label_set_markup (GTK_LABEL (gtk_bin_get_child (GTK_BIN (item->data))),
+					      text);
+			g_free (text);
+			
+			set_tab_width_item_blocked (window, GTK_MENU_ITEM (item->data));
+			gtk_widget_set_sensitive (GTK_WIDGET (item->data), TRUE);
+			
+			break;
+		}
+	}
+	
+	g_list_free (items);
+}
+
+static void
+language_changed (GObject     *object,
+		  GParamSpec  *pspec,
+		  GeditWindow *window)
+{
+	GList *items;
+	GList *item;
+	GeditStatusComboBox *combo = GEDIT_STATUS_COMBO_BOX (window->priv->language_combo);
+	GtkSourceLanguage *new_language;
+	const gchar *new_id;
+	
+	items = gedit_status_combo_box_get_items (combo);
+
+	new_language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (object));
+	
+	if (new_language)
+		new_id = gtk_source_language_get_id (new_language);
+	else
+		new_id = NULL;
+	
+	for (item = items; item; item = item->next)
+	{
+		GtkSourceLanguage *lang = g_object_get_data (G_OBJECT (item->data), LANGUAGE_DATA);
+		
+		if ((new_id == NULL && lang == NULL) || 
+		    (new_id != NULL && lang != NULL && strcmp (gtk_source_language_get_id (lang),
+		    					       new_id) == 0))
+		{
+			g_signal_handlers_block_by_func (window->priv->language_combo, 
+							 language_combo_changed, 
+					 		 window);
+			
+			gedit_status_combo_box_set_item (GEDIT_STATUS_COMBO_BOX (window->priv->language_combo),
+					 		 GTK_MENU_ITEM (item->data));
+
+			g_signal_handlers_unblock_by_func (window->priv->language_combo, 
+							   language_combo_changed, 
+					 		   window);
+		}
+	}
+}
+
 static void 
 notebook_switch_page (GtkNotebook     *book, 
 		      GtkNotebookPage *pg,
@@ -1962,14 +2281,33 @@
 	GeditTab *tab;
 	GtkAction *action;
 	gchar *action_name;
-
+	
 	/* CHECK: I don't know why but it seems notebook_switch_page is called
 	two times every time the user change the active tab */
 	
 	tab = GEDIT_TAB (gtk_notebook_get_nth_page (book, page_num));
 	if (tab == window->priv->active_tab)
 		return;
-
+	
+	if (window->priv->active_tab)
+	{
+		if (window->priv->tab_width_id)
+		{
+			g_signal_handler_disconnect (gedit_tab_get_view (window->priv->active_tab), 
+						     window->priv->tab_width_id);
+		
+			window->priv->tab_width_id = 0;
+		}
+		
+		if (window->priv->spaces_instead_of_tabs_id)
+		{
+			g_signal_handler_disconnect (gedit_tab_get_view (window->priv->active_tab), 
+						     window->priv->spaces_instead_of_tabs_id);
+		
+			window->priv->spaces_instead_of_tabs_id = 0;
+		}
+	}
+	
 	/* set the active tab */		
 	window->priv->active_tab = tab;
 
@@ -2001,6 +2339,26 @@
 	gedit_statusbar_set_overwrite (GEDIT_STATUSBAR (window->priv->statusbar),
 				       gtk_text_view_get_overwrite (GTK_TEXT_VIEW (view)));
 
+	gtk_widget_set_sensitive (window->priv->tab_width_combo, TRUE);
+	window->priv->tab_width_id = g_signal_connect (view, 
+						       "notify::tab-width", 
+						       G_CALLBACK (tab_width_changed),
+						       window);
+	window->priv->spaces_instead_of_tabs_id = g_signal_connect (view, 
+								    "notify::insert-spaces-instead-of-tabs", 
+								    G_CALLBACK (spaces_instead_of_tabs_changed),
+								    window);
+
+	window->priv->language_changed_id = g_signal_connect (gedit_tab_get_document (tab),
+							      "notify::language",
+							      G_CALLBACK (language_changed),
+							      window);
+
+	/* call it for the first time */
+	tab_width_changed (G_OBJECT (view), NULL, window);
+	spaces_instead_of_tabs_changed (G_OBJECT (view), NULL, window);
+	language_changed (G_OBJECT (gedit_tab_get_document (tab)), NULL, window);
+
 	g_signal_emit (G_OBJECT (window), 
 		       signals[ACTIVE_TAB_CHANGED], 
 		       0, 
@@ -2606,6 +2964,24 @@
 					      G_CALLBACK (drop_uris_cb),
 					      NULL);
 
+	if (window->priv->tab_width_id)
+	{
+		g_signal_handler_disconnect (view, window->priv->tab_width_id);
+		window->priv->tab_width_id = 0;
+	}
+	
+	if (window->priv->spaces_instead_of_tabs_id)
+	{
+		g_signal_handler_disconnect (view, window->priv->spaces_instead_of_tabs_id);
+		window->priv->spaces_instead_of_tabs_id = 0;
+	}
+	
+	if (window->priv->language_changed_id)
+	{
+		g_signal_handler_disconnect (doc, window->priv->language_changed_id);
+		window->priv->language_changed_id = 0;
+	}
+
 	g_return_if_fail (window->priv->num_tabs >= 0);
 	if (window->priv->num_tabs == 0)
 	{
@@ -2620,7 +2996,9 @@
 				-1);
 				
 		gedit_statusbar_clear_overwrite (
-				GEDIT_STATUSBAR (window->priv->statusbar));								
+				GEDIT_STATUSBAR (window->priv->statusbar));
+		
+		gtk_widget_set_sensitive (window->priv->tab_width_combo, FALSE);
 	}
 
 	if (!window->priv->removing_tabs)



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