ソースを参照

cdb-types: manage recursive edition on cdb-types

lviguier 1 年間 前
コミット
faa70069cf
3 ファイル変更223 行追加186 行削除
  1. 9 0
      bin/style.css
  2. 10 0
      bin/style.less
  3. 204 186
      hide/comp/cdb/Cell.hx

+ 9 - 0
bin/style.css

@@ -1302,6 +1302,13 @@ input[type=checkbox]:checked:after {
   margin: 2px 2px 2px 2px;
   display: flex;
   background-color: #333333;
+  border-style: solid;
+  border-width: 1px;
+  border-color: #474747;
+}
+.cdb-types select {
+  min-width: 100px;
+  width: auto!important;
 }
 .cdb-types #dropdown-custom-type {
   width: fit-content;
@@ -1322,6 +1329,8 @@ input[type=checkbox]:checked:after {
 .cdb-types p {
   margin-top: 2px;
   margin-bottom: 2px;
+  padding-left: 2px;
+  padding-right: 2px;
 }
 /* Curve editor */
 .hide-curve-editor {

+ 10 - 0
bin/style.less

@@ -1422,6 +1422,14 @@ input[type=checkbox] {
 	margin: 2px 2px 2px 2px;
 	display: flex;
 	background-color: #333333;
+	border-style: solid;
+	border-width: 1px;
+	border-color: #474747;
+
+	select {
+		min-width: 100px;
+		width: auto!important;
+	}
 
 	#dropdown-custom-type {
 		width:fit-content;
@@ -1446,6 +1454,8 @@ input[type=checkbox] {
 	p {
 		margin-top: 2px;
 		margin-bottom: 2px;
+		padding-left: 2px;
+		padding-right: 2px;
 	}
 }
 

+ 204 - 186
hide/comp/cdb/Cell.hx

@@ -993,199 +993,17 @@ class Cell {
 			}
 		case TCustom(typeName):
 			{
-				var customType = editor.base.getCustomType(typeName);
-				var curValue = currentValue != null ? customType.cases[currentValue[0]] : null;
-
 				var shouldClose = false;
 				if (elementHtml.classList.contains("edit"))
 					shouldClose = true;
 
+				if (shouldClose)
+					return;
+
 				elementHtml.innerHTML = null;
 				elementHtml.classList.add("edit");
-
 				var cellEl = new Element(elementHtml);
-				var rootEl = new Element("<div></div>").appendTo(cellEl);
-				new Element('<p>...</p>').css("margin", "0px").css("text-align","center").appendTo(rootEl);
-
-				function getHtml(value : Dynamic, type : cdb.Data.ColumnType) {
-					switch (type) {
-						case TId, TString, TDynamic:
-							return new Element('<input type="text" ${value != null ? 'value="${value}"': ''}></input>');
-						case TBool:
-							var el =  new Element('<input type="checkbox"></input>');
-							if (value != null && value)
-								el.attr("checked", "true");
-							return el;
-						case TInt, TFloat:
-							var t = value;
-							return new Element('<input type="number" ${value != null ? 'value="${value}"': ''}></input>');
-						case TRef(name):
-							{
-								var sdat = editor.base.getSheet(name);
-								if( sdat == null ) return new Element("<p>No sheet data found</p>");
-
-								var isLocal = sdat.idCol.scope != null;
-								var elts: Array<hide.comp.Dropdown.Choice>;
-
-								function makeClasses(o: cdb.Sheet.SheetIndex) {
-									var ret = [];
-									for( c in sdat.columns ) {
-										switch( c.type ) {
-											case TId | TBool:
-												ret.push("r_" + c.name + "_" + Reflect.field(o.obj, c.name));
-											case TEnum( values ):
-												ret.push("r_" + c.name + "_" + values[Reflect.field(o.obj, c.name)]);
-											case TFlags( values ):
-											default:
-										}
-									}
-									return ret;
-								}
-
-								if( isLocal ) {
-									var scope = refScope(sdat,table.getRealSheet(),line.obj,[]);
-									var prefix = table.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,
-										classes : makeClasses(d),
-									}];
-								} else {
-									elts = [ for( d in sdat.all ) {
-										id : d.id,
-										ico : d.ico,
-										text : d.disp,
-										classes : makeClasses(d),
-									}];
-								}
-
-								if( column.opt || currentValue == null || currentValue == "" ) {
-									elts.unshift({
-										id : null,
-										ico : null,
-										text : "--- None ---",
-									});
-								}
-
-								function makeIcon(c: hide.comp.Dropdown.Choice) {
-									if (sdat.props.displayIcon == null)
-										return null;
-									if (c.ico == null)
-										return new Element("<div style='display:inline-block;width:16px'/>");
-									return new Element(tileHtml(c.ico, true).str);
-								}
-
-								var html = new Element('
-								<select name="ref">
-									${ [for(idx in 0...elts.length) '<option value="${idx}" ${elts[idx].text == value ? "selected":""}>${elts[idx].text}</option>'].join('') }
-								</select>');
-								return html;
-							}
-						case TCustom(name):
-							{
-								return null;
-							}
-						default:
-							return new Element('<p>Not supported</p>');
-					}
-				}
-
-				var content = new Element('
-				<div class="cdb-types">
-					<select name="customType" id="dropdown-custom-type">
-					<option value="none">None</option>
-					${ [for (idx in 0...customType.cases.length) '<option value=${idx}>${customType.cases[idx].name}</option>'].join("") }
-					</select>
-					<div id="parameters">
-					<div>
-				</div>');
-
-				var d = content.find("#dropdown-custom-type");
-				if (currentValue != null)
-					d.find("option").eq(Std.int(currentValue[0] + 1)).attr("selected", "true");
-
-				var paramsContent = content.find("#parameters");
-
-				function buildParameters() {
-					paramsContent.empty();
-					var val = d.val();
-					var selected = val != null ? customType.cases[content.find("#dropdown-custom-type").val()] : null;
-
-					if (selected != null && selected.args.length > 0) {
-						for (idx in 0...selected.args.length) {
-							new Element('<p>${idx == 0 ? '(' : ''}${selected.args[idx].name}&nbsp:&nbsp</p>').appendTo(paramsContent);
-
-							var paramVal = Reflect.field(line.obj, column.name);
-							getHtml(paramVal != null ? paramVal[idx + 1] : null, selected.args[idx].type).addClass("value").appendTo(paramsContent);
-
-							if (idx != selected.args.length - 1)
-								new Element('<p>&nbsp,&nbsp</p>').appendTo(paramsContent);
-							else
-								new Element('<p>&nbsp)</p>').appendTo(paramsContent);
-						}
-					}
-				}
-
-				function closeCdbTypeEdit() {
-					var val = d.val();
-					var selected = val != null ? customType.cases[content.find("#dropdown-custom-type").val()] : null;
-					var stringValue = "";
-
-					if (selected != null) {
-						stringValue = selected.name;
-
-						if (selected.args != null && selected.args.length > 0) {
-							stringValue = '${selected.name}(';
-
-							var paramsValues = paramsContent.find(".value");
-							for (idx in 0...selected.args.length) {
-								var paramValue = paramsValues.eq(idx);
-
-								if (paramValue.is("input[type=checkbox]"))
-									stringValue += paramValue.is(":checked");
-								else if (paramValue.is("select")) {
-									stringValue += paramValue.find(":selected").text();
-								}
-								else
-									stringValue += paramsValues.eq(idx).val();
-
-								if (idx != selected.args.length -1)
-									stringValue += (",");
-							}
-
-							stringValue += ')';
-						}
-					}
-
-					cellEl.empty();
-					this.setRawValue(stringValue);
-					this.closeEdit();
-				}
-
-				buildParameters();
-
-				d.on("change", function(e) {
-					buildParameters();
-				});
-
-				// Prevent missclick to actually close the edit mode and
-				// open another one
-				rootEl.on("click", function(e) { closeCdbTypeEdit(); e.stopPropagation(); });
-				content.on("click", function(e) { e.stopPropagation(); });
-				content.on("dblclick", function(e) { e.stopPropagation(); });
-
-				var offset = 1920 - (cellEl.offset().left + cellEl.width());
-				content.css("right", '${offset}px');
-				content.css("top", '${cellEl.offset().top}px');
-				content.css("min-width", '${cellEl.width()}px');
-				content.appendTo(cellEl);
-
-				d.focus();
-
-				if (shouldClose)
-					closeCdbTypeEdit();
-
+				editCustomType(typeName, currentValue, cellEl);
 			}
 		case TColor:
 			var elem = new Element(elementHtml);
@@ -1460,4 +1278,204 @@ class Cell {
 		focus();
 	}
 
+	public function editCustomType(typeName : String, currentValue : Dynamic, parentEl : Element, depth : Int = 0, ?minWidth: Float) {
+		var customType = editor.base.getCustomType(typeName);
+
+		parentEl.empty();
+		var rootEl = new Element("<div></div>").appendTo(parentEl);
+		new Element('<p>...</p>').css("margin", "0px").css("text-align","center").appendTo(rootEl);
+
+		function getHtml(value : Dynamic, column : cdb.Data.Column) {
+			switch (column.type) {
+				case TId, TString, TDynamic:
+					return new Element('<input type="text" ${value != null ? 'value="${value}"': ''}></input>');
+				case TBool:
+					var el =  new Element('<input type="checkbox"></input>');
+					if (value != null && value)
+						el.attr("checked", "true");
+					return el;
+				case TInt, TFloat:
+					return new Element('<input type="number" ${value != null ? 'value="${value}"': ''}></input>');
+				case TRef(name):
+					{
+						var sdat = editor.base.getSheet(name);
+						if( sdat == null ) return new Element("<p>No sheet data found</p>");
+
+						var isLocal = sdat.idCol.scope != null;
+						var elts: Array<hide.comp.Dropdown.Choice>;
+
+						function makeClasses(o: cdb.Sheet.SheetIndex) {
+							var ret = [];
+							for( c in sdat.columns ) {
+								switch( c.type ) {
+									case TId | TBool:
+										ret.push("r_" + c.name + "_" + Reflect.field(o.obj, c.name));
+									case TEnum( values ):
+										ret.push("r_" + c.name + "_" + values[Reflect.field(o.obj, c.name)]);
+									case TFlags( values ):
+									default:
+								}
+							}
+							return ret;
+						}
+
+						if( isLocal ) {
+							var scope = refScope(sdat,table.getRealSheet(),line.obj,[]);
+							var prefix = table.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,
+								classes : makeClasses(d),
+							}];
+						} else {
+							elts = [ for( d in sdat.all ) {
+								id : d.id,
+								ico : d.ico,
+								text : d.disp,
+								classes : makeClasses(d),
+							}];
+						}
+
+						if( column.opt || currentValue == null || currentValue == "" ) {
+							elts.unshift({
+								id : null,
+								ico : null,
+								text : "--- None ---",
+							});
+						}
+
+						function makeIcon(c: hide.comp.Dropdown.Choice) {
+							if (sdat.props.displayIcon == null)
+								return null;
+							if (c.ico == null)
+								return new Element("<div style='display:inline-block;width:16px'/>");
+							return new Element(tileHtml(c.ico, true).str);
+						}
+
+						var html = new Element('
+						<select name="ref">
+							${ [for(idx in 0...elts.length) '<option value="${idx}" ${elts[idx].text == value ? "selected":""}>${elts[idx].text}</option>'].join('') }
+						</select>');
+						return html;
+					}
+				case TCustom(name):
+					{
+						var valueHtml = this.valueHtml(column, value, line.table.getRealSheet(), currentValue, []);
+						var html = new Element('<div class="sub-cdb-type"><p>${valueHtml.str}</p></div>').css("min-width","80px").css("background-color","#222222");
+						html.on("click", function(e) {
+							editCustomType(name, value, html, depth + 1, minWidth == null ? parentEl.width() : minWidth);
+						});
+
+						return html;
+					}
+				default:
+					return new Element('<p>Not supported</p>');
+			}
+		}
+
+		var content = new Element('
+		<div class="cdb-types">
+			<select name="customType" id="dropdown-custom-type">
+			<option value="none">None</option>
+			${ [for (idx in 0...customType.cases.length) '<option value=${idx}>${customType.cases[idx].name}</option>'].join("") }
+			</select>
+			<div id="parameters">
+			<div>
+		</div>');
+
+		var d = content.find("#dropdown-custom-type");
+		if (currentValue != null)
+			d.find("option").eq(Std.int(currentValue[0] + 1)).attr("selected", "true");
+
+		var paramsContent = content.find("#parameters");
+
+		function buildParameters() {
+			paramsContent.empty();
+			var val = d.val();
+			var selected = val != null ? customType.cases[content.find("#dropdown-custom-type").val()] : null;
+
+			if (selected != null && selected.args.length > 0) {
+				for (idx in 0...selected.args.length) {
+					new Element('<p>${idx == 0 ? '(' : ''}${selected.args[idx].name}&nbsp:&nbsp</p>').appendTo(paramsContent);
+
+					var paramVal = cast currentValue;
+					getHtml(currentValue != null ? currentValue[idx + 1] : null, selected.args[idx]).addClass("value").appendTo(paramsContent);
+
+					if (idx != selected.args.length - 1)
+						new Element('<p>&nbsp,&nbsp</p>').appendTo(paramsContent);
+					else
+						new Element('<p>&nbsp)</p>').appendTo(paramsContent);
+				}
+			}
+		}
+
+		function closeCdbTypeEdit() {
+			var val = d.val();
+			var selected = val != null ? customType.cases[content.find("#dropdown-custom-type").val()] : null;
+			var stringValue = "";
+
+			if (selected != null) {
+				stringValue = selected.name;
+
+				if (selected.args != null && selected.args.length > 0) {
+					stringValue = '${selected.name}(';
+
+					var paramsValues = paramsContent.find(".value");
+					for (idx in 0...selected.args.length) {
+						var paramValue = paramsValues.eq(idx);
+
+						if (paramValue.is("input[type=checkbox]"))
+							stringValue += paramValue.is(":checked");
+						else if (paramValue.is("select")) {
+							var sel = paramValue.find(":selected");
+							if (sel.val() != 0)
+								stringValue += sel.text();
+						}
+						else if (paramValue.is("div")) {
+							// Case where the param value is another cdbType
+							stringValue += paramValue.children().first().text();
+						}
+						else
+							stringValue += paramsValues.eq(idx).val();
+
+						if (idx != selected.args.length -1)
+							stringValue += (",");
+					}
+
+					stringValue += ')';
+				}
+			}
+
+			parentEl.empty();
+
+			if (depth == 0) {
+				this.setRawValue(stringValue);
+				this.closeEdit();
+			}
+			else {
+				new Element('<p>${stringValue}</p>').appendTo(parentEl);
+			}
+		}
+
+		buildParameters();
+
+		d.on("change", function(e) {
+			buildParameters();
+		});
+
+		// Prevent missclick to actually close the edit mode and
+		// open another one
+		rootEl.on("click", function(e) { closeCdbTypeEdit(); e.stopPropagation(); });
+		content.on("click", function(e) { e.stopPropagation(); });
+		content.on("dblclick", function(e) { e.stopPropagation(); });
+
+		var offset = depth == 0 ? 1920 - (parentEl.offset().left + parentEl.width()) : 0;
+		content.css("right", '${offset}px');
+		content.css("top", '${depth == 0 ? parentEl.offset().top : parentEl.height()}px');
+		content.css("min-width", '${minWidth == null ? parentEl.width() : minWidth}px');
+		content.appendTo(parentEl);
+
+		d.focus();
+	}
 }