/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.menu;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import org.eclipse.che.ide.api.action.Action;
import org.eclipse.che.ide.api.action.ActionGroup;
import org.eclipse.che.ide.api.action.ActionManager;
import org.eclipse.che.ide.api.action.ActionSelectedHandler;
import org.eclipse.che.ide.api.action.DefaultActionGroup;
import org.eclipse.che.ide.api.action.IdeActions;
import org.eclipse.che.ide.api.keybinding.KeyBindingAgent;
import org.eclipse.che.ide.api.parts.PerspectiveManager;
import org.eclipse.che.ide.ui.toolbar.CloseMenuHandler;
import org.eclipse.che.ide.ui.toolbar.MenuLockLayer;
import org.eclipse.che.ide.ui.toolbar.PopupMenu;
import org.eclipse.che.ide.ui.toolbar.PresentationFactory;
import static com.google.gwt.dom.client.Style.Unit.PX;
/**
* Manages the Content menu.
* Call <b>show</b> method to show menu and <b>hide</b> to hide it.
* Also this manager filters the list of actions and displays only actions that are belong to Main MachineContext menu group.
*
* @author Vitaliy Guliy
* @author Dmitry Shnurenko
* @author Vlad Zhukovskyi
*/
@Singleton
public class ContextMenu implements CloseMenuHandler, ActionSelectedHandler {
private final ActionManager actionManager;
private final KeyBindingAgent keyBindingAgent;
private final Provider<PerspectiveManager> managerProvider;
private PopupMenu popupMenu;
private MenuLockLayer lockLayer;
protected final PresentationFactory presentationFactory;
@Inject
public ContextMenu(ActionManager actionManager, KeyBindingAgent keyBindingAgent, Provider<PerspectiveManager> managerProvider) {
this.actionManager = actionManager;
this.keyBindingAgent = keyBindingAgent;
this.managerProvider = managerProvider;
presentationFactory = new PresentationFactory();
blockBrowserMenu();
}
/**
* Add a handler to block browser content menu.
*/
private void blockBrowserMenu() {
com.google.gwt.user.client.Event.sinkEvents(RootPanel.getBodyElement(), com.google.gwt.user.client.Event.ONCONTEXTMENU);
DOM.setEventListener(RootPanel.getBodyElement(), new com.google.gwt.user.client.EventListener() {
@Override
public void onBrowserEvent(com.google.gwt.user.client.Event event) {
if (com.google.gwt.user.client.Event.ONCONTEXTMENU == event.getTypeInt()) {
event.stopPropagation();
event.preventDefault();
}
}
});
}
/**
* Shows a content menu and moves it to specified position.
*
* @param x
* x coordinate
* @param y
* y coordinate
*/
public void show(final int x, final int y) {
hide();
ActionGroup actions = updateActions();
lockLayer = new MenuLockLayer(this);
popupMenu = new PopupMenu(actions,
actionManager,
managerProvider,
presentationFactory,
lockLayer,
this,
keyBindingAgent,
"contextMenu");
popupMenu.getElement().getStyle().setProperty("opacity", "0");
popupMenu.getElement().getStyle().setProperty("transition", "opacity 0.5s ease");
lockLayer.add(popupMenu);
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
@Override
public void execute() {
popupMenu.getElement().getStyle().setProperty("opacity", "1");
updateMenuPosition(popupMenu, x, y);
}
});
}
private void updateMenuPosition(PopupMenu popupMenu, int x, int y) {
if (x + popupMenu.getOffsetWidth() > Window.getClientWidth()) {
popupMenu.getElement().getStyle().setLeft(x - popupMenu.getOffsetWidth() - 1, PX);
} else {
popupMenu.getElement().getStyle().setLeft(x, PX);
}
if (y + popupMenu.getOffsetHeight() > Window.getClientHeight()) {
popupMenu.getElement().getStyle().setTop(y - popupMenu.getOffsetHeight() - 1, PX);
} else {
popupMenu.getElement().getStyle().setTop(y, PX);
}
}
/**
* Updates the list of visible actions.
*/
protected ActionGroup updateActions() {
final ActionGroup actionGroup = (ActionGroup)actionManager.getAction(getGroupMenu());
if (actionGroup == null) {
return new DefaultActionGroup(actionManager);
}
return actionGroup;
}
protected String getGroupMenu() {
return IdeActions.GROUP_MAIN_CONTEXT_MENU;
}
@Override
public void onActionSelected(Action action) {
hide();
}
@Override
public void onCloseMenu() {
hide();
}
/**
* Hides opened content menu.
*/
public void hide() {
if (popupMenu != null) {
popupMenu.removeFromParent();
popupMenu = null;
}
if (lockLayer != null) {
lockLayer.removeFromParent();
lockLayer = null;
}
}
}