Improve lxpanel_image_new_for_icon() API to follow panel icons size changes.
authorAndriy Grytsenko <andrej@rep.kiev.ua>
Sat, 15 Nov 2014 12:48:41 +0000 (14:48 +0200)
committerAndriy Grytsenko <andrej@rep.kiev.ua>
Sat, 15 Nov 2014 12:57:03 +0000 (14:57 +0200)
ChangeLog
plugins/menu.c
src/configurator.c
src/misc.c
src/misc.h

index 57084f8..685b2eb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -25,6 +25,8 @@
 * Added API panel_config_click_button_new() to configure mouse gestures.
 * Added "icon-size-changed" signal to LXPanel which is emitted when icons
     size in configuration dialog was changed.
+* Improved lxpanel_image_new_for_icon() API to follow panel icons size
+    changes, not only theme changes.
 
 0.7.2
 -------------------------------------------------------------------------
index b000563..c2fe8bc 100644 (file)
@@ -798,7 +798,7 @@ read_item(menup *m, config_setting_t *s)
         GtkWidget *img;
 
         tmp = expand_tilda(fname);
-        img = lxpanel_image_new_for_icon(tmp, m->iconsize);
+        img = lxpanel_image_new_for_icon(m->panel, tmp, m->iconsize, NULL);
         gtk_widget_show(img);
         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
         g_free(tmp);
@@ -934,7 +934,7 @@ read_submenu(menup *m, config_setting_t *s, gboolean as_item)
         if (fname) {
             GtkWidget *img;
             char *expanded = expand_tilda(fname);
-            img = lxpanel_image_new_for_icon(expanded, m->iconsize);
+            img = lxpanel_image_new_for_icon(m->panel, expanded, m->iconsize, NULL);
             gtk_widget_show(img);
             gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
             g_free(expanded);
index 49aec41..8394d10 100644 (file)
@@ -508,10 +508,13 @@ set_height_when_minimized(GtkSpinButton* spin, LXPanel* panel)
 }
 
 static void
-set_icon_size( GtkSpinButton* spin,  Panel* p  )
+set_icon_size(GtkSpinButton *spin, LXPanel *panel)
 {
+    Panel *p = panel->priv;
+
     p->icon_size = (int)gtk_spin_button_get_value(spin);
     panel_set_panel_configuration_changed(p);
+    _panel_emit_icon_size_changed(panel);
     UPDATE_GLOBAL_INT(p, "iconsize", p->icon_size);
 }
 
@@ -1129,7 +1132,7 @@ void panel_configure( LXPanel* panel, int sel_page )
     w = (GtkWidget*)gtk_builder_get_object( builder, "icon_size" );
     gtk_spin_button_set_range( GTK_SPIN_BUTTON(w), PANEL_HEIGHT_MIN, PANEL_HEIGHT_MAX );
     gtk_spin_button_set_value( GTK_SPIN_BUTTON(w), p->icon_size );
-    g_signal_connect( w, "value-changed", G_CALLBACK(set_icon_size), p );
+    g_signal_connect( w, "value-changed", G_CALLBACK(set_icon_size), panel );
 
     /* properties */
 
index c582910..285fc5e 100644 (file)
 typedef struct {
     FmIcon *icon;
     guint theme_changed_handler;
+    guint icon_changed_handler;
     GdkPixbuf* pixbuf;
     GdkPixbuf* hilight;
     gulong hicolor;
     gint size; /* desired size */
+    LXPanel *panel;
+    char *fallback;
 } ImgData;
 
 static GQuark img_data_id = 0;
 
-static void on_theme_changed(GtkIconTheme* theme, GtkWidget* img);
 static void _gtk_image_set_from_file_scaled(GtkWidget *img, ImgData *data);
 
 /* X11 data types */
@@ -922,15 +924,22 @@ static void img_data_free(ImgData * data)
     g_object_unref(data->icon);
     if (data->theme_changed_handler != 0)
         g_signal_handler_disconnect(gtk_icon_theme_get_default(), data->theme_changed_handler);
+    if (data->panel != NULL)
+    {
+        g_object_remove_weak_pointer(G_OBJECT(data->panel), (gpointer *)&data->panel);
+        g_signal_handler_disconnect(data->panel, data->icon_changed_handler);
+    }
     if (data->pixbuf != NULL)
         g_object_unref(data->pixbuf);
     if (data->hilight != NULL)
         g_object_unref(data->hilight);
