The current implementation does not in all cases enforce that visibility toggles are always before any custom items. The JavaDoc warns about this and the order is also restored whenever a visibility toggle is added or removed. Change-Id: I7160a04d6c96b2d6d821b13e420172e6115bc072tags/7.5.0.beta1
@@ -3012,12 +3012,13 @@ public class Grid<T> extends ResizeComposite implements | |||
menuBar = new MenuBar(true) { | |||
@Override | |||
public MenuItem addItem(MenuItem item) { | |||
public MenuItem insertItem(MenuItem item, int beforeIndex) | |||
throws IndexOutOfBoundsException { | |||
if (getParent() == null) { | |||
content.insert(this, 0); | |||
updateVisibility(); | |||
} | |||
return super.addItem(item); | |||
return super.insertItem(item, beforeIndex); | |||
} | |||
@Override | |||
@@ -3273,12 +3274,13 @@ public class Grid<T> extends ResizeComposite implements | |||
private void updateTogglesOrder() { | |||
if (!hidingColumn) { | |||
int lastIndex = 0; | |||
for (Column<?, T> column : getColumns()) { | |||
if (column.isHidable()) { | |||
final MenuItem menuItem = columnToHidingToggleMap | |||
.get(column); | |||
sidebar.menuBar.removeItem(menuItem); | |||
sidebar.menuBar.addItem(menuItem); | |||
sidebar.menuBar.insertItem(menuItem, lastIndex++); | |||
} | |||
} | |||
} | |||
@@ -7710,4 +7712,50 @@ public class Grid<T> extends ResizeComposite implements | |||
private Sidebar getSidebar() { | |||
return sidebar; | |||
} | |||
/** | |||
* Gets the customizable menu bar that is by default used for toggling | |||
* column hidability. The application developer is allowed to add their | |||
* custom items to the end of the menu, but should try to avoid modifying | |||
* the items in the beginning of the menu that control the column hiding if | |||
* any columns are marked as hidable. A toggle for opening the menu will be | |||
* displayed whenever the menu contains at least one item. | |||
* | |||
* @since 7.5.0 | |||
* @return the menu bar | |||
*/ | |||
public MenuBar getSidebarMenu() { | |||
return sidebar.menuBar; | |||
} | |||
/** | |||
* Tests whether the sidebar menu is currently open. | |||
* | |||
* @since 7.5.0 | |||
* @see #getSidebarMenu() | |||
* @return <code>true</code> if the sidebar is open; <code>false</code> if | |||
* it is closed | |||
*/ | |||
public boolean isSidebarOpen() { | |||
return sidebar.isOpen(); | |||
} | |||
/** | |||
* Sets whether the sidebar menu is open. | |||
* | |||
* | |||
* @since 7.5.0 | |||
* @see #getSidebarMenu() | |||
* @see #isSidebarOpen() | |||
* @param sidebarOpen | |||
* <code>true</code> to open the sidebar; <code>false</code> to | |||
* close it | |||
*/ | |||
public void setSidebarOpen(boolean sidebarOpen) { | |||
if (sidebarOpen) { | |||
sidebar.open(); | |||
} else { | |||
sidebar.close(); | |||
} | |||
} | |||
} |
@@ -15,6 +15,8 @@ | |||
*/ | |||
package com.vaadin.tests.components.grid.basicfeatures.client; | |||
import java.util.List; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
import org.openqa.selenium.By; | |||
@@ -49,6 +51,103 @@ public class GridSidebarContentTest extends GridBasicClientFeaturesTest { | |||
} | |||
@Test | |||
public void testAddingCustomSidebarItem() { | |||
openTestURL(); | |||
CustomGridElement gridElement = getGridElement(); | |||
selectMenuPath("Component", "Sidebar", "Add item to end"); | |||
gridElement.findElement(By.className("v-grid-sidebar-button")).click(); | |||
WebElement sidebarItem = gridElement.findElement(By | |||
.cssSelector(".v-grid-sidebar-content .gwt-MenuItem")); | |||
sidebarItem.click(); | |||
Assert.assertEquals("Sidebar should be closed after clicking item 0", | |||
0, countBySelector(".v-grid-sidebar-content")); | |||
} | |||
@Test | |||
public void testProgrammaticSidebarToggle() { | |||
openTestURL(); | |||
selectMenuPath("Component", "Columns", "Column 0", "Hidable"); | |||
selectMenuPath("Component", "Sidebar", "Toggle sidebar visibility"); | |||
Assert.assertEquals("Sidebar be open", 1, | |||
countBySelector(".v-grid-sidebar-content")); | |||
selectMenuPath("Component", "Sidebar", "Toggle sidebar visibility"); | |||
Assert.assertEquals("Sidebar be closed", 0, | |||
countBySelector(".v-grid-sidebar-content")); | |||
} | |||
@Test | |||
public void testBasicSidebarOrder() { | |||
openTestURL(); | |||
CustomGridElement gridElement = getGridElement(); | |||
// First add custom content | |||
selectMenuPath("Component", "Sidebar", "Add separator to end"); | |||
selectMenuPath("Component", "Sidebar", "Add item to end"); | |||
// Then make one column togglable | |||
selectMenuPath("Component", "Columns", "Column 0", "Hidable"); | |||
selectMenuPath("Component", "Sidebar", "Toggle sidebar visibility"); | |||
assertSidebarMenuItems("Header (0,0)", null, "Custom menu item 0"); | |||
} | |||
@Test | |||
public void testSidebarOrderAbuse() { | |||
openTestURL(); | |||
CustomGridElement gridElement = getGridElement(); | |||
selectMenuPath("Component", "Columns", "Column 0", "Hidable"); | |||
selectMenuPath("Component", "Columns", "Column 1", "Hidable"); | |||
// Inserts a menu item between the two visibility toggles | |||
selectMenuPath("Component", "Sidebar", "Add item before index 1"); | |||
selectMenuPath("Component", "Sidebar", "Toggle sidebar visibility"); | |||
// Total order enforcement not implemented at this point. Test can be | |||
// updated when it is. | |||
assertSidebarMenuItems("Header (0,0)", "Custom menu item 0", | |||
"Header (0,1)"); | |||
selectMenuPath("Component", "Columns", "Column 2", "Hidable"); | |||
// Adding a new togglable column should have restored the expected order | |||
assertSidebarMenuItems("Header (0,0)", "Header (0,1)", "Header (0,2)", | |||
"Custom menu item 0"); | |||
} | |||
private void assertSidebarMenuItems(String... items) { | |||
List<WebElement> menuItems = getGridElement().findElements( | |||
By.cssSelector(".v-grid-sidebar-content td")); | |||
Assert.assertEquals("Expected " + items.length + " menu items", | |||
items.length, menuItems.size()); | |||
for (int i = 0; i < items.length; i++) { | |||
String expectedItem = items[i]; | |||
if (expectedItem == null) { | |||
Assert.assertEquals("Item " + i + " should be a separator", | |||
"gwt-MenuItemSeparator", | |||
menuItems.get(i).getAttribute("class")); | |||
} else { | |||
Assert.assertEquals("Unexpected content for item " + i, | |||
expectedItem, menuItems.get(i).getText()); | |||
} | |||
} | |||
} | |||
private int countBySelector(String cssSelector) { | |||
return getGridElement().findElements(By.cssSelector(cssSelector)) | |||
.size(); |
@@ -36,6 +36,8 @@ import com.google.gwt.user.client.ui.Composite; | |||
import com.google.gwt.user.client.ui.FlowPanel; | |||
import com.google.gwt.user.client.ui.HTML; | |||
import com.google.gwt.user.client.ui.Label; | |||
import com.google.gwt.user.client.ui.MenuItem; | |||
import com.google.gwt.user.client.ui.MenuItemSeparator; | |||
import com.google.gwt.user.client.ui.TextBox; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.vaadin.client.data.DataSource; | |||
@@ -409,6 +411,7 @@ public class GridBasicClientFeaturesWidget extends | |||
createInternalsMenu(); | |||
createDataSourceMenu(); | |||
createDetailsMenu(); | |||
createSidebarMenu(); | |||
grid.getElement().getStyle().setZIndex(0); | |||
@@ -1478,4 +1481,88 @@ public class GridBasicClientFeaturesWidget extends | |||
} | |||
} | |||
private static Logger getLogger() { | |||
return Logger.getLogger(GridBasicClientFeaturesWidget.class.getName()); | |||
} | |||
private void createSidebarMenu() { | |||
String[] menupath = new String[] { "Component", "Sidebar" }; | |||
final List<MenuItem> customMenuItems = new ArrayList<MenuItem>(); | |||
final List<MenuItemSeparator> separators = new ArrayList<MenuItemSeparator>(); | |||
addMenuCommand("Add item to end", new ScheduledCommand() { | |||
@Override | |||
public void execute() { | |||
MenuItem item = createSidebarMenuItem(customMenuItems.size()); | |||
customMenuItems.add(item); | |||
grid.getSidebarMenu().addItem(item); | |||
} | |||
}, menupath); | |||
addMenuCommand("Add item before index 1", new ScheduledCommand() { | |||
@Override | |||
public void execute() { | |||
MenuItem item = createSidebarMenuItem(customMenuItems.size()); | |||
customMenuItems.add(item); | |||
grid.getSidebarMenu().insertItem(item, 1); | |||
} | |||
}, menupath); | |||
addMenuCommand("Remove last added item", new ScheduledCommand() { | |||
@Override | |||
public void execute() { | |||
grid.getSidebarMenu().removeItem( | |||
customMenuItems.remove(customMenuItems.size() - 1)); | |||
} | |||
}, menupath); | |||
addMenuCommand("Add separator to end", new ScheduledCommand() { | |||
@Override | |||
public void execute() { | |||
MenuItemSeparator separator = new MenuItemSeparator(); | |||
separators.add(separator); | |||
grid.getSidebarMenu().addSeparator(separator); | |||
} | |||
}, menupath); | |||
addMenuCommand("Add separator before index 1", new ScheduledCommand() { | |||
@Override | |||
public void execute() { | |||
MenuItemSeparator separator = new MenuItemSeparator(); | |||
separators.add(separator); | |||
grid.getSidebarMenu().insertSeparator(separator, 1); | |||
} | |||
}, menupath); | |||
addMenuCommand("Remove last added separator", new ScheduledCommand() { | |||
@Override | |||
public void execute() { | |||
grid.getSidebarMenu().removeSeparator( | |||
separators.remove(separators.size() - 1)); | |||
} | |||
}, menupath); | |||
addMenuCommand("Toggle sidebar visibility", new ScheduledCommand() { | |||
@Override | |||
public void execute() { | |||
grid.setSidebarOpen(!grid.isSidebarOpen()); | |||
} | |||
}, menupath); | |||
} | |||
private MenuItem createSidebarMenuItem(final int index) { | |||
final MenuItem menuItem = new MenuItem("Custom menu item " + index, | |||
new ScheduledCommand() { | |||
@Override | |||
public void execute() { | |||
if (index % 2 == 0) { | |||
grid.setSidebarOpen(false); | |||
} | |||
getLogger().info("Menu item " + index + " selected"); | |||
} | |||
}); | |||
return menuItem; | |||
} | |||
} |