1 package org.vaadin.peter.contextmenu.client;
2
3 import com.google.gwt.dom.client.Document;
4 import com.google.gwt.dom.client.ImageElement;
5 import com.google.gwt.dom.client.SpanElement;
6 import com.google.gwt.user.client.DOM;
7 import com.google.gwt.user.client.Event;
8 import com.google.gwt.user.client.ui.FlowPanel;
9 import com.google.gwt.user.client.ui.FocusWidget;
10 import com.google.gwt.user.client.ui.Label;
11
12
13
14
15
16
17
18 public class ContextMenuItemWidget extends FocusWidget {
19 private final FlowPanel root;
20
21 protected ImageElement icon;
22 private final FlowPanel iconContainer;
23 private final Label text;
24
25 private ContextMenuOverlay subMenu;
26
27 private ContextMenuItemWidget parentItem;
28 private ContextMenuOverlay overlay;
29
30 private ContextMenuWidget rootComponent;
31
32 private String id;
33
34 public ContextMenuItemWidget() {
35 root = new FlowPanel();
36 root.setStylePrimaryName("v-context-menu-item-basic");
37
38 setElement(root.getElement());
39
40 root.addStyleName("v-context-submenu");
41
42 iconContainer = new FlowPanel();
43 iconContainer.setStyleName("v-context-menu-item-basic-icon-container");
44
45 text = new Label();
46 text.setStyleName("v-context-menu-item-basic-text");
47
48 root.add(iconContainer);
49 root.add(text);
50 }
51
52 @Override
53 public void setFocus(boolean focused) {
54 if (hasSubMenu()) {
55 subMenu.setFocus(false);
56 }
57
58 super.setFocus(focused);
59
60 if (!focused) {
61 DOM.releaseCapture(getElement());
62 }
63 }
64
65
66
67
68 public boolean hasSubMenu() {
69 return subMenu != null && subMenu.getNumberOfItems() > 0;
70 }
71
72
73
74
75 public void hideSubMenu() {
76 if (hasSubMenu()) {
77 subMenu.hide();
78 removeStyleName("v-context-menu-item-basic-open");
79 }
80 }
81
82
83
84
85 public boolean isRootItem() {
86 return parentItem == null;
87 }
88
89
90
91
92
93
94 public void setOverlay(ContextMenuOverlay owner) {
95 this.overlay = owner;
96 }
97
98
99
100
101
102
103
104 public void setParentItem(ContextMenuItemWidget parentItem) {
105 this.parentItem = parentItem;
106 }
107
108
109
110
111 public ContextMenuItemWidget getParentItem() {
112 return parentItem;
113 }
114
115
116
117
118 public boolean isSubmenuOpen() {
119 return hasSubMenu() && subMenu.isShowing();
120 }
121
122
123
124
125
126 public void clearItems() {
127 if (hasSubMenu()) {
128 subMenu.clearItems();
129 }
130 }
131
132
133
134
135
136
137 public void addSubMenuItem(ContextMenuItemWidget contextMenuItem) {
138 if (!hasSubMenu()) {
139 subMenu = new ContextMenuOverlay();
140 setStylePrimaryName("v-context-menu-item-basic-submenu");
141 }
142
143 contextMenuItem.setParentItem(this);
144 subMenu.addMenuItem(contextMenuItem);
145 }
146
147 public void setCaption(String caption) {
148 text.setText(caption);
149 }
150
151 public void setIcon(String url) {
152 if (url == null) {
153 iconContainer.clear();
154 icon = null;
155 } else {
156
157
158 String ICON_FONT_CODE = "iconfont#";
159 if (url.startsWith(ICON_FONT_CODE)) {
160 SpanElement iconFont;
161 iconFont = Document.get().createSpanElement();
162 String iconFontCssClass = url.substring(ICON_FONT_CODE.length());
163 iconFont.setClassName("v-icon " + iconFontCssClass);
164 iconContainer.getElement().appendChild(iconFont);
165 }
166 else {
167
168 icon = Document.get().createImageElement();
169 icon.setClassName("v-icon");
170 icon.setSrc(url);
171 iconContainer.getElement().appendChild(icon);
172 }
173
174 }
175 }
176
177 public void setRootComponent(ContextMenuWidget rootComponent) {
178 this.rootComponent = rootComponent;
179 }
180
181 public void setId(String id) {
182 this.id = id;
183 }
184
185 public String getId() {
186 return id;
187 }
188
189 public void closeSiblingMenus() {
190 overlay.closeSubMenus();
191 }
192
193 protected void selectLowerSibling() {
194 setFocus(false);
195 overlay.selectItemAfter(ContextMenuItemWidget.this);
196
197 }
198
199 protected void selectUpperSibling() {
200 setFocus(false);
201 overlay.selectItemBefore(ContextMenuItemWidget.this);
202 }
203
204 protected void closeThisAndSelectParent() {
205 if (!isRootItem()) {
206 setFocus(false);
207 parentItem.hideSubMenu();
208 parentItem.setFocus(true);
209 }
210 }
211
212
213
214
215
216
217
218 protected boolean onItemClicked() {
219 if (isEnabled()) {
220 overlay.closeSubMenus();
221
222 if (hasSubMenu()) {
223 openSubMenu();
224 return false;
225 } else {
226 if (isRootItem()) {
227 closeContextMenu();
228 } else {
229 parentItem.closeContextMenu();
230 }
231
232 return true;
233 }
234 }
235
236 return false;
237 }
238
239 private void closeContextMenu() {
240 if (isRootItem()) {
241 rootComponent.hide();
242 } else {
243 parentItem.closeContextMenu();
244 }
245 }
246
247
248
249
250 private void openSubMenu() {
251 if (isEnabled() && hasSubMenu() && !subMenu.isShowing()) {
252 overlay.closeSubMenus();
253
254 setFocus(false);
255 addStyleName("v-context-menu-item-basic-open");
256 subMenu.openNextTo(this);
257 }
258 }
259
260
261
262
263
264
265 public boolean eventTargetsPopup(Event nativeEvent) {
266 if (overlay.eventTargetsPopup(nativeEvent)) {
267 return true;
268 }
269
270 if (hasSubMenu()) {
271 for (ContextMenuItemWidget item : subMenu.getMenuItems()) {
272 if (item.eventTargetsPopup(nativeEvent)) {
273 return true;
274 }
275 }
276 }
277
278 return false;
279 }
280
281 public void setSeparatorVisible(boolean separatorVisible) {
282 if (separatorVisible) {
283 root.addStyleName("v-context-menu-item-separator");
284 } else {
285 root.removeStyleName("v-context-menu-item-separator");
286 }
287 }
288
289 @Override
290 public void setEnabled(boolean enabled) {
291 super.setEnabled(enabled);
292 if (enabled) {
293 root.removeStyleName("v-context-menu-item-disabled");
294 } else {
295 root.addStyleName("v-context-menu-item-disabled");
296 }
297 }
298 }