Nicer Tooltips and balloon help for Flex 4

May 30, 2010. Posted by Andy Hulstkamp under Actionscript 3 FXG Sound flex 4
Keywords: , , , , ,

Tooltips are a good way to provide a user with additional information for controls and Flex offers Tooltips out of the box. The default Tooltips are fine but when text gets longer than just a few words usability may suffer.

For a current project, I needed more like a balloon help in place of tooltips and therefore decided not to use Flex default tooltips.

Regarding usability of the tooltips (balloon help) I want to be able to

  • Display an optional tooltip title
  • Display formatted tooltip text
  • Display icons
  • Colorize the tooltip based on the semantic of the invoking control
  • Consistent Placement
  • Have all title, text, styles for the tooltips stored in a central location
  • Have the tooltips work in a generic and Flex-compliant way

Flex gives you a few ways to customize tooltips from registering your custom ToolTip class to intercepting Tooltip events where you can hook up the custom tooltip. All of these approaches fall either short of the requirements I had or would add additional overhead so I simply created a custom ToolTipManager that would alter the behaviour of the default ToolTipManager.

Here’s a demo of the final result, the approch is described further down.


NiceToolTips Demo

Since I like to have all resources centralized, the approach I followed was to interpret the value of the tooltip- or the errorString property on a control not as the tooltip text to display but as a partial key to lookup title, text, styles etc. in a resource bundle. Form this partial key concrete keys would be derived to lookup the values for a controls tooltip.

For example

<s:Button label=”OK” tooltip=”ToolTipBundle.okButton” />

would point to the ResourceBundle named  ‘ToolTipBundle’ and within this to all entries of a key starting with tooltip.okButton. Then the values for title, text etc. will be looked up by the custom ToolTipManager implementation and be applied to the tooltip.

The first token in the tooltip property specifies the name of the resource bundle, the second token the partial key for looking up the entries in the resource bundle. If no second token is specified the id (if any) of the component is being used.

Entries in the resource bundle then refer to the partial key submitted and define the concrete values to use for the tooltip.

tooltip.okButton.title=Title of Tooltip
tooltip.okButton.text=Text for this tooltip
tooltip.okButton.styleName=CSS class to use for this tooltip
tooltip.okButton.placement=bottomRight|bottomLeft|topRight|topLeft
tooltip.okButton.color=Color of text
tooltip.okButton.chromeColor=Color of tooltip

Color and chromeColor are there for convenience but can also be set via the CSS class specified by styleName. If any of the entries are not specified fallbacks to default values are used.

To make this work some methods of the default ToolTipManager need to be overwritten

override mx_internal function initializeTip():void

This is where the cstom implementation looks up the values and assigns them to the tooltip.

Additionally there’s the

override mx_internal function positionTip():void

method to position the tooltip in a custom way.

The custom ToolTipManager implementation is registered at loading using a custom preloader class.

The custom Tooltip itself  is a simple SkinnableComponent associated with a SparkSkin. There’s a required skin part for the text and a dynamic skin part for the label that only gets added if any value for a title  is provided.

For both title and text a RichText component is used within the skin so that formatting the text in a rich way is possible. The associated skin is then responsible to draw the tooltip based on the provided placement.
Having set this up, usage of the custom tooltips for any app is simple.

<s:Application               
    preloader="com.hulstkamp.flex.spark.preloaders.CustomMixinPreloader">
</s:Application>

This will register the custom ToolTipManager.

For additional documentation see the source in the demo (view source is enabled).



Share/Save/Bookmark

