From 63e82d2437ba18c31876defafb691422862fc91b Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 20 Dec 2007 16:39:49 +0000 Subject: [PATCH] New chat theme engine imported from Gossip (Daniel Gryniewicz, Xavier Claessens). svn path=/trunk/; revision=494 --- libempathy-gtk/Makefile.am | 8 + libempathy-gtk/empathy-chat-view.c | 932 +++++---------------- libempathy-gtk/empathy-chat-view.h | 27 +- libempathy-gtk/empathy-theme-boxes.c | 1036 ++++++++++++++++++++++++ libempathy-gtk/empathy-theme-boxes.h | 55 ++ libempathy-gtk/empathy-theme-irc.c | 486 +++++++++++ libempathy-gtk/empathy-theme-irc.h | 53 ++ libempathy-gtk/empathy-theme-manager.c | 798 +----------------- libempathy-gtk/empathy-theme-manager.h | 7 - libempathy-gtk/empathy-theme-utils.c | 90 ++ libempathy-gtk/empathy-theme-utils.h | 40 + libempathy-gtk/empathy-theme.c | 475 +++++++++++ libempathy-gtk/empathy-theme.h | 132 +++ libempathy/empathy-marshal.list | 1 + libempathy/empathy-message.c | 20 + libempathy/empathy-message.h | 2 + 16 files changed, 2669 insertions(+), 1493 deletions(-) create mode 100644 libempathy-gtk/empathy-theme-boxes.c create mode 100644 libempathy-gtk/empathy-theme-boxes.h create mode 100644 libempathy-gtk/empathy-theme-irc.c create mode 100644 libempathy-gtk/empathy-theme-irc.h create mode 100644 libempathy-gtk/empathy-theme-utils.c create mode 100644 libempathy-gtk/empathy-theme-utils.h create mode 100644 libempathy-gtk/empathy-theme.c create mode 100644 libempathy-gtk/empathy-theme.h diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am index 2e996653..494e3c4c 100644 --- a/libempathy-gtk/Makefile.am +++ b/libempathy-gtk/Makefile.am @@ -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 \ diff --git a/libempathy-gtk/empathy-chat-view.c b/libempathy-gtk/empathy-chat-view.c index 9f10f024..94728159 100644 --- a/libempathy-gtk/empathy-chat-view.c +++ b/libempathy-gtk/empathy-chat-view.c @@ -64,21 +64,12 @@ #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); + } +} + diff --git a/libempathy-gtk/empathy-chat-view.h b/libempathy-gtk/empathy-chat-view.h index 0402bd7c..37a7f997 100644 --- a/libempathy-gtk/empathy-chat-view.h +++ b/libempathy-gtk/empathy-chat-view.h @@ -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 index 00000000..2905f2be --- /dev/null +++ b/libempathy-gtk/empathy-theme-boxes.c @@ -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 + +#include + +#include +#include + +#include + +#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 ("%s", 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 ("%s", 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, ×tamp); + + 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 index 00000000..a5428369 --- /dev/null +++ b/libempathy-gtk/empathy-theme-boxes.h @@ -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 + +#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 index 00000000..afe71e5e --- /dev/null +++ b/libempathy-gtk/empathy-theme-irc.c @@ -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 +#include + +#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, ×tamp); + + 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 index 00000000..dc52a56c --- /dev/null +++ b/libempathy-gtk/empathy-theme-irc.h @@ -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 + +#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__ */ + diff --git a/libempathy-gtk/empathy-theme-manager.c b/libempathy-gtk/empathy-theme-manager.c index 268760a5..6feea2fc 100644 --- a/libempathy-gtk/empathy-theme-manager.c +++ b/libempathy-gtk/empathy-theme-manager.c @@ -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 */ #include "config.h" @@ -27,24 +25,32 @@ #include #include -#include #include +#include #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); - } -} - diff --git a/libempathy-gtk/empathy-theme-manager.h b/libempathy-gtk/empathy-theme-manager.h index d20a916e..6bd2d41f 100644 --- a/libempathy-gtk/empathy-theme-manager.h +++ b/libempathy-gtk/empathy-theme-manager.h @@ -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 */ #ifndef __EMPATHY_THEME_MANAGER_H__ @@ -25,8 +23,6 @@ #include -#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 index 00000000..56b758e2 --- /dev/null +++ b/libempathy-gtk/empathy-theme-utils.c @@ -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 + +#include + +#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 index 00000000..af970775 --- /dev/null +++ b/libempathy-gtk/empathy-theme-utils.h @@ -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 +#include + +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 index 00000000..185ad925 --- /dev/null +++ b/libempathy-gtk/empathy-theme.c @@ -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 + +#include +#include +#include + +#include +#include +#include +#include + +#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, ×tamp); + + 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 index 00000000..b05342aa --- /dev/null +++ b/libempathy-gtk/empathy-theme.h @@ -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 +#include + +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; + + /* */ + 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__ */ + diff --git a/libempathy/empathy-marshal.list b/libempathy/empathy-marshal.list index 383bfbbe..1a79b058 100644 --- a/libempathy/empathy-marshal.list +++ b/libempathy/empathy-marshal.list @@ -1,3 +1,4 @@ +VOID:VOID VOID:OBJECT,UINT VOID:OBJECT,BOOLEAN VOID:OBJECT,POINTER diff --git a/libempathy/empathy-message.c b/libempathy/empathy-message.c index 5c2028bd..2d3fd69e 100644 --- a/libempathy/empathy-message.c +++ b/libempathy/empathy-message.c @@ -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) { diff --git a/libempathy/empathy-message.h b/libempathy/empathy-message.h index af19d364..668b3331 100644 --- a/libempathy/empathy-message.h +++ b/libempathy/empathy-message.h @@ -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); -- 2.39.2