/** * Expands the given item. Calling this method will have no effect if the * item is already expanded or if it has no children. The index is provided * by the client-side or calculated from a full data request. * {@code syncAndRefresh} indicates whether the changes should be * synchronised to the client and the data provider be notified. * * @param item * the item to expand * @param index * the index of the item * @param syncAndRefresh * {@code true} if the changes should be synchronised to the * client and the data provider should be notified of the * changes, {@code false} otherwise. */ private void doExpand(T item, Integer index, boolean syncAndRefresh) { Range addedRows = mapper.expand(item, index); if (syncAndRefresh) { if (!reset && !addedRows.isEmpty()) { getClientRpc().insertRows(addedRows.getStart(), addedRows.length()); Stream<T> children = mapper.fetchItems(item, Range.withLength(0, addedRows.length())); pushData(addedRows.getStart(), children.collect(Collectors.toList())); } refresh(item); } }
/** * Expands the given item. * * @param item * the item to expand * @param position * the index of the item * @return range of rows added by expanding the item */ public Range expand(T item, Integer position) { if (doExpand(item) && position != null) { return Range.withLength(position + 1, (int) getHierarchy(item, false).count()); } return Range.emptyRange(); }
/** * Gets a stream of items in the form of a flattened hierarchy from the * back-end and filter the wanted results from the list. * * @param range * the requested item range * @return the stream of items */ public Stream<T> fetchItems(Range range) { return getHierarchy(null).skip(range.getStart()).limit(range.length()); }
/** * Collapses the given item and removes its sub-hierarchy. Calling this * method will have no effect if the row is already collapsed. The index is * provided by the client-side or calculated from a full data request. * {@code syncAndRefresh} indicates whether the changes should be * synchronised to the client and the data provider be notified. * * @param item * the item to collapse * @param index * the index of the item * @param syncAndRefresh * {@code true} if the changes should be synchronised to the * client and the data provider should be notified of the * changes, {@code false} otherwise. */ private void doCollapse(T item, Integer index, boolean syncAndRefresh) { Range removedRows = mapper.collapse(item, index); if (syncAndRefresh) { if (!reset && !removedRows.isEmpty()) { getClientRpc().removeRows(removedRows.getStart(), removedRows.length()); } refresh(item); } }
@Override public Range collapse(T item, Integer position) { int removedChildren; if (itemInteractionAvailability.test(item)) { final Map<T, Set<T>> relationMap = accessChildMap(); final Set<T> children = relationMap.get(item); removedChildren = (int) children.stream().filter(child -> !itemInteractionAvailability.test(child)).count(); } else { getDataProvider().refreshAll(); return Range.emptyRange(); } final Range toCollapse = super.collapse(item, position); return Range.between(toCollapse.getStart(), toCollapse.getEnd() + removedChildren); }
@Override public void onDataAvailable(DataAvailableEvent event) { int current = cell.getRowIndex(); int min = Math.min(current, previous); int max = Math.max(current, previous); if (!ctrlOrMeta) { model.deselectAll(); } Range dataAvailable = event.getAvailableRows(); Range selected = Range.between(min, max + 1); Range[] partition = selected.partitionWith(dataAvailable); for (int i = partition[1].getStart(); i < partition[1].getEnd(); ++i) { model.select(grid.getDataSource().getRow(i)); } if (handler != null) { handler.removeHandler(); } } }
/** * Initially and in the case of a reset all data should be pushed to the * client. */ @Override public void beforeClientResponse(boolean initial) { super.beforeClientResponse(initial); if (initial && getPushRows().isEmpty()) { // Make sure rows are pushed when component is attached. setPushRows(Range.withLength(0, getMinPushSize())); } sendDataToClient(initial); }
@Override public List<T> fetchItemsWithRange(int offset, int limit) { // Instead of adding logic to this class, delegate request to the // separate object handling hierarchies. return mapper.fetchItems(Range.withLength(offset, limit)) .collect(Collectors.toList()); }
/** * Gets the stream of direct children for given node. * * @param parent * the parent node * @return the stream of direct children */ private Stream<T> getDirectChildren(T parent) { return doFetchDirectChildren(parent, Range.between(0, getDataProvider() .getChildCount(new HierarchicalQuery<>(filter, parent)))); }
/** * Gets a stream of children for the given item in the form of a flattened * hierarchy from the back-end and filter the wanted results from the list. * * @param parent * the parent item for the fetch * @param range * the requested item range * @return the stream of items */ public Stream<T> fetchItems(T parent, Range range) { return getHierarchy(parent, false).skip(range.getStart()) .limit(range.length()); }
/** * Request the given rows to be available on the client side. * * @param firstRowIndex * the index of the first requested row * @param numberOfRows * the number of requested rows * @param firstCachedRowIndex * the index of the first cached row * @param cacheSize * the number of cached rows * @since 8.0.6 */ protected void onRequestRows(int firstRowIndex, int numberOfRows, int firstCachedRowIndex, int cacheSize) { setPushRows(Range.withLength(firstRowIndex, numberOfRows)); markAsDirty(); }
setPushRows(Range.between(0, getMinPushSize())); if (isAttached()) { attachDataProviderListener();
if (!requestedRows.isEmpty()) { int offset = requestedRows.getStart(); int limit = requestedRows.length(); setPushRows(Range.withLength(0, 0)); reset = triggerReset; updatedData.clear();
/** * Generic method for finding direct children of a given parent, limited by * given range. * * @param parent * the parent * @param range * the range of direct children to return * @return the requested children of the given parent */ @SuppressWarnings({ "rawtypes", "unchecked" }) private Stream<T> doFetchDirectChildren(T parent, Range range) { return getDataProvider().fetchChildren(new HierarchicalQuery( range.getStart(), range.length(), getBackEndSorting(), getInMemorySorting(), getFilter(), parent)); }
/** * Collapses the given item. * * @param item * the item to collapse * @param position * the index of the item * * @return range of rows removed by collapsing the item */ public Range collapse(T item, Integer position) { Range removedRows = Range.emptyRange(); if (isExpanded(item)) { if (position != null) { removedRows = Range.withLength(position + 1, (int) getHierarchy(item, false).count()); } expandedItemIds.remove(getDataProvider().getId(item)); } return removedRows; }
private void pushRowData(int firstRowToPush, int numberOfRows, int firstCachedRowIndex, int cacheSize) { Range newRange = Range.withLength(firstRowToPush, numberOfRows); Range cached = Range.withLength(firstCachedRowIndex, cacheSize); Range fullRange = newRange; if (!cached.isEmpty()) { fullRange = newRange.combineWith(cached); } List<?> itemIds = container.getItemIds(fullRange.getStart(), fullRange.length()); JsonArray rows = Json.createArray(); // Offset the index to match the wanted range. int diff = 0; if (!cached.isEmpty() && newRange.getStart() > cached.getStart()) { diff = cached.length(); } for (int i = 0; i < newRange.length() && i + diff < itemIds.size(); ++i) { Object itemId = itemIds.get(i + diff); Item item = container.getItem(itemId); rows.set(i, getRowData(getGrid().getColumns(), itemId, item)); } rpc.setRowData(firstRowToPush, rows); activeItemHandler.addActiveItems(itemIds); }
if (!requestedRows.isEmpty()) { int offset = requestedRows.getStart(); int limit = requestedRows.length() + getMinPushSize(); List<T> rowsToPush = fetchItemsWithRange(offset, limit); int lastIndex = offset + rowsToPush.size(); rowsToAdd + (rowsToPush.size() == limit ? 1 : 0)); knownSize = lastIndex; } else if (rowsToPush.size() < requestedRows.length()) { requestedRows.length() - rowsToPush.size(), knownSize - lastIndex); knownSize = lastIndex; setPushRows(Range.withLength(0, 0)); getUpdatedData().clear();