Procházet zdrojové kódy

added scoped id support, fixed some real-sheet/virtual-sheet mixups

Nicolas Cannasse před 5 roky
rodič
revize
ac513f3d6f

+ 5 - 1
bin/cdb.css

@@ -380,11 +380,15 @@
 .cdb .content-modal form .t_custom .custom {
   display: table-row;
 }
+.cdb .content-modal form .t_id .scope {
+  display: table-row;
+}
 .cdb .content-modal form .values,
 .cdb .content-modal form .sheet,
 .cdb .content-modal form .custom,
 .cdb .content-modal form .disp,
-.cdb .content-modal form .kind {
+.cdb .content-modal form .kind,
+.cdb .content-modal form .scope {
   display: none;
 }
 .cdb .content-modal form.edit input.create {

+ 2 - 2
bin/cdb.less

@@ -414,8 +414,8 @@
 			.t_ref .sheet { display : table-row; }
 			.t_layer .sheet { display : table-row; }
 			.t_custom .custom { display : table-row; }
-			.values, .sheet, .custom, .disp, .kind { display : none; }
-
+			.t_id .scope { display : table-row; }
+			.values, .sheet, .custom, .disp, .kind, .scope { display : none; }
 		}
 
 		form.edit {

+ 80 - 11
hide/comp/cdb/Cell.hx

@@ -80,7 +80,7 @@ class Cell extends Component {
 
 	public function refresh() {
 		currentValue = Reflect.field(line.obj, column.name);
-		var html = valueHtml(column, value, line.table.sheet, line.obj);
+		var html = valueHtml(column, value, line.table.getRealSheet(), line.obj, []);
 		if( html == "&nbsp;" ) element.text(" ") else if( html.indexOf('<') < 0 && html.indexOf('&') < 0 ) element.text(html) else element.html(html);
 		updateClasses();
 	}
@@ -113,7 +113,51 @@ class Cell extends Component {
 		return view.show == null || view.show.indexOf(column) >= 0;
 	}
 
-	public function valueHtml( c : cdb.Data.Column, v : Dynamic, sheet : cdb.Sheet, obj : Dynamic ) : String {
+	var _cachedScope : Array<{ s : cdb.Sheet, obj : Dynamic }>;
+	function getScope() {
+		if( _cachedScope != null ) return _cachedScope;
+		var scope = [];
+		var line = line;
+		while( true ) {
+			var p = Std.downcast(line.table, SubTable);
+			if( p == null ) break;
+			line = p.cell.line;
+			scope.unshift({ s : line.table.getRealSheet(), obj : line.obj });
+		}
+		return _cachedScope = scope;
+	}
+
+	function makeId( scopes : Array<{ s : cdb.Sheet, obj : Dynamic }>, scope : Int, id : String ) {
+		var ids = [];
+		if( id != null ) ids.push(id);
+		var pos = scopes.length;
+		while( true ) {
+			pos -= scope;
+			if( pos < 0 ) {
+				scopes = getScope();
+				pos += scopes.length;
+			}
+			var s = scopes[pos];
+			var pid = Reflect.field(s.obj, s.s.idCol.name);
+			if( pid == null ) return "";
+			ids.unshift(pid);
+			scope = s.s.idCol.scope;
+			if( scope == null ) break;
+		}
+		return ids.join(":");
+	}
+
+	function refScope( targetSheet : cdb.Sheet, currentSheet : cdb.Sheet, obj : Dynamic, localScope : Array<{ s : cdb.Sheet, obj : Dynamic }> ) {
+		var targetDepth = targetSheet.name.split("@").length;
+		var scope = getScope().concat(localScope);
+		if( scope.length < targetDepth )
+			scope.push({ s : currentSheet, obj : obj });
+		while( scope.length >= targetDepth )
+			scope.pop();
+		return scope;
+	}
+
+	function valueHtml( c : cdb.Data.Column, v : Dynamic, sheet : cdb.Sheet, obj : Dynamic, scope : Array<{ s : cdb.Sheet, obj : Dynamic }> ) : String {
 		if( v == null ) {
 			if( c.opt )
 				return "&nbsp;";
@@ -128,7 +172,13 @@ class Cell extends Component {
 				v + "";
 			}
 		case TId:
-			v == "" ? '<span class="error">#MISSING</span>' : (editor.base.getSheet(sheet.name).index.get(v).obj == obj ? v : '<span class="error">#DUP($v)</span>');
+			if( v == "" )
+				'<span class="error">#MISSING</span>';
+			else {
+				var id = c.scope != null ? makeId(scope,c.scope,v) : v;
+				var uniq = editor.base.getSheet(sheet.name).index.get(id);
+				uniq == null || uniq.obj == obj ? v : '<span class="error">#DUP($v)</span>';
+			}
 		case TString if( c.kind == Script ):
 			v == "" ? "&nbsp;" : colorizeScript(c,v);
 		case TString, TLayer(_):
@@ -138,7 +188,7 @@ class Cell extends Component {
 				'<span class="error">#MISSING</span>';
 			else {
 				var s = editor.base.getSheet(sname);
-				var i = s.index.get(v);
+				var i = s.index.get(s.idCol.scope != null ? makeId(refScope(s,sheet,obj,scope),s.idCol.scope,v) : v);
 				i == null ? '<span class="error">#REF($v)</span>' : (i.ico == null ? "" : tileHtml(i.ico,true)+" ") + StringTools.htmlEscape(i.disp);
 			}
 		case TBool:
@@ -152,6 +202,7 @@ class Cell extends Component {
 			var ps = sheet.getSub(c);
 			var out : Array<String> = [];
 			var size = 0;
+			scope.push({ s : sheet, obj : obj });
 			for( v in a ) {
 				var vals = [];
 				for( c in ps.columns )
@@ -160,7 +211,7 @@ class Cell extends Component {
 						continue;
 					default:
 						if( !canViewSubColumn(ps, c.name) ) continue;
-						var h = valueHtml(c, Reflect.field(v, c.name), ps, v);
+						var h = valueHtml(c, Reflect.field(v, c.name), ps, v, scope);
 						if( h != "" && h != "&nbsp;" )
 							vals.push(h);
 					}
@@ -179,18 +230,21 @@ class Cell extends Component {
 				size += vstr.length;
 				out.push(v);
 			}
+			scope.pop();
 			if( out.length == 0 )
 				return "";
 			return out.join(", ");
 		case TProperties:
 			var ps = sheet.getSub(c);
 			var out = [];
+			scope.push({ s : sheet, obj : obj });
 			for( c in ps.columns ) {
 				var pval = Reflect.field(v, c.name);
 				if( pval == null && c.opt ) continue;
 				if( !canViewSubColumn(ps, c.name) ) continue;
-				out.push(c.name+" : "+valueHtml(c, pval, ps, v));
+				out.push(c.name+" : "+valueHtml(c, pval, ps, v, scope));
 			}
+			scope.pop();
 			return out.join("<br/>");
 		case TCustom(name):
 			var t = editor.base.getCustomType(name);
@@ -202,7 +256,7 @@ class Cell extends Component {
 				var out = [];
 				var pos = 1;
 				for( i in 1...a.length )
-					out.push(valueHtml(cas.args[i-1], a[i], sheet, this));
+					out.push(valueHtml(cas.args[i-1], a[i], sheet, this, scope));
 				str += out.join(",");
 				str += ")";
 			}
@@ -401,7 +455,14 @@ class Cell extends Component {
 			element.addClass("edit");
 
 			var s = new Element("<select>");
-			var elts = [for( d in sdat.all ){ id : d.id, ico : d.ico, text : d.disp }];
+			var isLocal = sdat.idCol.scope != null;
+			var elts;
+			if( isLocal ) {
+				var scope = refScope(sdat,table.getRealSheet(),line.obj,[]);
+				var prefix = makeId(scope, sdat.idCol.scope, null)+":";
+				elts = [for( d in sdat.all ) if( StringTools.startsWith(d.id,prefix) ) { id : d.id.split(":").pop(), ico : d.ico, text : d.disp }];
+			} else
+				elts = [for( d in sdat.all ) { id : d.id, ico : d.ico, text : d.disp }];
 			if( column.opt || currentValue == null || currentValue == "" )
 				elts.unshift( { id : "~", ico : null, text : "--- None ---" } );
 			element.append(s);
@@ -603,16 +664,24 @@ class Cell extends Component {
 		case TId:
 			var obj = line.obj;
 			var prevValue = value;
+			var realSheet = table.getRealSheet();
+			var isLocal = realSheet.idCol.scope != null;
+			var parentID = isLocal ? makeId([],realSheet.idCol.scope,null) : null;
 			// most likely our obj, unless there was a #DUP
-			var prevObj = value != null ? table.sheet.index.get(value) : null;
+			var prevObj = value != null ? realSheet.index.get(isLocal ? parentID+":"+value : value) : null;
 			// have we already an obj mapped to the same id ?
-			var prevTarget = table.sheet.index.get(newValue);
+			var prevTarget = realSheet.index.get(isLocal ? parentID+":"+newValue : newValue);
 			editor.beginChanges();
 			if( prevObj == null || prevObj.obj == obj ) {
 				// remap
 				var m = new Map();
 				m.set(value, newValue);
-				editor.base.updateRefs(table.sheet, m);
+				if( isLocal ) {
+					var scope = getScope();
+					var parent = scope[scope.length - realSheet.idCol.scope];
+					editor.base.updateLocalRefs(realSheet, m, parent.obj, parent.s);
+				} else
+					editor.base.updateRefs(realSheet, m);
 			}
 			setValue(newValue);
 			editor.endChanges();

+ 14 - 13
hide/comp/cdb/Editor.hx

@@ -326,7 +326,7 @@ class Editor extends Component {
 			Reflect.deleteField(line.obj, column.name);
 		else
 			Reflect.setField(line.obj, column.name, value);
-		line.table.sheet.updateValue(column, line.index, prev);
+		line.table.getRealSheet().updateValue(column, line.index, prev);
 		endChanges();
 	}
 
@@ -552,7 +552,7 @@ class Editor extends Component {
 	}
 
 	public function newColumn( sheet : cdb.Sheet, ?index : Int, ?onDone : cdb.Data.Column -> Void ) {
-		var modal = new hide.comp.cdb.ModalColumnForm(base, null, element);
+		var modal = new hide.comp.cdb.ModalColumnForm(base, sheet, null, element);
 		modal.setCallback(function() {
 			var c = modal.getColumn(base, sheet, null);
 			if (c == null)
@@ -578,7 +578,7 @@ class Editor extends Component {
 	}
 
 	public function editColumn( sheet : cdb.Sheet, col : cdb.Data.Column ) {
-		var modal = new hide.comp.cdb.ModalColumnForm(base, col, element);
+		var modal = new hide.comp.cdb.ModalColumnForm(base, sheet, col, element);
 		modal.setCallback(function() {
 			var c = modal.getColumn(base, sheet, col);
 			if (c == null)
@@ -636,22 +636,23 @@ class Editor extends Component {
 	public function popupColumn( table : Table, col : cdb.Data.Column, ?cell : Cell ) {
 		if( view != null )
 			return;
-		var indexColumn = table.sheet.columns.indexOf(col);
+		var sheet = table.getRealSheet();
+		var indexColumn = sheet.columns.indexOf(col);
 		var menu : Array<hide.comp.ContextMenu.ContextMenuItem> = [
-			{ label : "Edit", click : function () editColumn(table.sheet, col) },
-			{ label : "Add Column", click : function () newColumn(table.sheet, indexColumn) },
+			{ label : "Edit", click : function () editColumn(sheet, col) },
+			{ label : "Add Column", click : function () newColumn(sheet, indexColumn) },
 			{ label : "", isSeparator: true },
 			{ label : "Move Left", enabled:  (indexColumn > 0), click : function () {
 				beginChanges();
-				table.sheet.columns.remove(col);
-				table.sheet.columns.insert(indexColumn - 1, col);
+				sheet.columns.remove(col);
+				sheet.columns.insert(indexColumn - 1, col);
 				endChanges();
 				refresh();
 			}},
-			{ label : "Move Right", enabled: (indexColumn < table.sheet.columns.length - 1), click : function () {
+			{ label : "Move Right", enabled: (indexColumn < sheet.columns.length - 1), click : function () {
 				beginChanges();
-				table.sheet.columns.remove(col);
-				table.sheet.columns.insert(indexColumn + 1, col);
+				sheet.columns.remove(col);
+				sheet.columns.insert(indexColumn + 1, col);
 				endChanges();
 				refresh();
 			}},
@@ -659,9 +660,9 @@ class Editor extends Component {
 			{ label : "Delete", click : function () {
 				beginChanges();
 				if( table.displayMode == Properties )
-					changeObject(cell.line, col, base.getDefault(col,table.sheet));
+					changeObject(cell.line, col, base.getDefault(col,sheet));
 				else
-					table.sheet.deleteColumn(col.name);
+					sheet.deleteColumn(col.name);
 				endChanges();
 				refresh();
 			}}

+ 30 - 3
hide/comp/cdb/ModalColumnForm.hx

@@ -7,7 +7,7 @@ class ModalColumnForm extends Modal {
 	var contentModal : Element;
 	var form : Element;
 
-	public function new(base : cdb.Database, column : cdb.Data.Column, ?parent,?el) {
+	public function new(base : cdb.Database, sheet : cdb.Sheet, column : cdb.Data.Column, ?parent,?el) {
 		super(parent,el);
 
 		var editForm = (column != null);
@@ -88,6 +88,14 @@ class ModalColumnForm extends Modal {
 					<td><select name="ctype"></select>
 				</tr>
 
+				<tr class="scope">
+					<td>Scope
+					<td>
+					<select name="scope">
+					<option value="">Global</option>
+					</select>
+				</tr>
+
 				<tr class="opt">
 					<td>&nbsp;
 					<td><label><input type="checkbox" name="req"/>&nbsp;Required</label>
@@ -106,11 +114,27 @@ class ModalColumnForm extends Modal {
 
 			</form>').appendTo(contentModal);
 
+		var parent = sheet.getParent();
+		if( parent == null )
+			form.find(".scope").remove();
+		else {
+			var scope = 1;
+			var scopes = form.find("[name=scope]");
+			var p = parent;
+			while( p != null ) {
+				if( p.s.idCol != null )
+					new Element("<option>").attr("value",""+scope).text(p.s.name).appendTo(scopes);
+				p = p.s.getParent();
+				scope++;
+			}
+		}
+
 		var sheets = form.find("[name=sheet]");
 		sheets.empty();
 		for( i in 0...base.sheets.length ) {
 			var s = base.sheets[i];
-			if( s.props.hide ) continue;
+			if( s.idCol == null ) continue;
+			if( s.idCol.scope != null && !StringTools.startsWith(sheet.name,s.name.split("@").slice(0,-s.idCol.scope).join("@")) ) continue;
 			new Element("<option>").attr("value", "" + i).text(s.name).appendTo(sheets);
 		}
 
@@ -133,11 +157,13 @@ class ModalColumnForm extends Modal {
 			form.find("[name=req]").prop("checked", !column.opt);
 			form.find("[name=display]").val(column.display == null ? "0" : Std.string(column.display));
 			form.find("[name=kind]").val(column.kind == null ? "" : ""+column.kind);
+			form.find("[name=scope]").val(column.scope == null ? "" : ""+column.scope);
 			switch( column.type ) {
 			case TEnum(values), TFlags(values):
 				form.find("[name=values]").val(values.join(","));
 			case TRef(sname), TLayer(sname):
-				form.find("[name=sheet]").val( "" + base.sheets.indexOf(base.getSheet(sname)));
+				var index = base.sheets.indexOf(base.getSheet(sname));
+				form.find("[name=sheet]").val( "" + index);
 			case TCustom(name):
 				form.find("[name=ctype]").val(name);
 			default:
@@ -249,6 +275,7 @@ class ModalColumnForm extends Modal {
 		case "localizable": c.kind = Localizable;
 		case "script": c.kind = Script;
 		}
+		if( t == TId && v.scope != "" ) c.scope = Std.parseInt(v.scope);
 		return c;
 	}
 

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

@@ -47,7 +47,11 @@ class SubTable extends Table {
 		super(editor, sheet, root, mode);
 	}
 
-	public function makeSubSheet() {
+	override function getRealSheet() {
+		return cell.table.sheet.getSub(cell.column);
+	}
+
+	function makeSubSheet() {
 		var sheet = cell.table.sheet;
 		var c = cell.column;
 		var index = cell.line.index;

+ 5 - 1
hide/comp/cdb/Table.hx

@@ -45,6 +45,10 @@ class Table extends Component {
 		refresh();
 	}
 
+	public function getRealSheet() {
+		return sheet;
+	}
+
 	public function canInsert() {
 		return view == null || view.insert;
 	}
@@ -142,7 +146,7 @@ class Table extends Component {
 				}
 			});
 			col.dblclick(function(_) {
-				if( editor.view == null ) editor.editColumn(sheet, c);
+				if( editor.view == null ) editor.editColumn(getRealSheet(), c);
 			});
 			cols.append(col);