Custom DataTip in Flex - apache-flex

I want to use datatips in my charts in Flex 4. I know how to use them, but the standard DataTip only shows text. I would like to show text + a button. How would I go on about this?
I thought about extending DataTip in a custom DataTip class and add the button there somewhere like this
public class MyDataTip extends DataTip {
// Override some methods to add the button here?
}
Is this possible / the correct idea? Or do I have to do it differently?
Any code examples for this?

You can use a DataTipRenderer to achieve this. Here is a example of it.
<?xml version="1.0"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
implements="mx.core.IFlexDisplayObject, mx.core.IDataRenderer"
width="120">
<fx:Metadata>
[Event(name="DataSelect", type="flash.events.Event")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import flashx.textLayout.conversion.TextConverter;
import flashx.textLayout.elements.TextFlow;
import mx.charts.HitData;
import mx.charts.series.items.ColumnSeriesItem;
private var _data:HitData;
[Bindable]
private var _xValue:String;
[Bindable]
private var _yValue:String;
[Bindable]
private var _displayText:TextFlow;
public function get data():Object
{
// TODO Auto Generated method stub
return null;
}
public function set data(value:Object):void
{
// HitData data from chart
_data = value as HitData;
// The display text used in datatip which comes in HTML format
_displayText = TextConverter.importToFlow(_data.displayText, TextConverter.TEXT_FIELD_HTML_FORMAT);
// HitData contains a reference to the ChartItem
var item:ColumnSeriesItem = _data.chartItem as ColumnSeriesItem;
// ChartItem xValue and yValue
_xValue = String(item.xValue);
_yValue = String(item.yValue);
}
]]>
</fx:Script>
<fx:Declarations>
</fx:Declarations>
<s:Rect right="0" left="0" bottom="0" top="0">
<s:filters>
<s:DropShadowFilter blurX="20" blurY="20" alpha="0.22" distance="5" angle="90" knockout="false" />
</s:filters>
<s:fill>
<s:SolidColor color="0xFFFFEE"/>
</s:fill>
<s:stroke>
<s:SolidColorStroke color="0x1a1a19" weight="1" alpha=".2" />
</s:stroke>
</s:Rect>
<s:VGroup width="100%" height="100%" paddingTop="10" paddingRight="10" paddingBottom="10" paddingLeft="10">
<s:RichEditableText textFlow="{_displayText}" width="100%" textAlign="center" selectable="false" editable="false"/>
<s:Button label="Click me !"/>
</s:VGroup>
</s:Group>
And in your Chart mxml tag just add following
<mx:ColumnChart id="myChart" showDataTips="true" dataTipRenderer="com.CustomDataTipRenderer">

Related

How to set different font color in combobox items in flex

I have a ComboBox in Flex which is listing like this:
A-B-C-D-E-F
A-B-C-D-E-F-*
A-B-C-D-E-F-G-*
A-B-C-D-E-F-*
I want to make the * appear red. Could anyone help me regarding this?
Hopefully self-explaining:
<s:ComboBox itemRendererFunction="getItemRenderer"
dataProvider="{new ArrayList(['A-B-C-D-E-F', 'A-B-C-D-E-F-', 'A-B-C-D-E-F-G-', 'A-B-C-D-E-F-'])}"/>
<fx:Declarations>
<fx:Component className="RedItemRenderer">
<s:ItemRenderer>
<s:HGroup verticalAlign="middle">
<s:Label text="{data}" color="red" paddingLeft="3" paddingRight="3" paddingTop="5" paddingBottom="5"/>
<s:Image source="#Embed(source='warning.png')"/>
</s:HGroup>
</s:ItemRenderer>
</fx:Component>
</fx:Declarations>
<fx:Script><![CDATA[
import mx.collections.ArrayList;
import spark.skins.spark.DefaultItemRenderer;
private function getItemRenderer(item:Object):IFactory
{
var s:String = item as String;
if (s.charAt(s.length-1) == '-')
return new ClassFactory(RedItemRenderer);
else
return new ClassFactory(DefaultItemRenderer);
}
]]></fx:Script>
This is how it looks like:

Invisible part of BitmapImage

