Removing a blinking cursor in Flex Flash Player - apache-flex

I have a MX TextInput field on my form. As one of our user has seizure problems with blinking cursors, I am trying to disable it but without success. Through Control Panel, I have been able to prevent a blinking cursor in Office Apps and on the Web browsers but not with the Flex Application which uses the Flash Player. Has anyone come across this issue and have a solution?

Here's a simple solution that removes the cursor all together. I'm not sure if you want to remove the cursor (feasible) or stop the cursor from blinking (seems less feasible).
It works by setting the underlying TextField object's selectable property to false. The MX TextInput class has it's own selectable property, however, the code in TextInput also requires the editable property to be false to disable selection. So you need to extend TextInput to work around that.
The underlying TextField doesn't expose any properties to stop the cursor from blinking (that I'm aware of). TextField is one of Flash Player's built in classes, so the chances of modifying this low level behavior seem slim.
This obviously breaks the ability to copy/paste in the TextInput. You might have to devise a way to temporarily enable selection to support copy/paste or selecting text in general.
package
{
import mx.controls.TextInput;
public class CustomTextInput extends TextInput
{
public function CustomTextInput()
{
}
private var _hideCursor:Boolean = true;
private var hideCursorChanged:Boolean = true;
public function get hideCursor():Boolean
{
return _hideCursor;
}
public function set hideCursor(value:Boolean):void
{
if (value == hideCursor)
{
return;
}
hideCursorChanged = true;
_hideCursor = value;
invalidateProperties();
}
override protected function commitProperties():void
{
super.commitProperties();
if (hideCursorChanged)
{
hideCursorChanged = false;
textField.selectable = !_hideCursor;
}
}
}
}

Related

Interaction with parent control triggers RippleDrawable in Xamarin.Forns custom renderer

I have implemented a custom clickable label class in Xamarin.Forms along with a custom renderer, that adds a RippleDrawable as the controls Foreground. I am creating the RippleDrawable with the following code:
public static Drawable CreateRippleDrawable(Context context)
{
var typedValue = new TypedValue();
context.Theme.ResolveAttribute(Resource.Attribute.SelectableItemBackground, typedValue, true);
var rippleDrawable = context.Resources.GetDrawable(typedValue.ResourceId, context.Theme);
return rippleDrawable;
}
In my custom renderer I assign the drawable
this.Control.Foreground = DrawableHelper.CreateRippleDrawable(this.Context);
and update the ripple when the user touches the control
private void LinkLabelRenderer_Touch(object sender, TouchEventArgs e)
{
if (e.Event.Action == MotionEventActions.Down)
{
this.Pressed = true;
}
if (e.Event.Action == MotionEventActions.Cancel)
{
this.Pressed = false;
}
if (e.Event.Action == MotionEventActions.Up)
{
this.Ripple.SetHotspot(e.Event.GetX(), e.Event.GetY());
this.Pressed = false;
// raise the event of the Xamarin.Forms control
}
}
Now, whenever I click the control, the ripple will be shown, which is the expected behavior, but if I touch (tap or long-press) the parents of the control (e.g. the StackLayout, Grid or whatever layout contains the label, including their parent Layout, Page or View) the ripple animation will be triggered. Anyway, the event handler LinkLabelRenderer_Touch in not called in this case, only when the actual control is touched.
I can work around this behavior by adding an empty GestureRecognizer to the respective parent(s), but I really dislike this solution, because this is but a hack. And to make things worse it is a hack I'll always have to remember whenever I use the control.
How can I prevent the RippleDrawable being shown when the parent is touched?
Turned out I got things fundamentally wrong. Subscribing the Touch event is not the way to go. I had to make the control clickable and subscribe the Click event
this.Control.Clickable = true;
this.Click += LinkLabelRenderer_OnClick;
There is no need to handle all that RippleTouch stuff the way I did (via the Touch event) but could let android handle things for me.

In JavaFx, how to control focus of a custom control?

