浏览代码

undo/redo fixes, restore cursor and opened tables correctly.

Nicolas Cannasse 6 年之前
父节点
当前提交
5b1649a985
共有 10 个文件被更改,包括 168 次插入76 次删除
  1. 20 17
      bin/cdb.css
  2. 25 18
      bin/cdb.less
  3. 2 2
      hide/comp/Component.hx
  4. 2 2
      hide/comp/cdb/AllEditors.hx
  5. 18 6
      hide/comp/cdb/Cell.hx
  6. 10 1
      hide/comp/cdb/Cursor.hx
  7. 78 25
      hide/comp/cdb/Editor.hx
  8. 5 2
      hide/comp/cdb/SubTable.hx
  9. 7 3
      hide/comp/cdb/Table.hx
  10. 1 0
      hide/view/CdbTable.hx

+ 20 - 17
bin/cdb.css

@@ -1,6 +1,26 @@
 .cdb {
   background-color: black;
 }
+.cdb:focus {
+  outline: none;
+}
+.cdb:focus .cdb-sheet td.cursorView {
+  outline: 1px solid #ccc;
+}
+.cdb:focus .cdb-sheet tr.cursorLine {
+  background-color: #262d35;
+}
+.cdb:focus .cdb-sheet tr.cursorLine td.start {
+  background-color: #313a48;
+}
+.cdb:focus .cdb-sheet tr.selected,
+.cdb:focus .cdb-sheet td.selected {
+  background-color: #313a48;
+}
+.cdb:focus .cdb-sheet tr.selected td.start,
+.cdb:focus .cdb-sheet td.selected td.start {
+  background-color: #313a48;
+}
 .cdb .cdb-sheet {
   width: 100%;
   table-layout: fixed;
@@ -62,23 +82,6 @@
 .cdb .cdb-sheet td.edit_long {
   padding-bottom: 0px;
 }
-.cdb .cdb-sheet td.cursorView {
-  outline: 1px solid #ccc;
-}
-.cdb .cdb-sheet tr.cursorLine {
-  background-color: #262d35;
-}
-.cdb .cdb-sheet tr.cursorLine td.start {
-  background-color: #313a48;
-}
-.cdb .cdb-sheet tr.selected,
-.cdb .cdb-sheet td.selected {
-  background-color: #313a48;
-}
-.cdb .cdb-sheet tr.selected td.start,
-.cdb .cdb-sheet td.selected td.start {
-  background-color: #313a48;
-}
 .cdb .cdb-sheet tr.filtered {
   display: none;
 }

+ 25 - 18
bin/cdb.less

@@ -3,6 +3,31 @@
 
 	background-color : black;
 
+	&:focus {
+		outline: none;
+	}
+
+	&:focus .cdb-sheet {
+
+		td.cursorView {
+			outline : 1px solid #ccc;
+		}
+
+		tr.cursorLine {
+			background-color: #262d35;
+			td.start {
+				background-color: #313a48;
+			}
+		}
+
+		tr.selected, td.selected {
+			background-color : #313a48;
+			td.start {
+				background-color: #313a48;
+			}
+		}
+	}
+
 	.cdb-sheet {
 
 		width : 100%;
@@ -68,24 +93,6 @@
 			padding-bottom : 0px;
 		}
 
-		td.cursorView {
-			outline : 1px solid #ccc;
-		}
-
-		tr.cursorLine {
-			background-color: #262d35;
-			td.start {
-				background-color: #313a48;
-			}
-		}
-
-		tr.selected, td.selected {
-			background-color : #313a48;
-			td.start {
-				background-color: #313a48;
-			}
-		}
-
 		tr.filtered {
 			display : none;
 		}

+ 2 - 2
hide/comp/Component.hx

@@ -3,7 +3,7 @@ package hide.comp;
 class Component {
 
 	var ide : hide.Ide;
-	public var name(get, never) : String;
+	public var componentName(get, never) : String;
 	public var element(default,null) : Element;
 	public var saveDisplayKey : String;
 
@@ -20,7 +20,7 @@ class Component {
 		element.remove();
 	}
 
-	@:final function get_name() return Type.getClassName(Type.getClass(this));
+	@:final function get_componentName() return Type.getClassName(Type.getClass(this));
 
 	function getDisplayState( key : String ) : Dynamic {
 		if( saveDisplayKey == null )

+ 2 - 2
hide/comp/cdb/AllEditors.hx

@@ -13,10 +13,10 @@ class AllEditors extends Editor {
 		return [for( i in ide.getViews(hide.view.CdbTable) ) @:privateAccess i.editor];
 	}
 
-	override function refresh() {
+	override function refresh( ?state : Editor.UndoState ) {
 		for( e in getEditors() ) {
 			e.syncSheet();
-			e.refresh();
+			e.refresh(state);
 		}
 	}
 

+ 18 - 6
hide/comp/cdb/Cell.hx

@@ -31,7 +31,7 @@ class Cell extends Component {
 
 	public function refresh() {
 		currentValue = Reflect.field(line.obj, column.name);
-		var html = valueHtml(column, value, editor.sheet, line.obj);
+		var html = valueHtml(column, value, line.table.sheet, line.obj);
 		if( html == "&nbsp;" ) element.text(" ") else if( html.indexOf('<') < 0 && html.indexOf('&') < 0 ) element.text(html) else element.html(html);
 		updateClasses();
 	}
@@ -241,15 +241,14 @@ class Cell extends Component {
 	}
 
 	public function focus() {
-		editor.element.focus();
+		editor.focus();
 		editor.cursor.set(table, this.columnIndex, this.line.index);
 	}
 
 	public function edit() {
 		switch( column.type ) {
 		case TString if( column.kind == Script ):
-			var str = value == null ? "" : editor.base.valToString(column.type, value);
-			@:privateAccess table.toggleList(this, function() return new ScriptTable(editor, this));
+			open();
 		case TInt, TFloat, TString, TId, TCustom(_), TDynamic:
 			var str = value == null ? "" : editor.base.valToString(column.type, value);
 			var textSpan = element.wrapInner("<span>").find("span");
@@ -313,7 +312,7 @@ class Cell extends Component {
 			setValue( currentValue == false && column.opt && table.displayMode != Properties ? null : currentValue == null ? true : currentValue ? false : true );
 			refresh();
 		case TProperties, TList:
-			@:privateAccess table.toggleList(this);
+			open();
 		case TRef(name):
 			var sdat = editor.base.getSheet(name);
 			if( sdat == null ) return;
@@ -482,6 +481,15 @@ class Cell extends Component {
 		}
 	}
 
+	public function open( ?immediate : Bool ) {
+		if( column.type == TString && column.kind == Script ) {
+			if( immediate ) return;
+			var str = value == null ? "" : editor.base.valToString(column.type, value);
+			@:privateAccess table.toggleList(this, function() return new ScriptTable(editor, this));
+		} else
+			@:privateAccess table.toggleList(this, immediate);
+	}
+
 	public function setErrorMessage( msg : String ) {
 		element.find("div.error").remove();
 		if( msg == null )  return;
@@ -510,9 +518,13 @@ class Cell extends Component {
 			}
 			setValue(newValue);
 			editor.endChanges();
+			editor.refreshAll();
+			focus();
+			/*
 			// creates or remove a #DUP : need to refresh the whole table
 			if( prevTarget != null || (prevObj != null && (prevObj.obj != obj || table.sheet.index.get(prevValue) != null)) )
 				table.refresh();
+			*/
 		case TString if( column.kind == Script ):
 			setValue(StringTools.trim(newValue));
 		default:
@@ -529,7 +541,7 @@ class Cell extends Component {
 		var str = element.find("input,textarea").val();
 		if( str != null ) setRawValue(str);
 		refresh();
-		table.editor.element.focus();
+		focus();
 	}
 
 }

+ 10 - 1
hide/comp/cdb/Cursor.hx

@@ -14,7 +14,14 @@ class Cursor {
 		set();
 	}
 
-	public function set( ?t, ?x=0, ?y=0, ?sel, update = true ) {
+	public function set( ?t:Table, ?x=0, ?y=0, ?sel, update = true ) {
+		if( t != null ) {
+			for( t2 in editor.tables )
+				if( t.sheet.name == t2.sheet.name ) {
+					t = t2;
+					break;
+				}
+		}
 		this.table = t;
 		this.x = x;
 		this.y = y;
@@ -104,6 +111,8 @@ class Cursor {
 			select = null;
 		}
 		var line = getLine();
+		if( line == null )
+			return;
 		if( x < 0 ) {
 			line.element.addClass("selected");
 			if( select != null ) {

+ 78 - 25
hide/comp/cdb/Editor.hx

@@ -3,12 +3,15 @@ import hxd.Key in K;
 
 typedef UndoState = {
 	var data : Any;
+	var cursor : { sheet : String, x : Int, y : Int, select : Null<{ x : Int, y : Int }> };
+	var tables : Array<{ sheet : String, parent : { sheet : String, line : Int, column : Int } }>;
 }
 
 typedef EditorApi = {
 	function load( data : Any ) : Void;
 	function copy() : Any;
 	function save() : Void;
+	var ?currentValue : Any;
 	var ?undo : hide.ui.UndoHistory;
 	var ?undoState : Array<UndoState>;
 	var ?editor : Editor;
@@ -29,7 +32,6 @@ class Editor extends Component {
 		schema : Array<cdb.Data.Column>,
 	};
 	var changesDepth : Int = 0;
-	var currentValue : Any;
 	var api : EditorApi;
 	public var config : hide.Config;
 	public var cursor : Cursor;
@@ -43,6 +45,7 @@ class Editor extends Component {
 		this.sheet = sheet;
 		if( api.undoState == null ) api.undoState = [];
 		if( api.editor == null ) api.editor = this;
+		if( api.currentValue == null ) api.currentValue = api.copy();
 		this.undo = api.undo == null ? new hide.ui.UndoHistory() : api.undo;
 		api.undo = undo;
 		init();
@@ -50,7 +53,7 @@ class Editor extends Component {
 
 	function init() {
 		element.attr("tabindex", 0);
-		element.on("blur", function(_) cursor.set());
+		element.on("focus", function(_) onFocus());
 		element.on("keypress", function(e) {
 			if( e.target.nodeName == "INPUT" )
 				return;
@@ -68,8 +71,8 @@ class Editor extends Component {
 		keys.register("paste", onPaste);
 		keys.register("delete", onDelete);
 		keys.register("cdb.showReferences", showReferences);
-		keys.register("undo", function() if( undo.undo() ) refresh());
-		keys.register("redo", function() if( undo.redo() ) refresh());
+		keys.register("undo", function() undo.undo());
+		keys.register("redo", function() undo.redo());
 		keys.register("cdb.insertLine", function() { insertLine(cursor.table,cursor.y); cursor.move(0,1,false,false); });
 		for( k in ["cdb.editCell","rename"] )
 			keys.register(k, function() {
@@ -78,12 +81,10 @@ class Editor extends Component {
 			});
 		keys.register("cdb.closeList", function() {
 			var c = cursor.getCell();
-			if( c != null ) {
-				var sub = Std.instance(c.table, SubTable);
-				if( sub != null ) {
-					sub.cell.element.click();
-					return;
-				}
+			var sub = Std.instance(c == null ? cursor.table : c.table, SubTable);
+			if( sub != null ) {
+				sub.cell.element.click();
+				return;
 			}
 			if( cursor.select != null ) {
 				cursor.select = null;
@@ -94,7 +95,6 @@ class Editor extends Component {
 		base = sheet.base;
 		cursor = new Cursor(this);
 		if( displayMode == null ) displayMode = Table;
-		currentValue = api.copy();
 		refresh();
 	}
 
@@ -258,27 +258,72 @@ class Editor extends Component {
 	**/
 	public function beginChanges() {
 		if( changesDepth == 0 ) {
-			api.undoState.push({
-				data : currentValue,
+			api.undoState.unshift({
+				data : api.currentValue,
+				cursor : cursor.table == null ? null : {
+					sheet : cursor.table.sheet.name,
+					x : cursor.x,
+					y : cursor.y,
+					select : cursor.select == null ? null : { x : cursor.select.x, y : cursor.select.y }
+				},
+				tables : [for( i in 1...tables.length ) {
+					var t = tables[i];
+					var tp = t.sheet.parent;
+					{ sheet : t.sheet.name, parent : { sheet : tp.sheet.name, line : tp.line, column : tp.column } }
+				}],
 			});
 		}
 		changesDepth++;
 	}
 
+	function setState( state : UndoState ) {
+		var cur = state.cursor;
+
+		trace({ cursor : cur, tables : state.tables });
+
+		for( t in state.tables ) {
+			var tparent = null;
+			for( tp in tables )
+				if( tp.sheet.name == t.parent.sheet ) {
+					tparent = tp;
+					break;
+				}
+			if( tparent != null )
+				tparent.lines[t.parent.line].cells[t.parent.column].open(true);
+		}
+
+		if( cur != null ) {
+			var table = null;
+			for( t in tables )
+				if( t.sheet.name == cur.sheet ) {
+					table = t;
+					break;
+				}
+			if( table != null )
+				focus();
+			cursor.set(table, cur.x, cur.y, cur.select == null ? null : { x : cur.select.x, y : cur.select.y } );
+		} else
+			cursor.set();
+	}
+
 	/**
 		Call when changes are done, after endChanges.
 	**/
 	public function endChanges() {
 		changesDepth--;
-		if( changesDepth == 0 )
-			undo.change(Custom(makeCustom(api)));
+		if( changesDepth == 0 ) {
+			var f = makeCustom(api);
+			if( f != null ) undo.change(Custom(f));
+		}
 	}
 
 	// do not reference "this" editor in undo state !
 	static function makeCustom( api : EditorApi ) {
-		var state = api.undoState[0];
 		var newValue = api.copy();
-		api.editor.currentValue = newValue;
+		if( newValue == api.currentValue )
+			return null;
+		var state = api.undoState[0];
+		api.currentValue = newValue;
 		api.save();
 		return function(undo) api.editor.handleUndo(state, newValue, undo);
 	}
@@ -286,13 +331,13 @@ class Editor extends Component {
 	function handleUndo( state : UndoState, newValue : Any, undo : Bool ) {
 		if( undo ) {
 			api.undoState.shift();
-			currentValue = state.data;
+			api.currentValue = state.data;
 		} else {
 			api.undoState.unshift(state);
-			currentValue = newValue;
+			api.currentValue = newValue;
 		}
-		api.load(currentValue);
-		refresh();
+		api.load(api.currentValue);
+		refreshAll(state);
 		api.save();
 	}
 
@@ -329,11 +374,11 @@ class Editor extends Component {
 			}
 	}
 
-	function refreshAll() {
-		api.editor.refresh();
+	function refreshAll( ?state : UndoState ) {
+		api.editor.refresh(state);
 	}
 
-	function refresh() {
+	function refresh( ?state : UndoState ) {
 
 		base.sync();
 
@@ -366,9 +411,12 @@ class Editor extends Component {
 		new Table(this, sheet, content, displayMode);
 		content.appendTo(element);
 
+		if( state != null )
+			setState(state);
+
 		if( cursor.table != null ) {
 			for( t in tables )
-				if( t.sheet == cursor.table.sheet )
+				if( t.sheet.name == cursor.table.sheet.name )
 					cursor.table = t;
 			cursor.update();
 		}
@@ -464,7 +512,12 @@ class Editor extends Component {
 	}
 
 	public function focus() {
+		if( element.is(":focus") ) return;
 		element.focus();
+		onFocus();
+	}
+
+	public dynamic function onFocus() {
 	}
 
 }

+ 5 - 2
hide/comp/cdb/SubTable.hx

@@ -79,8 +79,11 @@ class SubTable extends Table {
 		},key, { sheet : sheet, column : cell.columnIndex, line : index });
 	}
 
-	public function show() {
-		slider.slideDown(100);
+	public function show( ?immediate ) {
+		if( immediate )
+			slider.show();
+		else
+			slider.slideDown(100);
 	}
 
 	override public function close() {

+ 7 - 3
hide/comp/cdb/Table.hx

@@ -241,7 +241,7 @@ class Table extends Component {
 		return false;
 	}
 
-	function toggleList( cell : Cell, ?make : Void -> SubTable ) {
+	function toggleList( cell : Cell, ?immediate : Bool, ?make : Void -> SubTable ) {
 		var line = cell.line;
 		var cur = line.subTable;
 		if( cur != null ) {
@@ -249,8 +249,12 @@ class Table extends Component {
 			if( cur.cell == cell ) return; // toggle
 		}
 		var sub = make == null ? new SubTable(editor, cell) : make();
-		sub.show();
-		if( sub.lines.length > 0 ) editor.cursor.set(sub);
+		sub.show(immediate);
+		editor.cursor.set(sub);
+	}
+
+	function toString() {
+		return "Table#"+sheet.name;
 	}
 
 }

+ 1 - 0
hide/view/CdbTable.hx

@@ -25,6 +25,7 @@ class CdbTable extends hide.ui.View<{ path : String }> {
 		}
 		element.addClass("hide-scroll");
 		editor = new hide.comp.cdb.Editor(sheet,config,ide.databaseApi,element);
+		editor.onFocus = activate;
 		undo = editor.undo;
 		new Element("<div style='width:100%; height:300px'></div>").appendTo(element);
 	}