123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- package h2d.domkit;
- class Style extends domkit.CssStyle {
- var currentObjects : Array<h2d.Object> = [];
- var resources : Array<hxd.res.Resource> = [];
- var errors : Array<String>;
- var errorsText : h2d.Text;
- public var allowInspect(default, set) = false;
- public var inspectKeyCode : Int = 0;
- public var inspectDetailsKeyCode : Int = hxd.Key.CTRL;
- public var s3d : h3d.scene.Scene;
- public function new() {
- super();
- }
- public function load( r : hxd.res.Resource, watchChanges = true ) {
- if( watchChanges ) r.watch(function() {
- #if (sys || nodejs)
- var fs = hxd.impl.Api.downcast(hxd.res.Loader.currentInstance.fs, hxd.fs.LocalFileSystem);
- if( fs != null ) fs.clearCache();
- #end
- onChange();
- });
- resources.push(r);
- add(new domkit.CssParser().parseSheet(r.entry.getText()));
- for( o in currentObjects )
- o.dom.applyStyle(this);
- }
- override function clear() {
- super.clear();
- resources.resize(0);
- }
- public function addObject( obj ) {
- currentObjects.remove(obj);
- currentObjects.push(obj);
- obj.dom.applyStyle(this);
- }
- public function removeObject(obj) {
- currentObjects.remove(obj);
- }
- /**
- Returns number of dom elements that were updated
- **/
- public function sync( ?dt : Float ) {
- if( dt == null )
- dt = hxd.Timer.elapsedTime;
- var T0 = domkit.CssStyle.TAG;
- for( o in currentObjects )
- o.dom.applyStyle(this, true);
- updateTime(dt);
- return domkit.CssStyle.TAG - T0;
- }
- override function onInvalidProperty(e:domkit.Properties<Dynamic>, s:domkit.CssStyle.RuleStyle, msg:String) {
- if( errors != null ) {
- var path = s.p.name;
- var ee = e;
- while(ee != null) {
- path = (ee.id.isDefined() ? "#" + ee.id.toString() : ee.component.name) + "." + path;
- ee = ee.parent;
- }
- if( msg == null ) msg = "Invalid property value '"+(domkit.CssParser.valueStr(s.value))+"'";
- errors.push(msg+" for " + path);
- }
- }
- function onChange( ntry : Int = 0 ) {
- if( ntry >= 10 ) return;
- ntry++;
- var oldRules = data.rules;
- errors = [];
- data.rules = [];
- for( r in resources ) {
- var txt = try r.entry.getText() catch( e : Dynamic ) { haxe.Timer.delay(onChange.bind(ntry),100); data.rules = oldRules; return; }
- var parser = new domkit.CssParser();
- try {
- data.add(parser.parseSheet(txt));
- } catch( e : domkit.Error ) {
- parser.warnings.push({ msg : e.message, pmin : e.pmin, pmax : e.pmax });
- }
- for( w in parser.warnings ) {
- var line = txt.substr(0,w.pmin).split("\n").length;
- errors.push(r.entry.path+":"+line+": " + w.msg);
- }
- }
- for( o in currentObjects )
- o.dom.applyStyle(this);
- if( errors.length == 0 ) {
- if( errorsText != null ) {
- errorsText.parent.remove();
- errorsText = null;
- }
- } else {
- if( errorsText == null ) {
- if( currentObjects.length == 0 ) return;
- var scene = currentObjects[0].getScene();
- if( scene == null ) {
- for( o in currentObjects ) {
- scene = o.getScene();
- if( scene != null ) break;
- }
- if( scene == null ) return;
- }
- var fl = new h2d.Flow();
- scene.add(fl,100);
- fl.backgroundTile = h2d.Tile.fromColor(0x400000,0.9);
- fl.padding = 10;
- errorsText = new h2d.Text(hxd.res.DefaultFont.get(), fl);
- }
- var fl = hxd.impl.Api.downcast(errorsText.parent, h2d.Flow);
- var sc = fl.getScene();
- fl.maxWidth = sc.width;
- errorsText.text = errors.join("\n");
- var b = fl.getBounds();
- fl.y = sc.height - Std.int(b.height);
- }
- }
- // ------ inspector -----
- var inspectModeActive = false;
- var inspectModeDetails = false;
- var inspectModeDetailsRight = -1;
- var inspectPreview : h2d.Object;
- var inspectPreviewObjects : Array<h2d.Object>;
- function set_allowInspect(b) {
- if( allowInspect == b )
- return b;
- @:privateAccess domkit.Properties.KEEP_VALUES = b;
- if( b ) {
- hxd.Window.getInstance().addEventTarget(onWindowEvent);
- onChange();
- } else {
- hxd.Window.getInstance().removeEventTarget(onWindowEvent);
- var scenes = [];
- for( o in currentObjects ) {
- var s = o.getScene();
- if( s == null || scenes.indexOf(s) >= 0 ) continue;
- scenes.push(s);
- function scanRec(o:h2d.Object) {
- if( o.dom != null ) @:privateAccess o.dom.currentValues = null;
- for( o in o ) scanRec(o);
- }
- scanRec(s);
- }
- if( inspectModeActive ) {
- inspectModeActive = false;
- hxd.System.setNativeCursor(Default);
- }
- }
- return allowInspect = b;
- }
- function onWindowEvent( e : hxd.Event ) {
- switch( e.kind ) {
- case EPush if( inspectKeyCode == 0 || hxd.Key.isDown(inspectKeyCode) ):
- if( e.button == hxd.Key.MOUSE_MIDDLE ) {
- if(hxd.Key.isDown(inspectDetailsKeyCode)) {
- inspectModeActive = true;
- inspectModeDetails = true;
- inspectModeDetailsRight = -1;
- }
- else {
- inspectModeActive = !inspectModeActive;
- inspectModeDetails = false;
- inspectModeDetailsRight = -1;
- }
- if( inspectModeActive && s3d != null && @:privateAccess s3d.renderer.debugging )
- inspectModeActive = false;
- if( inspectModeActive )
- updatePreview(e);
- else {
- clearPreview();
- hxd.System.setNativeCursor(Default);
- }
- }
- case EMove:
- if( inspectModeActive && !inspectModeDetails) updatePreview(e);
- case EWheel if( inspectKeyCode == 0 || hxd.Key.isDown(inspectKeyCode) ):
- if( inspectPreviewObjects != null ) {
- if( e.wheelDelta > 0 ) {
- var p = inspectPreviewObjects[0].parent;
- while( p != null && p.dom == null ) p = p.parent;
- if( p != null ) {
- var prev = inspectPreviewObjects;
- clearPreview();
- setPreview(p);
- inspectPreviewObjects = prev;
- inspectPreviewObjects.unshift(p);
- }
- } else if( inspectPreviewObjects.length > 1 ) {
- var prev = inspectPreviewObjects;
- clearPreview();
- prev.shift();
- setPreview(prev[0]);
- inspectPreviewObjects = prev;
- }
- }
- default:
- }
- if( inspectModeActive ) hxd.System.setNativeCursor(Move);
- }
- function clearPreview() {
- if( inspectPreview == null ) return;
- var obj = inspectPreviewObjects[0];
- var flow = Std.downcast(obj, h2d.Flow);
- if( flow != null ) flow.debug = false;
- inspectPreview.remove();
- inspectPreview = null;
- inspectPreviewObjects = null;
- }
- function updatePreview( e : hxd.Event ) {
- clearPreview();
- var checkedScenes = [];
- var ox = e.relX, oy = e.relY;
- for( o in currentObjects ) {
- var scene = o.getScene();
- if( scene == null || checkedScenes.indexOf(scene) >= 0 ) continue;
- checkedScenes.push(scene);
- e.relX = scene.mouseX;
- e.relY = scene.mouseY;
- if( lookupRec(scene, e) )
- break;
- }
- e.relX = ox;
- e.relY = oy;
- }
- function lookupRec( obj : h2d.Object, e : hxd.Event ) {
- if( !obj.visible || obj.alpha <= 0 )
- return false;
- var ch = @:privateAccess obj.children;
- for( i in 0...ch.length ) {
- if( lookupRec(ch[ch.length-1-i], e) )
- return true;
- }
- if( obj.dom == null )
- return false;
- var b = obj.getBounds();
- if( !b.contains(new h2d.col.Point(e.relX,e.relY)) )
- return false;
- if( Type.getClass(obj) == h2d.Object ) // objects containing transparent flow?
- return false;
- var fl = Std.downcast(obj, h2d.Flow);
- if( fl != null && fl.backgroundTile == null && fl.interactive == null )
- return false;
- setPreview(obj);
- return true;
- }
- @:access(domkit.Properties)
- static function getDisplayInfo(obj: h2d.Object) : String {
- var dom = obj.dom;
- var nameParts = [];
- if(dom != null) {
- nameParts.push(dom.component.name);
- if( dom.classes != null ) {
- for( c in dom.classes )
- nameParts.push("."+c);
- }
- if( dom.id.isDefined() )
- nameParts.push("#"+dom.id);
- }
- else
- nameParts.push('<font color="#aaaaaa">' + Type.getClassName(Type.getClass(obj)).split(".").pop() + '</font>');
- var sz = obj.getSize();
- nameParts.push(' <font color="#808080">${Math.ceil(sz.width)}x${Math.ceil(sz.height)}</font>');
- return nameParts.join("");
- }
- @:access(domkit.Properties)
- function setPreview( obj : h2d.Object, ?details=false) {
- var b = obj.getBounds();
- if( b.xMin < 0 ) b.xMin = 0;
- if( b.yMin < 0 ) b.yMin = 0;
- var scene = obj.getScene();
- if( scene == null ) return;
- inspectPreview = new h2d.Object();
- scene.add(inspectPreview, @:privateAccess scene.layerCount - 1);
- inspectPreviewObjects = [obj];
- if(inspectModeDetails) {
- var treeRoot = new h2d.Flow(inspectPreview);
- treeRoot.layout = Vertical;
- treeRoot.backgroundTile = h2d.Tile.fromColor(0x101010,1.0);
- treeRoot.padding = 6;
- var parents : Array<h2d.Object> = [];
- {
- var o = obj;
- for(i in 0...20) {
- o = o.parent;
- if(o == null) break;
- parents.push(o);
- }
- }
- function addBtn(o : h2d.Object, indent: Int, open: Bool) {
- var btn = new Flow(treeRoot);
- var txt = new HtmlText(hxd.res.DefaultFont.get(), btn);
- var text = getDisplayInfo(o);
- if(o.numChildren > 0 && !open)
- text = '<font color="#808080">[+] </font>' + text;
- txt.text = text;
- btn.paddingLeft = 10 * indent;
- btn.paddingTop = btn.paddingBottom = 2;
- btn.paddingRight = 10;
- btn.enableInteractive = true;
- if(o == obj)
- btn.backgroundTile = Tile.fromColor(0x50aaff, 1, 1, 0.5);
- else {
- btn.interactive.onOver = function(_) btn.backgroundTile = Tile.fromColor(0x202020, 1, 1, 1.0);
- btn.interactive.onOut = function(_) btn.backgroundTile = null;
- }
- btn.interactive.onPush = function(e) {
- clearPreview();
- setPreview(o, true);
- }
- }
- for(i in 0...parents.length)
- addBtn(parents[parents.length-1 - i], i, true);
- var thisIndent = parents.length;
- var childCount = 0;
- final maxDepth = 3;
- function addChildRec(o : h2d.Object, depth : Int) {
- if(childCount > 50) return;
- addBtn(o, thisIndent + depth, depth < maxDepth);
- ++childCount;
- if(depth < maxDepth) {
- for(i in 0...o.numChildren)
- addChildRec(o.getChildAt(i), depth+1);
- }
- }
- addChildRec(obj, 0);
- if(inspectModeDetailsRight < 0)
- inspectModeDetailsRight = (scene.mouseX > scene.width / 2) ? 0 : 1;
- if(inspectModeDetailsRight > 0)
- treeRoot.x = scene.width - treeRoot.getBounds().width;
- }
- var p = new h2d.Bitmap(h2d.Tile.fromColor(0xFF0000, Math.round(b.width), Math.round(b.height), 0.1), inspectPreview);
- p.x = Math.round(b.xMin);
- p.y = Math.round(b.yMin);
- var flow = Std.downcast(obj, h2d.Flow);
- if( flow != null )
- flow.debug = true;
- else {
- var w = p.tile.iwidth;
- var h = p.tile.iheight;
- var horiz = h2d.Tile.fromColor(0xFF0000, w, 1);
- var vert = h2d.Tile.fromColor(0xFF0000, 1, h);
- new h2d.Bitmap(horiz, p);
- new h2d.Bitmap(vert, p);
- new h2d.Bitmap(horiz, p).y = h - 1;
- new h2d.Bitmap(vert, p).x = w - 1;
- }
- var prevFlow = new h2d.Flow(p);
- prevFlow.backgroundTile = h2d.Tile.fromColor(0,0.8);
- prevFlow.padding = 7;
- prevFlow.paddingTop = 4;
- var previewText = new h2d.HtmlText(hxd.res.DefaultFont.get(), prevFlow);
- var lines = [];
- lines.push(getDisplayInfo(obj));
- lines.push("");
- var dom = obj.dom;
- if(dom != null) {
- for( s in dom.style ) {
- if( s.p.name == "text" || hxd.impl.Api.isOfType(s.value,h2d.Tile) ) continue;
- lines.push(' <font color="#D0D0D0"> ${s.p.name}</font> <font color="#808080">${s.value}</font><font color="#606060"> (style)</font>');
- }
- for( i in 0...dom.currentSet.length ) {
- var p = dom.currentSet[i];
- if( p.name == "text" ) continue;
- var v = dom.currentValues == null ? null : dom.currentValues[i];
- var vstr = v == null ? "???" : StringTools.htmlEscape(domkit.CssParser.valueStr(v));
- lines.push(' <font color="#D0D0D0"> ${p.name}</font> <font color="#808080">$vstr</font>');
- }
- previewText.text = lines.join("<br/>");
- }
- var size = prevFlow.getBounds();
- if( b.xMax + size.width < scene.width )
- prevFlow.x = Std.int(b.width+2);
- else if( b.xMin - size.width > 0 )
- prevFlow.x = -Std.int(size.width+2);
- if( b.yMin + size.height + 10 > scene.height )
- prevFlow.y = Std.int(scene.height - (b.yMin + size.height + 10));
- }
- }
|