@@ -0,0 +1,13 @@ | |||
package com.vaadin.tests.widgetset.client.contextmenu; | |||
import com.vaadin.shared.communication.ClientRpc; | |||
public interface ContextMenuClientRpc extends ClientRpc { | |||
/** | |||
* Sends request to client widget to open context menu to given position. | |||
* | |||
* @param x | |||
* @param y | |||
*/ | |||
public void showContextMenu(int x, int y); | |||
} |
@@ -0,0 +1,120 @@ | |||
package com.vaadin.tests.widgetset.client.contextmenu; | |||
import java.util.logging.Logger; | |||
import com.vaadin.client.ServerConnector; | |||
import com.vaadin.client.communication.StateChangeEvent; | |||
import com.vaadin.client.extensions.AbstractExtensionConnector; | |||
import com.vaadin.client.ui.VMenuBar.CustomMenuItem; | |||
import com.vaadin.client.ui.menubar.MenuBarConnector; | |||
import com.vaadin.shared.ui.Connect; | |||
import com.vaadin.tests.widgetset.contextmenu.ContextMenu; | |||
@SuppressWarnings("serial") | |||
@Connect(ContextMenu.class) | |||
public class ContextMenuConnector extends AbstractExtensionConnector { | |||
@SuppressWarnings("unused") | |||
private static Logger logger = Logger.getLogger("ContextMenuConnector"); | |||
private MenuBarConnector innerConnector = new MenuBarConnector() { | |||
@Override | |||
public VContextMenuBar getWidget() { | |||
// todo another class? | |||
return (VContextMenuBar) super.getWidget(); | |||
} | |||
}; | |||
private VContextMenuBar contextMenuWidget = (VContextMenuBar) innerConnector | |||
.getWidget(); | |||
@Override | |||
public ContextMenuState getState() { | |||
return (ContextMenuState) super.getState(); | |||
} | |||
@Override | |||
public void onStateChanged(StateChangeEvent stateChangeEvent) { | |||
super.onStateChanged(stateChangeEvent); | |||
innerConnector.onStateChanged(stateChangeEvent); | |||
} | |||
@Override | |||
protected void init() { | |||
super.init(); | |||
innerConnector.doInit(getConnectorId(), getConnection()); | |||
contextMenuWidget.setPixelSize(0, 0); | |||
/* | |||
* CustomMenuItem item = GWT.create(CustomMenuItem.class); | |||
* dummyRootMenuBar.getItems().add(item); | |||
* | |||
* contextMenuWidget = new MyVMenuBar(true, dummyRootMenuBar); | |||
* contextMenuWidget.setConnection(getConnection()); | |||
* item.setSubMenu(contextMenuWidget); | |||
*/ | |||
registerRpc(ContextMenuClientRpc.class, new ContextMenuClientRpc() { | |||
@Override | |||
public void showContextMenu(int x, int y) { | |||
showMenu(x, y); | |||
} | |||
}); | |||
/* | |||
* Event.addNativePreviewHandler(new NativePreviewHandler() { | |||
* | |||
* @Override public void onPreviewNativeEvent(NativePreviewEvent event) | |||
* { if (event.getTypeInt() == Event.ONKEYDOWN && | |||
* contextMenuWidget.isPopupShowing()) { boolean handled = | |||
* contextMenuWidget.handleNavigation( | |||
* event.getNativeEvent().getKeyCode(), | |||
* event.getNativeEvent().getCtrlKey(), | |||
* event.getNativeEvent().getShiftKey()); | |||
* | |||
* if (handled) { event.cancel(); } } } }); | |||
*/ | |||
} | |||
private void showMenu(int eventX, int eventY) { | |||
if (contextMenuWidget.getItems().size() == 0) { | |||
return; | |||
} | |||
CustomMenuItem firstItem = innerConnector.getWidget().getItems().get(0); | |||
contextMenuWidget.setSelected(firstItem); | |||
contextMenuWidget.showChildMenuAt(firstItem, eventY, eventX); | |||
} | |||
@Override | |||
protected void extend(ServerConnector target) { | |||
Logger.getLogger("ContextMenuConnector").info("extend"); | |||
// Widget widget = ((AbstractComponentConnector) target).getWidget(); | |||
// widget.addDomHandler(new ContextMenuHandler() { | |||
// | |||
// @Override | |||
// public void onContextMenu(ContextMenuEvent event) { | |||
// event.stopPropagation(); | |||
// event.preventDefault(); | |||
// | |||
// showMenu(event.getNativeEvent().getClientX(), event | |||
// .getNativeEvent().getClientY()); | |||
// } | |||
// }, ContextMenuEvent.getType()); | |||
// widget.addDomHandler(new KeyDownHandler() { | |||
// @Override | |||
// public void onKeyDown(KeyDownEvent event) { | |||
// // FIXME: check if menu is shown or handleNavigation will do it? | |||
// | |||
// boolean handled = contextMenuWidget.handleNavigation(event | |||
// .getNativeEvent().getKeyCode(), event.getNativeEvent() | |||
// .getCtrlKey(), event.getNativeEvent().getShiftKey()); | |||
// | |||
// if (handled) { | |||
// event.stopPropagation(); | |||
// event.preventDefault(); | |||
// } | |||
// } | |||
// }, KeyDownEvent.getType()); | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
package com.vaadin.tests.widgetset.client.contextmenu; | |||
import com.vaadin.shared.communication.ServerRpc; | |||
public interface ContextMenuServerRpc extends ServerRpc { | |||
void itemClicked(int itemId, boolean menuClosed); | |||
} |
@@ -0,0 +1,9 @@ | |||
package com.vaadin.tests.widgetset.client.contextmenu; | |||
import com.vaadin.shared.ui.menubar.MenuBarState; | |||
public class ContextMenuState extends MenuBarState { | |||
{ | |||
primaryStyleName = "v-contextmenu"; | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
package com.vaadin.tests.widgetset.client.contextmenu; | |||
import com.vaadin.client.ui.VMenuBar; | |||
public class VContextMenuBar extends VMenuBar { | |||
public VContextMenuBar() { | |||
setPixelSize(0, 0); | |||
setVisible(false); | |||
} | |||
@Override | |||
public void showChildMenuAt(CustomMenuItem item, int top, int left) { | |||
super.showChildMenuAt(item, top, left); | |||
} | |||
} |
@@ -1,4 +1,165 @@ | |||
package com.vaadin.tests.widgetset.contextmenu; | |||
public class ContextMenu { | |||
import java.io.Serializable; | |||
import java.lang.reflect.Method; | |||
import java.util.EventListener; | |||
import java.util.EventObject; | |||
import java.util.List; | |||
import com.vaadin.event.ContextClickEvent; | |||
import com.vaadin.server.AbstractExtension; | |||
import com.vaadin.server.Resource; | |||
import com.vaadin.shared.Registration; | |||
import com.vaadin.ui.AbstractComponent; | |||
import com.vaadin.ui.Component; | |||
import com.vaadin.ui.MenuBar; | |||
import com.vaadin.ui.MenuBar.Command; | |||
import com.vaadin.ui.MenuBar.MenuItem; | |||
import com.vaadin.util.ReflectTools; | |||
public class ContextMenu extends AbstractExtension { | |||
private final MenuItem rootItem; | |||
private final MenuBar innerMenubar; | |||
public ContextMenu(AbstractComponent parentComponent, | |||
boolean setAsMenuForParentComponent) { | |||
innerMenubar = new MenuBar(); | |||
rootItem = innerMenubar.addItem(""); | |||
// todo | |||
extend(parentComponent); | |||
// todo enable registerRpc(new ContextMenuServerRpc() { | |||
// @Override | |||
// public void itemClicked(int itemId, boolean menuClosed) { | |||
// menu.itemClicked(itemId); | |||
// } | |||
// }); | |||
// | |||
// todo enable if (setAsMenuForParentComponent) { | |||
// setAsContextMenuOf(parentComponent); | |||
// } | |||
} | |||
public void setAsContextMenuOf( | |||
ContextClickEvent.ContextClickNotifier component) { | |||
// todo | |||
} | |||
// Should these also be in MenuInterface and then throw exception for | |||
// MenuBar? | |||
public MenuItem addSeparator() { | |||
return rootItem.addSeparator(); | |||
} | |||
public MenuItem addSeparatorBefore(MenuItem itemToAddBefore) { | |||
return rootItem.addSeparatorBefore(itemToAddBefore); | |||
} | |||
public MenuItem addItem(String caption, Command command) { | |||
return rootItem.addItem(caption, command); | |||
} | |||
public MenuItem addItem(String caption, Resource icon, Command command) { | |||
return rootItem.addItem(caption, icon, command); | |||
} | |||
public MenuItem addItemBefore(String caption, Resource icon, | |||
Command command, MenuItem itemToAddBefore) { | |||
return rootItem.addItemBefore(caption, icon, command, itemToAddBefore); | |||
} | |||
public List<MenuItem> getItems() { | |||
return rootItem.getChildren(); | |||
} | |||
public void removeItem(MenuItem item) { | |||
rootItem.removeChild(item); | |||
} | |||
public void removeItems() { | |||
rootItem.removeChildren(); | |||
} | |||
public int getSize() { | |||
return rootItem.getSize(); | |||
} | |||
public boolean isHtmlContentAllowed() { | |||
return innerMenubar.isHtmlContentAllowed(); | |||
} | |||
public void setHtmlContentAllowed(boolean htmlContentAllowed) { | |||
innerMenubar.setHtmlContentAllowed(true); | |||
} | |||
public Registration addContextMenuOpenListener( | |||
ContextMenuOpenListener contextMenuOpenListener) { | |||
// todo | |||
return null; | |||
} | |||
public interface ContextMenuOpenListener | |||
extends EventListener, Serializable { | |||
public static final Method MENU_OPENED = ReflectTools.findMethod( | |||
ContextMenuOpenListener.class, "onContextMenuOpen", | |||
ContextMenuOpenEvent.class); | |||
public void onContextMenuOpen(ContextMenuOpenEvent event); | |||
public static class ContextMenuOpenEvent extends EventObject { | |||
private final ContextMenu contextMenu; | |||
private final int x; | |||
private final int y; | |||
private ContextClickEvent contextClickEvent; | |||
public ContextMenuOpenEvent(ContextMenu contextMenu, | |||
ContextClickEvent contextClickEvent) { | |||
super(contextClickEvent.getComponent()); | |||
this.contextMenu = contextMenu; | |||
this.contextClickEvent = contextClickEvent; | |||
x = contextClickEvent.getClientX(); | |||
y = contextClickEvent.getClientY(); | |||
} | |||
/** | |||
* @return ContextMenu that was opened. | |||
*/ | |||
public ContextMenu getContextMenu() { | |||
return contextMenu; | |||
} | |||
/** | |||
* @return Component which initiated the context menu open request. | |||
*/ | |||
public Component getSourceComponent() { | |||
return (Component) getSource(); | |||
} | |||
/** | |||
* @return x-coordinate of open position. | |||
*/ | |||
public int getX() { | |||
return x; | |||
} | |||
/** | |||
* @return y-coordinate of open position. | |||
*/ | |||
public int getY() { | |||
return y; | |||
} | |||
public ContextClickEvent getContextClickEvent() { | |||
return contextClickEvent; | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,95 @@ | |||
package com.vaadin.tests.widgetset.contextmenu; | |||
import java.io.Serializable; | |||
import java.util.EventListener; | |||
import com.vaadin.shared.ui.grid.GridConstants.Section; | |||
import com.vaadin.tests.widgetset.contextmenu.ContextMenu.ContextMenuOpenListener.ContextMenuOpenEvent; | |||
import com.vaadin.tests.widgetset.contextmenu.GridContextMenu.GridContextMenuOpenListener.GridContextMenuOpenEvent; | |||
import com.vaadin.ui.Grid; | |||
import com.vaadin.ui.Grid.Column; | |||
import com.vaadin.ui.Grid.GridContextClickEvent; | |||
@SuppressWarnings("serial") | |||
public class GridContextMenu<T> extends ContextMenu { | |||
public GridContextMenu(Grid<T> parentComponent) { | |||
super(parentComponent, true); | |||
} | |||
private void addGridSectionContextMenuListener(final Section section, | |||
final GridContextMenuOpenListener<T> listener) { | |||
addContextMenuOpenListener((final ContextMenuOpenEvent event) -> { | |||
if (event.getContextClickEvent() instanceof GridContextClickEvent) { | |||
@SuppressWarnings("unchecked") | |||
GridContextClickEvent<T> gridEvent = (GridContextClickEvent<T>) event | |||
.getContextClickEvent(); | |||
if (gridEvent.getSection() == section) { | |||
listener.onContextMenuOpen(new GridContextMenuOpenEvent<>( | |||
GridContextMenu.this, gridEvent)); | |||
} | |||
} | |||
}); | |||
} | |||
public void addGridHeaderContextMenuListener( | |||
GridContextMenuOpenListener<T> listener) { | |||
addGridSectionContextMenuListener(Section.HEADER, listener); | |||
} | |||
public void addGridFooterContextMenuListener( | |||
GridContextMenuOpenListener<T> listener) { | |||
addGridSectionContextMenuListener(Section.FOOTER, listener); | |||
} | |||
public void addGridBodyContextMenuListener( | |||
GridContextMenuOpenListener<T> listener) { | |||
addGridSectionContextMenuListener(Section.BODY, listener); | |||
} | |||
public interface GridContextMenuOpenListener<T> | |||
extends EventListener, Serializable { | |||
public void onContextMenuOpen(GridContextMenuOpenEvent<T> event); | |||
public static class GridContextMenuOpenEvent<T> | |||
extends ContextMenuOpenEvent { | |||
private final T item; | |||
private final Grid<T> component; | |||
private final int rowIndex; | |||
private final Column<T, ?> column; | |||
private final Section section; | |||
public GridContextMenuOpenEvent(ContextMenu contextMenu, | |||
GridContextClickEvent<T> contextClickEvent) { | |||
super(contextMenu, contextClickEvent); | |||
item = contextClickEvent.getItem(); | |||
component = contextClickEvent.getComponent(); | |||
rowIndex = contextClickEvent.getRowIndex(); | |||
column = contextClickEvent.getColumn(); | |||
section = contextClickEvent.getSection(); | |||
} | |||
public T getItem() { | |||
return item; | |||
} | |||
public Grid<T> getComponent() { | |||
return component; | |||
} | |||
public int getRowIndex() { | |||
return rowIndex; | |||
} | |||
public Column<T, ?> getColumn() { | |||
return column; | |||
} | |||
public Section getSection() { | |||
return section; | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,99 @@ | |||
package com.vaadin.tests.widgetset.contextmenu.demo; | |||
import com.vaadin.annotations.Theme; | |||
import com.vaadin.annotations.Widgetset; | |||
import com.vaadin.icons.VaadinIcons; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.tests.components.AbstractTestUI; | |||
import com.vaadin.tests.widgetset.TestingWidgetSet; | |||
import com.vaadin.tests.widgetset.contextmenu.ContextMenu; | |||
import com.vaadin.ui.Button; | |||
import com.vaadin.ui.MenuBar; | |||
import com.vaadin.ui.Notification; | |||
import com.vaadin.ui.VerticalLayout; | |||
@SuppressWarnings({ "serial", "unchecked" }) | |||
@Theme("contextmenu") | |||
@Widgetset(TestingWidgetSet.NAME) | |||
public class ContextmenuUI extends AbstractTestUI { | |||
Button but3 = new Button("remove Tooltip"); | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
final VerticalLayout layout = new VerticalLayout(); | |||
layout.setMargin(true); | |||
setContent(layout); | |||
Button button = new Button("Button 1"); | |||
layout.addComponent(button); | |||
Button button2 = new Button("Button 2"); | |||
layout.addComponent(button2); | |||
ContextMenu contextMenu = new ContextMenu(this, false); | |||
fillMenu(contextMenu); | |||
contextMenu.setAsContextMenuOf(button); | |||
contextMenu.setAsContextMenuOf(button2); | |||
contextMenu.addContextMenuOpenListener( | |||
new ContextMenu.ContextMenuOpenListener() { | |||
@Override | |||
public void onContextMenuOpen(ContextMenuOpenEvent event) { | |||
Notification.show("Context menu on" | |||
+ event.getSourceComponent().getCaption()); | |||
} | |||
}); | |||
layout.addComponent(new GridWithGenericListener()); | |||
layout.addComponent(new GridWithGridListener()); | |||
layout.addComponent(but3); | |||
layout.addComponent(new Button("Remove items from context menu", e -> { | |||
contextMenu.removeItems(); | |||
})); | |||
} | |||
private void fillMenu(ContextMenu menu) { | |||
final MenuBar.MenuItem item = menu.addItem("Checkable", e -> { | |||
Notification.show("checked: " + e.isChecked()); | |||
}); | |||
item.setCheckable(true); | |||
item.setChecked(true); | |||
MenuBar.MenuItem item2 = menu.addItem("Disabled", e -> { | |||
Notification.show("disabled"); | |||
}); | |||
item2.setDescription("Disabled item"); | |||
item2.setEnabled(false); | |||
MenuBar.MenuItem item3 = menu.addItem("Invisible", e -> { | |||
Notification.show("invisible"); | |||
}); | |||
item3.setVisible(false); | |||
if (menu instanceof ContextMenu) { | |||
((ContextMenu) menu).addSeparator(); | |||
} | |||
MenuBar.MenuItem item4 = menu | |||
.addItem("Icon + Description + <b>HTML</b>", e -> { | |||
Notification.show("icon"); | |||
}); | |||
item4.setIcon(VaadinIcons.ADJUST); | |||
item4.setDescription("Test tooltip"); | |||
but3.addClickListener(e -> item4.setDescription("")); | |||
MenuBar.MenuItem item5 = menu.addItem("Custom stylename", e -> { | |||
Notification.show("stylename"); | |||
}); | |||
item5.setStyleName("teststyle"); | |||
MenuBar.MenuItem item6 = menu.addItem("Submenu", e -> { | |||
}); | |||
item6.addItem("Subitem", e -> Notification.show("SubItem")); | |||
item6.addSeparator(); | |||
item6.addItem("Subitem", e -> Notification.show("SubItem")) | |||
.setDescription("Test"); | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
package com.vaadin.tests.widgetset.contextmenu.demo; | |||
import java.util.Collections; | |||
import com.vaadin.data.provider.ListDataProvider; | |||
import com.vaadin.tests.widgetset.contextmenu.ContextMenu; | |||
import com.vaadin.ui.Grid; | |||
import com.vaadin.ui.Notification; | |||
public class GridWithGenericListener extends Grid<String[]> { | |||
private static final String FIRST_NAME = "First name"; | |||
private static final String LAST_NAME = "Last name"; | |||
private static final String SHOE_SIZE = "Shoe size"; | |||
public GridWithGenericListener() { | |||
setCaption("Grid with generic listener"); | |||
ContextMenu contextMenu2 = new ContextMenu(this, true); | |||
setHeightByRows(3); | |||
addColumn(arr -> arr[0]).setCaption(FIRST_NAME); | |||
addColumn(arr -> arr[1]).setCaption(LAST_NAME); | |||
addColumn(arr -> arr[2]).setCaption(SHOE_SIZE); | |||
ListDataProvider<String[]> ds = new ListDataProvider<>(Collections | |||
.singletonList(new String[] { "John", "Doe", "57" })); | |||
setDataProvider(ds); | |||
contextMenu2.addContextMenuOpenListener(this::onGenericContextMenu); | |||
} | |||
private void onGenericContextMenu( | |||
ContextMenu.ContextMenuOpenListener.ContextMenuOpenEvent event) { | |||
GridContextClickEvent<String[]> gridE = (GridContextClickEvent<String[]>) event | |||
.getContextClickEvent(); | |||
ContextMenu menu = event.getContextMenu(); | |||
menu.removeItems(); | |||
if (gridE.getColumn() != null) { | |||
menu.addItem( | |||
"Called from column " + gridE.getColumn().getCaption() | |||
+ " on row " + gridE.getRowIndex(), | |||
f -> Notification.show("did something")); | |||
} else if (gridE.getRowIndex() >= 0) { | |||
menu.addItem("Called on row " + gridE.getRowIndex(), | |||
f -> Notification.show("did something")); | |||
} else { | |||
menu.addItem("Called on background", | |||
f -> Notification.show("did something")); | |||
} | |||
} | |||
} |
@@ -0,0 +1,53 @@ | |||
package com.vaadin.tests.widgetset.contextmenu.demo; | |||
import java.util.Collections; | |||
import com.vaadin.data.provider.ListDataProvider; | |||
import com.vaadin.tests.widgetset.contextmenu.GridContextMenu; | |||
import com.vaadin.ui.Grid; | |||
public class GridWithGridListener extends Grid<String[]> { | |||
public GridWithGridListener() { | |||
setCaption("Grid with Grid specific listener"); | |||
setHeightByRows(3); | |||
final GridContextMenu<String[]> gridContextMenu = new GridContextMenu<>( | |||
this); | |||
addColumn(arr -> arr[0]).setCaption("Column 1(right-click here)"); | |||
addColumn(arr -> arr[1]).setCaption("Column 2(right-click here)"); | |||
final ListDataProvider<String[]> dataSource = new ListDataProvider<>( | |||
Collections.singletonList(new String[] { "foo", "bar" })); | |||
setDataProvider(dataSource); | |||
gridContextMenu.addGridHeaderContextMenuListener(e -> { | |||
gridContextMenu.removeItems(); | |||
gridContextMenu.addItem(getText(e), null); | |||
}); | |||
gridContextMenu.addGridBodyContextMenuListener(e -> { | |||
gridContextMenu.removeItems(); | |||
gridContextMenu.addItem(getText(e), null); | |||
}); | |||
} | |||
private static String getText( | |||
final GridContextMenu.GridContextMenuOpenListener.GridContextMenuOpenEvent<String[]> e) { | |||
final Column<String[], ?> column = e.getColumn(); | |||
final String columnText; | |||
if (column != null) { | |||
columnText = "'" + column.getCaption() + "'"; | |||
} else { | |||
columnText = "'?'"; | |||
} | |||
final String gridCaption = e.getComponent() == null ? "(NULL)" | |||
: e.getComponent().getCaption(); | |||
return "Context menu for " + e.getSection() + ", column: " + columnText | |||
+ ", gridCaption: " + gridCaption; | |||
} | |||
} |