/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2002-2007 Imendio AB
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2010 Collabora Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
#include <libempathy/empathy-gsettings.h>
#include <libempathy/empathy-utils.h>
#include <libempathy/empathy-dispatcher.h>
+#include <libempathy/empathy-marshal.h>
#include "empathy-chat.h"
#include "empathy-spell.h"
#include "empathy-contact-list-store.h"
#include "empathy-contact-list-view.h"
#include "empathy-contact-menu.h"
+#include "empathy-input-text-view.h"
#include "empathy-search-bar.h"
#include "empathy-theme-manager.h"
#include "empathy-smiley-manager.h"
#define DEBUG_FLAG EMPATHY_DEBUG_CHAT
#include <libempathy/empathy-debug.h>
-#define CHAT_DIR_CREATE_MODE (S_IRUSR | S_IWUSR | S_IXUSR)
-#define CHAT_FILE_CREATE_MODE (S_IRUSR | S_IWUSR)
#define IS_ENTER(v) (v == GDK_KEY_Return || v == GDK_KEY_ISO_Enter || v == GDK_KEY_KP_Enter)
-#define MAX_INPUT_HEIGHT 150
#define COMPOSING_STOP_TIMEOUT 5
#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyChat)
TpHandleType handle_type;
gint contacts_width;
gboolean has_input_vscroll;
- gint topic_width;
/* TRUE if spell checking is enabled, FALSE otherwise.
* This is to keep track of the last state of spell checking
/* Source func ID for update_misspelled_words () */
guint update_misspelled_words_id;
+ /* Source func ID for save_paned_pos_timeout () */
+ guint save_paned_pos_id;
GtkWidget *widget;
GtkWidget *hpaned;
}
static void
-chat_message_received (EmpathyChat *chat, EmpathyMessage *message)
+chat_message_received (EmpathyChat *chat,
+ EmpathyMessage *message,
+ gboolean pending)
{
EmpathyChatPriv *priv = GET_PRIV (chat);
EmpathyContact *sender;
chat);
priv->unread_messages++;
- g_signal_emit (chat, signals[NEW_MESSAGE], 0, message);
+ g_signal_emit (chat, signals[NEW_MESSAGE], 0, message, pending);
}
static void
EmpathyMessage *message,
EmpathyChat *chat)
{
- chat_message_received (chat, message);
+ chat_message_received (chat, message, FALSE);
}
static void
g_free (str);
}
-/* WARNING: EXPLICIT CONTENT, keep away childrens!
- *
- * When a GtkLabel is set to wrap, it assume and hardcoded width. To change
- * that width we have to set a size request on the label... but that's not
- * possible because we want the window to be able to shrink, so we MUST request
- * width of 1. Note that the height of a wrapping label depends on its width.
- *
- * To work around that, here is what happens:
- * 1) size-request is first called, an hardcoded small width is requested by
- * GtkLabel, which means also a too big height. We do nothing.
- * 2) size-allocate is called with the full width available, that's the width
- * we really want to make wrap the label. We save that width and restart a
- * size-request/size-allocate round.
- * 3) size-request is called a 2nd time, now we can tell the pango layout its
- * width (we can't do that in step 2 because GtkLabel::size-request recreate
- * the layout each time). When the layout has its width, we can know the
- * height of the label and set its requisition. The width request is set to
- * 1px to make sure the window can shrink, the layout will fill all the
- * available width anyway.
- */
-static void
-chat_topic_label_size_request_cb (GtkLabel *label,
- GtkRequisition *requisition,
- EmpathyChat *chat)
-{
- EmpathyChatPriv *priv = GET_PRIV (chat);
-
- if (gtk_label_get_line_wrap (label) && priv->topic_width > 0) {
- PangoLayout *layout;
- PangoRectangle rect;
- gint ypad;
-
- layout = gtk_label_get_layout (label);
- pango_layout_set_width (layout, priv->topic_width * PANGO_SCALE);
- pango_layout_get_extents (layout, NULL, &rect);
- gtk_misc_get_padding (GTK_MISC (label), NULL, &ypad);
-
- requisition->width = 1;
- requisition->height = PANGO_PIXELS (rect.height) + ypad * 2;
- }
-}
-
static void
chat_topic_label_size_allocate_cb (GtkLabel *label,
GtkAllocation *allocation,
EmpathyChatPriv *priv = GET_PRIV (chat);
if (!gtk_label_get_line_wrap (label)) {
- priv->topic_width = -1;
-
if (pango_layout_is_ellipsized (gtk_label_get_layout (label)))
gtk_widget_show (priv->expander_topic);
else
return;
}
-
- if (priv->topic_width != allocation->width) {
- priv->topic_width = allocation->width;
- gtk_widget_queue_resize (GTK_WIDGET (label));
- }
}
static void
return TRUE;
}
-static gboolean
-chat_input_set_size_request_idle (gpointer sw)
-{
- gtk_widget_set_size_request (sw, -1, MAX_INPUT_HEIGHT);
-
- return FALSE;
-}
-
-static void
-chat_input_size_request_cb (GtkWidget *widget,
- GtkRequisition *requisition,
- EmpathyChat *chat)
-{
- EmpathyChatPriv *priv = GET_PRIV (chat);
- GtkWidget *sw;
-
- sw = gtk_widget_get_parent (widget);
- if (requisition->height >= MAX_INPUT_HEIGHT && !priv->has_input_vscroll) {
- g_idle_add (chat_input_set_size_request_idle, sw);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
- GTK_POLICY_NEVER,
- GTK_POLICY_ALWAYS);
- priv->has_input_vscroll = TRUE;
- }
-
- if (requisition->height < MAX_INPUT_HEIGHT && priv->has_input_vscroll) {
- gtk_widget_set_size_request (sw, -1, -1);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
- GTK_POLICY_NEVER,
- GTK_POLICY_NEVER);
- priv->has_input_vscroll = FALSE;
- }
-}
-
static void
chat_input_realize_cb (GtkWidget *widget,
EmpathyChat *chat)
g_assert (codes != NULL);
if (g_list_length (codes) > 1) {
/* translators: %s is the selected word */
- label = g_strdup_printf(_("Add '%s' to Dictionary"),
+ label = g_strdup_printf (_("Add '%s' to Dictionary"),
chat_spell->word);
item = gtk_image_menu_item_new_with_mnemonic (label);
g_free (label);
g_assert (name != NULL);
/* translators: first %s is the selected word,
* second %s is the language name of the target dictionary */
- label = g_strdup_printf(_("Add '%s' to %s Dictionary"),
+ label = g_strdup_printf (_("Add '%s' to %s Dictionary"),
chat_spell->word, name);
item = gtk_image_menu_item_new_with_mnemonic (label);
g_free (label);
for (; pending; pending = g_list_next (pending)) {
if (empathy_message_equal (message, pending->data)) {
+ g_object_unref (message);
return FALSE;
}
}
for (l = messages; l != NULL ; l = g_list_next (l)) {
EmpathyMessage *message = EMPATHY_MESSAGE (l->data);
- chat_message_received (chat, message);
+ chat_message_received (chat, message, TRUE);
}
}
priv->spell_checking_enabled = spell_checker;
}
+static gboolean
+save_paned_pos_timeout (gpointer data)
+{
+ EmpathyChat *self = data;
+ gint hpaned_pos;
+
+ hpaned_pos = gtk_paned_get_position (GTK_PANED (self->priv->hpaned));
+
+ g_settings_set_int (self->priv->gsettings_ui,
+ EMPATHY_PREFS_UI_CHAT_WINDOW_PANED_POS,
+ hpaned_pos);
+
+ return FALSE;
+}
+
static gboolean
chat_hpaned_pos_changed_cb (GtkWidget* hpaned,
GParamSpec *spec,
gpointer user_data)
{
EmpathyChat *chat = EMPATHY_CHAT (user_data);
- gint hpaned_pos;
- hpaned_pos = gtk_paned_get_position (GTK_PANED(hpaned));
- g_settings_set_int (chat->priv->gsettings_ui,
- EMPATHY_PREFS_UI_CHAT_WINDOW_PANED_POS,
- hpaned_pos);
+ if (chat->priv->save_paned_pos_id != 0)
+ g_source_remove (chat->priv->save_paned_pos_id);
+
+ chat->priv->save_paned_pos_id = g_timeout_add_seconds (1,
+ save_paned_pos_timeout, chat);
return TRUE;
}
empathy_builder_connect (gui, chat,
"expander_topic", "notify::expanded", chat_topic_expander_activate_cb,
"label_topic", "size-allocate", chat_topic_label_size_allocate_cb,
- "label_topic", "size-request", chat_topic_label_size_request_cb,
NULL);
g_free (filename);
gtk_widget_show (GTK_WIDGET (chat->view));
/* Add input GtkTextView */
- chat->input_text_view = g_object_new (GTK_TYPE_TEXT_VIEW,
- "pixels-above-lines", 2,
- "pixels-below-lines", 2,
- "pixels-inside-wrap", 1,
- "right-margin", 2,
- "left-margin", 2,
- "wrap-mode", GTK_WRAP_WORD_CHAR,
- NULL);
+ chat->input_text_view = empathy_input_text_view_new ();
+
g_signal_connect (chat->input_text_view, "key-press-event",
G_CALLBACK (chat_input_key_press_event_cb),
chat);
- g_signal_connect (chat->input_text_view, "size-request",
- G_CALLBACK (chat_input_size_request_cb),
- chat);
g_signal_connect (chat->input_text_view, "realize",
G_CALLBACK (chat_input_realize_cb),
chat);
if (priv->update_misspelled_words_id != 0)
g_source_remove (priv->update_misspelled_words_id);
+ if (priv->save_paned_pos_id != 0)
+ g_source_remove (priv->save_paned_pos_id);
+
g_object_unref (priv->gsettings_chat);
g_object_unref (priv->gsettings_ui);
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
+ _empathy_marshal_VOID__OBJECT_BOOLEAN,
G_TYPE_NONE,
- 1, EMPATHY_TYPE_MESSAGE);
+ 2, EMPATHY_TYPE_MESSAGE, G_TYPE_BOOLEAN);
g_type_class_add_private (object_class, sizeof (EmpathyChatPriv));
}