I have a SkinnableContainer, which contains s:BitmapImage. I need a part of the image (Rect) to be fully transparent. Just make a transparent cut-out, that would be easy to position.
The image in the background is width="300" height="200" and transparent area should be width="200" height="20" and right="0" bottom="50". I managed to achieve similar effect with BlendMode.OVERLAY, but I believe there must be a better way.
Any ideas, suggestions, please?
You could apply another object (like a UIMovieClip) to the image as a Mask. You could also manipulate the pixels of a Bitmap and set it as the source of the BitmapImage. This may or may not make sense depending on your specific requirements.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="onComplete(event)"
backgroundColor="0xEEEEEE">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.graphics.ImageSnapshot;
import mx.skins.RectangularBorder;
protected function onComplete(event:Event):void
{
var bW:int = 300;
var bH:int = 200;
var X:int = 0;
var Y:int = 150;
var W:int = 200;
var H:int = 20;
var topRect:Rectangle = new Rectangle(0,0,bW,Y);
var righRect:Rectangle = new Rectangle(W,0,bW-W,bH);
var bottomRect:Rectangle = new Rectangle(0,Y+H,bW,bH-(Y+H));
var targetBitmapData:BitmapData = ImageSnapshot.captureBitmapData(original);
var newBitmapData:BitmapData = new BitmapData(bW,bH,true,0x00000000);
newBitmapData.copyPixels(targetBitmapData, topRect, new Point(0, 0),null, null, true);
newBitmapData.copyPixels(targetBitmapData, righRect, new Point(W, 0),null, null, true);
newBitmapData.copyPixels(targetBitmapData, bottomRect, new Point(0,Y+H),null, null, true);
modified.source = new Bitmap(newBitmapData);
}
]]>
</fx:Script>
<s:VGroup gap="10" left="10" top="10">
<s:Group id="original">
<s:Rect width="300" height="200">
<s:fill>
<s:SolidColor/>
</s:fill>
<s:stroke>
<s:SolidColorStroke color="0xFF0000"/>
</s:stroke>
</s:Rect>
</s:Group>
<s:Group>
<mx:Image width="300" height="200" id="modified" />
<s:Rect top="0" left="0" right="0" bottom="0">
<s:stroke>
<s:SolidColorStroke color="0xFF0000"/>
</s:stroke>
</s:Rect>
</s:Group>
</s:VGroup>
</s:Application>
An example for your particular case, maybe you'll extend this.

Adobe Flex 4.5 Spark: Binding ItemRenderer Component to Parent

In Flex 3, it used to be possible to bind a component property within an itemRenderer via outerDocument. So for instance, if there was a image inside an itemRenderer that was only displayed on a given condition of the parent, something like this would work perfectly:
<mx:itemRenderer>
<mx:Component>
<mx:Label text="{data}"/>
<mx:Image id="img" visible="{outerDocument.ShowImage}" includeInLayout="{outerDocument.ShowImage}"/>
</mx:Component>
</mx:itemRenderer>
where the outer document (not the list, but the mxml the list is in) contained something like
[Bindable]
public function get ShowImage():void
{
return showImage;
}
public function set ShowImage(val:Boolean):void
{
showImage = val;
}
I've tried to do the same thing in Flex 4.5 using Spark item renderers using parentDocument, but it doesn't seem to be aware to the binding. When I do this in Flex 4.5, the itemRenderer doesn't seem to be aware when the parentDocument ShowImage changes.
Has anyone seen this issue and is able to offer a solution?
EDIT: Add Spark Source
As requested here is my spark source:
MyItemRenderer.mxml
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:Label id="myLabel" text="{data}/>
<s:Image src="something.png" visible="{parentDocument.ShowImage}" includeInLayout="{parentDocument.ShowImage}"/>
</s:ItemRenderer>
RendererContainer.mxml
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
private var showImage:Boolean = false;
[Bindable]
public function set ShowImage(val:Boolean):void
{
showImage = val;
}
public function get ShowImage():Boolean
{
return showImage;
}
]]>
</fx:Script>
<!-- Content Group -->
<s:List id="lstCell" width="100%" height="100%" itemRenderer="MyItemRenderer">
</s:List>
</s:Panel>
Ok so there is a checkbox in a wrapper outside of RendererContainer.mxml that dispatches a custom event that is handled by changing a Bindable Boolean. The change in that var then changes the ShowImage property on my RendererContainer component. I would expect that the binding would then be picked up by MyItemRenderer but it doesnt seem to be working.
So my outer wrapper would access ShowImage like this
<comp:RendererContainer id="myId" ShowImage="{myCheckbox.selected}"/>
I think this should do the trick for you, YourTypeHere would be the class of the containing
object, make sure the ShowImage property is public and bindable.
<mx:itemRenderer>
<mx:Component>
<mx:Script>
<![CDATA[
import YourTypeHere;
]]>
</mx:Script>
<mx:Label text="{data}"/>
<mx:Image id="img"
visible="{YourTypeHere(this.parent.ShowImage)}"
includeInLayout="{YourTypeHere(this.parent.ShowImage)}"/>
</mx:Component>
</mx:itemRenderer>
P.s. please don't name properties with a starting uppercase letter, including getters, consider naming it showImage and your private var to something like _showImage instead :D
Your getter seems to have return type as void. Change that to Boolean
[Bindable]
public function get ShowImage():Boolean
{
return showImage;
}
public function set ShowImage(val:Boolean):void
{
showImage = val;
}
This will help.
<s:Image src="something.png" visible="{RendererContainer(ListSkin(parentDocument).parentDocument).ShowImage}" includeInLayout="{RendererContainer(ListSkin(parentDocument).parentDocument).ShowImage}"/>
Following works perfectly fine:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
private var showImage:Boolean = false;
[Bindable]
public function set ShowImage(val:Boolean):void
{
showImage = val;
}
public function get ShowImage():Boolean
{
return showImage;
}
]]>
</fx:Script>
<s:CheckBox label="Select" change="{ShowImage = !ShowImage}"/>
<!-- Content Group -->
<s:List id="lstCell" width="100%" height="100%" dataProvider="{new ArrayCollection(['A','B'])}">
<s:itemRenderer>
<fx:Component>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<s:Label id="myLabel" text="{data}"/>
<s:Button label="something.png" visible="{outerDocument.ShowImage}" includeInLayout="{outerDocument.ShowImage}"/>
</s:ItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:List>
</s:Panel>
</s:WindowedApplication>

