]> git.0d.be Git - empathy.git/commitdiff
New chat theme engine imported from Gossip (Daniel Gryniewicz, Xavier Claessens).
authorXavier Claessens <xclaesse@src.gnome.org>
Thu, 20 Dec 2007 16:39:49 +0000 (16:39 +0000)
committerXavier Claessens <xclaesse@src.gnome.org>
Thu, 20 Dec 2007 16:39:49 +0000 (16:39 +0000)
svn path=/trunk/; revision=494

16 files changed:
libempathy-gtk/Makefile.am
libempathy-gtk/empathy-chat-view.c
libempathy-gtk/empathy-chat-view.h
libempathy-gtk/empathy-theme-boxes.c [new file with mode: 0644]
libempathy-gtk/empathy-theme-boxes.h [new file with mode: 0644]
libempathy-gtk/empathy-theme-irc.c [new file with mode: 0644]
libempathy-gtk/empathy-theme-irc.h [new file with mode: 0644]
libempathy-gtk/empathy-theme-manager.c
libempathy-gtk/empathy-theme-manager.h
libempathy-gtk/empathy-theme-utils.c [new file with mode: 0644]
libempathy-gtk/empathy-theme-utils.h [new file with mode: 0644]
libempathy-gtk/empathy-theme.c [new file with mode: 0644]
libempathy-gtk/empathy-theme.h [new file with mode: 0644]
libempathy/empathy-marshal.list
libempathy/empathy-message.c
libempathy/empathy-message.h

index 2e9966536202e538f66f6058d5861158d21242cb..494e3c4ce8e6978469c7ce676194b8f2045322db 100644 (file)
@@ -32,7 +32,11 @@ libempathy_gtk_la_SOURCES =                  \
        empathy-contact-list-store.c            \
        empathy-contact-list-view.c             \
        empathy-preferences.c                   \
+       empathy-theme.c                                 \
+       empathy-theme-boxes.c                   \
+       empathy-theme-irc.c                             \
        empathy-theme-manager.c                 \
+       empathy-theme-utils.c                   \
        empathy-smiley-manager.c                \
        empathy-chat-window.c                   \
        empathy-chat.c                          \
@@ -85,7 +89,11 @@ libempathy_gtk_headers =                     \
        empathy-contact-list-store.h            \
        empathy-contact-list-view.h             \
        empathy-preferences.h                   \
+       empathy-theme.h                                 \
+       empathy-theme-boxes.h                   \
+       empathy-theme-irc.h                             \
        empathy-theme-manager.h                 \
+       empathy-theme-utils.h                   \
        empathy-smiley-manager.h                \
        empathy-chat-window.h                   \
        empathy-chat.h                          \
index 9f10f024fec0de2b79cd92beab99c1f330ce7366..947281590b544adbb1498b4c2e82e5e3343425bf 100644 (file)
 
 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_CHAT_VIEW, EmpathyChatViewPriv))
 
-typedef enum {
-       BLOCK_TYPE_NONE,
-       BLOCK_TYPE_SELF,
-       BLOCK_TYPE_OTHER,
-       BLOCK_TYPE_EVENT,
-       BLOCK_TYPE_TIME,
-       BLOCK_TYPE_INVITE
-} BlockType;
-
 struct _EmpathyChatViewPriv {
-       EmpathySmileyManager *smiley_manager;
-
        GtkTextBuffer *buffer;
 
-       gboolean       irc_style;
+       EmpathyTheme   *theme;
+       gpointer       theme_context;
+
        time_t         last_timestamp;
        BlockType      last_block_type;
 
@@ -136,32 +127,11 @@ static void     chat_view_copy_address_cb            (GtkMenuItem              *
                                                      const gchar              *url);
 static void     chat_view_clear_view_cb              (GtkMenuItem              *menuitem,
                                                      EmpathyChatView           *view);
-static void     chat_view_insert_text_with_emoticons (EmpathyChatView          *view,
-                                                     GtkTextIter              *iter,
-                                                     const gchar              *str);
 static gboolean chat_view_is_scrolled_down           (EmpathyChatView           *view);
 static void     chat_view_theme_changed_cb           (EmpathyThemeManager       *manager,
                                                      EmpathyChatView           *view);
-static void     chat_view_maybe_append_date_and_time (EmpathyChatView           *view,
-                                                     EmpathyMessage            *msg);
-static void     chat_view_append_spacing             (EmpathyChatView           *view);
-static void     chat_view_append_text                (EmpathyChatView           *view,
-                                                     const gchar              *body,
-                                                     const gchar              *tag);
-static void     chat_view_maybe_append_fancy_header  (EmpathyChatView           *view,
-                                                     EmpathyMessage            *msg);
-static void     chat_view_append_irc_action          (EmpathyChatView           *view,
-                                                     EmpathyMessage            *msg);
-static void     chat_view_append_fancy_action        (EmpathyChatView           *view,
-                                                     EmpathyMessage            *msg);
-static void     chat_view_append_irc_message         (EmpathyChatView           *view,
-                                                     EmpathyMessage            *msg);
-static void     chat_view_append_fancy_message       (EmpathyChatView           *view,
-                                                     EmpathyMessage            *msg);
-static GdkPixbuf *chat_view_pad_to_size              (GdkPixbuf                *pixbuf,
-                                                     gint                      width,
-                                                     gint                      height,
-                                                     gint                      extra_padding_right);
+static void     chat_view_theme_updated_cb           (EmpathyTheme              *theme, 
+                                                     EmpathyChatView           *view);
 
 G_DEFINE_TYPE (EmpathyChatView, empathy_chat_view, GTK_TYPE_TEXT_VIEW);
 
@@ -186,7 +156,6 @@ empathy_chat_view_init (EmpathyChatView *view)
 
        priv = GET_PRIV (view);
 
-       priv->smiley_manager = empathy_smiley_manager_new ();
        priv->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
 
        priv->last_block_type = BLOCK_TYPE_NONE;
@@ -224,8 +193,7 @@ empathy_chat_view_init (EmpathyChatView *view)
                               EMPATHY_PREFS_UI_SHOW_AVATARS,
                               &show_avatars);
 
-       empathy_theme_manager_update_show_avatars (empathy_theme_manager_get (),
-                                                 view, show_avatars);
+       empathy_theme_set_show_avatars (priv->theme, show_avatars);
 
        g_signal_connect (view,
                          "populate-popup",
@@ -253,9 +221,6 @@ chat_view_finalize (GObject *object)
        empathy_conf_notify_remove (empathy_conf_get (), priv->notify_system_fonts_id);
        empathy_conf_notify_remove (empathy_conf_get (), priv->notify_show_avatars_id);
 
-       if (priv->smiley_manager) {
-               g_object_unref (priv->smiley_manager);
-       }
        if (priv->last_contact) {
                g_object_unref (priv->last_contact);
        }
@@ -266,6 +231,17 @@ chat_view_finalize (GObject *object)
                g_source_remove (priv->scroll_timeout);
        }
 
+       if (priv->theme) {
+               g_signal_handlers_disconnect_by_func (priv->theme,
+                                                     chat_view_theme_updated_cb,
+                                                     view);
+
+               empathy_theme_detach_from_view (priv->theme, priv->theme_context,
+                                              view);
+
+               g_object_unref (priv->theme);
+       }
+
        G_OBJECT_CLASS (empathy_chat_view_parent_class)->finalize (object);
 }
 
@@ -364,9 +340,11 @@ chat_view_notify_system_font_cb (EmpathyConf  *conf,
                                 gpointer     user_data)
 {
        EmpathyChatView *view;
+       EmpathyChatViewPriv *priv;
        gboolean        show_avatars = FALSE;
 
        view = user_data;
+       priv = GET_PRIV (view);
 
        chat_view_system_font_update (view);
 
@@ -378,8 +356,7 @@ chat_view_notify_system_font_cb (EmpathyConf  *conf,
                               EMPATHY_PREFS_UI_SHOW_AVATARS,
                               &show_avatars);
 
-       empathy_theme_manager_update_show_avatars (empathy_theme_manager_get (),
-                                                 view, show_avatars);
+       empathy_theme_set_show_avatars (priv->theme, show_avatars);
 }
 
 static void
@@ -396,8 +373,7 @@ chat_view_notify_show_avatars_cb (EmpathyConf  *conf,
 
        empathy_conf_get_bool (conf, key, &show_avatars);
 
-       empathy_theme_manager_update_show_avatars (empathy_theme_manager_get (),
-                                                 view, show_avatars);
+       empathy_theme_set_show_avatars (priv->theme, show_avatars);
 }
 
 static void
@@ -593,40 +569,6 @@ chat_view_clear_view_cb (GtkMenuItem *menuitem, EmpathyChatView *view)
        empathy_chat_view_clear (view);
 }
 
-static void
-chat_view_insert_text_with_emoticons (EmpathyChatView *view,
-                                     GtkTextIter     *iter,
-                                     const gchar     *str)
-{
-       EmpathyChatViewPriv *priv = GET_PRIV (view);
-       GtkTextBuffer       *buf = priv->buffer;
-       gboolean             use_smileys = FALSE;
-       GSList              *smileys, *l;
-
-       empathy_conf_get_bool (empathy_conf_get (),
-                              EMPATHY_PREFS_CHAT_SHOW_SMILEYS,
-                              &use_smileys);
-
-       if (!use_smileys) {
-               gtk_text_buffer_insert (buf, iter, str, -1);
-               return;
-       }
-
-       smileys = empathy_smiley_manager_parse (priv->smiley_manager, str);
-       for (l = smileys; l; l = l->next) {
-               EmpathySmiley *smiley;
-
-               smiley = l->data;
-               if (smiley->pixbuf) {
-                       gtk_text_buffer_insert_pixbuf (buf, iter, smiley->pixbuf);
-               } else {
-                       gtk_text_buffer_insert (buf, iter, smiley->str, -1);
-               }
-               empathy_smiley_free (smiley);
-       }
-       g_slist_free (smileys);
-}
-
 static gboolean
 chat_view_is_scrolled_down (EmpathyChatView *view)
 {
@@ -691,222 +633,72 @@ chat_view_maybe_trim_buffer (EmpathyChatView *view)
 }
 
 static void
-chat_view_maybe_append_date_and_time (EmpathyChatView *view,
-                                     EmpathyMessage  *msg)
+chat_view_theme_changed_cb (EmpathyThemeManager *manager,
+                           EmpathyChatView     *view)
 {
        EmpathyChatViewPriv *priv;
-       const gchar        *tag;
-       time_t              timestamp;
-       GDate              *date, *last_date;
-       GtkTextIter         iter;
-       gboolean            append_date, append_time;
-       GString            *str;
+       gboolean            show_avatars = FALSE;
+       gboolean            theme_rooms = FALSE;
 
        priv = GET_PRIV (view);
 
-       if (priv->irc_style) {
-               tag = "irc-time";
-       } else {
-               tag = "fancy-time";
-       }
-
-       if (priv->last_block_type == BLOCK_TYPE_TIME) {
-               return;
-       }
-
-       str = g_string_new (NULL);
-
-       timestamp = 0;
-       if (msg) {
-               timestamp = empathy_message_get_timestamp (msg);
-       }
-
-       if (timestamp <= 0) {
-               timestamp = empathy_time_get_current ();
-       }
-
-       date = g_date_new ();
-       g_date_set_time_t (date, timestamp);
-
-       last_date = g_date_new ();
-       g_date_set_time_t (last_date, priv->last_timestamp);
-
-       append_date = FALSE;
-       append_time = FALSE;
-
-       if (g_date_compare (date, last_date) > 0) {
-               append_date = TRUE;
-               append_time = TRUE;
-       }
-
-       if (priv->last_timestamp + TIMESTAMP_INTERVAL < timestamp) {
-               append_time = TRUE;
-       }
-
-       if (append_time || append_date) {
-               chat_view_append_spacing (view);
-
-               g_string_append (str, "- ");
-       }
-
-       if (append_date) {
-               gchar buf[256];
-
-               g_date_strftime (buf, 256, _("%A %d %B %Y"), date);
-               g_string_append (str, buf);
-
-               if (append_time) {
-                       g_string_append (str, ", ");
-               }
-       }
-
-       g_date_free (date);
-       g_date_free (last_date);
-
-       if (append_time) {
-               gchar *tmp;
-
-               tmp = empathy_time_to_string_local (timestamp, EMPATHY_TIME_FORMAT_DISPLAY_SHORT);
-               g_string_append (str, tmp);
-               g_free (tmp);
-       }
-
-       if (append_time || append_date) {
-               g_string_append (str, " -\n");
-
-               gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-               gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
-                                                         &iter,
-                                                         str->str, -1,
-                                                         tag,
-                                                         NULL);
-
-               priv->last_block_type = BLOCK_TYPE_TIME;
-               priv->last_timestamp = timestamp;
-       }
-
-       g_string_free (str, TRUE);
-}
-
-static void
-chat_view_append_spacing (EmpathyChatView *view)
-{
-       EmpathyChatViewPriv *priv;
-       const gchar        *tag;
-       GtkTextIter         iter;
-
-       priv = GET_PRIV (view);
+       priv->last_block_type = BLOCK_TYPE_NONE;
 
-       if (priv->irc_style) {
-               tag = "irc-spacing";
+       empathy_conf_get_bool (empathy_conf_get (),
+                             EMPATHY_PREFS_CHAT_THEME_CHAT_ROOM,
+                             &theme_rooms);
+       if (!theme_rooms && priv->is_group_chat) {
+               empathy_theme_manager_apply (manager, view, NULL);
        } else {
-               tag = "fancy-spacing";
+               empathy_theme_manager_apply_saved (manager, view);
        }
 
-       gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-       gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
-                                                 &iter,
-                                                 "\n",
-                                                 -1,
-                                                 "cut",
-                                                 tag,
-                                                 NULL);
+       /* Needed for now to update the "rise" property of the names to get it
+        * vertically centered.
+        */
+       empathy_conf_get_bool (empathy_conf_get (),
+                              EMPATHY_PREFS_UI_SHOW_AVATARS,
+                              &show_avatars);
+       empathy_theme_set_show_avatars (priv->theme, show_avatars);
 }
 
-static void
-chat_view_append_text (EmpathyChatView *view,
-                      const gchar    *body,
-                      const gchar    *tag)
+/* Pads a pixbuf to the specified size, by centering it in a larger transparent
+ * pixbuf. Returns a new ref.
+ */
+static GdkPixbuf *
+chat_view_pad_to_size (GdkPixbuf *pixbuf,
+                      gint       width,
+                      gint       height,
+                      gint       extra_padding_right)
 {
-       EmpathyChatViewPriv *priv;
-       GtkTextIter         start_iter, end_iter;
-       GtkTextMark        *mark;
-       GtkTextIter         iter;
-       gint                num_matches, i;
-       GArray             *start, *end;
-       const gchar        *link_tag;
-
-       priv = GET_PRIV (view);
-
-       if (priv->irc_style) {
-               link_tag = "irc-link";
-       } else {
-               link_tag = "fancy-link";
-       }
-
-       gtk_text_buffer_get_end_iter (priv->buffer, &start_iter);
-       mark = gtk_text_buffer_create_mark (priv->buffer, NULL, &start_iter, TRUE);
-
-       start = g_array_new (FALSE, FALSE, sizeof (gint));
-       end = g_array_new (FALSE, FALSE, sizeof (gint));
-
-       num_matches = empathy_regex_match (EMPATHY_REGEX_ALL, body, start, end);
-
-       if (num_matches == 0) {
-               gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-               chat_view_insert_text_with_emoticons (view, &iter, body);
-       } else {
-               gint   last = 0;
-               gint   s = 0, e = 0;
-               gchar *tmp;
-
-               for (i = 0; i < num_matches; i++) {
-                       s = g_array_index (start, gint, i);
-                       e = g_array_index (end, gint, i);
-
-                       if (s > last) {
-                               tmp = empathy_substring (body, last, s);
-
-                               gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-                               chat_view_insert_text_with_emoticons (view,
-                                                                     &iter,
-                                                                     tmp);
-                               g_free (tmp);
-                       }
-
-                       tmp = empathy_substring (body, s, e);
-
-                       gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-                       gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
-                                                                 &iter,
-                                                                 tmp,
-                                                                 -1,
-                                                                 link_tag,
-                                                                 "link",
-                                                                 NULL);
-
-                       g_free (tmp);
-
-                       last = e;
-               }
-
-               if (e < strlen (body)) {
-                       tmp = empathy_substring (body, e, strlen (body));
+       gint       src_width, src_height;
+       GdkPixbuf *padded;
+       gint       x_offset, y_offset;
 
-                       gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-                       chat_view_insert_text_with_emoticons (view,
-                                                             &iter,
-                                                             tmp);
-                       g_free (tmp);
-               }
-       }
+       src_width = gdk_pixbuf_get_width (pixbuf);
+       src_height = gdk_pixbuf_get_height (pixbuf);
 
-       g_array_free (start, TRUE);
-       g_array_free (end, TRUE);
+       x_offset = (width - src_width) / 2;
+       y_offset = (height - src_height) / 2;
 
-       gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-       gtk_text_buffer_insert (priv->buffer, &iter, "\n", 1);
+       padded = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (pixbuf),
+                                TRUE, /* alpha */
+                                gdk_pixbuf_get_bits_per_sample (pixbuf),
+                                width + extra_padding_right,
+                                height);
 
-       /* Apply the style to the inserted text. */
-       gtk_text_buffer_get_iter_at_mark (priv->buffer, &start_iter, mark);
-       gtk_text_buffer_get_end_iter (priv->buffer, &end_iter);
+       gdk_pixbuf_fill (padded, 0);
 
