diff --git a/haxe/ui/backend/ComponentImpl.hx b/haxe/ui/backend/ComponentImpl.hx index 7514edb..3f79e71 100644 --- a/haxe/ui/backend/ComponentImpl.hx +++ b/haxe/ui/backend/ComponentImpl.hx @@ -1,5 +1,6 @@ package haxe.ui.backend; +import haxe.ui.backend.TextInputImpl.TextInputEvent; import flixel.FlxG; import flixel.FlxSprite; import flixel.math.FlxRect; @@ -284,11 +285,17 @@ class ComponentImpl extends ComponentBase { _unsolicitedMembers = []; } if (findUnsolictedEntryFromSprite(sprite) == null) { - _unsolicitedMembers.push({ - sprite: sprite, - originalX: sprite.x, - originalY: sprite.y - }); + var use = true; + if (_textInput != null && _textInput.equals(sprite)) { + use = false; + } + if (use) { + _unsolicitedMembers.push({ + sprite: sprite, + originalX: sprite.x, + originalY: sprite.y + }); + } } } super.preAdd(sprite); @@ -350,7 +357,7 @@ class ComponentImpl extends ComponentBase { _textDisplay.tf.visible = show; } if (hasTextInput()) { - _textInput.tf.visible = show; + _textInput.visible = show; } for (c in this.childComponents) { @@ -387,7 +394,7 @@ class ComponentImpl extends ComponentBase { getTextDisplay().tf.alpha = value; } if (hasTextInput()) { - getTextInput().tf.alpha = value; + getTextInput().alpha = value; } for (c in childComponents) { c.applyAlpha(value); @@ -400,7 +407,7 @@ class ComponentImpl extends ComponentBase { getTextDisplay().tf.alpha = value; } if (hasTextInput()) { - getTextInput().tf.alpha = alpha; + getTextInput().alpha = alpha; } return super.set_alpha(alpha); } @@ -474,7 +481,7 @@ class ComponentImpl extends ComponentBase { notifyMouseMove(true); _eventMap.set(MouseEvent.MOUSE_DOWN, listener); if (hasTextInput()) { - getTextInput().tf.addEventListener(openfl.events.MouseEvent.MOUSE_DOWN, __onTextInputMouseEvent); + getTextInput().onMouseDown = __onTextInputMouseEvent; } } @@ -485,7 +492,7 @@ class ComponentImpl extends ComponentBase { notifyMouseMove(true); _eventMap.set(MouseEvent.MOUSE_UP, listener); if (hasTextInput()) { - getTextInput().tf.addEventListener(openfl.events.MouseEvent.MOUSE_UP, __onTextInputMouseEvent); + getTextInput().onMouseUp = __onTextInputMouseEvent; } } @@ -503,7 +510,7 @@ class ComponentImpl extends ComponentBase { notifyMouseMove(true); _eventMap.set(MouseEvent.CLICK, listener); if (hasTextInput()) { - getTextInput().tf.addEventListener(openfl.events.MouseEvent.CLICK, __onTextInputMouseEvent); + getTextInput().onClick = __onTextInputMouseEvent; } } @@ -543,7 +550,7 @@ class ComponentImpl extends ComponentBase { if (_eventMap.exists(UIEvent.CHANGE) == false) { if (hasTextInput() == true) { _eventMap.set(UIEvent.CHANGE, listener); - getTextInput().tf.addEventListener(Event.CHANGE, __onTextInputChange); + getTextInput().onChange = __onTextInputChange; } } } @@ -569,7 +576,7 @@ class ComponentImpl extends ComponentBase { notifyMouseUp(false); notifyMouseMove(false); if (hasTextInput()) { - getTextInput().tf.removeEventListener(openfl.events.MouseEvent.MOUSE_DOWN, __onTextInputMouseEvent); + getTextInput().onMouseDown = null; } @@ -579,7 +586,7 @@ class ComponentImpl extends ComponentBase { notifyMouseUp(false); notifyMouseMove(false); if (hasTextInput()) { - getTextInput().tf.removeEventListener(openfl.events.MouseEvent.MOUSE_UP, __onTextInputMouseEvent); + getTextInput().onMouseUp = null; } case MouseEvent.MOUSE_WHEEL: @@ -593,7 +600,7 @@ class ComponentImpl extends ComponentBase { notifyMouseUp(false); notifyMouseMove(false); if (hasTextInput()) { - getTextInput().tf.removeEventListener(openfl.events.MouseEvent.CLICK, __onTextInputMouseEvent); + getTextInput().onClick = null; } case MouseEvent.DBL_CLICK: @@ -623,7 +630,7 @@ class ComponentImpl extends ComponentBase { case UIEvent.CHANGE: _eventMap.remove(type); if (hasTextInput() == true) { - getTextInput().tf.removeEventListener(Event.CHANGE, __onTextInputChange); + getTextInput().onChange = null; } } } @@ -693,16 +700,14 @@ class ComponentImpl extends ComponentBase { } } - private function __onTextInputChange(event:Event) { + private function __onTextInputChange(event:TextInputEvent) { var fn:UIEvent->Void = _eventMap.get(UIEvent.CHANGE); if (fn != null) { fn(new UIEvent(UIEvent.CHANGE)); } } - // since we use openfl's text input for text input we need to handle its events differently - // to how we do in the rest of haxeui-flixel - private function __onTextInputMouseEvent(event:openfl.events.MouseEvent) { + private function __onTextInputMouseEvent(event:TextInputEvent) { var type = null; switch (event.type) { case openfl.events.MouseEvent.MOUSE_DOWN: @@ -1036,8 +1041,8 @@ class ComponentImpl extends ComponentBase { if (_textInput == null) { super.createTextInput(text); _textInput.attach(); - _textInput.tf.visible = false; - FlxG.addChildBelowMouse(_textInput.tf, 0xffffff); + _textInput.visible = false; + _textInput.addToComponent(cast this); /* Toolkit.callLater(function() { // lets show it a frame later so its had a chance to reposition if (_textInput != null) { @@ -1079,10 +1084,10 @@ class ComponentImpl extends ComponentBase { var offsetY = 2 / Toolkit.scaleY; #end - _textInput.tf.x = (_surface.x + _textInput.left - offsetX) * FlxG.scaleMode.scale.x; - _textInput.tf.y = (_surface.y + _textInput.top - offsetY) * FlxG.scaleMode.scale.y; - _textInput.tf.scaleX = FlxG.scaleMode.scale.x; - _textInput.tf.scaleY = FlxG.scaleMode.scale.y; + _textInput.x = (_surface.x + _textInput.left - offsetX) * FlxG.scaleMode.scale.x; + _textInput.y = (_surface.y + _textInput.top - offsetY) * FlxG.scaleMode.scale.y; + _textInput.scaleX = FlxG.scaleMode.scale.x; + _textInput.scaleY = FlxG.scaleMode.scale.y; _textInput.update(); } @@ -1225,8 +1230,12 @@ class ComponentImpl extends ComponentBase { // application, this means that when things are removed from the screen (and not destroyed) it can leave them // behind private function applyAddInternal() { + if (!TextInputImpl.USE_ON_ADDED) { + return; + } + if (hasTextInput() && asComponent.hidden == false) { - getTextInput().tf.visible = true; + getTextInput().visible = true; } for (c in childComponents) { c.applyAddInternal(); @@ -1234,8 +1243,12 @@ class ComponentImpl extends ComponentBase { } private function applyRemoveInternal() { + if (!TextInputImpl.USE_ON_REMOVED) { + return; + } + if (hasTextInput()) { - getTextInput().tf.visible = false; + getTextInput().visible = false; } for (c in childComponents) { c.applyRemoveInternal(); @@ -1258,7 +1271,7 @@ class ComponentImpl extends ComponentBase { } if (_textInput != null) { - _textInput.destroy(); + _textInput.destroy(cast this); _textInput = null; } diff --git a/haxe/ui/backend/TextInputImpl.hx b/haxe/ui/backend/TextInputImpl.hx index 061bf09..5eba182 100644 --- a/haxe/ui/backend/TextInputImpl.hx +++ b/haxe/ui/backend/TextInputImpl.hx @@ -1,6 +1,13 @@ package haxe.ui.backend; -import haxe.ui.backend.flixel.textinputs.OpenFLTextInput; +typedef TextInputEvent = {type:String, stageX:Float, stageY:Float}; -class TextInputImpl extends OpenFLTextInput { -} +#if flixel_text_input + +typedef TextInputImpl = haxe.ui.backend.flixel.textinputs.FlxTextInput; + +#else + +typedef TextInputImpl = haxe.ui.backend.flixel.textinputs.OpenFLTextInput; + +#end diff --git a/haxe/ui/backend/flixel/textinputs/FlxTextInput.hx b/haxe/ui/backend/flixel/textinputs/FlxTextInput.hx new file mode 100644 index 0000000..e4a69f7 --- /dev/null +++ b/haxe/ui/backend/flixel/textinputs/FlxTextInput.hx @@ -0,0 +1,343 @@ +package haxe.ui.backend.flixel.textinputs; + +import flixel.FlxSprite; +import haxe.ui.backend.TextInputImpl.TextInputEvent; +import haxe.ui.core.Component; +import openfl.events.Event; + +class FlxTextInput extends TextBase { + public static var USE_ON_ADDED:Bool = false; + public static var USE_ON_REMOVED:Bool = false; + + private var PADDING_X:Int = 4; + private var PADDING_Y:Int = 0; + + private var tf:flixel.addons.text.FlxTextInput; + + public function new() { + super(); + tf = new flixel.addons.text.FlxTextInput(); + tf.onChange.add(onInternalChange); + tf.onScroll.add(onScroll); + tf.moves = false; + } + + public override function focus() { + tf.focus = true; + } + + public override function blur() { + tf.focus = false; + } + + public function attach() { + } + + public var visible(get, set):Bool; + private function get_visible():Bool { + return tf.visible; + } + private function set_visible(value:Bool):Bool { + tf.visible = value; + return value; + } + + public var x(get, set):Float; + private function get_x():Float { + return tf.x; + } + private function set_x(value:Float):Float { + tf.x = value; + return value; + } + + public var y(get, set):Float; + private function get_y():Float { + return tf.y; + } + private function set_y(value:Float):Float { + tf.y = value; + return value; + } + + public var scaleX(get, set):Float; + private function get_scaleX():Float { + return tf.scale.x; + } + private function set_scaleX(value:Float):Float { + tf.scale.x = value; + return value; + } + + public var scaleY(get, set):Float; + private function get_scaleY():Float { + return tf.scale.y; + } + private function set_scaleY(value:Float):Float { + tf.scale.y = value; + return value; + } + + public var alpha(get, set):Float; + private function get_alpha():Float { + return tf.alpha; + } + private function set_alpha(value:Float):Float { + tf.alpha = value; + return value; + } + + private override function validateData() { + if (_text != null) { + if (_dataSource == null) { + tf.text = normalizeText(_text); + } + } + + var hscrollValue = Std.int(_inputData.hscrollPos); + if (tf.scrollH != hscrollValue) { + tf.scrollH = hscrollValue; + } + + var vscrollValue = Std.int(_inputData.vscrollPos); + if (tf.scrollV != vscrollValue) { + tf.scrollV = vscrollValue; + } + } + + private function normalizeText(text:String):String { + text = StringTools.replace(text, "\\n", "\n"); + return text; + } + + private override function measureText() { + //tf.width = _width * Toolkit.scaleX; + _textHeight = tf.textField.textHeight; + if (_textHeight == 0) { + var tmpText:String = tf.text; + tf.text = "|"; + _textHeight = tf.textField.textHeight; + tf.text = tmpText; + } + + _textWidth = Math.round(_textWidth) / Toolkit.scaleX; + _textHeight = Math.round(_textHeight) / Toolkit.scaleY; + + ////////////////////////////////////////////////////////////////////////////// + + _inputData.hscrollMax = tf.maxScrollH; + // see below + _inputData.hscrollPageSize = (_width * _inputData.hscrollMax) / _textWidth; + + _inputData.vscrollMax = tf.maxScrollV; + _inputData.vscrollPageSize = (_height * _inputData.vscrollMax) / _textHeight; + } + + private override function validateStyle():Bool { + var measureTextRequired:Bool = false; + + if (_textStyle != null) { + if (tf.alignment != _textStyle.textAlign) { + tf.alignment = _textStyle.textAlign; + } + + var fontSizeValue = Std.int(_textStyle.fontSize); + if (tf.size != fontSizeValue) { + tf.size = Std.int(fontSizeValue * Toolkit.scale); + + measureTextRequired = true; + } + + if (_fontInfo != null && tf.font != _fontInfo.data) { + tf.font = _fontInfo.data; + measureTextRequired = true; + } + + if (tf.color != _textStyle.color) { + tf.color = _textStyle.color; + } + + if (tf.bold != _textStyle.fontBold) { + tf.bold = _textStyle.fontBold; + measureTextRequired = true; + } + + if (tf.italic != _textStyle.fontItalic) { + tf.italic = _textStyle.fontItalic; + measureTextRequired = true; + } + } + + if (tf.wordWrap != _displayData.wordWrap) { + tf.wordWrap = _displayData.wordWrap; + measureTextRequired = true; + } + + if (tf.multiline != _displayData.multiline) { + tf.multiline = _displayData.multiline; + measureTextRequired = true; + } + + if (tf.displayAsPassword != _inputData.password) { + tf.displayAsPassword = _inputData.password; + } + + return measureTextRequired; + } + + private override function validatePosition() { + _left = Math.round(_left * Toolkit.scaleX); + _top = Math.round(_top * Toolkit.scaleY); + } + + private override function validateDisplay() { + if (_width <= 0 || _height <= 0) { + return; + } + + if (tf.width != _width * Toolkit.scaleX) { + tf.width = _width * Toolkit.scaleX; + tf.fieldWidth = tf.width; + } + + if (tf.height != _height * Toolkit.scaleY) { + tf.height = _height * Toolkit.scaleY; + tf.fieldHeight = tf.height; + } + } + + private var _onMouseDown:TextInputEvent->Void = null; + public var onMouseDown(null, set):TextInputEvent->Void; + private function set_onMouseDown(value:TextInputEvent->Void):TextInputEvent->Void { + if (_onMouseDown != null) { + //tf.removeEventListener(openfl.events.MouseEvent.MOUSE_DOWN, __onTextInputMouseDownEvent); + } + _onMouseDown = value; + if (_onMouseDown != null) { + //tf.addEventListener(openfl.events.MouseEvent.MOUSE_DOWN, __onTextInputMouseDownEvent); + } + return value; + } + + /* + private function __onTextInputMouseDownEvent(event:openfl.events.MouseEvent) { + if (_onMouseDown != null) { + _onMouseDown({ + type: event.type, + stageX: event.stageX, + stageY: event.stageY + }); + } + } + */ + + private var _onMouseUp:TextInputEvent->Void = null; + public var onMouseUp(null, set):TextInputEvent->Void; + private function set_onMouseUp(value:TextInputEvent->Void):TextInputEvent->Void { + if (_onMouseUp != null) { + //tf.removeEventListener(openfl.events.MouseEvent.MOUSE_UP, __onTextInputMouseUpEvent); + } + _onMouseUp = value; + if (_onMouseUp != null) { + //tf.addEventListener(openfl.events.MouseEvent.MOUSE_UP, __onTextInputMouseUpEvent); + } + return value; + } + + /* + private function __onTextInputMouseUpEvent(event:openfl.events.MouseEvent) { + if (_onMouseUp != null) { + _onMouseUp({ + type: event.type, + stageX: event.stageX, + stageY: event.stageY + }); + } + } + */ + + public function equals(sprite:FlxSprite):Bool { + return sprite == tf; + } + + private var _onClick:TextInputEvent->Void = null; + public var onClick(null, set):TextInputEvent->Void; + private function set_onClick(value:TextInputEvent->Void):TextInputEvent->Void { + if (_onClick != null) { + //tf.removeEventListener(openfl.events.MouseEvent.CLICK, __onTextInputClickEvent); + } + _onClick = value; + if (_onClick != null) { + //tf.addEventListener(openfl.events.MouseEvent.CLICK, __onTextInputClickEvent); + } + return value; + } + + /* + private function __onTextInputClickEvent(event:openfl.events.MouseEvent) { + if (_onClick != null) { + _onClick({ + type: event.type, + stageX: event.stageX, + stageY: event.stageY + }); + } + } + */ + + private var _onChange:TextInputEvent->Void = null; + public var onChange(null, set):TextInputEvent->Void; + private function set_onChange(value:TextInputEvent->Void):TextInputEvent->Void { + if (_onChange != null) { + tf.onChange.remove(__onTextInputChangeEvent); + } + _onChange = value; + if (_onChange != null) { + tf.onChange.add(__onTextInputChangeEvent); + } + return value; + } + + private function __onTextInputChangeEvent() { + if (_onChange != null) { + _onChange({ + type: "change", + stageX: 0, + stageY: 0 + }); + } + } + + private function onInternalChange() { + _text = tf.text; + + measureText(); + + if (_inputData.onChangedCallback != null) { + _inputData.onChangedCallback(); + } + } + + private function onScroll() { + _inputData.hscrollPos = tf.scrollH; + _inputData.vscrollPos = tf.scrollV; + + if (_inputData.onScrollCallback != null) { + _inputData.onScrollCallback(); + } + } + + public function update() { + } + + public function addToComponent(component:Component) { + //StateHelper.currentState.add(tf); + component.add(tf); + } + + public function destroy(component:Component) { + tf.visible = false; + component.remove(tf); + tf = null; + } +} \ No newline at end of file diff --git a/haxe/ui/backend/flixel/textinputs/OpenFLTextInput.hx b/haxe/ui/backend/flixel/textinputs/OpenFLTextInput.hx index 0d19c0b..db55676 100644 --- a/haxe/ui/backend/flixel/textinputs/OpenFLTextInput.hx +++ b/haxe/ui/backend/flixel/textinputs/OpenFLTextInput.hx @@ -1,5 +1,6 @@ package haxe.ui.backend.flixel.textinputs; +import flixel.FlxSprite; import flixel.FlxG; import haxe.ui.Toolkit; import haxe.ui.core.Component; @@ -11,8 +12,12 @@ import openfl.text.TextField; import openfl.text.TextFieldAutoSize; import openfl.text.TextFieldType; import openfl.text.TextFormat; +import haxe.ui.backend.TextInputImpl.TextInputEvent; class OpenFLTextInput extends TextBase { + public static var USE_ON_ADDED:Bool = true; + public static var USE_ON_REMOVED:Bool = true; + private var PADDING_X:Int = 4; private var PADDING_Y:Int = 0; @@ -29,24 +34,179 @@ class OpenFLTextInput extends TextBase { tf.wordWrap = true; tf.tabEnabled = false; //tf.stage.focus = null; - tf.addEventListener(Event.CHANGE, onChange); + tf.addEventListener(Event.CHANGE, onInternalChange); } public override function focus() { if (tf.stage != null) { - tf.stage.focus = tf; + //tf.stage.focus = tf; } } public override function blur() { if (tf.stage != null) { - tf.stage.focus = null; + //tf.stage.focus = null; } } public function attach() { } + public var visible(get, set):Bool; + private function get_visible():Bool { + return tf.visible; + } + private function set_visible(value:Bool):Bool { + tf.visible = value; + return value; + } + + public var x(get, set):Float; + private function get_x():Float { + return tf.x; + } + private function set_x(value:Float):Float { + tf.x = value; + return value; + } + + public var y(get, set):Float; + private function get_y():Float { + return tf.y; + } + private function set_y(value:Float):Float { + tf.y = value; + return value; + } + + public var scaleX(get, set):Float; + private function get_scaleX():Float { + return tf.scaleX; + } + private function set_scaleX(value:Float):Float { + tf.scaleX = value; + return value; + } + + public var scaleY(get, set):Float; + private function get_scaleY():Float { + return tf.scaleY; + } + private function set_scaleY(value:Float):Float { + tf.scaleY = value; + return value; + } + + public var alpha(get, set):Float; + private function get_alpha():Float { + return tf.alpha; + } + private function set_alpha(value:Float):Float { + tf.alpha = value; + return value; + } + + + private var _onMouseDown:TextInputEvent->Void = null; + public var onMouseDown(null, set):TextInputEvent->Void; + private function set_onMouseDown(value:TextInputEvent->Void):TextInputEvent->Void { + if (_onMouseDown != null) { + tf.removeEventListener(openfl.events.MouseEvent.MOUSE_DOWN, __onTextInputMouseDownEvent); + } + _onMouseDown = value; + if (_onMouseDown != null) { + tf.addEventListener(openfl.events.MouseEvent.MOUSE_DOWN, __onTextInputMouseDownEvent); + } + return value; + } + + private function __onTextInputMouseDownEvent(event:openfl.events.MouseEvent) { + if (_onMouseDown != null) { + _onMouseDown({ + type: event.type, + stageX: event.stageX, + stageY: event.stageY + }); + } + } + + private var _onMouseUp:TextInputEvent->Void = null; + public var onMouseUp(null, set):TextInputEvent->Void; + private function set_onMouseUp(value:TextInputEvent->Void):TextInputEvent->Void { + if (_onMouseUp != null) { + tf.removeEventListener(openfl.events.MouseEvent.MOUSE_UP, __onTextInputMouseUpEvent); + } + _onMouseUp = value; + if (_onMouseUp != null) { + tf.addEventListener(openfl.events.MouseEvent.MOUSE_UP, __onTextInputMouseUpEvent); + } + return value; + } + + private function __onTextInputMouseUpEvent(event:openfl.events.MouseEvent) { + if (_onMouseUp != null) { + _onMouseUp({ + type: event.type, + stageX: event.stageX, + stageY: event.stageY + }); + } + } + + private var _onClick:TextInputEvent->Void = null; + public var onClick(null, set):TextInputEvent->Void; + private function set_onClick(value:TextInputEvent->Void):TextInputEvent->Void { + if (_onClick != null) { + tf.removeEventListener(openfl.events.MouseEvent.CLICK, __onTextInputClickEvent); + } + _onClick = value; + if (_onClick != null) { + tf.addEventListener(openfl.events.MouseEvent.CLICK, __onTextInputClickEvent); + } + return value; + } + + private function __onTextInputClickEvent(event:openfl.events.MouseEvent) { + if (_onClick != null) { + _onClick({ + type: event.type, + stageX: event.stageX, + stageY: event.stageY + }); + } + } + + private var _onChange:TextInputEvent->Void = null; + public var onChange(null, set):TextInputEvent->Void; + private function set_onChange(value:TextInputEvent->Void):TextInputEvent->Void { + if (_onChange != null) { + tf.removeEventListener(Event.CHANGE, __onTextInputChangeEvent); + } + _onChange = value; + if (_onChange != null) { + tf.addEventListener(Event.CHANGE, __onTextInputChangeEvent); + } + return value; + } + + private function __onTextInputChangeEvent(event:Event) { + if (_onChange != null) { + _onChange({ + type: event.type, + stageX: 0, + stageY: 0 + }); + } + } + + public function addToComponent(component:Component) { + FlxG.addChildBelowMouse(tf, 0xffffff); + } + + public function equals(sprite:FlxSprite):Bool { + return false; + } + private var _parentHidden:Bool = false; public function update() { var ref = parentComponent; @@ -98,7 +258,7 @@ class OpenFLTextInput extends TextBase { */ } - public function destroy() { + public function destroy(component:Component) { _parentHidden = true; tf.visible = false; FlxG.removeChild(tf); @@ -219,7 +379,7 @@ class OpenFLTextInput extends TextBase { return measureTextRequired; } - private function onChange(e) { + private function onInternalChange(e:Event) { _text = tf.text; measureText();