24 Responses to “Nicer Tooltips and balloon help for Flex 4”

  1. Andrew Westberg Says:

    This is very sweet. I’m going to take a closer look at this code when I get further with my project.

  2. Markus Gritsch Says:

    I was very pleased to see that you have updated your blog with another awesome component as well as your other components

    i will integrate it in my current project maybe i had to customize it a bit to fulfill i18n compatibilty (LocalizationMap).

    best regards, gurkerl

  3. Andy Hulstkamp Says:

    @Andrew, @Markus

    Thanks a lot - glad you found this somehow useful.

    @Markus

    I’ve been sunk in JEE-Projects during the past months. I’m very happy to be able to work with Flex again, so updates on this blog should get more frequent again - hopefully.

  4. heru Says:

    Very Nice Tooltips, thank you very much!!!

    Noob question:
    There is an easy way into insert a dynamic one?
    var impl:NiceToolTipManagerImpl;
    impl = NiceToolTipManagerImpl (mx.core.Singleton.getInstance(”mx.managers::IToolTipManager2″));
    var toolTip_TL:toolTip_TL = impl.createToolTip(”", 100, 50,null,this) as toolTip_TL;
    toolTip_TL.x = …

    another aproximation is creating over an object (label,button via xmxl mode) and later manipulate position and values, but no way to acces to .ToolTipInstance ;(

  5. Andy Hulstkamp Says:

    Heru,

    not sure if I understand you’re question.

    I needed to change the behaviour of how Flex handles the Tooltips that is why I went for a custom ToolTipManagerImpl and this post is about that.

    For standard custom tooltips you might want to check the docs.

  6. heru Says:

    Yes, you are right, i was complicating the solution xD
    Anyway saved to useful libs…
    (excuse poor english, i know its hard to help people adding the efford to understand ’strange’ ang. constructions ;)
    thanks again!

  7. Linda Says:

    Hi Andy,

    thanks a lot for the tutorial and sharing your code.
    Somehow I get this error message: Unable to resolve resource bundle “ToolTipBundle” for locale “en_US”.
    do you happen to know why?

    thanks and keep up the great work
    Linda

  8. Andy Hulstkamp Says:

    Linda

    Did you configure the resource bundles?

    You need to tell the Flex Compiler where to find the resource bundles.

    Go to Project Properties, then Flex Compiler and put this under additional compiler arguments:

    -locale en_US -source-path=/locale/

    This tells the compiler to lookup the resources for en_US under the path /locale/. Obviousliy ToolTipBundle.properties must be there. At compile time it is embedded via the application (alternatively you could load rb at runtime).

    hth
    andy

  9. Linda Says:

    Hi Andy,

    thanks a lot for your reply!
    I have it working right now and it is working beautifully.
    Absolutely love it.

    Two more questions though.
    1. Images within the tooltips take a bit to appear and I am under the impression that embedding the needed assets could probably help the issue. But how to embed an images such as the one that you specify in the “Tooltip and Image” example?
    2. Do you have any idea how to deal with more than one language? I would really like to avoid any redundancy such as having many different tooltip.properties files with different title and text information but identical color, placement and other layout details.

    Again. Thank you very much.
    Best wishes and kind regards,
    Linda

  10. Sam Says:

    I tend to get the warning:
    “The CSS type selector ‘tooltip.NiceToolTip’ was not processed, because the type was not used in the application.”
    Do you happen to know why that might be?

  11. Andy Hulstkamp Says:

    @Linda

    1. As for Images it is the default behaviour for resource bundles. Flex does not know the class at compile-time. You can try to explicitly embedd the images elsewhere in the application and see if caching does the job.

    2. You might want to change the NiceToolTipManagerImpl and pass a default locale for the properties that are identical accross locales. Flex might do this for you via the locale chain anyway.

  12. Andy Hulstkamp Says:

    @Sam

    Any path, location info? Did you add any CSS?

    If you want to style the custom NiceToolTip then you need something like ah|NiceToolTip (Assuming you use the namespace ah)

  13. Nicer Tooltips and balloon help for Flex 4 : Flashflex.com Says:

    [...] Author: Andy Hulstkamp Source: http://www.hulstkamp.com/ [...]

  14. Sam Says:

    Mmhh. Thanks for your reply, Andy.
    I guess it is me being stopid but where exactly do you specify which styles.css/css the custom NiceToolTip should read for its layout properties?

    thank you a lot!! -Sam

  15. Todd Says:

    Hello,

    Is there a way to pass in dynamic text based off the object that the tool tip is called on? I would like to use some of the data to seed part of the text.

    Thoughts?

    Thanks.

  16. Andy Hulstkamp Says:

    Todd

    First note that standard Flex tooltips can be customized and if using the Flex ToolTipManager the value in the tooltip property is interpreted as the string to display in the tooltip. You can set this string any time at runtime - based on your data.

    This example uses a custom ToolTipManager to look up title, text, styles etc. in resource bundles. For this, the value in the tooltip property is interpreted as a key to look up the text etc. in the bundles.

    In assignResourcesToToolTip() of NiceToolTipManagerImpl you could change the way of how the values are looked up and assigned to the tooltip.

    For instance you could introduce further tokens for the value in the tooltip property and parse these tokens as parameters to get a parametrized text from the resource bundle

    • Bundle.Key#dynamic text
    • parse #tokens to use as params in resource bundle lookup
    • var toolTipText:String = ResourceManager.getInstance().getString(bundleKey, lookupKey + “.text”, params);

    For a more OOP approach you could introduce some interface like IToolTipTextOverride that has a get / set toolTipOverride():String function.

    Let your components implement this interface (returning a string based on your data) and in NiceToolTipManagerImpl check to see if the currentTarget (the component the tooltip should be shown on) is of type IToolTipTextOverride.

    If true get the text from the toolTipOverride property of the currentTarget instead of looking it up from the resource bundle and assign this text to the tooltip text.

    Andy

  17. Kevin Says:

    Hi,
    I’m having the same issue as the above poster regarding dynamic text in the tooltip. I’m having a hard time implementing/understanding your suggestion. Do you have an example using this approach or could you possibly provide a little more detail?
    Thanks

    Kevin

  18. Andy Hulstkamp Says:

    Kevin,

    Here’s a quick demo implementation of the aforementioned approaches.

    get the fxp here.

    Look at NiceToolTipManagerImpl Line #275 and #209 for the code that looks up the text.

    Look at TextInputWithOverridenDynamicToolTipText for an example that uses the OOP-Approach.

    hope this helps
    andy

  19. shaman4d Says:

    Thank you a lot Andy. Especially thank you for your last post with example of dynamic tooltip.

  20. Thijs Says:

    Any reason you extend DownloadProgressbar instead of SparkDownloadProgressBar? At first glance they both seem to work correctly, only difference is the look.

  21. Andy Hulstkamp Says:

    Thijs

    This answer took a while, sorry;-)

    There’s no reason to use the DownlaodProgressbar instead of the SparkDownloadProgressBar. I simply didn’t pay much attention, since the only purpose of extending the Progressbar is to inject the custom ToolTipManagerImpl. Thanks for pointing this out!

    Andy

  22. Mark Says:

    Hi Andy,

    I’ve incorporated your wonderful Nicer Tooltips into an AIR project I’m working on.

    Is there a way to restrict the tooltip to the stage? (it is occasionally popping up partially off-stage :-P )

    thanks,

    Mark

  23. Sam Says:

    Hi Andy,

    In my application, the tooltip’s title and text should be displayed dynamicly. From example, there is button which label will be often changed by user. And its tooltip will always display the latest label string.

    How could I do when use your nice tooltip?

    Thanks!

  24. Andy Hulstkamp Says:

    Sam,

    See the discussion above with Todd and Kevin.

Leave a Reply