Creating a multiline label inside a custom togglebuttonbar - actionscript-3

i have a custom toggleButtonBar class that allows label placement on the button, however, i would like to have the labels to be multiline. I'm not good at extending default components. Is there anyone that can help me out?
package com.vit2print.plugin.transvit.tools
{
import mx.controls.Button;
import mx.controls.ToggleButtonBar;
import mx.core.IFlexDisplayObject;
public class IconToggleButtonBar extends ToggleButtonBar
{
[Inspectable(enumeration="left,right,top,bottom", defaultValue="left")]
public var labelPlacement:String = "left";
override protected function createNavItem(label:String, icon:Class=null):IFlexDisplayObject {
var b:Button = Button(super.createNavItem(label, icon));
b.labelPlacement = labelPlacement;
return b;
}
}
}
Any help would be appreciated.

If you can use Spark components, you can accomplish this through a custom skin for the buttons of the ButtonBar. When skinning the ButtonBar, you'll have to create 4 skins though:
one for the ButtonBar itself
one for the first button
one for the middle buttons
one for the last button
Unless all the buttons can look the same, in which case you'll need only one skin for all three kinds of buttons.
First create the three (or one) skins for the buttons by copying the default Spark ToggleButtonSkin. In the FlashBuilder wizard that would look like this:
Scroll down to the bottom and find the Label tag with id labelDisplay. It has its masDisplayedLines property set to 1. Remove it or set it to a value that is more convenient for your use case.
Now create a skin for the ButtonBar itself by copying the default Spark ButtonBarSkin. Find the three button factories and replace the skinClass styles with the button skin(s) you've just created.
<fx:Declarations>
<fx:Component id="firstButton">
<s:ButtonBarButton skinClass="net.riastar.skins.MyButtonBarFirstButtonSkin" />
</fx:Component>
<fx:Component id="middleButton" >
<s:ButtonBarButton skinClass="net.riastar.skins.MyButtonBarButtonSkin" />
</fx:Component>
<fx:Component id="lastButton" >
<s:ButtonBarButton skinClass="net.riastar.skins.MyButtonBarLastButtonSkin" />
</fx:Component>
</fx:Declarations>
Now apply this skin to your ButtonBar and you're all set.
<s:ButtonBar dataProvider="{dp}" skinClass="net.riastar.so.MyButtonBarSkin" width="200" />
Remember, in general with Spark components: if you want them to look different without really changing / customizing their behaviour, use skinning instead of custom components.

Related

if we can access outer function from rendered item by using "outerdocument" object then cant we access inner function from outside.?

These are the scripts under same application first one is under application and second is under dataGrid. from first script through outerClick() i am accessing a inner() function in itemrenderer. Well I can easily access the function outer() from innerClick() by outerDocument object but what_to_use to access inner() function in itemrenderer from outerClick() function. i tried with mx:component id"" and also class="" but it is not able to identify functions under itemrenderer.
<mx:Script>
<![CDATA[
public function outer():void{
Alert.show("Hi i am outer object");
}
public function outerClick():void{
what_to_use.inner();
}
]]>
</mx:Script>
This below item is rendered under data grid.
<s:itemRenderer>
<mx:Component>
<s:GridItemRenderer>
<fx:Script>
<![CDATA[
public function innerClick():void{
outerDocument.outer();
}
public function inner():void{
Alert.show("Hi i am inner");
}
]]>
</fx:Script>
<s:CheckBox id="sel" selected="{data.checked=sel.selected}" change="{data.checked}" click="innerClick()"/>
</s:GridItemRenderer>
</mx:Component>
</s:itemRenderer>
if we can access outer function from rendered item by using
“outerdocument” object then cant we access inner function from
outside.?
You seem to have a distinct misunderstanding of what itemRenderers are. An itemRenderer is a component definition, sort of like creating your own class. since you are using your the 'outerDocument' reference, you are creating your own class in-line / embedded within another class.
An instance of your custom itemRenderer class is created for every visible item in your List based class; so your own class is created multiple times, which means there is more than 1 instance of your itemRenderer function. How would Flex know which itemRenderer instances you want to call the function on? In fact it can't.
That is why you can call up, but you cannot call down.
If you need to make changes inside the itemRenderer, you should do so by changing the data elements of the dataProvider.
For all intents and purposes, I recommend against using outerDocument too. It is a break in encapsulation. A component should never try to access its' parent; because that often introduces an unneeded dependency to your component, limiting reuse. The proper way to "communicate up" is to dispatch an event from the itemRenderer and listen for it in the parent class.
This concept is covered briefly on the answer to one of your previous questions.

How to set DefaultComplexItemRenderer background alpha to 0