-       gtk_text_buffer_apply_tag_by_name (priv->buffer,
-                                          tag,
-                                          &start_iter,
-                                          &end_iter);
+       gdk_pixbuf_copy_area (pixbuf,
+                             0, /* source coords */
+                             0,
+                             src_width,
+                             src_height,
+                             padded,
+                             x_offset, /* dest coords */
+                             y_offset);
 
-       gtk_text_buffer_delete_mark (priv->buffer, mark);
+       return padded;
 }
 
 typedef struct {
@@ -924,8 +716,8 @@ chat_view_avatar_cache_data_free (gpointer ptr)
        g_slice_free (AvatarData, data);
 }
 
-static GdkPixbuf *
-chat_view_get_avatar_pixbuf_with_cache (EmpathyContact *contact)
+GdkPixbuf *
+empathy_chat_view_get_avatar_pixbuf_with_cache (EmpathyContact *contact)
 {
        static GHashTable *avatar_cache = NULL;
        AvatarData        *data;
@@ -976,425 +768,38 @@ chat_view_get_avatar_pixbuf_with_cache (EmpathyContact *contact)
        return data->pixbuf;
 }
 
-static void
-chat_view_maybe_append_fancy_header (EmpathyChatView *view,
-                                    EmpathyMessage  *msg)
-{
-       EmpathyChatViewPriv *priv;
-       EmpathyContact      *sender;
-       const gchar        *name;
-       gboolean            header;
-       GtkTextIter         iter;
-       gchar              *tmp;
-       const gchar        *tag;
-       const gchar        *avatar_tag;
-       const gchar        *line_top_tag;
-       const gchar        *line_bottom_tag;
-       gboolean            from_self;
-       GdkPixbuf          *avatar = NULL;
-
-       priv = GET_PRIV (view);
-
-       sender = empathy_message_get_sender (msg);
-       name = empathy_contact_get_name (sender);
-       from_self = empathy_contact_is_user (sender);
-
-       empathy_debug (DEBUG_DOMAIN, "Maybe add fancy header");
-
-       if (from_self) {
-               tag = "fancy-header-self";
-               line_top_tag = "fancy-line-top-self";
-               line_bottom_tag = "fancy-line-bottom-self";
-       } else {
-               tag = "fancy-header-other";
-               line_top_tag = "fancy-line-top-other";
-               line_bottom_tag = "fancy-line-bottom-other";
-       }
-
-       header = FALSE;
-
-       /* Only insert a header if the previously inserted block is not the same
-        * as this one. This catches all the different cases:
-        */
-       if (priv->last_block_type != BLOCK_TYPE_SELF &&
-           priv->last_block_type != BLOCK_TYPE_OTHER) {
-               header = TRUE;
-       }
-       else if (from_self && priv->last_block_type == BLOCK_TYPE_OTHER) {
-               header = TRUE;
-       }
-       else if (!from_self && priv->last_block_type == BLOCK_TYPE_SELF) {
-               header = TRUE;
-       }
-       else if (!from_self &&
-                (!priv->last_contact ||
-                 !empathy_contact_equal (sender, priv->last_contact))) {
-               header = TRUE;
-       }
-
-       if (!header) {
-               return;
-       }
-
-       chat_view_append_spacing (view);
-
-       gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-       gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
-                                                 &iter,
-                                                 "\n",
-                                                 -1,
-                                                 line_top_tag,
-                                                 NULL);
-       avatar = chat_view_get_avatar_pixbuf_with_cache (sender);
-       if (avatar) {
-               GtkTextIter start;
-
-               gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-               gtk_text_buffer_insert_pixbuf (priv->buffer, &iter, avatar);
-
-               gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-               start = iter;
-               gtk_text_iter_backward_char (&start);
-
-               if (from_self) {
-                       gtk_text_buffer_apply_tag_by_name (priv->buffer,
-                                                          "fancy-avatar-self",
-                                                          &start, &iter);
-                       avatar_tag = "fancy-header-self-avatar";
-               } else {
-                       gtk_text_buffer_apply_tag_by_name (priv->buffer,
-                                                          "fancy-avatar-other",
-                                                          &start, &iter);
-                       avatar_tag = "fancy-header-other-avatar";
-               }
-       } else {
-               avatar_tag = NULL;
-       }
-
-       tmp = g_strdup_printf ("%s\n", name);
-
-       gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-       gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
-                                                 &iter,
-                                                 tmp,
-                                                 -1,
-                                                 tag,
-                                                 avatar_tag,
-                                                 NULL);
-       g_free (tmp);
-
-       gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-       gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
-                                                 &iter,
-                                                 "\n",
-                                                 -1,
-                                                 line_bottom_tag,
-                                                 NULL);
-}
-
-static void
-chat_view_append_irc_action (EmpathyChatView *view,
-                            EmpathyMessage  *msg)
-{
-       EmpathyChatViewPriv *priv;
-       EmpathyContact      *sender;
-       const gchar        *name;
-       GtkTextIter         iter;
-       const gchar        *body;
-       gchar              *tmp;
-       const gchar        *tag;
-
-       priv = GET_PRIV (view);
-
-       empathy_debug (DEBUG_DOMAIN, "Add IRC action");
-
-       sender = empathy_message_get_sender (msg);
-       name = empathy_contact_get_name (sender);
-
-       if (empathy_contact_is_user (sender)) {
-               tag = "irc-action-self";
-       } else {
-               tag = "irc-action-other";
-       }
-
-       if (priv->last_block_type != BLOCK_TYPE_SELF &&
-           priv->last_block_type != BLOCK_TYPE_OTHER) {
-               chat_view_append_spacing (view);
-       }
-
-       gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-
-       tmp = g_strdup_printf (" * %s ", name);
-       gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
-                                                 &iter,
-                                                 tmp,
-                                                 -1,
-                                                 "cut",
-                                                 tag,
-                                                 NULL);
-       g_free (tmp);
-
-       body = empathy_message_get_body (msg);
-       chat_view_append_text (view, body, tag);
-}
-
-static void
-chat_view_append_fancy_action (EmpathyChatView *view,
-                              EmpathyMessage  *msg)
-{
-       EmpathyChatViewPriv *priv;
-       EmpathyContact      *sender;
-       const gchar        *name;
-       const gchar        *body;
-       GtkTextIter         iter;
-       gchar              *tmp;
-       const gchar        *tag;
-       const gchar        *line_tag;
-
-       priv = GET_PRIV (view);
-
-       empathy_debug (DEBUG_DOMAIN, "Add fancy action");
-
-       sender = empathy_message_get_sender (msg);
-       name = empathy_contact_get_name (sender);
-
-       if (empathy_contact_is_user (sender)) {
-               tag = "fancy-action-self";
-               line_tag = "fancy-line-self";
-       } else {
-               tag = "fancy-action-other";
-               line_tag = "fancy-line-other";
-       }
-
-       tmp = g_strdup_printf (" * %s ", name);
-       gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-       gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
-                                                 &iter,
-                                                 tmp,
-                                                 -1,
-                                                 tag,
-                                                 NULL);
-       g_free (tmp);
-
-       body = empathy_message_get_body (msg);
-       chat_view_append_text (view, body, tag);
-}
-
-static void
-chat_view_append_irc_message (EmpathyChatView *view,
-                             EmpathyMessage  *msg)
-{
-       EmpathyChatViewPriv *priv;
-       EmpathyContact      *sender;
-       const gchar        *name;
-       const gchar        *body;
-       const gchar        *nick_tag;
-       const gchar        *body_tag;
-       GtkTextIter         iter;
-       gchar              *tmp;
-
-       priv = GET_PRIV (view);
-
-       empathy_debug (DEBUG_DOMAIN, "Add IRC message");
-
-       body = empathy_message_get_body (msg);
-       sender = empathy_message_get_sender (msg);
-       name = empathy_contact_get_name (sender);
-
-       if (empathy_contact_is_user (sender)) {
-               nick_tag = "irc-nick-self";
-               body_tag = "irc-body-self";
-       } else {
-               if (empathy_chat_should_highlight_nick (msg)) {
-                       nick_tag = "irc-nick-highlight";
-               } else {
-                       nick_tag = "irc-nick-other";
-               }
-
-               body_tag = "irc-body-other";
-       }
-
-       if (priv->last_block_type != BLOCK_TYPE_SELF &&
-           priv->last_block_type != BLOCK_TYPE_OTHER) {
-               chat_view_append_spacing (view);
-       }
-
-       gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-
-       /* The nickname. */
-       tmp = g_strdup_printf ("%s: ", name);
-       gtk_text_buffer_insert_with_tags_by_name (priv->buffer,
-                                                 &iter,
-                                                 tmp,
-                                                 -1,
-                                                 "cut",
-                                                 nick_tag,
-                                                 NULL);
-       g_free (tmp);
-
-       /* The text body. */
-       chat_view_append_text (view, body, body_tag);
-}
-
-static void
-chat_view_append_fancy_message (EmpathyChatView *view,
-                               EmpathyMessage  *msg)
-{
-       EmpathyChatViewPriv *priv;
-       EmpathyContact      *sender;
-       const gchar        *body;
-       const gchar        *tag;
-
-       priv = GET_PRIV (view);
-
-       sender = empathy_message_get_sender (msg);
-
-       if (empathy_contact_is_user (sender)) {
-               tag = "fancy-body-self";
-       } else {
-               tag = "fancy-body-other";
-
-               /* FIXME: Might want to support nick highlighting here... */
-       }
-
-       body = empathy_message_get_body (msg);
-       chat_view_append_text (view, body, tag);
-}
-
-static void
-chat_view_theme_changed_cb (EmpathyThemeManager *manager,
-                           EmpathyChatView     *view)
-{
-       EmpathyChatViewPriv *priv;
-       gboolean            show_avatars = FALSE;
-       gboolean            theme_rooms = FALSE;
-
-       priv = GET_PRIV (view);
-
-       priv->last_block_type = BLOCK_TYPE_NONE;
-
-       empathy_conf_get_bool (empathy_conf_get (),
-                             EMPATHY_PREFS_CHAT_THEME_CHAT_ROOM,
-                             &theme_rooms);
-       if (!theme_rooms && priv->is_group_chat) {
-               empathy_theme_manager_apply (manager, view, NULL);
-       } else {
-               empathy_theme_manager_apply_saved (manager, view);
-       }
-
-       /* Needed for now to update the "rise" property of the names to get it
-        * vertically centered.
-        */
-       empathy_conf_get_bool (empathy_conf_get (),
-                              EMPATHY_PREFS_UI_SHOW_AVATARS,
-                              &show_avatars);
-       empathy_theme_manager_update_show_avatars (manager, view, show_avatars);
-}
-
-/* Pads a pixbuf to the specified size, by centering it in a larger transparent
- * pixbuf. Returns a new ref.
- */
-static GdkPixbuf *
-chat_view_pad_to_size (GdkPixbuf *pixbuf,
-                      gint       width,
-                      gint       height,
-                      gint       extra_padding_right)
-{
-       gint       src_width, src_height;
-       GdkPixbuf *padded;
-       gint       x_offset, y_offset;
-
-       src_width = gdk_pixbuf_get_width (pixbuf);
-       src_height = gdk_pixbuf_get_height (pixbuf);
-
-       x_offset = (width - src_width) / 2;
-       y_offset = (height - src_height) / 2;
-
-       padded = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (pixbuf),
-                                TRUE, /* alpha */
-                                gdk_pixbuf_get_bits_per_sample (pixbuf),
-                                width + extra_padding_right,
-                                height);
-
-       gdk_pixbuf_fill (padded, 0);
-
-       gdk_pixbuf_copy_area (pixbuf,
-                             0, /* source coords */
-                             0,
-                             src_width,
-                             src_height,
-                             padded,
-                             x_offset, /* dest coords */
-                             y_offset);
-
-       return padded;
-}
-
 EmpathyChatView *
 empathy_chat_view_new (void)
 {
        return g_object_new (EMPATHY_TYPE_CHAT_VIEW, NULL);
 }
 
