How to manually remove view component from Parsley context?
Lets say I have one view and main application.
I have done the following but it does not work - view remains within Parsley context.
Main Application:
<s:Application>
<parsley:ContextBuilder config="ApplicationConfig"/>
<view:SomeView id="someView"/>
<s:Button label="Enable View"
click="enableViewHandler()"/>
<s:Button label="Disable View"
click="disableViewHandler()"/>
<fx:Script>
private function enableViewHandler():void {
someView.dispatchEvent(new Event("configureView", true));
}
private function disableViewHandler():void {
someView.dispatchEvent(new Event("removeView", true));
}
</fx:Script>
</s:Application>
View Component:
<s:VGroup>
<fx:Metadata>
[Autoremove("false")]
</fx:Metadata>
</s:VGroup>
The only solution I have found is to change enableViewHandler() to Configure.view(someView).autoremove(false).execute();
Related
i have a datagroup compoenent in Adobe Air application and i have used custom itemrenderer in it, i attached source code of itemRenderer as well as i attached profiling of it,
Question:
When i come back from other module to the module which have this datagroup at that time it again create Objects for itemrender and previous object of itemrender wont released.
if you have idea, please suggest me
<?xml version="1.0" encoding="utf-8"?>
<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="false"
buttonMode="true"
click="clickHandler(event)"
mouseChildren="false"
rollOut="rollOutHandler(event)"
rollOver="rollOverHandler(event)"
removedFromStage="itemrenderer1_removedFromStageHandler(event)"
creationComplete="itemrenderer1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import coX.XXXXXXXXXXXXXXX.event.ThumbEvent;
import mx.events.FlexEvent;
protected function image_completeHandler(event:Event):void
{
ConsoleUtils.logIt(" ThumbImage.mxml :image_completeHandler - ");
image.removeEventListener(Event.COMPLETE, image_completeHandler);
fadeIn.target=image;
fadeIn.play();
}
protected function clickHandler(event:MouseEvent):void
{
owner.dispatchEvent(new ThumbEvent("itemclick", data, itemIndex));
}
protected function rollOverHandler(event:MouseEvent):void
{
owner.dispatchEvent(new ThumbEvent("itemrollover", data, itemIndex));
}
protected function rollOutHandler(event:MouseEvent):void
{
owner.dispatchEvent(new ThumbEvent("itemrollout", data, itemIndex));
}
protected function itemrenderer1_removedFromStageHandler(event:Event):void
{
this.removeEventListener(Event.REMOVED_FROM_STAGE, itemrenderer1_removedFromStageHandler);
this.removeEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
this.removeEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
this.removeEventListener(MouseEvent.CLICK, clickHandler);
this.removeAllElements();
}
protected function itemrenderer1_creationCompleteHandler(event:FlexEvent):void
{
this.removeEventListener(FlexEvent.CREATION_COMPLETE, itemrenderer1_creationCompleteHandler);
image.source="test.png";
//image.addEventListener(Event.COMPLETE, image_completeHandler);
}
]]>
</fx:Script>
<fx:Declarations>
<s:Fade id="fadeIn"
alphaFrom="0"
alphaTo="1"/>
</fx:Declarations>
<s:BitmapImage id="image"
horizontalAlign="center"
smooth="true"
smoothingQuality="high"
verticalAlign="middle"/>
</s:ItemRenderer>
Snapshot of Profiling
as you can see, in profile, i have 21 orphan objects which won't recyle and profiling shows me that at saved at line no 12 while line no 12 is creation_complete event and i have removed it.
Thanks in Advance
i have used DataGroup as parent component and i have define above itemRenderer in itemRenderer property of the DataGroup, and in dispose function i have define DataGroup.itemRenderer is null in DataGroup. so it will eligible for GC. and i see that now no instance of itemRenderer is in memory.
Here is my code.
<?xml version="1.0" encoding="utf-8"?>
<fx:Script>
<![CDATA[
import comps.sampleTextArea;
import mx.managers.PopUpManager;
protected function button1_clickHandler(event:MouseEvent):void
{
var pop:sampleTextArea = new sampleTextArea();
PopUpManager.createPopUp(this, sampleTextArea, false);
PopUpManager.centerPopUp(pop);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Button click="button1_clickHandler(event)" label="open popup"/>
and here is code of popup
<?xml version="1.0" encoding="utf-8"?>
<fx:Script>
<![CDATA[
import mx.managers.PopUpManager;
protected function button1_clickHandler(event:MouseEvent):void
{
ta.text = '';
PopUpManager.removePopUp(this);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:layout>
<s:VerticalLayout horizontalAlign="center" verticalAlign="top" />
</s:layout>
<s:TextArea id="ta" width="100%" height="90%">
</s:TextArea>
<s:Button label="Submit" click="button1_clickHandler(event)" />
when i click on text area following error through by the application.
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at spark.components::Scroller/focusInHandler()[E:\dev\4.y\frameworks\projects\spark\src\spark\components\Scroller.as:2139]
at flash.display::Stage/set focus()
at flashx.textLayout.container::ContainerController/http://ns.adobe.com/textLayout/internal/2008::setFocus()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\container\ContainerController.as:2265]
at flashx.textLayout.container::ContainerController/mouseDownHandler()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\container\ContainerController.as:2067]
at flashx.textLayout.container::TextContainerManager/mouseDownHandler()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\container\TextContainerManager.as:1939]
at spark.components.supportClasses::RichEditableTextContainerManager/mouseDownHandler()[E:\dev\4.y\frameworks\projects\spark\src\spark\components\supportClasses\RichEditableTextContainerManager.as:666]
at flashx.textLayout.container::ContainerController/http://ns.adobe.com/textLayout/internal/2008::requiredMouseDownHandler()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\container\ContainerController.as:2088]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.core::UIComponent/dispatchEvent()[E:\dev\4.y\frameworks\projects\framework\src\mx\core\UIComponent.as:13152]
at mx.managers::SystemManager/mouseEventHandler()[E:\dev\4.y\frameworks\projects\framework\src\mx\managers\SystemManager.as:2918]
How i handle this issue
try, because this refer to stage no the clicked element:
PopUpManager.removePopUp(event.target);
You may not be able to popup a focusable component inside a
non-IFocusManagerContainer. If your Group container implements IFocusManagerContainer class, you may use PopUpManager.
<s:Group implements="mx.managers.IFocusManagerContainer"/>
I ran into the same issue, and the root cause was that PopUpManager/PopUpAnchor would not properly set the focusManager if the component being popped up does not implement the IFocusManagerContainer interface. After implementing such interface, the problem goes away.
You may read this blog post that inspired the solution.
After doing many experiments/ways i conclude that problem is due to the popup component parent container.
I use Group/VGroup/HGroup of spark then this issue remains but if i change the parent container with spark Panel/SkinnableContainer then issue solved.
Try yourself and enjoy.
this is one script in my.mxml
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
public function __changeSel():void{
}
]]>
</fx:Script>
another script in component tag in same my.mxml
<fx:Component>
<s:ComboBox change="changeSel(event)">
<s:id>selID</s:id>
<s:dataProvider>
<s:ArrayCollection>
<fx:String>Less Than</fx:String>
</s:ArrayCollection>
</s:dataProvider>
<fx:Script>
<![CDATA[
public function changeSel(even:Event):void{
__changeSel();
}
]]>
</fx:Script>
</s:ComboBox>
</fx:Component>
But when i call __changeSel(); it dose not recognize this function. is there any way to get this thing fixed.
You should not use inline components. That leads to a scope shift. Write a proper self contains component and dispatch events over the display list, so the composites root can set a listener on the bubbling events.
Otherwise try to use outerDocument in the inline renderer to invoke the method.
I would like to know if it's possible to skin view for my Flex mobile application :
My ActivityView.as
public class ActivityView extends View
My ActivityViewSkin.mxml (It skin associated)
<?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("com.corp.views.activity.ActivityView")]
...
It's a good way for mobile development ?
And how can I use this in this skin :
<s:navigationContent>
Thank you very much !
Anthony
no.
Spark skin is not optimized for mobile. you should use MobileSkin . (Action script only).
I have been looking for similar information, however everything I can deduce from documentation and blogs implies that MobileSkin is something you do for component-level skinning (e.g. buttons, lists, itemRenderers, etc.), things that would be used many times throughout the app.
THe other reason to think you might be able to get away with skinning your View via MXML is that all the Views I have seen code for are done so declaratively (MXML) and by skinning the View subclass using just the Skin class, you are only adding one more layer of hierarchy via the contentGroup in most skinnableContainer skins.
If you are using spark.components.View, then you are using a skin associated with as it is a SkinnableContainer. It is NOT a simple group as you might think.
I dunno, I am kinda at a loss as to where to focus my efforts. I am sure performance implications (if any) will rear their heads way later in the development stage.
From experience so far, you don't skin the View. You skin the ViewNavigatorApplication. First, create the custom skin:
public class DViewNavigatorApplicationSkin extends ViewNavigatorApplicationSkin
{
[Embed(source="assets/wine_240.jpg")]
protected var cornerImage:Class;
public function DViewNavigatorApplicationSkin()
{
super();
}
override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
{
graphics.beginFill(0x000000);
graphics.drawRect(0,0, unscaledWidth, unscaledHeight);
graphics.endFill();
var ba:BitmapAsset = new cornerImage() as BitmapAsset;
var translateMatrix:Matrix = new Matrix();
translateMatrix.tx = unscaledWidth - ba.width;
translateMatrix.ty = unscaledHeight - ba.height;
graphics.beginBitmapFill(ba.bitmapData, translateMatrix);
graphics.drawRect(unscaledWidth - ba.width + 1, unscaledHeight - ba.height + 1, ba.width, ba.height);
graphics.endFill();
}
The contents of drawBackground docks the image to the lower right-hand corner of the display. You can draw anything in this function.
Then in the theme.css:
s|ViewNavigatorApplication
{
color: #ffffff;
focusColor: #ff9999;
skinClass: ClassReference("com.domain.skins.mobile.ThemeName.DViewNavigatorApplicationSkin");
}
s|View
{
backgroundAlpha: 0;
}
You draw the background image on the application itself. You then make the View totally transparent so that you can see the background image through it.
It may be possible to skin each individual view, but so far, it seems more practical to skin the application instead.
It is kinda late to answer this question. Actually, we can use Spark Skin to skin the View component without any problem. View is just a subclass of SkinnableContainer (which is subclass of SkinnableComponent) so by default, whatever content you add directly to the MXML of View component will be added to contenGroup of SkinnableContainer.
I have added an example to skin the View using Spark Skin:
Main Application:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" applicationDPI="160">
<fx:Script>
<![CDATA[
import com.accessdigital.core.SimpleView;
]]>
</fx:Script>
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
#namespace core "com.accessdigital.core.*";
core|SimpleView{
skinClass : ClassReference("skin.view.Skin_SimpleView");
}
</fx:Style>
<s:ViewNavigator width="100%" height="100%"
firstView="{SimpleView}">
</s:ViewNavigator>
</s:Application>
View Class
public class SimpleView extends View
{
public function SimpleView()
{
super();
}
[SkinPart(required="true")]
public var myButton:Button;
override protected function createChildren():void{
super.createChildren();
var anotherButton:Button = new Button();
anotherButton.label = "Another button";
anotherButton.addEventListener(MouseEvent.CLICK, onAnotherButtonClick);
if(!actionContent){
actionContent = [];
}
actionContent.push(anotherButton);
}
protected function onAnotherButtonClick(event:MouseEvent):void
{
trace("This is another button");
}
override protected function partAdded(partName:String, instance:Object):void{
super.partAdded(partName, instance);
if(instance == myButton){
myButton.addEventListener(MouseEvent.CLICK, onButtonClick);
}
}
protected function onButtonClick(event:MouseEvent):void
{
trace("This is a simple button");
}
}
Skin File:
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<!-- host component -->
<fx:Metadata>
[HostComponent("com.accessdigital.core.SimpleView")]
</fx:Metadata>
<!-- states -->
<s:states>
<s:State name="disabled" />
<s:State name="normal" />
</s:states>
<!-- SkinParts
name=myButton, type=spark.components.Button, required=true
name=contentGroup, type=spark.components.Group, required=false
-->
<s:Rect width="100%" height="100%">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="#666666"/>
<s:GradientEntry color="#222222"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Group id="contentGroup" width="100%" height="100%">
<s:Button id="myButton" label="My Button" horizontalCenter="0" verticalCenter="0"/>
</s:Group>
</s:Skin>
Hope it helps
I created a custom MXML component, TurboContent, that extends the NavigatorContent class:
<s:NavigatorContent 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:Metadata>
[DefaultProperty("mxmlContentFactory")]
</Fx:Metadata>
<s:Group id="midWrapper">
<s:Button id="btnAdd" />
</s:Group>
<s:Group id="rightWrapper" >
<s:DataGrid id="dgdSelect" >
<s:columns>
<s:ArrayList>
<s:GridColumn headerText="Yo"></s:GridColumn>
</s:ArrayList>
</s:columns>
</s:DataGrid>
<s:Button id="btnRemove" />
<s:Button id="btnClear" />
</s:Group>
</s:NavigatorContent>
I am trying to extend that custom component but when I add display elements to the second extended componet they elements are never seen. For instance: (The first custom component is in the comp package)
<comp:TurboContent 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:comp="comp.*">
<s:Button id="myButton"/>
</comp:TurboContent>
In this case, the 'myButton' component never shows up, but all the elements of the base component do (3 buttons and a datagrid).
I'm curious to understand what you're trying to achieve?
From the pieces of code it seems you're trying to compose a new view which visually inherits the TurboContent-component and adds another button to it.
What happens really under the hood is that the NavigatorContent extends SkinnableContainer. SkinnableContainer has as a default property mxmlContentFactory, which once initialized can not be changed or substituted, or add stuff on top of it, unless you do that with ActionScript:
mxmlContentFactory = null; // or some IDeferredInstance
But then your approach of visual inheritance won't be visual inheritance, but content substitution.
The base class already has initialized it, so the subclasses can't do modifications to it.
From what I can tell, the pattern of defining a component directly in MXML (as you referenced was done in the FIAW series) disallows the ability to then visually insert children in the container's display list. One of the problems is that the mxmlContent (which normally a skin would control) is statically defined in the component and it doesn't seem like one can use contentGroup inside the MXML component directly.
For better control, and what I consider a more strict implementation of the MVC pattern (which Flex 4, as a framework, implements), try separating your visual layout out into an MXML skin, and defining the component in AS3.
From what little I see of your component, I can't really make a judgment as to what properties of the component you want to expose to the container that will instantiate it. I'll at least give an example here of how one can pass info from the component to the skin.
I apologize for the MX components, but I only have Flex 4.1, and I wanted to make sure the program compiled fine. It shouldn't be too hard for you to swap in the spark versions.
Example Component (TurboContentAS.as)
package components {
import mx.controls.DataGrid;
import spark.components.NavigatorContent;
public class TurboContentAS extends NavigatorContent {
public function TurboContentAS() {
super();
}
// Skin Parts that constitute the necessary parts of the component
[SkinPart(required="true")]
public var dgdSelect:DataGrid; //just an example
// property you want to expose to the instantiating object
[Bindable]
public var firstColumnHeader:String = "default header";
}
}
Example Skin (TurboContentSkin.mxml)
<?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"
xmlns:mx="library://ns.adobe.com/flex/mx"
alpha.disabled="0.5" >
<fx:Metadata>[HostComponent("components.TurboContentAS")]</fx:Metadata>
<s:states>
<s:State name="normal" />
<s:State name="disabled" />
</s:states>
<!-- this is where the children that you add later go-->
<s:Group id="contentGroup" left="0" right="0" top="100" bottom="0" minWidth="0" minHeight="0">
<s:layout>
<s:BasicLayout/>
</s:layout>
</s:Group>
<s:Group id="midWrapper">
<s:Button id="btnAdd" label="Add" />
</s:Group>
<s:Group id="rightWrapper" left="200">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<mx:DataGrid id="dgdSelect">
<mx:columns>
<fx:Array>
<!-- This will bind to the publicly exposed property in the component definition -->
<mx:DataGridColumn headerText="{hostComponent.firstColumnHeader}"/>
</fx:Array>
</mx:columns>
</mx:DataGrid>
<s:Button id="btnRemove" label="Remove"/>
<s:Button id="btnClear" label="Clear"/>
</s:Group>
</s:Skin>
Example Instantiation
<components:TurboContentAS skinClass="skins.TurboContentSkin" firstColumnHeader="myHeader">
<s:Button label="myButton"/>
</components:TurboContentAS>