org.guifications.plugins: 2c0c3344d1469f3c1b6af5ca12d2fd297eca8e8f
grim at guifications.org
grim at guifications.org
Fri Apr 4 22:15:14 CDT 2008
-----------------------------------------------------------------
Revision: 2c0c3344d1469f3c1b6af5ca12d2fd297eca8e8f
Ancestor: ca1f0a3e5b55641c21a98bf2da1ba34f5cb79f38
Author: grim at guifications.org
Date: 2008-04-05T01:45:32
Branch: org.guifications.plugins
Added files:
manualsize/manualsize.c
Added directories:
manualsize
ChangeLog:
Adding nodashi's manualsize plugin as it was posted on our trac
Closes #496
-----------------------------------------------------------------
This revision's diffstat output:
manualsize.c | 318 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 318 insertions(+)
-------------- next part --------------
============================================================
--- manualsize/manualsize.c 31726065fc4506a16b775fd92be2f2854fd9c27e
+++ manualsize/manualsize.c 31726065fc4506a16b775fd92be2f2854fd9c27e
@@ -0,0 +1,318 @@
+/*
+ *
+ * Pidgin 2.4 manual entry area height sizing plugin
+ * License: GPL version 2 or later
+ *
+ * Copyright (C) 2008, Artemy Kapitula <dalt74 at gmail.com>
+ *
+ */
+
+#include "internal.h"
+#include "pidgin.h"
+#include "gtkprefs.h"
+
+#include "conversation.h"
+#include "prefs.h"
+#include "signals.h"
+#include "version.h"
+#include "debug.h"
+
+#include "gtkplugin.h"
+#include "gtkutils.h"
+#include "gtkimhtml.h"
+
+#ifndef _WIN32
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#endif
+
+#define NOTIFY_PLUGIN_ID "pidgin-entry-manual-height"
+
+static PurplePlugin * myself = NULL;
+
+static PurplePlugin *my_plugin = NULL;
+ // Static plugin registration info
+
+static gboolean page_added = FALSE; // The flag of page has been added.
+ // It's used to track a case when we add a second page and should to do some
+ // additional work to track a page resize issues
+
+static GList * books_connected = NULL;
+ // List of notebooks we connected to. When plugin is unloaded,
+ // we will disconnect our handler for a "page-added" signal
+
+//
+// Find a first "placed" objects (the object that has allocation with a height > 1)
+// and it's internal height.
+//
+// It's required because when creating a non-first page in the notebook,
+// the widget of the added page has allocation->heigth = 1, and we cannot
+// use it as a base for evaluating position of separator in a GtkVPaned
+//
+static GtkWidget * find_placed_object(GtkWidget * w, int * client_height) {
+ GtkWidget * ret;
+ int border_width;
+ border_width = gtk_container_get_border_width( GTK_CONTAINER(w) );
+ if ((w->allocation.height > 1)||(gtk_widget_get_parent(w)==NULL)) {
+ *client_height = w->allocation.height;
+ return w;
+ } else {
+ ret = find_placed_object( gtk_widget_get_parent(w), client_height );
+ *client_height = *client_height - border_width + 2;
+ return ret;
+ }
+}
+
+//
+// Find a GtkNotebook in the widget's parents
+// It's used to find a GtkNotebook in a conversation window
+// to attach a "page-added" signal handler
+//
+static GtkWidget * get_notebook(GtkWidget * w) {
+ if (strcmp(GTK_OBJECT_TYPE_NAME(w),"GtkNotebook")==0) return w;
+ if (gtk_widget_get_parent(w)==NULL) return NULL;
+ return get_notebook(gtk_widget_get_parent(w));
+}
+
+//
+// Signal handler. Triggers a page_added flag.
+//
+static void
+on_page_add( GtkNotebook * book, GtkWidget * widget, guint page_num, gpointer user_data ) {
+ page_added = TRUE;
+ return;
+}
+
+//
+// When removing last page, forget this notebook
+//
+static void
+on_page_remove( GtkNotebook * book, GtkWidget * widget, guint page_num, gpointer user_data ) {
+ if (gtk_notebook_get_n_pages(book) == 0) {
+ books_connected = g_list_remove( books_connected, book );
+ printf("Removed!\n");
+ }
+}
+
+//
+// Attach a handlers on a notebook if it is not already attached
+// Adds a notebook into a tracked objects list
+//
+static void
+connect_notebook_handler(GtkNotebook * notebook) {
+ GList * item = g_list_find( books_connected, notebook );
+ if (!item) {
+ g_signal_connect_after( notebook, "page-added", on_page_add, NULL );
+ g_signal_connect_after( notebook, "page-removed", on_page_remove, NULL );
+ books_connected = g_list_append( books_connected, notebook );
+ printf("Added!\n");
+ }
+}
+
+//
+// Rebuild conversation pane.
+// Find a conversation pane ("pane")
+// Find a parent for a pane ("top")
+// Create GtkVPaned ("vpaned")
+// Move "pane" from a "top" to the up of "vpaned"
+// Move "lower_hbox" of conversation to the bottom "vpaned"
+// Insert "vpaned" into a "top"
+// Change "vpaned" divider position
+//
+static void
+rebuild_container(PidginConversation * conv) {
+
+ GtkWidget * pane = gtk_widget_get_parent(GTK_WIDGET(conv->lower_hbox));
+ GtkWidget * top = gtk_widget_get_parent( pane );
+ GtkWidget * vpaned = gtk_vpaned_new();
+ GtkNotebook * notebook = GTK_NOTEBOOK(get_notebook(top));
+ gboolean chat = (conv->active_conv->type == PURPLE_CONV_TYPE_CHAT);
+ int handle_size = 0;
+ int parent_area = 0;
+ int border_size = 0;
+ int new_pos;
+ GtkPositionType tabpos = -1;
+ GValue v;
+
+ int stored_height = (chat)?
+ purple_prefs_get_int( "/plugins/manualsize/chat_entry_height" )
+ :
+ purple_prefs_get_int( "/plugins/manualsize/im_entry_height" );
+
+ if (stored_height < 0) stored_height = 128;
+
+ if (notebook) {
+ tabpos = gtk_notebook_get_tab_pos( notebook );
+ connect_notebook_handler( notebook );
+ }
+
+ memset( &v, 0, sizeof(v) );
+ g_value_init( &v, G_TYPE_BOOLEAN );
+
+ gtk_widget_show( vpaned );
+
+ g_value_set_boolean( &v, TRUE );
+ gtk_widget_reparent( pane, vpaned );
+ gtk_container_child_set_property( GTK_CONTAINER(vpaned), pane, "resize", &v );
+
+ g_value_set_boolean( &v, FALSE );
+ gtk_widget_reparent( conv->lower_hbox, vpaned );
+ gtk_container_child_set_property( GTK_CONTAINER(vpaned), conv->lower_hbox, "resize", &v );
+
+ g_value_unset( &v );
+
+ gtk_container_add( GTK_CONTAINER(top), vpaned );
+
+ gtk_widget_style_get( vpaned, "handle-size", &handle_size, NULL );
+
+ find_placed_object( top, &parent_area );
+ border_size = gtk_container_get_border_width(GTK_CONTAINER(top));
+
+ new_pos =
+ parent_area -
+ stored_height -
+ handle_size -
+ border_size * 2 -
+ (((page_added==TRUE)&&((tabpos==GTK_POS_TOP)||(tabpos==GTK_POS_BOTTOM)))?24:0);
+
+ gtk_paned_set_position( GTK_PANED(vpaned), new_pos );
+
+ page_added = FALSE;
+
+ gtk_widget_grab_focus( conv->entry );
+
+}
+
+//
+// Store input area size depending on a conversation type
+//
+static void
+store_area_size(PidginConversation * conv) {
+
+ gboolean chat = (conv->active_conv->type == PURPLE_CONV_TYPE_CHAT);
+
+ if (strcmp("GtkVPaned",(GTK_OBJECT_TYPE_NAME(gtk_widget_get_parent( GTK_WIDGET(conv->lower_hbox)))))==0) {
+ if (chat) {
+ purple_prefs_set_int(
+ "/plugins/manualsize/chat_entry_height",
+ conv->lower_hbox->allocation.height
+ );
+ } else {
+ purple_prefs_set_int(
+ "/plugins/manualsize/im_entry_height",
+ conv->lower_hbox->allocation.height
+ );
+ }
+ }
+ return;
+}
+
+//
+// Signal handler. Called when conversation created, and rebuilds a conversation pane
+//
+static void
+on_display(void* data) {
+ PidginConversation * gtkconv = (PidginConversation*)data;
+ rebuild_container( gtkconv );
+}
+
+//
+// Signal handler. Called when conversation destroyed, to store an input area size
+//
+static void
+on_destroy(void * data) {
+ PurpleConversation * conv = (PurpleConversation*)data;
+ PidginConversation * gtkconv;
+ if (conv) {
+ gtkconv = PIDGIN_CONVERSATION( conv );
+ if (gtkconv) {
+ store_area_size( gtkconv );
+ }
+ }
+}
+
+//
+// Traverse connected notebooks and remove our signal handler
+//
+static void
+cleanup_callback(gpointer data, gpointer user_data) {
+ g_signal_handlers_disconnect_by_func( data, on_page_add, NULL );
+ g_signal_handlers_disconnect_by_func( data, on_page_remove, NULL );
+}
+
+static gboolean
+plugin_load(PurplePlugin *plugin)
+{
+ void * gtk_conv_handle = pidgin_conversations_get_handle();
+ void * conv_handle = purple_conversations_get_handle();
+
+ myself = plugin;
+ purple_prefs_add_none( "/plugins" );
+ purple_prefs_add_none( "/plugins/manualsize" );
+ purple_prefs_add_int( "/plugins/manualsize/chat_entry_height", 128 );
+ purple_prefs_add_int( "/plugins/manualsize/im_entry_height", 128 );
+
+ my_plugin = plugin;
+
+ purple_signal_connect(gtk_conv_handle, "conversation-displayed", plugin,
+ PURPLE_CALLBACK(on_display), NULL);
+ purple_signal_connect(conv_handle, "deleting-conversation", plugin,
+ PURPLE_CALLBACK(on_destroy), NULL);
+
+ return TRUE;
+}
+
+static gboolean
+plugin_unload(PurplePlugin *plugin)
+{
+ myself = NULL;
+ g_list_foreach( books_connected, cleanup_callback, NULL );
+ g_list_free( books_connected );
+ return TRUE;
+}
+
+static PurplePluginInfo info =
+{
+ PURPLE_PLUGIN_MAGIC,
+ PURPLE_MAJOR_VERSION,
+ PURPLE_MINOR_VERSION,
+ PURPLE_PLUGIN_STANDARD, /**< type */
+ PIDGIN_PLUGIN_TYPE, /**< ui_requirement */
+ 0, /**< flags */
+ NULL, /**< dependencies */
+ PURPLE_PRIORITY_DEFAULT, /**< priority */
+
+ NOTIFY_PLUGIN_ID, /**< id */
+ N_("Entry area manual sizing"), /**< name */
+ DISPLAY_VERSION, /**< version */
+
+ N_("Allows you to change entry area height"), /** summary */
+ N_("Allows you to change entry area height"), /** description */
+
+ "Artemy Kapitula <dalt74 at gmail.com>", /**< author */
+ PURPLE_WEBSITE, /**< homepage */
+
+ plugin_load, /**< load */
+ plugin_unload, /**< unload */
+ NULL, /**< destroy */
+
+ NULL, /**< ui_info */
+ NULL, /**< extra_info */
+ NULL,
+ NULL,
+
+ /* padding */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void
+init_plugin(PurplePlugin *plugin)
+{
+ return;
+}
+
+PURPLE_INIT_PLUGIN(manualsize, init_plugin, info)
More information about the Plugins-commits
mailing list