Mercurial > pidgin
changeset 15079:32814a36f363
[gaim-migrate @ 17864]
Work in progress. I'm committing this mostly so i can work on it from home.
I'm hacking up statusbox to no longer descend from combobox to better get the
appearance and behavior we want. Seems mostly functional, but a lot of looes
ends to tie up.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Fri, 01 Dec 2006 05:01:51 +0000 |
parents | 49d03b561f14 |
children | d24de6319f87 |
files | gtk/gtkstatusbox.c gtk/gtkstatusbox.h |
diffstat | 2 files changed, 287 insertions(+), 125 deletions(-) [+] |
line wrap: on
line diff
--- a/gtk/gtkstatusbox.c Fri Dec 01 04:38:54 2006 +0000 +++ b/gtk/gtkstatusbox.c Fri Dec 01 05:01:51 2006 +0000 @@ -73,21 +73,19 @@ static void gtk_gaim_status_box_refresh(GtkGaimStatusBox *status_box); static void status_menu_refresh_iter(GtkGaimStatusBox *status_box); static void gtk_gaim_status_box_regenerate(GtkGaimStatusBox *status_box); -static void gtk_gaim_status_box_changed(GtkComboBox *box); +static void gtk_gaim_status_box_changed(GtkGaimStatusBox *box); static void gtk_gaim_status_box_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_gaim_status_box_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static gboolean gtk_gaim_status_box_expose_event (GtkWidget *widget, GdkEventExpose *event); static void gtk_gaim_status_box_redisplay_buddy_icon(GtkGaimStatusBox *status_box); static void gtk_gaim_status_box_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); +static void gaim_gtk_status_box_popup(GtkGaimStatusBox *box); +static void gaim_gtk_status_box_popdown(GtkGaimStatusBox *box); static void do_colorshift (GdkPixbuf *dest, GdkPixbuf *src, int shift); static void icon_choose_cb(const char *filename, gpointer data); static void remove_buddy_icon_cb(GtkWidget *w, GtkGaimStatusBox *box); -static void (*combo_box_size_request)(GtkWidget *widget, GtkRequisition *requisition); -static void (*combo_box_size_allocate)(GtkWidget *widget, GtkAllocation *allocation); -static void (*combo_box_forall) (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); - enum { /** A GtkGaimStatusBoxItemType */ TYPE_COLUMN, @@ -123,7 +121,7 @@ PROP_ICON_SEL, }; -GtkComboBoxClass *parent_class = NULL; +GtkContainerClass *parent_class = NULL; static void gtk_gaim_status_box_class_init (GtkGaimStatusBoxClass *klass); static void gtk_gaim_status_box_init (GtkGaimStatusBox *status_box); @@ -149,7 +147,7 @@ NULL /* value_table */ }; - status_box_type = g_type_register_static(GTK_TYPE_COMBO_BOX, + status_box_type = g_type_register_static(GTK_TYPE_CONTAINER, "GtkGaimStatusBox", &status_box_info, 0); @@ -199,8 +197,13 @@ } if (status_no != -1) { + GtkTreePath *path; gtk_widget_set_sensitive(GTK_WIDGET(status_box), FALSE); - gtk_combo_box_set_active(GTK_COMBO_BOX(status_box), status_no); + path = gtk_tree_path_new_from_indices(status_no, -1); + if (status_box->active_row) + gtk_tree_row_reference_free(status_box->active_row); + status_box->active_row = gtk_tree_row_reference_new(status_box->dropdown_store, path); + gtk_tree_path_free(path); message = gaim_status_get_attr_string(newstatus, "message"); @@ -324,6 +327,9 @@ status_box->icon = gtk_image_new(); status_box->icon_box = gtk_event_box_new(); + gtk_widget_set_parent(status_box->icon_box, GTK_WIDGET(status_box)); + gtk_widget_show(status_box->icon_box); + if (status_box->account && !gaim_account_get_ui_bool(status_box->account, GAIM_GTK_UI, "use-global-buddyicon", TRUE)) { @@ -353,9 +359,7 @@ g_signal_connect(G_OBJECT(status_box->icon_box), "button-press-event", G_CALLBACK(icon_box_press_cb), status_box); gtk_container_add(GTK_CONTAINER(status_box->icon_box), status_box->icon); - - gtk_widget_show_all(status_box->icon_box); - gtk_widget_set_parent(status_box->icon_box, GTK_WIDGET(status_box)); + gtk_widget_show(status_box->icon); } static void @@ -446,27 +450,27 @@ G_OBJECT_CLASS(parent_class)->finalize(obj); } +static GType +gtk_gaim_status_box_child_type (GtkContainer *container) +{ + return GTK_TYPE_WIDGET; +} + static void gtk_gaim_status_box_class_init (GtkGaimStatusBoxClass *klass) { GObjectClass *object_class; - GtkComboBoxClass *combo_class; GtkWidgetClass *widget_class; GtkContainerClass *container_class = (GtkContainerClass*)klass; parent_class = g_type_class_peek_parent(klass); - combo_class = (GtkComboBoxClass*)klass; - combo_class->changed = gtk_gaim_status_box_changed; - widget_class = (GtkWidgetClass*)klass; - combo_box_size_request = widget_class->size_request; widget_class->size_request = gtk_gaim_status_box_size_request; - combo_box_size_allocate = widget_class->size_allocate; widget_class->size_allocate = gtk_gaim_status_box_size_allocate; widget_class->expose_event = gtk_gaim_status_box_expose_event; - combo_box_forall = container_class->forall; + container_class->child_type = gtk_gaim_status_box_child_type; container_class->forall = gtk_gaim_status_box_forall; container_class->remove = NULL; @@ -504,7 +508,6 @@ static void gtk_gaim_status_box_refresh(GtkGaimStatusBox *status_box) { - gboolean show_buddy_icons; GtkIconSize icon_size; GtkStyle *style; char aa_color[8]; @@ -515,13 +518,8 @@ gboolean account_status = FALSE; GaimAccount *acct = (status_box->token_status_account) ? status_box->token_status_account : status_box->account; - - show_buddy_icons = gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons"); - if (show_buddy_icons) - icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS); - else - icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS_SMALL); - + icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS); + style = gtk_widget_get_style(GTK_WIDGET(status_box)); snprintf(aa_color, sizeof(aa_color), "#%02x%02x%02x", style->text_aa[GTK_STATE_NORMAL].red >> 8, @@ -542,7 +540,11 @@ gpointer data; /* Primary (get the status selected in the dropdown) */ - gtk_combo_box_get_active_iter(GTK_COMBO_BOX(status_box), &iter); + path = gtk_tree_row_reference_get_path(status_box->active_row); + if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(status_box->dropdown_store), &iter, path)) + return; + gtk_tree_path_free(path); + gtk_tree_model_get(GTK_TREE_MODEL(status_box->dropdown_store), &iter, TYPE_COLUMN, &type, DATA_COLUMN, &data, @@ -595,11 +597,11 @@ if (account_status) pixbuf = gaim_gtk_create_prpl_icon_with_status(acct, gaim_status_get_type(gaim_account_get_active_status(acct)), - show_buddy_icons ? 1.0 : 0.5); + 0.5); else pixbuf = gaim_gtk_create_gaim_icon_with_status( gaim_savedstatus_get_type(saved_status), - show_buddy_icons ? 1.0 : 0.5); + 0.5); if (!gaim_savedstatus_is_transient(saved_status)) { @@ -622,15 +624,12 @@ } if (status_box->account != NULL) { - text = g_strdup_printf("%s%s<span size=\"smaller\" color=\"%s\">%s</span>", - gaim_account_get_username(status_box->account), - show_buddy_icons ? "\n" : " - ", aa_color, - secondary ? secondary : primary); + text = g_strdup_printf("%s - <span size=\"smaller\" color=\"%s\">%s</span>", + gaim_account_get_username(status_box->account), + aa_color, secondary ? secondary : primary); } else if (secondary != NULL) { - char *separator; - separator = show_buddy_icons ? "\n" : " - "; - text = g_strdup_printf("%s<span size=\"smaller\" color=\"%s\">%s%s</span>", - primary, aa_color, separator, secondary); + text = g_strdup_printf("%s<span size=\"smaller\" color=\"%s\"> - %s</span>", + primary, aa_color, secondary); } else { text = g_strdup(primary); } @@ -716,8 +715,14 @@ (primitive == GAIM_STATUS_INVISIBLE) || (primitive == GAIM_STATUS_OFFLINE)) && (!gaim_savedstatus_has_substatuses(saved_status))) { + GtkTreePath *path; index = get_statusbox_index(status_box, saved_status); - gtk_combo_box_set_active(GTK_COMBO_BOX(status_box), index); + path = gtk_tree_path_new_from_indices(index, -1); + if (status_box->active_row) + gtk_tree_row_reference_free(status_box->active_row); + status_box->active_row = gtk_tree_row_reference_new(status_box->dropdown_store, path); + gtk_tree_path_free(path); + } else { @@ -726,7 +731,9 @@ gpointer data; /* Unset the active item */ - gtk_combo_box_set_active(GTK_COMBO_BOX(status_box), -1); + if (status_box->active_row) + gtk_tree_row_reference_free(status_box->active_row); + status_box->active_row = NULL; /* If this saved status is in the list store, then set it as the active item */ if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(status_box->dropdown_store), &iter)) @@ -754,7 +761,8 @@ || !strcmp(name, acct_status_name)) { /* Found! */ - gtk_combo_box_set_active_iter(GTK_COMBO_BOX(status_box), &iter); + // gtk_combo_box_set_active_iter(GTK_COMBO_BOX(status_box), &iter); + g_free(name); break; } @@ -764,7 +772,7 @@ (GPOINTER_TO_INT(data) == gaim_savedstatus_get_creation_time(saved_status))) { /* Found! */ - gtk_combo_box_set_active_iter(GTK_COMBO_BOX(status_box), &iter); + // gtk_combo_box_set_active_iter(GTK_COMBO_BOX(status_box), &iter); break; } } @@ -804,8 +812,7 @@ static void add_popular_statuses(GtkGaimStatusBox *statusbox) { - gboolean show_buddy_icons; - GtkIconSize icon_size; + GtkIconSize icon_size; GList *list, *cur; GdkPixbuf *pixbuf, *emblem; int width, height; @@ -815,11 +822,7 @@ /* Odd... oh well, nothing we can do about it. */ return; - show_buddy_icons = gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons"); - if (show_buddy_icons) - icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS); - else - icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS_SMALL); + icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS_SMALL); gtk_gaim_status_box_add_separator(statusbox); @@ -832,7 +835,7 @@ /* Get an appropriate status icon */ pixbuf = gaim_gtk_create_gaim_icon_with_status( gaim_savedstatus_get_type(saved), - show_buddy_icons ? 1.0 : 0.5); + 0.5); if (gaim_savedstatus_is_transient(saved)) { @@ -927,7 +930,7 @@ } static void -add_account_statuses(GtkGaimStatusBox *status_box, GaimAccount *account, gboolean show_buddy_icons) +add_account_statuses(GtkGaimStatusBox *status_box, GaimAccount *account) { /* Per-account */ const GList *l; @@ -940,8 +943,7 @@ if (!gaim_status_type_is_user_settable(status_type)) continue; - tmp = gaim_gtk_create_prpl_icon_with_status(account, status_type, - show_buddy_icons ? 1.0 : 0.5); + tmp = gaim_gtk_create_prpl_icon_with_status(account, status_type, 0.5); gtk_gaim_status_box_add(GTK_GAIM_STATUS_BOX(status_box), GTK_GAIM_STATUS_BOX_TYPE_PRIMITIVE, tmp, gaim_status_type_get_name(status_type), @@ -950,24 +952,18 @@ if (tmp != NULL) g_object_unref(tmp); } - gtk_combo_box_set_model(GTK_COMBO_BOX(status_box), GTK_TREE_MODEL(status_box->dropdown_store)); } static void gtk_gaim_status_box_regenerate(GtkGaimStatusBox *status_box) { - gboolean show_buddy_icons; GdkPixbuf *pixbuf, *pixbuf2, *pixbuf3, *pixbuf4; GtkIconSize icon_size; - show_buddy_icons = gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons"); - if (show_buddy_icons) - icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS); - else - icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS_SMALL); + icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS_SMALL); /* Unset the model while clearing it */ - gtk_combo_box_set_model(GTK_COMBO_BOX(status_box), NULL); + gtk_tree_view_set_model(GTK_TREE_VIEW(status_box->tree_view), NULL); gtk_list_store_clear(status_box->dropdown_store); /* Don't set the model until the new statuses have been added to the box. * What is presumably a bug in Gtk < 2.4 causes things to get all confused @@ -982,7 +978,7 @@ * If so, display them instead of our global list. */ if (status_box->token_status_account) { - add_account_statuses(status_box, status_box->token_status_account, show_buddy_icons); + add_account_statuses(status_box, status_box->token_status_account); } else { /* Global */ pixbuf2 = gtk_widget_render_icon (GTK_WIDGET(status_box->vbox), GAIM_STOCK_STATUS_AWAY, @@ -1009,19 +1005,19 @@ gtk_gaim_status_box_add(GTK_GAIM_STATUS_BOX(status_box), GTK_GAIM_STATUS_BOX_TYPE_SAVED, pixbuf, _("Saved..."), NULL, NULL); if (pixbuf) g_object_unref(G_OBJECT(pixbuf)); - gtk_combo_box_set_model(GTK_COMBO_BOX(status_box), GTK_TREE_MODEL(status_box->dropdown_store)); status_menu_refresh_iter(status_box); } else { - add_account_statuses(status_box, status_box->account, show_buddy_icons); + add_account_statuses(status_box, status_box->account); update_to_reflect_account_status(status_box, status_box->account, gaim_account_get_active_status(status_box->account)); } + gtk_tree_view_set_model(GTK_TREE_VIEW(status_box->tree_view), status_box->dropdown_store); } static gboolean combo_box_scroll_event_cb(GtkWidget *w, GdkEventScroll *event, GtkIMHtml *imhtml) { - gtk_combo_box_popup(GTK_COMBO_BOX(w)); + gaim_gtk_status_box_popup(GTK_GAIM_STATUS_BOX(w)); return TRUE; } @@ -1088,15 +1084,9 @@ cache_pixbufs(GtkGaimStatusBox *status_box) { GtkIconSize icon_size; - - if (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons")) - { - g_object_set(G_OBJECT(status_box->icon_rend), "xpad", 6, NULL); - icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS_TWO_LINE); - } else { - g_object_set(G_OBJECT(status_box->icon_rend), "xpad", 3, NULL); - icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS_SMALL_TWO_LINE); - } + + g_object_set(G_OBJECT(status_box->icon_rend), "xpad", 3, NULL); + icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS_SMALL_TWO_LINE); if (status_box->connecting_pixbufs[0] != NULL) gdk_pixbuf_unref(status_box->connecting_pixbufs[0]); @@ -1157,16 +1147,6 @@ } static void -buddy_list_details_pref_changed_cb(const char *name, GaimPrefType type, - gconstpointer val, gpointer data) -{ - GtkGaimStatusBox *status_box = (GtkGaimStatusBox *)data; - - cache_pixbufs(status_box); - gtk_gaim_status_box_regenerate(status_box); -} - -static void spellcheck_prefs_cb(const char *name, GaimPrefType type, gconstpointer value, gpointer data) { @@ -1190,7 +1170,6 @@ if (event->button != 1) return FALSE; - gtk_combo_box_popdown(GTK_COMBO_BOX(box)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(box->toggle_button), FALSE); if (!box->imhtml_visible) g_signal_emit_by_name(G_OBJECT(box), "changed", NULL, NULL); @@ -1209,10 +1188,101 @@ #endif static void +gtk_gaim_status_box_list_position (GtkGaimStatusBox *status_box, int *x, int *y, int *width, int *height) +{ + GdkScreen *screen; + gint monitor_num; + GdkRectangle monitor; + GtkRequisition popup_req; + GtkPolicyType hpolicy, vpolicy; + + gdk_window_get_origin (GTK_WIDGET(status_box)->window, x, y); + + *x += GTK_WIDGET(status_box)->allocation.x; + *y += GTK_WIDGET(status_box)->allocation.y; + + *width = GTK_WIDGET(status_box)->allocation.width; + + hpolicy = vpolicy = GTK_POLICY_NEVER; + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (status_box->scrolled_window), + hpolicy, vpolicy); + gtk_widget_size_request (status_box->popup_frame, &popup_req); + + if (popup_req.width > *width) + { + hpolicy = GTK_POLICY_ALWAYS; + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (status_box->scrolled_window), + hpolicy, vpolicy); + gtk_widget_size_request (status_box->popup_frame, &popup_req); + } + + *height = popup_req.height; + + screen = gtk_widget_get_screen (GTK_WIDGET (status_box)); + monitor_num = gdk_screen_get_monitor_at_window (screen, + GTK_WIDGET (status_box)->window); + gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); + + if (*x < monitor.x) + *x = monitor.x; + else if (*x + *width > monitor.x + monitor.width) + *x = monitor.x + monitor.width - *width; + + if (*y + GTK_WIDGET(status_box)->allocation.height + *height <= monitor.y + monitor.height) + *y += GTK_WIDGET(status_box)->allocation.height; + else if (*y - *height >= monitor.y) + *y -= *height; + else if (monitor.y + monitor.height - (*y + GTK_WIDGET(status_box)->allocation.height) > *y - monitor.y) + { + *y += GTK_WIDGET(status_box)->allocation.height; + *height = monitor.y + monitor.height - *y; + } + else + { + *height = *y - monitor.y; + *y = monitor.y; + } + + if (popup_req.height > *height) + { + vpolicy = GTK_POLICY_ALWAYS; + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (status_box->scrolled_window), + hpolicy, vpolicy); + } +} + +static void +gaim_gtk_status_box_popup(GtkGaimStatusBox *box) +{ + int width, height, x, y; + gtk_gaim_status_box_list_position (box, &x, &y, &width, &height); + + gtk_widget_set_size_request (box->popup_window, width, height); + gtk_window_move (GTK_WINDOW (box->popup_window), x, y); + gtk_widget_show(box->popup_window); + box->popup_in_progress = TRUE; +} + +static void +gaim_gtk_status_box_popdown(GtkGaimStatusBox *box) { + gtk_widget_hide(box->popup_window); + box->popup_in_progress = FALSE; + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (box->toggle_button), + FALSE); + +} + + +static void toggled_cb(GtkWidget *widget, GtkGaimStatusBox *box) { - gtk_combo_box_popup(GTK_COMBO_BOX(box)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(box->toggle_button), FALSE); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) { + if (!box->popup_in_progress) + gaim_gtk_status_box_popup (box); + } else { + gaim_gtk_status_box_popdown(box); + } } static void @@ -1287,18 +1357,45 @@ static void update_buddyicon_cb(const char *name, GaimPrefType type, - gconstpointer value, gpointer data) + gconstpointer value, gpointer data) { buddy_icon_set_cb(value, (GtkGaimStatusBox*) data); } +static gboolean +treeview_button_release_cb(GtkWidget *widget, GdkEventButton *event, GtkGaimStatusBox *status_box) +{ + GtkTreePath *path = NULL; + int ret = gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (status_box->tree_view), + event->x, event->y, + &path, + NULL, NULL, NULL); + + if (!ret) + return TRUE; /* clicked outside window? */ + + if (status_box->active_row) + gtk_tree_row_reference_free(status_box->active_row); + + status_box->active_row = gtk_tree_row_reference_new(GTK_TREE_MODEL(status_box->dropdown_store), path); + gtk_tree_path_free (path); + + gaim_gtk_status_box_popdown (status_box); + gtk_gaim_status_box_changed(status_box); + + return TRUE; +} + static void gtk_gaim_status_box_init (GtkGaimStatusBox *status_box) { GtkCellRenderer *text_rend; GtkCellRenderer *icon_rend; GtkTextBuffer *buffer; + GtkWidget *toplevel; + GtkTreeSelection *sel; + GTK_WIDGET_SET_FLAGS (status_box, GTK_NO_WINDOW); status_box->imhtml_visible = FALSE; status_box->network_available = gaim_network_is_available(); status_box->connecting = FALSE; @@ -1308,12 +1405,11 @@ status_box->cell_view = gtk_cell_view_new(); status_box->vsep = gtk_vseparator_new(); status_box->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE); - + status_box->store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_INT, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); status_box->dropdown_store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_INT, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); - gtk_combo_box_set_model(GTK_COMBO_BOX(status_box), GTK_TREE_MODEL(status_box->dropdown_store)); +; gtk_cell_view_set_model(GTK_CELL_VIEW(status_box->cell_view), GTK_TREE_MODEL(status_box->store)); - gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(status_box), 0); gtk_list_store_append(status_box->store, &(status_box->iter)); gtk_container_add(GTK_CONTAINER(status_box->toggle_button), status_box->hbox); @@ -1327,10 +1423,59 @@ text_rend = gtk_cell_renderer_text_new(); icon_rend = gtk_cell_renderer_pixbuf_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box), icon_rend, FALSE); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box), text_rend, TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box), icon_rend, "pixbuf", ICON_COLUMN, NULL); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box), text_rend, "markup", TEXT_COLUMN, NULL); + + + status_box->popup_window = gtk_window_new (GTK_WINDOW_POPUP); + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (status_box)); + if (GTK_IS_WINDOW (toplevel)) { + gtk_window_set_transient_for (GTK_WINDOW (status_box->popup_window), + GTK_WINDOW (toplevel)); + } + + gtk_window_set_resizable (GTK_WINDOW (status_box->popup_window), FALSE); + gtk_window_set_screen (GTK_WINDOW (status_box->popup_window), + gtk_widget_get_screen (GTK_WIDGET (status_box))); + status_box->popup_frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (status_box->popup_frame), + GTK_SHADOW_ETCHED_IN); + gtk_container_add (GTK_CONTAINER (status_box->popup_window), + status_box->popup_frame); + + gtk_widget_show (status_box->popup_frame); + + status_box->scrolled_window = gtk_scrolled_window_new (NULL, NULL); + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (status_box->scrolled_window), + GTK_POLICY_NEVER, + GTK_POLICY_NEVER); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (status_box->scrolled_window), + GTK_SHADOW_NONE); + + gtk_widget_show (status_box->scrolled_window); + + gtk_container_add (GTK_CONTAINER (status_box->popup_frame), + status_box->scrolled_window); + + status_box->tree_view = gtk_tree_view_new (); + sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (status_box->tree_view)); + gtk_tree_selection_set_mode (sel, GTK_SELECTION_BROWSE); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (status_box->tree_view), + FALSE); + gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (status_box->tree_view), + TRUE); + gtk_tree_view_set_model (GTK_TREE_VIEW (status_box->tree_view), + status_box->dropdown_store); + status_box->column = gtk_tree_view_column_new (); + gtk_tree_view_append_column (GTK_TREE_VIEW (status_box->tree_view), + status_box->column); + gtk_tree_view_column_pack_start(status_box->column, icon_rend, FALSE); + gtk_tree_view_column_pack_start(status_box->column, text_rend, TRUE); + gtk_tree_view_column_set_attributes(GTK_CELL_LAYOUT(status_box->column), icon_rend, "pixbuf", ICON_COLUMN, NULL); + gtk_tree_view_column_set_attributes(GTK_CELL_LAYOUT(status_box->column), text_rend, "markup", TEXT_COLUMN, NULL); + gtk_container_add(GTK_CONTAINER(status_box->scrolled_window), status_box->tree_view); + gtk_widget_show(status_box->tree_view); + #if GTK_CHECK_VERSION(2, 6, 0) g_object_set(text_rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL); #endif @@ -1370,17 +1515,19 @@ gaim_gtk_setup_gtkspell(GTK_TEXT_VIEW(status_box->imhtml)); #endif gtk_widget_set_parent(status_box->vbox, GTK_WIDGET(status_box)); + gtk_widget_show_all(status_box->vbox); + gtk_widget_set_parent(status_box->toggle_button, GTK_WIDGET(status_box)); - GTK_BIN(status_box)->child = status_box->toggle_button; gtk_box_pack_start(GTK_BOX(status_box->vbox), status_box->sw, TRUE, TRUE, 0); g_signal_connect(G_OBJECT(status_box), "scroll_event", G_CALLBACK(combo_box_scroll_event_cb), NULL); g_signal_connect(G_OBJECT(status_box->imhtml), "scroll_event", G_CALLBACK(imhtml_scroll_event_cb), status_box->imhtml); + g_signal_connect(G_OBJECT(status_box->tree_view), "button_release_event", G_CALLBACK(treeview_button_release_cb), status_box); #if GTK_CHECK_VERSION(2,6,0) - gtk_combo_box_set_row_separator_func(GTK_COMBO_BOX(status_box), dropdown_store_row_separator_func, NULL, NULL); + gtk_tree_view_set_row_separator_func(GTK_TREE_VIEW(status_box->tree_view), dropdown_store_row_separator_func, NULL, NULL); #endif status_box->token_status_account = check_active_accounts_for_identical_statuses(); @@ -1402,8 +1549,6 @@ GAIM_CALLBACK(account_status_changed_cb), status_box); - gaim_prefs_connect_callback(status_box, "/gaim/gtk/blist/show_buddy_icons", - buddy_list_details_pref_changed_cb, status_box); gaim_prefs_connect_callback(status_box, "/gaim/gtk/conversations/spellcheck", spellcheck_prefs_cb, status_box); gaim_prefs_connect_callback(status_box, "/gaim/gtk/accounts/buddyicon", @@ -1415,8 +1560,13 @@ GtkRequisition *requisition) { GtkRequisition box_req; - combo_box_size_request(widget, requisition); - requisition->height += 3; + gint border_width = GTK_CONTAINER (widget)->border_width; + + gtk_widget_size_request(GTK_GAIM_STATUS_BOX(widget)->toggle_button, requisition); + + /* Make this icon the same size as other buddy icons in the list; unless it already wants to be bigger */ + if ( gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons")) + requisition->height = MAX(requisition->height, 30 + (border_width*2)); /* If the gtkimhtml is visible, then add some additional padding */ gtk_widget_size_request(GTK_GAIM_STATUS_BOX(widget)->vbox, &box_req); @@ -1424,8 +1574,6 @@ requisition->height += box_req.height + 3; requisition->width = 1; - - } /* From gnome-panel */ @@ -1477,7 +1625,11 @@ GtkAllocation parent_alc, box_alc, icon_alc; gint border_width = GTK_CONTAINER (widget)->border_width; - combo_box_size_request(widget, &req); + gtk_widget_size_request(status_box->toggle_button, &req); + /* Make this icon the same size as other buddy icons in the list; unless it already wants to be bigger */ + + if ( gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons")) + req.height = MAX(req.height, 30 + (border_width*2)); box_alc = *allocation; @@ -1488,7 +1640,7 @@ gtk_widget_size_allocate((GTK_GAIM_STATUS_BOX(widget))->vbox, &box_alc); parent_alc = *allocation; - parent_alc.height = MAX(1,req.height - (border_width )); + parent_alc.height = MAX(1,req.height - (border_width *2)); parent_alc.width -= (border_width * 2); parent_alc.x += border_width; parent_alc.y += border_width; @@ -1498,7 +1650,7 @@ GtkTextDirection dir = gtk_widget_get_direction(widget); parent_alc.width -= (parent_alc.height + border_width); icon_alc = *allocation; - icon_alc.height = MAX(1,req.height) - (border_width); + icon_alc.height = MAX(1,req.height) - (border_width*2); icon_alc.width = icon_alc.height; if (dir == GTK_TEXT_DIR_RTL) { icon_alc.x = parent_alc.x; @@ -1516,7 +1668,6 @@ gtk_widget_size_allocate(status_box->icon_box, &icon_alc); } - combo_box_size_allocate(widget, &parent_alc); gtk_widget_size_allocate(status_box->toggle_button, &parent_alc); widget->allocation = *allocation; } @@ -1543,14 +1694,12 @@ if (include_internals) { - (* callback) (status_box->vbox, callback_data); + (* callback) (status_box->vbox, callback_data); (* callback) (status_box->toggle_button, callback_data); (* callback) (status_box->arrow, callback_data); if (status_box->icon_box) (* callback) (status_box->icon_box, callback_data); } - - combo_box_forall(container, include_internals, callback, callback_data); } GtkWidget * @@ -1599,12 +1748,10 @@ } else { - gboolean show_buddy_icons; GtkStyle *style; char aa_color[8]; gchar *escaped_title, *escaped_desc; - show_buddy_icons = gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons"); style = gtk_widget_get_style(GTK_WIDGET(status_box)); snprintf(aa_color, sizeof(aa_color), "#%02x%02x%02x", style->text_aa[GTK_STATE_NORMAL].red >> 8, @@ -1613,10 +1760,9 @@ escaped_title = g_markup_escape_text(title, -1); escaped_desc = g_markup_escape_text(desc, -1); - text = g_strdup_printf("%s%s<span color=\"%s\" size=\"smaller\">%s</span>", + text = g_strdup_printf("%s - <span color=\"%s\" size=\"smaller\">%s</span>", escaped_title, - show_buddy_icons ? "\n" : " - ", - aa_color, escaped_desc); + aa_color, escaped_desc); g_free(escaped_title); g_free(escaped_desc); } @@ -1759,12 +1905,15 @@ gpointer data; gchar *title; GtkTreeIter iter; + GtkTreePath *path; char *message; GaimSavedStatus *saved_status = NULL; gboolean changed = TRUE; - - if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(status_box), &iter)) + + path = gtk_tree_row_reference_get_path(status_box->active_row); + if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(status_box->dropdown_store), &iter, path)) return; + gtk_tree_path_free(path); gtk_tree_model_get(GTK_TREE_MODEL(status_box->dropdown_store), &iter, TYPE_COLUMN, &type, @@ -1808,11 +1957,14 @@ gint active; GaimStatus *status; const char *id = NULL; + GtkTreePath *path = gtk_tree_row_reference_get_path(status_box->active_row); + active = gtk_tree_path_get_indices(path)[0]; + + gtk_tree_path_free(path); status = gaim_account_get_active_status(status_box->token_status_account); - g_object_get(G_OBJECT(status_box), "active", &active, NULL); - acct_status_type = find_status_type_by_index(status_box->token_status_account, active); + acct_status_type = find_status_type_by_index(status_box->token_status_account, active); id = gaim_status_type_get_id(acct_status_type); if (strncmp(id, gaim_status_get_id(status), strlen(id)) == 0) @@ -1998,18 +2150,19 @@ gtk_gaim_status_box_refresh(status_box); } -static void gtk_gaim_status_box_changed(GtkComboBox *box) +static void gtk_gaim_status_box_changed(GtkGaimStatusBox *status_box) { - GtkGaimStatusBox *status_box; + GtkTreePath *path = gtk_tree_row_reference_get_path(status_box->active_row); GtkTreeIter iter; GtkGaimStatusBoxItemType type; gpointer data; GList *accounts = NULL, *node; - status_box = GTK_GAIM_STATUS_BOX(box); - - if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(status_box), &iter)) + + if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(status_box->dropdown_store), &iter, path)) return; + gtk_tree_path_free(path); + gtk_tree_model_get(GTK_TREE_MODEL(status_box->dropdown_store), &iter, TYPE_COLUMN, &type, DATA_COLUMN, &data,
--- a/gtk/gtkstatusbox.h Fri Dec 01 04:38:54 2006 +0000 +++ b/gtk/gtkstatusbox.h Fri Dec 01 05:01:51 2006 +0000 @@ -65,7 +65,7 @@ struct _GtkGaimStatusBox { - GtkComboBox parent_instance; + GtkContainer parent_instance; /** * This GtkListStore contains only one row--the currently selected status. @@ -128,11 +128,20 @@ GtkWidget *toggle_button; GtkWidget *vsep; GtkWidget *arrow; + + GtkWidget *popup_window; + GtkWidget *popup_frame; + GtkWidget *scrolled_window; + GtkWidget *cell_view_frame; + GtkTreeViewColumn *column; + GtkWidget *tree_view; + gboolean popup_in_progress; + GtkTreeRowReference *active_row; }; struct _GtkGaimStatusBoxClass { - GtkComboBoxClass parent_class; + GtkContainerClass parent_class; /* signals */ void (* changed) (GtkComboBox *combo_box);