2
0
Эх сурвалжийг харах

initial uikit editor/preview

ncannasse 6 жил өмнө
parent
commit
47880e40b1

+ 3 - 0
bin/defaultProps.json

@@ -96,6 +96,9 @@
 	"fx.shaders": [
 	"fx.shaders": [
 		"h3d.shader.AnimatedTexture",
 		"h3d.shader.AnimatedTexture",
 		"h3d.shader.ColorAdd"],
 		"h3d.shader.ColorAdd"],
+		
+	// UIKIT css files list	
+	"uikit.css" : [],
 
 
 	// reserved for internal ide usage
 	// reserved for internal ide usage
 	"debug.displayErrors" : true,
 	"debug.displayErrors" : true,

+ 10 - 0
bin/style.css

@@ -1175,3 +1175,13 @@ div.sp-container input:hover {
   padding: 5px;
   padding: 5px;
   height: 400px;
   height: 400px;
 }
 }
+.uikit .leftpanel .cssErrors {
+  background: #840;
+  border: 1px solid #F80;
+  color: #F80;
+  padding: 10px;
+  position: absolute;
+  z-index: 1;
+  left: 10px;
+  bottom: 10px;
+}

+ 10 - 0
bin/style.less

@@ -1306,5 +1306,15 @@ div.sp-container {
 				height: 400px;
 				height: 400px;
 			}
 			}
 		}
 		}
+		.cssErrors {
+			background : #840;
+			border : 1px solid #F80;
+			color : #F80;
+			padding : 10px;
+			position: absolute;
+			z-index: 1;
+			left : 10px;
+			bottom : 10px;
+		}
 	}
 	}
 }
 }

+ 6 - 7
hide/comp/CodeEditor.hx

@@ -63,7 +63,7 @@ class CodeEditor extends Component {
 	public function clearError() {
 	public function clearError() {
 		if( currrentDecos.length != 0 )
 		if( currrentDecos.length != 0 )
 			currrentDecos = editor.deltaDecorations(currrentDecos,[]);
 			currrentDecos = editor.deltaDecorations(currrentDecos,[]);
-		errorMessage.hide();
+		errorMessage.toggle(false);
 	}
 	}
 
 
 	public function setError( msg : String, line : Int, pmin : Int, pmax : Int ) {
 	public function setError( msg : String, line : Int, pmin : Int, pmax : Int ) {
@@ -74,12 +74,11 @@ class CodeEditor extends Component {
 			{ range : range, options : { inlineClassName: "codeErrorContentLine", isWholeLine : true } },
 			{ range : range, options : { inlineClassName: "codeErrorContentLine", isWholeLine : true } },
 			{ range : range, options : { linesDecorationsClassName: "codeErrorLine", inlineClassName: "codeErrorContent" } }
 			{ range : range, options : { linesDecorationsClassName: "codeErrorLine", inlineClassName: "codeErrorContent" } }
 		]);
 		]);
-		errorMessage.text(msg);
-		errorMessage.show(function() {
-			var rect = errorMessage[0].getBoundingClientRect();
-			if( rect.bottom > js.Browser.window.innerHeight )
-				errorMessage[0].scrollIntoView(false);
-		});
+		errorMessage.html([for( l in msg.split("\n") ) StringTools.htmlEscape(l)].join("<br/>"));
+		errorMessage.toggle(true);
+		var rect = errorMessage[0].getBoundingClientRect();
+		if( rect.bottom > js.Browser.window.innerHeight )
+			errorMessage[0].scrollIntoView(false);
 	}
 	}
 
 
 }
 }

+ 3 - 1
hide/comp/Scene.hx

