From 8825e92be49ca190cf585da7c1628804fc5db59f Mon Sep 17 00:00:00 2001 From: Josh Tynjala Date: Mon, 9 Sep 2024 13:20:35 -0700 Subject: [PATCH] GridView, TreeGridView: allow items in dataProvider to be string Similar to ListView and other components, check if item is String and use separate StringMap for those values because they can't be stored in ObjectMap --- src/feathers/controls/GridView.hx | 86 ++++++++++++++++++++------ src/feathers/controls/TreeGridView.hx | 89 +++++++++++++++++++++------ 2 files changed, 136 insertions(+), 39 deletions(-) diff --git a/src/feathers/controls/GridView.hx b/src/feathers/controls/GridView.hx index 46b9f3a2..3fc29573 100644 --- a/src/feathers/controls/GridView.hx +++ b/src/feathers/controls/GridView.hx @@ -8,13 +8,6 @@ package feathers.controls; -import feathers.dragDrop.DragDropManager; -import feathers.dragDrop.DragData; -import feathers.dragDrop.IDropTarget; -import feathers.dragDrop.IDragSource; -import openfl.Lib; -import feathers.layout.IDragDropLayout; -import feathers.events.DragDropEvent; import feathers.controls.dataRenderers.GridViewRowRenderer; import feathers.controls.dataRenderers.IGridViewHeaderRenderer; import feathers.controls.dataRenderers.ItemRenderer; @@ -35,11 +28,17 @@ import feathers.data.GridViewHeaderState; import feathers.data.IFlatCollection; import feathers.data.ISortOrderObserver; import feathers.data.SortOrder; +import feathers.dragDrop.DragData; +import feathers.dragDrop.DragDropManager; +import feathers.dragDrop.IDragSource; +import feathers.dragDrop.IDropTarget; +import feathers.events.DragDropEvent; import feathers.events.FeathersEvent; import feathers.events.FlatCollectionEvent; import feathers.events.GridViewEvent; import feathers.events.TriggerEvent; import feathers.layout.GridViewRowLayout; +import feathers.layout.IDragDropLayout; import feathers.layout.IKeyboardNavigationLayout; import feathers.layout.ILayout; import feathers.layout.ILayoutIndexObject; @@ -56,6 +55,8 @@ import feathers.utils.DisplayUtil; import feathers.utils.ExclusivePointer; import feathers.utils.MathUtil; import haxe.ds.ObjectMap; +import haxe.ds.StringMap; +import openfl.Lib; import openfl.display.DisplayObject; import openfl.display.DisplayObjectContainer; import openfl.display.InteractiveObject; @@ -1194,7 +1195,8 @@ class GridView extends BaseScrollContainer implements IIndexSelector implements private var headerRendererToHeaderState = new ObjectMap(); private var inactiveRowRenderers:Array = []; private var activeRowRenderers:Array = []; - private var dataToRowRenderer = new ObjectMap(); + private var stringDataToRowRenderer = new StringMap(); + private var objectDataToRowRenderer = new ObjectMap(); private var rowRendererToRowState = new ObjectMap(); private var headerStatePool = new ObjectPool(() -> new GridViewHeaderState()); private var rowStatePool = new ObjectPool(() -> new GridViewRowState()); @@ -1484,7 +1486,12 @@ class GridView extends BaseScrollContainer implements IIndexSelector implements if (item == null) { return null; } - var rowRenderer = this.dataToRowRenderer.get(item); + var rowRenderer:GridViewRowRenderer = null; + if ((item is String)) { + rowRenderer = this.stringDataToRowRenderer.get(cast item); + } else { + rowRenderer = this.objectDataToRowRenderer.get(item); + } if (rowRenderer == null) { return null; } @@ -1527,7 +1534,12 @@ class GridView extends BaseScrollContainer implements IIndexSelector implements if (item == null) { return null; } - var rowRenderer = this.dataToRowRenderer.get(item); + var rowRenderer:GridViewRowRenderer = null; + if ((item is String)) { + rowRenderer = this.stringDataToRowRenderer.get(cast item); + } else { + rowRenderer = this.objectDataToRowRenderer.get(item); + } if (rowRenderer == null) { return null; } @@ -1792,8 +1804,12 @@ class GridView extends BaseScrollContainer implements IIndexSelector implements var newColumns:ArrayCollection = null; if (this._dataProvider != null && this._dataProvider.length > 0) { var item = this._dataProvider.get(0); - newColumns = new ArrayCollection(Reflect.fields(item) - .map((fieldName) -> new GridViewColumn(fieldName, (item) -> Std.string(Reflect.getProperty(item, fieldName))))); + newColumns = new ArrayCollection(Reflect.fields(item).map((fieldName) -> { + return new GridViewColumn(fieldName, (item) -> { + var propertyValue = Reflect.getProperty(item, fieldName); + return Std.string(propertyValue); + }); + })); } else { newColumns = new ArrayCollection(); } @@ -2324,7 +2340,11 @@ class GridView extends BaseScrollContainer implements IIndexSelector implements } var item = state.data; this.rowRendererToRowState.remove(rowRenderer); - this.dataToRowRenderer.remove(item); + if ((item is String)) { + this.stringDataToRowRenderer.remove(cast item); + } else { + this.objectDataToRowRenderer.remove(item); + } rowRenderer.removeEventListener(GridViewEvent.CELL_TRIGGER, gridView_rowRenderer_cellTriggerHandler); rowRenderer.removeEventListener(TriggerEvent.TRIGGER, gridView_rowRenderer_triggerHandler); rowRenderer.removeEventListener(MouseEvent.MOUSE_DOWN, gridView_rowRenderer_mouseDownHandler); @@ -2382,7 +2402,12 @@ class GridView extends BaseScrollContainer implements IIndexSelector implements } for (i in this._visibleIndices.start...this._visibleIndices.end + 1) { var item = this._dataProvider.get(i); - var rowRenderer = this.dataToRowRenderer.get(item); + var rowRenderer:GridViewRowRenderer = null; + if ((item is String)) { + rowRenderer = this.stringDataToRowRenderer.get(cast item); + } else { + rowRenderer = this.objectDataToRowRenderer.get(item); + } if (rowRenderer != null) { var state = this.rowRendererToRowState.get(rowRenderer); var changed = this.populateCurrentRowState(item, i, state, this._forceItemStateUpdate); @@ -2437,7 +2462,12 @@ class GridView extends BaseScrollContainer implements IIndexSelector implements rowRenderer.addEventListener(TriggerEvent.TRIGGER, gridView_rowRenderer_triggerHandler); rowRenderer.addEventListener(MouseEvent.MOUSE_DOWN, gridView_rowRenderer_mouseDownHandler); this.rowRendererToRowState.set(rowRenderer, state); - this.dataToRowRenderer.set(state.data, rowRenderer); + var row = state.data; + if ((row is String)) { + this.stringDataToRowRenderer.set(cast row, rowRenderer); + } else { + this.objectDataToRowRenderer.set(row, rowRenderer); + } return rowRenderer; } @@ -2700,7 +2730,13 @@ class GridView extends BaseScrollContainer implements IIndexSelector implements } var changed = this._selectedIndex != result; if (!changed && result != -1) { - var rowRenderer = this.dataToRowRenderer.get(this._dataProvider.get(result)); + var rowRenderer:GridViewRowRenderer = null; + var row = this._dataProvider.get(result); + if ((row is String)) { + rowRenderer = this.stringDataToRowRenderer.get(cast row); + } else { + rowRenderer = this.objectDataToRowRenderer.get(row); + } if (rowRenderer == null) { // if we can't find the item renderer, we need to scroll changed = true; @@ -2807,7 +2843,12 @@ class GridView extends BaseScrollContainer implements IIndexSelector implements targetY = result.y; } else { var row = this._dataProvider.get(rowIndex); - var rowRenderer = this.dataToRowRenderer.get(row); + var rowRenderer:GridViewRowRenderer = null; + if ((row is String)) { + rowRenderer = this.stringDataToRowRenderer.get(cast row); + } else { + rowRenderer = this.objectDataToRowRenderer.get(row); + } if (rowRenderer == null) { return; } @@ -3105,8 +3146,13 @@ class GridView extends BaseScrollContainer implements IIndexSelector implements if (this._virtualCache != null) { this._virtualCache[index] = null; } - var item = this._dataProvider.get(index); - var rowRenderer = this.dataToRowRenderer.get(item); + var row = this._dataProvider.get(index); + var rowRenderer:GridViewRowRenderer = null; + if ((row is String)) { + rowRenderer = this.stringDataToRowRenderer.get(cast row); + } else { + rowRenderer = this.objectDataToRowRenderer.get(row); + } if (rowRenderer == null) { // doesn't exist yet, so we need to do a full invalidation this.setInvalid(DATA); @@ -3118,7 +3164,7 @@ class GridView extends BaseScrollContainer implements IIndexSelector implements return; } rowRenderer.updateCells(); - this.populateCurrentRowState(item, index, state, true); + this.populateCurrentRowState(row, index, state, true); // in order to display the same item with modified properties, this // hack tricks the item renderer into thinking that it has been given // a different item to render. diff --git a/src/feathers/controls/TreeGridView.hx b/src/feathers/controls/TreeGridView.hx index aa95cf4d..b341dcc3 100644 --- a/src/feathers/controls/TreeGridView.hx +++ b/src/feathers/controls/TreeGridView.hx @@ -48,6 +48,7 @@ import feathers.utils.DisplayUtil; import feathers.utils.ExclusivePointer; import feathers.utils.MathUtil; import haxe.ds.ObjectMap; +import haxe.ds.StringMap; import openfl.display.DisplayObject; import openfl.display.DisplayObjectContainer; import openfl.display.InteractiveObject; @@ -961,7 +962,8 @@ class TreeGridView extends BaseScrollContainer implements IDataSelector private var headerRendererToHeaderState = new ObjectMap(); private var inactiveRowRenderers:Array = []; private var activeRowRenderers:Array = []; - private var dataToRowRenderer = new ObjectMap(); + private var stringDataToRowRenderer = new StringMap(); + private var objectDataToRowRenderer = new ObjectMap(); private var rowRendererToRowState = new ObjectMap(); private var headerStatePool = new ObjectPool(() -> new TreeGridViewHeaderState()); private var rowStatePool = new ObjectPool(() -> new TreeGridViewRowState()); @@ -1074,7 +1076,12 @@ class TreeGridView extends BaseScrollContainer implements IDataSelector if (item == null) { return null; } - var rowRenderer = this.dataToRowRenderer.get(item); + var rowRenderer:TreeGridViewRowRenderer = null; + if ((item is String)) { + rowRenderer = this.stringDataToRowRenderer.get(cast item); + } else { + rowRenderer = this.objectDataToRowRenderer.get(item); + } if (rowRenderer == null) { return null; } @@ -1171,7 +1178,12 @@ class TreeGridView extends BaseScrollContainer implements IDataSelector if (item == null) { return null; } - var rowRenderer = this.dataToRowRenderer.get(item); + var rowRenderer:TreeGridViewRowRenderer = null; + if ((item is String)) { + rowRenderer = this.stringDataToRowRenderer.get(cast item); + } else { + rowRenderer = this.objectDataToRowRenderer.get(item); + } if (rowRenderer == null) { return null; } @@ -1429,8 +1441,12 @@ class TreeGridView extends BaseScrollContainer implements IDataSelector var newColumns:ArrayCollection = null; if (this._dataProvider != null && this._dataProvider.getLength() > 0) { var item = this._dataProvider.get([0]); - newColumns = new ArrayCollection(Reflect.fields(item) - .map((fieldName) -> new TreeGridViewColumn(fieldName, (item) -> Std.string(Reflect.getProperty(item, fieldName))))); + newColumns = new ArrayCollection(Reflect.fields(item).map((fieldName) -> { + return new TreeGridViewColumn(fieldName, (item) -> { + var propertyValue = Reflect.getProperty(item, fieldName); + return Std.string(propertyValue); + }); + })); } else { newColumns = new ArrayCollection(); } @@ -1959,9 +1975,13 @@ class TreeGridView extends BaseScrollContainer implements IDataSelector if (state == null) { continue; } - var item = state.data; + var row = state.data; this.rowRendererToRowState.remove(rowRenderer); - this.dataToRowRenderer.remove(item); + if ((row is String)) { + this.stringDataToRowRenderer.remove(cast row); + } else { + this.objectDataToRowRenderer.remove(row); + } rowRenderer.removeEventListener(TreeGridViewEvent.CELL_TRIGGER, treeGridView_rowRenderer_cellTriggerHandler); rowRenderer.removeEventListener(TriggerEvent.TRIGGER, treeGridView_rowRenderer_triggerHandler); rowRenderer.removeEventListener(Event.OPEN, treeGridView_rowRenderer_openHandler); @@ -2043,15 +2063,20 @@ class TreeGridView extends BaseScrollContainer implements IDataSelector return layoutIndex; } - private function findRowRenderer(item:Dynamic, location:Array, layoutIndex:Int):Void { - var rowRenderer = this.dataToRowRenderer.get(item); + private function findRowRenderer(row:Dynamic, location:Array, layoutIndex:Int):Void { + var rowRenderer:TreeGridViewRowRenderer = null; + if ((row is String)) { + rowRenderer = this.stringDataToRowRenderer.get(cast row); + } else { + rowRenderer = this.objectDataToRowRenderer.get(row); + } if (rowRenderer == null) { this._unrenderedLocations.push(location); this._unrenderedLayoutIndices.push(layoutIndex); return; } var state = this.rowRendererToRowState.get(rowRenderer); - var changed = this.populateCurrentRowState(item, location, layoutIndex, state, this._forceItemStateUpdate); + var changed = this.populateCurrentRowState(row, location, layoutIndex, state, this._forceItemStateUpdate); if (changed) { this.updateRowRenderer(rowRenderer, state); } @@ -2103,7 +2128,12 @@ class TreeGridView extends BaseScrollContainer implements IDataSelector rowRenderer.addEventListener(Event.OPEN, treeGridView_rowRenderer_openHandler); rowRenderer.addEventListener(Event.CLOSE, treeGridView_rowRenderer_closeHandler); this.rowRendererToRowState.set(rowRenderer, state); - this.dataToRowRenderer.set(state.data, rowRenderer); + var row = state.data; + if ((row is String)) { + this.stringDataToRowRenderer.set(cast row, rowRenderer); + } else { + this.objectDataToRowRenderer.set(row, rowRenderer); + } this.activeRowRenderers.push(rowRenderer); return rowRenderer; } @@ -2494,8 +2524,14 @@ class TreeGridView extends BaseScrollContainer implements IDataSelector var pendingLocation:Array = null; if (!changed && result != -1) { pendingLocation = this.displayIndexToLocation(result); - var itemRenderer = this.dataToRowRenderer.get(this._dataProvider.get(pendingLocation)); - if (itemRenderer == null) { + var row = this._dataProvider.get(pendingLocation); + var rowRenderer:TreeGridViewRowRenderer = null; + if ((row is String)) { + rowRenderer = this.stringDataToRowRenderer.get(cast row); + } else { + rowRenderer = this.objectDataToRowRenderer.get(row); + } + if (rowRenderer == null) { // if we can't find the item renderer, we need to scroll changed = true; } else if ((this.layout is IScrollLayout)) { @@ -2551,8 +2587,13 @@ class TreeGridView extends BaseScrollContainer implements IDataSelector targetX = result.x; targetY = result.y; } else { - var item = this._dataProvider.get(location); - var rowRenderer = this.dataToRowRenderer.get(item); + var row = this._dataProvider.get(location); + var rowRenderer:TreeGridViewRowRenderer = null; + if ((row is String)) { + rowRenderer = this.stringDataToRowRenderer.get(cast row); + } else { + rowRenderer = this.objectDataToRowRenderer.get(row); + } if (rowRenderer == null) { return; } @@ -2584,7 +2625,12 @@ class TreeGridView extends BaseScrollContainer implements IDataSelector } private function toggleBranchInternal(branch:Dynamic, location:Array, layoutIndex:Int, open:Bool):Int { - var rowRenderer = this.dataToRowRenderer.get(branch); + var rowRenderer:TreeGridViewRowRenderer = null; + if ((branch is String)) { + rowRenderer = this.stringDataToRowRenderer.get(cast branch); + } else { + rowRenderer = this.objectDataToRowRenderer.get(branch); + } var state:TreeGridViewRowState = null; if (rowRenderer != null) { state = this.rowRendererToRowState.get(rowRenderer); @@ -2813,8 +2859,13 @@ class TreeGridView extends BaseScrollContainer implements IDataSelector if (this._virtualCache != null && layoutIndex != -1) { this._virtualCache[layoutIndex] = null; } - var item = this._dataProvider.get(location); - var rowRenderer = this.dataToRowRenderer.get(item); + var row = this._dataProvider.get(location); + var rowRenderer:TreeGridViewRowRenderer = null; + if ((row is String)) { + rowRenderer = this.stringDataToRowRenderer.get(cast row); + } else { + rowRenderer = this.objectDataToRowRenderer.get(row); + } if (rowRenderer == null) { // doesn't exist yet, so we need to do a full invalidation this.setInvalid(DATA); @@ -2826,7 +2877,7 @@ class TreeGridView extends BaseScrollContainer implements IDataSelector return; } rowRenderer.updateCells(); - this.populateCurrentRowState(item, location, layoutIndex, state, true); + this.populateCurrentRowState(row, location, layoutIndex, state, true); // in order to display the same item with modified properties, this // hack tricks the item renderer into thinking that it has been given // a different item to render.