/*******************************************************************************
* 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.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.eclipse.che.ide.api.action.Action;
import org.eclipse.che.ide.api.action.ActionEvent;
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.CustomComponentAction;
import org.eclipse.che.ide.api.action.IdeActions;
import org.eclipse.che.ide.api.action.Presentation;
import org.eclipse.che.ide.api.action.Separator;
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.PresentationFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Implements {@link StatusPanelGroupView}
*
* @author Oleksii Orel
* @author Dmitry Shnurenko
*/
public class StatusPanelGroupViewImpl extends Composite implements StatusPanelGroupView, CloseMenuHandler, ActionSelectedHandler {
private final MenuResources resources;
private final Provider<PerspectiveManager> perspectiveManager;
private final PresentationFactory presentationFactory = new PresentationFactory();
private final FlowPanel centerPanel = new FlowPanel();
private final FlowPanel rightPanel = new FlowPanel();
private final FlowPanel leftPanel = new FlowPanel();
/** Panel, which contains top menu. */
private final FlowPanel rootPanel = new FlowPanel();
/** Lock layer for displaying popup menus. */
private MenuLockLayer lockLayer;
/** List Menu Bar items. */
private Map<Action, MenuBarItem> action2barItem = new HashMap<>();
/** Store selected Menu Bar item. */
private MenuBarItem selectedMenuBarItem;
private List<Action> rightVisibleActions = new ArrayList<>();
private List<Action> centerVisibleActions = new ArrayList<>();
private List<Action> leftVisibleActions = new ArrayList<>();
private ActionManager actionManager;
/** Create new {@link MainMenuViewImpl} */
@Inject
public StatusPanelGroupViewImpl(MenuResources resources, ActionManager actionManager, Provider<PerspectiveManager> perspectiveManager) {
this.resources = resources;
this.actionManager = actionManager;
this.perspectiveManager = perspectiveManager;
initWidget(rootPanel);
rootPanel.setStyleName(resources.menuCss().menuBar());
rootPanel.addStyleName(resources.menuCss().statusPanel());
leftPanel.addStyleName(resources.menuCss().leftPanel());
leftPanel.getElement().getStyle().setPropertyPx("marginLeft", 1);
rootPanel.add(leftPanel);
centerPanel.setStyleName(resources.menuCss().leftPanel());
rootPanel.add(centerPanel);
rightPanel.addStyleName(resources.menuCss().rightPanel());
rightPanel.getElement().getStyle().setPropertyPx("marginRight", 1);
rootPanel.add(rightPanel);
}
@Override
public void setDelegate(ActionDelegate delegate) {
new Timer() {
@Override
public void run() {
updateMenuActions();
}
}.scheduleRepeating(1000);
}
/** Handle closing of all popup windows. */
public void onCloseMenu() {
selectedMenuBarItem.setNormalState();
selectedMenuBarItem = null;
lockLayer = null;
}
void updateMenuActions() {
if (selectedMenuBarItem != null) {
return;
}
List<Action> newCenterVisibleActions = new ArrayList<>();
expandActionGroup(IdeActions.GROUP_CENTER_STATUS_PANEL, newCenterVisibleActions, actionManager);
if (!newCenterVisibleActions.equals(centerVisibleActions)) {
centerPanel.clear();
for (Action action : newCenterVisibleActions) {
addToPanel(centerPanel, action, presentationFactory);
}
centerVisibleActions = newCenterVisibleActions;
}
List<Action> newRightVisibleActions = new ArrayList<>();
expandActionGroup(IdeActions.GROUP_RIGHT_STATUS_PANEL, newRightVisibleActions, actionManager);
if (!newRightVisibleActions.equals(rightVisibleActions)) {
rightPanel.clear();
for (Action action : newRightVisibleActions) {
addToPanel(rightPanel, action, presentationFactory);
}
rightVisibleActions = newRightVisibleActions;
}
List<Action> newLeftVisibleActions = new ArrayList<>();
expandActionGroup(IdeActions.GROUP_LEFT_STATUS_PANEL, newLeftVisibleActions, actionManager);
if (!newLeftVisibleActions.equals(leftVisibleActions)) {
leftPanel.clear();
for (Action action : newLeftVisibleActions) {
addToPanel(leftPanel, action, presentationFactory);
}
leftVisibleActions = newLeftVisibleActions;
}
centerPanel.getElement().getStyle().setPropertyPx("marginLeft", rootPanel.getOffsetWidth() / 2 - leftPanel.getOffsetWidth() -
centerPanel.getOffsetWidth() / 2);
}
/**
* Create a new widget and add it to panel menu.
*/
private void addToPanel(FlowPanel panel, Action action, PresentationFactory presentationFactory) {
Presentation presentation = presentationFactory.getPresentation(action);
if (action instanceof Separator) {
panel.add(new SeparatorItem(resources.menuCss().panelSeparator()));
// todo find way to render non custom actions
} else if (action instanceof CustomComponentAction) {
CustomComponentAction customComponentAction = (CustomComponentAction)action;
Widget component = customComponentAction.createCustomComponent(presentation);
component.addStyleName(resources.menuCss().customComponent());
panel.add(component);
}
}
private void expandActionGroup(String actionGroupId, final List<Action> newVisibleActions, ActionManager actionManager) {
final ActionGroup mainActionGroup = (ActionGroup)actionManager.getAction(actionGroupId);
if (mainActionGroup == null) return;
expandActionGroup(newVisibleActions, actionManager, mainActionGroup);
}
private void expandActionGroup(List<Action> newVisibleActions, ActionManager actionManager, ActionGroup mainActionGroup) {
final Action[] children = mainActionGroup.getChildren(null);
for (final Action action : children) {
final Presentation presentation = presentationFactory.getPresentation(action);
final ActionEvent e = new ActionEvent(presentation, actionManager, perspectiveManager.get());
action.update(e);
if (presentation.isVisible()) { // add only visible items
newVisibleActions.add(action);
}
if (action2barItem.containsKey(action)) {
action2barItem.get(action).update();
}
}
}
@Override
public void onActionSelected(Action action) {
if (action2barItem.containsKey(action)) {
MenuBarItem item = action2barItem.get(action);
if (selectedMenuBarItem != null && selectedMenuBarItem != item) {
selectedMenuBarItem.setNormalState();
selectedMenuBarItem.closePopupMenu();
}
selectedMenuBarItem = item;
} else {
lockLayer.close();
lockLayer = null;
}
}
private static class SeparatorItem extends Composite {
SeparatorItem(String styleName) {
final FlowPanel widget = new FlowPanel();
widget.addStyleName(styleName);
Element separator = widget.getElement();
for (int i = 0; i < 6; i++) {
separator.appendChild(DOM.createDiv());
}
initWidget(widget);
}
}
}