diff options
author | Pekka Hyvönen <pekka@vaadin.com> | 2015-03-19 08:29:00 +0200 |
---|---|---|
committer | Pekka Hyvönen <pekka@vaadin.com> | 2015-03-19 08:29:31 +0200 |
commit | 4d5f6cf73f84bd0f68f05eb534699bddb898f9f1 (patch) | |
tree | 3bd75f12598d8598963d94b97c5cb8e30a6808a5 /client/src | |
parent | 7a0be4e8e71df51f6fe49d2651f05e9430e307e1 (diff) | |
parent | 4e26f150752d29a015dec71dfcba186b19b7506a (diff) | |
download | vaadin-framework-4d5f6cf73f84bd0f68f05eb534699bddb898f9f1.tar.gz vaadin-framework-4d5f6cf73f84bd0f68f05eb534699bddb898f9f1.zip |
Merge remote-tracking branch 'origin/grid-columnhiding' into grid-7.5
Change-Id: Ice80ed9d5a96d9de824cc932873b4e6a736459a8
Diffstat (limited to 'client/src')
-rw-r--r-- | client/src/com/vaadin/client/widgets/Grid.java | 304 |
1 files changed, 296 insertions, 8 deletions
diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index ea9525f157..c6ac35bba0 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -62,9 +62,13 @@ import com.google.gwt.user.client.Event.NativePreviewHandler; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; +import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HasEnabled; +import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.ResizeComposite; +import com.google.gwt.user.client.ui.ToggleButton; +import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.BrowserInfo; import com.vaadin.client.DeferredWorker; @@ -75,6 +79,7 @@ import com.vaadin.client.renderers.ComplexRenderer; import com.vaadin.client.renderers.Renderer; import com.vaadin.client.renderers.WidgetRenderer; import com.vaadin.client.ui.SubPartAware; +import com.vaadin.client.ui.VButton; import com.vaadin.client.ui.dd.DragAndDropHandler; import com.vaadin.client.ui.dd.DragAndDropHandler.DragAndDropCallback; import com.vaadin.client.widget.escalator.Cell; @@ -2882,6 +2887,258 @@ public class Grid<T> extends ResizeComposite implements } /** + * Sidebar displaying toggles for hidable columns and additional custom + * widgets. + * <p> + * The button for opening the sidebar is automatically visible inside the + * grid, if it contains any column hiding options or custom widgets. The + * column hiding toggles and custom widgets become visible once the sidebar + * has been opened. + * + * @since + */ + public static class Sidebar extends Composite { + + private final ClickHandler openCloseButtonHandler = new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + if (!open) { + open(); + } else { + close(); + } + } + }; + + /** + * Contains all the widgets which should be shown once the sidebar is + * opened + */ + private final List<Widget> widgets = new ArrayList<Widget>(); + + private final VerticalPanel rootContainer; + + private final VButton openCloseButton; + + private final Grid<?> grid; + + private boolean open; + + public Sidebar(Grid<?> grid) { + this.grid = grid; + + rootContainer = new VerticalPanel(); + initWidget(rootContainer); + + openCloseButton = new VButton(); + openCloseButton.addClickHandler(openCloseButtonHandler); + + rootContainer.add(openCloseButton); + rootContainer + .setCellHorizontalAlignment( + openCloseButton, + HorizontalAlignmentConstant + .endOf(com.google.gwt.i18n.client.HasDirection.Direction.LTR)); + } + + /** + * Opens the sidebar if not yet opened. + * + * @since + */ + public void open() { + if (!open) { + addStyleName("opened"); + open = true; + for (Widget w : widgets) { + rootContainer.add(w); + } + } + } + + /** + * Closes the sidebar if not yet closed. + * + * @since + */ + public void close() { + if (open) { + removeStyleName("opened"); + open = false; + rootContainer.clear(); + rootContainer.add(openCloseButton); + } + } + + /** + * Returns whether the sidebar is open or not. + * <p> + * <em>Note:</em> The sidebar can be in "open state" but not actually + * visible inside grid. See {@link #isVisibleInGrid()}. + * + * @since + * @return <code>true</code> if open, <code>false</code> if not + */ + public boolean isOpen() { + return open; + } + + /** + * Adds or moves the given widget to the end of the sidebar. + * + * @param widget + * the widget to add or move + */ + public void add(Widget widget) { + widgets.remove(widget); + widgets.add(widget); + if (open) { + rootContainer.add(widget); + } + updateVisibility(); + } + + /** + * Removes the given widget from the sidebar. + * + * @param widget + * the widget to remove + */ + public void remove(Widget widget) { + widgets.remove(widget); + if (open) { + rootContainer.remove(widget); + } + updateVisibility(); + } + + /** + * Inserts given widget to the given index inside the sidebar. If the + * widget is already in the sidebar, then it is moved to the new index. + * <p> + * See + * {@link VerticalPanel#insert(com.google.gwt.user.client.ui.IsWidget, int)} + * for further details. + * + * @param widget + * the widget to insert + * @param beforeIndex + * 0-based index position for the widget. + */ + public void insert(Widget widget, int beforeIndex) { + widgets.remove(widget); + widgets.add(beforeIndex, widget); + if (open) { + // the first widget in the container is always the open button + rootContainer.insert(widget, beforeIndex + 1); + } + updateVisibility(); + } + + @Override + public void setStylePrimaryName(String styleName) { + super.setStylePrimaryName(styleName); + openCloseButton.setStylePrimaryName(styleName + "-button"); + } + + private void updateVisibility() { + final boolean hasWidgets = widgets.size() > 0; + final boolean isVisible = getParent() != null; + if (isVisible && !hasWidgets) { + getElement().removeFromParent(); + removeFromParent(); + } else if (!isVisible && hasWidgets) { + grid.getElement().appendChild(getElement()); + Grid.setParent(this, grid); + } + } + + } + + /** + * UI and functionality related to hiding columns with toggles in the + * sidebar. + */ + private final class ColumnHider extends VerticalPanel { + + ColumnHider() { + setStyleName("column-hiding-panel"); + } + + /** Map from columns to their hiding toggles, component might change */ + private HashMap<Column<?, T>, ToggleButton> columnToHidingToggleMap = new HashMap<Grid.Column<?, T>, ToggleButton>(); + + private void updateColumnHidable(final Column<?, T> column) { + if (column.isHidable()) { + ToggleButton cb = columnToHidingToggleMap.get(column); + if (cb == null) { + cb = createToggle(column); + } + updateToggleValue(cb, column.isHidden()); + } else if (columnToHidingToggleMap.containsValue(column)) { + ((Widget) columnToHidingToggleMap.remove(column)) + .removeFromParent(); + } + updateTogglesOrder(); + updatePanelVisibility(); + } + + private ToggleButton createToggle(final Column<?, T> column) { + ToggleButton toggle = new ToggleButton(column.headerCaption); + toggle.addStyleName("column-hiding-toggle"); + toggle.addValueChangeHandler(new ValueChangeHandler<Boolean>() { + + @Override + public void onValueChange(ValueChangeEvent<Boolean> event) { + column.setHidden(!event.getValue(), true); + } + }); + columnToHidingToggleMap.put(column, toggle); + return toggle; + } + + private void updateTogglesOrder() { + clear(); + for (Column<?, T> c : getColumns()) { + if (c.isHidable()) { + add(columnToHidingToggleMap.get(c)); + } + } + } + + private void updatePanelVisibility() { + final boolean columnHidable = getWidgetCount() > 0; + // parent for the panel might be null sidebar is not open + final boolean columnTogglesPanelIsVisible = sidebar.widgets + .contains(this); + + if (columnHidable && !columnTogglesPanelIsVisible) { + sidebar.insert(this, 0); + } else if (!columnHidable && columnTogglesPanelIsVisible) { + sidebar.remove(this); + } + } + + private void updateToggleValue(Column<?, T> column) { + if (column.isHidable()) { + updateToggleValue(columnToHidingToggleMap.get(column), + column.isHidden()); + } // else we can just ignore + } + + private void updateToggleValue(ToggleButton hasValue, boolean hidden) { + hasValue.setValue(!hidden, false); + hasValue.setStyleName("hidden", hidden); + } + + private void updateColumnHidingToggleCaption(Column<?, T> column) { + columnToHidingToggleMap.get(column).setText(column.headerCaption); + } + + } + + /** * Escalator used internally by grid to render the rows */ private Escalator escalator = GWT.create(Escalator.class); @@ -2890,6 +3147,8 @@ public class Grid<T> extends ResizeComposite implements private final Footer footer = GWT.create(Footer.class); + private final Sidebar sidebar = new Sidebar(this); + /** * List of columns in the grid. Order defines the visible order. */ @@ -2974,6 +3233,8 @@ public class Grid<T> extends ResizeComposite implements private boolean columnReorderingAllowed; + private ColumnHider columnHider = new ColumnHider(); + private DragAndDropHandler dndHandler = new DragAndDropHandler(); private AutoScroller autoScroller = new AutoScroller(this); @@ -3488,7 +3749,7 @@ public class Grid<T> extends ResizeComposite implements private boolean hidden = false; - private boolean hideable = false; + private boolean hidable = false; private String headerCaption = ""; @@ -3600,6 +3861,9 @@ public class Grid<T> extends ResizeComposite implements HeaderRow row = grid.getHeader().getDefaultRow(); if (row != null) { row.getCell(this).setText(headerCaption); + if (isHidable()) { + grid.columnHider.updateColumnHidingToggleCaption(this); + } } } @@ -3767,6 +4031,10 @@ public class Grid<T> extends ResizeComposite implements * to show */ public void setHidden(boolean hidden) { + setHidden(hidden, false); + } + + private void setHidden(boolean hidden, boolean userOriginated) { if (this.hidden != hidden) { if (hidden) { grid.escalator.getColumnConfiguration().removeColumns( @@ -3777,9 +4045,10 @@ public class Grid<T> extends ResizeComposite implements grid.escalator.getColumnConfiguration().insertColumns( grid.getVisibleColumns().indexOf(this), 1); } + grid.columnHider.updateToggleValue(this); scheduleColumnWidthRecalculator(); this.grid.fireEvent(new ColumnVisibilityChangeEvent<T>(this, - hidden, false)); + hidden, userOriginated)); } } @@ -3802,13 +4071,15 @@ public class Grid<T> extends ResizeComposite implements * programmatically using {@link #setHidden(boolean)}. * * @since - * @param hideable + * @param hidable * <code>true</code> if the user can hide this column, * <code>false</code> if not */ - public void setHideable(boolean hideable) { - this.hideable = hideable; - // TODO update whether sidebar/popup can be opened + public void setHidable(boolean hidable) { + if (this.hidable != hidable) { + this.hidable = hidable; + grid.columnHider.updateColumnHidable(this); + } } /** @@ -3822,8 +4093,8 @@ public class Grid<T> extends ResizeComposite implements * @return <code>true</code> if the user can hide the column, * <code>false</code> if not */ - public boolean isHideable() { - return hideable; + public boolean isHidable() { + return hidable; } @Override @@ -4547,6 +4818,7 @@ public class Grid<T> extends ResizeComposite implements super.setStylePrimaryName(style); escalator.setStylePrimaryName(style); editor.setStylePrimaryName(style); + sidebar.setStylePrimaryName(style + "-sidebar"); String rowStyle = getStylePrimaryName() + "-row"; rowHasDataStyleName = rowStyle + "-has-data"; @@ -6641,6 +6913,8 @@ public class Grid<T> extends ResizeComposite implements row.calculateColspans(); } + columnHider.updateTogglesOrder(); + fireEvent(new ColumnReorderEvent<T>()); } @@ -7079,4 +7353,18 @@ public class Grid<T> extends ResizeComposite implements public void recalculateColumnWidths() { autoColumnWidthsRecalculator.schedule(); } + + /** + * Returns the sidebar for this grid. + * <p> + * The grid's sidebar shows the column hiding options for those columns that + * have been set as {@link Column#setHidable(boolean) hidable}. + * + * @since + * @return the sidebar widget for this grid + */ + public Sidebar getSidebar() { + return sidebar; + } + } |