Flex easy set buttonmode to all buttons - apache-flex

is there an easy way to set the buttonMode to true to all my buttons in my application?
I thought to create a custom component which extends the s:Button and set there buttonMode to true but I wonder if there is an easier way like with CSS.
Thanks in advance

As Wade said, the skin is a good way to go. While setting buttomMode="true" on the skin won't work the way you want, you can set the host button's buttonMode from the skin like so:
<fx:Script>
<![CDATA[
import spark.components.Button;
override protected function commitProperties():void
{
super.commitProperties();
hostComponent.buttonMode = true;
}
]]>
</fx:Script>

You may be able to do this with a skin and css. Copy the default ButtonSkin to a custom skin class and set buttonMode="true" on the skin. (If that doesn't work you can try to set hostComponent.buttonMode = true on creation complete.) Then set the skin for s:Button to your custom skin in your css.

You could either try writing a crawler which would walk through all your object at runtime, or something like this:
stage.addEventListener(Event.ADDED_TO_STAGE, parseItem, true);
and then:
function parseItem(e:Event):void{
if (e.target is Button)
e.target.buttonMode = true;
}
Each item which is added to the stage should go through this event (even if only its parent is added to the display list).
Of course you'll have to add this event listener before anything is added to the stage actually!

Unfortunately, I don't think you have any other option that creating a custom Button.
You could monkey patch the original Button component but I wouldn't recommand this pratice.

I would also suggest Maurycy's approach or you could just monkey patch the Button class in your project. That might even be easier and it would not cause a performance hit.

Related

How to skin buttons in flex 3?

Just out of curiosity, I am making an effort to optimize every part of our flex app (which is a small part of our app in general). Currently, I am working on optimizing all of the buttons/skins. I have linked a few of the buttons that I use, and some sample code I am using to generate them.
Please advise on how to make this more efficient, usable, and just better overall. Thanks!
As you can see, our buttons can be pretty different, but have a similar look and feel. Currently, I am creating 'stateful skins,' by setting up something like this:
skin: ClassReference('com.mysite.assets.skins.NavigationButtonSkin');
Then, NavigationButtonSkin looks something like this:
public class NavigationButtonSkin extends UIComponent {
// imports, constructor, etc
protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
// initialize fillColors, fillAlphas, roundedCorners, etc
switch( name ){
case 'upSkin':
fillColors = [getStyle('backgroundColor'),getStyle('backgroundColor2')];
break;
// do the same for overSkin, downSkin, disabledSkin, etc
}
// use this.graphics to draw background
// use this.graphics to draw border on top of background
}
}
I commented out some of the straight forward parts, but let me know if this is a bad/inefficient way of doing this - and how to improve.
Thanks!
In terms of performances, it would be better that your skin inherits from ProgrammaticSkin instead of UIComponent.
ProgrammticSkin itself inherits from Shape and provides utility methods for skinning such as verticalGradientMatrix, drawRoundRect, ...
That's all I can say looking at your code.
Good point is you use programmatic skin instead of bitmap/swf based skins.
Okay, I'm not getting where you're getting at with this. You just want to know if you're doing it right? I'm assuming that your skin: ClassReference('com.mysite.assets.skins.NavigationButtonSkin'); is added to the css of a Button, which is good, however I don't see why you're doing it all in Actionscript. Seems inefficient and essentially you're losing all the ability of mxml layouts and support for Catalyst (if you'd ever need it in the future).
Try creating a skin in Flash Builder, it'll create an MXML with the default button skin where you can just edit it as you please. It's also A LOT easier to do state based design using mxml over actionscript. You should modify from there on and have a separate skin for each button types.
EDIT: oh crap, didn't see this was Flex 3... Get with the program ;) Just listen to what Florian said.

How does focus works in Flex?

