haxeui/haxeui-core

View on GitHub
haxe/ui/core/InteractiveComponent.hx

Summary

Maintainability
Test Coverage
package haxe.ui.core;

import haxe.ui.behaviours.DefaultBehaviour;
import haxe.ui.core.IValueComponent;
import haxe.ui.events.FocusEvent;
import haxe.ui.events.UIEvent;
import haxe.ui.focus.FocusManager;
import haxe.ui.focus.IFocusable;
import haxe.ui.validators.Validators;

/**
 A component that can be interacted with and gain input focus via either mouse or keyboard
**/
@:access(haxe.ui.events.Events)
class InteractiveComponent extends Component implements IFocusable implements IValueComponent {
    public var actionRepeatInterval = 100;

    //***********************************************************************************************************
    // Public API
    //***********************************************************************************************************
    @:clonable @:behaviour(DefaultBehaviour, true)      public var allowInteraction:Bool;

    private var _focus:Bool = false;
    /**
     Whether this component currently has focus

     *Note*: components that have focus will have an `:active` css psuedo class automatically added
    **/
    public var focus(get, set):Bool;
    private function get_focus():Bool {
        return _focus;
    }
    private function set_focus(value:Bool):Bool {
        if (_focus == value || allowFocus == false) {
            return value;
        }

        _focus = value;
        var eventType = null;
        if (_focus == true) {
            eventType = FocusEvent.FOCUS_IN;
            FocusManager.instance.focus = cast(this, IFocusable);

            // if we are focusing lets see if there is a ancestor scrollview we might want to scroll into view
            var scrollview = findScroller();
            if (scrollview != null) {
                scrollview.ensureVisible(this);
            }
        } else {
            eventType = FocusEvent.FOCUS_OUT;
            FocusManager.instance.focus = null;
        }
        invalidateComponentData();
        dispatch(new FocusEvent(eventType));
        return value;
    }

    private var _allowFocus:Bool = true;
    /**
     Whether this component is allowed to gain focus
    **/
    public var allowFocus(get, set):Bool;
    private function get_allowFocus():Bool {
        return _allowFocus;
    }
    private function set_allowFocus(value:Bool):Bool {
        if (_allowFocus == value) {
            return value;
        }

        _allowFocus = value;
        for (child in childComponents) {
            if ((child is IFocusable)) {
                cast(child, IFocusable).allowFocus = value;
            }
        }
        return value;
    }

    private var _autoFocus:Bool = true;
    /**
     Whether this component is allowed to gain focus automatically 
    **/
    public var autoFocus(get, set):Bool;
    private function get_autoFocus():Bool {
        return _autoFocus;
    }
    private function set_autoFocus(value:Bool):Bool {
        if (_autoFocus == value) {
            return value;
        }

        _autoFocus = value;
        for (child in childComponents) {
            if ((child is IFocusable)) {
                cast(child, IFocusable).autoFocus = value;
            }
        }
        return value;
    }
    
    private var _validators:Validators = null;
    @:clonable public var validators(get, set):Validators;
    private function get_validators():Validators {
        return _validators;
    }
    private function set_validators(value:Validators):Validators {
        if (value == null) {
            unregisterEvent(UIEvent.CHANGE, _onInteractiveChange);
        }
        _validators = value;
        if (_validators != null) {
            @:privateAccess _validators.component = this;
            registerEvent(UIEvent.CHANGE, _onInteractiveChange);
            @:privateAccess _validators.setup();
            _validators.validate();
        }
        return value;
    }

    //***********************************************************************************************************
    // Internal
    //***********************************************************************************************************

    private function _onInteractiveChange(event:UIEvent) {
        if (_validators != null) {
            _validators.validate();
        }
    }

    private override function onDestroy() {
        if (_validators != null) {
            @:privateAccess _validators.component = null;
            _validators = null;
        }
        super.onDestroy();
    }
}