A proposal for units in GTK+



One problem we have in GTK+ is that all of our packing is tied to pixel
sizes.  This is awkward for a number of reasons.  It results in many
programmers picking a variety of arbitrary sizes for their interface.
The resulting UI may look goon in a particular theme/font combination,
but is not necessarily going to look good in all.  Additionally, given
that people are thinking about UI's that need to appear on both very
small screens (such as PDA's) and very large screens (eg. video walls),
the need for a more flexible packing scheme seems more clear.  Even the
HIG can't escape this -- it suggests pixel sizes in alerts, which
clearly don't work well with a 6 pixel or 30 pixel tall font[1].

http://developer.gnome.org/projects/gup/hig/1.0/windows.html#alert-spacing

A nicer solution would be to be able to give sizes to widgets in units
other than pixels.  For example, being able to pack buttons one 'em'
apart would be one nice solution.

PROPOSAL:

As a rough proposal, I would like to add two additional classes of
possible units to GTK+ to go along with the current pixel-based values
we use.  They would be font based (such as ems), and physically based
(such as points, inches).  The addition of these two units would
overlay the current box system.  As a rough example, we could do
something like:

  box = gtk_vbox_new (FALSE, GTK_UNIT_EM (2));
  gtk_container_set_border_width (container, GTK_UNIT_CM (5));

We can also provide a variety of conversion macros:

GTK_UNIT_INCH
GTK_UNIT_MM
GTK_UNIT_POINT
GTK_UNIT_TWIP
GTK_UNIT_EN
GTK_UNIT_EM
GTK_UNIT_TO_PIXEL
etc.

As a complication, widgets need to know what units were passed in.  They
will need to update font-based sizes when the font size changes, and
will update physical units when the resolution or DPI changes.  After
talking to Owen for a while, we felt like one of the easiest ways to do
this was by setting the high bits on ints that we pass in.  For example,
an integer with the top bit set would be in a physical unit like a
twip[2], and one with the second highest bit set would be a font based
unit.

The primary use of these bits would be to let us store the value and
unit pair.  Widgets would convert the value to pixels before doing any
calculations, and statements like 'GTK_UNIT_INCH (1) + GTK_UNIT_EM(4)'
are clearly nonsensical.  Signals like size_request and size_allocate
would remain unchanged.  Additionally, all values will remain integers.
We will just pick a small enough measure that we should have fine
grained enough support for sizing.

Over all, I think doing something like this would bring a lot of
positive benefits to GTK+, and a lot of nice flexibility to the layout
of interfaces.

Some other random thoughts:

 * This involves a lot of changes to a lot of widgets and has the
   potential to destabilize GTK+.  It also makes writing a new widget
   that much harder.  It could also break existing code that's expecting
   a reasonable value for a size.  We might require the app 'turn the
   feature on' to use it, then.

 * Also, some widgets won't handle the change gracefully.  For example,
   the GtkContainer structure only allocates 16 bits for the border
   width, as does GtkBox with regard to its spacing.  We can mirror
   these values in pixel sizes, and keep the real size in private data.
   It might be confusing to someone looking at the actual values though.

 * I don't know what effect on accessibility will be, though I expect it
   will be positive in the long run.  We'll have to make sure that the
   current stuff isn't hurt.  Additionally, it will interact kind of
   akwardly with the current a11y stuff, in that current large-print
   style themes are all pixel based.

 * Physical units are probably problematic in UI's and should be used
   sparingly.  They are very unpredictable, as the screen could possibly
   change size dramatically.

 * It might be nice to introduce a GtkSpacing widget as a means of
   adding blank space to an area.

I'd appreciate any thoughts or comments.

Thanks,
-Jonathan

[1] I'm well aware the HIG authors are unhappy about this.  Sorry to
pick on them a little.
[2] TWIP == TWentIeth of a Point, or 1/1440 inch



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