Adobe Flex - show custom tooltip on button click - apache-flex

I am trying to make a custom Flex tooltip a la this tutorial. It's basically just a bunch of labels showing a colour legend. This all works fine and well when the tooltip shows from the button event toolTipCreate:
<mx:Button label="ToolTip example" toolTip=" "
toolTipCreate="toolTipCreateHandler(event)" />
However, I want to show the tooltip when the button is clicked and not wait for the actual tooltip delay. (In this sense, I'm not even sure if the terminology "tooltip" even applies anymore, but that's for another time). I call the same handler with an instantiated ToolTipEvent being passed as the argument:
<mx:Button label="ToolTip example" toolTip=" "
click="toolTipCreateHandler(new ToolTipEvent(ToolTipEvent.CREATE, false, false, instanceOfMyCustomToolTip))" />
However, this doesn't work, and it's driving me up the wall trying to figure out how to do this. This doesn't seem like such an uncommon thing to do, but every example I find on the internet uses the actual tooltip delay instead of a button click. Any help would be appreciated.
P.S. - I want to do it as a tooltip specifically so I can try to get the little "balloon tail" as shown here.
EDIT: I have also tried ToolTipManager.createToolTip in the click event of the button, but this doesn't work either.
<mx:Button id="ttt" label="Tooltip test"
click="ToolTipManager.createToolTip(' ',75,75,'errorTipBelow',instanceOfMyCustomToolTip)"/>

After much research, this is impossible in its current form. Here is what should work:
<mx:Button id="ttt" label="Tooltip test"
click="createTooltip()"/>
private function createTooltip():void {
ToolTipManager.toolTipClass = MyCustomToolTip;
ToolTipManager.createToolTip('any text here');
}
At this point, the ToolTipManager should create a new tooltip using the class specified in ToolTipManager.toolTipClass. However, due to a yet-unresolved bug in the Adobe Flex SDK, ToolTipManager.createToolTip ignores this class and always uses the default class ToolTip.
So nothing short of a monkey patch will get this to work correctly. Found info on this bug (and corresponding patch) in this blog post. The post talks about Flex 3, but this bug is still unresolved as of Flex 4.5.1.

Related

Flex: PopUpManager giving "...null object reference" error

I have a main application calling several ViewStack states, each with popup windows. If I don't open any popup windows, I can move between states fine. If I open a popup window then try to change the state using currentState=... I get the error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at spark.components::Scroller/focusInHandler()[E:\dev\4.y\frameworks\projects\spark\src\spark\components\Scroller.as:2139]
at flash.display::Stage/set focus()
at mx.core::UIComponent/setFocus() [E:\dev\4.y\frameworks\projects\framework\src\mx\core\UIComponent.as:9905]
...
I see others having the same problem, for example here:
http://forums.adobe.com/thread/1031531
http://forums.adobe.com/message/2767130
http://forums.adobe.com/message/3448443
http://forums.adobe.com/thread/655749?tstart=-1
http://forums.adobe.com/thread/801149
http://flex4examples.wordpress.com/2011/05/05/skinnabletextbase-focusmanager-runtime-error-popup/
http://bugs.adobe.com/jira/browse/SDK-32036?page=com.atlassian.jira.plugin.system.issuetabpanels%3Aall-tabpanel
But I haven't figured out how to implement the recommended solution. It sounds like I should just include:
import mx.managers.PopUpManager; PopUpManager;
inside my main application and it should work, but it doesn't work for me.
My application has each view state in a different file, each defined using <views:View>. Also, all of the popups are separate files defined as <s:TitleWindow>. Each file includes this line:
import mx.managers.PopUpManager;
I wonder if this means each file is using a different popup manager(?), when it's a singleton and only one should be used for the whole app (how to set that up?).
The code I use to call a popup is:
var _popupName:MyTitleWindowFileName = MyTitleWindowFileName(
PopUpManager.createPopUp(this, MyTitleWindowFileName, true));
_popupName.addEventListener(MyAppController.CLOSE_POPUP,onClosePopUp);
PopUpManager.centerPopUp(_popupName); // call popup
Note that when the main application (the one defined as <s:Application>) runs, the ViewStack states have not been loaded yet (since they get loaded when they are used the first time). Not sure if that has any cause/effect here.
I've tried to follow Adobe's example code in the "Passing data to and from a Spark pop-up window" section here:
http://help.adobe.com/en_US/flex/using/WS6c678f7b363d5da52e8f1ca1124a0430dcf-8000.html#WS6c678f7b363d5da52e8f1ca1124a0430dcf-7ffe
Any ideas much appreciated.
Based on your comments, it seems like the error occurs because the focus remains in the popup. I would expect the PopUpManager and FocusManager classes to handle this better.
One thing I can think of is that the FocusManager may be trying to handle this. But since the state changes, the item that originally had focus (in the view stack child, before the pop up was opened) may no longer be there when the view state changes. Just a hunch, w/out seeing your code.
Here's some things you can do to either work around the problem (or better) further debug it to understand what is happening:
Use FocusManager.setFocus() to move the focus back to an object in the view stack child before closing the pop up
Use FocusManager.getFocus() to debug and see where it thinks the focus is at various stages (before opening popup, before/after changing state, and before/after closing pop up).
It appears this is the situation I'm experiencing:
Adobe Air: scroller throws error when changes focus between different applications
It's an Adobe bug. Solution from Adobe is:
This bug is easily fixed by changing Scroller to do a null pointer check on focusManager before using it.
which is what the first link above attempts to do.
Another link: http://forums.adobe.com/message/3812805

