Browse Source

Add jump to last/next cursor position in cdb (#140)

use the side mouse buttons or Alt-Left and Alt-Right to jump the
cursor position
Leonardo Jeanteur 4 years ago
parent
commit
7d5ce90795
5 changed files with 169 additions and 26 deletions
  1. 2 0
      bin/defaultProps.json
  2. 5 4
      hide/comp/cdb/Cell.hx
  3. 30 2
      hide/comp/cdb/Cursor.hx
  4. 129 18
      hide/comp/cdb/Editor.hx
  5. 3 2
      hide/view/CdbTable.hx

+ 2 - 0
bin/defaultProps.json

@@ -62,6 +62,8 @@
 	"key.cdb.closeList" : "Escape",
 	"key.cdb.editCell" : "Enter",
 	"key.cdb.insertLine" : "Insert",
+	"key.cdb.moveBack" : "Alt-Left",
+	"key.cdb.moveAhead" : "Alt-Right",
 
 	// Scene editor config
 	"key.sceneeditor.focus": "F",

+ 5 - 4
hide/comp/cdb/Cell.hx

@@ -38,6 +38,11 @@ class Cell extends Component {
 		root.prop("cellComp", this);
 		if( column.kind == Script ) root.addClass("t_script");
 		refresh();
+
+		root.click(function(e) {
+			editor.cursor.clickCell(this, e.shiftKey);
+			e.stopPropagation();
+		});
 		switch( column.type ) {
 		case TList, TProperties:
 			element.click(function(e) {
@@ -54,10 +59,6 @@ class Cell extends Component {
 				root.addClass("t_readonly");
 		}
 
-		root.click(function(e) {
-			editor.cursor.clickCell(this, e.shiftKey);
-			e.stopPropagation();
-		});
 		root.contextmenu(function(e) {
 			showMenu();
 			e.stopPropagation();

+ 30 - 2
hide/comp/cdb/Cursor.hx

@@ -1,5 +1,13 @@
 package hide.comp.cdb;
 
+
+typedef CursorState = {
+	var sheet : String;
+	var x : Int;
+	var y : Int;
+	var select : Null<{ x : Int, y : Int }>;
+}
+
 class Cursor {
 
 	var editor : Editor;
@@ -14,6 +22,22 @@ class Cursor {
 		set();
 	}
 
+	public function setState(state : CursorState, ?table : Table) {
+		if( state == null )
+			set(table);
+		else
+			set(table, state.x, state.y, state.select);
+	}
+
+	public function getState() : CursorState {
+		return table == null ? null : {
+			sheet : table.sheet.getPath(),
+			x : x,
+			y : y,
+			select : Reflect.copy(select)
+		};
+	}
+
 	public function set( ?t:Table, ?x=0, ?y=0, ?sel, update = true ) {
 		if( t != null ) {
 			for( t2 in editor.tables )
@@ -210,8 +234,10 @@ class Cursor {
 		if( shiftKey && this.table == line.table && x < 0 ) {
 			select = { x : -1, y : line.index };
 			update();
-		} else
+		} else {
+			editor.pushCursorState();
 			set(line.table, -1, line.index);
+		}
 	}
 
 	public function clickCell( cell : Cell, shiftKey = false ) {
@@ -219,8 +245,10 @@ class Cursor {
 		if( shiftKey && table == cell.table ) {
 			select = { x : xIndex, y : cell.line.index };
 			update();
-		} else
+		} else {
+			editor.pushCursorState();
 			set(cell.table, xIndex, cell.line.index);
+		}
 	}
 
 }

+ 129 - 18
hide/comp/cdb/Editor.hx

@@ -14,7 +14,7 @@ typedef UndoSheet = {
 typedef UndoState = {
 	var data : Any;
 	var sheet : String;
-	var cursor : { sheet : String, x : Int, y : Int, select : Null<{ x : Int, y : Int }> };
+	var cursor : Cursor.CursorState;
 	var tables : Array<UndoSheet>;
 }
 
@@ -53,17 +53,21 @@ class Editor extends Component {
 	var api : EditorApi;
 	var undoState : Array<UndoState> = [];
 	var currentValue : Any;
+	var cdbTable : hide.view.CdbTable;
 	public var view : cdb.DiffFile.ConfigView;
 	public var config : hide.Config;
 	public var cursor : Cursor;
 	public var keys : hide.ui.Keys;
 	public var undo : hide.ui.UndoHistory;
+	public var cursorStates : Array<UndoState> = [];
+	public var cursorIndex : Int = 0;
 	public var formulas : Formulas;
 
-	public function new(config,api) {
+	public function new(config, api, ?cdbTable) {
 		super(null,null);
 		this.api = api;
 		this.config = config;
+		this.cdbTable = cdbTable;
 		view = cast this.config.get("cdb.view");
 		undo = new hide.ui.UndoHistory();
 	}
@@ -90,6 +94,9 @@ class Editor extends Component {
 				cell.edit();
 		});
 		element.contextmenu(function(e) e.preventDefault());
+
+		cdbTable.element.mousedown(onMouseDown);
+
 		keys = new hide.ui.Keys(element);
 		keys.addListener(onKey);
 		keys.register("search", function() {
@@ -102,6 +109,8 @@ class Editor extends Component {
 		keys.register("cdb.showReferences", showReferences);
 		keys.register("undo", function() undo.undo());
 		keys.register("redo", function() undo.redo());
+		keys.register("cdb.moveBack", () -> cursorJump(true));
+		keys.register("cdb.moveAhead", () -> cursorJump(false));
 		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() {
@@ -122,14 +131,31 @@ class Editor extends Component {
 		});
 		keys.register("cdb.gotoReference", () -> gotoReference(cursor.getCell()));
 		base = sheet.base;
-		cursor = new Cursor(this);
+		if( cursor == null )
+			cursor = new Cursor(this);
+		else if ( !tables.contains(cursor.table) )
+			cursor.set();
 		if( displayMode == null ) displayMode = Table;
 		DataFiles.load();
 		if( currentValue == null ) currentValue = api.copy();
 		refresh();
 	}
 
+	function onMouseDown( e : js.jquery.Event ) {
+		switch ( e.which ) {
+		case 4:
+			cursorJump(true);
+			return false;
+		case 5:
+			cursorJump(false);
+			return false;
+		}
+		return true;
+	}
+
 	function onKey( e : js.jquery.Event ) {
+		if( e.altKey )
+			return false;
 		switch( e.keyCode ) {
 		case K.LEFT:
 			cursor.move( -1, 0, e.shiftKey, e.ctrlKey);
@@ -419,14 +445,8 @@ class Editor extends Component {
 		return {
 			data : currentValue,
 			sheet : getCurrentSheet(),
-			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 }
-			},
+			cursor : cursor.getState(),
 			tables : [for( i in 1...tables.length ) {
-				var t = tables[i];
 				function makeParent(t:Table) : UndoSheet {
 					var tp = t.parent;
 					return { sheet : t.sheet.name, parent : tp == null ? null : {
@@ -448,7 +468,7 @@ class Editor extends Component {
 					var t = openRec(s.parent.sheet);
 					if( t != null ) {
 						var cell = t.lines[s.parent.line].cells[t.displayMode == Properties || t.displayMode == AllProperties ? 0 : s.parent.column];
-						if( cell.line.subTable == null )
+						if( cell.line.subTable == null && (cell.column.type == TList || cell.column.type == TProperties) )
 							cell.open(true);
 						return cell.line.subTable;
 					}
@@ -464,14 +484,15 @@ class Editor extends Component {
 
 		if( cur != null ) {
 			var table = null;
-			for( t in tables )
-				if( t.sheet.name == cur.sheet ) {
+			for( t in tables ) {
+				if( t.sheet.getPath() == cur.sheet ) {
 					table = t;
 					break;
 				}
+			}
 			if( table != null && doFocus )
 				focus();
-			cursor.set(table, cur.x, cur.y, cur.select == null ? null : { x : cur.select.x, y : cur.select.y } );
+			cursor.setState(cur, table);
 		} else
 			cursor.set();
 	}
@@ -501,6 +522,7 @@ class Editor extends Component {
 				currentValue = newValue;
 				currentSheet = newSheet;
 			}
+			pushCursorState();
 			api.load(currentValue);
 			DataFiles.save(true); // save reloaded data
 			element.removeClass("is-cdb-editor");
@@ -516,6 +538,97 @@ class Editor extends Component {
 		api.save();
 	}
 
+
+	function undoStatesEqual( s1 : UndoState, s2 : UndoState, cmpCursors = true ) {
+		function cursorEqual(c1 : Cursor.CursorState, c2 : Cursor.CursorState) {
+			if( c1 == c2 )
+				return true;
+			if( c1 == null || c2 == null )
+				return false;
+			return c1.sheet == c2.sheet && c1.x == c2.x && c1.y == c2.y;
+		}
+		function undoSheetEqual(s1 : UndoSheet, s2 : UndoSheet) {
+			if( s1.parent == null && s2.parent == null )
+				return s1.sheet == s2.sheet;
+			if( s1.parent == null || s2.parent == null )
+				return false;
+			if ( s1.sheet != s2.sheet || s1.parent.column != s2.parent.column || s1.parent.line != s2.parent.line )
+				return false;
+			return undoSheetEqual(s1.parent.sheet, s2.parent.sheet);
+		}
+		if ( s1.sheet != s2.sheet )
+			return false;
+		if( s1.tables.length != s2.tables.length )
+			return false;
+		for( i in 0...s1.tables.length ) {
+			if( !undoSheetEqual(s1.tables[i], s2.tables[i]) )
+				return false;
+		}
+		if( !cmpCursors )
+			return true;
+		if( cursorEqual(s1.cursor, s2.cursor) )
+			return true;
+		if( s1.cursor == null || s2.cursor == null )
+			return false;
+		return s1.cursor.y == -1 && s2.cursor.y == -1;
+	}
+
+	public function pushCursorState() {
+		if ( cursor == null )
+			return;
+		var state = getState();
+		state.data = null;
+
+		var stateBehind = (cursorStates.length <= 0) ? null : cursorStates[cursorIndex];
+		if( stateBehind != null && undoStatesEqual(state, stateBehind) )
+			return;
+		var stateAhead = (cursorStates.length <= 0 || cursorIndex >= cursorStates.length - 1) ? null : cursorStates[cursorIndex + 1];
+		if ( stateAhead != null && undoStatesEqual(state, stateAhead) ) {
+			cursorIndex++;
+			return;
+		}
+
+		if( cursorIndex < cursorStates.length - 1 && cursorIndex >= 0 ) {
+			if( stateBehind != null && !undoStatesEqual(state, stateBehind, false) ) {
+				cursorStates.splice(cursorIndex + 1, cursorStates.length);
+			}
+		}
+
+		cursorStates.insert(cursorIndex + 1, state);
+		if( cursorIndex < cursorStates.length - 1 )
+			cursorIndex++;
+	}
+
+	function cursorJump(back = true) {
+		focus();
+
+		if( (back && cursorIndex <= 0) || (!back && cursorIndex >= cursorStates.length - 1) )
+			return;
+		pushCursorState();
+		if(back)
+			cursorIndex--;
+		else
+			cursorIndex++;
+
+		var state = cursorStates[cursorIndex];
+		syncSheet(null, state.sheet);
+
+		if( undoStatesEqual(state, getState(), false) ) {
+			setState(state, true);
+			if( cursor.table != null ) {
+				for( t in tables ) {
+					if( t.sheet.getPath() == cursor.table.sheet.getPath() )
+						cursor.table = t;
+				}
+				cursor.update();
+			}
+		} else
+			refresh(state);
+
+		if( cdbTable != null )
+			@:privateAccess cdbTable.syncTabs();
+	}
+
 	public static var inRefreshAll(default,null) : Bool;
 	public static function refreshAll( eraseUndo = false ) {
 		var editors : Array<Editor> = [for( e in new Element(".is-cdb-editor").elements() ) e.data("cdb")];
@@ -576,7 +689,6 @@ class Editor extends Component {
 	}
 
 	public function refresh( ?state : UndoState ) {
-
 		if( state == null )
 			state = getState();
 
@@ -612,12 +724,11 @@ class Editor extends Component {
 		new Table(this, currentSheet, content, displayMode);
 		content.appendTo(element);
 
-		if( state != null )
-			setState(state, hasFocus);
+		setState(state, hasFocus);
 
 		if( cursor.table != null ) {
 			for( t in tables )
-				if( t.sheet.name == cursor.table.sheet.name )
+				if( t.sheet.getPath() == cursor.table.sheet.getPath() )
 					cursor.table = t;
 			cursor.update();
 		}

+ 3 - 2
hide/view/CdbTable.hx

@@ -11,14 +11,14 @@ class CdbTable extends hide.ui.View<{}> {
 
 	public function new( ?state ) {
 		super(state);
-		editor = new hide.comp.cdb.Editor(config,{
+		editor = new hide.comp.cdb.Editor(config, {
 			copy : () -> (ide.database.save() : Any),
 			load : (v:Any) -> ide.database.load((v:String)),
 			save : function() {
 				ide.saveDatabase();
 				haxe.Timer.delay(syncTabs,0);
 			}
-		});
+		}, this);
 		undo = editor.undo;
 		currentSheet = this.config.get("cdb.currentSheet");
 		view = cast this.config.get("cdb.view");
@@ -56,6 +56,7 @@ class CdbTable extends hide.ui.View<{}> {
 
 	function setEditor(index:Int) {
 		var sheets = getSheets();
+		editor.pushCursorState();
 		editor.show(sheets[index],tabContents[index]);
 		currentSheet = editor.getCurrentSheet();
 		ide.currentConfig.set("cdb.currentSheet", sheets[index].name);