Improving the default FM2 Popup Menu style under OS X
This post describes changes you can make to improve the appearance of popup menus in your Delphi XE3 FireMonkey applications that target OS X.
Modifying OS X styles at design time
To modify OS X styles at design time you must change the target platform for the application to OS X. Otherwise you will always be modifying a windows based style at design time.
If you want to RUN your application with an OS X style on a Windows machine (can be handy for debugging) you need to find and comment out the following lines of the FMX.Styles.pas unit. Copy the unit to your application before modifying it.
Locate the “class function TStyleManager.LoadFromStream(const AStream: TStream): TFmxObject;” method implementation. Towards the end there is a section of code that checks the description and shows a message dialog if the style being used doesn’t match the current target. You can comment out that entire block of code.
What is interesting about this dialog, is that if it does show in your application, due to invalid style being used for the target platform – your application will crash terribly after the dialog is shown. Probably not something you would want to happen.
The Default Popup Menu Style
Here is a screen capture of what the default FM2 popup menu style looks like under Mountain Lion.
Here is a screen capture of what the native menu looks like under Mountain Lion.
As you can see, there are some obvious differences between the default style that FM2 expects you to use and what should be expected.
- FM2 menu has square corners
- Font is totally wrong
- Disabled item state isn’t very clear
- Separator too close to previous item
- Selected item doesn’t span the width of the menu
- First (and last) items are not padded from the top (or bottom) of the menu
Background on menu styles
There are three different styles contained in the default style.
- menuviewstyle – the style that makes up the background of the popup menu
- menuitemstyle – the style that makes up the item in the menu
- menuseparatorstyle – the style used for a separator in the menu
If you extract the default styles from the IDE, why these aren’t included as raw style files is an unbelievable oversight by Embarcadero you can look at these styles and expand, modify or redo them.
Chris Rolliston has a great post on how to extract the default styles for a given platform here: http://delphihaven.wordpress.com/2012/09/11/inspecting-the-default-platform-fmx-styles-in-xe3/
menuviewstyle changes
The changes made to the menuviewstyle are significant. Gone is the “pixel perfect” usage of TSubImage since it kills the rounded appearance of the popup menu it’s been replaced with a TRectangle shape, shadow effect and some very selective use of the padding properties (to have the shadow appear correctly).
The content layout now contains padding values to have the items span the width of the popup menu, as well as provide extra space at the top and bottom of the menu.
menuitemstyle changes
There were two changes to this style.
- Changed the font family and size to the “text” and “shortcut” TText objects
- Added TColorAnimation components to the “text” and “shortcut” objects that trigger when the Enabled property is changed
menuseparator style
The following changes were made to this style:
- Made the separator span the entire width of the item
- Made the separator height 1 pixel
- Modified the top and bottom padding of the sub image object to center the line better within the item
NOTE: The source lookup for the TSubImage component included in the style reference “OSX Lionstyle.png”. You need to change this value when adding these styles into your retina style book. I have not tested on a retina system, but if you want to send me a retina enabled laptop for testing, please email me (jeremy.north@gmail.com) for the ship to address!
Style only changes
With some changes to the menu, menu item and menu separator styles, I’ve managed to make the FM2 menu style a little more plausible.
Here is the result:
Style and three source code changes
Throw in a couple of modifications to the FMX.Menus.pas unit, the results are improved once again.
- Item height reduction
- Disabled text actually looks disabled
This is the final result for the modified popup menu.
Not perfect and could be tweaked further but I think its a vast improvement on the default!
How to put these changes in your application
Modified style download
To get these changes working in your applications, download the attached popupmenustyle.style file and Add that to your OS X style book(s) for your application. Use the Add… feature in the Style Designer.
Code changes
Copy the FMX.Menus.pas unit to your application folder.
In the TMenuItem.ApplyStyle method add the two lines of code to the end of the method:
ApplyTriggerEffect(Self, ‘Enabled’);
StartTriggerAnimation(Self, ‘Enabled’);
In the TMenuItem.SetEnabled method add the same two lines inside the “if Value <> Enabled then” statement.
These two changes causes the Enabled property to trigger the animation which turns the Text color to Gray.
If you inspect the styles included in the style file, both the text and shortcut style items for the ‘menuitemstyle’ have color animation components added to them with triggers. Some screen captures of the style changes are below.
Instead of applying a color animation, this could have been achieved by directly updating the text and shortcut style items. However this solution allows for further customizations down the track if required. Such as making the disabled color RED!
The final code change addresses the issue of the menu items default height. Currently it is 23, however the native height is 19 (on my installation anyway). To address this issue (which isn’t an ideal solution) I did the following change:
In the TMenuItem.CalcSize method change the following line:
Result := PointF(0, 23);
To something like this:
{$IFDEF JEDOSX}
Result := PointF(0, 19);
{$ELSE}
Result := PointF(0, 23);
{$ENDIF}
NOTE: A define is used here because you don’t want to affect other target platform item sizes. For my applications that target OS X, I always define JEDOSX. This is why I used this define – you should define your own value here!
What I should have done here is added a TStyleTag to the style and set its stylename to ItemHeight and read the value from the style, instead of hardcoding it. This is left as an exercise for the reader – I’ve already spent way too long on this as it is.
Conclusion
Hopefully this post has helped improve the default look of a popup menu in your applications that target OS X. Any queries, post a comment and I’ll try and respond.
NOTE: I’m not done with popup menus and there use in FM2, however that will have to wait for another post.