I have a simple list with a tileLayout of images. From the examples I've looked at it looks like i'm supposed to use the DefaultComplexItemRenderer. It works, and my array of images loads fine, but each item has a solid background. I need the background behind each image to have an alpha of 0. How Can I set that?
In the past i've just made a custom itemRenderer, and overrided the drawBackground function on itemRenderers, but DefaultComplexRenderer doesn't have a drawBackground function to override.
Is there another simple solution in the flex code? OR it would be awesome if someone could show me how to make a custom DefaultComplexRenderer.
NOTE:
This is a Flex MOBILE project. I know some itemRenderer's aren't friendly with mobile. Adobe says to "always do item renderers in AS3 rather than mxml" so, keep that in mind.
Thanks!
Here's my code:
<fx:Declarations>
<s:ArrayList id="arrList">
<s:BitmapImage source="assets/images/one.png" scaleMode="letterbox" smooth="true" width="100%" height="100%"/>
<s:BitmapImage source="assets/images/two.png" scaleMode="letterbox" smooth="true" width="100%" height="100%"/>
<s:BitmapImage source="assets/images/three.png" scaleMode="letterbox" smooth="true" width="100%" height="100%"/>
<s:BitmapImage source="assets/images/four.png" scaleMode="letterbox" smooth="true" width="100%" height="100%"/>
</s:ArrayList>
</fx:Declarations>
<s:List id="extrasList_list" width="100%" height="100%"
dataProvider="{arrList}"
itemRenderer="spark.skins.spark.DefaultComplexItemRenderer"
horizontalCenter="0"
verticalCenter="0">
<s:layout>
<s:TileLayout requestedColumnCount="-1"
requestedRowCount="-1"
horizontalGap="10"
verticalGap="10"
orientation="rows"
columnAlign="justifyUsingWidth"
/>
</s:layout>
</s:List>
Things I've tried:
this in my main css file...
s|DefaultComplexItemRenderer {
contentBackgroundAlpha:0;
}
but i get this warning, and it doesn't work...
-Cannot resolve namespace qualified type 'DefaultComplexItemRenderer' in CSS selector 'DefaultComplexItemRenderer'
[Edit]
The contentBackgroundAlpha and contentBackgroundColor styles for a Flex List are somewhat misleading! You generally want to style the item renderers. In the context of a list, these styles only affect a tiny bit of "chrome" that can appear around the list. See below for details on styling the renderers.
If you just want to show an image, the IconItemRenderer is the way to go. It extends LabelItemRenderer so it's optimized for mobile and also has two text fields as well.
Flex List components recycle item renderers to be efficient, and only create as many renderers as needed to display what is currently visible. To do this, the list populates the renderer's data property. So you want to configure your item renderer using this data property.
An efficient way to do that is to override the setter function for data. Create a new Actionscript class that extends IconItemRenderer add this to it:
override public function set data(value:Object):void
{
super.data = value;
// IconItemRenderer already has a BitmapImage component, it's property name is iconDisplay
// your ArrayList should therefore only contain Strings representing the image sources
// note how I've changed your ArrayList in the declarations tag below
iconDisplay.source = data.imageSource;
}
You'll likely want to configure that iconDisplay BitmapImage to look how you want it. The method above may get called frequently, so you can put code that only needs to happen once somewhere else... by overriding a Flex component lifecycle method like createChildren():
override protected function createChildren():void
{
super.createChildren();
iconDisplay.scaleMode="letterbox";
iconDisplay.smooth=true;
}
Now tell the List to use your renderer w/syntax like this:
<s:List itemRenderer="com.yourdomain.or.whatever.MyIconItemRendererClass" />
Styling the renderer:
<s:List alternatingItemColors="[0xFFFFFF, 0xFFFFFF]" selectionColor="#FF0000" />
Another way is to override the mobile item renderer's drawBackground() and/or drawBorder() protected methods and draw your own stuff w/the graphics api (or nothing at all).
Supplying the data:
Instead of giving the list an array of BitmapImage components, you give it an array of objects that contain your data. It's better to use strongly typed objects, but this works too:
<fx:Declarations>
<s:ArrayList id="arrList">
<fx:Object imageSource="assets/images/one.png" />
<fx:Object imageSource="assets/images/two.png" />
<fx:Object imageSource="assets/images/three.png" />
</s:ArrayList>
</fx:Declarations>
I like writing renderers in Actionscript... But there is also an MXML example in the link to IconItemRenderer docs at the top. It also shows how you to set the values of the two text areas in this renderer (with labelField and messageField). You can also specify a function that returns the label/message/icon values (with labelFunction, messageFunction, and iconFunction).
Looks like you should be able to use setStyle('contentBackgroundAlpha', 0); on your DefaultComplexItemRenderer.
Not 100% this is what you're looking for, not really familiar with this class. Any reason you're using this over extending LabelItemRenderer?
edit
I believe you may want to extend IconItemRenderer
Check out this tutorial
http://www.youtube.com/watch?v=EOpsDZaQrOI
Thanks for trying to help guys, but I found the quickest/simple solution to be be just as simple as copying the DefaultComplexItemRender from the SDK into a custom one, and then changing this one line of code
autoDrawBackground="false"
It's simple and it worked.

What is the hostComponent?

