1 package org.vaadin.peter.contextmenu.client;
2
3 import org.vaadin.peter.contextmenu.client.ContextMenuState.ContextMenuItemState;
4
5 import com.google.gwt.core.client.GWT;
6 import com.google.gwt.dom.client.Element;
7 import com.google.gwt.event.dom.client.KeyCodes;
8 import com.google.gwt.event.logical.shared.CloseHandler;
9 import com.google.gwt.user.client.DOM;
10 import com.google.gwt.user.client.Event;
11 import com.google.gwt.user.client.Event.NativePreviewEvent;
12 import com.google.gwt.user.client.Event.NativePreviewHandler;
13 import com.google.gwt.user.client.Window;
14 import com.google.gwt.user.client.ui.PopupPanel;
15 import com.google.gwt.user.client.ui.Widget;
16 import com.vaadin.client.extensions.AbstractExtensionConnector;
17
18
19
20
21
22
23 public class ContextMenuWidget extends Widget {
24 private final ContextMenuOverlay menuOverlay;
25
26 private final NativePreviewHandler nativeEventHandler = new NativePreviewHandler() {
27
28 @Override
29 public void onPreviewNativeEvent(NativePreviewEvent event) {
30 if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ESCAPE) {
31
32 hide();
33 }
34
35 Event nativeEvent = Event.as(event.getNativeEvent());
36 boolean targetsContextMenu = eventTargetContextMenu(nativeEvent);
37
38 if (!targetsContextMenu) {
39 int type = nativeEvent.getTypeInt();
40 switch (type) {
41 case Event.ONMOUSEDOWN: {
42 hide();
43 }
44 }
45 }
46 }
47 };
48
49 public ContextMenuWidget() {
50 Element element = DOM.createDiv();
51 setElement(element);
52
53 Event.addNativePreviewHandler(nativeEventHandler);
54
55 menuOverlay = new ContextMenuOverlay();
56 }
57
58 protected boolean eventTargetContextMenu(Event nativeEvent) {
59 for (ContextMenuItemWidget item : menuOverlay.getMenuItems()) {
60 if (item.eventTargetsPopup(nativeEvent)) {
61 return true;
62 }
63 }
64
65 return false;
66 }
67
68 protected boolean isShowing() {
69 return menuOverlay.isShowing();
70 }
71
72 public void hide() {
73 menuOverlay.hide();
74 }
75
76
77
78
79
80
81
82 public void addRootMenuItem(ContextMenuItemState rootItem,
83 AbstractExtensionConnector connector) {
84 ContextMenuItemWidget itemWidget = createEmptyItemWidget(rootItem.id,
85 rootItem.caption, connector);
86 itemWidget.setEnabled(rootItem.enabled);
87 itemWidget.setSeparatorVisible(rootItem.separator);
88
89 menuOverlay.addMenuItem(itemWidget);
90
91 for (ContextMenuItemState childState : rootItem.getChildren()) {
92 createSubMenu(itemWidget, childState, connector);
93 }
94 }
95
96
97
98
99
100
101
102
103
104 private ContextMenuItemWidget createEmptyItemWidget(String id,
105 String caption, AbstractExtensionConnector contextMenuConnector) {
106 ContextMenuItemWidget widget = GWT.create(ContextMenuItemWidget.class);
107 widget.setId(id);
108 widget.setCaption(caption);
109
110 widget.setIcon(contextMenuConnector.getResourceUrl(id));
111
112 ContextMenuItemWidgetHandler handler = new ContextMenuItemWidgetHandler(
113 widget, contextMenuConnector);
114 widget.addClickHandler(handler);
115 widget.addMouseOutHandler(handler);
116 widget.addMouseOverHandler(handler);
117 widget.addKeyUpHandler(handler);
118 widget.setRootComponent(this);
119
120 return widget;
121 }
122
123 private void createSubMenu(ContextMenuItemWidget parentWidget,
124 ContextMenuItemState childState, AbstractExtensionConnector connector) {
125 ContextMenuItemWidget childWidget = createEmptyItemWidget(
126 childState.id, childState.caption, connector);
127 childWidget.setEnabled(childState.enabled);
128 childWidget.setSeparatorVisible(childState.separator);
129 parentWidget.addSubMenuItem(childWidget);
130
131 for (ContextMenuItemState child : childState.getChildren()) {
132 createSubMenu(childWidget, child, connector);
133 }
134 }
135
136 public void clearItems() {
137 menuOverlay.clearItems();
138 }
139
140 public void showContextMenu(int rootMenuX, int rootMenuY) {
141 rootMenuX += Window.getScrollLeft();
142 rootMenuY += Window.getScrollTop();
143
144 menuOverlay.showAt(rootMenuX, rootMenuY);
145 }
146
147 public void addCloseHandler(CloseHandler<PopupPanel> popupCloseHandler) {
148 menuOverlay.addCloseHandler(popupCloseHandler);
149 }
150 }