Icon Property on Button causes Compiler Error

When I attempt to add an icon to a button like this:
<s:Button icon="#Embed(source='assets/logo.jpg')"/>
I receive this error:
Multiple markers at this line:
-Button
-Cannot resolve attribute 'icon' for component type spark.components.Button.
The documentation specifies that you can add an icon like that. See Button Reference.
It is interesting because I can add other Common Styles with no trouble. For example this compiles fine:
<s:Button color="#998877" fontSize="16"/>
What am I goofing up here? Sure it is pretty simple.
Edit: There is also an example right here. The example uses version 4.6. I am on version 4.
I ran into this when I first started using the spark components. I was too was using the original Flex 4 version. They originally didn't support an icon property. You'd have to skin it to get it to work. See the following link:
http://www.flexer.info/2009/06/12/how-to-skin-a-button-with-icon-in-flex-4-sdk-spark/
However, rather than using skins to just add a image to the button, I'd also suggest moving up to flex 4.5 and up. Those include enhancements along with the addition of the icon property to the spark button.

Autocomplete in Flex 4.0 not displaying items in dropdown list

I am new to flex, actionscript and flash builder (having to do an upgrade to an existing project).
One of the problems I seem to have is that the Autocomplete component that seems to be part of flex extras is not displaying the list of items in the dropdown list. Basically, I get a list of blank items. I know they are there and they are the right items because as soon as I click on one, I get the right text in the combobox.
my Code in the mxml looks something like this
<mx:FormItem label="Company:" width="750" fontSize="20" horizontalAlign="right" color="#000000" required="true">
<ns1:AutoComplete enabled="true" labelField="CompanyName" textAlign="left" dropdownWidth="450" id="txtCompany" width="450" />
</mx:FormItem>
In the actionscript when the form loads, as part of the initialization a webservice call is made and the results from that call are set as the dataprovider for the above AutoComplete box like so
public function handleGetCompanyResult(event:ResultEvent):void{
txtCompany.dataProvider = event.result;
}
As I said, when I type a letter in the text box, I see a dropdownlist with a scroll bar on the left but it looks empty. When I click on one of the items, I see the associated company name in the text box. When I set a breakpoint the event.result is an ArrayCollection of proxyObjects.
I tried to change it and put some dummy data like so
public function handleGetCompanyResult(event:ResultEvent):void{
var companyList:ArrayCollection = ArrayCollection(event.result);
var displayCompanyList:ArrayCollection = new ArrayCollection();
displayCompanyList.addItem({CompanyName:"Test1"});
displayCompanyList.addItem({CompanyName:"Test2"});
displayCompanyList.addItem({CompanyName:"Test3"});
txtCompany.dataProvider = displayCompanyList;
}
Again, when I type "T" in the text box I see a dropdown list with 3 empty items. Clicking on the third item puts "Test3" in the textbox. But the items themselves are not visible.
It almost as if its a font/foreground color thing, but I've played around with some of those settings too with no success.
Any help would be much appreciated.
Ok, turns out the project was a Flex 3 project that was imported into Flex 4. It works where it does and breaks down where it doesn't. I created a simple Flex 4 project with an alert box and it worked. I slowly moved all my code across to this project and it worked. It gave me a warning about the styles tag about not being able to use or something like that. I just removed all of the style tags and it worked fine. It doesn't look the same, so I have to fiddle with it a bit more, but at least the text showed up. So something to do with the themes and the Flashbuilder compiler using them at compile time.
All I have to say is what a crappy tool. If the import didn't work, it should have failed completely ages ago. I searched and searched for any projects files or code files that were related to css or styles or themes. But clearly it was using something that was independent of my project to control some tiny part(s) of my project. The parameters of controls in my project were essentially dependent on some environmental/ide factors. What a pain to debug.