I try to figure out how does focus mechanism work in Flex. Here comes the example of what I mean:
Let's assume that we have a simple web application, which contains custom component that extends Canvas and implements mx.managers.IFocusManagerComponent. This component overrides focusInHandler and focusOutHandler methods and shows some feedback on how they are called (thinner or thicker border). This custom component also contains some Text.
The source of the component is:
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100" height="100" creationComplete="cc();" implements="mx.managers.IFocusManagerComponent">
<mx:Script>
<![CDATA[
import mx.containers.Canvas;
import mx.controls.Text;
import mx.controls.TextArea;
import mx.core.UIComponent;
import mx.managers.IFocusManagerComponent;
public function cc():void
{
text = new Text;
text.text = "123";
addChild(text);
setStyle("backgroundColor", "0xddddff");
setStyle("borderColor", "0x000000");
setStyle("borderThickness", 1);
setStyle("borderStyle", "solid");
}
private var text:Text;
override protected function focusInHandler(e:FocusEvent):void {
trace("focusInHandler, currFocus: " + focusManager.getFocus());
setStyle("borderThickness", 4);
}
override protected function focusOutHandler(e:FocusEvent):void {
trace("focusOutHandler, currFocus: " + focusManager.getFocus());
setStyle("borderThickness", 1);
}
]]>
</mx:Script>
</mx:Canvas>
Here is the live version (with source view): http://rafalrybacki.com/lab/focus_question/. In the app there is also a TextArea below the Canvas - to ease the focus manipulation when testing.
The questions:
If you click once on a violet canvas it receives focus (focusInHandler is called), then if you click again the focus is lost (focusOutHandler called) - why?
Of you click on a Text the Canvas receives focus (focusInHandler called) and keeps it when being clicked wherever on the area (focusOutHandler nevet called) - why?
Maybe my understanding of the whole focus issue is wrong? Thank you for any suggestions.
With respect,
Rafal
Hey Rafalrybacki. [I'm in a meeting, and can't really spend time on the question but thought I could help with a pointer or two:]
First, the intent of a Canvas is to interact with FocusManager differently than a component that implements IFocusManagerComponent. Canvas implements IFocusManagerContainer and while you can accomplish what you're trying to accomplish by making the container an IFocusManagerComponent, I'd avoid it, simply because I try to do that which I think the flex sdk team intended when using internal components.
What I think they'd intend is for you to listen to the FocusEvent in your container. FocusEvents bubble by default, so you can accomplish most everything you need to with a simple event listener.
Note: Listening to a focusOut can get confusing with components that have multiple uicomponents as children --- i.e. combobox has a UITextField and a Button, so the component has multiple FocusOut and FocusIn events happening from whithin the same component. Your savior will be (I would guess) doing a container.contains() on a focusManger.getFocus() item (casting it etc.) to accurately set your style.
I just blab, so if you need some help beyond this, or would like to know more about why a focusIn or focusOut evt is being dispatched when it is being dispatched -- I'd be happy to slap some code together for you and explain why the type of event is being caught. Your best bet tho' (to fit within flex sdk guidelines) is to use an event listener from within the container, and not fight with a component that is both an IFocusManagerComponent AND an IFocusManagerContainer. Could get messy.
Hope that helps. Best of luck,
Jeremy

Adding an MXML component as a child of the main application using ActionScript

How can I add an MXML component as a child of the main application using ActionScript. It's not possible to instatiate it, is it? Assuming that behind every mxml file stands an actionscrpt3 class, I tried to import it but id didn't show up.
You'll want to familiarize yourself with the flex component lifecycle: http://msimtiyaz.wordpress.com/flex/adobe-flex-component-instantiation-life-cycle/
It explains the actionscript code behind the mxml components, and it's important to be familiar with, because if you implement your components incorrectly, it can really slow down your application.
Anyway, I think you may be confused about what imports do. Import statements make the code available to use in your code, but it wouldn't create a component. You'd need to create a component the same way you create any object in actionscript, and then you'll need to add that component to the display list to make it show up.
The appropriate place to do this is in the createChildren() function:
override protected function createChildren():void {
super.createChildren();
var myText:Text = new Text();//create a new object
this.addChild(myText);//add it to the display list
}