Suppose a JavaFX CustomControl node that contains, say, two TextFields.
If any of these TextFields has the focus, then CustomControl.isFocused() should return true. If none of them has focus, then CustomControl.isFocused() should return false.
How do I do that?
As your CustomControl uses composition, you can delegate to the focus properties of each TextField. Given two instances,
private final TextField tf1 = new TextField("One");
private final TextField tf2 = new TextField("Two");
The implementation of an instance method isFocused() is then straightforward:
private boolean isFocused() {
return tf1.isFocused() | tf2.isFocused();
}
Add focus listeners as shown here to see the effect.
tf1.focusedProperty().addListener((Observable o) -> {
System.out.println(isFocused());
});
tf2.focusedProperty().addListener((Observable o) -> {
System.out.println(isFocused());
});
This can't be done. The whole problem is that isFocused() is final in Node.
It seems you wanted to override isFocused() in CustomControl, but that is not possible for a final method and it would violate the notion of a single component having focus. As CustomControl is a composite, you'll need to manage focus internally. You may want to use a custom FocusModel as seen in ListView.
Try one line solution:
public BooleanBinding aggregatedFocusProperty() {
return Bindings.or(field1.focusedProperty(), field2.focusedProperty());
}
Now on a client side you may listen this aggregated focus property.

How do I make sure the text of an ActionScript TextInput is updated when the Object property defining that text is updated?

Not an easy question to decipher, so let me boil it down. I'm trying to convert an MXML component to an ActionScript Class. The component consists of a Form with a TextInput, TextArea, and two buttons - Save and Cancel, and a Validator for the TextInput, and other logic to handle events that occur. This component is currently extended by several other components.
Now, in the MXML component binding the TextInput text property to a property in an Object was very easy:
<mx:TextInput text="{_itemToEdit.name}" />
But in ActionScript, I'm creating the TextInput and setting the text property before the Object is set, and the TextInput is not being updated:
public var itemToEdit:Object = {};
private var nameInput:TextInput = new TextInput();
public function MyClass()
{
nameInput.text = itemToEdit.name;
}
How can I make sure that the TextInput text property is bound to the specified property in the Object?
Binding is all about firing change events. you'll need to modify your 'itemToEdit' class to be an EventDispatcher for this hack to work. here goes
//item to edit class
private var _name:String;
public function set name(value:String):void
{
_name = value;
dispatchEvent(new Event("NAME_CHANGED"));
}
//whatever the binding class is
private var _itemToEdit:ItemToEdit;
private var _textField:TextField;
public function set itemToEdit(value:ItemToEdit):void
{
if (_itemToEdit) removeEventListeners();
_itemToEdit = value;
if (_itemToEdit) addEventListeners();
}
private function addEventListeners():void
{
_itemToEdit.addEventListener("NAME_CHANGED", itemToEdit_nameChangedHandler);
itemToEditChangedHandler(null);
}
private function itemToEdit_nameChangedHandler(event:Event):void
{
_textField.text = _itemToEdit.name;
}
Obviously this was done just for speed, you'll need custom events and some better names etc, but this is the basic jist.
Apparently it's slightly more complex than a simple assignment to bind purely in AS, here's a couple tutorial/docs to show you how to pull it off.
http://cookbooks.adobe.com/index.cfm?event=showdetails&postId=6802
http://raghuonflex.wordpress.com/2007/08/30/binding-in-mxml-as/
Compile your MXML component with the -keep option. Examine the ActionScript code that was generated by mxmlc and do something similar.
You may also do it using the Proxy object - I blogged about it over here: http://flexblog.faratasystems.com/?p=433
If "itemToEdit" is a pure AS3 Object, then the binding probably doesn't work properly anyway. That is, it will work when the object is initially created, but any changes to "name" in the object won't be detected. (I could be wrong...haven't done extensive tests)
Anyway, your problem is easy to solve with getters/setters:
private var _itemToEdit:Object;
public function get itemToEdit():Object { return _itemToEdit; }
public function set itemToEdit(value:Objecy):void {
_itemToEdit = value;
nameInput.text = value.name;
}
Binding isn't necessary here.

How to raise an event from a SWF in a SWFLoader to a parent Flex application?

How can I raise an event from a SWF file loaded into a Flex application (using SWFLoader)?
I want to be able to detect
a) when a button is pressed
b) when the animation ends
You'll need to do 2 things:
Dispatch an event from the loaded swf. Make sure the event bubbles if you sent it from nested views. Bubbling can be set through the bubbles property of the event.
Listen to the event from your main application. I think you should be able to do that on the content property of the SWFLoader instance.
mySWFLoader.content.addEventListener("myEvent", myEventHandler);
I took a lazier approach for raising the event inside flash
Flex:
<mx:SWFLoader source="homeanimations/tired.swf" id="swfTired" complete="swfTiredLoaded(event)" />
private function swfTiredLoaded(event:Event): void {
mySWFLoader.content.addEventListener("continueClicked", continueClickedHandler);
}
Flash:
dispatchEvent(new Event("continueClicked", true, true));
I believe its because you would be creating two seperate custom event class one in Flash and the other in Flex.
Dispatching one EV_NOTIFY.ANIMATION_ENDED from Flash may not be understood by Flex,since it has its own version of EV_NOTIFY.ANIMATION_ENDED.
As an adjunct to the answer by Christophe Herreman, and in case you were wondering, here is a way of making your own events...
package yourpackage.events
{
import flash.events.Event;
[Event(name="EV_Notify", type="yourpackage.events.EV_Notify")]
public class EV_Notify extends Event
{
public function EV_Notify(bubbles:Boolean=true, cancelable:Boolean=false)
{
super("EV_Notify", bubbles, cancelable);
}
}
}
I have taken the liberty of setting the default value of bubbles to true and passing the custom event type to the super constructor by default, so you can then just say...
dispatchEvent(new EV_Notify());
In your particular case I doubt there are times when you would not want your event to bubble.
The prefix EV_ on the name is my own convention for events so I can easily find them in the code completion popups, you'll obviously pick your own name.
For the two cases you cite you can either have two events and listen for both of them, or add a property to the event which says what just happened, which is the approach which is taken by controls like Alert...
package yourpackage.events
{
import flash.events.Event;
[Event(name="EV_Notify", type="yourpackage.events.EV_Notify")]
public class EV_Notify extends Event
{
public static var BUTTON_PRESSED:int = 1;
public static var ANIMATION_ENDED:int = 2;
public var whatHappened:int;
public function EV_Notify(whatHappened:int, bubbles:Boolean=true, cancelable:Boolean=false)
{
this.whatHappened = whatHappened;
super("EV_Notify", bubbles, cancelable);
}
}
}
then you call it as follows...
dispatchEvent(new EV_Notify(EV_NOTIFY.ANIMATION_ENDED));
you can then inspect the whatHappened field in your event handler.
private function handleNotify(ev:EV_Notify):void
{
if (ev.whatHappened == EV_Notify.ANIMATION_ENDED)
{
// do something
}
else if (ev.whatHappened == EV_Notify.BUTTON_PRESSED)
{
// do something else
}
etc...
}
HTH
I could not make this last approach work (with Flash CS4 and Flex 3). I put the dispatchEvent call in one of the last frames of my Flash animation, but could not pick it up in Flex.
I resorted to a counter variable and incrementing until I reached the known last frame number using the ENTER_FRAME event - which I can pick up using almost the same code.
If I can pick this up, then why can't I pick up a custom event?

