I have a button which I use for sending a message. When the message text is empty, it should not be possible to click the button.
This is all fine and not an issue. The only thing that is bugging me is the fact that I can disable the send button but the image does not get disabled (like I would expect).
Is there a way to do this elegantly because I don't want to provide a sendicon_disabled.png and change it myself (I don't think this should be my job).
You can use the following button for that:
package
{
import mx.controls.Button;
import mx.core.mx_internal;
use namespace mx_internal;
public class IconButton extends Button
{
private var enabledChanged:Boolean = false;
override public function set enabled(value:Boolean):void
{
if (super.enabled == value)
{
return;
}
super.enabled = value;
enabledChanged = true;
invalidateDisplayList();
}
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if (enabledChanged)
{
if (!enabled && currentIcon)
{
currentIcon.alpha = 0.5;
}
enabledChanged = false;
}
}
}
}
You can use your custom alpha value or move it to separate style.
Related
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 create 3 TitleWindow:
PopUpManager.addPopUp( TitleWindow1, root, false);
PopUpManager.addPopUp( TitleWindow2, root, false);
PopUpManager.addPopUp( TitleWindow3, root, false );
And then I manage those position and depth using mouse. Now I want to delete them by depth.
In my TitleWindow add listener:
root.addEventListener( KeyboardEvent.KEY_DOWN, onKeyDown );
private function onKeyDown(event:KeyboardEvent = null):void {
if ( event.keyCode == Keyboard.ESCAPE && this. ) { //!!!! how to detect this window depth, that it at first plan??
event.preventDefault();
event.stopImmediatePropagation();
closeHandler();
}
}
}
How does me solve this issue?
Now, I can offer one idea, I use state inactive:
private function onKeyDown(event:KeyboardEvent = null):void {
if ( event.keyCode == Keyboard.ESCAPE
&& this.getCurrentSkinState() != "inactive" ) {
event.preventDefault();
event.stopImmediatePropagation();
closeHandler();
}
}
override protected function stateChanged (oldState:String, newState:String, recursive:Boolean) : void {
super.stateChanged( oldState, newState, recursive );
if ( oldState == "inactive" && newState == "normal" ) {
PopUpManager.bringToFront( this );
}
}
You'll need to keep track of this when you add the pop ups. Here is an example class that extends the pop up manager:
package
{
import flash.display.DisplayObject;
import mx.collections.ArrayCollection;
import mx.core.IFlexDisplayObject;
import mx.core.IFlexModuleFactory;
import mx.core.UIComponent;
import mx.managers.PopUpManager;
public class PopManagerDepth extends PopUpManager
{
public function PopManagerDepth() { super(); }
public static var popUpsByDepth :ArrayCollection = new ArrayCollection();
public static function addPopUpWithDepth(window:IFlexDisplayObject,
parent:DisplayObject,
modal:Boolean = false,
childList:String = null,
moduleFactory:IFlexModuleFactory = null):void
{
PopUpManager.addPopUp(window, parent, modal, childList, moduleFactory);
PopManagerDepth.popUpsByDepth.addItem( window );
}
public static function removeLastPopUp():void{
PopManagerDepth.removePopUpByIndex(PopManagerDepth.popUpsByDepth.length);
}
public static function removePopUpByIndex( idx :uint ):void{
if( PopManagerDepth.popUpsByDepth.length > idx){
PopUpManager.removePopUp( popUpsByDepth.getItemAt( idx ) as IFlexDisplayObject );
}
}
}
}
You'd use this class to add your popups, just like popupmanager but with this method:
PopManagerDepth.addPopUpWithDepth( .... );
The difference is there is a new method you'd use to remove them :
PopManagerDepth.removeLastPopUp();
or
PopManagerDepth.removePopUpByIndex();
Should do the trick, sorry I cant test it right now, but should work or close to it. I'll help ya debug if needed :)
By Windows depth do you mean the z-index ? If so you might want to try the getChildIndex and removeChildAt methods on the DisplayObject class. However, since PopUps exists in a different heirarchy than the rest of the general components, I am unsure if this will work but it is a start ?
Here's what I would do:
Create an Array to keep track of each TitleWindow instance you pop up. You can use the Array index as a z-index indicator.
In your closeHandler() method, iterate through each member of the Array and close that TitleWindow instance.
When a combobox is elected in the flex app, there is a quick flicker, then the combobox needs to be selected again in order to get the dropdown to open. After that, the dropdown works as expected, but only while selecting the control subsequent times while on the form. Reloading the form requires the double selection again. Any insights to how to clear this up would be very much appreciated.
The way I had to get around this issue was my creating a custom component that extends the ComboBox control that will set the ComboBox's List dataProvider at the same time as the ComboBox's dataProvider.
ComboBoxFix.as
package
{
import mx.controls.ComboBox;
public class ComboBoxFix extends ComboBox
{
public function ComboBoxFix()
{
super();
}
override public function set dataProvider(value:Object):void
{
super.dataProvider=value;
if(dropdown != null)
{
super.dropdown.dataProvider=value;
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number ):void
{
super.updateDisplayList (unscaledWidth, unscaledHeight);
if (dropdown != null)
{
dropdown.width = unscaledWidth;
}
}
}
}
I'm trying to set the height of a vertical bar (activityBar) but it does not appear to do anything. i have tried something similar with the whole component, but setting the dimensions does nothing (even in the mxml used to instantiate the class). Indeed, I've added transparent graphics just to give the component some dimensions
I'm not sure what I'm doing wrong. It's something bad though; my approach seems dire.
FYI: I'm trying to create a mic activity bar that will respond to the mic by simply setting the height of the activityBar child (which seems to me to be more efficient than redrawing the graphics each time).
Thanks for your help!
package components {
import mx.core.UIComponent;
public class MicActivityBar extends UIComponent {
public var activityBar:UIComponent;
// Constructor
public function MicActivityBar() {
super();
this.opaqueBackground = 0xcc4444;
graphics.beginFill(0xcccccc, 0);
graphics.drawRect(0,-15,5,30);
graphics.endFill();// background for bar
activityBar = new UIComponent();
activityBar.graphics.beginFill(0xcccccc, 0.8);
activityBar.graphics.drawRect(0,-15,5,20);
activityBar.graphics.endFill();
activityBar.height=10;
addChild(activityBar);
}
}
}
package components {
import mx.core.UIComponent;
public class MicActivityBar extends UIComponent {
public var activityBar:UIComponent;
private var _w:Number;
// Constructor
public function MicActivityBar() {
super();
this.opaqueBackground = 0xcc4444;
graphics.beginFill(0xcccccc, 0);
graphics.drawRect(0,-15,5,30);
graphics.endFill();// background for bar
activityBar = new UIComponent();
activityBar.graphics.beginFill(0xcccccc, 0.8);
activityBar.graphics.drawRect(0,-15,5,20);
activityBar.graphics.endFill();
activityBar.height=10;
addChild(activityBar);
}
public function get w():Number {
return _w;
}
public function set w(value:Number):void {
_w = value;
}
override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
this.height=w;
this.weight=w;
}
}
}
See my updated code above.
package {
import mx.controls.LinkButton;
import flash.text.TextLineMetrics;
public class multiLineLinkButton extends LinkButton {
override protected function createChildren():void {
super.createChildren();
if (textField){
textField.wordWrap = true;
textField.multiline = true;
}
}
override public function measureText(s:String):TextLineMetrics {
textField.text = s;
var lineMetrics:TextLineMetrics = textField.getLineMetrics(0);
lineMetrics.width = textField.textWidth;
lineMetrics.height = textField.textHeight;
return lineMetrics;
}
}
my issue here is if you use this component you will see that the text is bunched up into a very small area. It does not fill the entire width of the linkButton. Anyone know why this is happening?
The container is probably not wide enough. Set the container percentWidth to 100 and see if it fixes your problem. You can also set the LinkButton to a fixed width and see if that helps.