Themability of icon size



Hello:

Owen asked me to post an explanation of this issue to the list some time
ago; apologies for being so far behind ;-)

Currently in gtk+ there is no way to override the default icon sizes for
the whole set, one can only replace individual icons which, if not
wildcarded, will be rendered without rescaling.  However for
accessibility reasons it is necessary to provide larger versions of
all icons for some users, and it is generally useful and desirable to
allow themes to customize the sizes associated with logical icons types
such as "dialog", "menu", etc.

Bugzilla bug 70648 covers this problem (it was until recently somewhat
misleadingly named "GTK+ stock icons can't be easily themed", it's now
named "GTK+ stock icon sizes cannot be themed").  Bug 74274 filed by Nat
also depends on this feature being fixed.

This bug is currently marked priority "LOW" but it's actually a stopper
for accessibility.

With the existing codebase the best one can do it to replace the entire
icon set, for *all* icon sizes, with icons of the desired sizes, and
hope that apps which use icons don't use wildcarding (since wildcarded
icons get sized to the hard-coded size defaults).  In fact, we now have
some
nice alternate icon sets for accessibility thanks to tigert and jimmac,
but can't use them without patching gtk+, or resampling the icons for
all sizes and specifying each separately (which would mean nearly 500 
image files, not counting icons used by core apps but no in the stock
icon set).

The logical approach is to provide a gtksettings property to change
this; Havoc and Owen have expressed a preference for a single setting
string that indicates sizes with delimiters, for instance:

gtk-icon-sizes = "dnd 64,64:menu 32,32:large-toolbar 48,48:small-toolbar
48,48:button 32,32:dialog 64,64"

There has been a patch in bugzilla for this bug bitrotting for some
time; it has one known problem however that, in order to work
consistently with the default icon set, it has to turn on resizing of
all icons, even those that aren't wildcarded.  This is a behavioral
change that may not be acceptable.

We can use the "high contrast, large size" icon set without the
offending behavioral change above, by reverting a single line of the
patch.  However if we do that it means that any icons that are not
wildcarded won't get resized either, which means that the icons which
gtk+ installs using add_sized_with_fallback() will remain unscaled.  Not
a problem for the default theme, but inconsistent enough that it might
be a problem if a user decides to change the icon sizes without
replacing the stock icons themselves.

An better solution would allow specifying "resizeable" icons that
aren't wildcarded, but that may have to wait for 2.X unless a good (and
implementable) solution is proposed soon.

My suggestion is that if we don't come up with a solution that 
addresses all of these issues soon, we should commit the patch (without
the behavioral change) so that an RC-file based theme can use alternate
(size-wildcarded) icon sets.  The primary limitation that we'd then be
left with would be fact that gtk+ default icon sizes would become
slightly inconsistent if a user respecified the icon sizes (since only
wildcarded stock icons would be resized).

Of course a specialized engine could be written to implement any
resizing policy, but it would mean that only one theme engine was 
"accessible", and it probably would not be the default for most 
distributions.  An rc-file-based solution like the one in the patch 
would work for all theme engines that used RC files and did not already 
override GTK+'s default icon rendering behavior.

I attach the modified patch, which does not change the existing behavior
of GTK+ or themes unless an RC file respecifying the icon sizes is in
use; it also does not change the behavior of non-wildcarded icons.  If 
anyone wants the tarfile with the new HighContrastLargePrint
theme (which includes the new icon image maps, which is why I did not
post it to the list), please ask and I will send it.

best regards,

Bill



Index: gtk+/gtk/gtkiconfactory.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkiconfactory.c,v
retrieving revision 1.39
diff -u -r1.39 gtkiconfactory.c
--- gtk+/gtk/gtkiconfactory.c	18 Apr 2002 22:04:43 -0000	1.39
+++ gtk+/gtk/gtkiconfactory.c	30 May 2002 07:40:48 -0000
@@ -28,6 +28,7 @@
 #include "stock-icons/gtkstockpixbufs.h"
 #include "gtkstock.h"
 #include "gtkintl.h"
+#include "gtksettings.h"
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
@@ -825,14 +826,85 @@
 static gint      icon_sizes_allocated = 0;
 static gint      icon_sizes_used = 0;
 
