org.opencms.ui.client.contextmenu.CmsContextMenuOverlay Maven / Gradle / Ivy
Show all versions of opencms-gwt Show documentation
package org.opencms.ui.client.contextmenu;
import org.opencms.gwt.client.util.CmsDomUtil;
import org.opencms.gwt.client.util.CmsDomUtil.Style;
import java.util.LinkedList;
import java.util.List;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.PopupPanel;
import com.vaadin.client.ui.VOverlay;
/**
* Menu is a visible item of ContextMenu component. For every child menu new
* instance of Menu class will be instantiated.
*
* Adapted from ContextMenu by Peter Lehto / Vaadin Ltd.
*/
@SuppressWarnings("deprecation")
class CmsContextMenuOverlay extends VOverlay {
/** The close handler. */
private final CloseHandler m_closeHandler = new CloseHandler() {
@Override
public void onClose(CloseEvent event) {
unfocusAll();
}
};
/** The close handler registration. */
private final HandlerRegistration m_closeHandlerRegistration;
/** The menu items. */
private final List m_menuItems;
/** The root panel. */
private final FlowPanel m_root;
/**
* Constructor.
*/
public CmsContextMenuOverlay() {
super(false, false);
m_closeHandlerRegistration = addCloseHandler(m_closeHandler);
setStyleName("v-context-menu-container");
m_root = new FlowPanel();
m_root.setStyleName("v-context-menu");
m_menuItems = new LinkedList();
add(m_root);
}
/**
* Adds a menu item.
*
* @param menuItem the item to add
*/
public void addMenuItem(CmsContextMenuItemWidget menuItem) {
menuItem.setOverlay(this);
m_menuItems.add(menuItem);
m_root.add(menuItem);
}
/**
* Clears the menu items.
*/
public void clearItems() {
m_menuItems.clear();
m_root.clear();
}
/**
* Closes the sub menus.
*/
public void closeSubMenus() {
for (CmsContextMenuItemWidget child : m_menuItems) {
child.hideSubMenu();
}
}
/**
* Returns the menu items.
*
* @return the menu items
*/
public List getMenuItems() {
return m_menuItems;
}
/**
* Returns the number of menu items.
*
* @return number of visible items in this menu
*/
public int getNumberOfItems() {
return this.m_menuItems.size();
}
/**
* Hides the overlay.
*/
@Override
public void hide() {
unfocusAll();
closeSubMenus();
super.hide();
}
/**
* Returns whether the sub menu is open.
*
* @return true
if the sub menu is open
*/
public boolean isSubmenuOpen() {
for (CmsContextMenuItemWidget item : m_menuItems) {
if (item.isSubmenuOpen()) {
return true;
}
}
return false;
}
/**
* Opens next to the given parent item.
*
* @param parentMenuItem the perent item
*/
public void openNextTo(CmsContextMenuItemWidget parentMenuItem) {
int left = parentMenuItem.getAbsoluteLeft() + parentMenuItem.getOffsetWidth();
int top = parentMenuItem.getAbsoluteTop() - Window.getScrollTop();
showAt(left, top);
}
/**
* Selects the next sibling.
*
* @param item the item
*/
public void selectItemAfter(CmsContextMenuItemWidget item) {
int index = m_menuItems.indexOf(item);
index += 1;
if (index >= m_menuItems.size()) {
index = 0;
}
CmsContextMenuItemWidget itemToSelect = m_menuItems.get(index);
itemToSelect.setFocus(true);
}
/**
* Selects the previous sibling.
*
* @param item the item
*/
public void selectItemBefore(CmsContextMenuItemWidget item) {
int index = m_menuItems.indexOf(item);
index -= 1;
if (index < 0) {
index = m_menuItems.size() - 1;
}
CmsContextMenuItemWidget itemToSelect = m_menuItems.get(index);
itemToSelect.setFocus(true);
}
/**
* Sets the focus.
*
* @param focused the focus
*/
public void setFocus(boolean focused) {
unfocusAll();
if (focused) {
focusFirstItem();
}
}
/**
* @see com.google.gwt.user.client.ui.PopupPanel#setPopupPositionAndShow(com.google.gwt.user.client.ui.PopupPanel.PositionCallback)
*/
@Override
public void setPopupPositionAndShow(PositionCallback callback) {
super.setPopupPositionAndShow(callback);
normalizeItemWidths();
}
/**
* Shows the overlay at the given position.
*
* @param x the client x position
* @param y the client y position
*/
public void showAt(final int x, final int y) {
setPopupPositionAndShow(new PopupPanel.PositionCallback() {
@Override
public void setPosition(int offsetWidth, int offsetHeight) {
int left = x + Window.getScrollLeft();
int top = y + Window.getScrollTop();
int exceedingWidth = (offsetWidth + left) - (Window.getClientWidth() + Window.getScrollLeft());
if (exceedingWidth > 0) {
left -= exceedingWidth;
if (left < 0) {
left = 0;
}
}
int exceedingHeight = (offsetHeight + top) - (Window.getClientHeight() + Window.getScrollTop());
if (exceedingHeight > 0) {
top -= exceedingHeight;
if (top < 0) {
top = 0;
}
}
setPopupPosition(left, top);
}
});
}
/**
* Unregisters the close handler.
*/
public void unregister() {
m_closeHandlerRegistration.removeHandler();
hide();
}
/**
* Returns whether the given event targets the popup.
*
* @param event the event to check
*
* @return true
if the event targets the popup
*/
protected boolean eventTargetsPopup(NativeEvent event) {
EventTarget target = event.getEventTarget();
if (Element.is(target)) {
return getElement().isOrHasChild(Element.as(target));
}
return false;
}
/**
* Normalizes the item width.
*/
protected void normalizeItemWidths() {
int widestItemWidth = 1 + getWidthOfWidestItem();
// Add 1 because actual width may not be an integer
for (CmsContextMenuItemWidget item : m_menuItems) {
if (measureWidth(item) <= widestItemWidth) {
item.setWidth(widestItemWidth + "px");
}
}
}
/**
* Removes the focus from all items.
*/
void unfocusAll() {
for (CmsContextMenuItemWidget item : m_menuItems) {
item.setFocus(false);
}
}
/**
* Focuses the first item.
*/
private void focusFirstItem() {
if (m_menuItems.size() > 0) {
m_menuItems.iterator().next().setFocus(true);
}
}
/**
* Returns the item width.
*
* @return the item width
*/
private int getWidthOfWidestItem() {
int maxWidth = 0;
for (CmsContextMenuItemWidget item : m_menuItems) {
item.getElement().getStyle().clearWidth();
int itemWidth = measureWidth(item);
if (itemWidth > maxWidth) {
maxWidth = itemWidth;
}
}
return maxWidth;
}
/**
* Measures the width of a context menu item.
*
* @param item the menu item
* @return the width
*/
private int measureWidth(CmsContextMenuItemWidget item) {
return item.getOffsetWidth()
- CmsDomUtil.getCurrentStyleInt(item.getElement(), Style.paddingLeft)
- CmsDomUtil.getCurrentStyleInt(item.getElement(), Style.paddingRight);
}
}