Skip to content

Commit

Permalink
Improve message shown for expandable node
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
iloveeclipse committed Aug 21, 2023
1 parent 9911469 commit ed71f53
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -232,4 +232,5 @@ ConfigureColumnsDialog_up = &Up
ConfigureColumnsDialog_down = Dow&n

# org.eclipse.jface.viewers.internal.ExpandableNode
ExpandableNode.defaultLabel = Show {0}...{1} ({2})
ExpandableNode.defaultLabel = Show next {0} items from remaining {1}
ExpandableNode.showRemaining = Show remaining {0} item{1}
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,7 @@ final Object[] applyItemsLimit(Object parent, Object[] sorted) {
// limit the number of items to be created. sorted always gets the remaining
// elements to be created.
final int itemsLimit = getItemsLimit();
if (itemsLimit <= 0 || sorted.length <= itemsLimit) {
if (itemsLimit <= 0 || sorted.length <= itemsLimit || sorted.length == itemsLimit + 1) {
return sorted;
}

Expand Down Expand Up @@ -958,6 +958,12 @@ Object[] getChildrenWithLimitApplied(final Object parent, Item[] visibleChildren
// there can any number of elements in the model. but viewer was showing
// ExpandableNode. Then return the same length.
if (visibleChildren[visibleItemsLength - 1].getData() instanceof ExpandableNode) {
if (sortedAll.length == visibleItemsLength) {
// model returns now exact the visible number of elements (note, last visible is
// expandable node): just return all without expandable node
return sortedAll;
}

// Now we need exactly previously visible length.
Object[] subArray = new Object[visibleItemsLength];
System.arraycopy(sortedAll, 0, subArray, 0, visibleItemsLength - 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ public int getOffset() {
return startOffSet;
}

/**
* @return limit value
*/
public int getLimit() {
return limit;
}

/**
* This method returns those children of the current node which are supposed to
* be not created / shown yet in the viewer.
Expand Down Expand Up @@ -157,15 +164,21 @@ public Object[] getAllElements() {
/**
* {@return label shown for the node in the viewer}
*/
@SuppressWarnings("boxing")
public String getLabel() {
Integer start = Integer.valueOf(this.start + 1);
Integer length = Integer.valueOf(orginalArray.length + addedElements.size());
int next = this.start + this.limit;
if (next > orginalArray.length + addedElements.size()) {
next = orginalArray.length + addedElements.size();
int all = orginalArray.length + addedElements.size();
int remaining = all - start;
String label;
if (remaining > limit) {
if (remaining == limit + 1) {
String suffix = remaining == 1 ? "" : "s"; //$NON-NLS-1$ //$NON-NLS-2$
return JFaceResources.format("ExpandableNode.showRemaining", remaining, suffix); //$NON-NLS-1$ ;
}
label = JFaceResources.format("ExpandableNode.defaultLabel", limit, remaining); //$NON-NLS-1$
} else {
String suffix = remaining == 1 ? "" : "s"; //$NON-NLS-1$ //$NON-NLS-2$
label = JFaceResources.format("ExpandableNode.showRemaining", remaining, suffix); //$NON-NLS-1$
}
Integer nextBlock = Integer.valueOf(next);
String label = JFaceResources.format("ExpandableNode.defaultLabel", start, nextBlock, length); //$NON-NLS-1$
return label;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class BaseLimitBasedViewerTest extends ViewerTestCase {

List<DataModel> rootModel;
protected static final int VIEWER_LIMIT = 4;
protected static final int DEFAULT_ELEMENTS_COUNT = 40;

public BaseLimitBasedViewerTest(String name) {
super(name);
Expand All @@ -37,16 +38,16 @@ protected StructuredViewer createViewer(Composite parent) {
return null;
}

protected static List<DataModel> createModel() {
protected static List<DataModel> createModel(final int maxCount) {
List<DataModel> rootModel = new ArrayList<>();
for (int i = 0; i < 40; i++) {
for (int i = 0; i < maxCount; i++) {
if (i % 2 == 0) {
DataModel rootLevel = new DataModel(Integer.valueOf(i));
for (int j = 0; j < 40; j++) {
for (int j = 0; j < maxCount; j++) {
if (j % 2 == 0) {
DataModel level1 = new DataModel(Integer.valueOf(j));
level1.parent = rootLevel;
for (int k = 0; k < 40; k++) {
for (int k = 0; k < maxCount; k++) {
if (k % 2 == 0) {
DataModel level2 = new DataModel(Integer.valueOf(k));
level2.parent = level1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.internal.ExpandableNode;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
Expand All @@ -49,6 +50,7 @@ public void testLimitedItemsCreatedWithExpansionNode() {
}

public void testAddElement() {
processEvents();
Table table = tableViewer.getTable();
assertLimitedItems(table.getItems());
DataModel data = (DataModel) table.getItems()[2].getData();
Expand All @@ -73,9 +75,31 @@ public void testAddElement() {
assertLimitedItems(table.getItems());
data = (DataModel) table.getItems()[2].getData();
assertEquals("wrong item is found at given location", Integer.valueOf(3), data.id);

// Add elements one by one
rootModel = createModel(1);
fViewer.setInput(rootModel);
processEvents();

while (rootModel.size() < VIEWER_LIMIT) {
DataModel element = new DataModel(Integer.valueOf(rootModel.size() + 1));
rootModel.add(element);
tableViewer.add(element);
processEvents();
TableItem[] items = table.getItems();
Object last = items[items.length - 1].getData();
assertFalse("Last item shouln't be expandable: " + last, tableViewer.isExpandableNode(last));
}

DataModel element = new DataModel(Integer.valueOf(rootModel.size() + 1));
rootModel.add(element);
tableViewer.add(element);
processEvents();
assertLimitedItems(table.getItems());
}

public void testRemoveElement() {
processEvents();
Table table = tableViewer.getTable();
assertLimitedItems(table.getItems());
DataModel data = (DataModel) table.getItems()[2].getData();
Expand All @@ -85,19 +109,35 @@ public void testRemoveElement() {
DataModel removed = rootModel.remove(2);
tableViewer.remove(removed);
processEvents();
// check items and label after addition.
// check items and label after removal.
assertLimitedItems(table.getItems());
data = (DataModel) table.getItems()[2].getData();
assertEquals("wrong item is found at given location", Integer.valueOf(6), data.id);

// this element must not be visible only expandable node label must be updated.
DataModel removed1 = rootModel.remove(7);
tableViewer.remove(removed1);
removed = rootModel.remove(7);
tableViewer.remove(removed);
processEvents();
// check items and label after addition.
// check items and label after removal.
assertLimitedItems(table.getItems());
data = (DataModel) table.getItems()[2].getData();
assertEquals("wrong item is found at given location", Integer.valueOf(6), data.id);

while (rootModel.size() > VIEWER_LIMIT + 1) {
removed = rootModel.remove(rootModel.size() - 1);
tableViewer.remove(removed);

processEvents();
TableItem[] items = table.getItems();
// check items and label after removal.
if (rootModel.size() > VIEWER_LIMIT + 1) {
assertLimitedItems(items);
} else {
Object last = items[items.length - 1].getData();
assertFalse("Last item shouln't be expandable: " + last, tableViewer.isExpandableNode(last));
}
}

}

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

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

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

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

@SuppressWarnings("boxing")
private String calculateExpandableLabel(Object data) {
ExpandableNode node = (ExpandableNode) data;
int all = rootModel.size();
int remaining = all - node.getOffset();
String expectedLabel;
if (remaining > node.getLimit()) {
if (remaining == node.getLimit() + 1) {
String suffix = remaining == 1 ? "" : "s"; //$NON-NLS-1$ //$NON-NLS-2$
return JFaceResources.format("ExpandableNode.showRemaining", remaining, suffix); //$NON-NLS-1$ ;
}
expectedLabel = JFaceResources.format("ExpandableNode.defaultLabel", node.getLimit(), remaining); //$NON-NLS-1$
} else {
String suffix = remaining == 1 ? "" : "s"; //$NON-NLS-1$
expectedLabel = JFaceResources.format("ExpandableNode.showRemaining", remaining, suffix); //$NON-NLS-1$
}
return expectedLabel;
}

public void testSetInput() {
List<DataModel> rootModel = new ArrayList<>();
DataModel rootLevel = new DataModel(Integer.valueOf(100));
rootModel.add(rootLevel);
tableViewer.setInput(rootModel);
processEvents();
assertEquals("there must be only one item", 1, tableViewer.getTable().getItems().length);
tableViewer.setInput(createModel());
tableViewer.setInput(createModel(DEFAULT_ELEMENTS_COUNT));
processEvents();
assertLimitedItems(tableViewer.getTable().getItems());
}
Expand Down Expand Up @@ -309,7 +368,7 @@ protected StructuredViewer createViewer(Composite parent) {

@Override
protected void setInput() {
rootModel = createModel();
rootModel = createModel(DEFAULT_ELEMENTS_COUNT);
fViewer.setInput(rootModel);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,14 @@ public void testRemoveItemsAtParent() {
}

public void testRemoveItem() {
processEvents();
treeViewer.expandAll();
processEvents();
DataModel firstEle = rootModel.remove(0);
TreeItem firstItem = treeViewer.getTree().getItem(0);
assertEquals("element contains unexpected data", firstEle, firstItem.getData());
treeViewer.remove(firstEle);
processEvents();
firstEle = rootModel.get(0);
firstItem = treeViewer.getTree().getItem(0);
assertEquals("element contains unexpected data", firstEle, firstItem.getData());
Expand Down Expand Up @@ -243,7 +247,7 @@ public void testSetInput() {
treeViewer.setInput(rootModel);
processEvents();
assertEquals("there must be only one item", 1, treeViewer.getTree().getItems().length);
treeViewer.setInput(createModel());
treeViewer.setInput(createModel(DEFAULT_ELEMENTS_COUNT));
processEvents();
assertLimitedItems();
}
Expand Down Expand Up @@ -279,7 +283,7 @@ protected StructuredViewer createViewer(Composite parent) {

@Override
protected void setInput() {
rootModel = createModel();
rootModel = createModel(DEFAULT_ELEMENTS_COUNT);
treeViewer.setInput(rootModel);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,14 +242,25 @@ private void assertLimitedItems(int currentLimit, int realInputSize, Item[] item
if (nextBlock > realInputSize) {
nextBlock = realInputSize;
}
String expLabel = JFaceResources.format("ExpandableNode.defaultLabel", currentLimit + 1, nextBlock,
realInputSize);

assertEquals("Incorrect text for expand node", expLabel, lastItem.getText().trim());
String expLabel = calculateExpandableLabel(lastItem.getData(), realInputSize);
ExpandableNode node = (ExpandableNode) lastItem.getData();
assertEquals(expLabel, node.getLabel());
}

@SuppressWarnings("boxing")
private String calculateExpandableLabel(Object data, int realInputSize) {
ExpandableNode node = (ExpandableNode) data;
int remaining = realInputSize - node.getOffset();
String expectedLabel;
if (remaining > node.getLimit()) {
expectedLabel = JFaceResources.format("ExpandableNode.defaultLabel", node.getLimit(), remaining); //$NON-NLS-1$
} else {
String suffix = remaining == 1 ? "" : "s"; //$NON-NLS-1$
expectedLabel = JFaceResources.format("ExpandableNode.showRemaining", remaining, suffix); //$NON-NLS-1$
}
return expectedLabel;
}

private void setNewViewerLimit(int viewerLimit) {
preferenceStore.setValue(IWorkbenchPreferenceConstants.LARGE_VIEW_LIMIT, viewerLimit);
int readViewLimit = preferenceStore.getInt(IWorkbenchPreferenceConstants.LARGE_VIEW_LIMIT);
Expand Down

0 comments on commit ed71f53

Please sign in to comment.