Mercurial > dive4elements > river
diff gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DatacageWidget.java @ 9220:e3c2ae1887e8
Allow to filter contents of datacage on client side.
Allow to override column label of datacage
Some code cleanup
author | gernotbelger |
---|---|
date | Wed, 04 Jul 2018 12:00:51 +0200 |
parents | 93da474506e7 |
children | 84397da33d17 |
line wrap: on
line diff
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DatacageWidget.java Wed Jul 04 10:46:37 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DatacageWidget.java Wed Jul 04 12:00:51 2018 +0200 @@ -8,468 +8,409 @@ package org.dive4elements.river.client.client.ui; -import com.google.gwt.core.client.GWT; - -import com.google.gwt.user.client.rpc.AsyncCallback; - -import com.smartgwt.client.types.SelectionStyle; -import com.smartgwt.client.types.TreeModelType; - -import com.smartgwt.client.util.SC; - -import com.smartgwt.client.widgets.Button; - -import com.smartgwt.client.widgets.events.ClickEvent; -import com.smartgwt.client.widgets.events.ClickHandler; - -import com.smartgwt.client.widgets.grid.HoverCustomizer; -import com.smartgwt.client.widgets.grid.ListGridRecord; - -import com.smartgwt.client.widgets.grid.events.RecordDoubleClickEvent; -import com.smartgwt.client.widgets.grid.events.RecordDoubleClickHandler; - -import com.smartgwt.client.widgets.layout.VLayout; - -import com.smartgwt.client.widgets.tree.Tree; -import com.smartgwt.client.widgets.tree.TreeGrid; -import com.smartgwt.client.widgets.tree.TreeNode; - import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.MissingResourceException; import java.util.Stack; import org.dive4elements.river.client.client.Config; import org.dive4elements.river.client.client.FLYSConstants; - import org.dive4elements.river.client.client.event.DatacageDoubleClickHandler; import org.dive4elements.river.client.client.event.DatacageHandler; - import org.dive4elements.river.client.client.services.MetaDataService; import org.dive4elements.river.client.client.services.MetaDataServiceAsync; - -import org.dive4elements.river.client.shared.model.Artifact; import org.dive4elements.river.client.shared.model.AttrList; import org.dive4elements.river.client.shared.model.DataCageNode; import org.dive4elements.river.client.shared.model.DataCageTree; import org.dive4elements.river.client.shared.model.ToLoad; import org.dive4elements.river.client.shared.model.User; +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.smartgwt.client.types.SelectionStyle; +import com.smartgwt.client.types.TreeModelType; +import com.smartgwt.client.util.SC; +import com.smartgwt.client.widgets.Button; +import com.smartgwt.client.widgets.events.ClickEvent; +import com.smartgwt.client.widgets.events.ClickHandler; +import com.smartgwt.client.widgets.grid.HoverCustomizer; +import com.smartgwt.client.widgets.grid.ListGridRecord; +import com.smartgwt.client.widgets.grid.events.RecordDoubleClickEvent; +import com.smartgwt.client.widgets.grid.events.RecordDoubleClickHandler; +import com.smartgwt.client.widgets.layout.VLayout; +import com.smartgwt.client.widgets.tree.Tree; +import com.smartgwt.client.widgets.tree.TreeGrid; +import com.smartgwt.client.widgets.tree.TreeNode; + // TODO: refactor, extract ~DataCageGrid /** * Display tree of, for example, previous calculations and allows * selection in order to access/clone these. */ -public class DatacageWidget -extends VLayout -{ +public class DatacageWidget extends VLayout { public static final int MAX_OPEN = 30; - protected MetaDataServiceAsync metaDataService = - GWT.create(MetaDataService.class); - - protected FLYSConstants messages = - GWT.create(FLYSConstants.class); - - protected Artifact artifact; - protected User user; - protected String outs; - protected String parameters; - - protected TreeGrid treeGrid; - protected Tree tree; - - protected ToLoad toLoad; - - protected List<DatacageHandler> handlers; - protected List<DatacageDoubleClickHandler> doubleHandlers; - - /** Layout to show spinning wheel of joy. */ - protected VLayout lockScreen; - - - public DatacageWidget() { - handlers = new ArrayList<DatacageHandler>(); - doubleHandlers = new ArrayList<DatacageDoubleClickHandler>(); + public interface DatacageFilter { + boolean accept(DataCageNode node); } - - public DatacageWidget(Artifact artifact, User user) { - this(artifact, user, null); - } - - public DatacageWidget(Artifact artifact, User user, String outs) { - this(artifact, user, outs, true); - } + public static final DatacageFilter ACCEPT_ALL_FILTER = new DatacageFilter() { + @Override + public boolean accept(final DataCageNode node) { + return true; + } + }; - public DatacageWidget( - Artifact artifact, - User user, - String outs, - boolean showButton - ) { - this(artifact, user, outs, null, showButton); - } - + private final MetaDataServiceAsync metaDataService = GWT.create(MetaDataService.class); - public DatacageWidget( - Artifact artifact, - User user, - String outs, - String parameters, - boolean showButton - ) { - this(); + private final FLYSConstants messages = GWT.create(FLYSConstants.class); - this.artifact = artifact; - this.user = user; - this.outs = outs; - this.parameters = parameters; + private final List<DatacageHandler> handlers = new ArrayList<DatacageHandler>(); - toLoad = new ToLoad(); + private final List<DatacageDoubleClickHandler> doubleHandlers = new ArrayList<DatacageDoubleClickHandler>(); + + private final TreeGrid treeGrid; + + private Tree tree; + + private ToLoad toLoad; + + /** Layout to show spinning wheel of joy. */ + private VLayout lockScreen; + + private DataCageTree dcTree; + + private DatacageFilter filter = ACCEPT_ALL_FILTER; + + private DatacageWidgetData data; + + public DatacageWidget(final DatacageWidgetData data) { + + this.data = data; + + this.toLoad = new ToLoad(); setWidth100(); - tree = new Tree(); - tree.setModelType(TreeModelType.CHILDREN); - tree.setNameProperty("name"); - tree.setIdField("id"); - tree.setChildrenProperty("children-nodes"); - tree.setShowRoot(false); + this.treeGrid = new TreeGrid(); - treeGrid = new TreeGrid(); - treeGrid.setLoadDataOnDemand(false); - treeGrid.setWidth100(); - treeGrid.setHeight100(); - treeGrid.setShowRoot(false); - treeGrid.setNodeIcon("[SKIN]/../blank.gif"); - treeGrid.setShowConnectors(true); - treeGrid.setLoadingMessage(messages.databasket_loading()); - treeGrid.setEmptyMessage(messages.databasket_loading()); - treeGrid.setLoadingDataMessage(messages.databasket_loading()); + final String columnLabel = this.data.getColumnLabel(); + if (columnLabel != null) + this.treeGrid.setTreeFieldTitle(columnLabel); - treeGrid.setHoverMoveWithMouse(true); - treeGrid.setCanHover(true); - treeGrid.setShowHover(true); - treeGrid.setHoverOpacity(75); - treeGrid.setHoverWidth(120); + this.treeGrid.setLoadDataOnDemand(false); + this.treeGrid.setWidth100(); + this.treeGrid.setHeight100(); + this.treeGrid.setShowRoot(false); + this.treeGrid.setNodeIcon("[SKIN]/../blank.gif"); + this.treeGrid.setShowConnectors(true); + this.treeGrid.setLoadingMessage(this.messages.databasket_loading()); + this.treeGrid.setLoadingDataMessage(this.messages.databasket_loading()); - treeGrid.setHoverCustomizer(new HoverCustomizer() { + // FIXME: other message + this.treeGrid.setEmptyMessage(this.messages.databasket_loading()); + + this.treeGrid.setHoverMoveWithMouse(true); + this.treeGrid.setCanHover(true); + this.treeGrid.setShowHover(true); + this.treeGrid.setHoverOpacity(75); + this.treeGrid.setHoverWidth(120); + + this.treeGrid.setHoverCustomizer(new HoverCustomizer() { @Override - public String hoverHTML(Object value, - ListGridRecord record, - int rowNum, - int colNum - ) { - if(record instanceof TreeNode) { - TreeNode hoveredTreeNode = (TreeNode)record; + public String hoverHTML(final Object value, final ListGridRecord record, final int rowNum, final int colNum) { + if (record instanceof TreeNode) { + final TreeNode hoveredTreeNode = (TreeNode) record; String info = hoveredTreeNode.getAttribute("info"); if (info == null) { info = hoveredTreeNode.getName(); } return info; } - else { - return "";// should not happen - } + + return "";// should not happen } }); - treeGrid.addRecordDoubleClickHandler(new RecordDoubleClickHandler() { + this.treeGrid.addRecordDoubleClickHandler(new RecordDoubleClickHandler() { @Override - public void onRecordDoubleClick(RecordDoubleClickEvent event) { + public void onRecordDoubleClick(final RecordDoubleClickEvent event) { doubleClickedOnTree(event); } }); - addMember(treeGrid); + addMember(this.treeGrid); - if (showButton) { + if (data.isShowButton()) addMember(createPlusButton()); - } triggerTreeBuilding(); } + public void setFilter(final DatacageFilter filter) { + assert (filter != null); + + this.filter = filter; + + if (this.dcTree != null) + updateTree(this.dcTree); + } + /** Disable input, show spinning wheel of joy. */ - public void lockUI() { - lockScreen = ScreenLock.lockUI(this, lockScreen); + private void lockUI() { + this.lockScreen = ScreenLock.lockUI(this, this.lockScreen); } /** Enable input, remove grey, remove spinning wheel of joy. */ - public void unlockUI() { - ScreenLock.unlockUI(this, lockScreen); + protected final void unlockUI() { + ScreenLock.unlockUI(this, this.lockScreen); } /** - * @param handler Handler to be added (notified on add-action). + * Sets whether more than one item can be selected. + * + * @param multi + * if true, allow mutliple selections. */ - public DatacageWidget(Artifact artifact, User user, String outs, - DatacageHandler handler) { - this(artifact, user, outs); - this.addDatacageHandler(handler); - } - - - public DatacageWidget( - Artifact artifact, - User user, - String outs, - DatacageHandler handler, - String parameters - ) { - this(artifact, user, outs, handler); - this.parameters = parameters; - } - - - /** - * Sets whether more than one item can be selected. - * @param multi if true, allow mutliple selections. - */ - public void setIsMutliSelectable(boolean multi) { + public void setIsMutliSelectable(final boolean multi) { if (multi) { - treeGrid.setSelectionType(SelectionStyle.MULTIPLE); - } - else { - treeGrid.setSelectionType(SelectionStyle.SINGLE); + this.treeGrid.setSelectionType(SelectionStyle.MULTIPLE); + } else { + this.treeGrid.setSelectionType(SelectionStyle.SINGLE); } } - /** - * @param handler Handler to be added (notified on add-action). + * @param handler + * Handler to be added (notified on add-action). */ - public void addDatacageHandler(DatacageHandler handler) { - if (!handlers.contains(handler)) { - handlers.add(handler); - } - } - - - /** - * @param h Handler to be added (notified on Double click on node). - */ - public void addDatacageDoubleClickHandler(DatacageDoubleClickHandler h) { - if (!doubleHandlers.contains(h)) { - doubleHandlers.add(h); + public void addDatacageHandler(final DatacageHandler handler) { + if (!this.handlers.contains(handler)) { + this.handlers.add(handler); } } + /** + * @param h + * Handler to be added (notified on Double click on node). + */ + public void addDatacageDoubleClickHandler(final DatacageDoubleClickHandler h) { + if (!this.doubleHandlers.contains(h)) { + this.doubleHandlers.add(h); + } + } /** - * @param handler Handler to remove from list. + * @param handler + * Handler to remove from list. */ - public void removeDatacageHandler(DatacageHandler handler) { - handlers.remove(handler); + public void removeDatacageHandler(final DatacageHandler handler) { + this.handlers.remove(handler); } - - public ToLoad getToLoad() { - return toLoad; - } - - public ToLoad getSelection() { // Reset content of toLoads. - toLoad = new ToLoad(); + this.toLoad = new ToLoad(); - if (treeGrid == null) { - return toLoad; + if (this.treeGrid == null) { + return this.toLoad; } - ListGridRecord [] selection = treeGrid.getSelectedRecords(); + final ListGridRecord[] selection = this.treeGrid.getSelectedRecords(); if (selection != null) { - for (ListGridRecord record: selection) { + for (final ListGridRecord record : selection) { if (record instanceof TreeNode) { - collectToLoads((TreeNode)record); + collectToLoads((TreeNode) record); } } } - return toLoad; + return this.toLoad; } - public List<TreeNode> getPlainSelection() { - ListGridRecord [] selection = treeGrid.getSelectedRecords(); - List<TreeNode> nodes = new ArrayList<TreeNode>(); + final ListGridRecord[] selection = this.treeGrid.getSelectedRecords(); + final List<TreeNode> nodes = new ArrayList<TreeNode>(); if (selection != null) { - for (ListGridRecord record: selection) { + for (final ListGridRecord record : selection) { if (record instanceof TreeNode) { - nodes.add((TreeNode)record); + nodes.add((TreeNode) record); } } } return nodes; } - /** * Returns the titles of selected items (if any). */ public String[] getSelectionTitles() { - if (treeGrid == null) { + if (this.treeGrid == null) { return new String[] {}; } - ListGridRecord [] selection = treeGrid.getSelectedRecords(); + final ListGridRecord[] selection = this.treeGrid.getSelectedRecords(); if (selection == null) { return new String[] {}; } - List<String> titleList = new ArrayList<String>(); - for (ListGridRecord record: selection) { + final List<String> titleList = new ArrayList<String>(); + for (final ListGridRecord record : selection) { if (record instanceof TreeNode) { - titleList.add(((TreeNode)record).getAttribute("name")); + titleList.add(((TreeNode) record).getAttribute("name")); } } return titleList.toArray(new String[titleList.size()]); } - /** * Callback for add-button. * Fires to load for every selected element and handler. */ - public void plusClicked() { + protected final void plusClicked() { if (!getSelection().isEmpty()) { fireToLoad(); } } - - protected Button createPlusButton() { - Button plusBtn = new Button(messages.datacageAdd()); + private Button createPlusButton() { + final Button plusBtn = new Button(this.messages.datacageAdd()); plusBtn.addClickHandler(new ClickHandler() { @Override - public void onClick(ClickEvent event) { + public void onClick(final ClickEvent event) { plusClicked(); } }); return plusBtn; } - - protected void fireToLoad() { - for (DatacageHandler handler: handlers) { - handler.toLoad(toLoad); + private void fireToLoad() { + for (final DatacageHandler handler : this.handlers) { + handler.toLoad(this.toLoad); } } - /** Notify DatacageDoubleClickHandlers that a doubleclick happened. */ - protected void fireOnDoubleClick() { - for (DatacageDoubleClickHandler handler: doubleHandlers) { - handler.onDoubleClick(toLoad); + private void fireOnDoubleClick() { + for (final DatacageDoubleClickHandler handler : this.doubleHandlers) { + handler.onDoubleClick(this.toLoad); } } - - protected void doubleClickedOnTree(RecordDoubleClickEvent event) { - TreeNode node = (TreeNode)event.getRecord(); + protected final void doubleClickedOnTree(final RecordDoubleClickEvent event) { + final TreeNode node = (TreeNode) event.getRecord(); collectToLoads(node); fireOnDoubleClick(); } - /** * Adds to toLoad, from info in node. * Afterwards, add all children of node to stack to parse (next time * collectToLoads is called). */ - protected void collectToLoads(TreeNode node) { - Stack<TreeNode> stack = new Stack<TreeNode>(); + private void collectToLoads(TreeNode node) { + final Stack<TreeNode> stack = new Stack<TreeNode>(); stack.push(node); while (!stack.isEmpty()) { node = stack.pop(); - String factory = node.getAttribute("factory"); + final String factory = node.getAttribute("factory"); if (factory != null) { // we need at least a factory - String artifact = node.getAttribute("artifact-id"); - String out = node.getAttribute("out"); - String name = node.getAttribute("facet"); - String ids = node.getAttribute("ids"); - String displayname = node.getAttribute("name"); - String targetOut = node.getAttribute("target_out"); + final String artifact = node.getAttribute("artifact-id"); + final String out = node.getAttribute("out"); + final String name = node.getAttribute("facet"); + final String ids = node.getAttribute("ids"); + final String displayname = node.getAttribute("name"); + final String targetOut = node.getAttribute("target_out"); String debugAttributeValues = ""; - for (String attr: node.getAttributes()) { - debugAttributeValues += ("[" + attr +": " - + node.getAttributeAsString(attr) + "] "); + for (final String attr : node.getAttributes()) { + debugAttributeValues += ("[" + attr + ": " + node.getAttributeAsString(attr) + "] "); } - GWT.log("DatacageWidget.collectToLoad, attributes are " - + debugAttributeValues); + GWT.log("DatacageWidget.collectToLoad, attributes are " + debugAttributeValues); - toLoad.add(artifact, - factory, - out, - name, - ids, - displayname, - targetOut); + this.toLoad.add(artifact, factory, out, name, ids, displayname, targetOut); } - TreeNode [] children = tree.getChildren(node); + final TreeNode[] children = this.tree.getChildren(node); if (children != null) { - for (TreeNode child: children) { + for (final TreeNode child : children) { stack.push(child); } } } } - /** Get meta-data and populate tree with it. */ - protected void triggerTreeBuilding() { - Config config = Config.getInstance(); - String locale = config.getLocale(); - - String artifactId = artifact.getUuid(); - String userId = (user != null) ? user.identifier() : null; - + private void triggerTreeBuilding() { lockUI(); - metaDataService.getMetaData( - locale, - artifactId, - userId, - outs, - parameters, - new AsyncCallback<DataCageTree>() { - @Override - public void onFailure(Throwable caught) { - GWT.log("Could not load meta data."); - SC.warn(caught.getMessage()); - unlockUI(); - } + final String locale = Config.getInstance().getLocale(); - @Override - public void onSuccess(DataCageTree dcTree) { - GWT.log("Successfully loaded meta data."); - IdGenerator idGenerator = new IdGenerator(); - DataCageNode dcRoot = dcTree.getRoot(); - TreeNode root = buildRecursiveChildren( - dcRoot, idGenerator); - tree.setRoot(root); + final String artifactId = this.data.getArtifact().getUuid(); + final User user = this.data.getUser(); + final String userId = user != null ? user.identifier() : null; + final String outs = this.data.getOuts(); + final String parameters = this.data.getParameters(); - TreeNode[] nodes = tree.getChildren(root); - for (TreeNode node: nodes) { - if (node.getAttribute("factory") == null && - !tree.hasChildren(node)) { - node.setIsFolder(true); - } - } + this.metaDataService.getMetaData(locale, artifactId, userId, outs, parameters, new AsyncCallback<DataCageTree>() { + @Override + public void onFailure(final Throwable caught) { + GWT.log("Could not load meta data."); + SC.warn(caught.getMessage()); + unlockUI(); + } - if (idGenerator.current() < MAX_OPEN) { - tree.openAll(); - } - treeGrid.setData(tree); - unlockUI(); - } - }); + @Override + public void onSuccess(final DataCageTree dcData) { + GWT.log("Successfully loaded meta data."); + + setDatacageData(dcData); + unlockUI(); + } + }); + } + + protected final void setDatacageData(final DataCageTree dcTree) { + + this.dcTree = dcTree; + + if (this.tree != null) + this.tree.destroy(); + + updateTree(this.dcTree); + } + + private void updateTree(final DataCageTree data) { + + this.tree = new Tree(); + this.tree.setModelType(TreeModelType.CHILDREN); + this.tree.setNameProperty("name"); + this.tree.setIdField("id"); + this.tree.setChildrenProperty("children-nodes"); + this.tree.setShowRoot(false); + + final IdGenerator idGenerator = new IdGenerator(); + final DataCageNode dcRoot = data.getRoot(); + final TreeNode root = buildRecursiveChildren(dcRoot, idGenerator); + if (root != null) { + this.tree.setRoot(root); + + // FIXME: why is this necessary? an it only happens for the first level... + final TreeNode[] nodes = this.tree.getChildren(root); + for (final TreeNode node : nodes) { + if (node.getAttribute("factory") == null && !this.tree.hasChildren(node)) + node.setIsFolder(true); + } + } + + if (idGenerator.current() < MAX_OPEN) + this.tree.openAll(); + + this.treeGrid.setData(this.tree); } private static final class IdGenerator { @@ -479,11 +420,11 @@ } public int next() { - return current++; + return this.current++; } public int current() { - return current; + return this.current; } } // class IdGenerator @@ -492,48 +433,58 @@ return s; } - s = s.substring(2, s.length()-1); + s = s.substring(2, s.length() - 1); try { - return messages.getString(s); + return this.messages.getString(s); } - catch (MissingResourceException mre) { + catch (final MissingResourceException mre) { GWT.log("cannot find i18n for + '" + s + "'"); return s; } } - protected TreeNode buildRecursiveChildren( - DataCageNode node, - IdGenerator idGenerator - ) { - TreeNode tn = new TreeNode(); + private TreeNode buildRecursiveChildren(final DataCageNode node, final IdGenerator idGenerator) { + + if (!this.filter.accept(node)) + return null; + + final List<DataCageNode> children = node.getChildren(); + + final Collection<TreeNode> tns = new ArrayList<TreeNode>(); + + if (children != null && !children.isEmpty()) { + + for (final DataCageNode child : children) { + + final TreeNode childNode = buildRecursiveChildren(child, idGenerator); + if (childNode != null) + tns.add(childNode); + } + + /* if we should have children, but all got filtered, hide this node as well */ + if (tns.isEmpty()) + return null; + } + + final TreeNode tn = new TreeNode(); tn.setAttribute("id", idGenerator.next()); - List<DataCageNode> children = node.getChildren(); - - if (children != null) { - TreeNode [] tns = new TreeNode[children.size()]; - for (int i = 0; i < tns.length; ++i) { - DataCageNode child = children.get(i); - tns[i] = buildRecursiveChildren(child, idGenerator); - } - tn.setAttribute("children-nodes", tns); - } + if (!tns.isEmpty()) + tn.setAttribute("children-nodes", tns.toArray(new TreeNode[tns.size()])); tn.setAttribute("name", i18n(node.getDescription())); tn.setAttribute("facet", node.getName()); - AttrList attrs = node.getAttributes(); + final AttrList attrs = node.getAttributes(); if (attrs != null) { for (int i = 0, N = attrs.size(); i < N; ++i) { - String key = attrs.getKey(i); - String value = attrs.getValue(i); + final String key = attrs.getKey(i); + final String value = attrs.getValue(i); tn.setAttribute(key, value); } } return tn; } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : +} \ No newline at end of file