ValidationSummary component in Flex Framework

Is there any component that does handle validation errors similarly to ASP.NET's ValidationSummary control in flex? (See screenshot)
alt text http://i.msdn.microsoft.com/ms972961.pdc_userinput_fig2(en-us,MSDN.10).gif
Component should really only display all the errors for the validator it watches.
I'm convinced I already used it but I was unable to find it anywhere in the doc.
There is no component in Flex specifically designed to show a collection of all the validation errors in a form. Some built-in components have support for validation error indicators. TextInput, for instance, can display a red border with an error tooltip that appears on mouse roll over.
Flex Validators work a bit differently than this but check out the Validator Samples in Tour de Flex.
Well, I achieved the results I was expecting with a bit of work.
Sharing in the event that somebody has the same needs that I had ;-):
Made a component that overrides validationResultHandler and manages validation errors
Made sure that all the validators that had to be shown in the component had their listener property set to the component's instance
And thats pretty much it.
<my:ValidationView id="vv" />
<mx:StringValidator listener="{vv}" ... />
<mx:Validator listener="{vv}" ... />

Flex Truncating Button Labels

First and foremost, I apologize for any vagueness in this question. At this point, I'm simply trying to get some new ideas of things to try in order to diagnose this bug.
Anyway, the problem I'm having is with an application that's using a custom moduleloader. That moduleloader has been compiled into an swc and the moduleloader is being instantiated via its namespace. This all works perfectly fine. The problem I'm encountering is specific to mx:button controls used within modules. For whatever reason, their labels are being truncated so, for example, Sign In is showing up with an ellipsis, as Sign ...
After quite a bit of fooling around I have been able to establish the following:
This problem only seems to occur within modules. If a button control is used in the main mxml, the label does not get truncated.
The button control whose label is being truncated does not have a width specified (setting its width to 100% or a specific pixel width doesn't fix the issue)
The button control is using the default padding (messing with the padding by setting left and right to 5 or any other value doesn't help matters either).
We are not using any embedded fonts so I've ruled that out as a possibility as well.
mx:CheckBox and mx:LinkButton are equally impacted by this problem although mx:CheckBox also seems to not want to show its checkbox, it just shows the truncated label.
A potential side affect of this is that attaching a dataprovider to mx:ComboBox causes the combobox control to throw a drawing error but I'm not entirely certain that it's related to the above problem.
One interesting thing I did find while perusing the net for an answer was a mention of fontContext and its relationship to IFlexModuleFactory. There's no specification for fontContext within our implementation of moduleloader so I'm not entirely certain if this could be the issue. In any case, if anyone has any ideas, it would be hugely appreciated. On the other hand, if you know exactly what ails me and can provide me with an answer, I might just wet myself with excitement. It's late. I'm tired. I NEED my Flex app to play nice.
Thanks in advance,
--Anne
Edit: To clarify what I'm looking for with this question, I really just need to know the following:
Could this issue be caused by a namespace conflict?
What else can potentially override the default behavior of labels if no CSS has been implemented?
Has anyone encountered a problem with inheritance being lost while using a custom implementation of moduleloader?
Has anyone encountered this problem or a similar problem with or without using moduleloader?
I'm not sharing any code with this question simply because I'd have to share the entire application and, unfortunately, I can't do that. Again, I'm not looking for the end all, be all solution, just some suggestions of things to look out for if anyone has any ideas.
I've been dealing with this issue myself, off and on and in various forms, for a year, and while I haven't figured out just what's causing it yet, there's clearly a mismeasurement happening somewhere along the line.
What I have been able to to, though, is work around it, essentially by subclassing button-type controls (in my case, Button, LinkButton, PopUpButton, et. al.) and assigning their textField members instances of a UITextField extension whose truncateToFit element simply returns false in all cases:
public class NonTruncatingUITextField extends UITextField
{
public function NonTruncatingUITextField ()
{
super();
}
override public function truncateToFit(s:String = null):Boolean
{
return false;
}
}
The custom component just extends Button (or whatever other button-type control is the culprit -- I've created a half-dozen or so of these myself, one for each type of control), but uses a NonTruncatingTextField as its label, where specified by the component user:
public class NonTruncatingButton extends Button
{
private var _truncateLabel:Boolean;
public function NonTruncatingButton()
{
super();
this._truncateLabel = true;
}
override protected function createChildren():void
{
if (!textField)
{
if (!_truncateLabel)
textField = new NonTruncatingUITextField();
else
textField = new UITextField();
textField.styleName = this;
addChild(DisplayObject(textField));
}
super.createChildren();
}
[Inspectable]
public function get truncateLabel():Boolean
{
return this._truncateLabel;
}
public function set truncateLabel(value:Boolean):void
{
this._truncateLabel = value;
}
}
... so then finally, in your MXML code, you'd reference the custom component thusly (in this case, I'm telling the control never to truncate its labels):
<components:NonTruncatingButton id="btn" label="Click This" truncateLabel="false" />
I agree it feels like a workaround, that the component architecture ought to handle all this more gracefully, and that it's probably something we're both overlooking, but it works; hopefully it'll solve your problem as you search for a more definitive solution. (Although personally, I'm using it as-is, and I've moved on to other things -- time's better spent elsewhere!)
Good luck -- let me know how it works out.
I've used the custom button and link button class solutions and still ran into problems - but found a workaround that's worked every time for me.
Create a css style that includes the font you'd like to use for you label. Be sure to check 'embed this font' right under the text selection dropdown. Go back and apply the style to your button (or your custom button, depending on how long you've been bashing your hear against this particular wall), and voila!
Or should be voila...
I just came across this issue and solve it this way:
<mx:LinkButton label="Some label"
updateComplete="event.target.mx_internal::getTextField().text = event.target.label"
/>;
I've had some success preventing Flex's erroneous button-label truncation by setting labelPlacement to "bottom", as in:
theButton.labelPlacement = ButtonLabelPlacement.BOTTOM;
Setting the label placement doesn't seem to help prevent truncation in some wider button sizes, but for many cases it works for me.
In cases where you can't use a bottom-aligned button label (such as when your button has a horizontally aligned icon), janusz's approach also seems to work. here's a version of janusz's .text reassignment technique in ActionScript rather than MXML:
theButton.addEventListener(FlexEvent.UPDATE_COMPLETE, function (e:FlexEvent):void {
e.target.mx_internal::getTextField().text = e.target.label;
});
The preceding code requires you to import mx_internal and FlexEvent first, as follows:
import mx.events.FlexEvent;
import mx.core.mx_internal;
And here are the results…
Before (note truncation despite ample horizontal space):
After:
The only downside to this approach is you lose the ellipsis, but in my case I considered that a welcome feature.

Resources