Explorar el Código

added html tags support

Nicolas Cannasse hace 9 meses
padre
commit
357024ccde
Se han modificado 3 ficheros con 134 adiciones y 15 borrados
  1. 78 15
      h2d/HtmlText.hx
  2. 28 0
      h2d/domkit/BaseComponents.hx
  3. 28 0
      h2d/domkit/Style.hx

+ 78 - 15
h2d/HtmlText.hx

@@ -66,6 +66,15 @@ class HtmlText extends Text {
 		return text;
 	}
 
+	static var defaultHtmlTags : Map<String,{color:Int,font:String}>;
+	/**
+		Associate a custom html tag to a specific font and color.
+	**/
+	public static function defineDefaultHtmlTag( name : String, ?fontColor : Int, ?fontName : String ) {
+		if( defaultHtmlTags == null ) defaultHtmlTags = [];
+		defaultHtmlTags.set(name,{color:fontColor,font:fontName});
+	}
+
 	/**
 		When enabled, condenses extra spaces (carriage-return, line-feed, tabulation and space character) to one space.
 		If not set, uncondensed whitespace is left as is, as well as line-breaks.
@@ -105,6 +114,7 @@ class HtmlText extends Text {
 	var newLine : Bool;
 	var aHrefs : Array<String>;
 	var aInteractive : Interactive;
+	var htmlTags : Map<String,{?color:Int,?font:String}>;
 
 	override function draw(ctx:RenderContext) {
 		if( dropShadow != null ) {
@@ -193,6 +203,31 @@ class HtmlText extends Text {
 		return defaultFormatText(text);
 	}
 
+	/**
+		Define a custom html tag to be displayed with specific font and color.
+	**/
+	public function defineHtmlTag( name : String, ?fontColor : Int, ?fontName : String ) {
+		if( htmlTags == null ) htmlTags = [];
+		htmlTags.set(name,{color:fontColor,font:fontName});
+		rebuild();
+	}
+
+	/**
+		Define or reset a set of custom html tags to be displayed with specific font and color.
+	**/
+	public function defineHtmlTags( tags : Array<{ name : String, ?color : Int, ?font : String }> ) {
+		if( tags == null ) {
+			if( htmlTags == null )
+				return;
+			htmlTags = null;
+		} else {
+			htmlTags = [];
+			for( t in tags )
+				htmlTags.set(t.name,{color:t.color,font:t.font});
+		}
+		rebuild();
+	}
+
 	override function set_text(t : String) {
 		super.set_text(formatText(t));
 		return t;
@@ -211,21 +246,36 @@ class HtmlText extends Text {
 		validateNodes(textXml);
 	}
 
+	function resolveHtmlTag( name : String ) {
+		if( htmlTags != null ) {
+			var t = htmlTags.get(name);
+			if( t != null ) return t;
+		}
+		if( defaultHtmlTags != null ) {
+			var t = defaultHtmlTags.get(name);
+			if( t != null ) return t;
+		}
+		return null;
+	}
+
 	function validateNodes( xml : Xml ) {
 		switch( xml.nodeType ) {
 		case Element:
 			var nodeName = xml.nodeName.toLowerCase();
-			switch ( nodeName ) {
-				case "img":
-					loadImage(xml.get("src"));
-				case "font":
-					if (xml.exists("face")) {
-						loadFont(xml.get("face"));
-					}
-				case "b", "bold":
-					loadFont("bold");
-				case "i", "italic":
-					loadFont("italic");
+			var t = resolveHtmlTag(nodeName);
+			if( t?.font != null ) loadFont(t.font);
+			switch( nodeName ) {
+			case "img":
+				loadImage(xml.get("src"));
+			case "font":
+				if (xml.exists("face")) {
+					loadFont(xml.get("face"));
+				}
+			case "b", "bold":
+				if( t?.font == null ) loadFont("bold");
+			case "i", "italic":
+				if( t?.font == null ) loadFont("italic");
+			default:
 			}
 			for( child in xml )
 				validateNodes(child);
@@ -330,6 +380,9 @@ class HtmlText extends Text {
 			}
 
 			var nodeName = e.nodeName.toLowerCase();
+			var tag = resolveHtmlTag(nodeName);
+			if( tag?.font != null )
+				font = loadFont(tag.font);
 			switch( nodeName ) {
 			case "p":
 				if ( !newLine ) {
@@ -396,9 +449,11 @@ class HtmlText extends Text {
 					}
 				}
 			case "b", "bold":
-				font = loadFont("bold");
+				if( tag?.font == null )
+					font = loadFont("bold");
 			case "i", "italic":
-				font = loadFont("italic");
+				if( tag?.font == null )
+					font = loadFont("italic");
 			default:
 			}
 			for( child in e )
@@ -668,6 +723,14 @@ class HtmlText extends Text {
 				@:privateAccess glyphs.curColor.load(prev.curColor);
 				elements.push(glyphs);
 			}
+			var tag = resolveHtmlTag(nodeName);
+			if( tag != null ) {
+				if( tag.font != null ) setFont(tag.font);
+				if( tag.color != null ) {
+					if( prevColor == null ) prevColor = @:privateAccess glyphs.curColor.clone();
+					glyphs.setDefaultColor(tag.color);
+				}
+			}
 			switch( nodeName ) {
 			case "font":
 				for( a in e.attributes() ) {
@@ -716,9 +779,9 @@ class HtmlText extends Text {
 					nextLine(align, metrics[sizePos].width);
 				}
 			case "b","bold":
-				setFont("bold");
+				if( tag?.font == null ) setFont("bold");
 			case "i","italic":
-				setFont("italic");
+				if( tag?.font == null ) setFont("italic");
 			case "br":
 				makeLineBreak();
 				newLine = true;

+ 28 - 0
h2d/domkit/BaseComponents.hx

@@ -448,6 +448,28 @@ class CustomParser extends domkit.CssValue.ValueParser {
 		return 0.;
 	}
 
+	function parseTagDefinition(value:CssValue) : {name:String,?font:String,?color:Int} {
+		return switch( value ) {
+		case VCall(id,[VString(font)]):
+			{name:id,font:font};
+		case VCall(id,[v = VIdent(c)]):
+			try {name:id,color:parseColor(v)} catch( e : InvalidProperty ) {name:id,font:c};
+		case VCall(id,[v]):
+			{name:id,color:parseColor(v)};
+		case VCall(id,[VString(font)|VIdent(font),col]):
+			{name:id,font:font,color:parseColor(col)};
+		default:
+			invalidProp();
+		}
+	}
+
+	public function parseTagDefinitions(value:CssValue) {
+		return switch(value) {
+		case VGroup(values): [for( v in values ) parseTagDefinition(v)];
+		default: [parseTagDefinition(value)];
+		}
+	}
+
 }
 
 #if !macro
@@ -824,6 +846,7 @@ class TextComp extends DrawableComp implements domkit.Component.ComponentDecl<h2
 class HtmlTextComp extends TextComp implements domkit.Component.ComponentDecl<h2d.HtmlText> {
 	@:p var condenseWhite : Bool;
 	@:p var propagateInteractiveNode: Bool;
+	@:p(tagDefinitions) var tags : Array<{name:String,font:String,color:Int}>;
 
 	static function create( parent : h2d.Object ) {
 		return new h2d.HtmlText(hxd.res.DefaultFont.get(),parent);
@@ -836,6 +859,11 @@ class HtmlTextComp extends TextComp implements domkit.Component.ComponentDecl<h2
 	static function set_propagateInteractiveNode(o : h2d.HtmlText, v) {
 		o.propagateInteractiveNode = v;
 	}
+
+	static function set_tags( o : h2d.HtmlText, tags:Array<{name:String,font:String,color:Int}>) {
+		o.defineHtmlTags(tags);
+	}
+
 }
 
 @:uiComp("scale-grid") @:domkitDecl

+ 28 - 0
h2d/domkit/Style.hx

@@ -557,6 +557,34 @@ class Style extends domkit.CssStyle {
 				posLines.push(lStr);
 				valueLines.push('<font color="#D0D0D0"> ${p.name}</font> <font color="#808080">$vstr</font>');
 			}
+			var txt = Std.downcast(obj, h2d.HtmlText);
+			if( txt != null ) {
+				// if the text has custom nodes, display them in CSS
+				var x = try @:privateAccess txt.parseText(txt.text) catch( e : Dynamic ) null;
+				var nodes = new Map();
+				function gatherRec(x:Xml) {
+					switch( x.nodeType ) {
+					case Element:
+						nodes.set(x.nodeName.toLowerCase(), true);
+						for( c in x )
+							gatherRec(c);
+					case Document:
+						for( c in x )
+							gatherRec(c);
+					default:
+					}
+				}
+				gatherRec(x);
+				nodes.remove("font");
+				nodes.remove("br");
+				nodes.remove("img");
+				var nodes = [for( k in nodes.keys() ) k];
+				nodes.sort(Reflect.compare);
+				if( nodes.length > 0 ) {
+					posLines.push("");
+					valueLines.push('<font color="#D0D0D0"> text-tags</font> <font color="#808080">${nodes.join(',')}</font>');
+				}
+			}
 			propsLineText.text = posLines.join("<br/>");
 			propsValueText.text = valueLines.join("<br/>");
 		}