How can I tab accross a ButtonBar component in Flex?

I have a button bar inf flex along with several other input controls, I have set the tabIndex property for each control and all goes well until I tab to the ButtonBar.
The ButtonBar has 3 buttons but tabbing to it, only the first button gets focus, tab again and the focus goes back to the top control...
How can I make tabbing go through ALL buttons in a Flex Button bar? Is there a way to do this or do I need to create individual buttons for this?
This seems like a possible bug to me...
The component is written so the user must press the left/right arrow keys when focus is within the bar to traverse the buttons--this is a fairly standard GUI behavior (you also see this in other places like radio button groups). If you look into the SDK source for ButtonBar, you can see where they've explicitly disabled tab focus for each child button as it's created:
override protected function createNavItem(
label:String,
icon:Class = null):IFlexDisplayObject
{
var newButton:Button = Button(navItemFactory.newInstance());
// Set tabEnabled to false so individual buttons don't get focus.
newButton.focusEnabled = false;
...
If you really want to change this behavior, you can make a subclass to do it, something like this:
package {
import mx.controls.Button;
import mx.controls.ButtonBar;
import mx.core.IFlexDisplayObject;
public class FocusableButtonBar extends ButtonBar {
public function FocusableButtonBar()
{
super();
this.focusEnabled = false;
}
override protected function createNavItem(
label:String, icon:Class=null):IFlexDisplayObject
{
var btn:Button = Button(super.createNavItem(label, icon));
btn.focusEnabled = true;
return btn;
}
}
}

Resources