package org.openlca.app.cloud.ui.diff; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.openlca.app.cloud.JsonLoader; import org.openlca.app.cloud.index.DiffType; import org.openlca.app.cloud.ui.diff.DiffResult.DiffResponse; import org.openlca.app.util.UI; public class CommitDiffViewer extends DiffTreeViewer { private List<DiffNode> selected = new ArrayList<>(); // The option fixNewElements will prevent the user to uncheck "NEW" // elements, used in ReferencesResultDialog private boolean fixNewElements; public CommitDiffViewer(Composite parent, JsonLoader jsonLoader, boolean fixNewElements) { super(parent, jsonLoader); this.fixNewElements = fixNewElements; } public void setInitialSelection(Set<String> initialSelection) { selected = findNodes(initialSelection, root); Set<String> expanded = new HashSet<>(); Tree tree = getViewer().getTree(); for (DiffNode node : selected) { if (!node.isModelNode() && !node.isCategoryNode()) continue; String cId = node.getContent().getDataset().categoryRefId; if (cId == null) cId = node.getModelType().name(); if (expanded.contains(cId)) continue; expanded.add(cId); getViewer().reveal(node); } tree.setRedraw(false); setChecked(initialSelection, tree.getItems()); tree.setRedraw(true); } // can't use setChecked(Object[]) for performance reasons. Original // reveals path internally for all elements, which is unnecessary // because this is already done in a more efficient way in // setInitialSelection private void setChecked(Set<String> refIds, TreeItem[] items) { for (TreeItem item : items) { DiffNode node = (DiffNode) item.getData(); if (node != null && !node.isModelTypeNode()) { String refId = node.getContent().getDataset().refId; // null is used as hack to select all if (refIds == null || refIds.contains(refId)) item.setChecked(true); } setChecked(refIds, item.getItems()); } } public void selectAll() { setInitialSelection(null); } private List<DiffNode> findNodes(Set<String> refIds, DiffNode node) { List<DiffNode> elements = new ArrayList<>(); for (DiffNode child : node.children) { if (!child.isModelTypeNode() && child.hasChanged()) { String refId = child.getContent().getDataset().refId; // null is used as hack to select all if (refIds == null || refIds.contains(refId)) elements.add(child); } elements.addAll(findNodes(refIds, child)); } return elements; } @Override protected TreeViewer createViewer(Composite parent) { CheckboxTreeViewer viewer = new CheckboxTreeViewer(parent, SWT.BORDER); configureViewer(viewer, true); viewer.addCheckStateListener((e) -> { DiffNode node = (DiffNode) e.getElement(); if (!isCheckable(node)) { if (e.getChecked()) viewer.setChecked(node, false); return; } if (e.getChecked()) { selected.add(node); } else { if (fixNewElements && node.getContent().local.type == DiffType.NEW) { viewer.setChecked(node, true); return; } selected.remove(node); } }); UI.gridData(viewer.getTree(), true, true); return viewer; } @Override public CheckboxTreeViewer getViewer() { return (CheckboxTreeViewer) super.getViewer(); } private boolean isCheckable(DiffNode node) { if (node.isModelTypeNode()) return false; if (node.getContent().getType() == DiffResponse.NONE) return false; return true; } public List<DiffNode> getChecked() { return selected; } public boolean hasChecked() { return !getChecked().isEmpty(); } }