flex3:How to override function set label of a button

Flex 3 question:
I trying here to avoid having to bind resources to all my components labels ( ie a button) and find a way to have this automated.
Problem:
It corrupts the layout in design mode to bind directly in the mxml label="{resourceManager.getString('myResources', 'submit')}" and makes the design view useless. but when declaring bindings elsewhere, in actionScript or via a bind tag, it is counter productive and prone to many errors and miss.
Proposition:
I would like to create my own button that automatically invoke resources to localize a button label. So the author puts "Submit" in the mxml description of my button, and when running it would take the value of the label ie "submit" and use resourceManager.getString('myResources', 'submit').
but I can't find the way to override the set label function, Is it possible if yes how? else how can I go about it?
Maybe I am missing an essential process here that would make the use of resources more elegant, as well as how to override such thing as a button's label.
Thanks for your advices.
Create a component called MyButton, extending Button. Then use this:
override public function set label(value:String):void {
super.label = resourceManager.getString('myResources', value) || value;
}
Assuming the resource manager returns "null" or "undefined" this will work, and will only replace the value if it exists in "myResources".
If you don't want to override every component you need to do this with, then you can add a FlexEvent.CREATION_COMPLETE event on every component. Then use a single generic function to do your label localization.

Custom Itemrender in Datagrid with Datatip

I have a datagrid with one datagridcolumn in it. Without a custom itemrenderer I can use a datatipfunction for showing a custom datatip but now I want to have a custom item render for colouring the rows differently. Therefore I extended a label and changed the data method but now my datatipfunction does not work anymore.
Any ideas?
thanks in advance
Sebastian
I know this question is a wee bit old, however I just ran into the same problem and solved it by looking at how the standard DataGridItemRenderer class does it.
So basically I ended up copying that toolTipShowHandler() function into my class (without any modification), implementing the IDropInListItemRenderer interface and adding a few lines into my renderer's commitProperties() function, which were inspired by the DataGridItemRenderer, too.
Hope this helps.
I'm a little late to the party, but I ran into this issue with a custom DataGridItemRenderer for images. The solution described at the following link worked out nicely for me:
http://www.kalengibbons.com/blog/index.php/2008/12/displaying-datatips-when-using-an-itemrenderer/
The gist is that you override the item render's updateDisplayList() and set a tool tip by calling the dataTipFunction and/or using the dataTipField just like a built-in item renderer.
copying the content of link given by cbranch here. stackoverflow is more reliable for keeping code snippets
Displaying DataTips when using an itemRenderer
One of the bad things about using itemRenderers in a DataGridColumn is that you lose the dataTip functionality that it normally provides. Well, here is a way to fake that functionality.
First, add the dataTipField or dataTipFunction to the DataGridColumn like you normally would.
<mx:DataGridColumn headerText="DataTip"
dataField="name1"
showDataTips="true"
dataTipField="description1" />
Then, in your itemRenderer add the following code to be able to tap into that information and display a tooltip instead.
private function getToolTip():String{
var dg:DataGrid = listData.owner as DataGrid;
var func:Function = dg.columns[listData.columnIndex].dataTipFunction;
if(func != null){
return func.call(this, this.data);
}else if(dg.columns[listData.columnIndex].dataTipField.length){
return data[dg.columns[listData.columnIndex].dataTipField];
}else{
return "";
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
this.toolTip = getToolTip();
}
This works with both dataTipFields and dataTipFunctions and lets you treat the dataTips in your columns the same way, regardless of whether you’re using an itemRenderer or not. The only minor difference is the positioning of the label, but that can be easily modified with styles. You can download the full source code here, for a functional example of how this works.
source
Just off the top of my head, maybe make your custom item renderer extend DataGridColumn. This will give your item renderer all the functionality of a regular column.

Resources