1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.vaadin.contextmenu.client;
18
19 import java.util.Iterator;
20 import java.util.Stack;
21
22 import com.google.gwt.core.client.GWT;
23 import com.google.gwt.dom.client.Element;
24 import com.google.gwt.dom.client.EventTarget;
25 import com.google.gwt.user.client.Command;
26 import com.google.gwt.user.client.Event;
27 import com.google.gwt.user.client.ui.Widget;
28 import com.vaadin.client.HasWidget;
29 import com.vaadin.client.ServerConnector;
30 import com.vaadin.client.communication.StateChangeEvent;
31 import com.vaadin.client.extensions.AbstractExtensionConnector;
32 import com.vaadin.client.ui.VMenuBar;
33 import com.vaadin.contextmenu.ContextMenu;
34 import com.vaadin.shared.ui.ComponentStateUtil;
35 import com.vaadin.shared.ui.Connect;
36
37 @Connect(ContextMenu.class)
38 public class ContextMenuConnector extends AbstractExtensionConnector
39 implements HasWidget {
40
41 private VContextMenu contextMenu;
42 private VMenuBar.CustomMenuItem contextMenuRoot;
43
44 @Override
45 protected void extend(ServerConnector target) {
46
47 }
48
49 @Override
50 public void onStateChanged(StateChangeEvent event) {
51 super.onStateChanged(event);
52 contextMenu.client = getConnection();
53 updateFromState(getState());
54 }
55
56 protected void updateFromState(ContextMenuState state) {
57
58 contextMenu.enabled = state.enabled;
59 contextMenu.htmlContentAllowed = state.htmlContentAllowed;
60
61 Stack<Iterator<ContextMenuItemState>> iteratorStack = new Stack<>();
62 Stack<VMenuBar> menuStack = new Stack<>();
63 VMenuBar currentMenu = contextMenuRoot.getSubMenu();
64 currentMenu.clearItems();
65 if (state.menuItems != null && !state.menuItems.isEmpty()) {
66 Iterator<ContextMenuItemState> itr = state.menuItems.iterator();
67 while (itr.hasNext()) {
68 ContextMenuItemState menuItemState = itr.next();
69 VMenuBar.CustomMenuItem currentItem;
70
71 boolean itemHasCommand = menuItemState.command;
72 boolean itemIsCheckable = menuItemState.checkable;
73
74 String iconUrl = menuItemState.icon == null ? null
75 : menuItemState.icon.getURL();
76 boolean subMenu = menuItemState.childItems != null
77 && !menuItemState.childItems.isEmpty();
78 String itemHTML = contextMenu.buildItemHTML(
79 menuItemState.separator, subMenu, iconUrl,
80 menuItemState.text);
81
82 Command cmd = null;
83 if (!menuItemState.separator) {
84 if (itemHasCommand || itemIsCheckable) {
85
86
87
88 cmd = () -> contextMenu.onMenuClick(menuItemState.id);
89 }
90 }
91
92 currentItem = currentMenu.addItem(itemHTML, cmd);
93 currentItem.setId("" + menuItemState.id);
94 updateItemFromState(currentItem, menuItemState);
95
96 if (subMenu) {
97 menuStack.push(currentMenu);
98 iteratorStack.push(itr);
99 itr = menuItemState.childItems.iterator();
100 currentMenu = new VContextMenu(true, currentMenu);
101 getConnection().getVTooltip()
102 .connectHandlersToWidget(currentMenu);
103
104
105
106
107 if (ComponentStateUtil.hasStyles(getState())) {
108 for (String style : getState().styles) {
109 currentMenu.addStyleDependentName(style);
110 }
111 }
112 currentItem.setSubMenu(currentMenu);
113 }
114
115 while (!itr.hasNext() && !iteratorStack.empty()) {
116 boolean hasCheckableItem = false;
117 for (VMenuBar.CustomMenuItem menuItem : currentMenu
118 .getItems()) {
119 hasCheckableItem = hasCheckableItem
120 || menuItem.isCheckable();
121 }
122 if (hasCheckableItem) {
123 currentMenu.addStyleDependentName("check-column");
124 } else {
125 currentMenu.removeStyleDependentName("check-column");
126 }
127
128 itr = iteratorStack.pop();
129 currentMenu = menuStack.pop();
130 }
131 }
132 }
133 }
134
135 private void updateItemFromState(VMenuBar.CustomMenuItem currentItem,
136 ContextMenuItemState menuItemState) {
137 currentItem.setSeparator(menuItemState.separator);
138 currentItem.setEnabled(menuItemState.enabled);
139
140 if (!menuItemState.separator && menuItemState.checked) {
141
142
143 currentItem.setCheckable(true);
144 currentItem.setChecked(menuItemState.checked);
145 } else {
146 currentItem.setCheckable(false);
147 }
148
149 currentItem.setStyleName(menuItemState.styleName);
150
151 currentItem.setDescription(menuItemState.description);
152 currentItem.setDescriptionContentMode(
153 menuItemState.descriptionContentMode);
154 if (menuItemState.description != null) {
155 currentItem.getElement().setAttribute("title",
156 menuItemState.description);
157 }
158
159 currentItem.updateStyleNames();
160
161 }
162
163 @Override
164 protected void init() {
165 super.init();
166 contextMenu = GWT.create(VContextMenu.class);
167 contextMenu.connector = this;
168 contextMenuRoot = contextMenu.addItem("", null);
169 contextMenuRoot.setSubMenu(new VContextMenu(true, contextMenu));
170
171 registerRpc(ContextMenuClientRpc.class, new ContextMenuClientRpc() {
172 @Override
173 public void showContextMenu(int x, int y) {
174 contextMenu.showRootMenu(x, y);
175 }
176 });
177
178 Event.addNativePreviewHandler(new Event.NativePreviewHandler() {
179 @Override
180 public void onPreviewNativeEvent(Event.NativePreviewEvent event) {
181 if (event.getTypeInt() == Event.ONMOUSEWHEEL && contextMenu.isVisible()) {
182 EventTarget eventTarget = event.getNativeEvent().getEventTarget();
183 if (contextMenu.getRoot().getMenuItemWithElement(Element.as(eventTarget)) == null) {
184 contextMenu.hideParents(true);
185 }
186 }
187 }
188 });
189
190 }
191
192 @Override
193 public ContextMenuState getState() {
194 return (ContextMenuState) super.getState();
195 }
196
197 public void onMenuClick(int clickedItemId) {
198 getRpcProxy(ContextMenuServerRpc.class).itemClicked(clickedItemId);
199 }
200
201 @Override
202 public Widget getWidget() {
203 return contextMenuRoot.getSubMenu();
204 }
205 }