Browse Source

added key and focus events
added h2d.comp.Input

ncannasse 12 năm trước cách đây
mục cha
commit
bcca55a743
10 tập tin đã thay đổi với 326 bổ sung39 xóa
  1. 6 0
      h2d/Event.hx
  2. 82 26
      h2d/Interactive.hx
  3. 36 0
      h2d/Key.hx
  4. 52 8
      h2d/Scene.hx
  5. 9 5
      h2d/Text.hx
  6. 116 0
      h2d/comp/Input.hx
  7. 9 0
      h2d/comp/Parser.hx
  8. 13 0
      h2d/css/default.css
  9. 3 0
      samples/comps/components.html
  10. BIN
      samples/comps/comps.swf

+ 6 - 0
h2d/Event.hx

@@ -7,6 +7,10 @@ enum EventKind {
 	EOver;
 	EOut;
 	EWheel;
+	EFocus;
+	EFocusLost;
+	EKeyDown;
+	EKeyUp;
 }
 
 class Event {
@@ -17,6 +21,8 @@ class Event {
 	public var propagate : Bool;
 	public var cancel : Bool;
 	public var touchId : Int;
+	public var keyCode : Int;
+	public var charCode : Int;
 	public var wheelDelta : Float;
 	
 	public function new(k,x=0.,y=0.) {

+ 82 - 26
h2d/Interactive.hx

@@ -29,14 +29,26 @@ class Interactive extends Sprite {
 	}
 	
 	override function onDelete() {
-		if( scene != null )
+		if( scene != null ) {
 			scene.removeEventTarget(this);
+			if( scene.currentOver == this ) {
+				scene.currentOver = null;
+				h3d.System.setCursor(Default);
+			}
+		}
 		super.onDelete();
 	}
 
+	function checkBounds( e : Event ) {
+		return switch( e.kind ) {
+		case EOut, ERelease, EFocus, EFocusLost: false;
+		default: true;
+		}
+	}
+	
 	@:allow(h2d.Scene)
 	function handleEvent( e : Event ) {
-		if( isEllipse && (e.kind != EOut && e.kind != ERelease) ) {
+		if( isEllipse && checkBounds(e) ) {
 			var cx = width * 0.5, cy = height * 0.5;
 			var dx = (e.relX - cx) / cx;
 			var dy = (e.relY - cy) / cy;
@@ -62,6 +74,16 @@ class Interactive extends Sprite {
 			onOut(e);
 		case EWheel:
 			onWheel(e);
+		case EFocusLost:
+			onFocusLost(e);
+			if( !e.cancel && scene != null && scene.currentFocus == this ) scene.currentFocus = null;
+		case EFocus:
+			onFocus(e);
+			if( !e.cancel && scene != null ) scene.currentFocus = this;
+		case EKeyUp:
+			onKeyUp(e);
+		case EKeyDown:
+			onKeyDown(e);
 		}
 	}
 	
@@ -72,34 +94,37 @@ class Interactive extends Sprite {
 		return c;
 	}
 	
+	function globalToLocal( e : Event ) {
+		// convert global event to our local space
+		var x = e.relX, y = e.relY;
+		var rx = x * scene.matA + y * scene.matB + scene.absX;
+		var ry = x * scene.matC + y * scene.matD + scene.absY;
+		var r = scene.height / scene.width;
+		
+		var i = this;
+		
+		var dx = rx - i.absX;
+		var dy = ry - i.absY;
+		
+		var w1 = i.width * i.matA * r;
+		var h1 = i.width * i.matC;
+		var ky = h1 * dx - w1 * dy;
+		
+		var w2 = i.height * i.matB * r;
+		var h2 = i.height * i.matD;
+		var kx = w2 * dy - h2 * dx;
+		
+		var max = h1 * w2 - w1 * h2;
+		
+		e.relX = (kx * r / max) * i.width;
+		e.relY = (ky / max) * i.height;
+	}
+	
 	public function startDrag(callb) {
 		scene.startDrag(function(event) {
-			// convert global event to our local space
 			var x = event.relX, y = event.relY;
-			var rx = x * scene.matA + y * scene.matB + scene.absX;
-			var ry = x * scene.matC + y * scene.matD + scene.absY;
-			var r = scene.height / scene.width;
-			
-			var i = this;
-			
-			var dx = rx - i.absX;
-			var dy = ry - i.absY;
-			
-			var w1 = i.width * i.matA * r;
-			var h1 = i.width * i.matC;
-			var ky = h1 * dx - w1 * dy;
-			
-			var w2 = i.height * i.matB * r;
-			var h2 = i.height * i.matD;
-			var kx = w2 * dy - h2 * dx;
-			
-			var max = h1 * w2 - w1 * h2;
-			
-			event.relX = (kx * r / max) * i.width;
-			event.relY = (ky / max) * i.height;
-			
+			globalToLocal(event);
 			callb(event);
-			
 			event.relX = x;
 			event.relY = y;
 		});
@@ -109,6 +134,25 @@ class Interactive extends Sprite {
 		scene.stopDrag();
 	}
 	
+	public function focus() {
+		if( scene == null )
+			return;
+		var ev = new h2d.Event(null);
+		if( scene.currentFocus != null ) {
+			if( scene.currentFocus == this )
+				return;
+			ev.kind = EFocusLost;
+			scene.currentFocus.handleEvent(ev);
+			if( ev.cancel ) return;
+		}
+		ev.kind = EFocus;
+		handleEvent(ev);
+	}
+	
+	public function hasFocus() {
+		return scene != null && scene.currentFocus == this;
+	}
+	
 	public dynamic function onOver( e : Event ) {
 	}
 
@@ -126,5 +170,17 @@ class Interactive extends Sprite {
 
 	public dynamic function onWheel( e : Event ) {
 	}
+
+	public dynamic function onFocus( e : Event ) {
+	}
+	
+	public dynamic function onFocusLost( e : Event ) {
+	}
+
+	public dynamic function onKeyUp( e : Event ) {
+	}
+
+	public dynamic function onKeyDown( e : Event ) {
+	}
 	
 }

+ 36 - 0
h2d/Key.hx

@@ -0,0 +1,36 @@
+package h2d;
+
+class Key {
+	public static inline var BACK 		= 8;
+	public static inline var TAB		= 9;
+	public static inline var ENTER		= 13;
+	public static inline var SHIFT		= 16;
+	public static inline var CTRL		= 17;
+	public static inline var ALT		= 18;
+	public static inline var ESCAPE		= 27;
+	public static inline var SPACE		= 32;
+	public static inline var PGUP		= 33;
+	public static inline var PGDOWN		= 34;
+	public static inline var END		= 35;
+	public static inline var HOME		= 36;
+	public static inline var LEFT		= 37;
+	public static inline var UP			= 38;
+	public static inline var RIGHT		= 39;
+	public static inline var DOWN		= 40;
+	public static inline var INSERT		= 45;
+	public static inline var DELETE		= 46;
+	
+	public static inline var NUMBER_0	= 48;
+	public static inline var NUMPAD_0	= 96;
+	public static inline var A			= 65;
+	public static inline var F1			= 112;
+	
+	public static inline var NUMPAD_MULT = 106;
+	public static inline var NUMPAD_ADD	= 107;
+	public static inline var NUMPAD_ENTER = 108;
+	public static inline var NUMPAD_SUB = 109;
+	public static inline var NUMPAD_DOT = 110;
+	public static inline var NUMPAD_DIV = 111;
+	
+}
+

+ 52 - 8
h2d/Scene.hx

@@ -16,6 +16,9 @@ class Scene extends Layers implements h3d.IDrawable {
 	
 	@:allow(h2d.Interactive)
 	var currentOver : Interactive;
+	@:allow(h2d.Interactive)
+	var currentFocus : Interactive;
+		
 	var pushList : Array<Interactive>;
 	var currentDrag : { f : Event -> Void, ref : Null<Int> };
 	
@@ -48,7 +51,10 @@ class Scene extends Layers implements h3d.IDrawable {
 			stage.removeEventListener(flash.events.MouseEvent.MOUSE_MOVE, onMouseMove);
 			stage.removeEventListener(flash.events.MouseEvent.MOUSE_UP, onMouseUp);
 			stage.removeEventListener(flash.events.MouseEvent.MOUSE_WHEEL, onMouseWheel);
-			flash.ui.Mouse.cursor = flash.ui.MouseCursor.AUTO;
+			stage.removeEventListener(flash.events.MouseEvent.MOUSE_UP, onMouseUp);
+			stage.removeEventListener(flash.events.KeyboardEvent.KEY_DOWN, onKeyDown);
+			stage.removeEventListener(flash.events.KeyboardEvent.KEY_UP, onKeyUp);
+			h3d.System.setCursor(Default);
 		}
 		super.onDelete();
 	}
@@ -64,6 +70,8 @@ class Scene extends Layers implements h3d.IDrawable {
 			stage.addEventListener(flash.events.MouseEvent.MOUSE_MOVE, onMouseMove);
 			stage.addEventListener(flash.events.MouseEvent.MOUSE_UP, onMouseUp);
 			stage.addEventListener(flash.events.MouseEvent.MOUSE_WHEEL, onMouseWheel);
+			stage.addEventListener(flash.events.KeyboardEvent.KEY_DOWN, onKeyDown);
+			stage.addEventListener(flash.events.KeyboardEvent.KEY_UP, onKeyUp);
 		}
 		super.onAlloc();
 	}
@@ -107,6 +115,24 @@ class Scene extends Layers implements h3d.IDrawable {
 		}
 	}
 	
+	function onKeyUp(e:flash.events.KeyboardEvent) {
+		if( pendingEvents != null ) {
+			var ev = new Event(EKeyUp);
+			ev.keyCode = e.keyCode;
+			ev.charCode = e.charCode;
+			pendingEvents.push(ev);
+		}
+	}
+
+	function onKeyDown(e:flash.events.KeyboardEvent) {
+		if( pendingEvents != null ) {
+			var ev = new Event(EKeyDown);
+			ev.keyCode = e.keyCode;
+			ev.charCode = e.charCode;
+			pendingEvents.push(ev);
+		}
+	}
+	
 	function onTouchDown(e:flash.events.TouchEvent) {
 		if( pendingEvents != null ) {
 			var ev = new Event(EPush, screenXToLocal(e.localX), screenYToLocal(e.localY));
@@ -136,13 +162,20 @@ class Scene extends Layers implements h3d.IDrawable {
 		var rx = x * matA + y * matB + absX;
 		var ry = x * matC + y * matD + absY;
 		var r = height / width;
-		var checkOver = false, checkPush = false;
+		var checkOver = false, checkPush = false, cancelFocus = false;
 		switch( event.kind ) {
 		case EMove: checkOver = true;
-		case EPush, ERelease: checkPush = true;
+		case EPush: cancelFocus = true; checkPush = true;
+		case ERelease: checkPush = true;
+		case EKeyUp, EKeyDown:
+			if( currentFocus != null )
+				currentFocus.handleEvent(event);
+			return;
 		default:
 		}
 		for( i in interactive ) {
+			
+
 			// TODO : we are not sure that the positions are correctly updated !
 			
 			// this is a bit tricky since we are not in the not-euclide viewport space
@@ -175,6 +208,7 @@ class Scene extends Layers implements h3d.IDrawable {
 			event.relY = (ky / max) * i.height;
 			
 			i.handleEvent(event);
+			
 			if( event.cancel )
 				event.cancel = false;
 			else if( checkOver ) {
@@ -199,19 +233,29 @@ class Scene extends Layers implements h3d.IDrawable {
 					event.propagate = old;
 				} else
 					checkOver = false;
-			} else if( checkPush ) {
-				if( event.kind == EPush )
-					pushList.push(i);
-				else
-					pushList.remove(i);
+			} else {
+				if( checkPush ) {
+					if( event.kind == EPush )
+						pushList.push(i);
+					else
+						pushList.remove(i);
+				}
+				if( cancelFocus && i == currentFocus )
+					cancelFocus = false;
 			}
 				
 			if( event.propagate ) {
 				event.propagate = false;
 				continue;
 			}
+			
 			break;
 		}
+		if( cancelFocus && currentFocus != null ) {
+			event.kind = EFocusLost;
+			currentFocus.handleEvent(event);
+			event.kind = EPush;
+		}
 		if( checkOver && currentOver != null ) {
 			event.kind = EOut;
 			currentOver.handleEvent(event);

+ 9 - 5
h2d/Text.hx

@@ -31,7 +31,7 @@ class Text extends Drawable {
 	
 	override function onAlloc() {
 		super.onAlloc();
-		if( text != null && font != null ) initGlyphs();
+		if( text != null && font != null ) initGlyphs(text);
 	}
 	
 	override function draw(ctx:RenderContext) {
@@ -53,11 +53,15 @@ class Text extends Drawable {
 	
 	function set_text(t) {
 		this.text = t == null ? "null" : t;
-		if( allocated ) initGlyphs();
+		if( allocated ) initGlyphs(text);
 		return t;
 	}
 	
-	function initGlyphs( rebuild = true ) {
+	public function calcTextWidth( text : String ) {
+		return initGlyphs(text,false).width;
+	}
+	
+	function initGlyphs( text : String, rebuild = true ) {
 		if( rebuild ) glyphs.reset();
 		var letters = font.glyphs;
 		var x = 0, y = 0, xMax = 0;
@@ -94,11 +98,11 @@ class Text extends Drawable {
 	}
 	
 	function get_textHeight() {
-		return initGlyphs(false).height;
+		return initGlyphs(text,false).height;
 	}
 	
 	function get_textWidth() {
-		return initGlyphs(false).width;
+		return initGlyphs(text,false).width;
 	}
 	
 	function set_maxWidth(w) {

+ 116 - 0
h2d/comp/Input.hx

@@ -0,0 +1,116 @@
+package h2d.comp;
+
+@:access(h2d.comp.Input.scene)
+class Input extends Component {
+	
+	var input : h2d.Interactive;
+	var tf : h2d.Text;
+	var cursor : h2d.Bitmap;
+	var cursorPos(default,set) : Int;
+	
+	public var value(default, set) : String;
+	
+	public function new(?parent) {
+		super("input",parent);
+		tf = new h2d.Text(null, this);
+		input = new h2d.Interactive(0, 0, bg);
+		input.cursor = TextInput;
+		cursor = new h2d.Bitmap(null, bg);
+		cursor.visible = false;
+		var active = false;
+		input.onPush = function(_) {
+			focus();
+		};
+		input.onOver = function(_) {
+			addClass(":hover");
+		};
+		input.onOut = function(_) {
+			active = false;
+			removeClass(":hover");
+		};
+		input.onFocus = function(_) {
+			addClass(":focus");
+			cursor.visible = true;
+		};
+		input.onFocusLost = function(_) {
+			removeClass(":focus");
+			cursor.visible = false;
+		};
+		input.onKeyDown = function(e:Event) {
+			if( input.hasFocus() ) {
+				// BACK
+				switch( e.keyCode ) {
+				case Key.LEFT:
+					if( cursorPos > 0 )
+						cursorPos--;
+				case Key.RIGHT:
+					if( cursorPos < value.length )
+						cursorPos++;
+				case Key.HOME:
+					cursorPos = 0;
+				case Key.END:
+					cursorPos = value.length;
+				case Key.DELETE:
+					value = value.substr(0, cursorPos) + value.substr(cursorPos + 1);
+					onChange(value);
+					return;
+				case Key.BACK:
+					value = value.substr(0, cursorPos - 1) + value.substr(cursorPos);
+					cursorPos--;
+					onChange(value);
+					return;
+				}
+				if( e.charCode != 0 ) {
+					value = value.substr(0, cursorPos) + String.fromCharCode(e.charCode) + value.substr(cursorPos);
+					cursorPos++;
+					onChange(value);
+				}
+			}
+		};
+		this.value = "";
+	}
+	
+	function set_cursorPos(v:Int) {
+		cursor.x = tf.calcTextWidth(value.substr(0, v)) + extLeft();
+		return cursorPos = v;
+	}
+
+	public function focus() {
+		input.focus();
+		cursorPos = value.length;
+	}
+	
+	function get_value() {
+		return tf.text;
+	}
+	
+	function set_value(t) {
+		needRebuild = true;
+		return value = t;
+	}
+	
+	override function resize( ctx : Context ) {
+		if( ctx.measure ) {
+			tf.font = getFont();
+			tf.textColor = style.color;
+			tf.text = value;
+			tf.filter = true;
+			contentWidth = tf.textWidth;
+			contentHeight = tf.textHeight;
+			if( cursorPos < 0 ) cursorPos = 0;
+			if( cursorPos > value.length ) cursorPos = value.length;
+			cursorPos = cursorPos;
+		}
+		super.resize(ctx);
+		if( !ctx.measure ) {
+			input.width = width - (style.marginLeft + style.marginRight);
+			input.height = height - (style.marginTop + style.marginBottom);
+			cursor.y = extTop() - 1;
+			cursor.tile = h2d.Tile.fromColor(style.cursorColor | 0xFF000000, 1, Std.int(height - extTop() - extBottom() + 2));
+		}
+	}
+	
+	public dynamic function onChange( value : String ) {
+	}
+	
+}

+ 9 - 0
h2d/comp/Parser.hx

@@ -43,6 +43,8 @@ class Parser {
 			c = new Checkbox(parent);
 		case "itemlist":
 			c = new ItemList(parent);
+		case "input":
+			c = new Input(parent);
 		case n:
 			var make = comps.get(n);
 			if( make != null )
@@ -65,6 +67,9 @@ class Parser {
 				case "slider":
 					var c : Slider = cast c;
 					c.value = Std.parseFloat(v);
+				case "input":
+					var c : Input = cast c;
+					c.value = v;
 				default:
 				}
 			case "onclick":
@@ -88,6 +93,10 @@ class Parser {
 					var c : ItemList = cast c;
 					var s = makeScript(c,v);
 					c.onChange = function(_) s();
+				case "input":
+					var c : Input = cast c;
+					var s = makeScript(c,v);
+					c.onChange = function(_) s();
 				default:
 				}
 			case "style":

+ 13 - 0
h2d/css/default.css

@@ -81,3 +81,16 @@ itemlist {
 	border : 1px solid gradient(#A0A0A0,#909090,#707070,#606060);
 	background-color : gradient(#303030,#252525,#252525,#252525);
 }
+
+input {
+	width : 80px;
+	height : 16px;
+	padding : 3px;
+	border : 1px solid gradient(#A0A0A0,#909090,#707070,#606060);
+	background-color : gradient(#303030,#252525,#252525,#252525);
+}
+
+input:focus {
+	border : 1px solid white;
+	cursor-color : white;
+}

+ 3 - 0
samples/comps/components.html

@@ -67,6 +67,9 @@
 				</div>
 			</itemlist>
 			
+			<input value="bla"/>
+			<input/>
+			
 			<div class="dock">
 				<div class="panel border" style="dock:top; height:60px"/>
 				<div class="panel border" style="dock:left; width:30px"/>

BIN
samples/comps/comps.swf