-/* The name is optional, if NULL, the sender for msg is used. */
 void
 empathy_chat_view_append_message (EmpathyChatView *view,
-                                EmpathyMessage  *msg)
+                                 EmpathyMessage  *msg)
 {
-       EmpathyChatViewPriv *priv;
+       EmpathyChatViewPriv *priv = GET_PRIV (view);
        EmpathyContact      *sender;
-       const gchar        *body;
-       gboolean            scroll_down;
+       gboolean             bottom;
+       gboolean             from_self;
 
        g_return_if_fail (EMPATHY_IS_CHAT_VIEW (view));
        g_return_if_fail (EMPATHY_IS_MESSAGE (msg));
 
-       priv = GET_PRIV (view);
-
-       body = empathy_message_get_body (msg);
-       if (!body) {
+       if (!empathy_message_get_body (msg)) {
                return;
        }
 
-       scroll_down = chat_view_is_scrolled_down (view);
-
-       chat_view_maybe_trim_buffer (view);
-       chat_view_maybe_append_date_and_time (view, msg);
-
+       bottom = chat_view_is_scrolled_down (view);
        sender = empathy_message_get_sender (msg);
+       from_self = empathy_contact_is_user (sender);
+       
+       chat_view_maybe_trim_buffer (view);
 
-       if (!priv->irc_style) {
-               chat_view_maybe_append_fancy_header (view, msg);
-       }
-
-       if (empathy_message_get_type (msg) == EMPATHY_MESSAGE_TYPE_ACTION) {
-               if (priv->irc_style) {
-                       chat_view_append_irc_action (view, msg);
-               } else {
-                       chat_view_append_fancy_action (view, msg);
-               }
-       } else {
-               if (priv->irc_style) {
-                       chat_view_append_irc_message (view, msg);
-               } else {
-                       chat_view_append_fancy_message (view, msg);
-               }
-       }
-
-       /* Reset the last inserted contact. */
-       if (priv->last_contact) {
-               g_object_unref (priv->last_contact);
-       }
+       empathy_theme_append_message (priv->theme, priv->theme_context,
+                                     view, msg);
 
-       if (empathy_contact_is_user (sender)) {
-               priv->last_block_type = BLOCK_TYPE_SELF;
-               priv->last_contact = NULL;
-       } else {
-               priv->last_block_type = BLOCK_TYPE_OTHER;
-               priv->last_contact = g_object_ref (sender);
-       }
-
-       if (scroll_down) {
+       if (bottom) {
                empathy_chat_view_scroll_down (view);
        }
 }
@@ -1405,9 +810,6 @@ empathy_chat_view_append_event (EmpathyChatView *view,
 {
        EmpathyChatViewPriv *priv;
        gboolean            bottom;
-       GtkTextIter         iter;
-       gchar              *msg;
-       const gchar        *tag;
 
        g_return_if_fail (EMPATHY_IS_CHAT_VIEW (view));
        g_return_if_fail (!G_STR_EMPTY (str));
@@ -1418,28 +820,9 @@ empathy_chat_view_append_event (EmpathyChatView *view,
 
        chat_view_maybe_trim_buffer (view);
 
-       if (priv->irc_style) {
-               tag = "irc-event";
-               msg = g_strdup_printf (" - %s\n", str);
-       } else {
-               tag = "fancy-event";
-               msg = g_strdup_printf (" - %s\n", str);
-       }
-
-       if (priv->last_block_type != BLOCK_TYPE_EVENT) {
-               /* Comment out for now. */
-               /*chat_view_append_spacing (view);*/
-       }
-
-       chat_view_maybe_append_date_and_time (view, NULL);
-
-       gtk_text_buffer_get_end_iter (priv->buffer, &iter);
-
-       gtk_text_buffer_insert_with_tags_by_name (priv->buffer, &iter,
-                                                 msg, -1,
-                                                 tag,
-                                                 NULL);
-       g_free (msg);
+       empathy_theme_append_event (priv->theme, 
+                                  priv->theme_context,
+                                  view, str);
 
        if (bottom) {
                empathy_chat_view_scroll_down (view);
@@ -1465,18 +848,17 @@ empathy_chat_view_append_button (EmpathyChatView *view,
 
        priv = GET_PRIV (view);
 
-       if (priv->irc_style) {
-               tag = "irc-invite";
-       } else {
-               tag = "fancy-invite";
-       }
+       tag = "invite";
 
        bottom = chat_view_is_scrolled_down (view);
 
-       chat_view_maybe_append_date_and_time (view, NULL);
+       empathy_theme_append_timestamp (priv->theme, priv->theme_context,
+                                      view, NULL,
+                                      TRUE, TRUE);
 
        if (message) {
-               chat_view_append_text (view, message, tag);
+               empathy_theme_append_text (priv->theme, priv->theme_context,
+                                         view, message, tag, NULL);
        }
 
        gtk_text_buffer_get_end_iter (priv->buffer, &iter);
@@ -1624,6 +1006,8 @@ empathy_chat_view_clear (EmpathyChatView *view)
         */
        priv = GET_PRIV (view);
 
+       empathy_theme_view_cleared (priv->theme, priv->theme_context, view);
+
        priv->last_block_type = BLOCK_TYPE_NONE;
        priv->last_timestamp = 0;
 }
@@ -1973,29 +1357,61 @@ empathy_chat_view_copy_clipboard (EmpathyChatView *view)
        gtk_text_buffer_copy_clipboard (buffer, clipboard);
 }
 
-gboolean
-empathy_chat_view_get_irc_style (EmpathyChatView *view)
+EmpathyTheme *
+empathy_chat_view_get_theme (EmpathyChatView *view)
 {
        EmpathyChatViewPriv *priv;
 
-       g_return_val_if_fail (EMPATHY_IS_CHAT_VIEW (view), FALSE);
+       g_return_val_if_fail (EMPATHY_IS_CHAT_VIEW (view), NULL);
 
        priv = GET_PRIV (view);
 
-       return priv->irc_style;
+       return priv->theme;
+}
+
+static void
+chat_view_theme_updated_cb (EmpathyTheme *theme, EmpathyChatView *view)
+{
+       EmpathyChatViewPriv *priv;
+
+       priv = GET_PRIV (view);
+       
+       empathy_theme_detach_from_view (priv->theme, priv->theme_context,
+                                      view);
+
+       priv->theme_context = empathy_theme_setup_with_view (theme, view);
 }
 
 void
-empathy_chat_view_set_irc_style (EmpathyChatView *view,
-                               gboolean        irc_style)
+empathy_chat_view_set_theme (EmpathyChatView *view, EmpathyTheme *theme)
 {
        EmpathyChatViewPriv *priv;
 
        g_return_if_fail (EMPATHY_IS_CHAT_VIEW (view));
+       g_return_if_fail (EMPATHY_IS_THEME (theme));
 
        priv = GET_PRIV (view);
 
-       priv->irc_style = irc_style;
+       if (priv->theme) {
+               g_signal_handlers_disconnect_by_func (priv->theme,
+                                                     chat_view_theme_updated_cb,
+                                                     view);
+               empathy_theme_detach_from_view (priv->theme, priv->theme_context,
+                                              view);
+
+               g_object_unref (priv->theme);
+       }
+
+       priv->theme = g_object_ref (theme);
+
+       g_signal_connect (priv->theme,
+                         "updated",
+                         G_CALLBACK (chat_view_theme_updated_cb),
+                         view);
+
+       priv->theme_context = empathy_theme_setup_with_view (theme, view);
+
+       /* FIXME: Possibly redraw the function and make it a property */
 }
 
 void
@@ -2092,3 +1508,85 @@ empathy_chat_view_set_is_group_chat (EmpathyChatView *view,
                                                  view);
        }
 }
+
+time_t
+empathy_chat_view_get_last_timestamp (EmpathyChatView *view)
+{
+       EmpathyChatViewPriv *priv;
+
+       g_return_val_if_fail (EMPATHY_IS_CHAT_VIEW (view), 0);
+
+       priv = GET_PRIV (view);
+
+       return priv->last_timestamp;
+}
+
+void
+empathy_chat_view_set_last_timestamp (EmpathyChatView *view,
+                                    time_t          timestamp)
+{
+       EmpathyChatViewPriv *priv;
+
+       g_return_if_fail (EMPATHY_IS_CHAT_VIEW (view));
+
+       priv = GET_PRIV (view);
+
+       priv->last_timestamp = timestamp;
+}
+
+BlockType
+empathy_chat_view_get_last_block_type (EmpathyChatView *view)
+{
+       EmpathyChatViewPriv *priv;
+
+       g_return_val_if_fail (EMPATHY_IS_CHAT_VIEW (view), 0);
+
+       priv = GET_PRIV (view);
+
+       return priv->last_block_type;
+}
+
+void
+empathy_chat_view_set_last_block_type (EmpathyChatView *view, 
+                                     BlockType       block_type)
+{
+       EmpathyChatViewPriv *priv;
+
+       g_return_if_fail (EMPATHY_IS_CHAT_VIEW (view));
+
+       priv = GET_PRIV (view);
+
+       priv->last_block_type = block_type;
+}
+
+EmpathyContact *
+empathy_chat_view_get_last_contact (EmpathyChatView *view)
+{
+       EmpathyChatViewPriv *priv;
+
+       g_return_val_if_fail (EMPATHY_IS_CHAT_VIEW (view), NULL);
+
+       priv = GET_PRIV (view);
+
+       return priv->last_contact;
+}
+
+void
+empathy_chat_view_set_last_contact (EmpathyChatView *view, EmpathyContact *contact)
+{
+       EmpathyChatViewPriv *priv;
+
+       g_return_if_fail (EMPATHY_IS_CHAT_VIEW (view));
+
+       priv = GET_PRIV (view);
+
+       if (priv->last_contact) {
+               g_object_unref (priv->last_contact);
+               priv->last_contact = NULL;
+       }
+
+       if (contact) {
+               priv->last_contact = g_object_ref (contact);
+       }
+}
+
index 0402bd7c0605c9c42488851861823f931ed81d57..37a7f9977cd92cbd344f43010f9c85b53c3bd7e5 100644 (file)
@@ -43,6 +43,8 @@ typedef struct _EmpathyChatView      EmpathyChatView;
 typedef struct _EmpathyChatViewClass EmpathyChatViewClass;
 typedef struct _EmpathyChatViewPriv  EmpathyChatViewPriv;
 
+#include "empathy-theme.h"
+
 struct _EmpathyChatView {
        GtkTextView parent;
 };
@@ -51,6 +53,15 @@ struct _EmpathyChatViewClass {
        GtkTextViewClass parent_class;
 };
 
+typedef enum {
+       BLOCK_TYPE_NONE,
+       BLOCK_TYPE_SELF,
+       BLOCK_TYPE_OTHER,
+       BLOCK_TYPE_EVENT,
+       BLOCK_TYPE_TIME,
+       BLOCK_TYPE_INVITE
+} BlockType;
+
 GType            empathy_chat_view_get_type             (void) G_GNUC_CONST;
 EmpathyChatView *empathy_chat_view_new                  (void);
 void             empathy_chat_view_append_message       (EmpathyChatView *view,
@@ -83,15 +94,25 @@ void             empathy_chat_view_find_abilities       (EmpathyChatView *view,
 void             empathy_chat_view_highlight            (EmpathyChatView *view,
                                                         const gchar     *text);
 void             empathy_chat_view_copy_clipboard       (EmpathyChatView *view);
-gboolean         empathy_chat_view_get_irc_style        (EmpathyChatView *view);
-void             empathy_chat_view_set_irc_style        (EmpathyChatView *view,
-                                                        gboolean         irc_style);
+EmpathyTheme *   empathy_chat_view_get_theme            (EmpathyChatView *view);
+void             empathy_chat_view_set_theme            (EmpathyChatView *view,
+                                                        EmpathyTheme    *theme);
 void             empathy_chat_view_set_margin           (EmpathyChatView *view,
                                                         gint             margin);
 GtkWidget *      empathy_chat_view_get_smiley_menu      (GCallback        callback,
                                                         gpointer         user_data);
 void             empathy_chat_view_set_is_group_chat    (EmpathyChatView *view,
                                                         gboolean         is_group_chat);
+time_t           empathy_chat_view_get_last_timestamp   (EmpathyChatView *view);
+void             empathy_chat_view_set_last_timestamp   (EmpathyChatView *view,
+                                                        time_t           timestamp);
+BlockType        empathy_chat_view_get_last_block_type  (EmpathyChatView *view);
+void             empathy_chat_view_set_last_block_type  (EmpathyChatView *view, 
+                                                        BlockType        block_type);
+EmpathyContact * empathy_chat_view_get_last_contact     (EmpathyChatView *view);
+void             empathy_chat_view_set_last_contact     (EmpathyChatView *view,
+                                                        EmpathyContact  *contact);
+GdkPixbuf *      empathy_chat_view_get_avatar_pixbuf_with_cache (EmpathyContact *contact);
 
 G_END_DECLS
 
diff --git a/libempathy-gtk/empathy-theme-boxes.c b/libempathy-gtk/empathy-theme-boxes.c
new file mode 100644 (file)
index 0000000..2905f2b
--- /dev/null
@@ -0,0 +1,1036 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Imendio AB
+ *
+ * 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 <config.h>
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <libempathy/empathy-debug.h>
+
+#include "empathy-ui-utils.h"
+#include "empathy-main-window.h"
+#include "empathy-theme-utils.h"
+#include "empathy-theme-boxes.h"
+
+#define DEBUG_DOMAIN "FancyTheme"
+
+#define MARGIN 4
+#define HEADER_PADDING 2
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_THEME_BOXES, EmpathyThemeBoxesPriv))
+
+typedef struct _EmpathyThemeBoxesPriv EmpathyThemeBoxesPriv;
+
+struct _EmpathyThemeBoxesPriv {
+       gchar *header_foreground;
+       gchar *header_background;
+       gchar *header_line_background;
+       gchar *text_foreground;
+       gchar *text_background;
+       gchar *action_foreground;
+       gchar *highlight_foreground;
+       gchar *time_foreground;
+       gchar *event_foreground;
+       gchar *invite_foreground;
+       gchar *link_foreground;
+};
+
+static void     theme_boxes_finalize          (GObject            *object);
+static void     theme_boxes_get_property      (GObject            *object,
+                                              guint               param_id,
+                                              GValue             *value,
+                                              GParamSpec         *pspec);
+static void     theme_boxes_set_property      (GObject            *object,
+                                              guint               param_id,
+                                              const GValue       *value,
+                                              GParamSpec         *pspec);
+static void     theme_boxes_define_theme_tags (EmpathyTheme        *theme,
+                                              EmpathyChatView     *view);
+static EmpathyThemeContext *
+theme_boxes_setup_with_view                   (EmpathyTheme        *theme,
+                                              EmpathyChatView     *view);
+static void     theme_boxes_detach_from_view  (EmpathyTheme        *theme,
+                                              EmpathyThemeContext *context,
+                                              EmpathyChatView     *view);
+static void     theme_boxes_view_cleared      (EmpathyTheme        *theme,
+                                              EmpathyThemeContext *context,
+                                              EmpathyChatView     *view);
+
+static void     theme_boxes_append_message    (EmpathyTheme        *theme,
+                                              EmpathyThemeContext *context,
+                                              EmpathyChatView     *view,
+                                              EmpathyMessage      *message);
+static void     theme_boxes_append_event      (EmpathyTheme        *theme,
+                                              EmpathyThemeContext *context,
+                                              EmpathyChatView     *view,
+                                              const gchar        *str);
+static void     theme_boxes_append_timestamp  (EmpathyTheme        *theme,
+                                              EmpathyThemeContext *context,
+                                              EmpathyChatView     *view,
+                                              EmpathyMessage      *message,
+                                              gboolean            show_date,
+                                              gboolean            show_time);
+static void     theme_boxes_append_spacing    (EmpathyTheme        *theme,
+                                              EmpathyThemeContext *context,
+                                              EmpathyChatView     *view);
+
+enum {
+       PROP_0,
+       PROP_HEADER_FOREGROUND,
+       PROP_HEADER_BACKGROUND,
+       PROP_HEADER_LINE_BACKGROUND,
+       PROP_TEXT_FOREGROUND,
+       PROP_TEXT_BACKGROUND,
+       PROP_ACTION_FOREGROUND,
+       PROP_HIGHLIGHT_FOREGROUND,
+       PROP_TIME_FOREGROUND,
+       PROP_EVENT_FOREGROUND,
+       PROP_INVITE_FOREGROUND,
+       PROP_LINK_FOREGROUND
+};
+
+enum {
+       PROP_FLOP,
+       PROP_MY_PROP
+};
+
+G_DEFINE_TYPE (EmpathyThemeBoxes, empathy_theme_boxes, EMPATHY_TYPE_THEME);
+
+static void
+empathy_theme_boxes_class_init (EmpathyThemeBoxesClass *class)
+{
+       GObjectClass     *object_class;
+       EmpathyThemeClass *theme_class;
+
+       object_class = G_OBJECT_CLASS (class);
+       theme_class  = EMPATHY_THEME_CLASS (class);
+
+       object_class->finalize       = theme_boxes_finalize;
+       object_class->get_property   = theme_boxes_get_property;
+       object_class->set_property   = theme_boxes_set_property;
+
+       theme_class->setup_with_view  = theme_boxes_setup_with_view;
+       theme_class->detach_from_view = theme_boxes_detach_from_view;
+       theme_class->view_cleared     = theme_boxes_view_cleared;
+       theme_class->append_message   = theme_boxes_append_message;
+       theme_class->append_event     = theme_boxes_append_event;
+       theme_class->append_timestamp = theme_boxes_append_timestamp;
+       theme_class->append_spacing   = theme_boxes_append_spacing;
+
+       g_object_class_install_property (object_class,
+                                        PROP_HEADER_FOREGROUND,
+                                        g_param_spec_string ("header-foreground",
+                                                             "",
+                                                             "",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+
+       g_object_class_install_property (object_class,
+                                        PROP_HEADER_BACKGROUND,
+                                        g_param_spec_string ("header-background",
+                                                             "",
+                                                             "",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+
+       g_object_class_install_property (object_class,
+                                        PROP_HEADER_LINE_BACKGROUND,
+                                        g_param_spec_string ("header-line-background",
+                                                             "",
+                                                             "",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+
+
+       g_object_class_install_property (object_class,
+                                        PROP_TEXT_FOREGROUND,
+                                        g_param_spec_string ("text-foreground",
+                                                             "",
+                                                             "",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+
+       g_object_class_install_property (object_class,
+                                        PROP_TEXT_BACKGROUND,
+                                        g_param_spec_string ("text-background",
+                                                             "",
+                                                             "",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+
+       g_object_class_install_property (object_class,
+                                        PROP_ACTION_FOREGROUND,
+                                        g_param_spec_string ("action-foreground",
+                                                             "",
+                                                             "",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+
+       g_object_class_install_property (object_class,
+                                        PROP_HIGHLIGHT_FOREGROUND,
+                                        g_param_spec_string ("highlight-foreground",
+                                                             "",
+                                                             "",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+
+       g_object_class_install_property (object_class,
+                                        PROP_TIME_FOREGROUND,
+                                        g_param_spec_string ("time-foreground",
+                                                             "",
+                                                             "",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+
+       g_object_class_install_property (object_class,
+                                        PROP_EVENT_FOREGROUND,
+                                        g_param_spec_string ("event-foreground",
+                                                             "",
+                                                             "",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+
+       g_object_class_install_property (object_class,
+                                        PROP_INVITE_FOREGROUND,
+                                        g_param_spec_string ("invite-foreground",
+                                                             "",
+                                                             "",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+
+       g_object_class_install_property (object_class,
+                                        PROP_LINK_FOREGROUND,
+                                        g_param_spec_string ("link-foreground",
+                                                             "",
+                                                             "",
+                                                             NULL,
+                                                             G_PARAM_READWRITE));
+
+       g_type_class_add_private (object_class, sizeof (EmpathyThemeBoxesPriv));
+}
+
+static void
+empathy_theme_boxes_init (EmpathyThemeBoxes *theme)
+{
+       EmpathyThemeBoxesPriv *priv;
+
+       priv = GET_PRIV (theme);
+}
+
+static void
+theme_boxes_finalize (GObject *object)
+{
+       EmpathyThemeBoxesPriv *priv;
+
+       priv = GET_PRIV (object);
+
+       g_free (priv->header_foreground);
+       g_free (priv->header_background);
+       g_free (priv->header_line_background);
+       g_free (priv->text_foreground);
+       g_free (priv->text_background);
+       g_free (priv->action_foreground);
+       g_free (priv->highlight_foreground);
+       g_free (priv->time_foreground);
+       g_free (priv->event_foreground);
+       g_free (priv->invite_foreground);
+       g_free (priv->link_foreground);
+       
+       (G_OBJECT_CLASS (empathy_theme_boxes_parent_class)->finalize) (object);
+}
+
+static void
+theme_boxes_get_property (GObject    *object,
+                         guint       param_id,
+                         GValue     *value,
+                         GParamSpec *pspec)
+{
+       EmpathyThemeBoxesPriv *priv;
+
+       priv = GET_PRIV (object);
+
+       switch (param_id) {
+       case PROP_HEADER_FOREGROUND:
+               g_value_set_string (value, priv->header_foreground);
+               break;
+       case PROP_HEADER_BACKGROUND:
+               g_value_set_string (value, priv->header_background);
+               break;
+       case PROP_HEADER_LINE_BACKGROUND:
+               g_value_set_string (value, priv->header_line_background);
+               break;
+       case PROP_TEXT_FOREGROUND:
+               g_value_set_string (value, priv->text_foreground);
+               break;
+       case PROP_TEXT_BACKGROUND:
+               g_value_set_string (value, priv->text_background);
+               break;
+       case PROP_ACTION_FOREGROUND:
+               g_value_set_string (value, priv->action_foreground);
+               break;
+       case PROP_HIGHLIGHT_FOREGROUND:
+               g_value_set_string (value, priv->highlight_foreground);
+               break;
+       case PROP_TIME_FOREGROUND:
+               g_value_set_string (value, priv->time_foreground);
+               break;
+       case PROP_EVENT_FOREGROUND:
+               g_value_set_string (value, priv->event_foreground);
+               break;
+       case PROP_INVITE_FOREGROUND:
+               g_value_set_string (value, priv->invite_foreground);
+               break;
+       case PROP_LINK_FOREGROUND:
+               g_value_set_string (value, priv->link_foreground);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+               break;
+       }
+}
+static void
+theme_boxes_set_property (GObject      *object,
+                   guint         param_id,
+                   const GValue *value,
+                   GParamSpec   *pspec)
+{
+       EmpathyThemeBoxesPriv *priv;
+
+       priv = GET_PRIV (object);
+
+       switch (param_id) {
+       case PROP_HEADER_FOREGROUND:
+               g_free (priv->header_foreground);
+               priv->header_foreground = g_value_dup_string (value);
+               break;
+       case PROP_HEADER_BACKGROUND:
+               g_free (priv->header_background);
+               priv->header_background = g_value_dup_string (value);
+               break;
+       case PROP_HEADER_LINE_BACKGROUND:
+               g_free (priv->header_line_background);
+               priv->header_line_background = g_value_dup_string (value);
+               break;
+       case PROP_TEXT_FOREGROUND:
+               g_free (priv->text_foreground);
+               priv->text_foreground = g_value_dup_string (value);
+               break;
+       case PROP_TEXT_BACKGROUND:
+               g_free (priv->text_background);
+               priv->text_background = g_value_dup_string (value);
+               break;
+       case PROP_ACTION_FOREGROUND:
+               g_free (priv->action_foreground);
+               priv->action_foreground = g_value_dup_string (value);
+               break;
+       case PROP_HIGHLIGHT_FOREGROUND:
+               g_free (priv->highlight_foreground);
+               priv->highlight_foreground = g_value_dup_string (value);
+               break;
+       case PROP_TIME_FOREGROUND:
+               g_free (priv->time_foreground);
+               priv->time_foreground = g_value_dup_string (value);
+               break;
+       case PROP_EVENT_FOREGROUND:
+               g_free (priv->event_foreground);
+               priv->event_foreground = g_value_dup_string (value);
+               break;
+       case PROP_INVITE_FOREGROUND:
+               g_free (priv->invite_foreground);
+               priv->invite_foreground = g_value_dup_string (value);
+               break;
+       case PROP_LINK_FOREGROUND:
+               g_free (priv->link_foreground);
+               priv->link_foreground = g_value_dup_string (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+               break;
+       }
+}
+
+static void
+theme_boxes_define_theme_tags (EmpathyTheme *theme, EmpathyChatView *view)
+{
+       EmpathyThemeBoxesPriv *priv;
+       GtkTextBuffer   *buffer;
+       GtkTextTagTable *table;
+       GtkTextTag      *tag;
+
+       priv = GET_PRIV (theme);
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+       table = gtk_text_buffer_get_tag_table (buffer);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "fancy-spacing");
+       g_object_set (tag,
+                     "size", 3000,
+                     "pixels-above-lines", 8,
+                     NULL);
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, 
+                                                  "fancy-header");
+       g_object_set (tag,
+                     "weight", PANGO_WEIGHT_BOLD,
+                     "pixels-above-lines", HEADER_PADDING,
+                     "pixels-below-lines", HEADER_PADDING,
+                     NULL);
+       if (priv->header_foreground) {
+               g_object_set (tag,
+                             "foreground", priv->header_foreground,
+                             "paragraph-background", priv->header_background,
+                             NULL);
+       }
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "fancy-header-line");
+       g_object_set (tag,
+                     "size", 1,
+                     NULL);
+       if (priv->header_line_background) {
+               g_object_set (tag,
+                             "paragraph-background", priv->header_line_background,
+                             NULL);
+       }
+
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "fancy-body");
+       g_object_set (tag,
+                     "pixels-above-lines", 4,
+                     NULL);
+       if (priv->text_background) {
+               g_object_set (tag,
+                             "paragraph-background", priv->text_background,
+                             NULL);
+       }
+
+       if (priv->text_foreground) {
+               g_object_set (tag,
+                             "foreground", priv->text_foreground,
+                             NULL);
+       }
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "fancy-action");
+       g_object_set (tag,
+                     "style", PANGO_STYLE_ITALIC,
+                     "pixels-above-lines", 4,
+                     NULL);
+
+       if (priv->text_background) {
+               g_object_set (tag,
+                             "paragraph-background", priv->text_background,
+                             NULL);
+       }
+
+       if (priv->action_foreground) {
+               g_object_set (tag,
+                             "foreground", priv->action_foreground,
+                             NULL);
+       } 
+
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table,
+                                                  "fancy-highlight");
+       g_object_set (tag,
+                     "weight", PANGO_WEIGHT_BOLD,
+                     "pixels-above-lines", 4,
+                     NULL);
+       if (priv->text_background) {
+               g_object_set (tag,
+                             "paragraph-background", priv->text_background,
+                             NULL);
+       }
+
+
+       if (priv->highlight_foreground) {
+               g_object_set (tag,
+                             "foreground", priv->highlight_foreground,
+                             NULL);
+       }
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "fancy-time");
+       g_object_set (tag,
+                     "justification", GTK_JUSTIFY_CENTER,
+                     NULL);
+       if (priv->time_foreground) {
+               g_object_set (tag,
+                             "foreground", priv->time_foreground,
+                             NULL);
+       }
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "fancy-event");
+       g_object_set (tag,
+                     "justification", GTK_JUSTIFY_LEFT,
+                     NULL);
+       if (priv->event_foreground) {
+               g_object_set (tag,
+                             "foreground", priv->event_foreground,
+                             NULL);
+       }
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "invite");
+       if (priv->invite_foreground) {
+               g_object_set (tag,
+                             "foreground", priv->invite_foreground,
+                             NULL);
+       }
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "fancy-link");
+       g_object_set (tag,
+                     "underline", PANGO_UNDERLINE_SINGLE,
+                     NULL);
+       if (priv->link_foreground) {
+               g_object_set (tag,
+                             "foreground", priv->link_foreground,
+                             NULL);
+       } 
+       empathy_theme_utils_add_tag (table, tag);
+}
+
+static void
+theme_boxes_fixup_tag_table (EmpathyTheme *theme, EmpathyChatView *view)
+{
+       GtkTextBuffer *buffer;
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       /* "Fancy" style tags. */
+       empathy_theme_utils_ensure_tag_by_name (buffer, "fancy-header");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "fancy-header-line");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "fancy-body");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "fancy-action");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "fancy-highlight");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "fancy-spacing");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "fancy-time");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "fancy-event");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "fancy-link");
+}
+
+typedef struct {
+       BlockType last_block_type;
+       time_t    last_timestamp;
+} FancyContext;
+
+static EmpathyThemeContext *
+theme_boxes_setup_with_view (EmpathyTheme *theme, EmpathyChatView *view)
+{
+       EmpathyThemeBoxesPriv *priv;
+
+       g_return_val_if_fail (EMPATHY_IS_THEME_BOXES (theme), NULL);
+
+       priv = GET_PRIV (theme);
+
+       theme_boxes_fixup_tag_table (theme, view);
+
+       theme_boxes_define_theme_tags (theme, view);
+       
+       empathy_chat_view_set_margin (view, MARGIN);
+
+       return NULL;
+}
+
+static void
+theme_boxes_detach_from_view (EmpathyTheme        *theme,
+                             EmpathyThemeContext *context,
+                             EmpathyChatView     *view)
+{
+       /* FIXME: Free the context */
+}
+
+static void 
+theme_boxes_view_cleared (EmpathyTheme        *theme,
+                         EmpathyThemeContext *context,
+                         EmpathyChatView     *view)
+{
+       /* FIXME: clear the context data */
+}
+
+static void
+table_size_allocate_cb (GtkWidget     *view,
+                       GtkAllocation *allocation,
+                       GtkWidget     *box)
+{
+       gint width, height;
+
+        gtk_widget_get_size_request (box, NULL, &height);
+
+       width = allocation->width;
+       
+       width -= \
+               gtk_text_view_get_right_margin (GTK_TEXT_VIEW (view)) - \
+               gtk_text_view_get_left_margin (GTK_TEXT_VIEW (view));
+       width -= 2 * MARGIN;
+       width -= 2 * HEADER_PADDING;
+
+        gtk_widget_set_size_request (box, width, height);
+}
+
+static void
+theme_boxes_maybe_append_header (EmpathyTheme        *theme,
+                                EmpathyThemeContext *context,
+                                EmpathyChatView     *view,
+                                EmpathyMessage      *msg)
+{
+       EmpathyThemeBoxesPriv *priv;
+       EmpathyContact        *contact;
+       GdkPixbuf            *avatar = NULL;
+       GtkTextBuffer        *buffer;
+       const gchar          *name;
+       gboolean              header;
+       GtkTextIter           iter;
+       GtkWidget            *label1, *label2;
+       GtkTextChildAnchor   *anchor;
+       GtkWidget            *box;
+       gchar                *str;
+       time_t                time;
+       gchar                *tmp;
+       GtkTextIter           start;
+       GdkColor              color;
+       gboolean              parse_success;
+       gboolean              from_self;
+
+       priv = GET_PRIV (theme);
+
+       contact = empathy_message_get_sender (msg);
+       from_self = empathy_contact_is_user (contact);
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       empathy_debug (DEBUG_DOMAIN, "Maybe add fancy header");
+
+       name = empathy_contact_get_name (contact);
+
+       header = FALSE;
+
+       /* Only insert a header if the previously inserted block is not the same
+        * as this one. This catches all the different cases:
+        */
+       if (empathy_chat_view_get_last_block_type (view) != BLOCK_TYPE_SELF &&
+           empathy_chat_view_get_last_block_type (view) != BLOCK_TYPE_OTHER) {
+               header = TRUE;
+       }
+       else if (from_self &&
+                empathy_chat_view_get_last_block_type (view) == BLOCK_TYPE_OTHER) {
+               header = TRUE;
+       }
+       else if (!from_self && 
+                empathy_chat_view_get_last_block_type (view) == BLOCK_TYPE_SELF) {
+               header = TRUE;
+       }
+       else if (!from_self &&
+                (!empathy_chat_view_get_last_contact (view) ||
+                 !empathy_contact_equal (contact, empathy_chat_view_get_last_contact (view)))) {
+               header = TRUE;
+       }
+
+       if (!header) {
+               return;
+       }
+
+       empathy_theme_append_spacing (theme, context, view);
+
+       gtk_text_buffer_get_end_iter (buffer, &iter);
+       gtk_text_buffer_insert_with_tags_by_name (buffer,
+                                                 &iter,
+                                                 "\n",
+                                                 -1,
+                                                 "fancy-header-line",
+                                                 NULL);
+
+       gtk_text_buffer_get_end_iter (buffer, &iter);
+       anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
+
+       box = gtk_hbox_new (FALSE, 0);
+
+
+       avatar = empathy_chat_view_get_avatar_pixbuf_with_cache (contact);
+       if (avatar && empathy_theme_get_show_avatars (theme)) {
+               GtkWidget *image;
+
+               image = gtk_image_new_from_pixbuf (avatar);
+
+               gtk_box_pack_start (GTK_BOX (box), image,
+                                   FALSE, TRUE, 2);
+
+       }
+
+       g_signal_connect_object (view, "size-allocate",
+                                G_CALLBACK (table_size_allocate_cb),
+                                box, 0);
+
+       str = g_strdup_printf ("<b>%s</b>", name);
+
+       label1 = g_object_new (GTK_TYPE_LABEL,
+                              "label", str,
+                              "use-markup", TRUE,
+                              "xalign", 0.0,
+                              NULL);
+
+       parse_success = gdk_color_parse (priv->header_foreground, &color);
+
+       if (parse_success) {
+               gtk_widget_modify_fg (label1, GTK_STATE_NORMAL, &color);
+       }
+
+       g_free (str);
+
+       time = empathy_message_get_timestamp (msg);
+
+       tmp = empathy_time_to_string_local (time, 
+                                          EMPATHY_TIME_FORMAT_DISPLAY_SHORT);
+       str = g_strdup_printf ("<i>%s</i>", tmp);
+       g_free (tmp);
+
+       label2 = g_object_new (GTK_TYPE_LABEL,
+                              "label", str,
+                              "use-markup", TRUE,
+                              "xalign", 1.0,
+                              NULL);
+       
+       if (parse_success) {
+               gtk_widget_modify_fg (label2, GTK_STATE_NORMAL, &color);
+       }
+
+       g_free (str);
+
+       gtk_misc_set_alignment (GTK_MISC (label1), 0.0, 0.5);
+       gtk_misc_set_alignment (GTK_MISC (label2), 1.0, 0.5);
+
+       gtk_box_pack_start (GTK_BOX (box), label1, TRUE, TRUE, 0);
+       gtk_box_pack_start (GTK_BOX (box), label2, TRUE, TRUE, 0);
+
+       gtk_text_view_add_child_at_anchor (GTK_TEXT_VIEW (view),
+                                          box,
+                                          anchor);
+
+       gtk_widget_show_all (box);
+
+       gtk_text_buffer_get_end_iter (buffer, &iter);
+       start = iter;
+       gtk_text_iter_backward_char (&start);
+       gtk_text_buffer_apply_tag_by_name (buffer,
+                                          "fancy-header",
+                                          &start, &iter);
+
+       gtk_text_buffer_insert_with_tags_by_name (buffer,
+                                                 &iter,
+                                                 "\n",
+                                                 -1,
+                                                 "fancy-header",
+                                                 NULL);
+
+       gtk_text_buffer_get_end_iter (buffer, &iter);
+       gtk_text_buffer_insert_with_tags_by_name (buffer,
+                                                 &iter,
+                                                 "\n",
+                                                 -1,
+                                                 "fancy-header-line",
+                                                 NULL);
+}
+
+static void
+theme_boxes_append_message (EmpathyTheme        *theme,
+                           EmpathyThemeContext *context,
+                           EmpathyChatView     *view,
+                           EmpathyMessage      *message)
+{
+       EmpathyContact *sender;
+
+       empathy_theme_maybe_append_date_and_time (theme, context, view, message);
+       theme_boxes_maybe_append_header (theme, context, view, message);
+
+       sender = empathy_message_get_sender (message);
+
+       if (empathy_message_get_type (message) == EMPATHY_MESSAGE_TYPE_ACTION) {
+               gchar *body;
+
+               body = g_strdup_printf (" * %s %s", 
+                                       empathy_contact_get_name (sender),
+                                       empathy_message_get_body (message));
+               empathy_theme_append_text (theme, context, view, body,
+                                          "fancy-action", "fancy-link");
+       } else {
+               empathy_theme_append_text (theme, context, view,
+                                          empathy_message_get_body (message),
+                                          "fancy-body", "fancy-link");
+       }
+       
+       if (empathy_contact_is_user (sender)) {
+               empathy_chat_view_set_last_block_type (view, BLOCK_TYPE_SELF);
+               empathy_chat_view_set_last_contact (view, NULL);
+       } else {
+               empathy_chat_view_set_last_block_type (view, BLOCK_TYPE_OTHER);
+               empathy_chat_view_set_last_contact (view, sender);
+       }
+}
+
+static void
+theme_boxes_append_event (EmpathyTheme        *theme,
+                         EmpathyThemeContext *context,
+                         EmpathyChatView     *view,
+                         const gchar        *str)
+{
+       GtkTextBuffer *buffer;
+       GtkTextIter    iter;
+       gchar         *msg;
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       empathy_theme_maybe_append_date_and_time (theme, context, view, NULL);
+
+       gtk_text_buffer_get_end_iter (buffer, &iter);
+
+       msg = g_strdup_printf (" - %s\n", str);
+
+       gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
+                                                 msg, -1,
+                                                 "fancy-event",
+                                                 NULL);
+       g_free (msg);
+
+       empathy_chat_view_set_last_block_type (view, BLOCK_TYPE_EVENT);
+}
+
+static void
+theme_boxes_append_timestamp (EmpathyTheme        *theme,
+                             EmpathyThemeContext *context,
+                             EmpathyChatView     *view,
+                             EmpathyMessage      *message,
+                             gboolean            show_date,
+                             gboolean            show_time)
+{
+       GtkTextBuffer *buffer;
+       time_t         timestamp;
+       GDate         *date;
+       GtkTextIter    iter;
+       GString       *str;
+       
+       if (!show_date) {
+               return;
+       }
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       date = empathy_message_get_date_and_time (message, &timestamp);
+
+       str = g_string_new (NULL);
+
+       if (show_time || show_date) {
+               empathy_theme_append_spacing (theme, 
+                                            context,
+                                            view);
+
+               g_string_append (str, "- ");
+       }
+
+       if (show_date) {
+               gchar buf[256];
+
+               g_date_strftime (buf, 256, _("%A %d %B %Y"), date);
+               g_string_append (str, buf);
+
+               if (show_time) {
+                       g_string_append (str, ", ");
+               }
+       }
+
+       g_date_free (date);
+
+       if (show_time) {
+               gchar *tmp;
+
+               tmp = empathy_time_to_string_local (timestamp, EMPATHY_TIME_FORMAT_DISPLAY_SHORT);
+               g_string_append (str, tmp);
+               g_free (tmp);
+       }
+
+       if (show_time || show_date) {
+               g_string_append (str, " -\n");
+
+               gtk_text_buffer_get_end_iter (buffer, &iter);
+               gtk_text_buffer_insert_with_tags_by_name (buffer,
+                                                         &iter,
+                                                         str->str, -1,
+                                                         "fancy-time",
+                                                         NULL);
+
+               empathy_chat_view_set_last_block_type (view, BLOCK_TYPE_TIME);
+               empathy_chat_view_set_last_timestamp (view, timestamp);
+       }
+
+       g_string_free (str, TRUE);
+       
+}
+
+static void
+theme_boxes_append_spacing (EmpathyTheme        *theme,
+                           EmpathyThemeContext *context,
+                           EmpathyChatView     *view)
+{
+       GtkTextBuffer *buffer;
+       GtkTextIter    iter;
+
+       g_return_if_fail (EMPATHY_IS_THEME (theme));
+       g_return_if_fail (EMPATHY_IS_CHAT_VIEW (view));
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       gtk_text_buffer_get_end_iter (buffer, &iter);
+       gtk_text_buffer_insert_with_tags_by_name (buffer,
+                                                 &iter,
+                                                 "\n",
+                                                 -1,
+                                                 "cut",
+                                                 "fancy-spacing",
+                                                 NULL);
+}
+
+static void
+theme_boxes_setup_clean (EmpathyTheme *theme)
+{
+       g_object_set (theme,
+                     "header-foreground", "black",
+                     "header-background", "#efefdf",
+                     "header_line_background", "#e3e3d3",
+                     "action_foreground", "brown4",
+                     "time_foreground", "darkgrey",
+                     "event_foreground", "darkgrey",
+                     "invite_foreground", "sienna",
+                     "link_foreground","#49789e",
+                     NULL);
+}
+
+static void
+theme_boxes_gdk_color_to_hex (GdkColor *gdk_color, gchar *str_color)
+{
+       g_snprintf (str_color, 10, 
+                   "#%02x%02x%02x", 
+                   gdk_color->red >> 8, 
+                   gdk_color->green >> 8, 
+                   gdk_color->blue >> 8);
+}
+
+static void
+theme_boxes_setup_themed (EmpathyTheme *theme)
+{
+       EmpathyThemeBoxesPriv *priv;
+       GtkWidget            *widget;
+       GtkStyle             *style;
+       gchar                 color[10];
+
+       priv = GET_PRIV (theme);
+
+       widget = gtk_entry_new ();
+       style = gtk_widget_get_style (widget);
+       gtk_widget_destroy (widget);
+
+       theme_boxes_gdk_color_to_hex (&style->base[GTK_STATE_SELECTED], color);
+
+       g_object_set (theme,
+                     "action-foreground", color,
+                     "link-foreground", color,
+                     NULL);
+
+       theme_boxes_gdk_color_to_hex (&style->bg[GTK_STATE_SELECTED], color);
+
+       g_object_set (theme,
+                     "header-background", color,
+                     NULL);
+
+       theme_boxes_gdk_color_to_hex (&style->dark[GTK_STATE_SELECTED], color);
+
+       g_object_set (theme,
+                     "header_line-background", color,
+                     NULL);
+
+       theme_boxes_gdk_color_to_hex (&style->fg[GTK_STATE_SELECTED], color);
+
+       g_object_set (theme,
+                     "header-foreground", color,
+                     NULL);
+}
+
+static void
+theme_boxes_theme_changed_cb (GtkWidget *widget,
+                             GtkStyle  *previous_style,
+                             gpointer   user_data)
+{
+       theme_boxes_setup_themed (EMPATHY_THEME (user_data));
+
+       g_signal_emit_by_name (G_OBJECT (user_data), "updated");
+}
+
+static void
+theme_boxes_setup_blue (EmpathyTheme *theme)
+{
+       g_object_set (theme,
+                     "header_foreground", "black",
+                     "header_background", "#88a2b4",
+                     "header_line_background", "#7f96a4",
+                     "text_foreground", "black",
+                     "text_background", "#adbdc8",
+                     "highlight_foreground", "black",
+                     "action_foreground", "brown4",
+                     "time_foreground", "darkgrey",
+                     "event_foreground", "#7f96a4",
+                     "invite_foreground", "sienna",
+                     "link_foreground", "#49789e",
+                     NULL);
+}
+
+EmpathyTheme *
+empathy_theme_boxes_new (const gchar *name)
+{
+       EmpathyTheme          *theme;
+       EmpathyThemeBoxesPriv *priv;
+
+       theme = g_object_new (EMPATHY_TYPE_THEME_BOXES, NULL);
+       priv  = GET_PRIV (theme);
+
+       if (strcmp (name, "clean") == 0) {
+               theme_boxes_setup_clean (theme);
+       }
+       else if (strcmp (name, "simple") == 0) {
+               /* FIXME: Make an actual accessor function */
+               g_signal_connect (empathy_main_window_show (),
+                                 "style-set",
+                                 G_CALLBACK (theme_boxes_theme_changed_cb),
+                                 theme);
+
+               theme_boxes_setup_themed (theme);
+       }
+       else if (strcmp (name, "blue") == 0) {
+               theme_boxes_setup_blue (theme);
+       }
+
+       return theme;
+}
+
+
diff --git a/libempathy-gtk/empathy-theme-boxes.h b/libempathy-gtk/empathy-theme-boxes.h
new file mode 100644 (file)
index 0000000..a542836
--- /dev/null
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Imendio AB
+ *
+ * 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 __EMPATHY_THEME_BOXES_H__
+#define __EMPATHY_THEME_BOXES_H__
+
+#include <glib-object.h>
+
+#include "empathy-theme.h"
+
+G_BEGIN_DECLS
+
+#define EMPATHY_TYPE_THEME_BOXES            (empathy_theme_boxes_get_type ())
+#define EMPATHY_THEME_BOXES(o)              (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_THEME_BOXES, EmpathyThemeBoxes))
+#define EMPATHY_THEME_BOXES_CLASS(k)        (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_THEME_BOXES, EmpathyThemeBoxesClass))
+#define EMPATHY_IS_THEME_BOXES(o)           (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_THEME_BOXES))
+#define EMPATHY_IS_THEME_BOXES_CLASS(k)     (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_THEME_BOXES))
+#define EMPATHY_THEME_BOXES_GET_CLASS(o)    (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_THEME_BOXES, EmpathyThemeBoxesClass))
+
+typedef struct _EmpathyThemeBoxes      EmpathyThemeBoxes;
+typedef struct _EmpathyThemeBoxesClass EmpathyThemeBoxesClass;
+
+struct _EmpathyThemeBoxes {
+       EmpathyTheme parent;
+};
+
+struct _EmpathyThemeBoxesClass {
+       EmpathyThemeClass parent_class;
+};
+
+GType         empathy_theme_boxes_get_type      (void) G_GNUC_CONST;
+
+EmpathyTheme * empathy_theme_boxes_new           (const gchar *name);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_THEME_BOXES_H__ */
+
diff --git a/libempathy-gtk/empathy-theme-irc.c b/libempathy-gtk/empathy-theme-irc.c
new file mode 100644 (file)
index 0000000..afe71e5
--- /dev/null
@@ -0,0 +1,486 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Imendio AB
+ *
+ * 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 "config.h"
+
+#include <glib/gi18n.h>
+#include <libempathy/empathy-debug.h>
+
+#include "empathy-chat.h"
+#include "empathy-theme-utils.h"
+#include "empathy-theme-irc.h"
+
+#define DEBUG_DOMAIN "Theme"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_THEME_IRC, EmpathyThemeIrcPriv))
+
+typedef struct _EmpathyThemeIrcPriv EmpathyThemeIrcPriv;
+
+struct _EmpathyThemeIrcPriv {
+       gint my_prop;
+};
+
+static void         theme_irc_finalize      (GObject             *object);
+static void         theme_irc_get_property  (GObject             *object,
+                                            guint                param_id,
+                                            GValue              *value,
+                                            GParamSpec          *pspec);
+static void         theme_irc_set_property  (GObject             *object,
+                                            guint                param_id,
+                                            const GValue        *value,
+                                            GParamSpec          *pspec);
+static EmpathyThemeContext *
+theme_irc_setup_with_view                      (EmpathyTheme         *theme,
+                                               EmpathyChatView      *view);
+static void         theme_irc_detach_from_view (EmpathyTheme        *theme,
+                                               EmpathyThemeContext *context,
+                                               EmpathyChatView     *view);
+static void         theme_irc_append_message   (EmpathyTheme        *theme,
+                                               EmpathyThemeContext *context,
+                                               EmpathyChatView     *view,
+                                               EmpathyMessage      *message);
+static void         theme_irc_append_event     (EmpathyTheme        *theme,
+                                               EmpathyThemeContext *context,
+                                               EmpathyChatView     *view,
+                                               const gchar        *str);
+static void         theme_irc_append_timestamp (EmpathyTheme        *theme,
+                                               EmpathyThemeContext *context,
+                                               EmpathyChatView     *view,
+                                               EmpathyMessage      *message,
+                                               gboolean            show_date,
+                                               gboolean            show_time);
+static void         theme_irc_append_spacing   (EmpathyTheme        *theme,
+                                               EmpathyThemeContext *context,
+                                               EmpathyChatView     *view);
+
+
+enum {
+       PROP_0,
+       PROP_MY_PROP
+};
+
+G_DEFINE_TYPE (EmpathyThemeIrc, empathy_theme_irc, EMPATHY_TYPE_THEME);
+
+static void
+empathy_theme_irc_class_init (EmpathyThemeIrcClass *class)
+{
+       GObjectClass *object_class;
+       EmpathyThemeClass *theme_class;
+
+       object_class = G_OBJECT_CLASS (class);
+       theme_class  = EMPATHY_THEME_CLASS (class);
+
+       object_class->finalize     = theme_irc_finalize;
+       object_class->get_property = theme_irc_get_property;
+       object_class->set_property = theme_irc_set_property;
+
+       theme_class->setup_with_view  = theme_irc_setup_with_view;
+       theme_class->detach_from_view = theme_irc_detach_from_view;
+       theme_class->append_message   = theme_irc_append_message;
+       theme_class->append_event     = theme_irc_append_event;
+       theme_class->append_timestamp = theme_irc_append_timestamp;
+       theme_class->append_spacing   = theme_irc_append_spacing;
+
+       g_object_class_install_property (object_class,
+                                        PROP_MY_PROP,
+                                        g_param_spec_int ("my-prop",
+                                                          "",
+                                                          "",
+                                                          0, 1,
+                                                          1,
+                                                          G_PARAM_READWRITE));
+
+       g_type_class_add_private (object_class, sizeof (EmpathyThemeIrcPriv));
+}
+
+static void
+empathy_theme_irc_init (EmpathyThemeIrc *presence)
+{
+       EmpathyThemeIrcPriv *priv;
+
+       priv = GET_PRIV (presence);
+}
+
+static void
+theme_irc_finalize (GObject *object)
+{
+       EmpathyThemeIrcPriv *priv;
+
+       priv = GET_PRIV (object);
+
+       (G_OBJECT_CLASS (empathy_theme_irc_parent_class)->finalize) (object);
+}
+
+static void
+theme_irc_get_property (GObject    *object,
+                   guint       param_id,
+                   GValue     *value,
+                   GParamSpec *pspec)
+{
+       EmpathyThemeIrcPriv *priv;
+
+       priv = GET_PRIV (object);
+
+       switch (param_id) {
+       case PROP_MY_PROP:
+               g_value_set_int (value, priv->my_prop);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+               break;
+       }
+}
+static void
+theme_irc_set_property (GObject      *object,
+                   guint         param_id,
+                   const GValue *value,
+                   GParamSpec   *pspec)
+{
+       EmpathyThemeIrcPriv *priv;
+
+       priv = GET_PRIV (object);
+
+       switch (param_id) {
+       case PROP_MY_PROP:
+               priv->my_prop = g_value_get_int (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+               break;
+       }
+}
+
+static void
+theme_irc_fixup_tag_table (EmpathyTheme *theme, EmpathyChatView *view)
+{
+       GtkTextBuffer *buffer;
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       /* IRC style tags. */
+       empathy_theme_utils_ensure_tag_by_name (buffer, "irc-nick-self");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "irc-body-self");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "irc-action-self");
+
+       empathy_theme_utils_ensure_tag_by_name (buffer, "irc-nick-other");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "irc-body-other");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "irc-action-other");
+
+       empathy_theme_utils_ensure_tag_by_name (buffer, "irc-nick-highlight");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "irc-spacing");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "irc-time");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "irc-event");
+       empathy_theme_utils_ensure_tag_by_name (buffer, "irc-link");
+}
+
+static void
+theme_irc_apply_theme_classic (EmpathyTheme *theme, EmpathyChatView *view)
+{
+       EmpathyThemeIrcPriv *priv;
+       GtkTextBuffer      *buffer;
+       GtkTextTagTable    *table;
+       GtkTextTag         *tag;
+
+       priv = GET_PRIV (theme);
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+       table = gtk_text_buffer_get_tag_table (buffer);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "irc-spacing");
+       g_object_set (tag,
+                     "size", 2000,
+                     NULL);
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "irc-nick-self");
+       g_object_set (tag,
+                     "foreground", "sea green",
+                     NULL);
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "irc-body-self");
+       g_object_set (tag,
+                     /* To get the default theme color: */
+                     "foreground-set", FALSE,
+                     NULL);
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "irc-action-self");
+       g_object_set (tag,
+                     "foreground", "brown4",
+                     "style", PANGO_STYLE_ITALIC,
+                     NULL);
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "irc-nick-highlight");
+       g_object_set (tag,
+                     "foreground", "indian red",
+                     "weight", PANGO_WEIGHT_BOLD,
+                     NULL);
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "irc-nick-other");
+       g_object_set (tag,
+                     "foreground", "skyblue4",
+                     NULL);
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "irc-body-other");
+       g_object_set (tag,
+                     /* To get the default theme color: */
+                     "foreground-set", FALSE,
+                     NULL);
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "irc-action-other");
+       g_object_set (tag,
+                     "foreground", "brown4",
+                     "style", PANGO_STYLE_ITALIC,
+                     NULL);
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "irc-time");
+       g_object_set (tag,
+                     "foreground", "darkgrey",
+                     "justification", GTK_JUSTIFY_CENTER,
+                     NULL);
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "irc-event");
+       g_object_set (tag,
+                     "foreground", "PeachPuff4",
+                     "justification", GTK_JUSTIFY_LEFT,
+                     NULL);
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "invite");
+       g_object_set (tag,
+                     "foreground", "sienna",
+                     NULL);
+       empathy_theme_utils_add_tag (table, tag);
+
+       tag = empathy_theme_utils_init_tag_by_name (table, "irc-link");
+       g_object_set (tag,
+                     "foreground", "steelblue",
+                     "underline", PANGO_UNDERLINE_SINGLE,
+                     NULL);
+       empathy_theme_utils_add_tag (table, tag);
+}
+
+
+static EmpathyThemeContext *
+theme_irc_setup_with_view (EmpathyTheme *theme, EmpathyChatView *view)
+{
+       theme_irc_fixup_tag_table (theme, view);
+       theme_irc_apply_theme_classic (theme, view);
+       empathy_chat_view_set_margin (view, 3);
+
+       return NULL;
+}
+
+static void
+theme_irc_detach_from_view (EmpathyTheme        *theme,
+                           EmpathyThemeContext *context,
+                           EmpathyChatView     *view)
+{
+       /* Free the context */
+}
+
+static void
+theme_irc_append_message (EmpathyTheme        *theme,
+                         EmpathyThemeContext *context,
+                         EmpathyChatView     *view,
+                         EmpathyMessage      *message)
+{
+       GtkTextBuffer *buffer;
+       const gchar   *name;
+       const gchar   *nick_tag;
+       const gchar   *body_tag;
+       GtkTextIter    iter;
+       gchar         *tmp;
+       EmpathyContact *contact;
+
+       empathy_theme_maybe_append_date_and_time (theme, context, view, message);
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       contact = empathy_message_get_sender (message);
+       name = empathy_contact_get_name (contact);
+
+       if (empathy_message_get_type (message) == EMPATHY_MESSAGE_TYPE_ACTION) {
+               if (empathy_contact_is_user (contact)) {
+                       body_tag = "irc-action-self";
+               } else {
+                       body_tag = "irc-action-other";
+               }
+
+               tmp = g_strdup_printf (" * %s %s", 
+                                      empathy_contact_get_name (contact),
+                                      empathy_message_get_body (message));
+               empathy_theme_append_text (theme, context, view, tmp,
+                                          body_tag, "irc-link");
+               g_free (tmp);
+               return;
+       }
+
+       if (empathy_contact_is_user (contact)) {
+               nick_tag = "irc-nick-self";
+               body_tag = "irc-body-self";
+       } else {
+               if (empathy_chat_should_highlight_nick (message)) {
+                       nick_tag = "irc-nick-highlight";
+               } else {
+                       nick_tag = "irc-nick-other";
+               }
+
+               body_tag = "irc-body-other";
+       }
+               
+       gtk_text_buffer_get_end_iter (buffer, &iter);
+
+       /* The nickname. */
+       tmp = g_strdup_printf ("%s: ", name);
+       gtk_text_buffer_insert_with_tags_by_name (buffer,
+                                                 &iter,
+                                                 tmp,
+                                                 -1,
+                                                 "cut",
+                                                 nick_tag,
+                                                 NULL);
+       g_free (tmp);
+
+       /* The text body. */
+       empathy_theme_append_text (theme, context, view, 
+                                 empathy_message_get_body (message),
+                                 body_tag, "irc-link");
+}
+
+static void
+theme_irc_append_event (EmpathyTheme        *theme,
+                       EmpathyThemeContext *context,
+                   EmpathyChatView     *view,
+                   const gchar        *str)
+{
+       GtkTextBuffer *buffer;
+       GtkTextIter    iter;
+       gchar         *msg;
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+       
+       empathy_theme_maybe_append_date_and_time (theme, context, view, NULL);
+
+       gtk_text_buffer_get_end_iter (buffer, &iter);
+
+       msg = g_strdup_printf (" - %s\n", str);
+       gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
+                                                 msg, -1,
+                                                 "irc-event",
+                                                 NULL);
+       g_free (msg);
+}
+
+static void
+theme_irc_append_timestamp (EmpathyTheme        *theme,
+                           EmpathyThemeContext *context,
+                           EmpathyChatView     *view,
+                           EmpathyMessage      *message,
+                           gboolean            show_date,
+                           gboolean            show_time)
+{
+       GtkTextBuffer *buffer;
+       time_t         timestamp;
+       GDate         *date;
+       GtkTextIter    iter;
+       GString       *str;
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       date = empathy_message_get_date_and_time (message, &timestamp);
+
+       str = g_string_new (NULL);
+
+       if (show_time || show_date) {
+               empathy_theme_append_spacing (theme, 
+                                            context,
+                                            view);
+
+               g_string_append (str, "- ");
+       }
+
+       if (show_date) {
+               gchar buf[256];
+
+               g_date_strftime (buf, 256, _("%A %d %B %Y"), date);
+               g_string_append (str, buf);
+
+               if (show_time) {
+                       g_string_append (str, ", ");
+               }
+       }
+
+       g_date_free (date);
+
+       if (show_time) {
+               gchar *tmp;
+
+               tmp = empathy_time_to_string_local (timestamp, EMPATHY_TIME_FORMAT_DISPLAY_SHORT);
+               g_string_append (str, tmp);
+               g_free (tmp);
+       }
+
+       if (show_time || show_date) {
+               g_string_append (str, " -\n");
+
+               gtk_text_buffer_get_end_iter (buffer, &iter);
+               gtk_text_buffer_insert_with_tags_by_name (buffer,
+                                                         &iter,
+                                                         str->str, -1,
+                                                         "irc-time",
+                                                         NULL);
+
+               empathy_chat_view_set_last_timestamp (view, timestamp);
+       }
+
+       g_string_free (str, TRUE);
+}
+
+static void
+theme_irc_append_spacing (EmpathyTheme        *theme,
+                         EmpathyThemeContext *context,
+                         EmpathyChatView     *view)
+{
+       GtkTextBuffer *buffer;
+       GtkTextIter    iter;
+
+       g_return_if_fail (EMPATHY_IS_THEME (theme));
+       g_return_if_fail (EMPATHY_IS_CHAT_VIEW (view));
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       gtk_text_buffer_get_end_iter (buffer, &iter);
+       gtk_text_buffer_insert_with_tags_by_name (buffer,
+                                                 &iter,
+                                                 "\n",
+                                                 -1,
+                                                 "cut",
+                                                 "irc-spacing",
+                                                 NULL);
+}
+
diff --git a/libempathy-gtk/empathy-theme-irc.h b/libempathy-gtk/empathy-theme-irc.h
new file mode 100644 (file)
index 0000000..dc52a56
--- /dev/null
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Imendio AB
+ *
+ * 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 __EMPATHY_THEME_IRC_H__
+#define __EMPATHY_THEME_IRC_H__
+
+#include <glib-object.h>
+
+#include "empathy-theme.h"
+
+G_BEGIN_DECLS
+
+#define EMPATHY_TYPE_THEME_IRC            (empathy_theme_irc_get_type ())
+#define EMPATHY_THEME_IRC(o)              (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_THEME_IRC, EmpathyThemeIrc))
+#define EMPATHY_THEME_IRC_CLASS(k)        (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_THEME_IRC, EmpathyThemeIrcClass))
+#define EMPATHY_IS_THEME_IRC(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_THEME_IRC))
+#define EMPATHY_IS_THEME_IRC_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_THEME_IRC))
+#define EMPATHY_THEME_IRC_GET_CLASS(o)    (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_THEME_IRC, EmpathyThemeIrcClass))
+
+typedef struct _EmpathyThemeIrc      EmpathyThemeIrc;
+typedef struct _EmpathyThemeIrcClass EmpathyThemeIrcClass;
+
+struct _EmpathyThemeIrc {
+       EmpathyTheme parent;
+};
+
+struct _EmpathyThemeIrcClass {
+       EmpathyThemeClass parent_class;
+};
+
+GType               empathy_theme_irc_get_type                 (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __EMPATHY_THEME_IRC_H__ */
+
index 268760a549031a15b751f35ae42d6828eb124385..6feea2fc44defd8b00efe4379e509fb207bead8e 100644 (file)
@@ -16,8 +16,6 @@
  * License along with this program; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
- * 
- * Authors: Richard Hult <richard@imendio.com>
  */
 
 #include "config.h"
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
-#include <libempathy/empathy-conf.h>
 #include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-conf.h>
 
 #include "empathy-chat-view.h"
 #include "empathy-preferences.h"
+#include "empathy-theme.h"
+#include "empathy-theme-boxes.h"
+#include "empathy-theme-irc.h"
 #include "empathy-theme-manager.h"
 
 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_THEME_MANAGER, EmpathyThemeManagerPriv))
 
 typedef struct {
-       gchar    *name;
-       guint     name_notify_id;
-       guint     room_notify_id;
+       gchar       *name;
+       guint        name_notify_id;
+       guint        room_notify_id;
+
+       gboolean     show_avatars;
+       guint        show_avatars_notify_id;
 
-       gboolean  show_avatars;
-       guint     show_avatars_notify_id;
+       EmpathyTheme *clean_theme;
+       EmpathyTheme *simple_theme;
+       EmpathyTheme *blue_theme;
+       EmpathyTheme *classic_theme;
 
-       gboolean  irc_style;
+       gboolean     irc_style;
 } EmpathyThemeManagerPriv;
 
 static void        theme_manager_finalize                 (GObject            *object);
