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);
}