diff --git a/o.n.swing.outline/apichanges.xml b/o.n.swing.outline/apichanges.xml --- a/o.n.swing.outline/apichanges.xml +++ b/o.n.swing.outline/apichanges.xml @@ -217,6 +217,23 @@ + + + RowMapping is enhanced to cache the transformed value. + + + + + + In order to make the row sorting faster and more robust, RowMapping + class is enhanced to cache the transformed value from the requested + column. A new constructor with ETable argument and method + getTransformedValue(int) are added. It prevents from altering of the + values during the sorting process. + + + + diff --git a/o.n.swing.outline/manifest.mf b/o.n.swing.outline/manifest.mf --- a/o.n.swing.outline/manifest.mf +++ b/o.n.swing.outline/manifest.mf @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.swing.outline OpenIDE-Module-Localizing-Bundle: org/netbeans/swing/outline/Bundle.properties -OpenIDE-Module-Specification-Version: 1.17 +OpenIDE-Module-Specification-Version: 1.18 diff --git a/o.n.swing.outline/src/org/netbeans/swing/etable/ETable.java b/o.n.swing.outline/src/org/netbeans/swing/etable/ETable.java --- a/o.n.swing.outline/src/org/netbeans/swing/etable/ETable.java +++ b/o.n.swing.outline/src/org/netbeans/swing/etable/ETable.java @@ -1714,7 +1714,7 @@ List rows = new ArrayList(); for (int i = 0; i < noRows; i++) { if (acceptByQuickFilter(model, i)) { - rows.add(new RowMapping(i, model)); + rows.add(new RowMapping(i, model, this)); } } Collections.sort(rows, c); @@ -2245,6 +2245,17 @@ private int originalIndex; // table model of my table private TableModel model; + // The table + private ETable table; + // The cached transformed value + private Object transformed = TRANSFORMED_NONE; + // The column of the transformed value + private int transformedColumn; + // When values from more columns are requested, the transformed values + // are stored in this array + private Object[] allTransformed = null; + + private static final Object TRANSFORMED_NONE = new Object(); /** * Create a new table row mapping. @@ -2255,6 +2266,21 @@ originalIndex = index; this.model = model; } + + /** + * Create a new table row mapping. + * @param index The row index + * @param model The table model + * @param table The table. This argument needs to be set when + * {@link #getTransformedValue(int)} is to be used. + * @since 1.18 + */ + public RowMapping(int index, TableModel model, ETable table) { + originalIndex = index; + this.model = model; + this.table = table; + } + /** * Get the model row index. * @return The model row index @@ -2262,14 +2288,65 @@ public int getModelRowIndex() { return originalIndex; } + /** * Get the model object at the row index of this mapping and the given column. * @param column The column * @return The model object + * @see {@link #getTransformedValue(int)} */ public Object getModelObject(int column) { return model.getValueAt(originalIndex, column); } + + /** + * Get the transformed value. This method assures that we retrieve every + * value only once per any number of calls. The table needs to be set + * in order to be able to transform the value, see + * {@link #RowMapping(int, javax.swing.table.TableModel, org.netbeans.swing.etable.ETable)}. + * + * @param column The column + * @return The transformed value. It returns the cached value of + * table.transformValue(getModelObject(column)). + * @throws IllegalStateException when table is not set + * @since 1.18 + */ + public Object getTransformedValue(int column) { + if (table == null) { + throw new IllegalStateException("The table was not set."); + } + Object value; + if (TRANSFORMED_NONE == transformed) { + value = transformed = table.transformValue(getModelObject(column)); + transformedColumn = column; + } else if (allTransformed != null) { + if (allTransformed.length <= column) { + Object[] newTransformed = new Object[column + 1]; + System.arraycopy(allTransformed, 0, newTransformed, 0, allTransformed.length); + for (int i = allTransformed.length; i < newTransformed.length; i++) { + newTransformed[i] = TRANSFORMED_NONE; + } + allTransformed = newTransformed; + } + if (TRANSFORMED_NONE == allTransformed[column]) { + value = allTransformed[column] = table.transformValue(getModelObject(column)); + } else { + value = allTransformed[column]; + } + } else if (transformedColumn != column) { + int n = Math.max(transformedColumn, column) + 1; + allTransformed = new Object[n]; + for (int i = 0; i < n; i++) { + allTransformed[i] = TRANSFORMED_NONE; + } + allTransformed[transformedColumn] = transformed; + value = allTransformed[column] = table.transformValue(getModelObject(column)); + } else { + value = transformed; + } + return value; + } + } /** diff --git a/o.n.swing.outline/src/org/netbeans/swing/etable/ETableColumn.java b/o.n.swing.outline/src/org/netbeans/swing/etable/ETableColumn.java --- a/o.n.swing.outline/src/org/netbeans/swing/etable/ETableColumn.java +++ b/o.n.swing.outline/src/org/netbeans/swing/etable/ETableColumn.java @@ -523,10 +523,8 @@ @SuppressWarnings("unchecked") @Override public int compare(ETable.RowMapping rm1, ETable.RowMapping rm2) { - Object obj1 = rm1.getModelObject(column); - Object obj2 = rm2.getModelObject(column); - obj1 = table.transformValue(obj1); - obj2 = table.transformValue(obj2); + Object obj1 = rm1.getTransformedValue(column); + Object obj2 = rm2.getTransformedValue(column); if (obj1 == null && obj2 == null) { return 0; } diff --git a/o.n.swing.outline/src/org/netbeans/swing/outline/Outline.java b/o.n.swing.outline/src/org/netbeans/swing/outline/Outline.java --- a/o.n.swing.outline/src/org/netbeans/swing/outline/Outline.java +++ b/o.n.swing.outline/src/org/netbeans/swing/outline/Outline.java @@ -480,7 +480,7 @@ for (int i = 0; i < noRows; i++) { if (acceptByQuickFilter(model, i)) { TreePath tp = getLayoutCache().getPathForRow(i); - RowMapping rm = new RowMapping(i, model); + RowMapping rm = new RowMapping(i, model, this); tsm.put(tp, rm); rows.add(rm); }