/*******************************************************************************
* 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.ui.menubutton;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusWidget;
import org.vectomatic.dom.svg.ui.SVGResource;
import java.util.List;
import java.util.Optional;
import static com.google.gwt.dom.client.NativeEvent.BUTTON_LEFT;
import static java.util.Optional.ofNullable;
/** Button with popup menu. */
public class MenuButton extends FlowPanel {
private static final Resources RESOURCES;
protected final ItemsProvider itemsProvider;
private final Timer showMenuTimer;
private ActionHandler actionHandler;
private ItemsList menu;
public MenuButton(SafeHtml content, ItemsProvider itemsProvider) {
super();
this.itemsProvider = itemsProvider;
addStyleName(RESOURCES.css().menuButton());
showMenuTimer = new Timer() {
@Override
public void run() {
showMenu();
}
};
final FocusWidget mainButton = new MainButton(content);
final FocusWidget dropButton = new DropButton();
add(mainButton);
add(dropButton);
attachMouseEventHandlers(mainButton);
attachMouseEventHandlers(dropButton);
}
private void attachMouseEventHandlers(FocusWidget widget) {
widget.addMouseOutHandler(event -> showMenuTimer.cancel());
widget.addMouseUpHandler(event -> showMenuTimer.cancel());
widget.addMouseDownHandler(event -> {
if (event.getNativeButton() == BUTTON_LEFT) {
showMenuTimer.schedule(1000);
} else {
showMenuTimer.cancel();
}
});
}
public Optional<ActionHandler> getActionHandler() {
return ofNullable(actionHandler);
}
/** Set {@link ActionHandler} to handle {@link MenuItem}s selection. */
public void setActionHandler(ActionHandler actionHandler) {
this.actionHandler = actionHandler;
}
private void showMenu() {
final List<MenuItem> items = itemsProvider.getItems();
if (!items.isEmpty()) {
menu = new ItemsList(items, itemsProvider, RESOURCES, null);
getActionHandler().ifPresent(handler -> menu.setActionHandler(handler));
menu.setPopupPosition(getAbsoluteLeft(), getAbsoluteTop() + getOffsetHeight());
menu.show();
}
}
public interface Resources extends ClientBundle {
@Source({"button.css", "org/eclipse/che/ide/api/ui/style.css"})
Css css();
@Source("arrowIcon.svg")
SVGResource arrowIcon();
}
public interface Css extends CssResource {
String menuButton();
String button();
String mainButton();
String dropButton();
String popupPanel();
String expandedImage();
String popupItem();
String popupItemOver();
String arrow();
String label();
}
private class MainButton extends FocusWidget {
MainButton(SafeHtml content) {
super(Document.get().createDivElement());
getElement().setInnerSafeHtml(content);
addStyleName(RESOURCES.css().button());
addStyleName(RESOURCES.css().mainButton());
addClickHandler(event -> {
if (menu != null && menu.isShowing()) {
return;
}
final Optional<MenuItem> defaultItem = itemsProvider.getDefaultItem();
if (defaultItem.isPresent()) {
getActionHandler().ifPresent(actionHandler -> actionHandler.onAction(defaultItem.get()));
} else {
showMenu();
}
});
}
}
private class DropButton extends FocusWidget {
DropButton() {
super(Document.get().createDivElement());
addStyleName(RESOURCES.css().button());
addStyleName(RESOURCES.css().dropButton());
final FlowPanel marker = new FlowPanel();
marker.getElement().appendChild(RESOURCES.arrowIcon().getSvg().getElement());
marker.addStyleName(RESOURCES.css().expandedImage());
getElement().appendChild(marker.getElement());
addClickHandler(event -> {
if (menu == null || !menu.isShowing()) {
showMenu();
}
});
}
}
static {
RESOURCES = GWT.create(Resources.class);
RESOURCES.css().ensureInjected();
}
}