Wednesday, May 13, 2009

Changes with Button Glyphs

If you ever worked with the Lazarus IDE under windows (or just compiled an LCL application for windows) you were probably sickened by the glyphs on the dialog buttons since it is not native for windows. But on linux all is vice versa - most of the buttons have glyphs (and for example gtk and qt suggest an appropriate API to query "stock" images for buttons with various actions like save, open, apply, cancel, ...).
Therefore I needed a solution which can satisfy both windows and linux users. I started from the TBitBtn class which represents a button control with an image inside it. What I have added is a new property "GlyphShowMode" with 4 states:
  • gsmAlways
  • gsmNever
  • gsmApplication
  • gsmSystem
It is clear what the gsmAlways and gsmNever states are for: gsmAlways - to show the glyph always and this is how it worked before, gsmNever - to show the glyph never. Well, you may ask: What do I need the gsmNever state for, if I can use a TButton instead?. And I would answer: TBitBtn is not just a button with an image. It also has a Kind property which is very useful to set the ModalResult and Caption of a button :) But let's return to the other modes. gsmSystem can be used to show glyph depending on current OS - on MS Windows glyph will not be shown and on other system it will. And the last mode which is also default for this property - gsmApplication. In this mode TBitBtn (well, not exactly TBitBtn but TButtonGlyph) will look at the Application object for its value.
So, you can control the visibility of all button glyphs using the Application object. How? There are 2 ways: at run time by changing the Application.ShowButtonGlyphs property or at design time by changing the same property for the TApplicationProperties component. TShowButtonGlyphs is an enumeration too with following elements similar to TGlyphShowMode:
  • sbgAlways
  • sbgNever
  • sbgSystem
The default value for the ShowButtonGlyphs property is sbgAlways and not sbgSystem as one may expect. The reason is compatibility with old applications. Developers don't like surprises after a development tool upgrade and the loss of images is not a nice surprise. Anyway, it is not difficult to change the behavior of your application.
One more thing - glyphs are always visible when you are designing your forms. The glyph visibility mode is applied to the controls only at run time (when you start your application).

And now with regards to the Lazarus IDE. After this change the IDE on windows does not show glyphs on buttons by default, but if you really liked them, you can ask IDE to return them. You need to open the IDE options dialog and select Desktop settings:


Havalito said...

just want to say that I admire your work.. really nice initative.. keep it up =)

DoDi said...

A button never should be blank. Consider the HTML browser convention, that every picture can have an replacement text - for browsers in text-only mode, or for missing pictures.

An option, whether to show a glyph on an button, should apply only to buttons with both text and glyph supplied, and with the text always shown on the button. Example: dialog box OK, CANCEL etc. buttons.

Toolbar buttons instead are designed for showing only a glyph. Additional text typically is shown only in a hint window, without affecting the layout (extent) of the toolbar. The user option would be to *also* show text for such buttons, typically *below* the buttons.

IMO we consequently should have separate user options: one for text-buttons, affecting the display of an additional glyph, and one for glyph-buttons, affecting the display of additional text. For additional text more options may make sense, whether, the text should appear below the button, or to the left or right of the glyph, depending on RTL or LTR reading user language.

Paul Ishenin said...

DoDi, TBitBtn class has properties to choose where and with what spacing an image will be shown.

And regards toolbuttons - this change only affects command buttons (TButton, TBitBtn).

dmitry said...
This comment has been removed by the author.
dmitry said...

imho, it's wrong to hardcode gsmSystem to a specific widget set.
It should be Themes API bound. (Yes Themes API again).
I.e. there's an option in Ubuntu, that allows to switch off all icons in the system menus and buttons (i use it to safe screen space for my EEEPC).

This information should be gathered from Themes API. Something like:

function SystemShowGlyphs: Boolean; inline;
Result := themes.ShowButtonGlyphs;

This will also make the code {$IFDEF}s free.

P.S. On Carbon glyphs should also not be shown:

Mike said...

I must say that you did great work. And I must admire it. Very useful & informative post. You described each and everything perfectly. Head off to to you !
comment system