I can't get my TextArea to take the focus skin which I did in the mxml skin file below. Can anyone help me with this. Note that in my application css file I have specified the focus skin as such : focus-skin: ClassReference("skins.focusSkin");
Skin File Code:
<?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">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import spark.components.supportClasses.SkinnableComponent;
private var _target:SkinnableComponent;
public function get target():SkinnableComponent
{
return _target;
}
public function set target(value:SkinnableComponent):void
{
_target = value;
if (_target.skin)
_target.skin.addEventListener(FlexEvent.UPDATE_COMPLETE,
skin_updateCompleteHandler, false, 0, true);
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
this.setActualSize(target.width, target.height);
super.updateDisplayList(target.width, target.height);
}
private function skin_updateCompleteHandler(event:Event):void
{
invalidateDisplayList();
}
]]>
</fx:Script>
<s:BitmapImage id="focusGroup" source="#Embed(source='mySkinFile.swf', symbol='mySymbol')" />
</s:Group>
Take a look at the examples in this blog post that demonstrates how to create custom focus skins in spark:
http://flexponential.com/2010/01/24/custom-focusskin-for-spark-components-in-flex-4/
Related
I have a Flex application which sends a query to a database when an user clicks a button. Since the query might be heavy, and can take up to a minute, I want to display an alert, which will close only after an event comes back from the database (user won't be able to close it himself). Is it possible in Flex? How do I do that?
I have functions sendQuery() and dataEventHandler(). I think I need to put code in sendQuery() to display the alert and in dataEventHandler() to close it after data comes from the DB, but how do I make the alert "unclosable" by the user?
The built in Flex Alert class will always have some type of close button.
However, there is no reason you can't create your own component; and then open and close it using the PopUpManager.
Following code may help you… (One of the solution...)
You can find I have made Solution 1 and Solution 2… You can use any one of it and third solution is to create your own Custom Component.
Please find below code…. You can use below logic to solve your problem..
Use Timer to check if data received or you can dispatch custom event and call updateAlertPosition function.
Hope it may help: -
<?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:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.CloseEvent;
import mx.managers.PopUpManager;
private var minuteTimer:Timer;
private var alert:Alert;
private var displayInitialText:String = "Data Not Received, Please wait....";
private var displayDataReveivedText:String = "Data Received...";
private function timerInit():void
{
//Logic to check if data Received.
minuteTimer = new Timer(3000);
minuteTimer.addEventListener(TimerEvent.TIMER, updateAlertPosition);
minuteTimer.start();
}
private function updateAlertPosition(event:Event = null):void {
minuteTimer.stop();
//Solution 1
//add your flag here if y you want to check if data is received or not
//if(Data Received)
alert.mx_internal::alertForm.mx_internal::buttons[0].enabled = true;
alert.mx_internal::alertForm.mx_internal::buttons[1].enabled = true;
alert.mx_internal::alertForm.mx_internal::textField.text = displayDataReveivedText;
//Solution 2
//alert.enabled = true;
//If you want to remove it automatically
//closeAutomatically();
}
private function closeAutomatically():void
{
PopUpManager.removePopUp(alert);
}
private function clickHandler():void
{
//Start Timer
timerInit();
//Solution 1
alert = Alert.show(displayInitialText, "Alert", Alert.OK|Alert.CANCEL,this,alertCloseHandler);
alert.mx_internal::alertForm.mx_internal::buttons[0].enabled = false;
alert.mx_internal::alertForm.mx_internal::buttons[1].enabled = false;
//Solution 2
//alert.enabled = false;
}
private function alertCloseHandler(event:CloseEvent):void
{
if(event.detail == Alert.CANCEL)
{
//Some Code on close
}
else
{
//Some Code on OK
}
}
]]>
</fx:Script>
<s:Button label="Show Alert" x="100" y="100" click="clickHandler()"/>
</s:Application>
make a 0-0.2 alpha shape what covers the whole application (probably you'll want to listen for resizeevents), and add a custom panel to the middle of it, with the message.
As an idea you can create a custom alert then:
Show Alert
Disable Application.
Hide Alert.
Enable Application.
An alert example:
<?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="400" height="300"
creationComplete="onCreationComplete(event)">
<s:Rect>
<s:fill>
<s:SolidColor color="0xFFFFFF"/>
</s:fill>
<s:stroke>
<s:SolidColorStroke />
</s:stroke>
</s:Rect>
<s:Label text="Please Wait..."/>
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
import mx.events.FlexEvent;
import mx.managers.PopUpManager;
public static function show():void
{
PopUpManager.createPopUp(FlexGlobals.topLevelApplication);
}
public static function hide():void
{
PopUpManager.removePopUp(this);
FlexGlobals.topLevelApplication.enabled = true;
}
protected function onCreationComplete(event:FlexEvent):void
{
PopUpManager.centerPopUp(this);
FlexGlobals.topLevelApplication.enabled = false;
}
]]>
</fx:Script>
</s:Group>
Usage:
YourAlert.show();
YourAlert.hide();
#Alex, I used your code but modify it a bit, because there was some errors:
<?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"
creationComplete="creationCompleteHandler()" width="100%" height="100%">
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
import mx.core.UIComponent;
import mx.managers.PopUpManager;
///////////////////////////////////////
//// public functions - my group is ImageViewer.mxml component
public static function show():ImageViewer {
return PopUpManager.createPopUp(FlexGlobals.topLevelApplication as DisplayObject, ImageViewer) as ImageViewer;
}
public function hide():void {
PopUpManager.removePopUp(this);
FlexGlobals.topLevelApplication.enabled = true;
}
////////////////////////////
//// component events
private function creationCompleteHandler():void {
PopUpManager.centerPopUp(this);
FlexGlobals.topLevelApplication.enabled = false;
}
]]>
</fx:Script>
</s:Group>
And call it like:
var imageviewer:ImageViewer = ImageViewer.show();
//imageviewer.imageURL = _value_dto.value;
I have to create the image object using something like this
[Embed("/assets/images/Header.png")]
public static var HeaderIcon:Class;
but now the string within embedd is dynamically brought from some xml
like xmlObject.child("icon"); which I tried it like
[Embed(xmlObject.child('icon').toString())]
public static var HeaderIcon:Class;
However it gives errors like
invalid metadata
I am using the above code in action script(as is obvious)
Is there any way to solve this?
You need to use the Loader class: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Loader.html
It's a bit more complicated than with embedded resources, but there are good examples in the documentation.
Class Name: -HeaderIconClass
//////////
package
{
import spark.components.Image;
internal dynamic class HeaderIconClass extends Image
{
public function HeaderIconClass()
{
super();
}
}
}
Inside your component or Application level: -
<?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="application1_creationCompleteHandler(event)">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
[Bindable]
public var headerIcon:HeaderIconClass = new HeaderIconClass();
//For your testing
protected function button1_clickHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
imageID.source = headerIcon.source
}
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
// TODO Auto-generated method stub
headerIcon.source = "#Embed('/assets/images/Header.png')";
}
]]>
</fx:Script>
<mx:VBox x="100" y="100">
<s:Button label="Show Image" click="button1_clickHandler(event)"/>
<s:Image id="imageID" width="50" height="50"/>
</mx:VBox>
</s:Application>
If you want to use this you can save this in variable: -
private var imagePath:String = xmlObject.child('icon').toString();
and change below function as: -
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
// TODO Auto-generated method stub
headerIcon.source = "#Embed('"+imagePath+"')";
}
Hope this may help .....
I have a flex application and a papervision BasicView. I would like to add a new flex UIComponent (such as a button) from within the papervision class. I have posted the full example code below. It works but I would like to be able to accomplish my goal without the "(this.parent.parent as Group).addElement(button);" line.
<!--Application 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="50" minHeight="50"
creationComplete="Init()" applicationComplete="Start()">
<fx:Script>
<![CDATA[
import mx.core.UIComponent;
import spark.components.Button;
public var start:QuickStart;
public function Init():void
{
start = new QuickStart();
var uicomp:UIComponent = new UIComponent();
addElement( uicomp );
uicomp.addChild( start );
}
public function Start():void
{
start.GoTime();
}
]]>
</fx:Script>
</s:Application>
//QuickStart.as
package{
import org.papervision3d.view.BasicView;
public class QuickStart extends BasicView
{
public function QuickStart()
{
super(500, 500, true, true);
}
public function GoTime():void
{
var button:Button = new Button;
//this is the offending line
(this.parent.parent as Group).addElement(button);
}
}
}
The version I have does work so please excuse any minor typos.
Logically you would dispatch an event inside your BasicView, listen for it in your main application, and create the button from up there. In a prefect OOP world, every class should be a black box sending events :)
I created a somewhat custom Spark button by doing the File > New > MXML skin and basing it on spark.components.button. The problem is that I need to add an extra text field to the button component and dynamically change that text...but of course, the property isn't recognized on a Spark Button.
Is there a simple way to add this field to my custom button skin & its property so it can be addressed? If not, is there a simple way to take what I've done and just extend the Spark Button? I can't seem to find any examples that show how to do it without writing it all up in ActionScript.
I'm glad you asked! This is much easier than you'd think so don't be discouraged! ActionScript is pretty easy once you get the hang of it.
First of all, let's define what we want. After reading your question I believe you would like to use your button something like this:
<local:MyCustomButton label="Hello" label2="World!"/>
So let's go over how to make that a reality.
Now, I would highly suggest extending Button with ActionScript, but it is also possible to do in mxml:
//MyCustomButton.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Button 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:Button>
Then you can add the SkinParts you need in a <fx:Script>:
<?xml version="1.0" encoding="utf-8"?>
<s:Button 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[
[SkinPart]
public var secondLabelDisplay:spark.components.Label;
]]>
</fx:Script>
</s:Button>
So now when you make a skin you should include something like the original label, just with a different ID to reflect your new SkinPart:
But wait! What text should our second label show?? Well, we will need to add another property that you can set for each individual instance of the button:
<?xml version="1.0" encoding="utf-8"?>
<s:Button 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[
[SkinPart]
public var secondLabelDisplay:spark.components.Label;
private var _label2:String;
public function get label2():String
{
return _label2;
}
public function set label2(value:String):void
{
_label2 = value;
}
]]>
</fx:Script>
</s:Button>
Cool, so now we can set label2 when we use our button, but at this point it won't change the label's actual text property. We need to hook up our label2 to our secondLabelDisplay. We do this by calling invalidateProperties when the label2 changes and then change the label in commitProperties (which will be called because of the invalidateProperties() call):
<?xml version="1.0" encoding="utf-8"?>
<s:Button 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[
[SkinPart]
public var secondLabelDisplay:spark.components.Label;
private var _label2:String;
private var label2Changed:Boolean;
public function get label2():String
{
return _label2;
}
public function set label2(value:String):void
{
_label2 = value;
label2Changed = true;
invalidateProperties();
}
override protected function commitProperties():void
{
super.commitProperties();
if(label2Changed)
{
label2Changed = false;
secondLabelDisplay.text = label2;
}
}
]]>
</fx:Script>
</s:Button>
Lastly, you'll notice that if you change label2 again afte runtime, the label will show the change. But it won't show the change if you set an initial label2 like in our target usage. The Flex team made a special method just for this case, partAdded(). I won't go over too many details about it because there is already a good amount of literature on the subject.
Finally, here's our finished, custom button awaiting a skin to put it to use:
<fx:Script>
<![CDATA[
[SkinPart]
public var secondLabelDisplay:spark.components.Label;
private var _label2:String;
private var label2Changed:Boolean;
public function get label2():String
{
return _label2;
}
public function set label2(value:String):void
{
_label2 = value;
label2Changed = true;
invalidateProperties();
}
override protected function commitProperties():void
{
super.commitProperties();
if(label2Changed)
{
label2Changed = false;
secondLabelDisplay.text = label2;
}
}
override protected function partAdded(partName:String, instance:Object):void
{
if(instance == secondLabelDisplay)
{
secondLabelDisplay.text = _label2;
}
}
]]>
</fx:Script>
Best of luck!
I'm trying to prevent a custom tooltip from disappearing. I've tried three runs at this, borrowing from the usual suspects: Peter Dehann, MonkeyPatch and others. As you can see from the code below I'd like to stay within the tool tip paradigm and not go to popups.
Can anyone suggest a way to persist a tooltip? The intent here is to have a component which can be cut and paste from.
Thanks,
Doug
<?xml version="1.0" encoding="utf-8"?>
<s:Application minHeight="600" creationComplete="application1_creationCompleteHandler(event)"
minWidth="955"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.events.ToolTipEvent;
protected function button1_clickHandler(event:MouseEvent):void {
// TODO Auto-generated method stub
}
protected function button1_toolTipCreateHandler(event:ToolTipEvent):void {
createCustomToolTip("title", "", event);
}
// TODO Auto-generated method stub
private function createCustomToolTip(title:String, body:String, event:ToolTipEvent):void {
var ptt:CustomToolTip = new CustomToolTip();
ptt.title = title;
ptt.bodyText = (event.currentTarget as Button).toolTip;
event.toolTip = ptt;
}
protected function button1_toolTipHideHandler(event:ToolTipEvent):void
{
// TODO Auto-generated method stub
event.stopPropagation();
event.preventDefault();
event.stopImmediatePropagation();
}
import mx.managers.ToolTipManager;
private var tt:CustomToolTip;
private var cc:CustomToolTip;
private function create_toolTip():void {
var str:String = "Tooltip text goes here...";
// We only want one tooltip.
if (tt == null) {
tt = ToolTipManager.createToolTip(str, 100, 50) as CustomToolTip;
}
}
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
// TODO Auto-generated method stub
mx.managers.ToolTipManager.toolTipClass = CustomToolTip;
//mx.managers.ToolTipManager.scrubDelay = 100000;
//mx.managers.ToolTipManager.hideDelay = 1000000;
}
protected function button1_toolTipEndHandler(event:ToolTipEvent):void
{
event.preventDefault();
event.stopImmediatePropagation();
// TODO Auto-generated method stub
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<mx:VBox>
<mx:Button click="button1_clickHandler(event)"
toolTip="helloWorld" toolTipHide="button1_toolTipHideHandler(event)" toolTipEnd="button1_toolTipEndHandler(event)"
toolTipCreate="button1_toolTipCreateHandler(event)" >
</mx:Button>
<mx:Button label="create tool tip" click="create_toolTip();" />
<mx:Button toolTip="hello world" label="hello">
</mx:Button>
</mx:VBox>
</s:Application>
Use some JavaScript that to show the tooltip in the onmouseover portion of the link:
<a href="page.aspx" onmouseover=showtooltip("Tooltip Text")></a>
don't include any JavaScript routine like onmouseout=hidetooltip() in your link, it will stay open.
P.S.: You can put a link in the "Tooltip Text" that includes onmouseout=hidetooltip(), something like:
<a href=originalpage.aspx onclick=hidetooltip()>Close</a>