@@ -71,6 +71,7 @@ class Scene extends Component implements h3d.IDrawable {
 	public var speed : Float = 1.0;
 	public var speed : Float = 1.0;
 	public var visible(default, null) : Bool = true;
 	public var visible(default, null) : Bool = true;
 	public var editor : hide.comp.SceneEditor;
 	public var editor : hide.comp.SceneEditor;
+	public var refreshIfUnfocused = false;
 
 
 	public function new(config, parent, el) {
 	public function new(config, parent, el) {
 		super(parent,el);
 		super(parent,el);
@@ -168,8 +169,9 @@ class Scene extends Component implements h3d.IDrawable {
 			ide.unregisterUpdate(sync);
 			ide.unregisterUpdate(sync);
 			return;
 			return;
 		}
 		}
-		if( !visible || !Ide.inst.isFocused)
+		if( !visible || (!Ide.inst.isFocused && !refreshIfUnfocused) )
 			return;
 			return;
+		refreshIfUnfocused = false;
 		setCurrent();
 		setCurrent();
 		sevents.checkEvents();
 		sevents.checkEvents();
 		var dt = hxd.Timer.tmod * speed / 60;
 		var dt = hxd.Timer.tmod * speed / 60;

+ 121 - 0
hide/view/UIKit.hx

@@ -0,0 +1,121 @@
+package hide.view;
+
+typedef UIKitDefinition = {
+	var type : String;
+	var html : String;
+	var json : {};
+}
+
+class UIKit extends FileView {
+
+	var scene : hide.comp.Scene;
+	var uiElt : UIKitDefinition;
+	var editor : hide.comp.CodeEditor;
+	var lastSaveHtml : String;
+	var doc : h2d.uikit.Document;
+	var cssFiles : Array<String>;
+	var sheets : h2d.uikit.CssStyle;
+	var root : h2d.Flow;
+
+	override function getDefaultContent() {
+		var p : UIKitDefinition = {
+			type : "ui",
+			html : "",
+			json : {},
+		};
+		return haxe.io.Bytes.ofString(ide.toJSON(p));
+	}
+
+	override function onDisplay() {
+		super.onDisplay();
+		uiElt = ide.parseJSON(sys.io.File.getContent(ide.getPath(state.path)));
+		lastSaveHtml = uiElt.html;
+
+		this.element.html('
+			<div class="uikit">
+				<div class="leftpanel">
+					<div class="html"></div>
+					<div class="cssErrors"></div>
+				</div>
+				<div class="scene">
+				</div>
+			</div>
+		');
+		scene = new hide.comp.Scene(config,null,element.find(".scene"));
+		scene.onResize = onSceneResize;
+		scene.onReady = sync;
+		editor = new hide.comp.CodeEditor(uiElt.html, "xml", element.find(".html"));
+		editor.onChanged = function() {
+			var cur = editor.code;
+			modified = cur != lastSaveHtml;
+			uiElt.html = cur;
+			sync();
+		};
+		editor.onSave = save;
+
+		cssFiles = this.config.get("uikit.css");
+		for( f in cssFiles )
+			watch(f, function() {
+				loadSheets();
+				if( doc != null ) doc.setStyle(sheets);
+				scene.refreshIfUnfocused = true;
+			});
+	}
+
+	function loadSheets() {
+		sheets = new h2d.uikit.CssStyle();
+		var warnings = [];
+		for( f in cssFiles ) {
+			var content = sys.io.File.getContent(ide.getPath(f));
+			var parser = new h2d.uikit.CssParser();
+			var css = parser.parseSheet(content);
+			sheets.add(css);
+			for( w in parser.warnings )
+				warnings.push({ file : f, line : content.substr(0,w.end).split("\n").length+1, msg : w.msg });
+		}
+		var warns = element.find(".cssErrors");
+		warns.html([for( w in warnings ) w.file+":"+w.line+": "+StringTools.htmlEscape(w.msg)].join("<br>"));
+		warns.toggle(warnings.length > 0);
+	}
+
+	function sync() {
+		if( sheets == null )
+			loadSheets();
+		editor.clearError();
+		var xml = try haxe.xml.Parser.parse(uiElt.html) catch( e : haxe.xml.Parser.XmlParserException ) {
+			editor.setError(e.message, e.lineNumber, e.position, e.position+1);
+			return;
+		};
+		if( doc != null ) {
+			doc.remove();
+			doc = null;
+		}
+
+		var b = new h2d.uikit.Builder();
+		doc = b.build(xml);
+		if( b.errors.length > 0 )
+			editor.setError(b.errors.join("\n"), 1, 0, uiElt.html.length);
+
+		if( root == null ) {
+			root = new h2d.Flow(scene.s2d);
+			onSceneResize();
+			root.horizontalAlign = Middle;
+			root.verticalAlign = Middle;
+		}
+		doc.addTo(root);
+		doc.setStyle(sheets);
+	}
+
+	function onSceneResize() {
+		if( root == null ) return;
+		root.minWidth = root.maxWidth = scene.s2d.width;
+		root.minHeight = root.maxHeight = scene.s2d.height;
+	}
+
+	override function save() {
+		sys.io.File.saveContent(ide.getPath(state.path), ide.toJSON(uiElt));
+		super.save();
+	}
+
+	static var _ = FileTree.registerExtension(UIKit, ["ui"], { icon : "id-card-o", createNew : "UI Component" });
+}