@@ -57,21 +63,6 @@ static void        theme_manager_notify_room_cb           (EmpathyConf         *
 static void        theme_manager_notify_show_avatars_cb   (EmpathyConf         *conf,
                                                           const gchar        *key,
                                                           gpointer            user_data);
-static void        theme_manager_ensure_tag_by_name       (GtkTextBuffer      *buffer,
-                                                          const gchar        *name);
-static gboolean    theme_manager_ensure_theme_exists      (const gchar        *name);
-static GtkTextTag *theme_manager_init_tag_by_name         (GtkTextTagTable    *table,
-                                                          const gchar        *name);
-static void        theme_manager_add_tag                  (GtkTextTagTable    *table,
-                                                          GtkTextTag         *tag);
-static void        theme_manager_fixup_tag_table          (EmpathyThemeManager *theme_manager,
-                                                          EmpathyChatView     *view);
-static void        theme_manager_apply_theme_classic      (EmpathyThemeManager *manager,
-                                                          EmpathyChatView     *view);
-static void        theme_manager_apply_theme_clean        (EmpathyThemeManager *manager,
-                                                          EmpathyChatView     *view);
-static void        theme_manager_apply_theme_blue         (EmpathyThemeManager *manager,
-                                                          EmpathyChatView     *view);
 static void        theme_manager_apply_theme              (EmpathyThemeManager *manager,
                                                           EmpathyChatView     *view,
                                                           const gchar        *name);
@@ -146,6 +137,11 @@ empathy_theme_manager_init (EmpathyThemeManager *manager)
        empathy_conf_get_bool (empathy_conf_get (),
                              EMPATHY_PREFS_UI_SHOW_AVATARS,
                              &priv->show_avatars);
+
+       priv->clean_theme   = empathy_theme_boxes_new ("clean");
+       priv->simple_theme  = empathy_theme_boxes_new ("simple");
+       priv->blue_theme    = empathy_theme_boxes_new ("blue");
+       priv->classic_theme = g_object_new (EMPATHY_TYPE_THEME_IRC, NULL);
 }
 
 static void
