From 0f7c34dfb0a7a30cfce0820be2a6c80a9d0210f8 Mon Sep 17 00:00:00 2001 From: Andy Hertzfeld Date: Sun, 1 Apr 2001 23:44:46 +0000 Subject: added a way for sidebar views to specify small images that are displayed added a way for sidebar views to specify small images that are displayed in their tab for notification purposes. Used that to make the notes component indicate if a note is present or not. * components/notes/nautilus-notes.c: (get_bonobo_properties), (set_bonobo_properties), (load_note_text_from_metadata), (done_with_file), (notes_load_metainfo), (notify_listeners_if_changed), (notes_save_metainfo), (do_destroy), (notes_get_indicator_image), (make_notes_view): added a property bag to the notes component to provide a tab_image property, and made it notify the listeners when the note text changes. * icons/Makefile.am: * icons/note-indicator.png: new notes indicator image from Arlo. * src/nautilus-sidebar-tabs.c: (tab_item_destroy), (pixbuf_composite), (draw_one_tab_plain), (draw_one_tab_themed), (get_tab_width), (draw_or_layout_all_tabs), (nautilus_sidebar_tabs_expose), (nautilus_sidebar_tabs_update_tab_item), (get_tab_item_from_view), (nautilus_sidebar_tabs_update_all_indicators), (nautilus_sidebar_tabs_update_indicator), (tab_indicator_changed_callback), (nautilus_sidebar_tabs_connect_view): * src/nautilus-sidebar-tabs.h: made the sidebar tabs hook up to the nautilus_view's tab_image property and use it to display a notification image in the tab if necessary. * src/nautilus-sidebar.c: (view_loaded_callback), (nautilus_sidebar_add_panel): connect the sidebar tabs to a newly added view, once the view is loaded. * src/nautilus-view-frame.c: (nautilus_view_frame_get_control): * src/nautilus-view-frame.h: added nautilus_view_frame_get_control so view properties can be accessed by the sidebar. --- ChangeLog | 46 +++++++ components/notes/nautilus-notes.c | 123 +++++++++++++++--- icons/Makefile.am | 1 + icons/note-indicator.png | Bin 0 -> 602 bytes src/nautilus-information-panel.c | 11 ++ src/nautilus-sidebar-tabs.c | 261 +++++++++++++++++++++++++++++++++++--- src/nautilus-sidebar-tabs.h | 3 + src/nautilus-sidebar.c | 11 ++ src/nautilus-view-frame.c | 11 ++ src/nautilus-view-frame.h | 1 + 10 files changed, 431 insertions(+), 37 deletions(-) create mode 100644 icons/note-indicator.png diff --git a/ChangeLog b/ChangeLog index ebc578ed1..3e33ef026 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,49 @@ +2001-04-01 Andy Hertzfeld + + reviewed by: Michael Engber + + added a way for sidebar views to specify small images that + are displayed in their tab for notification purposes. Used + that to make the notes component indicate if a note is present or + not. + + * components/notes/nautilus-notes.c: (get_bonobo_properties), + (set_bonobo_properties), (load_note_text_from_metadata), + (done_with_file), (notes_load_metainfo), + (notify_listeners_if_changed), (notes_save_metainfo), (do_destroy), + (notes_get_indicator_image), (make_notes_view): + added a property bag to the notes component to provide a tab_image + property, and made it notify the listeners when the note text + changes. + + * icons/Makefile.am: + * icons/note-indicator.png: + new notes indicator image from Arlo. + + * src/nautilus-sidebar-tabs.c: (tab_item_destroy), + (pixbuf_composite), (draw_one_tab_plain), (draw_one_tab_themed), + (get_tab_width), (draw_or_layout_all_tabs), + (nautilus_sidebar_tabs_expose), + (nautilus_sidebar_tabs_update_tab_item), (get_tab_item_from_view), + (nautilus_sidebar_tabs_update_all_indicators), + (nautilus_sidebar_tabs_update_indicator), + (tab_indicator_changed_callback), + (nautilus_sidebar_tabs_connect_view): + * src/nautilus-sidebar-tabs.h: + made the sidebar tabs hook up to the nautilus_view's tab_image + property and use it to display a notification image in the tab + if necessary. + + * src/nautilus-sidebar.c: (view_loaded_callback), + (nautilus_sidebar_add_panel): + connect the sidebar tabs to a newly added view, once the view + is loaded. + + * src/nautilus-view-frame.c: (nautilus_view_frame_get_control): + * src/nautilus-view-frame.h: + added nautilus_view_frame_get_control so view properties can be + accessed by the sidebar. + 2001-03-31 Ramiro Estrugo * src/nautilus-sidebar.c: (toggle_sidebar_panel): diff --git a/components/notes/nautilus-notes.c b/components/notes/nautilus-notes.c index b531e7ae0..da92d7852 100644 --- a/components/notes/nautilus-notes.c +++ b/components/notes/nautilus-notes.c @@ -54,22 +54,68 @@ #define NOTES_DEFAULT_BACKGROUND_COLOR "rgb:FFFF/FFFF/BBBB" - typedef struct { - NautilusView *view; - GtkWidget *note_text_field; - char *uri; - NautilusFile *file; - guint save_timeout_id; - char* previous_saved_text; + NautilusView *view; + BonoboPropertyBag *property_bag; + GtkWidget *note_text_field; + char *uri; + NautilusFile *file; + guint save_timeout_id; + char* previous_saved_text; } Notes; -static void notes_save_metainfo (Notes *notes); +static void notes_save_metainfo (Notes *notes); +static char* notes_get_indicator_image (const char *notes_text); +static void notify_listeners_if_changed (Notes *notes, char *new_notes); static int notes_object_count = 0; #define SAVE_TIMEOUT (3 * 1000) +/* property bag getting and setting routines */ +enum { + TAB_IMAGE, +} MyArgs; + +static void +get_bonobo_properties (BonoboPropertyBag *bag, + BonoboArg *arg, + guint arg_id, + CORBA_Environment *ev, + gpointer user_data) +{ + char *indicator_image; + Notes *notes; + notes = (Notes*) user_data; + + switch (arg_id) { + + case TAB_IMAGE: + { + /* if there is a note, return the name of the indicator image, + otherwise, return NULL */ + indicator_image = notes_get_indicator_image (notes->previous_saved_text); + BONOBO_ARG_SET_STRING (arg, indicator_image); + g_free (indicator_image); + break; + } + + default: + g_warning ("Unhandled arg %d", arg_id); + break; + } +} + +static void +set_bonobo_properties (BonoboPropertyBag *bag, + const BonoboArg *arg, + guint arg_id, + CORBA_Environment *ev, + gpointer user_data) +{ + g_warning ("Cant set note property %d", arg_id); +} + static gboolean schedule_save_callback (gpointer data) { @@ -119,6 +165,9 @@ load_note_text_from_metadata (NautilusFile *file, * metadata has actually changed. */ if (nautilus_strcmp (saved_text, notes->previous_saved_text) != 0) { + + notify_listeners_if_changed (notes, saved_text); + g_free (notes->previous_saved_text); notes->previous_saved_text = saved_text; cancel_pending_save (notes); @@ -146,8 +195,6 @@ static void done_with_file (Notes *notes) { cancel_pending_save (notes); - g_free (notes->previous_saved_text); - notes->previous_saved_text = NULL; if (notes->file != NULL) { nautilus_file_monitor_remove (notes->file, notes); @@ -163,13 +210,13 @@ notes_load_metainfo (Notes *notes) { GList *attributes; - gtk_editable_delete_text (GTK_EDITABLE (notes->note_text_field), 0, -1); - done_with_file (notes); notes->file = nautilus_file_get (notes->uri); + gtk_editable_delete_text (GTK_EDITABLE (notes->note_text_field), 0, -1); + if (notes->file == NULL) { - return; + return; } attributes = g_list_append (NULL, NAUTILUS_FILE_ATTRIBUTE_METADATA); @@ -187,8 +234,28 @@ notes_load_metainfo (Notes *notes) notes); } -/* save the metainfo corresponding to the current uri, if any, into the text field */ +/* utility to notify event listeners if the notes data actually changed */ +static void +notify_listeners_if_changed (Notes *notes, char *new_notes) +{ + char *tab_image; + BonoboArg *tab_image_arg; + + if (nautilus_strcmp (notes->previous_saved_text, new_notes) != 0) { + /* notify listeners that the notes text has changed */ + tab_image = notes_get_indicator_image (new_notes); + + tab_image_arg = bonobo_arg_new (BONOBO_ARG_STRING); + BONOBO_ARG_SET_STRING (tab_image_arg, tab_image); + + bonobo_property_bag_notify_listeners (notes->property_bag, "tab_image", tab_image_arg, NULL); + + bonobo_arg_release (tab_image_arg); + g_free (tab_image); + } +} +/* save the metainfo corresponding to the current uri, if any, into the text field */ static void notes_save_metainfo (Notes *notes) { @@ -208,12 +275,15 @@ notes_save_metainfo (Notes *notes) notes_text = gtk_editable_get_chars (GTK_EDITABLE (notes->note_text_field), 0 , -1); nautilus_file_set_metadata (notes->file, NAUTILUS_METADATA_KEY_ANNOTATION, NULL, notes_text); - g_free (notes->previous_saved_text); - notes->previous_saved_text = notes_text; - + gtk_signal_handler_unblock_by_func (GTK_OBJECT (notes->file), load_note_text_from_metadata, - notes); + notes); + + notify_listeners_if_changed (notes, notes_text); + + g_free (notes->previous_saved_text); + notes->previous_saved_text = notes_text; } static void @@ -268,6 +338,7 @@ do_destroy (GtkObject *obj, Notes *notes) done_with_file (notes); g_free (notes->uri); + g_free (notes->previous_saved_text); g_free (notes); notes_object_count--; @@ -276,6 +347,16 @@ do_destroy (GtkObject *obj, Notes *notes) } } +static char* +notes_get_indicator_image (const char *notes_text) +{ + if (notes_text != NULL && strlen (notes_text) > 0) { + return g_strdup ("note-indicator.png"); + } + + return NULL; +} + static BonoboObject * make_notes_view (BonoboGenericFactory *Factory, const char *goad_id, gpointer closure) { @@ -316,6 +397,12 @@ make_notes_view (BonoboGenericFactory *Factory, const char *goad_id, gpointer cl notes->view = nautilus_view_new (vbox); gtk_signal_connect (GTK_OBJECT (notes->view), "destroy", do_destroy, notes); + /* allocate a property bag to reflect the TAB_IMAGE property */ + notes->property_bag = bonobo_property_bag_new (get_bonobo_properties, set_bonobo_properties, notes); + bonobo_control_set_properties (nautilus_view_get_bonobo_control (notes->view), notes->property_bag); + + bonobo_property_bag_add (notes->property_bag, "tab_image", TAB_IMAGE, BONOBO_ARG_STRING, NULL, + "image indicating that a note is present", 0); notes_object_count++; /* handle events */ diff --git a/icons/Makefile.am b/icons/Makefile.am index 34002d4fa..bb9ad804d 100644 --- a/icons/Makefile.am +++ b/icons/Makefile.am @@ -227,6 +227,7 @@ icon_DATA =\ nautilus-mini-logo.png \ netscape.png \ not.png \ + note-indicator.png \ novice-selected.png \ novice.png \ number_strip.png \ diff --git a/icons/note-indicator.png b/icons/note-indicator.png new file mode 100644 index 000000000..f8b97567f Binary files /dev/null and b/icons/note-indicator.png differ diff --git a/src/nautilus-information-panel.c b/src/nautilus-information-panel.c index 159301b46..3a302bedd 100644 --- a/src/nautilus-information-panel.c +++ b/src/nautilus-information-panel.c @@ -850,6 +850,15 @@ nautilus_sidebar_drag_data_received (GtkWidget *widget, GdkDragContext *context, } } +static void +view_loaded_callback (NautilusViewFrame *view_frame, gpointer user_data) +{ + NautilusSidebar *sidebar; + + sidebar = NAUTILUS_SIDEBAR (user_data); + nautilus_sidebar_tabs_connect_view (sidebar->details->sidebar_tabs, GTK_WIDGET (view_frame)); +} + /* add a new panel to the sidebar */ void nautilus_sidebar_add_panel (NautilusSidebar *sidebar, NautilusViewFrame *panel) @@ -867,6 +876,8 @@ nautilus_sidebar_add_panel (NautilusSidebar *sidebar, NautilusViewFrame *panel) gtk_widget_show (label); + gtk_signal_connect (GTK_OBJECT (panel), "view_loaded", view_loaded_callback, sidebar); + gtk_notebook_append_page (GTK_NOTEBOOK (sidebar->details->notebook), GTK_WIDGET (panel), label); page_num = gtk_notebook_page_num (GTK_NOTEBOOK (sidebar->details->notebook), diff --git a/src/nautilus-sidebar-tabs.c b/src/nautilus-sidebar-tabs.c index 0d8ea539c..3ade8eb41 100644 --- a/src/nautilus-sidebar-tabs.c +++ b/src/nautilus-sidebar-tabs.c @@ -24,6 +24,13 @@ #include #include "nautilus-sidebar-tabs.h" +#include "nautilus-view-frame.h" + +#include +#include +#include +#include +#include #include #include @@ -75,7 +82,10 @@ typedef struct { gboolean visible; gboolean prelit; char *tab_text; + char *indicator_pixbuf_name; + GdkPixbuf *indicator_pixbuf; int notebook_page; + Bonobo_EventSource_ListenerId listener_id; GtkWidget *tab_view; GdkRectangle tab_rect; } TabItem; @@ -314,7 +324,31 @@ nautilus_sidebar_tabs_new (void) static void tab_item_destroy (TabItem *item) { + CORBA_Environment ev; + Bonobo_PropertyBag property_bag; + Bonobo_Control control; + g_free (item->tab_text); + g_free (item->indicator_pixbuf_name); + + if (item->indicator_pixbuf != NULL) { + gdk_pixbuf_unref (item->indicator_pixbuf); + } + + if (item->listener_id != 0) { + CORBA_exception_init (&ev); + control = nautilus_view_frame_get_control (NAUTILUS_VIEW_FRAME (item->tab_view)); + if (control != NULL) { + property_bag = Bonobo_Control_getProperties (control, &ev); + if (!BONOBO_EX (&ev) && property_bag != CORBA_OBJECT_NIL) { + bonobo_event_source_client_remove_listener + (property_bag, + item->listener_id, + &ev); + bonobo_object_release_unref (property_bag, &ev); + } + } + } g_free (item); } @@ -509,13 +543,41 @@ nautilus_sidebar_tabs_size_allocate(GtkWidget *widget, GtkAllocation *allocation } } +/* convenience routine to composite an image with the proper clipping */ +static void +pixbuf_composite (GdkPixbuf *source, GdkPixbuf *destination, int x_offset, int y_offset, int alpha) +{ + int source_width, source_height, dest_width, dest_height; + double float_x_offset, float_y_offset; + + source_width = gdk_pixbuf_get_width (source); + source_height = gdk_pixbuf_get_height (source); + dest_width = gdk_pixbuf_get_width (destination); + dest_height = gdk_pixbuf_get_height (destination); + + float_x_offset = x_offset; + float_y_offset = y_offset; + + /* clip to the destination size */ + if ((x_offset + source_width) > dest_width) { + source_width = dest_width - x_offset; + } + if ((y_offset + source_height) > dest_height) { + source_height = dest_height - y_offset; + } + + gdk_pixbuf_composite (source, destination, x_offset, y_offset, source_width, source_height, + float_x_offset, float_y_offset, 1.0, 1.0, GDK_PIXBUF_ALPHA_BILEVEL, alpha); +} + /* draw a single tab using the default, non-themed approach */ static int -draw_one_tab_plain (NautilusSidebarTabs *sidebar_tabs, GdkGC *gc, - char *tab_name, int x, int y, gboolean prelight_flag, GdkRectangle *tab_rect) +draw_one_tab_plain (NautilusSidebarTabs *sidebar_tabs, GdkGC *gc, char *tab_name, + GdkPixbuf *indicator_pixbuf, int x, int y, gboolean prelight_flag, GdkRectangle *tab_rect) { int tab_bottom; int tab_right; + int indicator_width; NautilusDimensions name_dimensions; int total_width; GtkWidget *widget; @@ -524,13 +586,19 @@ draw_one_tab_plain (NautilusSidebarTabs *sidebar_tabs, GdkGC *gc, g_assert (NAUTILUS_IS_SIDEBAR_TABS (sidebar_tabs)); + if (indicator_pixbuf != NULL) { + indicator_width = gdk_pixbuf_get_width (indicator_pixbuf); + } else { + indicator_width = 0; + } + /* measure the name and compute the bounding box */ name_dimensions = nautilus_scalable_font_measure_text (sidebar_tabs->details->tab_font, sidebar_tabs->details->font_size, tab_name, strlen (tab_name)); - total_width = name_dimensions.width + 2 * TAB_MARGIN; + total_width = name_dimensions.width + indicator_width + 2 * TAB_MARGIN; widget = GTK_WIDGET (sidebar_tabs); @@ -565,12 +633,17 @@ draw_one_tab_plain (NautilusSidebarTabs *sidebar_tabs, GdkGC *gc, gdk_draw_line(widget->window, gc, x + 2, y + 2, x + 2, y + sidebar_tabs->details->tab_height - 1); /* allocate the pixbuf and fill it with the background color */ - temp_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, name_dimensions.width + 1, name_dimensions.height + 1); + temp_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, name_dimensions.width + indicator_width + 1, name_dimensions.height + 1); nautilus_gdk_pixbuf_fill_rectangle_with_color (temp_pixbuf, NULL, nautilus_gdk_color_to_rgb (foreground_color)); + + /* draw the indicator if necessary */ + if (indicator_pixbuf) { + pixbuf_composite (indicator_pixbuf, temp_pixbuf, 0, 0, 255); + } /* draw the name into the pixbuf using anti-aliased text */ nautilus_scalable_font_draw_text (sidebar_tabs->details->tab_font, temp_pixbuf, - 1, 1, + 1 + indicator_width, 1, NULL, sidebar_tabs->details->font_size, tab_name, strlen (tab_name), @@ -578,7 +651,7 @@ draw_one_tab_plain (NautilusSidebarTabs *sidebar_tabs, GdkGC *gc, NAUTILUS_OPACITY_FULLY_OPAQUE); nautilus_scalable_font_draw_text (sidebar_tabs->details->tab_font, temp_pixbuf, - 0, 0, + indicator_width, 0, NULL, sidebar_tabs->details->font_size, tab_name, strlen (tab_name), @@ -591,7 +664,7 @@ draw_one_tab_plain (NautilusSidebarTabs *sidebar_tabs, GdkGC *gc, widget->window, 0, 0, x + TAB_MARGIN, y + 5, - name_dimensions.width + 1, name_dimensions.height + 1, + name_dimensions.width + indicator_width + 1, name_dimensions.height + 1, GDK_PIXBUF_ALPHA_BILEVEL, 128, GDK_RGB_DITHER_MAX, 0, 0); @@ -601,12 +674,12 @@ draw_one_tab_plain (NautilusSidebarTabs *sidebar_tabs, GdkGC *gc, /* draw the bottom lines */ tab_bottom = y + sidebar_tabs->details->tab_height - 1; gdk_gc_set_foreground (gc, &sidebar_tabs->details->line_color); - tab_right = x + 2*TAB_MARGIN + name_dimensions.width; + tab_right = x + 2*TAB_MARGIN + name_dimensions.width + indicator_width; gdk_gc_set_foreground (gc, &sidebar_tabs->details->line_color); gdk_draw_line(widget->window, gc, tab_right, tab_bottom, widget->parent->allocation.width, tab_bottom); gdk_draw_line(widget->window, gc, 0, tab_bottom, x, tab_bottom); - return name_dimensions.width + 2 * TAB_MARGIN; + return name_dimensions.width + indicator_width + 2 * TAB_MARGIN; } /* utility to draw a single tab piece into a pixbuf */ @@ -668,7 +741,7 @@ draw_tab_piece_aa (NautilusSidebarTabs *sidebar_tabs, GdkPixbuf *dest_pixbuf, in draw the right edge of the tab, as we don't have enough info about the next tab to do it properly at this time. We draw into an offscreen pixbuf so we can get nice anti-aliased text */ static int -draw_one_tab_themed (NautilusSidebarTabs *sidebar_tabs, GdkPixbuf *tab_pixbuf, +draw_one_tab_themed (NautilusSidebarTabs *sidebar_tabs, GdkPixbuf *tab_pixbuf, GdkPixbuf *indicator_pixbuf, char *tab_name, int x, int y, gboolean prelight_flag, gboolean first_flag, gboolean prev_invisible, int text_h_offset, GdkRectangle *tab_rect) @@ -681,6 +754,13 @@ draw_one_tab_themed (NautilusSidebarTabs *sidebar_tabs, GdkPixbuf *tab_pixbuf, int highlight_offset; int text_x; int text_y; + int indicator_width; + + if (indicator_pixbuf != NULL) { + indicator_width = gdk_pixbuf_get_width (indicator_pixbuf); + } else { + indicator_width = 0; + } left_width = 0; @@ -708,7 +788,7 @@ draw_one_tab_themed (NautilusSidebarTabs *sidebar_tabs, GdkPixbuf *tab_pixbuf, /* draw the middle portion in a loop */ text_x_pos = current_pos; - right_edge_pos = current_pos + name_dimensions.width; + right_edge_pos = current_pos + name_dimensions.width + indicator_width; while (current_pos < right_edge_pos) { piece_width = draw_tab_piece_aa (sidebar_tabs, tab_pixbuf, current_pos, y - widget->allocation.y, right_edge_pos, TAB_NORMAL_FILL + highlight_offset); @@ -724,6 +804,12 @@ draw_one_tab_themed (NautilusSidebarTabs *sidebar_tabs, GdkPixbuf *tab_pixbuf, /* make sure we can at least draw some of it */ if (text_x < gdk_pixbuf_get_width (tab_pixbuf)) { + if (indicator_pixbuf) { + + pixbuf_composite (indicator_pixbuf, tab_pixbuf, text_x, text_y, 255); + text_x += indicator_width; + } + nautilus_scalable_font_draw_text (sidebar_tabs->details->tab_font, tab_pixbuf, text_x, text_y, NULL, @@ -747,12 +833,12 @@ draw_one_tab_themed (NautilusSidebarTabs *sidebar_tabs, GdkPixbuf *tab_pixbuf, if (tab_rect) { tab_rect->x = x; tab_rect->y = y; - tab_rect->width = current_pos - x; + tab_rect->width = current_pos - x + indicator_width; tab_rect->height = sidebar_tabs->details->tab_height; } /* return the total tab width */ - tab_width = left_width + name_dimensions.width; + tab_width = left_width + name_dimensions.width + indicator_width; return tab_width; } @@ -777,12 +863,18 @@ get_text_offset (void) static int get_tab_width (NautilusSidebarTabs *sidebar_tabs, TabItem *this_tab, gboolean is_themed, gboolean first_flag) { - int edge_width; + int edge_width, indicator_width; NautilusDimensions name_dimensions; if (this_tab == NULL) return 0; + if (this_tab->indicator_pixbuf != NULL) { + indicator_width = gdk_pixbuf_get_width (this_tab->indicator_pixbuf); + } else { + indicator_width = 0; + } + if (is_themed) { if (first_flag) { edge_width = gdk_pixbuf_get_width (sidebar_tabs->details->tab_piece_images[TAB_NORMAL_LEFT]); @@ -799,7 +891,7 @@ get_tab_width (NautilusSidebarTabs *sidebar_tabs, TabItem *this_tab, gboolean is edge_width = 2 * TAB_MARGIN; name_dimensions.width = gdk_string_width (GTK_WIDGET (sidebar_tabs)->style->font, this_tab->tab_text); } - return name_dimensions.width + edge_width; + return name_dimensions.width + edge_width + indicator_width; } /* fill the canvas buffer with a tiled pixmap */ @@ -955,12 +1047,12 @@ draw_or_layout_all_tabs (NautilusSidebarTabs *sidebar_tabs, gboolean layout_only prev_invisible = prev_item && !prev_item->visible; if (is_themed) { g_assert (tab_pixbuf != NULL); - draw_one_tab_themed (sidebar_tabs, tab_pixbuf, this_item->tab_text, x_pos, y_pos, + draw_one_tab_themed (sidebar_tabs, tab_pixbuf, this_item->indicator_pixbuf, this_item->tab_text, x_pos, y_pos, this_item->prelit, first_flag, prev_invisible, text_h_offset, &this_item->tab_rect); } else { g_assert (temp_gc != NULL); - draw_one_tab_plain (sidebar_tabs, temp_gc, this_item->tab_text, + draw_one_tab_plain (sidebar_tabs, temp_gc, this_item->tab_text, this_item->indicator_pixbuf, x_pos, y_pos, this_item->prelit, &this_item->tab_rect); } } @@ -1176,7 +1268,7 @@ nautilus_sidebar_tabs_expose (GtkWidget *widget, GdkEventExpose *event) tab_height = gdk_pixbuf_get_height (sidebar_tabs->details->tab_piece_images[0]); pixbuf = allocate_cleared_pixbuf (widget->allocation.width, tab_height); - tab_width = draw_one_tab_themed (sidebar_tabs, pixbuf, sidebar_tabs->details->title, 0, 0, + tab_width = draw_one_tab_themed (sidebar_tabs, pixbuf, NULL, sidebar_tabs->details->title, 0, 0, sidebar_tabs->details->title_prelit, TRUE, FALSE, text_offset, &sidebar_tabs->details->title_rect); /* draw the right edge */ draw_tab_piece_aa (sidebar_tabs, pixbuf, tab_width, 0, -1, @@ -1194,7 +1286,7 @@ nautilus_sidebar_tabs_expose (GtkWidget *widget, GdkEventExpose *event) gdk_pixbuf_unref (pixbuf); } else { - draw_one_tab_plain (sidebar_tabs, temp_gc, sidebar_tabs->details->title, + draw_one_tab_plain (sidebar_tabs, temp_gc, sidebar_tabs->details->title, NULL, x_pos + TITLE_TAB_OFFSET, y_pos, sidebar_tabs->details->title_prelit, &sidebar_tabs->details->title_rect); } gdk_gc_unref (temp_gc); @@ -1208,6 +1300,137 @@ nautilus_sidebar_tabs_expose (GtkWidget *widget, GdkEventExpose *event) return FALSE; } +/* update the indicator image for the passed in tab */ +static void +nautilus_sidebar_tabs_update_tab_item (NautilusSidebarTabs *sidebar_tabs, TabItem *tab_item) +{ + CORBA_Environment ev; + Bonobo_Control control; + Bonobo_PropertyBag property_bag; + char *tab_image_name, *image_path; + + /* fetch indicator icon through the bonobo propertybag mechanism */ + CORBA_exception_init (&ev); + control = nautilus_view_frame_get_control (NAUTILUS_VIEW_FRAME (tab_item->tab_view)); + if (control != NULL) { + property_bag = Bonobo_Control_getProperties (control, &ev); + if (property_bag != NULL) { + tab_image_name = bonobo_property_bag_client_get_value_string (property_bag, "tab_image", &ev); + bonobo_object_release_unref (property_bag, &ev); + + /* see if the indicator icon changed; if so, fetch the new one */ + if (nautilus_strcmp (tab_image_name, tab_item->indicator_pixbuf_name) != 0) { + g_free (tab_item->indicator_pixbuf_name); + + if (tab_item->indicator_pixbuf != NULL) { + gdk_pixbuf_unref (tab_item->indicator_pixbuf); + tab_item->indicator_pixbuf = NULL; + } + + if (tab_image_name != NULL) { + tab_item->indicator_pixbuf_name = g_strdup (tab_image_name); + image_path = nautilus_theme_get_image_path (tab_image_name); + if (image_path != NULL) { + tab_item->indicator_pixbuf = gdk_pixbuf_new_from_file (image_path); + g_free (image_path); + } + } else { + tab_item->indicator_pixbuf_name = NULL; + if (tab_item->indicator_pixbuf != NULL) { + gdk_pixbuf_unref (tab_item->indicator_pixbuf); + tab_item->indicator_pixbuf = NULL; + } + } + + recalculate_size (sidebar_tabs); + gtk_widget_queue_draw (GTK_WIDGET (sidebar_tabs)); + } + g_free (tab_image_name); + } + } + CORBA_exception_free (&ev); + +} + +static TabItem * +get_tab_item_from_view (NautilusSidebarTabs *sidebar_tabs, GtkWidget *view) +{ + GList *iterator; + + for (iterator = sidebar_tabs->details->tab_items; iterator != NULL; iterator = iterator->next) { + TabItem *tab_item = iterator->data; + if (tab_item->tab_view == view) { + return tab_item; + } + } + return NULL; +} + +/* check all of the tabs to see if their indicator pixmaps are ready for updating */ +static void +nautilus_sidebar_tabs_update_all_indicators (NautilusSidebarTabs *sidebar_tabs) +{ + GList *iterator; + + for (iterator = sidebar_tabs->details->tab_items; iterator != NULL; iterator = iterator->next) { + TabItem *tab_item = iterator->data; + nautilus_sidebar_tabs_update_tab_item (sidebar_tabs, tab_item); + } +} + +/* check all of the tabs to see if their indicator pixmaps are ready for updating */ +static void +nautilus_sidebar_tabs_update_indicator (NautilusSidebarTabs *sidebar_tabs, GtkWidget *view) +{ + GList *iterator; + + for (iterator = sidebar_tabs->details->tab_items; iterator != NULL; iterator = iterator->next) { + TabItem *tab_item = iterator->data; + if (tab_item->tab_view == view) { + nautilus_sidebar_tabs_update_tab_item (sidebar_tabs, tab_item); + break; + } + } +} + +static void +tab_indicator_changed_callback (BonoboListener *listener, + char *event_name, + CORBA_any *arg, + CORBA_Environment *ev, + gpointer callback_data) +{ + NautilusSidebarTabs *sidebar_tabs; + sidebar_tabs = NAUTILUS_SIDEBAR_TABS (callback_data); + nautilus_sidebar_tabs_update_all_indicators (sidebar_tabs); +} + +/* listen for changes on the tab_image property */ +void +nautilus_sidebar_tabs_connect_view (NautilusSidebarTabs *sidebar_tabs, GtkWidget *view) +{ + CORBA_Environment ev; + Bonobo_PropertyBag property_bag; + TabItem *tab_item; + + tab_item = get_tab_item_from_view (sidebar_tabs, view); + if (tab_item == NULL) { + return; + } + + CORBA_exception_init (&ev); + property_bag = Bonobo_Control_getProperties (nautilus_view_frame_get_control (NAUTILUS_VIEW_FRAME (view)), &ev); + if (!BONOBO_EX (&ev) && property_bag != CORBA_OBJECT_NIL) { + tab_item->listener_id = bonobo_event_source_client_add_listener + (property_bag, tab_indicator_changed_callback, + "Bonobo/Property:change:tab_image", NULL, sidebar_tabs); + bonobo_object_release_unref (property_bag, &ev); + } + CORBA_exception_free (&ev); + + nautilus_sidebar_tabs_update_indicator (sidebar_tabs, view); +} + /* add a new tab entry, return TRUE if we succeed */ gboolean diff --git a/src/nautilus-sidebar-tabs.h b/src/nautilus-sidebar-tabs.h index 89731434b..a15b8f14c 100644 --- a/src/nautilus-sidebar-tabs.h +++ b/src/nautilus-sidebar-tabs.h @@ -57,6 +57,9 @@ gboolean nautilus_sidebar_tabs_add_view (NautilusSidebarTabs *sid const char *name, GtkWidget *new_view, int page_number); +void nautilus_sidebar_tabs_connect_view (NautilusSidebarTabs *sidebar_tabs, + GtkWidget *view); + char * nautilus_sidebar_tabs_get_title_from_index (NautilusSidebarTabs *sidebar_tabs, int which_tab); int nautilus_sidebar_tabs_hit_test (NautilusSidebarTabs *sidebar_tabs, diff --git a/src/nautilus-sidebar.c b/src/nautilus-sidebar.c index 159301b46..3a302bedd 100644 --- a/src/nautilus-sidebar.c +++ b/src/nautilus-sidebar.c @@ -850,6 +850,15 @@ nautilus_sidebar_drag_data_received (GtkWidget *widget, GdkDragContext *context, } } +static void +view_loaded_callback (NautilusViewFrame *view_frame, gpointer user_data) +{ + NautilusSidebar *sidebar; + + sidebar = NAUTILUS_SIDEBAR (user_data); + nautilus_sidebar_tabs_connect_view (sidebar->details->sidebar_tabs, GTK_WIDGET (view_frame)); +} + /* add a new panel to the sidebar */ void nautilus_sidebar_add_panel (NautilusSidebar *sidebar, NautilusViewFrame *panel) @@ -867,6 +876,8 @@ nautilus_sidebar_add_panel (NautilusSidebar *sidebar, NautilusViewFrame *panel) gtk_widget_show (label); + gtk_signal_connect (GTK_OBJECT (panel), "view_loaded", view_loaded_callback, sidebar); + gtk_notebook_append_page (GTK_NOTEBOOK (sidebar->details->notebook), GTK_WIDGET (panel), label); page_num = gtk_notebook_page_num (GTK_NOTEBOOK (sidebar->details->notebook), diff --git a/src/nautilus-view-frame.c b/src/nautilus-view-frame.c index 209ca3a66..4b67123c0 100644 --- a/src/nautilus-view-frame.c +++ b/src/nautilus-view-frame.c @@ -1271,6 +1271,17 @@ nautilus_view_frame_report_load_failed (NautilusViewFrame *view) view_frame_failed (view); } +/* return the Bonobo_Control CORBA object associated with the view frame */ +Bonobo_Control +nautilus_view_frame_get_control (NautilusViewFrame *view) +{ + if (view->details->control_frame == NULL) { + return NULL; + } + + return bonobo_control_frame_get_control (view->details->control_frame); +} + void nautilus_view_frame_go_back (NautilusViewFrame *view) { diff --git a/src/nautilus-view-frame.h b/src/nautilus-view-frame.h index 45ef8328f..14e49047a 100644 --- a/src/nautilus-view-frame.h +++ b/src/nautilus-view-frame.h @@ -99,6 +99,7 @@ typedef struct { GtkType nautilus_view_frame_get_type (void); NautilusViewFrame *nautilus_view_frame_new (BonoboUIContainer *ui_container, NautilusUndoManager *undo_manager); +Bonobo_Control nautilus_view_frame_get_control (NautilusViewFrame *view); /* connecting to a Nautilus:View */ void nautilus_view_frame_load_view (NautilusViewFrame *view, -- cgit v1.2.1