diff --git a/source/class/qxl/datagrid/binding/Bindings.js b/source/class/qxl/datagrid/binding/Bindings.js index 2fb2fda..0f4564c 100644 --- a/source/class/qxl/datagrid/binding/Bindings.js +++ b/source/class/qxl/datagrid/binding/Bindings.js @@ -33,7 +33,9 @@ qx.Class.define("qxl.datagrid.binding.Bindings", { * * @param {qx.data.Object} model The model to add the binding to * @param {String} bindingId Id of binding - * @param {String?"binding"} bindingType The type of the binding. Either "binding" or "listener". Defaults to binding. Set to "binding " if this is a binding to a property, or "listener" if it's for a listener added with "addListener". + * @param {String?"binding"} bindingType The type of the binding. Either "binding", "listener", or "callback". + * Defaults to binding. Set to "binding" if this is a binding to a property, or "listener" if it's + * for a listener added with "addListener". */ construct(model, bindingId, bindingType) { super(); @@ -72,18 +74,22 @@ qx.Class.define("qxl.datagrid.binding.Bindings", { * * @param {qx.core.Object} model the object with a binding * @param {*} bindingId the binding ID to release - * @param {String?} bindingType The type of the binding. Either "binding" or "listener". Defaults to auto detect. + * @param {String?} bindingType The type of the binding. Either "binding", "listener", or "callback". Defaults to auto detect. */ add(model, bindingId, bindingType) { if (bindingType === undefined) { if (typeof bindingId == "string") { bindingType = "listener"; + } else if (typeof bindingId == "function") { + bindingType = "callback"; } else { bindingType = "binding"; } } else if (qx.core.Environment.get("qx.debug")) { if (bindingType === "listener") { this.assertTrue(typeof bindingId == "string", "Invalid binding type " + bindingType + " for bindingId " + bindingId); + } else if (bindingType === "callback") { + this.assertTrue(typeof bindingId == "function", "Invalid binding type " + bindingType + " for bindingId " + bindingId); } else { this.assertTrue(typeof bindingId != "string", "Invalid binding type " + bindingType + " for bindingId " + bindingId); } diff --git a/source/class/qxl/datagrid/column/Column.js b/source/class/qxl/datagrid/column/Column.js index 3dc33ce..e7e6001 100644 --- a/source/class/qxl/datagrid/column/Column.js +++ b/source/class/qxl/datagrid/column/Column.js @@ -271,7 +271,10 @@ qx.Class.define("qxl.datagrid.column.Column", { let path = this.getPath(); let bindings = new qxl.datagrid.binding.Bindings(model); if (path) { - if (model) { + if (path == ".") { + widget.setValue(model); + bindings.add(model, () => widget.setValue(null)); + } else if (model) { let bindingId = model.bind(path, widget, "value", this.getBindingOptions()(widget, model)); bindings.add(model, bindingId); } @@ -323,6 +326,19 @@ qx.Class.define("qxl.datagrid.column.Column", { }); }, + /** + * Called to allow the column to update the state of the widget based on the model; + * this is typically used by the expansion column to show the correct icon for + * expanding/collapsing + * + * @param {qx.ui.core.Widget} widget + * @param {qx.core.Object} model + * @param {qxl.datagrid.ui.factory.IWidgetFactory} factory + */ + updateState(widget, model, factory) { + // Nothing to do + }, + /** * Apply for `width` property */ diff --git a/source/class/qxl/datagrid/column/tree/ExpansionColumn.js b/source/class/qxl/datagrid/column/tree/ExpansionColumn.js index 9d7ca55..21d9558 100644 --- a/source/class/qxl/datagrid/column/tree/ExpansionColumn.js +++ b/source/class/qxl/datagrid/column/tree/ExpansionColumn.js @@ -42,6 +42,18 @@ qx.Class.define("qxl.datagrid.column.tree.ExpansionColumn", { return new qxl.datagrid.column.tree.ExpansionWidget(); }, + /** + * @Override + */ + updateState(widget, model, factory) { + let state = factory.getDataSource().getNodeStateFor(model); + if (state == null) { + return; + } + widget.setIndentationLevel(state.level); + widget.setState(state.state); + }, + /** * @Override */ @@ -49,7 +61,6 @@ qx.Class.define("qxl.datagrid.column.tree.ExpansionColumn", { let bindings = super.bindWidget(widget, model); let state = factory.getDataSource().getNodeStateFor(model); if (state == null) { - debugger; return bindings; } widget.setIndentationLevel(state.level); diff --git a/source/class/qxl/datagrid/column/tree/ExpansionWidget.js b/source/class/qxl/datagrid/column/tree/ExpansionWidget.js index 72d2c4f..dee6ff4 100644 --- a/source/class/qxl/datagrid/column/tree/ExpansionWidget.js +++ b/source/class/qxl/datagrid/column/tree/ExpansionWidget.js @@ -28,17 +28,20 @@ qx.Class.define("qxl.datagrid.column.tree.ExpansionWidget", { construct() { super(); this._setLayout(new qxl.datagrid.column.tree.ExpansionLayout()); - this._add(this.getChildControl("expander")); + let expander = this.getChildControl("expander"); + this._add(expander); this._add(this.getChildControl("icon")); this._add(this.getChildControl("label")); - this.addListener("tap", evt => { + expander.addListener("tap", evt => { let state = this.getState(); if (state == "open") { this.setState("closed"); } else if (state == "closed") { this.setState("open"); } + evt.preventDefault(); + evt.stopPropagation(); }); }, @@ -182,7 +185,7 @@ qx.Class.define("qxl.datagrid.column.tree.ExpansionWidget", { let expander = this.getChildControl("expander"); if (!icon) { - expander.setVisibility("hidden"); + expander.setVisibility("excluded"); } else { expander.set({ source: icon, @@ -198,8 +201,7 @@ qx.Class.define("qxl.datagrid.column.tree.ExpansionWidget", { switch (id) { case "expander": var expander = new qx.ui.basic.Image().set({ - visibility: "hidden", - anonymous: true + visibility: "hidden" }); return expander; diff --git a/source/class/qxl/datagrid/ui/WidgetPane.js b/source/class/qxl/datagrid/ui/WidgetPane.js index bc4cff7..4c00ca8 100644 --- a/source/class/qxl/datagrid/ui/WidgetPane.js +++ b/source/class/qxl/datagrid/ui/WidgetPane.js @@ -46,7 +46,7 @@ qx.Class.define("qxl.datagrid.ui.WidgetPane", { this.setDataSource(dataSource); } this._setLayout(new qxl.datagrid.ui.layout.Fixed()); - this.addListener("tap", this.__onTap, this, true); + this.addListener("tap", this.__onTap, this); }, properties: { @@ -200,6 +200,8 @@ qx.Class.define("qxl.datagrid.ui.WidgetPane", { this._add(child); qx.ui.core.queue.Layout.add(child); this.__widgetFactory.bindWidget(child, model); + } else { + this.__widgetFactory.updateState(child, model); } const callbackArguments = [model, child, currentRelativePosition, currentAbsolutePosition]; diff --git a/source/class/qxl/datagrid/ui/factory/AbstractWidgetFactory.js b/source/class/qxl/datagrid/ui/factory/AbstractWidgetFactory.js index a744d1e..071b77a 100644 --- a/source/class/qxl/datagrid/ui/factory/AbstractWidgetFactory.js +++ b/source/class/qxl/datagrid/ui/factory/AbstractWidgetFactory.js @@ -123,6 +123,14 @@ qx.Class.define("qxl.datagrid.ui.factory.AbstractWidgetFactory", { widget.dispose(); }, + /** + * @override + */ + updateState(widget, model) { + let bindingData = widget.getUserData("qxl.datagrid.factory.AbstractWidgetFactory.bindingData"); + bindingData.column.updateState(widget, model, this); + }, + /** * Called to create a widget * diff --git a/source/class/qxl/datagrid/ui/factory/IWidgetFactory.js b/source/class/qxl/datagrid/ui/factory/IWidgetFactory.js index 0987ade..da7648d 100644 --- a/source/class/qxl/datagrid/ui/factory/IWidgetFactory.js +++ b/source/class/qxl/datagrid/ui/factory/IWidgetFactory.js @@ -60,6 +60,16 @@ qx.Interface.define("qxl.datagrid.ui.factory.IWidgetFactory", { */ unbindWidget(widget) {}, + /** + * Called to allow the column to update the state of the widget based on the model; + * this is typically used by the expansion column to show the correct icon for + * expanding/collapsing + * + * @param {qx.ui.core.Widget} widget + * @param {qx.core.Object} model + */ + updateState(widget, model) {}, + /** * Obtains the model which is bound to the widget *