+    if (data->fallback != NULL)
+        g_free(data->fallback);
     g_free(data);
 }
 
 /* Handler for "changed" signal in _gtk_image_new_from_file_scaled. */
-static void on_theme_changed(GtkIconTheme * theme, GtkWidget * img)
+static void on_theme_changed(GtkWidget * img, GObject * object)
 {
     ImgData * data = (ImgData *) g_object_get_qdata(G_OBJECT(img), img_data_id);
     _gtk_image_set_from_file_scaled(img, data);
@@ -987,6 +996,11 @@ void fb_button_set_from_file(GtkWidget * btn, const char * img_file, gint width,
 
 static void _gtk_image_set_from_file_scaled(GtkWidget * img, ImgData * data)
 {
+    gint size = data->size;
+
+    if (size < 0 && data->panel)
+        size = data->panel->priv->icon_size;
+
     if (data->pixbuf != NULL)
     {
         g_object_unref(data->pixbuf);
@@ -1001,15 +1015,26 @@ static void _gtk_image_set_from_file_scaled(GtkWidget * img, ImgData * data)
     }
 
     if (G_LIKELY(G_IS_THEMED_ICON(data->icon)))
-        data->pixbuf = fm_pixbuf_from_icon_with_fallback(data->icon, data->size,
-                                                         "application-x-executable");
+    {
+        const char *fallback = data->fallback;
+
+        if (fallback == NULL)
+            fallback = "application-x-executable";
+        data->pixbuf = fm_pixbuf_from_icon_with_fallback(data->icon, size, fallback);
+    }
     else
     {
         char *file = g_icon_to_string(fm_icon_get_gicon(data->icon));
-        data->pixbuf = gdk_pixbuf_new_from_file_at_scale(file, -1, data->size, TRUE, NULL);
+        data->pixbuf = gdk_pixbuf_new_from_file_at_scale(file, -1, size, TRUE, NULL);
         g_free(file);
     }
 
+    if (data->pixbuf == NULL && data->fallback != NULL && data->fallback[0] == '/')
+    {
+        /* if fallback was provided as a file path */
+        data->pixbuf = gdk_pixbuf_new_from_file_at_scale(data->fallback, -1, size, TRUE, NULL);
+    }
+
     if (data->pixbuf != NULL)
     {
         /* Set the pixbuf into the image widget. */
@@ -1023,21 +1048,32 @@ static void _gtk_image_set_from_file_scaled(GtkWidget * img, ImgData * data)
 }
 
 /* consumes reference on icon */
-static GtkWidget *_gtk_image_new_for_icon(FmIcon *icon, gint size)
+static GtkWidget *_gtk_image_new_for_icon(LXPanel *p, FmIcon *icon, gint size,
+                                          const char *fallback)
 {
     GtkWidget * img = gtk_image_new();
     ImgData * data = g_new0(ImgData, 1);
 
     data->icon = icon;
     data->size = size;
+    data->fallback = g_strdup(fallback);
     if (img_data_id == 0)
         img_data_id = g_quark_from_static_string("ImgData");
     g_object_set_qdata_full(G_OBJECT(img), img_data_id, data, (GDestroyNotify) img_data_free);
+    if (p && size < 0)
+    {
+        data->panel = p;
+        data->icon_changed_handler = g_signal_connect_swapped(p, "icon-size-changed",
+                                                G_CALLBACK(on_theme_changed), img);
+        /* it is in fact not required if image is panel child but let be safe */
+        g_object_add_weak_pointer(G_OBJECT(p), (gpointer *)&data->panel);
+    }
     _gtk_image_set_from_file_scaled(img, data);
     if (G_IS_THEMED_ICON(data->icon))
     {
         /* This image is loaded from icon theme.  Update the image if the icon theme is changed. */
-        data->theme_changed_handler = g_signal_connect(gtk_icon_theme_get_default(), "changed", G_CALLBACK(on_theme_changed), img);
+        data->theme_changed_handler = g_signal_connect_swapped(gtk_icon_theme_get_default(),
+                                                "changed", G_CALLBACK(on_theme_changed), img);
     }
     return img;
 }
@@ -1045,12 +1081,13 @@ static GtkWidget *_gtk_image_new_for_icon(FmIcon *icon, gint size)
 /* parameters width and keep_ratio are unused, kept for backward compatibility */
 GtkWidget * _gtk_image_new_from_file_scaled(const gchar * file, gint width, gint height, gboolean keep_ratio)
 {
-    return _gtk_image_new_for_icon(fm_icon_from_name(file), height);
+    return _gtk_image_new_for_icon(NULL, fm_icon_from_name(file), height, NULL);
 }
 
-GtkWidget *lxpanel_image_new_for_icon(const gchar *name, gint height)
+GtkWidget *lxpanel_image_new_for_icon(LXPanel *panel, const gchar *name,
+                                      gint height, const char *fallback)
 {
-    return _gtk_image_new_for_icon(fm_icon_from_name(name), height);
+    return _gtk_image_new_for_icon(panel, fm_icon_from_name(name), height, fallback);
 }
 
 void
@@ -1161,7 +1198,7 @@ static GtkWidget *_lxpanel_button_new_for_icon(LXPanel *panel, FmIcon *icon,
     gtk_container_set_border_width(GTK_CONTAINER(event_box), 0);
     gtk_widget_set_can_focus(event_box, FALSE);
 
-    GtkWidget * image = _gtk_image_new_for_icon(icon, size);
+    GtkWidget * image = _gtk_image_new_for_icon(panel, icon, size, NULL);
     gtk_misc_set_padding(GTK_MISC(image), 0, 0);
     gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.5);
     if (highlight_color != 0)
@@ -1198,15 +1235,15 @@ static GtkWidget *_lxpanel_button_new_for_icon(LXPanel *panel, FmIcon *icon,
 GtkWidget *lxpanel_button_new_for_icon(LXPanel *panel, const gchar *name, GdkColor *color, const gchar *label)
 {
     gulong highlight_color = color ? gcolor2rgb24(color) : PANEL_ICON_HIGHLIGHT;
-    return _lxpanel_button_new_for_icon(panel, fm_icon_from_name(name),
-                                        panel->priv->icon_size, highlight_color, label);
+    return _lxpanel_button_new_for_icon(panel, fm_icon_from_name(name), -1,
+                                        highlight_color, label);
 }
 
 GtkWidget *lxpanel_button_new_for_fm_icon(LXPanel *panel, FmIcon *icon, GdkColor *color, const gchar *label)
 {
     gulong highlight_color = color ? gcolor2rgb24(color) : PANEL_ICON_HIGHLIGHT;
-    return _lxpanel_button_new_for_icon(panel, g_object_ref(icon),
-                                        panel->priv->icon_size, highlight_color, label);
+    return _lxpanel_button_new_for_icon(panel, g_object_ref(icon), -1,
+                                        highlight_color, label);
 }
 
 /* parameters width and keep_ratio are unused, kept for backward compatibility */
index 9341e83..9e3f0ab 100644 (file)
@@ -142,11 +142,41 @@ gchar *expand_tilda(const gchar *file);
 
 void get_button_spacing(GtkRequisition *req, GtkContainer *parent, gchar *name);
 guint32 gcolor2rgb24(GdkColor *color);
+
+/**
+ * lxpanel_button_new_for_icon
+ * @panel: panel instance
+ * @name: icon name or path
+ * @color: (allow-none): hilight color for icon
+ * @label: (allow-none): optional label for button
+ *
+ * Creates new #GtkEventBox button which will follow theme and icon size
+ * changes on @panel. If icon name is not found in theme then fallback
+ * name "application-x-executable" will be used.
+ */
 GtkWidget *lxpanel_button_new_for_icon(LXPanel *panel, const gchar *name, GdkColor *color, const gchar *label);
 GtkWidget *lxpanel_button_new_for_fm_icon(LXPanel *panel, FmIcon *icon, GdkColor *color, const gchar *label);
+/**
+ * Deprecated since redudant.
+ */
 void lxpanel_button_set_icon(GtkWidget* btn, const gchar *name, gint size);
 void lxpanel_button_update_icon(GtkWidget* btn, FmIcon *icon, gint size);
-GtkWidget *lxpanel_image_new_for_icon(const gchar *name, gint height);
+
+/**
+ * lxpanel_image_new_for_icon
+ * @panel: (allow-none): panel instance
+ * @name: icon name or image path
+ * @height: image size
+ * @fallback: (allow-none): fallback image name or path
+ *
+ * Creates new #GtkImage which will follow theme if @name is a themed
+ * icon name. If @height is -1 then created image will also follow icon
+ * size changes on @panel. If icon not found in theme and @fallback is
+ * not %NULL then it will be used to load icon or image. Otherwise the
+ * "application-x-executable" will be used as fallback.
+ */
+GtkWidget *lxpanel_image_new_for_icon(LXPanel *panel, const gchar *name,
+                                      gint height, const gchar *fallback);
 
 G_END_DECLS