Переглянути джерело

allow default formula per column

Nicolas Cannasse 4 роки тому
батько
коміт
c47940a45b
6 змінених файлів з 126 додано та 58 видалено
  1. 13 7
      bin/cdb.css
  2. 10 8
      bin/cdb.less
  3. 2 2
      hide/comp/cdb/Cell.hx
  4. 17 6
      hide/comp/cdb/Editor.hx
  5. 34 29
      hide/comp/cdb/Formulas.hx
  6. 50 6
      hide/comp/cdb/ModalColumnForm.hx

+ 13 - 7
bin/cdb.css

@@ -221,13 +221,13 @@
 .cdb .cdb-sheet td.t_float.zero {
   color: #888;
 }
+.cdb .cdb-sheet td.nan {
+  color: #C44;
+}
 .cdb .cdb-sheet td.formula {
   font-style: italic;
   color: #888;
 }
-.cdb .cdb-sheet td.formula.error {
-  color: #C44;
-}
 .cdb .cdb-sheet td.t_list,
 .cdb .cdb-sheet td.t_properties {
   white-space: nowrap;
@@ -407,10 +407,17 @@
 .cdb .content-modal form td.first {
   width: 120px;
 }
+.cdb .content-modal form .formula {
+  display: none;
+}
 .cdb .content-modal form .t_int .disp,
 .cdb .content-modal form .t_float .disp {
   display: table-row;
 }
+.cdb .content-modal form .t_int .formula,
+.cdb .content-modal form .t_float .formula {
+  display: table-row;
+}
 .cdb .content-modal form .t_string .kind {
   display: table-row;
 }
@@ -438,13 +445,12 @@
 .cdb .content-modal form .scope {
   display: none;
 }
-.cdb .content-modal form #doctog {
+.cdb .content-modal form .doctog {
   cursor: pointer;
   color: #888;
 }
-.cdb .content-modal form .doc.hide span,
-.cdb .content-modal form .doc.hide textarea {
-  display: none;
+.cdb .content-modal form .hide {
+  display: none !important;
 }
 .cdb .content-modal form.edit input.create {
   display: none;

+ 10 - 8
bin/cdb.less

@@ -246,13 +246,13 @@
 		td.t_int.zero, td.t_float.zero {
 			color: #888;
 		}
+		td.nan {
+			color : #C44;
+		}
 
 		td.formula {
 			font-style : italic;
 			color : #888;
-			&.error {
-				color : #C44;
-			}
 		}
 
 		td.t_list, td.t_properties {
@@ -455,8 +455,12 @@
 			td.first {
 				width : 120px;
 			}
+			.formula {
+				display: none;
+			}
 			.t_int, .t_float {
 				.disp { display : table-row; }
+				.formula { display: table-row; }
 			}
 			.t_string {
 				.kind { display : table-row; }
@@ -467,14 +471,12 @@
 			.t_custom .custom { display : table-row; }
 			.t_id .scope { display : table-row; }
 			.values, .sheet, .custom, .disp, .kind, .scope { display : none; }
-			#doctog {
+			.doctog {
 				cursor:pointer;
 				color : #888;
 			}
-			.doc.hide {
-				span, textarea {
-					display: none;
-				}
+			.hide {
+				display: none !important;
 			}
 		}
 

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

@@ -94,7 +94,7 @@ class Cell extends Component {
 			}
 			var forms : Array<hide.comp.ContextMenu.ContextMenuItem>;
 			var current = editor.formulas.get(this);
-			forms = [for( f in editor.formulas.getList(this) ) { label : f.name, click : () -> if( f == current ) setF(null) else setF(f), checked : f == current }];
+			forms = [for( f in editor.formulas.getList(table.sheet) ) { label : f.name, click : () -> if( f == current ) setF(null) else setF(f), checked : f == current }];
 			forms.push({ label : "New...", click : () -> editor.formulas.createNew(this, setF) });
 			menu = [
 				{ label : "Formula", menu : forms }
@@ -146,7 +146,7 @@ class Cell extends Component {
 			element.toggleClass("false", value == false);
 		case TInt, TFloat:
 			element.toggleClass("zero", value == 0 );
-			element.toggleClass("error", Math.isNaN(value));
+			element.toggleClass("nan", Math.isNaN(value));
 			element.toggleClass("formula", editor.formulas.has(this) );
 		default:
 		}

+ 17 - 6
hide/comp/cdb/Editor.hx

@@ -19,6 +19,10 @@ typedef EditorApi = {
 	function save() : Void;
 }
 
+typedef EditorColumnProps = {
+	var ?formula : String;
+}
+
 @:allow(hide.comp.cdb)
 class Editor extends Component {
 
@@ -377,11 +381,12 @@ class Editor extends Component {
 	public function changeObject( line : Line, column : cdb.Data.Column, value : Dynamic ) {
 		beginChanges();
 		var prev = Reflect.field(line.obj, column.name);
-		if( value == null )
-			Reflect.deleteField(line.obj, column.name);
-		else
+		if( value == null ) {
+			formulas.setForValue(line.obj, line.table.sheet, column, null);
+		} else {
 			Reflect.setField(line.obj, column.name, value);
-		formulas.removeFromValue(line.obj, column);
+			formulas.removeFromValue(line.obj, column);
+		}
 		line.table.getRealSheet().updateValue(column, line.index, prev);
 		line.evaluate(); // propagate
 		endChanges();
@@ -628,10 +633,16 @@ class Editor extends Component {
 		return null;
 	}
 
+	public function getColumnProps( c : cdb.Data.Column ) {
+		var pr : EditorColumnProps = c.editor;
+		if( pr == null ) pr = {};
+		return pr;
+	}
+
 	public function newColumn( sheet : cdb.Sheet, ?index : Int, ?onDone : cdb.Data.Column -> Void, ?col ) {
-		var modal = new hide.comp.cdb.ModalColumnForm(base, sheet, col, element);
+		var modal = new hide.comp.cdb.ModalColumnForm(this, sheet, col, element);
 		modal.setCallback(function() {
-			var c = modal.getColumn(base, sheet, col);
+			var c = modal.getColumn(col);
 			if (c == null)
 				return;
 			beginChanges();

+ 34 - 29
hide/comp/cdb/Formulas.hx

@@ -32,18 +32,24 @@ class Formulas {
 			if( sheet != null && sheet != s ) continue;
 			var forms = fmap.get(s.name);
 			if( forms == null ) continue;
-			var columns = [for( c in s.columns ) if( c.type == TInt || c.type == TFloat ) c];
+			var columns = [];
+			for( c in s.columns )
+				if( c.type == TInt || c.type == TFloat ) {
+					var def = editor.getColumnProps(c).formula;
+					columns.push({ name : c.name, def : def, opt : c.opt });
+				}
 			for( o in s.getLines() ) {
 				for( c in columns ) {
-					var fname = Reflect.field(o,c.name+"__f");
+					var fname : String = Reflect.field(o,c.name+"__f");
+					if( fname == null ) fname = c.def;
 					if( fname == null ) continue;
-					var f = forms.get(fname);
-					if( f == null ) continue;
-					var v = try f.call(o) catch( e : Dynamic ) Math.NaN;
-					if( v == null )
+					var v = try forms.get(fname).call(o) catch( e : Dynamic ) Math.NaN;
+					if( v == null && c.opt )
 						Reflect.deleteField(o, c.name);
-					else
+					else {
+						if( v == null || !Std.is(v, Float) ) v = Math.NaN;
 						Reflect.setField(o, c.name, v);
+					}
 				}
 			}
 		}
@@ -99,30 +105,25 @@ class Formulas {
 		browseRec(expr);
 	}
 
-	public function getList( c : Cell ) : Array<Formula> {
-		var type = getTypeName(c.table.sheet);
+	public function getList( s : cdb.Sheet ) : Array<Formula> {
+		var type = getTypeName(s);
 		return [for( f in formulas ) if( f.type == type ) f];
 	}
 
 	public function get( c : Cell ) : Null<Formula> {
-		var f = Reflect.field(c.line.obj, c.column.name+"__f");
-		if( f == null )
-			return null;
 		var tmap = fmap.get(c.table.sheet.name);
 		if( tmap == null )
 			return null;
+		var f = Reflect.field(c.line.obj, c.column.name+"__f");
+		if( f == null && c.column.editor != null ) {
+			f = (c.column.editor:Editor.EditorColumnProps).formula;
+			if( f == null ) return null;
+		}
 		return tmap.get(f);
 	}
 
 	public function set( c : Cell, f : Formula ) {
-		var obj = c.line.obj;
-		var field = c.column.name+"__f";
-		if( f == null ) {
-			Reflect.deleteField(obj, field);
-			var def = c.table.editor.base.getDefault(c.column,c.table.sheet);
-			if( def == null ) Reflect.deleteField(obj, c.column.name) else Reflect.setField(obj, c.column.name, def);
-		} else
-			Reflect.setField(obj, field, f.name);
+		setForValue(c.line.obj, c.table.getRealSheet(), c.column, f == null ? null : f.name);
 	}
 
 	public inline function has(c:Cell) {
@@ -134,16 +135,20 @@ class Formulas {
 	}
 
 	public function setForValue( obj : Dynamic, sheet : cdb.Sheet, c : cdb.Data.Column, fname : String ) {
-		Reflect.setField(obj, c.name+"__f", fname);
-		Reflect.deleteField(obj, c.name);
-		var tmap = fmap.get(sheet.name);
-		if( tmap != null ) {
-			var f = tmap.get(fname);
-			if( f != null ) {
-				var v = f.call(obj);
-				if( v != null ) Reflect.setField(obj, c.name, v);
+		var field = c.name+"__f";
+		var fdef = editor.getColumnProps(c).formula;
+		if( fname != null && fdef == fname )
+			fname = null;
+		if( fname == null ) {
+			Reflect.deleteField(obj, field);
+			var def = editor.base.getDefault(c,sheet);
+			if( fdef != null ) {
+				var tmap = fmap.get(sheet.name);
+				def = try tmap.get(fdef).call(obj) catch( e : Dynamic ) Math.NaN;
 			}
-		}
+			if( def == null ) Reflect.deleteField(obj, c.name) else Reflect.setField(obj, c.name, def);
+		} else
+			Reflect.setField(obj, field, fname);
 	}
 
 	function getFormulaNameFromValue( obj : Dynamic, c : cdb.Data.Column ) {

+ 50 - 6
hide/comp/cdb/ModalColumnForm.hx

@@ -6,11 +6,16 @@ class ModalColumnForm extends Modal {
 
 	var contentModal : Element;
 	var form : Element;
+	var editor : Editor;
+	var sheet : cdb.Sheet;
 
-	public function new(base : cdb.Database, sheet : cdb.Sheet, column : cdb.Data.Column, ?parent,?el) {
+	public function new( editor : Editor, sheet : cdb.Sheet, column : cdb.Data.Column, ?parent,?el) {
 		super(parent,el);
 
 		var editForm = (column != null);
+		var base = editor.base;
+		this.editor = editor;
+		this.sheet = sheet;
 
 		contentModal = new Element("<div tabindex='0'>").addClass("content-modal").appendTo(content);
 
@@ -96,11 +101,27 @@ class ModalColumnForm extends Modal {
 					</select>
 				</tr>
 
+				<tr class="formula hide">
+					<td>Formula</td>
+					<td>
+						<select name="formula">
+						<option value="">None</option>
+						</select>
+					</td>
+				</tr>
+
 				<tr class="doc hide">
-					<td><a href="#" id="doctog">[+]</a><span>Documentation</span>
+					<td>Documentation
 					<td><textarea name="doc"></textarea>
 				</tr>
 
+				<tr class="more">
+					<td>
+						<a href="#" class="doctog can-hide">[+]</a>
+						<a href="#" class="doctog hide">[-]</a>
+					</td>
+				</tr>
+
 				<tr class="opt">
 					<td>&nbsp;
 					<td><label><input type="checkbox" name="req"/>&nbsp;Required</label>
@@ -155,8 +176,13 @@ class ModalColumnForm extends Modal {
 		for( t in base.getCustomTypes() )
 			new Element("<option>").attr("value", "" + t.name).text(t.name).appendTo(ctypes);
 
-		form.find("#doctog").click(function(_) {
-			form.find(".doc").toggleClass("hide");
+		var cforms = form.find("[name=formula]");
+		for( f in editor.formulas.getList(sheet) )
+			new Element("<option>").attr("value", f.name).text(f.name).appendTo(cforms);
+
+		form.find(".hide").addClass("can-hide");
+		form.find(".doctog").click(function(_) {
+			form.find(".can-hide").toggleClass("hide");
 		});
 
 		if (editForm) {
@@ -179,6 +205,9 @@ class ModalColumnForm extends Modal {
 				form.find("[name=sheet]").val( "" + index);
 			case TCustom(name):
 				form.find("[name=ctype]").val(name);
+			case TInt, TFloat:
+				var f = editor.getColumnProps(column).formula;
+				form.find("[name=formula]").val( f == null ? "" : f );
 			default:
 			}
 		} else {
@@ -208,8 +237,8 @@ class ModalColumnForm extends Modal {
 		close();
 	}
 
-	public function getColumn(base : cdb.Database, sheet : cdb.Sheet, refColumn : cdb.Data.Column) : Column{
-
+	public function getColumn( refColumn : cdb.Data.Column) : Column{
+		var base = editor.base;
 		var v : Dynamic<String> = { };
 		var cols = form.find("input, select, textarea").not("[type=submit]");
 		for( i in cols.elements() )
@@ -286,8 +315,23 @@ class ModalColumnForm extends Modal {
 		case "localizable": c.kind = Localizable;
 		case "script": c.kind = Script;
 		}
+		var props = editor.getColumnProps(c);
+		switch( t ) {
+		case TFloat, TInt:
+			props.formula = form.find("[name=formula]").val();
+			if( props.formula == "" ) props.formula = null;
+		default:
+		}
 		if( t == TId && v.scope != "" ) c.scope = Std.parseInt(v.scope);
 		if( v.doc != "" ) c.documentation = v.doc;
+
+		var hasProp = false;
+		for( f in Reflect.fields(props) )
+			if( Reflect.field(props,f) == null )
+				Reflect.deleteField(props, f);
+			else
+				hasProp = true;
+		c.editor = hasProp ? props : js.Lib.undefined;
 		return c;
 	}