From ca9eec91a358904986d5fb03000d02c1eca470c1 Mon Sep 17 00:00:00 2001 From: Costantino Perciante Date: Mon, 7 Nov 2016 17:47:06 +0000 Subject: [PATCH] still working on the twin column selection widget git-svn-id: http://svn.d4science-ii.research-infrastructures.eu/gcube/trunk/portlets/widgets/ckan-metadata-publisher-widget@133944 82a268e6-3cf1-43bd-a215-b396298e98cf --- .../TwinColumnSelection/ResourceCellLeft.java | 40 +++ .../ResourceCellRight.java | 32 ++ .../ResourceElementBean.java | 133 ++++++++ .../ShowMorePagerPanel.java | 102 ++++++ .../TwinColumnSelectionMainPanel.java | 313 +++++++++++++++++- .../TwinColumnSelectionMainPanel.ui.xml | 34 +- 6 files changed, 626 insertions(+), 28 deletions(-) create mode 100644 src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ResourceCellLeft.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ResourceCellRight.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ResourceElementBean.java create mode 100644 src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ShowMorePagerPanel.java diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ResourceCellLeft.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ResourceCellLeft.java new file mode 100644 index 0000000..01d030f --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ResourceCellLeft.java @@ -0,0 +1,40 @@ +package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection; + +import com.google.gwt.cell.client.AbstractCell; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; + +/** + * Cell that renders left side panel objects + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class ResourceCellLeft extends AbstractCell{ + + @Override + public void render(com.google.gwt.cell.client.Cell.Context context, + ResourceElementBean value, SafeHtmlBuilder sb) { + + // Do not render an object if + // - is null; + // - has been moved to the other side; + // - the parent folder is not null; + if (value == null || value.isMovedToRight()) { + return; + } + + sb.appendHtmlConstant("
"); + sb.appendEscaped("Parent"); + sb.appendHtmlConstant(""); + sb.appendEscaped(": " + (value.getParent() == null ? "-" : value.getParent().getName())); + sb.appendHtmlConstant("
"); + sb.appendEscaped("Name"); + sb.appendHtmlConstant(""); + sb.appendEscaped(": " + value.getName()); + sb.appendHtmlConstant("
"); + sb.appendEscaped("Type"); + sb.appendHtmlConstant(""); + sb.appendEscaped(": " + (value.isFolder() ? "Folder" : "File")); + sb.appendHtmlConstant("
"); + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ResourceCellRight.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ResourceCellRight.java new file mode 100644 index 0000000..c716449 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ResourceCellRight.java @@ -0,0 +1,32 @@ +package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection; + +import com.google.gwt.cell.client.AbstractCell; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; + +/** + * Cell that renders right side panel objects + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class ResourceCellRight extends AbstractCell{ + + @Override + public void render(com.google.gwt.cell.client.Cell.Context context, + ResourceElementBean value, SafeHtmlBuilder sb) { + + // Do not render an object if + // - is null; + // - is still on the left side + if (value == null || !value.isMovedToRight() || value.isFolder()) { + return; + } + sb.appendHtmlConstant(""); + sb.appendHtmlConstant("
"); + sb.appendHtmlConstant(""); + sb.appendEscaped("Name"); + sb.appendHtmlConstant(""); + sb.appendEscaped(": " + value.getFullPath()); + sb.appendHtmlConstant("
"); + } + +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ResourceElementBean.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ResourceElementBean.java new file mode 100644 index 0000000..fcfb952 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ResourceElementBean.java @@ -0,0 +1,133 @@ +package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection; + +import java.util.List; + +import com.google.gwt.core.shared.GWT; +import com.google.gwt.view.client.ProvidesKey; + + +/** + * A left-side element for the list in TwinColumnSelection + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class ResourceElementBean implements Comparable{ + + private int identifier; + private String name; + private boolean movedToRight; + private boolean isFolder; + private ResourceElementBean parent; + private List children; + private String fullPath; + + // to generate the identifiers + private static int nextId = 0; + + /** + * The key provider that provides the unique ID of a bean. + */ + public static final ProvidesKey KEY_PROVIDER = new ProvidesKey() { + @Override + public Object getKey(ResourceElementBean item) { + return item == null ? null : item.getIdentifier(); + } + }; + + /** + * @param identifier + * @param parentFolder + * @param name + * @param movedToRight + * @param isFolder + */ + public ResourceElementBean( + ResourceElementBean parent, + String name, + boolean isFolder, + List children, + String fullPath) { + this.identifier = nextId; + nextId++; + this.parent = parent; + this.name = name; + this.isFolder = isFolder; + this.children = children; + this.fullPath = fullPath; + } + + public ResourceElementBean getParent() { + return parent; + } + + public void setParent(ResourceElementBean parent) { + this.parent = parent; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isMovedToRight() { + return movedToRight; + } + + public void setMovedToRight(boolean movedToRight) { + this.movedToRight = movedToRight; + } + + public int getIdentifier() { + return identifier; + } + + public void setIdentifier(int identifier) { + this.identifier = identifier; + } + + public boolean isFolder() { + return isFolder; + } + + public void setFolder(boolean isFolder) { + this.isFolder = isFolder; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + public String getFullPath() { + return fullPath; + } + + public void setFullPath(String fullPath) { + this.fullPath = fullPath; + } + + @Override + public String toString() { + return "ResourceElementBean [identifier=" + identifier + ", name=" + + name + ", movedToRight=" + movedToRight + ", isFolder=" + + isFolder + ", fullPath=" + fullPath + "]"; + } + + @Override + public boolean equals(Object o) { + if (o instanceof ResourceElementBean) { + return identifier == ((ResourceElementBean) o).identifier; + } + return false; + } + + @Override + public int compareTo(ResourceElementBean o) { + return (o == null || o.name == null) ? -1 : -o.fullPath.compareTo(fullPath); + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ShowMorePagerPanel.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ShowMorePagerPanel.java new file mode 100644 index 0000000..e7cb6a5 --- /dev/null +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/ShowMorePagerPanel.java @@ -0,0 +1,102 @@ +package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection; + +import com.google.gwt.event.dom.client.ScrollEvent; +import com.google.gwt.event.dom.client.ScrollHandler; +import com.google.gwt.user.cellview.client.AbstractPager; +import com.google.gwt.user.client.ui.ScrollPanel; +import com.google.gwt.user.client.ui.Widget; +import com.google.gwt.view.client.HasRows; + +/** + * Basically a scroll panel + * Partially changed from the code at http://samples.gwtproject.org/samples/Showcase/Showcase.html#!CwCellList + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class ShowMorePagerPanel extends AbstractPager{ + + /** + * The default increment size. + */ + public static final int DEFAULT_INCREMENT = 5; + + /** + * The increment size. + */ + private int incrementSize = DEFAULT_INCREMENT; + + /** + * The last scroll position. + */ + private int lastScrollPos = 0; + + /** + * The scrollable panel. + */ + private final ScrollPanel scrollable = new ScrollPanel(); + + /** + * Construct a new {@link ShowMorePagerPanel}. + */ + public ShowMorePagerPanel() { + initWidget(scrollable); + + // Do not let the scrollable take tab focus. + scrollable.getElement().setTabIndex(-1); + + // Handle scroll events. + scrollable.addScrollHandler(new ScrollHandler() { + public void onScroll(ScrollEvent event) { + // If scrolling up, ignore the event. + int oldScrollPos = lastScrollPos; + lastScrollPos = scrollable.getVerticalScrollPosition(); + if (oldScrollPos >= lastScrollPos) { + return; + } + + HasRows display = getDisplay(); + if (display == null) { + return; + } + int maxScrollTop = scrollable.getWidget().getOffsetHeight() + - scrollable.getOffsetHeight(); + if (lastScrollPos >= maxScrollTop) { + // We are near the end, so increase the page size. + int newPageSize = Math.min( + display.getVisibleRange().getLength() + incrementSize, + display.getRowCount()); + display.setVisibleRange(0, newPageSize); + } + } + }); + } + + /** + * Get the number of rows by which the range is increased when the scrollbar + * reaches the bottom. + * @return the increment size + */ + public int getIncrementSize() { + return incrementSize; + } + + @Override + public void setDisplay(HasRows display) { + assert display instanceof Widget : "display must extend Widget"; + scrollable.setWidget((Widget) display); + super.setDisplay(display); + } + + /** + * Set the number of rows by which the range is increased when the scrollbar + * reaches the bottom. + * + * @param incrementSize the incremental number of rows + */ + public void setIncrementSize(int incrementSize) { + this.incrementSize = incrementSize; + } + + @Override + protected void onRangeOrRowCountChanged() { + } +} diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/TwinColumnSelectionMainPanel.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/TwinColumnSelectionMainPanel.java index 7f42ac0..c568a06 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/TwinColumnSelectionMainPanel.java +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/TwinColumnSelectionMainPanel.java @@ -1,12 +1,25 @@ package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.TwinColumnSelection; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + import com.github.gwtbootstrap.client.ui.Button; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Style.BorderStyle; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.cellview.client.CellList; +import com.google.gwt.user.cellview.client.HasKeyboardPagingPolicy.KeyboardPagingPolicy; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; +import com.google.gwt.view.client.ListDataProvider; +import com.google.gwt.view.client.MultiSelectionModel; +import com.google.gwt.view.client.SelectionChangeEvent; /** * The twin column panels for selection of the files to attach to the catalague product. @@ -14,18 +27,35 @@ import com.google.gwt.user.client.ui.Widget; * */ public class TwinColumnSelectionMainPanel extends Composite{ - - @UiField - VerticalPanel leftColumn; - @UiField - VerticalPanel rightColumn; - @UiField - Button addToSelected; - @UiField - Button addToSelectedWithChild; - @UiField - Button addToUnselected; + @UiField + VerticalPanel leftContainer; + @UiField + VerticalPanel rightContainer; + @UiField + VerticalPanel buttonsPanel; + @UiField + Button allToRightButton; + @UiField + Button toRightButton; + @UiField + Button toLeftButton; + @UiField + Button allToLeftButton; + @UiField + Button goRootButton; + + private final String PANEL_BORDER_COLOR = "#08c"; + private final String PANEL_HEIGHT = "400px"; + private ShowMorePagerPanel showMorePanelLeft = new ShowMorePagerPanel(); + private ShowMorePagerPanel showMorePanelRight = new ShowMorePagerPanel(); + private CellList cellListLeft; + private CellList cellListRight; + private ListDataProvider dataProviderLeft = new ListDataProvider(); + private ListDataProvider dataProviderRight = new ListDataProvider(); + private MultiSelectionModel selectionModelRight; + private MultiSelectionModel selectionModelLeft; + private final List initialElements; private static TwinColumnSelectionMainPanelUiBinder uiBinder = GWT .create(TwinColumnSelectionMainPanelUiBinder.class); @@ -34,11 +64,264 @@ public class TwinColumnSelectionMainPanel extends Composite{ UiBinder { } - /** - * Constructor - */ - public TwinColumnSelectionMainPanel() { + public TwinColumnSelectionMainPanel(List elements) { initWidget(uiBinder.createAndBindUi(this)); + + this.initialElements = elements; + this.buttonsPanel.getElement().getStyle().setMarginTop(50, Unit.PCT); + + allToRightButton.getElement().getStyle().setMarginBottom(4, Unit.PX); + toRightButton.getElement().getStyle().setMarginBottom(4, Unit.PX); + toLeftButton.getElement().getStyle().setMarginBottom(4, Unit.PX); + allToLeftButton.getElement().getStyle().setMarginBottom(4, Unit.PX); + buttonsPanel.getElement().setAttribute("align", "center"); + + prepareHandlers(); + initLeftSidePanel(elements); + initRightSidePanel(elements); + + } + + /** + * Initialize the left side panel + */ + private void initLeftSidePanel(List elements) { + + // initialize the left side list + ResourceCellLeft cell = new ResourceCellLeft(); + + // Set a key provider that provides a unique key for each object. + cellListLeft = new CellList(cell, ResourceElementBean.KEY_PROVIDER); + cellListLeft.setPageSize(elements.size()); + cellListLeft.setKeyboardPagingPolicy(KeyboardPagingPolicy.INCREASE_RANGE); + + // Add a selection model so we can select cells. + selectionModelLeft = new MultiSelectionModel(ResourceElementBean.KEY_PROVIDER); + cellListLeft.setSelectionModel(selectionModelLeft); + + // perform an action on selection + selectionModelLeft.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { + public void onSelectionChange(SelectionChangeEvent event) { + Iterator selectedObjectsIterator = selectionModelLeft.getSelectedSet().iterator(); + + while (selectedObjectsIterator.hasNext()) { + ResourceElementBean selectedBean = (ResourceElementBean) selectedObjectsIterator.next(); + if(selectedBean.isFolder()){ + if(selectionModelLeft.getSelectedSet().size() == 1){ + GWT.log("Selected folder"); + dataProviderLeft.setList(selectedBean.getChildren()); + dataProviderLeft.flush(); + dataProviderLeft.refresh(); + } + selectionModelLeft.setSelected(selectedBean, false); // unselect the folder + } + } + + // enable the buttons that allows to move the objects to the right + enableMoveToRightButtons(selectionModelLeft.getSelectedSet()); + } + }); + + + // set the list into the provider + dataProviderLeft.setList(elements); + + // set the cell list into the provider + dataProviderLeft.addDataDisplay(cellListLeft); + + // manage showMorePanelLeft + showMorePanelLeft.setDisplay(cellListLeft); + showMorePanelLeft.setHeight(PANEL_HEIGHT); + showMorePanelLeft.getElement().getStyle().setBorderStyle(BorderStyle.SOLID); + showMorePanelLeft.getElement().getStyle().setBorderColor(PANEL_BORDER_COLOR); + + // add the list to the leftContainerPanel + leftContainer.add(showMorePanelLeft); + + } + + /** + * Initialize the left side panel + */ + private void initRightSidePanel(List elements) { + + GWT.log("Size is " + elements.size()); + + // initialize the left side list + ResourceCellRight cell = new ResourceCellRight(); + + // Set a key provider that provides a unique key for each object. + cellListRight = new CellList(cell, ResourceElementBean.KEY_PROVIDER); + cellListRight.setKeyboardPagingPolicy(KeyboardPagingPolicy.INCREASE_RANGE); + cellListRight.setPageSize(elements.size()); + + // Add a selection model so we can select cells. + selectionModelRight = new MultiSelectionModel(ResourceElementBean.KEY_PROVIDER); + cellListRight.setSelectionModel(selectionModelRight); + + // perform an action on selection + selectionModelRight.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { + public void onSelectionChange(SelectionChangeEvent event) { + // enable the buttons that allows to move the objects to the left + enableMoveToLeftButtons(selectionModelRight.getSelectedSet()); + } + }); + + + // set the list into the provider + dataProviderRight.setList(elements); + + // set the cell list into the provider + dataProviderRight.addDataDisplay(cellListRight); + + // manage showMorePanelRight + showMorePanelRight.setDisplay(cellListRight); + showMorePanelRight.setHeight(PANEL_HEIGHT); + showMorePanelRight.getElement().getStyle().setBorderStyle(BorderStyle.SOLID); + showMorePanelRight.getElement().getStyle().setBorderColor(PANEL_BORDER_COLOR); + + // add the list to the leftContainerPanel + rightContainer.add(showMorePanelRight); + + } + + /** + * Enable/disable the buttons to move objects from left to right properly. + * @param setselectedItemsLeft + */ + private void enableMoveToRightButtons(Set setselectedItemsLeft){ + + if(setselectedItemsLeft.size() > 1){ + allToRightButton.setEnabled(true); + toRightButton.setEnabled(false); + } + else{ + allToRightButton.setEnabled(false); + toRightButton.setEnabled(true); + } + } + + /** + * Enable/disable the buttons to move objects from right to left properly. + * @param setselectedItemsRight + */ + private void enableMoveToLeftButtons(Set setselectedItemsRight){ + + if(setselectedItemsRight.size() > 1){ + allToLeftButton.setEnabled(true); + toLeftButton.setEnabled(false); + } + else{ + allToLeftButton.setEnabled(false); + toLeftButton.setEnabled(true); + } + } + + /** + * Prepare the buttons' handlers + */ + private void prepareHandlers() { + + goRootButton.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + + dataProviderLeft.setList(initialElements); + dataProviderLeft.flush(); + + } + }); + + allToRightButton.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + + moveToRight(selectionModelLeft.getSelectedSet()); + + } + }); + + toRightButton.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + + moveToRight(selectionModelLeft.getSelectedSet()); + + } + }); + + allToLeftButton.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + + moveToLeft(selectionModelRight.getSelectedSet()); + + } + }); + + toLeftButton.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + + moveToLeft(selectionModelRight.getSelectedSet()); + + } + }); + } + + /** + * Move to right + * @param toMoveRight + */ + private void moveToRight(Set set){ + + if(set == null) + return; + + Iterator iterator = set.iterator(); + while (iterator.hasNext()) { + ResourceElementBean resourceElementBean = (ResourceElementBean) iterator + .next(); + resourceElementBean.setMovedToRight(true); + GWT.log("To move right " + resourceElementBean); + } + + // refresh providers + dataProviderLeft.flush(); + dataProviderLeft.refresh(); + dataProviderRight.flush(); + dataProviderRight.refresh(); + + } + + /** + * Move to right + * @param toMoveLeft + */ + private void moveToLeft(Set set){ + + if(set == null) + return; + + Iterator iterator = set.iterator(); + while (iterator.hasNext()) { + ResourceElementBean resourceElementBean = (ResourceElementBean) iterator + .next(); + resourceElementBean.setMovedToRight(false); + GWT.log("To move left " + resourceElementBean); + } + + // refresh providers + dataProviderLeft.flush(); + dataProviderLeft.refresh(); + dataProviderRight.flush(); + dataProviderRight.refresh(); + } } diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/TwinColumnSelectionMainPanel.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/TwinColumnSelectionMainPanel.ui.xml index bd31337..70b6166 100644 --- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/TwinColumnSelectionMainPanel.ui.xml +++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/TwinColumnSelection/TwinColumnSelectionMainPanel.ui.xml @@ -2,25 +2,33 @@ - + .right-vertical-panel { + margin-top: 30px; + margin-left: 0px; + } - - - - - - - - + + Root level + - - + + + + + + + + + +