@@ -161,6 +157,11 @@ theme_manager_finalize (GObject *object)
 
        g_free (priv->name);
 
+       g_object_unref (priv->clean_theme);
+       g_object_unref (priv->simple_theme);
+       g_object_unref (priv->blue_theme);
+       g_object_unref (priv->classic_theme);
+
        G_OBJECT_CLASS (empathy_theme_manager_parent_class)->finalize (object);
 }
 
@@ -217,23 +218,6 @@ theme_manager_notify_show_avatars_cb (EmpathyConf  *conf,
        }
 }
 
-static void
-theme_manager_ensure_tag_by_name (GtkTextBuffer *buffer,
-                                 const gchar   *name)
-{
-       GtkTextTagTable *table;
-       GtkTextTag      *tag;
-
-       table = gtk_text_buffer_get_tag_table (buffer);
-       tag = gtk_text_tag_table_lookup (table, name);
-
-       if (!tag) {
-               gtk_text_buffer_create_tag (buffer,
-                                           name,
-                                           NULL);
-       }
-}
-
 static gboolean
 theme_manager_ensure_theme_exists (const gchar *name)
 {
@@ -252,690 +236,36 @@ theme_manager_ensure_theme_exists (const gchar *name)
        return FALSE;
 }
 
-static GtkTextTag *
-theme_manager_init_tag_by_name (GtkTextTagTable *table,
-                               const gchar     *name)
-{
-       GtkTextTag *tag;
-
-       tag = gtk_text_tag_table_lookup (table, name);
-
-       if (!tag) {
-               return gtk_text_tag_new (name);
-       }
-
-       /* Clear the old values so that we don't affect the new theme. */
-       g_object_set (tag,
-                     "background-set", FALSE,
-                     "foreground-set", FALSE,
-                     "invisible-set", FALSE,
-                     "justification-set", FALSE,
-                     "paragraph-background-set", FALSE,
-                     "pixels-above-lines-set", FALSE,
-                     "pixels-below-lines-set", FALSE,
-                     "rise-set", FALSE,
-                     "scale-set", FALSE,
-                     "size-set", FALSE,
-                     "style-set", FALSE,
-                     "weight-set", FALSE,
-                     NULL);
-
-       return tag;
-}
-
-static void
-theme_manager_add_tag (GtkTextTagTable *table,
-                      GtkTextTag      *tag)
-{
-       gchar      *name;
-       GtkTextTag *check_tag;
-
-       g_object_get (tag, "name", &name, NULL);
-       check_tag = gtk_text_tag_table_lookup (table, name);
-       g_free (name);
-       if (check_tag) {
-               return;
-       }
-
-       gtk_text_tag_table_add (table, tag);
-
-       g_object_unref (tag);
-}
-
-static void
-theme_manager_fixup_tag_table (EmpathyThemeManager *theme_manager,
-                              EmpathyChatView     *view)
-{
-       GtkTextBuffer *buffer;
-
-       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
-
-       /* "Fancy" style tags. */
-       theme_manager_ensure_tag_by_name (buffer, "fancy-header-self");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-header-self-avatar");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-avatar-self");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-line-top-self");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-line-bottom-self");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-body-self");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-action-self");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-highlight-self");
-
-       theme_manager_ensure_tag_by_name (buffer, "fancy-header-other");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-header-other-avatar");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-avatar-other");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-line-top-other");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-line-bottom-other");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-body-other");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-action-other");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-highlight-other");
-
-       theme_manager_ensure_tag_by_name (buffer, "fancy-spacing");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-time");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-event");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-invite");
-       theme_manager_ensure_tag_by_name (buffer, "fancy-link");
-
-       /* IRC style tags. */
-       theme_manager_ensure_tag_by_name (buffer, "irc-nick-self");
-       theme_manager_ensure_tag_by_name (buffer, "irc-body-self");
-       theme_manager_ensure_tag_by_name (buffer, "irc-action-self");
-
-       theme_manager_ensure_tag_by_name (buffer, "irc-nick-other");
-       theme_manager_ensure_tag_by_name (buffer, "irc-body-other");
-       theme_manager_ensure_tag_by_name (buffer, "irc-action-other");
-
-       theme_manager_ensure_tag_by_name (buffer, "irc-nick-highlight");
-       theme_manager_ensure_tag_by_name (buffer, "irc-spacing");
-       theme_manager_ensure_tag_by_name (buffer, "irc-time");
-       theme_manager_ensure_tag_by_name (buffer, "irc-event");
-       theme_manager_ensure_tag_by_name (buffer, "irc-invite");
-       theme_manager_ensure_tag_by_name (buffer, "irc-link");
-}
-
-static void
-theme_manager_apply_theme_classic (EmpathyThemeManager *manager,
-                                  EmpathyChatView     *view)
-{
-       EmpathyThemeManagerPriv *priv;
-       GtkTextBuffer          *buffer;
-       GtkTextTagTable        *table;
-       GtkTextTag             *tag;
-
-       priv = GET_PRIV (manager);
-
-       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
-       table = gtk_text_buffer_get_tag_table (buffer);
-
-       priv->irc_style = TRUE;
-
-       tag = theme_manager_init_tag_by_name (table, "irc-spacing");
-       g_object_set (tag,
-                     "size", 2000,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "irc-nick-self");
-       g_object_set (tag,
-                     "foreground", "sea green",
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "irc-body-self");
-       g_object_set (tag,
-                     /* To get the default theme color: */
-                     "foreground-set", FALSE,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "irc-action-self");
-       g_object_set (tag,
-                     "foreground", "brown4",
-                     "style", PANGO_STYLE_ITALIC,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "irc-nick-highlight");
-       g_object_set (tag,
-                     "foreground", "indian red",
-                     "weight", PANGO_WEIGHT_BOLD,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "irc-nick-other");
-       g_object_set (tag,
-                     "foreground", "skyblue4",
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "irc-body-other");
-       g_object_set (tag,
-                     /* To get the default theme color: */
-                     "foreground-set", FALSE,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "irc-action-other");
-       g_object_set (tag,
-                     "foreground", "brown4",
-                     "style", PANGO_STYLE_ITALIC,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "irc-time");
-       g_object_set (tag,
-                     "foreground", "darkgrey",
-                     "justification", GTK_JUSTIFY_CENTER,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "irc-event");
-       g_object_set (tag,
-                     "foreground", "PeachPuff4",
-                     "justification", GTK_JUSTIFY_LEFT,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "irc-invite");
-       g_object_set (tag,
-                     "foreground", "sienna",
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "irc-link");
-       g_object_set (tag,
-                     "foreground", "steelblue",
-                     "underline", PANGO_UNDERLINE_SINGLE,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-}
-
-static void
-theme_manager_apply_theme_simple (EmpathyThemeManager *manager,
-                                 EmpathyChatView     *view)
-{
-       EmpathyThemeManagerPriv *priv;
-       GtkTextBuffer          *buffer;
-       GtkTextTagTable        *table;
-       GtkTextTag             *tag;
-       GtkWidget              *widget;
-       GtkStyle               *style;
-
-       priv = GET_PRIV (manager);
-
-       widget = gtk_entry_new ();
-       style = gtk_widget_get_style (widget);
-       gtk_widget_destroy (widget);
-
-       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
-       table = gtk_text_buffer_get_tag_table (buffer);
-
-       priv->irc_style = FALSE;
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-spacing");
-       g_object_set (tag,
-                     "size", 3000,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-header-self");
-       g_object_set (tag,
-                     "weight", PANGO_WEIGHT_BOLD,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-header-self-avatar");
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-avatar-self");
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-line-top-self");
-       g_object_set (tag,
-                     "size", 6 * PANGO_SCALE,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-line-bottom-self");
-       g_object_set (tag,
-                     "size", 1,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-body-self");
-       g_object_set (tag,
-                     "pixels-above-lines", 2,
-                     "pixels-below-lines", 2,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-action-self");
-       g_object_set (tag,
-                     "foreground-gdk", &style->base[GTK_STATE_SELECTED],
-                     "style", PANGO_STYLE_ITALIC,
-                     "pixels-above-lines", 2,
-                     "pixels-below-lines", 2,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-highlight-self");
-       g_object_set (tag,
-                     "weight", PANGO_WEIGHT_BOLD,
-                     "pixels-above-lines", 2,
-                     "pixels-below-lines", 2,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-header-other");
-       g_object_set (tag,
-                     "weight", PANGO_WEIGHT_BOLD,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-header-other-avatar");
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-avatar-other");
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-line-top-other");
-       g_object_set (tag,
-                     "size", 6 * PANGO_SCALE,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-line-bottom-other");
-       g_object_set (tag,
-                     "size", 1,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-body-other");
-       g_object_set (tag,
-                     "pixels-above-lines", 2,
-                     "pixels-below-lines", 2,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-action-other");
-       g_object_set (tag,
-                     "foreground-gdk", &style->base[GTK_STATE_SELECTED],
-                     "style", PANGO_STYLE_ITALIC,
-                     "pixels-above-lines", 2,
-                     "pixels-below-lines", 2,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-highlight-other");
-       g_object_set (tag,
-                     "weight", PANGO_WEIGHT_BOLD,
-                     "pixels-above-lines", 2,
-                     "pixels-below-lines", 2,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-time");
-       g_object_set (tag,
-                     "foreground", "darkgrey",
-                     "justification", GTK_JUSTIFY_CENTER,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-event");
-       g_object_set (tag,
-                     "foreground", "darkgrey",
-                     "justification", GTK_JUSTIFY_LEFT,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-invite");
-       g_object_set (tag,
-                     "foreground", "darkgrey",
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-link");
-       g_object_set (tag,
-                     "foreground-gdk", &style->base[GTK_STATE_SELECTED],
-                     "underline", PANGO_UNDERLINE_SINGLE,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-}
-
-static void
-theme_manager_apply_theme_clean (EmpathyThemeManager *manager,
-                                EmpathyChatView     *view)
-{
-       EmpathyThemeManagerPriv *priv;
-       GtkTextBuffer          *buffer;
-       GtkTextTagTable        *table;
-       GtkTextTag             *tag;
-
-       priv = GET_PRIV (manager);
-
-       /* Inherit the simple theme. */
-       theme_manager_apply_theme_simple (manager, view);
-
-#define ELEGANT_HEAD "#efefdf"
-#define ELEGANT_LINE "#e3e3d3"
-
-       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
-       table = gtk_text_buffer_get_tag_table (buffer);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-spacing");
-       g_object_set (tag,
-                     "size", PANGO_SCALE * 10,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-header-self");
-       g_object_set (tag,
-                     "foreground", "black",
-                     "weight", PANGO_WEIGHT_BOLD,
-                     "paragraph-background", ELEGANT_HEAD,
-                     "pixels-above-lines", 2,
-                     "pixels-below-lines", 2,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-avatar-self");
-       g_object_set (tag,
-                     "paragraph-background", ELEGANT_HEAD,
-                     "pixels-above-lines", 2,
-                     "pixels-below-lines", 2,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-line-top-self");
-       g_object_set (tag,
-                     "size", 1 * PANGO_SCALE,
-                     "paragraph-background", ELEGANT_LINE,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-line-bottom-self");
-       g_object_set (tag,
-                     "size", 1 * PANGO_SCALE,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-action-self");
-       g_object_set (tag,
-                     "foreground", "brown4",
-                     "style", PANGO_STYLE_ITALIC,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-highlight-self");
-       g_object_set (tag,
-                     "foreground", "black",
-                     "weight", PANGO_WEIGHT_BOLD,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-header-other");
-       g_object_set (tag,
-                     "foreground", "black",
-                     "weight", PANGO_WEIGHT_BOLD,
-                     "paragraph-background", ELEGANT_HEAD,
-                     "pixels-above-lines", 2,
-                     "pixels-below-lines", 2,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-avatar-other");
-       g_object_set (tag,
-                     "paragraph-background", ELEGANT_HEAD,
-                     "pixels-above-lines", 2,
-                     "pixels-below-lines", 2,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-line-top-other");
-       g_object_set (tag,
-                     "size", 1 * PANGO_SCALE,
-                     "paragraph-background", ELEGANT_LINE,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-line-bottom-other");
-       g_object_set (tag,
-                     "size", 1 * PANGO_SCALE,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-action-other");
-       g_object_set (tag,
-                     "foreground", "brown4",
-                     "style", PANGO_STYLE_ITALIC,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-time");
-       g_object_set (tag,
-                     "foreground", "darkgrey",
-                     "justification", GTK_JUSTIFY_CENTER,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-event");
-       g_object_set (tag,
-                     "foreground", "darkgrey",
-                     "justification", GTK_JUSTIFY_LEFT,
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-invite");
-       g_object_set (tag,
-                     "foreground", "sienna",
-                     NULL);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-link");
-       g_object_set (tag,
-                     "foreground", "#49789e",
-                     "underline", PANGO_UNDERLINE_SINGLE,
-                     NULL);
-}
-
-static void
-theme_manager_apply_theme_blue (EmpathyThemeManager *manager,
-                               EmpathyChatView     *view)
-{
-       EmpathyThemeManagerPriv *priv;
-       GtkTextBuffer          *buffer;
-       GtkTextTagTable        *table;
-       GtkTextTag             *tag;
-
-       priv = GET_PRIV (manager);
-
-       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
-       table = gtk_text_buffer_get_tag_table (buffer);
-
-       priv->irc_style = FALSE;
-
-#define BLUE_BODY_SELF "#dcdcdc"
-#define BLUE_HEAD_SELF "#b9b9b9"
-#define BLUE_LINE_SELF "#aeaeae"
-
-#define BLUE_BODY_OTHER "#adbdc8"
-#define BLUE_HEAD_OTHER "#88a2b4"
-#define BLUE_LINE_OTHER "#7f96a4"
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-spacing");
-       g_object_set (tag,
-                     "size", 3000,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-header-self");
-       g_object_set (tag,
-                     "foreground", "black",
-                     "paragraph-background", BLUE_HEAD_SELF,
-                     "weight", PANGO_WEIGHT_BOLD,
-                     "pixels-above-lines", 2,
-                     "pixels-below-lines", 2,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-header-self-avatar");
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-avatar-self");
-       g_object_set (tag,
-                     "paragraph-background", BLUE_HEAD_SELF,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-line-top-self");
-       g_object_set (tag,
-                     "size", 1,
-                     "paragraph-background", BLUE_LINE_SELF,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-line-bottom-self");
-       g_object_set (tag,
-                     "size", 1,
-                     "paragraph-background", BLUE_LINE_SELF,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-body-self");
-       g_object_set (tag,
-                     "foreground", "black",
-                     "paragraph-background", BLUE_BODY_SELF,
-                     "pixels-above-lines", 4,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-action-self");
-       g_object_set (tag,
-                     "foreground", "brown4",
-                     "style", PANGO_STYLE_ITALIC,
-                     "paragraph-background", BLUE_BODY_SELF,
-                     "pixels-above-lines", 4,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-highlight-self");
-       g_object_set (tag,
-                     "foreground", "black",
-                     "weight", PANGO_WEIGHT_BOLD,
-                     "paragraph-background", BLUE_BODY_SELF,
-                     "pixels-above-lines", 4,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-header-other");
-       g_object_set (tag,
-                     "foreground", "black",
-                     "paragraph-background", BLUE_HEAD_OTHER,
-                     "weight", PANGO_WEIGHT_BOLD,
-                     "pixels-above-lines", 2,
-                     "pixels-below-lines", 2,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-header-other-avatar");
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-avatar-other");
-       g_object_set (tag,
-                     "paragraph-background", BLUE_HEAD_OTHER,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-line-top-other");
-       g_object_set (tag,
-                     "size", 1,
-                     "paragraph-background", BLUE_LINE_OTHER,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-line-bottom-other");
-       g_object_set (tag,
-                     "size", 1,
-                     "paragraph-background", BLUE_LINE_OTHER,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-body-other");
-       g_object_set (tag,
-                     "foreground", "black",
-                     "paragraph-background", BLUE_BODY_OTHER,
-                     "pixels-above-lines", 4,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-action-other");
-       g_object_set (tag,
-                     "foreground", "brown4",
-                     "style", PANGO_STYLE_ITALIC,
-                     "paragraph-background", BLUE_BODY_OTHER,
-                     "pixels-above-lines", 4,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-highlight-other");
-       g_object_set (tag,
-                     "foreground", "black",
-                     "weight", PANGO_WEIGHT_BOLD,
-                     "paragraph-background", BLUE_BODY_OTHER,
-                     "pixels-above-lines", 4,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-time");
-       g_object_set (tag,
-                     "foreground", "darkgrey",
-                     "justification", GTK_JUSTIFY_CENTER,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-event");
-       g_object_set (tag,
-                     "foreground", BLUE_LINE_OTHER,
-                     "justification", GTK_JUSTIFY_LEFT,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-invite");
-       g_object_set (tag,
-                     "foreground", "sienna",
-                     NULL);
-       theme_manager_add_tag (table, tag);
-
-       tag = theme_manager_init_tag_by_name (table, "fancy-link");
-       g_object_set (tag,
-                     "foreground", "#49789e",
-                     "underline", PANGO_UNDERLINE_SINGLE,
-                     NULL);
-       theme_manager_add_tag (table, tag);
-}
-
 static void
 theme_manager_apply_theme (EmpathyThemeManager *manager,
                           EmpathyChatView     *view,
                           const gchar        *name)
 {
        EmpathyThemeManagerPriv *priv;
-       gint                    margin;
+       EmpathyTheme            *theme;
 
        priv = GET_PRIV (manager);
 
        /* Make sure all tags are present. Note: not useful now but when we have
         * user defined theme it will be.
         */
-       theme_manager_fixup_tag_table (manager, view);
-
        if (theme_manager_ensure_theme_exists (name)) {
                if (strcmp (name, "clean") == 0) {
-                       theme_manager_apply_theme_clean (manager, view);
-                       margin = 3;
+                       theme = priv->clean_theme;
                }
                else if (strcmp (name, "simple") == 0) {
-                       theme_manager_apply_theme_simple (manager, view);
-                       margin = 3;
+                       theme = priv->simple_theme;
                }
                else if (strcmp (name, "blue") == 0) {
-                       theme_manager_apply_theme_blue (manager, view);
-                       margin = 0;
+                       theme = priv->blue_theme;
                } else {
-                       theme_manager_apply_theme_classic (manager, view);
-                       margin = 3;
+                       theme = priv->classic_theme;
                }
        } else {
-               theme_manager_apply_theme_classic (manager, view);
-               margin = 3;
+               theme = priv->classic_theme;
        }
 
-       empathy_chat_view_set_margin (view, margin);
-       empathy_chat_view_set_irc_style (view, priv->irc_style);
+       empathy_chat_view_set_theme (view, theme);
 }
 
 EmpathyThemeManager *
@@ -979,67 +309,3 @@ empathy_theme_manager_apply_saved (EmpathyThemeManager *manager,
        theme_manager_apply_theme (manager, view, priv->name);
 }
 
-/* FIXME: A bit ugly. We should probably change the scheme so that instead of
- * the manager signalling, views are registered and applied to automatically.
- */
-void
-empathy_theme_manager_update_show_avatars (EmpathyThemeManager *manager,
-                                         EmpathyChatView     *view,
-                                         gboolean            show)
-{
-       EmpathyThemeManagerPriv *priv;
-       GtkTextBuffer          *buffer;
-       GtkTextTagTable        *table;
-       GtkTextTag             *tag_text_self, *tag_text_other;
-       GtkTextTag             *tag_image_self, *tag_image_other;
-
-       priv = GET_PRIV (manager);
-
-       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
-       table = gtk_text_buffer_get_tag_table (buffer);
-
-       tag_text_self = gtk_text_tag_table_lookup (table, "fancy-header-self-avatar");
-       tag_text_other = gtk_text_tag_table_lookup (table, "fancy-header-other-avatar");
-
-       tag_image_self = gtk_text_tag_table_lookup (table, "fancy-avatar-self");
-       tag_image_other = gtk_text_tag_table_lookup (table, "fancy-avatar-other");
-
-       if (!show) {
-               g_object_set (tag_text_self,
-                             "rise", 0,
-                             NULL);
-               g_object_set (tag_text_other,
-                             "rise", 0,
-                             NULL);
-               g_object_set (tag_image_self,
-                             "invisible", TRUE,
-                             NULL);
-               g_object_set (tag_image_other,
-                             "invisible", TRUE,
-                             NULL);
-       } else {
-               GtkTextAttributes *attrs;
-               gint               size;
-               gint               rise;
-
-               attrs = gtk_text_view_get_default_attributes (GTK_TEXT_VIEW (view));
-               size = pango_font_description_get_size (attrs->font);
-               rise = MAX (0, (32 * PANGO_SCALE - size) / 2.0);
-
-               g_object_set (tag_text_self,
-                             "rise", rise,
-                             NULL);
-               g_object_set (tag_text_other,
-                             "rise", rise,
-                             NULL);
-               g_object_set (tag_image_self,
-                             "invisible", FALSE,
-                             NULL);
-               g_object_set (tag_image_other,
-                             "invisible", FALSE,
-                             NULL);
-
-               gtk_text_attributes_unref (attrs);
-       }
-}
-
index d20a916e1245aacccf56c42e330c0f8a22608778..6bd2d41f55be6728a23ee4a1c56be39153f391c9 100644 (file)
@@ -16,8 +16,6 @@
  * License along with this program; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
- * 
- * Authors: Richard Hult <richard@imendio.com>
  */
 
 #ifndef __EMPATHY_THEME_MANAGER_H__
@@ -25,8 +23,6 @@
 
 #include <glib-object.h>
 
-#include "empathy-chat-view.h"
-
 G_BEGIN_DECLS
 
 #define EMPATHY_TYPE_THEME_MANAGER         (empathy_theme_manager_get_type ())
@@ -55,9 +51,6 @@ void                empathy_theme_manager_apply               (EmpathyThemeManag
                                                              const gchar        *theme);
 void                empathy_theme_manager_apply_saved         (EmpathyThemeManager *manager,
                                                              EmpathyChatView     *view);
-void                empathy_theme_manager_update_show_avatars (EmpathyThemeManager *manager,
-                                                             EmpathyChatView     *view,
-                                                             gboolean            show);
 
 G_END_DECLS
 
diff --git a/libempathy-gtk/empathy-theme-utils.c b/libempathy-gtk/empathy-theme-utils.c
new file mode 100644 (file)
index 0000000..56b758e
--- /dev/null
@@ -0,0 +1,90 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Imendio AB
+ *
+ * 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 <config.h>
+
+#include <gtk/gtktexttag.h>
+
+#include "empathy-theme-utils.h"
+
+void
+empathy_theme_utils_ensure_tag_by_name (GtkTextBuffer *buffer, const gchar *name)
+{
+       GtkTextTagTable *table;
+       GtkTextTag      *tag;
+
+       table = gtk_text_buffer_get_tag_table (buffer);
+       tag = gtk_text_tag_table_lookup (table, name);
+
+       if (!tag) {
+               gtk_text_buffer_create_tag (buffer,
+                                           name,
+                                           NULL);
+       }
+}
+
+GtkTextTag *
+empathy_theme_utils_init_tag_by_name (GtkTextTagTable *table, const gchar *name)
+{
+       GtkTextTag *tag;
+
+       tag = gtk_text_tag_table_lookup (table, name);
+
+       if (!tag) {
+               return gtk_text_tag_new (name);
+       }
+
+       /* Clear the old values so that we don't affect the new theme. */
+       g_object_set (tag,
+                     "background-set", FALSE,
+                     "foreground-set", FALSE,
+                     "invisible-set", FALSE,
+                     "justification-set", FALSE,
+                     "paragraph-background-set", FALSE,
+                     "pixels-above-lines-set", FALSE,
+                     "pixels-below-lines-set", FALSE,
+                     "rise-set", FALSE,
+                     "scale-set", FALSE,
+                     "size-set", FALSE,
+                     "style-set", FALSE,
+                     "weight-set", FALSE,
+                     NULL);
+
+       return tag;
+}
+
+void
+empathy_theme_utils_add_tag (GtkTextTagTable *table, GtkTextTag *tag)
+{
+       gchar      *name;
+       GtkTextTag *check_tag;
+
+       g_object_get (tag, "name", &name, NULL);
+       check_tag = gtk_text_tag_table_lookup (table, name);
+       g_free (name);
+       if (check_tag) {
+               return;
+       }
+
+       gtk_text_tag_table_add (table, tag);
+
+       g_object_unref (tag);
+}
+
diff --git a/libempathy-gtk/empathy-theme-utils.h b/libempathy-gtk/empathy-theme-utils.h
new file mode 100644 (file)
index 0000000..af97077
--- /dev/null
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Imendio AB
+ *
+ * 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 __EMPATHY_THEME_UTILS_H__
+#define __EMPATHY_THEME_UTILS_H__
+
+#include <gtk/gtktextbuffer.h>
+#include <gtk/gtktexttag.h>
+
+G_BEGIN_DECLS
+
+void          empathy_theme_utils_ensure_tag_by_name  (GtkTextBuffer   *buffer,
+                                                      const gchar     *name);
+GtkTextTag *  empathy_theme_utils_init_tag_by_name    (GtkTextTagTable *table,
+                                                      const gchar     *name);
+void          empathy_theme_utils_add_tag             (GtkTextTagTable *table,
+                                                      GtkTextTag      *tag);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_THEME_UTILS_H__ */
+
+
diff --git a/libempathy-gtk/empathy-theme.c b/libempathy-gtk/empathy-theme.c
new file mode 100644 (file)
index 0000000..185ad92
--- /dev/null
@@ -0,0 +1,475 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Imendio AB
+ *
+ * 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 <config.h>
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <libempathy/empathy-conf.h>
+#include <libempathy/empathy-debug.h>
+#include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-marshal.h>
+
+#include "empathy-chat.h"
+#include "empathy-preferences.h"
+#include "empathy-theme-utils.h"
+#include "empathy-theme.h"
+#include "empathy-smiley-manager.h"
+
+#define DEBUG_DOMAIN "Theme"
+
+/* Number of seconds between timestamps when using normal mode, 5 minutes. */
+#define TIMESTAMP_INTERVAL 300
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_THEME, EmpathyThemePriv))
+
+typedef struct _EmpathyThemePriv EmpathyThemePriv;
+
+struct _EmpathyThemePriv {
+       EmpathySmileyManager *smiley_manager;
+       gboolean show_avatars;
+};
+
+static void         theme_finalize            (GObject            *object);
+static void         theme_get_property        (GObject            *object,
+                                              guint               param_id,
+                                              GValue             *value,
+                                              GParamSpec         *pspec);
+static void         theme_set_property        (GObject            *object,
+                                              guint               param_id,
+                                              const GValue       *value,
+                                              GParamSpec         *pspec);
+
+
+G_DEFINE_TYPE (EmpathyTheme, empathy_theme, G_TYPE_OBJECT);
+
+enum {
+       PROP_0,
+       PROP_SHOW_AVATARS
+};
+
+enum {
+       UPDATED,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+empathy_theme_class_init (EmpathyThemeClass *class)
+{
+       GObjectClass *object_class;
+
+       object_class = G_OBJECT_CLASS (class);
+
+       object_class->finalize     = theme_finalize;
+       object_class->get_property = theme_get_property;
+       object_class->set_property = theme_set_property;
+
+       class->setup_with_view  = NULL;
+       class->view_cleared     = NULL;
+       class->append_message   = NULL;
+       class->append_event     = NULL;
+       class->append_timestamp = NULL;
+       class->append_spacing   = NULL;
+
+       g_object_class_install_property (object_class,
+                                        PROP_SHOW_AVATARS,
+                                        g_param_spec_boolean ("show-avatars",
+                                                              "", "",
+                                                              TRUE,
+                                                              G_PARAM_READWRITE));
+
+       signals[UPDATED] =
+               g_signal_new ("updated",
+                             G_TYPE_FROM_CLASS (class),
+                             G_SIGNAL_RUN_LAST,
+                             0,
+                             NULL, NULL,
+                             empathy_marshal_VOID__VOID,
+                             G_TYPE_NONE, 
+                             0);
+
+       g_type_class_add_private (object_class, sizeof (EmpathyThemePriv));
+}
+
+static void
+empathy_theme_init (EmpathyTheme *presence)
+{
+       EmpathyThemePriv *priv;
+
+       priv = GET_PRIV (presence);
+
+       priv->smiley_manager = empathy_smiley_manager_new ();
+}
+
+static void
+theme_finalize (GObject *object)
+{
+       EmpathyThemePriv *priv;
+
+       priv = GET_PRIV (object);
+
+       if (priv->smiley_manager) {
+               g_object_unref (priv->smiley_manager);
+       }
+
+       (G_OBJECT_CLASS (empathy_theme_parent_class)->finalize) (object);
+}
+
+static void
+theme_get_property (GObject    *object,
+                   guint       param_id,
+                   GValue     *value,
+                   GParamSpec *pspec)
+{
+       EmpathyThemePriv *priv;
+
+       priv = GET_PRIV (object);
+
+       switch (param_id) {
+       case PROP_SHOW_AVATARS:
+               g_value_set_boolean (value, priv->show_avatars);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+               break;
+       }
+}
+
+static void
+theme_set_property (GObject      *object,
+                    guint         param_id,
+                    const GValue *value,
+                    GParamSpec   *pspec)
+{
+       EmpathyThemePriv *priv;
+
+       priv = GET_PRIV (object);
+
+       switch (param_id) {
+       case PROP_SHOW_AVATARS:
+               priv->show_avatars = g_value_get_boolean (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+               break;
+       }
+}
+
+void
+empathy_theme_maybe_append_date_and_time (EmpathyTheme        *theme,
+                                        EmpathyThemeContext *context,
+                                        EmpathyChatView     *view,
+                                        EmpathyMessage      *message)
+{
+       time_t    timestamp;
+       GDate    *date, *last_date;
+       gboolean  append_date, append_time;
+
+       date = empathy_message_get_date_and_time (message, &timestamp);
+
+       last_date = g_date_new ();
+       g_date_set_time (last_date, empathy_chat_view_get_last_timestamp (view));
+
+       append_date = FALSE;
+       append_time = FALSE;
+
+       if (g_date_compare (date, last_date) > 0) {
+               append_date = TRUE;
+               append_time = TRUE;
+       }
+       
+       g_date_free (last_date);
+       g_date_free (date);
+
+       if (empathy_chat_view_get_last_timestamp (view) + TIMESTAMP_INTERVAL < timestamp) {
+               append_time = TRUE;
+       }
+
+       if (append_time || append_date) {
+               empathy_theme_append_timestamp (theme, context,
+                                              view, message,
+                                              append_date, append_time);
+       }
+}
+
+EmpathyTheme *
+empathy_theme_new (void)
+{
+       EmpathyTheme     *theme;
+
+       theme = g_object_new (EMPATHY_TYPE_THEME, NULL);
+
+       return theme;
+}
+
+EmpathyThemeContext *
+empathy_theme_setup_with_view (EmpathyTheme    *theme,
+                             EmpathyChatView *view)
+{
+       if (!EMPATHY_THEME_GET_CLASS(theme)->setup_with_view) {
+               g_error ("Theme must override setup_with_view");
+       }
+
+       return EMPATHY_THEME_GET_CLASS(theme)->setup_with_view (theme, view);
+}
+
+void
+empathy_theme_detach_from_view (EmpathyTheme        *theme,
+                              EmpathyThemeContext *context,
+                              EmpathyChatView     *view)
+{
+       if (!EMPATHY_THEME_GET_CLASS(theme)->detach_from_view) {
+               g_error ("Theme must override detach_from_view");
+       }
+
+       return EMPATHY_THEME_GET_CLASS(theme)->detach_from_view (theme, context,
+                                                               view);
+}
+
+void
+empathy_theme_view_cleared (EmpathyTheme        *theme,
+                          EmpathyThemeContext *context,
+                          EmpathyChatView     *view)
+{
+       if (!EMPATHY_THEME_GET_CLASS(theme)->view_cleared) {
+               return;
+       }
+
+       EMPATHY_THEME_GET_CLASS(theme)->view_cleared (theme, context, view);
+}
+
+void
+empathy_theme_append_message (EmpathyTheme        *theme,
+                            EmpathyThemeContext *context,
+                            EmpathyChatView     *view,
+                            EmpathyMessage      *message)
+{
+       if (!EMPATHY_THEME_GET_CLASS(theme)->append_message) {
+               g_warning ("Theme should override append_message");
+               return;
+       }
+
+       EMPATHY_THEME_GET_CLASS(theme)->append_message (theme, context, view,
+                                                      message);
+}
+
+static void
+theme_insert_text_with_emoticons (GtkTextBuffer *buf,
+                                 GtkTextIter   *iter,
+                                 const gchar   *str,
+                                 EmpathySmileyManager *smiley_manager)
+{
+       gboolean             use_smileys = FALSE;
+       GSList              *smileys, *l;
+
+       empathy_conf_get_bool (empathy_conf_get (),
+                             EMPATHY_PREFS_CHAT_SHOW_SMILEYS,
+                             &use_smileys);
+
+       if (!use_smileys) {
+               gtk_text_buffer_insert (buf, iter, str, -1);
+               return;
+       }
+
+       smileys = empathy_smiley_manager_parse (smiley_manager, str);
+       for (l = smileys; l; l = l->next) {
+               EmpathySmiley *smiley;
+
+               smiley = l->data;
+               if (smiley->pixbuf) {
+                       gtk_text_buffer_insert_pixbuf (buf, iter, smiley->pixbuf);
+               } else {
+                       gtk_text_buffer_insert (buf, iter, smiley->str, -1);
+               }
+               empathy_smiley_free (smiley);
+       }
+       g_slist_free (smileys);
+}
+
+void
+empathy_theme_append_text (EmpathyTheme        *theme,
+                         EmpathyThemeContext *context,
+                         EmpathyChatView     *view,
+                         const gchar        *body,
+                         const gchar        *tag,
+                         const gchar        *link_tag)
+{
+       EmpathyThemePriv *priv;
+       GtkTextBuffer   *buffer;
+       GtkTextIter      start_iter, end_iter;
+       GtkTextMark     *mark;
+       GtkTextIter      iter;
+       gint             num_matches, i;
+       GArray          *start, *end;
+
+       priv = GET_PRIV (theme);
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+       gtk_text_buffer_get_end_iter (buffer, &start_iter);
+       mark = gtk_text_buffer_create_mark (buffer, NULL, &start_iter, TRUE);
+
+       start = g_array_new (FALSE, FALSE, sizeof (gint));
+       end = g_array_new (FALSE, FALSE, sizeof (gint));
+
+       num_matches = empathy_regex_match (EMPATHY_REGEX_ALL, body, start, end);
+
+       if (num_matches == 0) {
+               gtk_text_buffer_get_end_iter (buffer, &iter);
+               theme_insert_text_with_emoticons (buffer, &iter, body, priv->smiley_manager);
+       } else {
+               gint   last = 0;
+               gint   s = 0, e = 0;
+               gchar *tmp;
+
+               for (i = 0; i < num_matches; i++) {
+                       s = g_array_index (start, gint, i);
+                       e = g_array_index (end, gint, i);
+
+                       if (s > last) {
+                               tmp = empathy_substring (body, last, s);
+
+                               gtk_text_buffer_get_end_iter (buffer, &iter);
+                               theme_insert_text_with_emoticons (buffer,
+                                                                 &iter,
+                                                                 tmp,
+                                                                 priv->smiley_manager);
+                               g_free (tmp);
+                       }
+
+                       tmp = empathy_substring (body, s, e);
+
+                       gtk_text_buffer_get_end_iter (buffer, &iter);
+                       if (!link_tag) {
+                               gtk_text_buffer_insert (buffer, &iter,
+                                                       tmp, -1);
+                       } {
+                               gtk_text_buffer_insert_with_tags_by_name (buffer,
+                                                                         &iter,
+                                                                         tmp,
+                                                                         -1,
+                                                                         link_tag,
+                                                                         "link",
+                                                                         NULL);
+                       }
+
+                       g_free (tmp);
+
+                       last = e;
+               }
+
+               if (e < strlen (body)) {
+                       tmp = empathy_substring (body, e, strlen (body));
+
+                       gtk_text_buffer_get_end_iter (buffer, &iter);
+                       theme_insert_text_with_emoticons (buffer,
+                                                         &iter,
+                                                         tmp,
+                                                         priv->smiley_manager);
+                       g_free (tmp);
+               }
+       }
+
+       g_array_free (start, TRUE);
+       g_array_free (end, TRUE);
+
+       gtk_text_buffer_get_end_iter (buffer, &iter);
+       gtk_text_buffer_insert (buffer, &iter, "\n", 1);
+
+       /* Apply the style to the inserted text. */
+       gtk_text_buffer_get_iter_at_mark (buffer, &start_iter, mark);
+       gtk_text_buffer_get_end_iter (buffer, &end_iter);
+
+       gtk_text_buffer_apply_tag_by_name (buffer,
+                                          tag,
+                                          &start_iter,
+                                          &end_iter);
+
+       gtk_text_buffer_delete_mark (buffer, mark);
+}
+
+void 
+empathy_theme_append_event (EmpathyTheme        *theme,
+                          EmpathyThemeContext *context,
+                          EmpathyChatView     *view,
+                          const gchar        *str)
+{
+       EMPATHY_THEME_GET_CLASS(theme)->append_event (theme, context, view, str);
+}
+
+void
+empathy_theme_append_spacing (EmpathyTheme        *theme, 
+                            EmpathyThemeContext *context,
+                            EmpathyChatView     *view)
+{
+       if (!EMPATHY_THEME_GET_CLASS(theme)->append_spacing) {
+               return;
+       }
+
+       EMPATHY_THEME_GET_CLASS(theme)->append_spacing (theme, context, view);
+}
+
+
+void 
+empathy_theme_append_timestamp (EmpathyTheme        *theme,
+                              EmpathyThemeContext *context,
+                              EmpathyChatView     *view,
+                              EmpathyMessage      *message,
+                              gboolean            show_date,
+                              gboolean            show_time)
+{
+       if (!EMPATHY_THEME_GET_CLASS(theme)->append_timestamp) {
+               return;
+       }
+
+       EMPATHY_THEME_GET_CLASS(theme)->append_timestamp (theme, context, view,
+                                                        message, show_date,
+                                                        show_time);
+}
+
+gboolean
+empathy_theme_get_show_avatars (EmpathyTheme *theme)
+{
+       EmpathyThemePriv *priv;
+
+       g_return_val_if_fail (EMPATHY_IS_THEME (theme), FALSE);
+
+       priv = GET_PRIV (theme);
+
+       return priv->show_avatars;
+}
+
+void
+empathy_theme_set_show_avatars (EmpathyTheme *theme, gboolean show)
+{
+       EmpathyThemePriv *priv;
+
+       g_return_if_fail (EMPATHY_IS_THEME (theme));
+
+       priv = GET_PRIV (theme);
+
+       priv->show_avatars = show;
+
+       g_object_notify (G_OBJECT (theme), "show-avatars");
+}
+
diff --git a/libempathy-gtk/empathy-theme.h b/libempathy-gtk/empathy-theme.h
new file mode 100644 (file)
index 0000000..b05342a
--- /dev/null
@@ -0,0 +1,132 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Imendio AB
+ *
+ * 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 __EMPATHY_THEME_H__
+#define __EMPATHY_THEME_H__
+
+#include <glib-object.h>
+#include <gtk/gtktextbuffer.h>
+
+G_BEGIN_DECLS
+
+#define EMPATHY_TYPE_THEME            (empathy_theme_get_type ())
+#define EMPATHY_THEME(o)              (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_THEME, EmpathyTheme))
+#define EMPATHY_THEME_CLASS(k)        (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_THEME, EmpathyThemeClass))
+#define EMPATHY_IS_THEME(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_THEME))
+#define EMPATHY_IS_THEME_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_THEME))
+#define EMPATHY_THEME_GET_CLASS(o)    (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_THEME, EmpathyThemeClass))
+
+typedef struct _EmpathyTheme      EmpathyTheme;
+typedef struct _EmpathyThemeClass EmpathyThemeClass;
+
+#include "empathy-chat-view.h"
+
+struct _EmpathyTheme {
+       GObject parent;
+};
+
+typedef void EmpathyThemeContext;
+
+struct _EmpathyThemeClass {
+       GObjectClass parent_class;
+
+       /* <vtable> */
+       EmpathyThemeContext * (*setup_with_view)  (EmpathyTheme        *theme,
+                                                 EmpathyChatView     *view);
+       void                 (*detach_from_view) (EmpathyTheme        *theme,
+                                                 EmpathyThemeContext *context,
+                                                 EmpathyChatView     *view);
+       void                 (*view_cleared)     (EmpathyTheme        *theme,
+                                                 EmpathyThemeContext *context,
+                                                 EmpathyChatView     *view);
+       void                 (*append_message)   (EmpathyTheme        *theme,
+                                                 EmpathyThemeContext *context,
+                                                 EmpathyChatView     *view,
+                                                 EmpathyMessage      *message);
+       void                 (*append_event)     (EmpathyTheme        *theme,
+                                                 EmpathyThemeContext *context,
+                                                 EmpathyChatView     *view,
+                                                 const gchar        *str);
+       void                 (*append_timestamp) (EmpathyTheme        *theme,
+                                                 EmpathyThemeContext *context,
+                                                 EmpathyChatView     *view,
+                                                 EmpathyMessage      *message,
+                                                 gboolean            show_date,
+                                                 gboolean            show_time);
+       void                 (*append_spacing)   (EmpathyTheme        *theme,
+                                                 EmpathyThemeContext *context,
+                                                 EmpathyChatView     *view);
+       void                 (*update_show_avatars) (EmpathyTheme     *theme,
+                                                    EmpathyThemeContext *context,
+                                                    EmpathyChatView  *view,
+                                                    gboolean         show);
+};
+
+GType         empathy_theme_get_type             (void) G_GNUC_CONST;
+
+EmpathyTheme * empathy_theme_new                  (void);
+
+EmpathyThemeContext *
+empathy_theme_setup_with_view                    (EmpathyTheme        *theme,
+                                                EmpathyChatView     *view);
+void         empathy_theme_detach_from_view      (EmpathyTheme        *theme,
+                                                EmpathyThemeContext *context,
+                                                EmpathyChatView     *view);
+void         empathy_theme_view_cleared          (EmpathyTheme        *theme,
+                                                EmpathyThemeContext *context,
+                                                EmpathyChatView     *view);
+
+void         empathy_theme_append_message        (EmpathyTheme        *theme,
+                                                EmpathyThemeContext *context,
+                                                EmpathyChatView     *view,
+                                                EmpathyMessage      *msg);
+void         empathy_theme_append_text           (EmpathyTheme        *theme,
+                                                EmpathyThemeContext *context,
+                                                EmpathyChatView     *view,
+                                                const gchar        *body,
+                                                const gchar        *tag, 
+                                                const gchar        *link_tag);
+void         empathy_theme_append_spacing        (EmpathyTheme        *theme,
+                                                EmpathyThemeContext *context,
+                                                EmpathyChatView     *view);
+void         empathy_theme_append_event          (EmpathyTheme        *theme,
+                                                EmpathyThemeContext *context,
+                                                EmpathyChatView     *view,
+                                                const gchar        *str);
+void         empathy_theme_append_timestamp      (EmpathyTheme        *theme,
+                                                EmpathyThemeContext *context,
+                                                EmpathyChatView     *view,
+                                                EmpathyMessage      *message,
+                                                gboolean            show_date,
+                                                gboolean            show_time);
+
+void      
+empathy_theme_maybe_append_date_and_time         (EmpathyTheme        *theme,
+                                                EmpathyThemeContext *context,
+                                                EmpathyChatView     *view,
+                                                EmpathyMessage      *message);
+gboolean     empathy_theme_get_show_avatars      (EmpathyTheme        *theme);
+void         empathy_theme_set_show_avatars      (EmpathyTheme        *theme,
+                                                gboolean            show);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_THEME_H__ */
+
index 383bfbbedd0b98f6ca3f6a20957eb09801ee7b7b..1a79b058a0834c7ab70499b042d3c9be1d45bb63 100644 (file)
@@ -1,3 +1,4 @@
+VOID:VOID
 VOID:OBJECT,UINT
 VOID:OBJECT,BOOLEAN
 VOID:OBJECT,POINTER
index 5c2028bd01975432c70fa60e89e21a60b042f717..2d3fd69e474bc736b7661ea039f35f3df51021e4 100644 (file)
@@ -417,6 +417,26 @@ empathy_message_set_timestamp (EmpathyMessage *message,
        g_object_notify (G_OBJECT (message), "timestamp");
 }
 
+GDate *
+empathy_message_get_date_and_time (EmpathyMessage *message, time_t *timestamp)
+{
+       GDate *date;
+
+       *timestamp = 0;
+       if (message) {
+               *timestamp = empathy_message_get_timestamp (message);
+       }
+
+       if (timestamp <= 0) {
+               *timestamp = empathy_time_get_current ();
+       }
+
+       date = g_date_new ();
+       g_date_set_time (date, *timestamp);
+
+       return date;
+}
+
 EmpathyMessageType
 empathy_message_type_from_str (const gchar *type_str)
 {
index af19d364c1416a4ce3b30aa33e5d47b419372359..668b33311f942745eb0a72f88e2494c4dceb99ca 100644 (file)
@@ -75,6 +75,8 @@ void               empathy_message_set_body      (EmpathyMessage     *message,
 time_t             empathy_message_get_timestamp (EmpathyMessage     *message);
 void               empathy_message_set_timestamp (EmpathyMessage     *message,
                                                  time_t              timestamp);
+GDate *            empathy_message_get_date_and_time (EmpathyMessage *message,
+                                 time_t             *timestamp);
 EmpathyMessageType empathy_message_type_from_str (const gchar        *type_str);
 const gchar *      empathy_message_type_to_str   (EmpathyMessageType  type);