فهرست منبع

started css engine (not working yet)

ncannasse 6 سال پیش
والد
کامیت
2fef60cea1
4فایلهای تغییر یافته به همراه158 افزوده شده و 6 حذف شده
  1. 127 0
      h2d/uikit/CssEngine.hx
  2. 27 4
      h2d/uikit/CssParser.hx
  3. 3 2
      h2d/uikit/Element.hx
  4. 1 0
      h2d/uikit/Property.hx

+ 127 - 0
h2d/uikit/CssEngine.hx

@@ -0,0 +1,127 @@
+package h2d.uikit;
+
+private class Rule {
+	public var id : Int;
+	public var priority : Int;
+	public var cl : CssParser.CssClass;
+	public var properties : Array<Property>;
+	public function new() {
+	}
+}
+
+@:access(h2d.uikit.Element)
+class CssEngine {
+
+	var rules : Array<Rule>;
+	var needSort = true;
+
+	public function new() {
+		rules = [];
+	}
+
+	function sortByPriority(r1:Rule, r2:Rule) {
+		var dp = r1.priority - r2.priority;
+		return dp == 0 ? r1.id - r2.id : dp;
+	}
+
+	public function applyStyle( e : Element ) {
+		if( needSort ) {
+			needSort = false;
+			rules.sort(sortByPriority);
+		}
+		if( e.needStyleRefresh ) {
+			e.needStyleRefresh = false;
+			for( r in rules ) {
+				if( !ruleMatch(r.cl,e) ) continue;
+			}
+		}
+	}
+
+	public function add( sheet : CssParser.CssSheet ) {
+		for( r in sheet ) {
+			var important = [];
+			for( p in r.style ) {
+				switch( p ) {
+				case PImportant(p): important.push(p);
+				default:
+				}
+			}
+			var style = r.style;
+			if( important.length != 0 )
+				style = [for( p in r.style ) if( !p.match(PImportant(_)) ) p];
+			for( cl in r.classes ) {
+				var nids = 0, nothers = 0, nnodes = 0;
+				var c = cl;
+				while( c != null ) {
+					if( c.id != null ) nids++;
+					if( c.node != null ) nnodes++;
+					if( c.pseudoClass != null ) nothers++;
+					if( c.className != null ) nothers++;
+					c = c.parent;
+				}
+				var priority = (nids << 16) | (nothers << 8) | nnodes;
+
+				if( style.length > 0 ) {
+					var rule = new Rule();
+					rule.id = rules.length;
+					rule.cl = cl;
+					rule.properties = style;
+					rule.priority = priority;
+					rules.push(rule);
+				}
+
+				if( important.length > 0 ) {
+					var rule = new Rule();
+					rule.id = rules.length;
+					rule.cl = cl;
+					rule.properties = important;
+					rule.priority = (1<<24) | priority;
+					rules.push(rule);
+				}
+			}
+		}
+		needSort = true;
+	}
+
+	public static function ruleMatch( c : CssParser.CssClass, e : Element ) {
+		if( c.pseudoClass != null ) {
+			var pc = ":" + c.pseudoClass;
+			var found = false;
+			for( cc in e.classes )
+				if( cc == pc ) {
+					found = true;
+					break;
+				}
+			if( !found )
+				return false;
+		}
+		if( c.className != null ) {
+			if( e.classes == null )
+				return false;
+			var found = false;
+			for( cc in e.classes )
+				if( cc == c.className ) {
+					found = true;
+					break;
+				}
+			if( !found )
+				return false;
+		}
+		if( c.node != null && c.node != e.obj.name )
+			return false;
+		if( c.id != null && c.id != e.id )
+			return false;
+		if( c.parent != null ) {
+			var p = e.parent;
+			while( p != null ) {
+				if( ruleMatch(c.parent, p) )
+					break;
+				p = p.parent;
+			}
+			if( p == null )
+				return false;
+		}
+		return true;
+	}
+
+}

+ 27 - 4
h2d/uikit/CssParser.hx

@@ -46,6 +46,8 @@ class CssClass {
 	}
 }
 
+typedef CssSheet = Array<{ classes : Array<CssClass>, style : Array<Property> }>;
+
 class CssParser {
 
 	var css : String;
@@ -53,8 +55,11 @@ class CssParser {
 
 	var spacesTokens : Bool;
 	var tokens : Array<Token>;
+	var pparser : Property.PropertyParser;
+	public var warnings : Array<{ start : Int, end : Int, msg : String }>;
 
 	public function new() {
+		this.pparser = new Property.PropertyParser();
 	}
 
 	function error( msg : String ) {
@@ -110,6 +115,7 @@ class CssParser {
 		this.css = css;
 		pos = 0;
 		tokens = [];
+		warnings = [];
 		return parseStyle(TEof);
 	}
 
@@ -117,6 +123,7 @@ class CssParser {
 		this.css = valueStr;
 		pos = 0;
 		tokens = [];
+		warnings = [];
 		var v = readValue();
 		expect(TEof);
 		return v;
@@ -145,10 +152,26 @@ class CssParser {
 		while( true ) {
 			if( isToken(eof) )
 				break;
-			var r = readIdent();
+			var start = pos;
+			var name = readIdent();
 			expect(TDblDot);
-			var v = readValue();
-			style.push({ name : r, value : v });
+			var value = readValue();
+			var imp = false;
+			switch( value ) {
+			case VLabel("important", val):
+				imp = true;
+				value = val;
+			default:
+			}
+			var p = pparser.parse(name, value);
+			if( p == null )
+				warnings.push({ start : start, end : pos, msg : "Invalid property value "+valueStr(value) });
+			else if( p == PUnknown )
+				warnings.push({ start : start, end : pos, msg : "Unknown property "+name });
+			else {
+				if( imp ) p = PImportant(p);
+				style.push(p);
+			}
 			if( isToken(eof) )
 				break;
 			expect(TSemicolon);
@@ -156,7 +179,7 @@ class CssParser {
 		return style;
 	}
 
-	public function parseRules( css : String ) {
+	public function parseSheet( css : String ) : CssSheet {
 		this.css = css;
 		pos = 0;
 		tokens = [];

+ 3 - 2
h2d/uikit/Element.hx

@@ -2,11 +2,13 @@ package h2d.uikit;
 
 class Element {
 
+	public var id : String;
 	public var obj : h2d.Object;
 	public var component : Component<Dynamic>;
-	public var classes : Array<String> = [];
+	public var classes : Array<String>;
 	public var parent : Element;
 	public var children : Array<Element> = [];
+	public var style : Array<Property> = [];
 	var needStyleRefresh : Bool = true;
 
 	public function new(obj,component,?parent) {
@@ -25,7 +27,6 @@ class Element {
 	}
 
 	public function setProp( p : Property ) {
-		trace( Std.string(p) );
 		switch( p ) {
 		case PClasses(cl):
 			classes = cl.copy();

+ 1 - 0
h2d/uikit/Property.hx

@@ -40,6 +40,7 @@ enum Property {
 	// Bitmap
 	PSource( res : hxd.res.Any );
 	// Other
+	PImportant( p : Property );
 	PCustom( name : String, value : Dynamic );
 	PUnknown;
 }