Flex: Custom ProgressBar bar skin won't fill entire track

I'm trying to create a simple skin for the flex progressbar control. Both the track and the bar should have rounded corners, and the bar should fill the track completely in the parts where it is being shown.
Here is the bar skin I've created based off this example:
<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
override protected function initializationComplete():void {
useChromeColor = true;
super.initializationComplete();
}
]]>
</fx:Script>
<s:Rect radiusX="5" radiusY="5" top="0" left="0" right="0" bottom="0">
<s:fill>
<s:SolidColor color="#bb0203" />
</s:fill>
</s:Rect>
</s:SparkSkin>
Here is the progress bar declaration:
<mx:ProgressBar id="progressBar" name="progressBar" top="40" left="10" width="480" height="25"
label="" labelWidth="0"
trackSkin="Skins.ProgressBar.TrackSkin"
barSkin="Skins.ProgressBar.BarSkin" />
And here is the track skin:
<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minHeight="25">
<fx:Script>
<![CDATA[
override protected function initializationComplete():void {
useChromeColor = true;
super.initializationComplete();
}
]]>
</fx:Script>
<s:Rect width="100%" height="100%" radiusX="5" radiusY="5">
<s:fill>
<s:SolidColor color="#d1d3d4" />
</s:fill>
</s:Rect>
</s:SparkSkin>
Unfortunately, it doesn't have quite the desired effect:
Instead of the bar being flush with the track, there's a margin, and the rounded border gets cut off.
How do I fix this?
In addition to setting the barSkin property, set the maskSkin property to the same value as barSkin:
You can assign this skin the same way as others in your code:
<mx:ProgressBar id="progressBar" name="progressBar" top="40" left="10" width="480" height="25"
label="" labelWidth="0"
trackSkin="Skins.ProgressBar.TrackSkin"
maskSkin="Skins.ProgressBar.BarSkin"
barSkin="Skins.ProgressBar.BarSkin" />

How to set Source of s:BitmapFill dynamically? (Flash Builder, Code Inside)

In Flash Builder (flex 4) I try to use next code to set selected by user (from file system) Image as a repeated background. It worked with mx:Image but I want to use cool repited capabiletis of s:BitmapFill.
BTW: Technic I use also does not work with S:BitmapImage. Also FP does not return any errors. What Shall I do with my code to make it work?
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:net="flash.net.*"
minWidth="955" minHeight="600" >
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.utils.ObjectUtil;
private function btn_click(evt:MouseEvent):void {
var arr:Array = [];
arr.push(new FileFilter("Images", ".gif;*.jpeg;*.jpg;*.png"));
fileReference.browse(arr);
}
private function fileReference_select(evt:Event):void {
fileReference.load();
}
private function fileReference_complete(evt:Event):void {
img.source = fileReference.data;
Alert.show(ObjectUtil.toString(fileReference));
}
]]>
</fx:Script>
<fx:Declarations>
<net:FileReference id="fileReference"
select="fileReference_select(event);"
complete="fileReference_complete(event);" />
</fx:Declarations>
<s:Rect id="backgroundRect" left="0" right="0" top="0" bottom="0">
<s:fill>
<s:BitmapFill id="img" source="#Embed('1.jpg')" fillMode="repeat" />
</s:fill>
</s:Rect>
<mx:Button id="btn"
label="Browse and preview..."
click="btn_click(event);" />
</s:Application>
Check this code:
private function fileReference_complete(evt:Event):void {
var loader:Loader = new Loader();
loader.loadBytes(fileReference.data);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderCompleteHandler);
}
private function loaderCompleteHandler(evt:Event):void{
img.source = evt.target.content;
}
So you need to use a loader in order to create the bitmap object.

Resources