I had a code like this
var str:string = "GeoCode: 3";
in this code I want ":" to be in bold.
How can I do that and this should be done in spark
Please help me
Thanks!
The simplest approach is to use TextFlowUtil.importFromString() and assign the resulting TextFlow object to a RichText component, like this:
<s:RichText id="textDisplay"/>
textDisplay.textFlow =
TextFlowUtil.importFromString('GeoCode<span fontWeight="bold">:</span> 3');
If you'd like to keep your original Strings intact, you can do a replace on them to add the span:
var str:String = "GeoCode: 3";
str = str.replace(/:/, '<span fontWeight="bold">:</span>');
textDisplay.textFlow = TextFlowUtil.importFromString(str);
I would do something like this:
The text property of the component is splitted into parts by means of ":" symbol. Then each part is added into a HGroup like a Label. Colons are added bold.
//Application
<?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"
minWidth="955" minHeight="600" xmlns:com="com.*">
<s:VGroup left="20" top="20">
<com:GeoLabel text="GeoCode: 3"/>
<com:GeoLabel text="GeoCode: 5: Some Info: 123"/>
</s:VGroup>
</s:Application>
//GeoLabel component
<?xml version="1.0" encoding="utf-8"?>
<s:HGroup xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="120" height="25" gap="0">
<fx:Script>
<![CDATA[
import spark.components.Label;
private var _text:String;
public function get text():String
{
return _text;
}
public function set text(value:String):void
{
_text = value;
createMembers();
}
private function insertLabel(str:String, bold:Boolean):void
{
var la:Label = new Label();
la.text = str;
if (bold)
la.setStyle("fontWeight", "bold");
this.addElement(la);
}
private function createMembers():void
{
this.removeAllElements();
var arr:Array = text.split(":");
for (var i:int = 0; i < arr.length; i++)
{
if (i != 0)
insertLabel(":", true);
insertLabel(arr[i], false);
}
}
]]>
</fx:Script>
</s:HGroup>
Related
After changing my OS's decimal separator as explained here:
( http://blogmines.com/blog/2010/03/11/how-to-change-the-decimal-separator-in-excel-2010/ ), I want to display a number in Flex that uses a comma for both the thousands separator and the decimal separator. Sounds simple enough, right?
I tried using three different NumberFormatters offered by Flex. Along the way, I learned that two of them didn't play well with others in the same class, even if using fully qualified class paths when declaring the variables, so I had to split them up into three classes, like so:
NF1 - spark.formatters.NumberFormatter
package dstrube
{
import flash.globalization.NumberParseResult;
import spark.formatters.NumberFormatter;
public class NF1
{
public static function get(value:String):String{
var nf1:NumberFormatter = new NumberFormatter();
var result:NumberParseResult = nf1.parse(value);
return nf1.format(result.value);
}
}
}
NF2 - flash.globalization.NumberFormatter
package dstrube
{
import flash.globalization.NumberParseResult;
import flash.globalization.NumberFormatter;
public class NF2
{
public static function get(value:String):String{
var nf2:NumberFormatter = new NumberFormatter("");// LocaleID.DEFAULT = same outcome as without
nf2.fractionalDigits = 2; //= same outcome as without
nf2.trailingZeros = true;
var result:NumberParseResult = nf2.parse(value);
//nf2.parseNumber(value); = NaN
return nf2.formatNumber(result.value)
}
}
}
NF3 - mx.formatters.NumberFormatter (deprecated)
package dstrube
{
//import mx.formatters.NumberBaseRoundType;
import mx.formatters.NumberFormatter;
public class NF3
{
public static function get(value:String):String{
var nf3:NumberFormatter = new NumberFormatter();
//nf3.rounding = NumberBaseRoundType.NEAREST; //no effect in this case
return nf3.format(value);
}
}
}
and finally, the main
<?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" minWidth="955" minHeight="600"
creationComplete="init()"
>
<fx:Script>
<![CDATA[
import dstrube.NF1;
import dstrube.NF2;
import dstrube.NF3;
[Bindable]
public var s:String = "";
protected function init():void{
var value:String = "5558049.90360013";
s = "spark.formatters.NumberFormatter = " + NF1.get(value); //5,558,049.90
s += "\n flash.globalization.NumberFormatter = " + NF2.get(value);//5,558,049,00
s += "\n mx.formatters.NumberFormatter = " + NF3.get(value); //5,558,049.90360013
}
]]>
</fx:Script>
<s:TextArea id="textArea" text="{s}" width="100%" height="100%" />
</s:Application>
The smartest of the three NumberFormatters is flash.globalization.NumberFormatter for recognizing decimal separator, but it rounds incorrectly, showing 5,558,049,00 instead of 5,558,049,90
Any ideas?
You can either:
Explicitly setting the formatter's properties will give you the
output you require.
Set the formatter to use the default locale.
[Bindable] protected var formatted:String;
protected function init(event:FlexEvent):void
{
var formatter:NumberFormatter = new NumberFormatter();
// Option 1 set explicitly
formatter.decimalSeparator = ",";
formatter.fractionalDigits = 2;
formatter.trailingZeros = true;
// Option 2 set default locale to be the locale
formatter.setStyle("locale", LocaleID.DEFAULT);
formatted = formatter.format("5558049.90360013");
}
]]>
</fx:Script>
<s:Label text="{formatted}" />
The output is "5,558,049,90".
This way will display whatever the decimal separator is set to be in the OS's settings.
<?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"
initialize="init(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import spark.formatters.NumberFormatter;
import flash.globalization.NumberFormatter;
[Bindable] protected var formatted:String;
protected function init(event:FlexEvent):void
{
var formatter:spark.formatters.NumberFormatter = new spark.formatters.NumberFormatter();
var nf2:flash.globalization.NumberFormatter = new flash.globalization.NumberFormatter("");
formatter.decimalSeparator = nf2.decimalSeparator;
formatter.fractionalDigits = 2;
formatter.trailingZeros = true;
formatted = formatter.format("5558049.90360013");
}
]]>
</fx:Script>
<s:Label text="{formatted}" />
</s:Application>
Flex Actionscript question.
I have a calloutbutton that is moving on the screen.
When I open the dropdown (by a click) it stays at the same position on the screen (only the arrow is moving). It does not follow the calloutbutton's position
I would like this dropdown to follow the position of the calloutbutton when it has moved (as it does when one clicks on the button again when it has moved).
I have tried to dispatch a MouseEvent.CLICK. It does not work.
Tried also to open, then close again dropdown with actionscript sing closeDropDown() and openDropDown(). No change.
Thanks
Sample code (call init() from creationComplete) :
creationComplete="init();">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import flash.events.MouseEvent;
import mx.events.DropdownEvent;
private function init():void {
var minuteTimer:Timer = new Timer(1*1000);
minuteTimer.addEventListener(TimerEvent.TIMER, updateCalloutPosition);
// starts the timer ticking
minuteTimer.start();
}
private function updateCalloutPosition(event:Event):void {
myButton.closeDropDown();
myButton.x = this.width * Math.random();
myButton.y = this.height * Math.random();
// myButton.openDropDown();
myButton.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
}
protected function myButton_clickHandler(event:MouseEvent):void
{
if (myButton.isPopUp) {
myButton.closeDropDown();
}
else {
myButton.openDropDown();
}
}
]]>
</fx:Script>
<s:CalloutButton id="myButton" click="myButton_clickHandler(event)">
</s:CalloutButton>
I tried some workaround but openDuration and closeDuration is not working for DropDownList if it can be achieved than following code may help you. Hope following code may help you.
<?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" minWidth="955" minHeight="600"
creationComplete="init()">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<s:ArrayCollection id="ac">
<fx:String>AK</fx:String>
<fx:String>AL</fx:String>
<fx:String>AR</fx:String>
</s:ArrayCollection>
</fx:Declarations>
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
#namespace mx "library://ns.adobe.com/flex/halo";
s|DropDownList {
openDuration: 0;
closeDuration: 0;
}
</fx:Style>
<fx:Script>
<![CDATA[
import flash.events.MouseEvent;
import spark.components.supportClasses.DropDownListBase;
import spark.components.supportClasses.TextBase;
import spark.events.DropDownEvent;
import spark.skins.spark.DropDownListSkin;
import spark.utils.LabelUtil;
private var storeVisible:Boolean = false;
private function init():void {
var minuteTimer:Timer = new Timer(1*1000);
minuteTimer.addEventListener(TimerEvent.TIMER, updateCalloutPosition);
minuteTimer.start();
}
private function updateCalloutPosition(event:Event = null):void {
myButton.x = this.width * Math.random();
myButton.y = this.height * Math.random();
if(myButton.isDropDownOpen)
{
myButton.closeDropDown(false);
storeVisible = true;
}
}
private function updateComp():void
{
if(storeVisible)
{
myButton.openDropDown();
storeVisible = false;
}
}
]]>
</fx:Script>
<s:DropDownList id="myButton" selectedIndex="0" dataProvider="{ac}" updateComplete="updateComp()"/>
</s:Application>
Can I write a function inside an attribute in flex? Something like this:
<s:Button id="btn" label="text" visible="{foo()}"/>
private function foo():Boolean
{
//do something
}
It seems it doesn't work at least for me.
I know that I can write like visible="{something == true && somethingElse == false}" etc. But I need it to do more like for loops etc.
Try this:
[Bindable(event="update")]
private function foo():Boolean
{
return a && b && c;
}
and when a or b or c is change just do this:
dispatchEven(new Event("update"));
This implementation is not bindable - if the result of foo() changes, it will not be reflected on your display list.
Although, I think this should work once upon creation complete:
<?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"
minWidth="955"
minHeight="600">
<fx:Script>
<![CDATA[
private function foo():Boolean
{
return false;
}
]]>
</fx:Script>
<s:Button label="text"
visible="{foo()}" />
</s:Application>
A better approach would be to incorporate a presentation model, leveraging binding as seen here:
<?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"
minWidth="955"
minHeight="600"
creationComplete="creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
[Bindable]
public var presentationVisible:Boolean = true;
private var timer:Timer = new Timer(500);
private function foo():void
{
presentationVisible = Math.random() > 0.5 ? true : false;
}
protected function creationCompleteHandler(event:FlexEvent):void
{
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
}
protected function timerHandler(event:TimerEvent):void
{
foo();
}
]]>
</fx:Script>
<s:Button label="text"
visible="{presentationVisible}" />
</s:Application>
If I execute the code below in FlashBuilder, I get the following error (I translate it)
TypeError: Error #1009: Access to an Attribute or Method of an null-Object is not possible.
at components::NumDisplay()[\src\components\NumDisplay.mxml:39]
This line in NumDisplay.mxml is the problem:
[Bindable]
public var oneled_top:OneDisplay = new OneDisplay(numberData.led_top);
If i change it from the above to:
[Bindable]
public var oneled_top:OneDisplay = new OneDisplay(1);
It is working, because I send a real Number.
So how can I access the value from numberData.led_top?
If I test the access in the samefile NumDisplay.mxml with the line
<s:Label text="{numberData.led_top}" color="#FF0000">
</s:Label>
it accesses the value, the same as if I put it in my component
<components:oneLedDisplay showData="{numberData.led_top}" x="10" y="10" />
I don't get it after searching a couple of hours...
Thanks in advance.
My main method tasachenrechner.mxml:
<?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" minWidth="600" minHeight="500" xmlns:components="components.*">
<fx:Script>
<![CDATA[
import components.NumberDisplay;
[Bindable]
protected var firstNumber:NumberDisplay = new NumberDisplay(1);
[Bindable]
protected var secondNumber:NumberDisplay = new NumberDisplay(2);
]]>
</fx:Script>
<components:NumDisplay
numberData="{firstNumber}"
x="10"
y="20"/>
<components:NumDisplay
numberData="{secondNumber}"
x="73"
y="20"/>
</s:Application>
My AS-Class NumberDisplay.as:
package components
{
import flash.display.DisplayObject;
[Bindable]
public class NumberDisplay
{
public var num:Number;
public var led_top:Number=0;
public var led_r1:Number=0;
public var led_r2:Number=0;
public var led_middle:Number=0;
public var led_l1:Number=0;
public var led_l2:Number=0;
public var led_bottom:Number=0;
public function NumberDisplay(num:Number)
{
this.num = num;
switch(this.num)
{
case 0:
trace("ZERo");
break;
case 1:
led_top = 1;
led_r1 = 1;
led_r2 = 1
trace("EINS" + led_top + " num:" + num);
break;
//[... some more cases]
default:
break;
}
}
}
}
My NumDisplay.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="45" height="59"
xmlns:components="components.*">
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
#namespace mx "library://ns.adobe.com/flex/mx";
#namespace components "components.*";
</fx:Style>
<fx:Script>
<![CDATA[
import components.NumberDisplay;
import components.OneDisplay;
[Bindable]
public var numberData:NumberDisplay;
[Bindable]
public var oneled_top:OneDisplay = new OneDisplay(numberData.led_top);
// some more init calls of data-objects same type
]]>
</fx:Script>
<s:Label text="{numberData.led_top}" color="#FF0000">
</s:Label>
<components:oneLedDisplay showData="{oneled_top}" x="10" y="10" />
// some more objects of same type
</s:Group>
My AS-Class OneDisplay.as:
package components
{
import flash.display.DisplayObject;
public class OneDisplay
{
[Bindable]
public var show:Number;
[Bindable]
public var value:Number=0;
public function OneDisplay(show:Number)
{
this.show = show;
switch(this.show)
{
case 0:
value = 0.3;
trace(value);
break;
case 1:
value = 1.0;
trace(value);
break;
}
}
}
}
My oneLedDisplay.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:Group 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[
import components.OneDisplay;
[Bindable]
public var showData:OneDisplay;
]]>
</fx:Script>
<s:Rect id="stroke" width="40" height="6" alpha="{showData.value}">
<s:fill>
<s:SolidColor color="#000000"/>
</s:fill>
</s:Rect>
<s:Label text="{showData.value}" color="#FF0000">
</s:Label>
</s:Group>
Remember that you are not only assigning a value, but declaring the member variable oneled_top. At that point, you cannot access numberData because it has not been instantiated (there is no call to new NumberData()! You have to find a way to make your call to new OneDisplay (numberData.led_top) at a later time, when there actually is a value to access.
You provided lots of code which I don't want to reverse engineer.
The answer is that oneled_top is being initialized before numberData. You have no control over initialization of variables when using MXML.
Set default values in the commitProperties() method, or if oneled_Top is supposed to be a skin part, set the default values in the PartAdded method.
You'll benefit from reading up on the Component Lifecycle.
You can use BindingUtils.bindSetter() to detect changes to numberData and then initialize oneled_top
BindingUtils.bindSetter(_setOneLabel_top, this, "numberData");
and setter:
function _setOneLabel_top(disp:NumberDisplay):void
{
/* if(this.oneled_top == null) */
this.oneled_top = new OneDisplay(disp.led_top);
}
But I think, that u're using [Bindable] where you shouldn't have to need it.
I have a DataGrid with a custom itemRenderer(Canvas) which has a context menu on its right click. I am trying to get the data of the itemRenderer.
I tried to find something in event & variables. I also tried with FlexNativeMenu on RIGHT_MOUSE_CLICK. But I didn't find any way out.
Please help me in getting the data of the itemrenderer or its instance.
contextMenuOwner property of the ContextMenuEvent dispatched by the ContextMenu would point to the itemRenderer of interest.
var renderer:Canvas = Canvas(event.contextMenuOwner);
trace(renderer.data);
trace(renderer.data.something);
Use ContextMenuEvent.mouseTarget:
<?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" initialize="init();">
<fx:Script>
<![CDATA[
import mx.core.IDataRenderer;
private function init():void
{
var dataGridContextMenu:ContextMenu = new ContextMenu();
dataGridContextMenu.hideBuiltInItems();
dataGridContextMenu.addEventListener(ContextMenuEvent.MENU_SELECT,
menuSelectHandler);
dataGrid.contextMenu = dataGridContextMenu;
}
private function menuSelectHandler(event:ContextMenuEvent):void
{
var displayObject:DisplayObject = event.mouseTarget as DisplayObject;
while (!(displayObject is IDataRenderer) && !(displayObject == dataGrid))
{
displayObject = displayObject.parent;
}
var data:Object;
if (displayObject is IDataRenderer)
data = IDataRenderer(displayObject).data;
var customItems:Array = [];
if (data)
{
var contextMenuItem:ContextMenuItem = new ContextMenuItem(data.name, false, false);
customItems.push(contextMenuItem);
}
var menu:ContextMenu = ContextMenu(event.target);
menu.customItems = customItems;
}
]]>
</fx:Script>
<mx:DataGrid id="dataGrid">
<mx:dataProvider>
<s:ArrayCollection>
<fx:Object name="Mike" age="21"/>
<fx:Object name="Juss" age="19"/>
</s:ArrayCollection>
</mx:dataProvider>
</mx:DataGrid>
</s:Application>