Ver código fonte

added text support

ncannasse 6 anos atrás
pai
commit
f9aa2aacdb
4 arquivos alterados com 212 adições e 24 exclusões
  1. 125 15
      h2d/uikit/BaseComponents.hx
  2. 9 5
      h2d/uikit/Builder.hx
  3. 68 3
      h2d/uikit/Component.hx
  4. 10 1
      h2d/uikit/CssParser.hx

+ 125 - 15
h2d/uikit/BaseComponents.hx

@@ -3,18 +3,27 @@ import h2d.uikit.Property;
 import h2d.uikit.CssParser.Value;
 
 final class Object extends Component<h2d.Object> {
+
+	static var p_min_width : Property<Null<Int>>;
+	static var p_min_height : Property<Null<Int>>;
+	static var p_max_width : Property<Null<Int>>;
+
 	function new() {
 		super("object",h2d.Object,h2d.Object.new,null);
+
+		// h2d.Object properties
 		addHandler( defineProp("name",parseIdent,null), (o,v) -> o.name = v);
-		addHandler( defineProp("position", parsePosition, { x : 0, y : 0 }), (o,v) -> { o.x = v.x; o.y = v.y; });
 		addHandler( defineProp("x", parseFloat, 0), (o,v) -> o.x = v);
 		addHandler( defineProp("y", parseFloat, 0), (o,v) -> o.y = v);
 		addHandler( defineProp("alpha", parseFloat, 1), (o,v) -> o.alpha = v);
 		addHandler( defineProp("rotation", parseFloat, 0), (o,v) -> o.rotation = v * Math.PI / 180);
 		addHandler( defineProp("visible", parseBool, true), (o,v) -> o.visible = v);
 		addHandler( defineProp("scale", parseScale, { x : 1, y : 1 }), (o,v) -> { o.scaleX = v.x; o.scaleY = v.y; });
+		addHandler( defineProp("blend", parseBlend, Alpha), (o,v) -> o.blendMode = v);
+
+		// flow properties
 		addHandler( defineProp("margin", parseBox, { left : 0, top : 0, right : 0, bottom : 0 }), (o,v) -> {
-			var p = getFlowParent(o);
+			var p = getFlowProps(o);
 			if( p != null ) {
 				p.paddingLeft = v.left;
 				p.paddingRight = v.right;
@@ -23,32 +32,79 @@ final class Object extends Component<h2d.Object> {
 			}
 		});
 		addHandler( defineProp("margin-left", parseInt, 0), (o,v) -> {
-			var p = getFlowParent(o);
+			var p = getFlowProps(o);
 			if( p != null ) p.paddingLeft = v;
 		});
 		addHandler( defineProp("margin-top", parseInt, 0), (o,v) -> {
-			var p = getFlowParent(o);
+			var p = getFlowProps(o);
 			if( p != null ) p.paddingTop = v;
 		});
 		addHandler( defineProp("margin-right", parseInt, 0), (o,v) -> {
-			var p = getFlowParent(o);
+			var p = getFlowProps(o);
 			if( p != null ) p.paddingRight = v;
 		});
 		addHandler( defineProp("margin-bottom", parseInt, 0), (o,v) -> {
-			var p = getFlowParent(o);
+			var p = getFlowProps(o);
 			if( p != null ) p.paddingBottom = v;
 		});
-		addHandler( defineProp("blend", parseBlend, Alpha), (o,v) -> o.blendMode = v);
+		addHandler( defineProp("align", parseAlign, { h : null, v : null }), (o,v) -> {
+			var p = getFlowProps(o);
+			if( p != null ) {
+				p.horizontalAlign = v.h;
+				p.verticalAlign = v.v;
+			}
+		});
+		addHandler( defineProp("halign", parseHAlign, null), (o,v) -> {
+			var p = getFlowProps(o);
+			if( p != null ) p.horizontalAlign = v;
+		});
+		addHandler( defineProp("valign", parseVAlign, null), (o,v) -> {
+			var p = getFlowProps(o);
+			if( p != null ) p.verticalAlign = v;
+		});
+		addHandler( defineProp("position",parsePosition,false), (o,v) -> {
+			var p = getFlowProps(o);
+			if( p != null ) p.isAbsolute = v;
+		});
+		addHandler( defineProp("offset", parseXY, { x : 0, y : 0 }), (o,v) -> {
+			var p = getFlowProps(o);
+			if( p != null ) {
+				p.offsetX = Std.int(v.x);
+				p.offsetY = Std.int(v.y);
+			}
+		});
+		addHandler( defineProp("offset-x", parseInt, 0), (o,v) -> {
+			var p = getFlowProps(o);
+			if( p != null ) p.offsetX = v;
+		});
+		addHandler( defineProp("offset-y", parseInt, 0), (o,v) -> {
+			var p = getFlowProps(o);
+			if( p != null ) p.offsetY = v;
+		});
+
+		addHandler( p_min_width = defineProp("min-width",parseNone.bind(parseInt),null), (o,v) -> {
+			var p = getFlowProps(o);
+			if( p != null ) p.minWidth = v;
+		});
+		addHandler( p_min_height = defineProp("min-height",parseNone.bind(parseInt),null), (o,v) -> {
+			var p = getFlowProps(o);
+			if( p != null ) p.minHeight = v;
+		});
+
+		p_max_width = defineProp("max-width",parseNone.bind(parseInt),null);
 	}
 
-	function getFlowParent( o : h2d.Object ) {
-		return Std.instance(o.parent, h2d.Flow);
+	function getFlowProps( o : h2d.Object ) {
+		var p = Std.instance(o.parent, h2d.Flow);
+		return p == null ? null : p.getProperties(o);
 	}
 
 	function parsePosition( value ) {
 		switch( value ) {
-		case VGroup([x,y]):
-			return { x : parseFloat(x), y : parseFloat(y) };
+		case VIdent("auto"):
+			return false;
+		case VIdent("absolute"):
+			return true;
 		default:
 			return invalidProp();
 		}
@@ -113,10 +169,10 @@ final class Flow extends Component<h2d.Flow> {
 		super("flow",h2d.Flow,h2d.Flow.new, Object.inst);
 		addHandler(defineProp("width",parseAuto.bind(parseInt),null),(o,v) -> { o.minWidth = o.maxWidth = v; });
 		addHandler(defineProp("height",parseAuto.bind(parseInt),null),(o,v) -> { o.minHeight = o.maxHeight = v; });
-		addHandler(defineProp("min-width",parseAuto.bind(parseInt),null),(o,v) -> o.minWidth = v);
-		addHandler(defineProp("min-height",parseAuto.bind(parseInt),null),(o,v) -> o.minHeight = v);
-		addHandler(defineProp("max-width",parseAuto.bind(parseInt),null),(o,v) -> o.maxWidth = v);
-		addHandler(defineProp("max-height",parseAuto.bind(parseInt),null),(o,v) -> o.maxHeight = v);
+		addHandler(@:privateAccess Object.p_min_width,(o,v) -> o.minWidth = v);
+		addHandler(@:privateAccess Object.p_min_height,(o,v) -> o.minHeight = v);
+		addHandler(@:privateAccess Object.p_max_width,(o,v) -> o.maxWidth = v);
+		addHandler(defineProp("max-height",parseNone.bind(parseInt),null),(o,v) -> o.maxHeight = v);
 		addHandler(defineProp("background",parseBackground,null),(o,v) -> {
 			if( v == null ) {
 				o.backgroundTile = null;
@@ -138,6 +194,12 @@ final class Flow extends Component<h2d.Flow> {
 		addHandler(defineProp("padding-right", parseInt, 0), (o,v) -> o.paddingRight = v);
 		addHandler(defineProp("padding-top", parseInt, 0), (o,v) -> o.paddingTop = v);
 		addHandler(defineProp("padding-bottom", parseInt, 0), (o,v) -> o.paddingBottom = v);
+		addHandler(defineProp("content-align", parseAlign, { h : null, v : null }), (o,v) -> {
+			o.horizontalAlign = v.h;
+			o.verticalAlign = v.v;
+		});
+		addHandler(defineProp("content-halign", parseVAlign, null), (o,v) -> o.horizontalAlign = v);
+		addHandler(defineProp("content-valign", parseHAlign, null), (o,v) -> o.verticalAlign = v);
 	}
 
 	function parseBackground(value) {
@@ -153,3 +215,51 @@ final class Flow extends Component<h2d.Flow> {
 	static var inst = new Flow();
 
 }
+
+final class Text extends Component<h2d.Text> {
+
+	public function new() {
+		super("text",h2d.Text,function(p) return new h2d.Text(hxd.res.DefaultFont.get(),p), Drawable.inst);
+		addHandler( defineProp("text",parseText,""), (o,v) -> o.text = v);
+		addHandler( defineProp("font",parseFont,null), (o,v) -> o.font = v == null ? hxd.res.DefaultFont.get() : v );
+		addHandler( defineProp("letter-spacing",parseInt,1), (o,v) -> o.letterSpacing = v);
+		addHandler( defineProp("line-spacing",parseInt,0), (o,v) -> o.lineSpacing = v);
+		addHandler( @:privateAccess Object.p_max_width, (o,v) -> o.maxWidth = v);
+		addHandler( defineProp("text-align",parseTextAlign, Left), (o,v) -> o.textAlign = v);
+		addHandler( defineProp("text-shadow",parseNone.bind(parseTextShadow), null), (o,v) -> o.dropShadow = v);
+	}
+
+	function parseTextAlign( value : CssParser.Value ) : h2d.Text.Align {
+		return switch( parseIdent(value) ) {
+		case "left": Left;
+		case "right": Right;
+		case "center": Center;
+		default: invalidProp();
+		}
+	}
+
+	function parseText( value : CssParser.Value ) {
+		return switch( value ) {
+		case VString(str): str;
+		case VIdent(i): i;
+		default: invalidProp();
+		}
+	}
+
+	function parseTextShadow( value : CssParser.Value ) {
+		return switch( value ) {
+		case VGroup(vl):
+			return { dx : parseFloat(vl[0]), dy : parseFloat(vl[1]), color : vl.length >= 3 ? parseColor(vl[2]) : 0, alpha : vl.length >= 4 ? parseFloat(vl[3]) : 1 };
+		default:
+			return { dx : 1, dy : 1, color : parseColor(value), alpha : 1 };
+		}
+	}
+
+	function parseFont( value : CssParser.Value ) {
+		var path = parsePath(value);
+		return loadResource(path).to(hxd.res.BitmapFont).toFont();
+	}
+
+	static var inst = new Text();
+
+}

+ 9 - 5
h2d/uikit/Builder.hx

@@ -34,13 +34,18 @@ class Builder {
 		return doc;
 	}
 
-	function buildRec( x : Xml, root : Element ) {
+	function buildRec( x : Xml, root : Element ) : Element {
+		var inst = null;
 		switch( x.nodeType ) {
 		case Comment, DocType, ProcessingInstruction, Document:
 			// nothing
 		case CData, PCData:
 			if( !IS_EMPTY.match(x.nodeValue) ) {
 				// add text
+				var txml = Xml.createElement("text");
+				inst = buildRec(txml, root);
+				if( inst != null )
+					inst.setAttribute(Property.get("text"), StringTools.trim(x.nodeValue));
 			}
 		case Element:
 			path.push(x.nodeName);
@@ -48,7 +53,7 @@ class Builder {
 			if( comp == null ) {
 				error("Unknown node");
 			} else {
-				var inst = new Element(comp.make(root == null ? null : root.obj), comp, root);
+				inst = new Element(comp.make(root == null ? null : root.obj), comp, root);
 				var css = new CssParser();
 				for( a in x.attributes() ) {
 					var v = x.get(a);
@@ -77,13 +82,12 @@ class Builder {
 					if( !inst.setAttribute(p,value) )
 						error("Unsupported attribute "+a+" in");
 				}
-				root = inst;
 			}
 			for( e in x )
-				buildRec(e, root);
+				buildRec(e, inst == null ? root : inst);
 			path.pop();
 		}
-		return root;
+		return inst;
 	}
 
 }

+ 68 - 3
h2d/uikit/Component.hx

@@ -30,7 +30,7 @@ class Component<T:h2d.Object> {
 		return switch( v ) { case VIdent(v): v; default: invalidProp(); }
 	}
 
-	function parseColor( v : CssParser.Value ) : Null<Int> {
+	function parseColor( v : CssParser.Value ) {
 		switch( v ) {
 		case VHex(h,color):
 			if( h.length == 3 ) {
@@ -48,14 +48,17 @@ class Component<T:h2d.Object> {
 		}
 	}
 
+	function loadResource( path : String ) {
+		return try hxd.res.Loader.currentInstance.load(path) catch( e : hxd.res.NotFound ) invalidProp("Resource not found "+path);
+	}
+
 	function parseTile( v : CssParser.Value ) {
 		try {
 			var c = parseColor(v);
 			return h2d.Tile.fromColor(c,1,1,(c>>>24)/255);
 		} catch( e : InvalidProperty ) {
 			var path = parsePath(v);
-			var res = try hxd.res.Loader.currentInstance.load(path) catch( e : hxd.res.NotFound ) invalidProp("Resource not found "+path);
-			return res.toTile();
+			return loadResource(path).toTile();
 		}
 	}
 
@@ -80,6 +83,10 @@ class Component<T:h2d.Object> {
 		return v.match(VIdent("auto")) ? null : either(v);
 	}
 
+	function parseNone<T>( either : CssParser.Value -> T, v : CssParser.Value ) : Null<T> {
+		return v.match(VIdent("none")) ? null : either(v);
+	}
+
 	function parseInt( v : CssParser.Value ) : Null<Int> {
 		return switch( v ) {
 		case VInt(i): i;
@@ -95,6 +102,64 @@ class Component<T:h2d.Object> {
 		}
 	}
 
+	function parseXY( v : CssParser.Value ) {
+		return switch( v ) {
+		case VGroup([x,y]): { x : parseFloat(x), y : parseFloat(y) };
+		default: invalidProp();
+		}
+	}
+
+	function parseHAlign( value ) : h2d.Flow.FlowAlign {
+		switch( parseIdent(value) ) {
+		case "auto":
+			return null;
+		case "middle":
+			return Middle;
+		case "left":
+			return Left;
+		case "right":
+			return Right;
+		default:
+			return invalidProp();
+		}
+	}
+
+	function parseVAlign( value ) : h2d.Flow.FlowAlign {
+		switch( parseIdent(value) ) {
+		case "auto":
+			return null;
+		case "middle":
+			return Middle;
+		case "top":
+			return Top;
+		case "bottom":
+			return Bottom;
+		default:
+			return invalidProp();
+		}
+	}
+
+	function parseAlign( value : CssParser.Value ) {
+		switch( value ) {
+		case VIdent("auto"):
+			return { h : null, v : null };
+		case VIdent(_):
+			try {
+				return { h : parseHAlign(value), v : null };
+			} catch( e : InvalidProperty ) {
+				return { h : null, v : parseVAlign(value) };
+			}
+		case VGroup([h,v]):
+			try {
+				return { h : parseHAlign(h), v : parseVAlign(v) };
+			} catch( e : InvalidProperty ) {
+				return { h : parseHAlign(v), v : parseVAlign(h) };
+			}
+		default:
+			return invalidProp();
+		}
+	}
+
 	function parseBox( v : CssParser.Value ) {
 		switch( v ) {
 		case VInt(v):

+ 10 - 1
h2d/uikit/CssParser.hx

@@ -48,6 +48,15 @@ class CssClass {
 
 typedef CssSheet = Array<{ classes : Array<CssClass>, style : Array<Property.PValue<Dynamic>> }>;
 
+class CssParserError {
+	public var message : String;
+	public var position : Int;
+	public function new(msg,pos) {
+		this.message = msg;
+		this.position = pos;
+	}
+}
+
 class CssParser {
 
 	var css : String;
@@ -61,7 +70,7 @@ class CssParser {
 	}
 
 	function error( msg : String ) {
-		throw msg;
+		throw new CssParserError(msg,pos);
 	}
 
 	function unexpected( t : Token ) : Dynamic {