+/**
+ * This method reads the gtk-icon-sizes property and
+ *    parses it to determine the default sizes to use for
+ *    gtk icons, both predefined named sizes, and new
+ *    named sizes.  If an icon size name does not appear
+ *    in the style property, the dimensions of that named
+ *    icon size are unchanged.
+ **/
+static void
+restyle_icon_dimensions_from_property (IconSize *sizes)
+{
+#define MAX_ICON_SIZES 24
+  gint i;
+  gint n = icon_sizes_used;
+  gchar *icon_size_prop = NULL;
+  gchar **size_strings;
+  GtkSettings *settings = gtk_settings_get_default ();
+  g_object_get (G_OBJECT (settings), "gtk-icon-sizes", &icon_size_prop, NULL);
+  if (icon_size_prop != NULL)
+    {
+      size_strings = g_strsplit (icon_size_prop, ":", MAX_ICON_SIZES);
+#undef MAX_ICON_SIZES  
+  /* parse by name */
+      i=0;
+      while (size_strings[i])
+        {
+	  gint j;
+	  gint k;
+	  gchar *name = NULL;
+	  gchar **substrings;
+	  substrings = g_strsplit (size_strings[i], " ", 2);
+	  j = 0;
+	  do
+	    {
+	      ++j;
+	      if (j == n) break;
+              if (!strncmp (sizes[j].name, "gtk-", 4))
+	        name = sizes[j].name+4;
+	      else
+	        name = sizes[j].name;
+	    } while (!name || strcmp (substrings[0], name)); 
+          if (j < n)
+            {
+	      gchar **istrings = g_strsplit (substrings[1], ",", 2);	    
+	      sizes[j].width = atoi (istrings [0]);	
+	      sizes[j].height = atoi (istrings [1]);
+	      g_message ("icon %s size set to %d\n", sizes[j].name,
+			 sizes[j].width);
+	      if (istrings[0]) g_free (istrings[0]);
+	      if (istrings[1]) g_free (istrings[1]);
+	      if (istrings) g_free (istrings);
+            }
+          k = 0;
+	  while (substrings[k])
+	    {
+              g_free (substrings[k]);
+	      ++k;
+	    }
+	  g_free (substrings);
+	  ++i;
+	}
+      i = 0;
+      while (size_strings[i])
+        {
+          g_free (size_strings[i]);
+	  ++i;
+	}
+      g_free (size_strings);
+      _gtk_icon_set_invalidate_caches ();
+    }
+}
+
 static void
 init_icon_sizes (void)
 {
   if (icon_sizes == NULL)
     {
-#define NUM_BUILTIN_SIZES 7
       gint i;
-
+#define NUM_BUILTIN_SIZES 7
       icon_aliases = g_hash_table_new (g_str_hash, g_str_equal);
       
       icon_sizes = g_new (IconSize, NUM_BUILTIN_SIZES);
@@ -890,8 +962,8 @@
           
           ++i;
         }
-      
 #undef NUM_BUILTIN_SIZES
+      restyle_icon_dimensions_from_property (icon_sizes);
     }
 }
 
Index: gtk+/gtk/gtkrc.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkrc.c,v
retrieving revision 1.124
diff -u -r1.124 gtkrc.c
--- gtk+/gtk/gtkrc.c	28 May 2002 22:23:35 -0000	1.124
+++ gtk+/gtk/gtkrc.c	30 May 2002 07:40:53 -0000
@@ -1688,7 +1688,6 @@
 	  const gchar *path;
           gchar *path_reversed;
 	  guint path_length;
-
 	  path = g_type_name (type);
 	  path_length = strlen (path);
 	  path_reversed = g_strdup (path);
Index: gtk+/gtk/gtksettings.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtksettings.c,v
retrieving revision 1.27
diff -u -r1.27 gtksettings.c
--- gtk+/gtk/gtksettings.c	29 Apr 2002 22:53:37 -0000	1.27
+++ gtk+/gtk/gtksettings.c	30 May 2002 07:40:54 -0000
@@ -31,7 +31,8 @@
   PROP_KEY_THEME_NAME,
   PROP_MENU_BAR_ACCEL,
   PROP_DND_DRAG_THRESHOLD,
-  PROP_FONT_NAME
+  PROP_FONT_NAME,
+  PROP_ICON_SIZES
 };
 
 
@@ -213,6 +214,15 @@
 								  G_PARAM_READWRITE),
                                              NULL);
   g_assert (result == PROP_FONT_NAME);
+ 
+  result = settings_install_property_parser (class,
+                                             g_param_spec_string ("gtk-icon-sizes",
+								   _("Icon Sized"),
+								   _("Size in pixels of Standard Icon Types (semicolon delimited list)"),
+								  "x",
+								  G_PARAM_READWRITE),
+                                             NULL);
+  g_assert (result == PROP_ICON_SIZES);
  
 }
 
Index: gtk+/gtk/gtkstyle.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkstyle.c,v
retrieving revision 1.117
diff -u -r1.117 gtkstyle.c
--- gtk+/gtk/gtkstyle.c	29 Apr 2002 22:53:37 -0000	1.117
+++ gtk+/gtk/gtkstyle.c	30 May 2002 07:40:59 -0000
@@ -1963,7 +1963,7 @@
       return NULL;
     }
 
-  /* If the size was wildcarded, and we're allowed to scale, then scale; otherwise,
+  /* If we're allowed to scale, then scale; otherwise,
    * leave it alone.
    */
   if (size != (GtkIconSize)-1 && gtk_icon_source_get_size_wildcarded (source))


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]