I am trying to override a Button class, i have a few properties which i wish directly initialise with the mxml description of the component, like :
<sl:TMyButton id="btnX" x="168" y="223" width="290" label="Button" myproperty1="10" myproperty2="101" myproperty3="4"/>
which function is triggered ( in order to override it ) when all properties with mxml description is fully initialised with their values ?
Flex components have 4 methods in protected namespace which should be overridden to solve different tasks:
createChildren() — calls one time to create and add subcomponents.
measure() called in process of lay outing to calculate components size.
updateDisplayList() has real component unscaled width and height as parameter. It is obvious this method is convenient for positioning of children.
commitProperties() is the method I suggest you to override in order to apply properties values which don't need component size to apply.
So in your case it can be updateDisplayList() or commitProperties(). I recommend you the following code snippets:
private var myproperty1Dirty:Boolean;
private var _myproperty1:String;
public function set myproperty1(value:String):void
{
if (_myproperty1 == value)
return;
_myproperty1 = value;
myproperty1Dirty = true;
// Postponed cumulative call of updateDisplayList() to place elements
invalidateDisplayList();
}
private var myproperty2Dirty:Boolean;
private var _myproperty2:String;
public function set myproperty2(value:String):void
{
if (_myproperty2 == value)
return;
_myproperty2 = value;
myproperty2Dirty = true;
// Postponed cumulative call of commitProperties() to apply property value
invalidatePropertues();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if (myproperty1Dirty)
{
// Perform children placing which depends on myproperty1 changes
myproperty1Dirty = false;
}
}
override protected function commitProperties():void
{
super.commitProperties();
if (myproperty2Dirty)
{
// Apply changes of myproperty2
myproperty2Dirty = false;
}
}
Hope this helps!
Related
The following code is working:
item renderer:
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(editMode)
dispatchEvent(new Event("editLayoutChange"));
}
Datagrid (event handler function for "editLayoutChange" - "viewport" is the AdvancedDataGrid):
public function editLayoutChange(event : Event) : void {
var viewportTopLeft : Point = viewport.localToGlobal(new Point(0,0));
var viewportBottom : Number = viewportTopLeft.y + viewport.height;
var rendererTopLeft : Point = Container(event.target).localToGlobal(new Point(0,0));
var rendererBottom : Number = rendererTopLeft.y + Container(event.target).getLayoutBoundsHeight();
var offset : Number = rendererBottom - viewportBottom;
if(offset > 0) {
// Typical item height is 21px
var itemHeight : Number = 21;
matrix.verticalScrollPosition += Math.ceil(offset / itemHeight);
}
}
But I'm not sure that overriding updateDisplayList is the cleanest implementation as it's firing quite a bit. I tried dispatching the "editLayoutChange" event in response to the "resize" event on the item renderer, but I'm seeing really erratic behavior. Is there a better choice for dispatching this event than updateDisplayList?
Edit - I'm listening on updateDisplayList because the renderer will change size (grow) when it enters edit mode, and can expand dynamically during editing.
The usual way to do this kind of thing is to dispatch from commitProperties -
In your renderer:
private var _editModeEntered:Boolean = false;
private var _editMode:Boolean;
public function set editMode(value:Boolean):void {
_editMode = true;
_editModeEntered = true;
invalidateProperties();
}
// probably want a getter for editMode too
override protected function commitProperties():void {
super.commitProperties();
if (_enteredEditMode) {
dispatchEvent(new Event("editLayoutChange"));
_enteredEditMode = false;
}
}
This ensures the event is dispatched only when you have changed editMode explictly.
You can use Advanced Data Grid public API scrollToIndex(index) to scroll to the row
when i use the following tree renderer class the the informtions in the tree gets chopped. Is there any solution to fix this bug. please help me.
The PLTree class is as follows:
import flash.events.Event;
import mx.events.ScrollEvent;
import mx.controls.Tree;
import mx.core.ScrollPolicy;
import mx.core.mx_internal;
import mx.events.TreeEvent;
public class PLTree extends Tree
{
private var _lastWidth:Number = 0;
private var _lastHeight:Number = 0;
public function PLTree() {
super();
horizontalScrollPolicy = ScrollPolicy.AUTO;
}
override public function get maxHorizontalScrollPosition():Number
{
return mx_internal::_maxHorizontalScrollPosition;
}
override public function set maxHorizontalScrollPosition(value:Number):void
{
mx_internal::_maxHorizontalScrollPosition = value;
dispatchEvent(new Event("maxHorizontalScrollPositionChanged"));
scrollAreaChanged = true;
invalidateDisplayList();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
var diffWidth:Number = measureWidthOfItems(0,0) - (unscaledWidth - viewMetrics.left - viewMetrics.right);
if (diffWidth <= 0) {
maxHorizontalScrollPosition = 0;
horizontalScrollPolicy = ScrollPolicy.OFF;
} else {
maxHorizontalScrollPosition = diffWidth;
horizontalScrollPolicy = ScrollPolicy.ON;
}
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
override protected function scrollHandler(event:Event):void
{
if (mx_internal::isOpening)
return;
// TextField.scroll bubbles so you might see it here
if (event is ScrollEvent){
super.scrollHandler(event);
invalidateDisplayList();
}
}
}
i am attaching the image file of how it looks when executed.
When surfing using google i found a suggesion to fix this bug is it the right way ?
(
Issue: Text getting chopped of at end.
Fix: change
maxHorizontalScrollPosition = diffWidth;
to
maxHorizontalScrollPosition = diffWidth + 10;
or what ever correction factor you need.
)
Kindly help me .Thanks a lot in advance.
Looking at your picture, I'd suspect the issue has nothing to do with the specific tree, and is only slightly related to the renderer. Instead, I think that when the container holding the Tree is created, it doesn't have a size, and when the Tree sizes its renderers, it gives them the wrong size. Since List-based controls don't set the actual width on renderers, choosing to set explicitWidth instead, the renderers aren't triggered into changing their size.
Check out http://www.developria.com/2009/12/handling-delayed-instantiation-1.html for more explicit details and fixes.
similar to the scroll handler in the above mentioned program. Use a mouse wheel scroll handler to handle that event as follows:
override protected function mouseWheelHandler(eventMouse:MouseEvent):void
{ if (mx_internal::isOpening)
return;
if (eventMouse is MouseEvent){
super.mouseWheelHandler(eventMouse);
invalidateDisplayList();
}
}
I'm using default drag/drop on Flex DataGrid, however, the dataGrid itself has an itemrenderer.
Looks like:
public class FlashFileDataGridRenderer extends Label{
public function FlashFileDataGridRenderer(){
super();
}
override protected function updateDisplayList (unscaledWidth:Number, unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
this.setStyle("paddingLeft", "3");
if (data instanceof FlashEntryBean) {
if ((data.cutFlag)) {
setStyle("color", "#AAAAAA");
}
else
setStyle("color", "#000000");
}
That's applied to all items in the datagrid. This no longer shows the proxy with lower alpha when being dragged. I want to be able to retain that style, how can I determine if this particular item is being applied itemrenderer. I am thinking if I can determine if the object is a proxy, then fade the text myself.
Thanks!
Try moving the setStyle calls to the overriden set data method
override public function set data(t:Object):void
{
super.data = t;
if (data instanceof FlashEntryBean) {
if (data.cutFlag)
setStyle("color", "#AAAAAA");
else
setStyle("color", "#000000");
}
}
Not sure which SDK version you're using but in 3.5 it certainly does retain grayish text color in dragged proxy.
I have the following MXML:
<mx:Script>
var someBoolean:Boolean = determineSomeCondition();
</mx:Script>
....
<foo:MyComponent somePropertyExpectingIDataRenderer="{
someBoolean
? new Component1ThatImplementsIDataRenderer()
: new Component2ThatImplementsIDataRenderer()
}">
</foo:MyComponent>
I have also overridden the createChildren() function:
override protected function createChildren():void {
super.createChildren();
//do something with somePropertyExpectingIDataRenderer
}
My problem is: createChildren() is being called before the squiggly bracket logic is being evaluated, so in createChildren(), somePropertyExpectingIDataRenderer is null.
However if I pass the component via MXML like this:
<foo:MyComponent>
<bar:somePropertyExpectingIDataRenderer>
<baz:Component1ThatImplementsIDataRenderer/>
</bar:somePropertyExpectingIDataRenderer>
</foo:MyComponent>
Then when createChildren() is called, that same property isn't null. Is this supposed to happen and if so, what other workarounds should I consider?
You have to wait until your component goes through the first invalidation phase in order to get access to the default value setted in your MXML. This happens just after createChildren() has been called, when the initialize event of your component has been dispatched.
Here is how I would do it :
public function set myProperty(value:IDataRenderer):void
{
if (_myProperty != value)
{
myPropertyChanged = true;
_myPropert = value;
invalidateDisplayList();
}
}
protected override function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
...
if (myPropertyChanged )
doWhateverYouNeedToDo();
}
(Of course, this example supposes changing your property needs a redrawing)
I have a custom ActionScript component that I'm using in a Flex application (Flex 3.3, ActionScript 3). This component contains an Image control whose visibility is set dynamically based on a property of the data element provided to the component.
The problem is that even when I set the image to be visible, it will not render onscreen. Is there something specific I need to do in order for the image to render? Snippets of relevant code below:
override public function set data( value:Object ):void
{
_data = value;
if( _data ) {
if( _myImg ) {
_myImg.source = someImageClass;
_myImg.visible = _data.visibilityProperty;
_myImg.includeInLayout = _data.visibilityProperty;
_myImg.invalidateProperties();
_myImg.invalidateDisplayList();
}
}
invalidateProperties();
invalidateDisplayList();
}
override protected function createChildren():void
{
super.createChildren();
if( !_myImg ) {
_myImg = new Image();
_myImg.height = 16;
_myImg.width = 16;
addChild( _myImg );
}
}
override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
{
super.updateDisplayList( unscaledWidth, unscaledHeight );
_myImg.x = calculatedXCoordinate;
_myImg.y = calculatedYCoordinate;
}
Did you add the component to the display list? It looks like you've added the image to the displaylist of the component, but potentially haven't done anything with the component itself.
It turns out the the above code I posted will, in fact, work properly. I discovered that due to a copy-and-paste bug that I should have caught, I wasn't adding the Image to the display list, hence why it was never appearing.