Im skinning a progressBar in Flex, and after reading a bit about it, I see that there is something called hostComponent.
Adobe site says:
"The host component is the component that uses the skin. By specifying the host component, Spark skins can gain a reference to the component instance that uses the skin by using the hostComponent property."
But, I still dont understand how this exactly works.
Any quick and practical explanation?
Thanks!
When you create custom components in the Spark architecture, you usually split them up into two parts:
an ActionScript class that contains the core functionality of the custom component. This class will usually extend SkinnableComponent or SkinnableContainer
an MXML skin class which is loosely associated with that ActionScript class and contains only the visual presentation of the component. This class should contain no real functionality and it should be trivial to substitute it with another skin.
The first of these two classes is referred to as the host component from the skin's point of view.
A simple example
Let's create a very simple panel by extending SkinnableContainer:
public class MyPanel extends SkinnableContainer {
[Bindable]
public var title:String;
}
As you can see, I made a property 'title' which we want to use to display a title in the Panel. Now let's create a skin that uses this property:
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Metadata>
[HostComponent("path.to.MyPanel")]
</fx:Metadata>
<!-- graphics for title bar go here -->
<s:Label text="{hostComponent.title}" top="5" left="5" />
<!-- graphics for panel content go here -->
<s:Group id="contentGroup" top="30" bottom="0" left="0" right="0" />
</s:Skin>
The hostcomponent is defined in the 'metadata' block and you see that we can use it to bind its properties into our visual representation. The 'contentGroup' is there because it is required by SkinnableContainer; this is were all the elements will go that you put inside the custom panel. So here's how to use it:
<myComps:MyPanel title="Panel title" skinClass="path.to.skins.MyPanelSkin">
<s:Label text="Hello Panel" />
<!--everything in here goes into the 'contentGroup'-->
</myComps:MyPanel>

Is there a way to eliminate borders on a DataGridColumn in Flex?

I can't see a way to get rid of certain borders within a DataGrid. I'd like to eliminate a side border on 2 of my columns so that they appear to look like a single column.
I'm trying to implement a "clear value" button on each of my DataGrid rows. I was able to have a button show on a custom ItemRenderer from a separate ActionScript file, but I was unsure how to have the button click event propagate to the mxml file where the DataGrid is located. It would be much easier for me to have an extra unresizable column with a 'clear' button.
So, to reiterate: Is there any way to change the border style or eliminate certain borders of a DataGridColumn?
It's kind of hacky, but I found a solution to fit my needs. I made a clear separator skin and used it as the verticalLockedSeparatorSkin, then locked the columns up until the separator. This worked because I had no horizontal scrolling in my DataGrid. It only allows, however, for the elimination of a single border between 2 columns (which is all I needed):
DataGrid mxml:
<mx:DataGrid lockedColumnCount="2" verticalLockedSeparatorSkin="ClearGridSeparatorSkin">
<mx:columns>
<mx:DataGridColumn />
<mx:DataGridColumn /> <!-- this column is to the left of the clear separator -->
<mx:DataGridColumn /> <!-- this column is on the right side of the separator -->
</mx:columns>
</mx:DataGrid>
Separator skin (as actionscript class):
package com.example.ClearSeparator
{
import mx.skins.ProgrammaticSkin;
public class ClearGridSeparatorSkin extends ProgrammaticSkin
{
public function ClearGridSeparatorSkin()
{
this.alpha=0;
this.width=1;
super();
}
}
}

How come you can change the id of an object in Actionscript but still refer to it with its old id?

For instance in Flex 4
?xml version="1.0"?>
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
private function setLabel():void {
trace ("the id is "+myButton.id);
myButton.id = "yourButton";
}
]]>
</fx:Script>
<s:Button id="myButton" label="Click Me" click="setLabel();"/>
the traces when the button is clicked twice are
'the id is myButton' followed by
'the id is yourButton'
Not just an idle query. I was hoping to change the id of custom components when populating a main app with them
I would assume that the id of the when set in mxml is the variable name which also sets the internal id (myButton.id = "myButton") Therefore you're able to change myButton.id to "yourButton" because id and variable name are different properties.
Weird one though I'll admit.
If you were to want to create custom components when populating your main app I would look in to a different approach than laying them all out in mxml. Perhaps creating the components in actionscript and setting them in mxml would be best? ( eg your main class is the mxml app and then you have a class behind that does the heavy lifting of creating the view, with all your custom named components )
Remember that MXML is parsed to ActionScript by mxmlc. mxmlc uses the ID attribute of the mxml tags to map to a public class member at compile time. Changing the runtime value of the ID field would have no change to the class structure.
Example:
<MyComponent>
<Button id="myButton" />
&lt/MyComponent>
When compiled, mxmlc transforms it roughly to:
package {
class MyComponent {
[Bindable]
public var myButton:Button;
// Other junk for class init, etc would show here...
}
}
And is then compiled to SWF byte code. At which point the ID attribute is just an attribute and would have no bearing on the class's functionality. You'd have to actually assign a new Button instance to this.myButton to get it to change.