View Javadoc
1   /*
2    * Copyright 2000-2018 Vaadin Ltd.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License. You may obtain a copy of
6    * the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  
17  package com.vaadin.contextmenu.client;
18  
19  import com.google.gwt.core.client.Scheduler;
20  import com.google.gwt.dom.client.Document;
21  import com.google.gwt.dom.client.SpanElement;
22  import com.google.gwt.event.dom.client.KeyCodes;
23  import com.google.gwt.event.logical.shared.CloseEvent;
24  import com.google.gwt.user.client.ui.PopupPanel;
25  import com.vaadin.client.WidgetUtil;
26  import com.vaadin.client.ui.Icon;
27  import com.vaadin.client.ui.VMenuBar;
28  import com.vaadin.client.ui.VOverlay;
29  
30  import java.util.List;
31  
32  public class VContextMenu extends VMenuBar {
33  
34      public ContextMenuConnector connector;
35  
36      private static VContextMenu currentVisibleContextMenu;
37  
38      public VContextMenu(boolean subMenu, VMenuBar parentMenu) {
39          super(subMenu, parentMenu);
40      }
41  
42      public VContextMenu() {
43      }
44  
45      public void showRootMenu(int x, int y) {
46          if (currentVisibleContextMenu != null) {
47              Scheduler.get().scheduleDeferred(() -> showRootMenu(x,y));
48          } else {
49              CustomMenuItem rootItem = items.get(0);
50              VMenuBar rootSubMenu = rootItem.getSubMenu();
51              List<CustomMenuItem> items = rootSubMenu.getItems();
52              if (!items.isEmpty()) {
53                  setSelected(rootItem);
54                  currentVisibleContextMenu = this;
55                  super.showChildMenuAt(rootItem, y, x);
56                  rootSubMenu.setSelected(items.get(0));
57              }
58          }
59      }
60  
61      @Override
62      public void onClose(CloseEvent<PopupPanel> event) {
63          super.close(event, currentVisibleContextMenu == null);
64          currentVisibleContextMenu = null;
65      }
66  
67      @Override
68      protected VOverlay createOverlay() {
69          VOverlay overlay = super.createOverlay();
70          for (VMenuBar current = this; current != null; current = current
71                  .getParentMenu()) {
72              if (current.client != null) {
73                  overlay.setApplicationConnection(current.client);
74                  break;
75              }
76          }
77          return overlay;
78      }
79  
80      @Override
81      public boolean handleNavigation(int keycode, boolean ctrl, boolean shift) {
82          if (keycode == KeyCodes.KEY_TAB) {
83              return true;
84          }
85          if (keycode == getNavigationUpKey() && getSelected() != null && items.indexOf(getSelected()) == 0 && (getParentMenu() == null
86                  || getParentMenu().getParentMenu() == null)) {
87              setSelected(items.get(items.size() - 1));
88              // do not close parent menu by up key
89              return true;
90          }
91          if (keycode == getNavigationLeftKey() && (getParentMenu() == null
92                  || getParentMenu().getParentMenu() == null)) {
93              // do not close parent menu by left key
94              return true;
95          }
96          if (keycode == getNavigationRightKey() && getSelected() != null
97                  && getSelected().getSubMenu() == null) {
98              // do not close menu by right key if there is no submenu
99              return true;
100         }
101         return super.handleNavigation(keycode, ctrl, shift);
102     }
103 
104     @Override
105     public void onMenuClick(int clickedItemId) {
106         connector.onMenuClick(clickedItemId);
107     }
108 
109     @Override
110     protected VMenuBar getRoot() {
111         VMenuBar root = this;
112 
113         while (root.getParentMenu() != null
114                 && root.getParentMenu().getParentMenu() != null) {
115             root = root.getParentMenu();
116         }
117 
118         return root;
119     }
120 
121     @Override
122     public String buildItemHTML(boolean separator, boolean subMenu,
123                                 String iconUrl, String text) {
124         // Construct html from the text and the optional icon
125         StringBuilder itemHTML = new StringBuilder();
126         if (separator) {
127             itemHTML.append("<span>---</span>");
128         } else {
129             // Add submenu indicator
130             if (subMenu) {
131                 String bgStyle = "";
132                 itemHTML.append("<span class=\"" + getStylePrimaryName()
133                         + "-submenu-indicator\"" + bgStyle
134                         + " aria-hidden=\"true\">&#x25BA;</span>");
135             }
136 
137             itemHTML.append("<span class=\"" + getStylePrimaryName()
138                     + "-menuitem-caption\">");
139             // Magnolia Icon Font patch (compatibility framework)
140             String ICON_FONT_CODE = "iconfont#";
141             if (iconUrl.startsWith(ICON_FONT_CODE)) {
142                 SpanElement iconFont;
143                 iconFont = Document.get().createSpanElement();
144                 String iconFontCssClass = iconUrl.substring(ICON_FONT_CODE.length());
145                 iconFont.setClassName("v-icon " + iconFontCssClass);
146                 itemHTML.append(iconFont.getString());
147             } else {
148                 Icon icon = client.getIcon(iconUrl);
149                 if (icon != null) {
150                     itemHTML.append(icon.getElement().getString());
151                 }
152             }
153             String itemText = text;
154             if (!htmlContentAllowed) {
155                 itemText = WidgetUtil.escapeHTML(itemText);
156             }
157             itemHTML.append(itemText);
158             itemHTML.append("</span>");
159         }
160         return itemHTML.toString();
161     }
162 }