Skip to content

Commit ed71f53

Browse files
committed
Improve message shown for expandable node
- In case there are more then limit (X) items hidden, will show "Show next X items from remaining Y" - In case there are less then limit (X) items hidden, will show Show remaining X item(s) - If elements added not "one by one" to the viewer, avoids showing expandable node if only one element would be hidden Fixes #1012 Fixes #1028
1 parent 9911469 commit ed71f53

File tree

7 files changed

+126
-31
lines changed

7 files changed

+126
-31
lines changed

bundles/org.eclipse.jface/src/org/eclipse/jface/messages.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,4 +232,5 @@ ConfigureColumnsDialog_up = &Up
232232
ConfigureColumnsDialog_down = Dow&n
233233

234234
# org.eclipse.jface.viewers.internal.ExpandableNode
235-
ExpandableNode.defaultLabel = Show {0}...{1} ({2})
235+
ExpandableNode.defaultLabel = Show next {0} items from remaining {1}
236+
ExpandableNode.showRemaining = Show remaining {0} item{1}

bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/ColumnViewer.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,7 @@ final Object[] applyItemsLimit(Object parent, Object[] sorted) {
872872
// limit the number of items to be created. sorted always gets the remaining
873873
// elements to be created.
874874
final int itemsLimit = getItemsLimit();
875-
if (itemsLimit <= 0 || sorted.length <= itemsLimit) {
875+
if (itemsLimit <= 0 || sorted.length <= itemsLimit || sorted.length == itemsLimit + 1) {
876876
return sorted;
877877
}
878878

@@ -958,6 +958,12 @@ Object[] getChildrenWithLimitApplied(final Object parent, Item[] visibleChildren
958958
// there can any number of elements in the model. but viewer was showing
959959
// ExpandableNode. Then return the same length.
960960
if (visibleChildren[visibleItemsLength - 1].getData() instanceof ExpandableNode) {
961+
if (sortedAll.length == visibleItemsLength) {
962+
// model returns now exact the visible number of elements (note, last visible is
963+
// expandable node): just return all without expandable node
964+
return sortedAll;
965+
}
966+
961967
// Now we need exactly previously visible length.
962968
Object[] subArray = new Object[visibleItemsLength];
963969
System.arraycopy(sortedAll, 0, subArray, 0, visibleItemsLength - 1);

bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/internal/ExpandableNode.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ public int getOffset() {
9898
return startOffSet;
9999
}
100100

101+
/**
102+
* @return limit value
103+
*/
104+
public int getLimit() {
105+
return limit;
106+
}
107+
101108
/**
102109
* This method returns those children of the current node which are supposed to
103110
* be not created / shown yet in the viewer.
@@ -157,15 +164,21 @@ public Object[] getAllElements() {
157164
/**
158165
* {@return label shown for the node in the viewer}
159166
*/
167+
@SuppressWarnings("boxing")
160168
public String getLabel() {
161-
Integer start = Integer.valueOf(this.start + 1);
162-
Integer length = Integer.valueOf(orginalArray.length + addedElements.size());
163-
int next = this.start + this.limit;
164-
if (next > orginalArray.length + addedElements.size()) {
165-
next = orginalArray.length + addedElements.size();
169+
int all = orginalArray.length + addedElements.size();
170+
int remaining = all - start;
171+
String label;
172+
if (remaining > limit) {
173+
if (remaining == limit + 1) {
174+
String suffix = remaining == 1 ? "" : "s"; //$NON-NLS-1$ //$NON-NLS-2$
175+
return JFaceResources.format("ExpandableNode.showRemaining", remaining, suffix); //$NON-NLS-1$ ;
176+
}
177+
label = JFaceResources.format("ExpandableNode.defaultLabel", limit, remaining); //$NON-NLS-1$
178+
} else {
179+
String suffix = remaining == 1 ? "" : "s"; //$NON-NLS-1$ //$NON-NLS-2$
180+
label = JFaceResources.format("ExpandableNode.showRemaining", remaining, suffix); //$NON-NLS-1$
166181
}
167-
Integer nextBlock = Integer.valueOf(next);
168-
String label = JFaceResources.format("ExpandableNode.defaultLabel", start, nextBlock, length); //$NON-NLS-1$
169182
return label;
170183
}
171184

tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/BaseLimitBasedViewerTest.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class BaseLimitBasedViewerTest extends ViewerTestCase {
2727

2828
List<DataModel> rootModel;
2929
protected static final int VIEWER_LIMIT = 4;
30+
protected static final int DEFAULT_ELEMENTS_COUNT = 40;
3031

3132
public BaseLimitBasedViewerTest(String name) {
3233
super(name);
@@ -37,16 +38,16 @@ protected StructuredViewer createViewer(Composite parent) {
3738
return null;
3839
}
3940

40-
protected static List<DataModel> createModel() {
41+
protected static List<DataModel> createModel(final int maxCount) {
4142
List<DataModel> rootModel = new ArrayList<>();
42-
for (int i = 0; i < 40; i++) {
43+
for (int i = 0; i < maxCount; i++) {
4344
if (i % 2 == 0) {
4445
DataModel rootLevel = new DataModel(Integer.valueOf(i));
45-
for (int j = 0; j < 40; j++) {
46+
for (int j = 0; j < maxCount; j++) {
4647
if (j % 2 == 0) {
4748
DataModel level1 = new DataModel(Integer.valueOf(j));
4849
level1.parent = rootLevel;
49-
for (int k = 0; k < 40; k++) {
50+
for (int k = 0; k < maxCount; k++) {
5051
if (k % 2 == 0) {
5152
DataModel level2 = new DataModel(Integer.valueOf(k));
5253
level2.parent = level1;

tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/TableViewerWithLimitTest.java

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.eclipse.jface.viewers.StructuredSelection;
2626
import org.eclipse.jface.viewers.StructuredViewer;
2727
import org.eclipse.jface.viewers.TableViewer;
28+
import org.eclipse.jface.viewers.internal.ExpandableNode;
2829
import org.eclipse.swt.SWT;
2930
import org.eclipse.swt.graphics.Rectangle;
3031
import org.eclipse.swt.widgets.Composite;
@@ -49,6 +50,7 @@ public void testLimitedItemsCreatedWithExpansionNode() {
4950
}
5051

5152
public void testAddElement() {
53+
processEvents();
5254
Table table = tableViewer.getTable();
5355
assertLimitedItems(table.getItems());
5456
DataModel data = (DataModel) table.getItems()[2].getData();
@@ -73,9 +75,31 @@ public void testAddElement() {
7375
assertLimitedItems(table.getItems());
7476
data = (DataModel) table.getItems()[2].getData();
7577
assertEquals("wrong item is found at given location", Integer.valueOf(3), data.id);
78+
79+
// Add elements one by one
80+
rootModel = createModel(1);
81+
fViewer.setInput(rootModel);
82+
processEvents();
83+
84+
while (rootModel.size() < VIEWER_LIMIT) {
85+
DataModel element = new DataModel(Integer.valueOf(rootModel.size() + 1));
86+
rootModel.add(element);
87+
tableViewer.add(element);
88+
processEvents();
89+
TableItem[] items = table.getItems();
90+
Object last = items[items.length - 1].getData();
91+
assertFalse("Last item shouln't be expandable: " + last, tableViewer.isExpandableNode(last));
92+
}
93+
94+
DataModel element = new DataModel(Integer.valueOf(rootModel.size() + 1));
95+
rootModel.add(element);
96+
tableViewer.add(element);
97+
processEvents();
98+
assertLimitedItems(table.getItems());
7699
}
77100

78101
public void testRemoveElement() {
102+
processEvents();
79103
Table table = tableViewer.getTable();
80104
assertLimitedItems(table.getItems());
81105
DataModel data = (DataModel) table.getItems()[2].getData();
@@ -85,19 +109,35 @@ public void testRemoveElement() {
85109
DataModel removed = rootModel.remove(2);
86110
tableViewer.remove(removed);
87111
processEvents();
88-
// check items and label after addition.
112+
// check items and label after removal.
89113
assertLimitedItems(table.getItems());
90114
data = (DataModel) table.getItems()[2].getData();
91115
assertEquals("wrong item is found at given location", Integer.valueOf(6), data.id);
92116

93117
// this element must not be visible only expandable node label must be updated.
94-
DataModel removed1 = rootModel.remove(7);
95-
tableViewer.remove(removed1);
118+
removed = rootModel.remove(7);
119+
tableViewer.remove(removed);
96120
processEvents();
97-
// check items and label after addition.
121+
// check items and label after removal.
98122
assertLimitedItems(table.getItems());
99123
data = (DataModel) table.getItems()[2].getData();
100124
assertEquals("wrong item is found at given location", Integer.valueOf(6), data.id);
125+
126+
while (rootModel.size() > VIEWER_LIMIT + 1) {
127+
removed = rootModel.remove(rootModel.size() - 1);
128+
tableViewer.remove(removed);
129+
130+
processEvents();
131+
TableItem[] items = table.getItems();
132+
// check items and label after removal.
133+
if (rootModel.size() > VIEWER_LIMIT + 1) {
134+
assertLimitedItems(items);
135+
} else {
136+
Object last = items[items.length - 1].getData();
137+
assertFalse("Last item shouln't be expandable: " + last, tableViewer.isExpandableNode(last));
138+
}
139+
}
140+
101141
}
102142

103143
public void testClickExpandableNode() {
@@ -109,10 +149,10 @@ public void testClickExpandableNode() {
109149
Item[] itemsBefore = table.getItems();
110150
assertEquals("There are more/less items rendered than viewer limit", VIEWER_LIMIT * 2 + 1, itemsBefore.length);
111151
Item item = itemsBefore[itemsBefore.length - 1];
112-
assertTrue("Last node must be an Expandable Node", tableViewer.isExpandableNode(item.getData()));
152+
Object data = item.getData();
153+
assertTrue("Last node must be an Expandable Node", tableViewer.isExpandableNode(data));
113154

114-
String expected = JFaceResources.format("ExpandableNode.defaultLabel", Integer.valueOf(VIEWER_LIMIT * 2 + 1),
115-
Integer.valueOf(VIEWER_LIMIT * 3), Integer.valueOf(rootModel.size()));
155+
String expected = calculateExpandableLabel(data);
116156
assertEquals("Expandable node has an incorrect text", expected, item.getText());
117157

118158
// click until all expandable nodes are expanded.
@@ -220,21 +260,40 @@ public void testRefresh() {
220260
private void assertLimitedItems(TableItem[] itemsBefore) {
221261
assertEquals("There are more/less items rendered than viewer limit", VIEWER_LIMIT + 1, itemsBefore.length);
222262
TableItem tableItem = itemsBefore[itemsBefore.length - 1];
223-
assertTrue("Last node must be an Expandable Node", tableViewer.isExpandableNode(tableItem.getData()));
263+
Object data = tableItem.getData();
264+
assertTrue("Last node must be an Expandable Node", tableViewer.isExpandableNode(data));
224265

225-
String expectedLabel = JFaceResources.format("ExpandableNode.defaultLabel", Integer.valueOf(VIEWER_LIMIT + 1),
226-
Integer.valueOf(VIEWER_LIMIT + VIEWER_LIMIT), Integer.valueOf(rootModel.size()));
266+
String expectedLabel = calculateExpandableLabel(data);
227267
assertEquals("Expandable node has an incorrect text", expectedLabel, tableItem.getText());
228268
}
229269

270+
@SuppressWarnings("boxing")
271+
private String calculateExpandableLabel(Object data) {
272+
ExpandableNode node = (ExpandableNode) data;
273+
int all = rootModel.size();
274+
int remaining = all - node.getOffset();
275+
String expectedLabel;
276+
if (remaining > node.getLimit()) {
277+
if (remaining == node.getLimit() + 1) {
278+
String suffix = remaining == 1 ? "" : "s"; //$NON-NLS-1$ //$NON-NLS-2$
279+
return JFaceResources.format("ExpandableNode.showRemaining", remaining, suffix); //$NON-NLS-1$ ;
280+
}
281+
expectedLabel = JFaceResources.format("ExpandableNode.defaultLabel", node.getLimit(), remaining); //$NON-NLS-1$
282+
} else {
283+
String suffix = remaining == 1 ? "" : "s"; //$NON-NLS-1$
284+
expectedLabel = JFaceResources.format("ExpandableNode.showRemaining", remaining, suffix); //$NON-NLS-1$
285+
}
286+
return expectedLabel;
287+
}
288+
230289
public void testSetInput() {
231290
List<DataModel> rootModel = new ArrayList<>();
232291
DataModel rootLevel = new DataModel(Integer.valueOf(100));
233292
rootModel.add(rootLevel);
234293
tableViewer.setInput(rootModel);
235294
processEvents();
236295
assertEquals("there must be only one item", 1, tableViewer.getTable().getItems().length);
237-
tableViewer.setInput(createModel());
296+
tableViewer.setInput(createModel(DEFAULT_ELEMENTS_COUNT));
238297
processEvents();
239298
assertLimitedItems(tableViewer.getTable().getItems());
240299
}
@@ -309,7 +368,7 @@ protected StructuredViewer createViewer(Composite parent) {
309368

310369
@Override
311370
protected void setInput() {
312-
rootModel = createModel();
371+
rootModel = createModel(DEFAULT_ELEMENTS_COUNT);
313372
fViewer.setInput(rootModel);
314373
}
315374

tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/TreeViewerWithLimitTest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,14 @@ public void testRemoveItemsAtParent() {
180180
}
181181

182182
public void testRemoveItem() {
183+
processEvents();
184+
treeViewer.expandAll();
185+
processEvents();
183186
DataModel firstEle = rootModel.remove(0);
184187
TreeItem firstItem = treeViewer.getTree().getItem(0);
185188
assertEquals("element contains unexpected data", firstEle, firstItem.getData());
186189
treeViewer.remove(firstEle);
190+
processEvents();
187191
firstEle = rootModel.get(0);
188192
firstItem = treeViewer.getTree().getItem(0);
189193
assertEquals("element contains unexpected data", firstEle, firstItem.getData());
@@ -243,7 +247,7 @@ public void testSetInput() {
243247
treeViewer.setInput(rootModel);
244248
processEvents();
245249
assertEquals("there must be only one item", 1, treeViewer.getTree().getItems().length);
246-
treeViewer.setInput(createModel());
250+
treeViewer.setInput(createModel(DEFAULT_ELEMENTS_COUNT));
247251
processEvents();
248252
assertLimitedItems();
249253
}
@@ -279,7 +283,7 @@ protected StructuredViewer createViewer(Composite parent) {
279283

280284
@Override
281285
protected void setInput() {
282-
rootModel = createModel();
286+
rootModel = createModel(DEFAULT_ELEMENTS_COUNT);
283287
treeViewer.setInput(rootModel);
284288
}
285289

tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/preferences/ViewerItemsLimitTest.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,14 +242,25 @@ private void assertLimitedItems(int currentLimit, int realInputSize, Item[] item
242242
if (nextBlock > realInputSize) {
243243
nextBlock = realInputSize;
244244
}
245-
String expLabel = JFaceResources.format("ExpandableNode.defaultLabel", currentLimit + 1, nextBlock,
246-
realInputSize);
247-
248-
assertEquals("Incorrect text for expand node", expLabel, lastItem.getText().trim());
245+
String expLabel = calculateExpandableLabel(lastItem.getData(), realInputSize);
249246
ExpandableNode node = (ExpandableNode) lastItem.getData();
250247
assertEquals(expLabel, node.getLabel());
251248
}
252249

250+
@SuppressWarnings("boxing")
251+
private String calculateExpandableLabel(Object data, int realInputSize) {
252+
ExpandableNode node = (ExpandableNode) data;
253+
int remaining = realInputSize - node.getOffset();
254+
String expectedLabel;
255+
if (remaining > node.getLimit()) {
256+
expectedLabel = JFaceResources.format("ExpandableNode.defaultLabel", node.getLimit(), remaining); //$NON-NLS-1$
257+
} else {
258+
String suffix = remaining == 1 ? "" : "s"; //$NON-NLS-1$
259+
expectedLabel = JFaceResources.format("ExpandableNode.showRemaining", remaining, suffix); //$NON-NLS-1$
260+
}
261+
return expectedLabel;
262+
}
263+
253264
private void setNewViewerLimit(int viewerLimit) {
254265
preferenceStore.setValue(IWorkbenchPreferenceConstants.LARGE_VIEW_LIMIT, viewerLimit);
255266
int readViewLimit = preferenceStore.getInt(IWorkbenchPreferenceConstants.LARGE_VIEW_LIMIT);

0 commit comments

Comments
 (0)