package org.geogebra.web.web.javax.swing;
import org.geogebra.common.awt.GPoint;
import org.geogebra.common.kernel.Kernel;
import org.geogebra.common.main.Feature;
import org.geogebra.web.html5.Browser;
import org.geogebra.web.html5.gui.GPopupPanel;
import org.geogebra.web.html5.main.AppW;
import org.geogebra.web.web.css.GuiResources;
import org.geogebra.web.web.css.MaterialDesignResources;
import org.geogebra.web.web.html5.AttachedToDOM;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.MenuItemSeparator;
import com.google.gwt.user.client.ui.Widget;
/**
* Popup menu for web.
*
* @author Judit Elias
*/
public class GPopupMenuW implements AttachedToDOM {
protected GPopupPanel popupPanel;
protected PopupMenuBar popupMenu;
private int popupMenuSize = 0;
/*
* popup panel for submenu this field used to avoid having more submenu at
* the same time
*/
GPopupMenuW subPopup;
private AppW app;
/**
* @param app
*
* Creates a popup menu. App needed for get environment style
*/
public GPopupMenuW(AppW app) {
this.app = app;
popupPanel = new GPopupPanel(app.getPanel());
Browser.scale(popupPanel.getElement(), app.getArticleElement()
.getScaleX(), 0, 0);
popupMenu = new PopupMenuBar(true);
popupMenu.setAutoOpen(true);
popupPanel.add(popupMenu);
popupPanel.addCloseHandler(new CloseHandler<GPopupPanel>() {
@Override
public void onClose(CloseEvent<GPopupPanel> event) {
if (subPopup != null) {
subPopup.removeFromDOM();
subPopup = null;
}
}
});
popupPanel.setAutoHideEnabled(true);
}
/**
* Constructor for submenu-popups
*
* @param mb
* menu
*/
public GPopupMenuW(MenuBar mb, AppW app) {
popupPanel = new GPopupPanel(app.getPanel());
popupPanel.add(mb);
}
// public void add(MenuItem mi) {
// impl.addItem(mi);
//
// }
/**
* @param v
* whether to show this
*/
public void setVisible(boolean v) {
popupPanel.setVisible(v);
}
/**
* Shows the popup menu, ensures that the popup menu must be on the client
* area.
*/
public void show(GPoint p) {
int top = p.getY();
int left = p.getX();
boolean newPoz = false;
showAtPoint(p);
if (left + popupPanel.getOffsetWidth()
* app.getArticleElement().getScaleX() > Window.getClientWidth()
+ Window.getScrollLeft()) {
left = Window.getClientWidth() - popupPanel.getOffsetWidth()
+ Window.getScrollLeft();
newPoz = true;
} else {
left = (int) (left * app.getArticleElement().getScaleX());
}
if (top + popupPanel.getOffsetHeight()
* app.getArticleElement().getScaleY() > Window
.getClientHeight() + Window.getScrollTop()) {
top = Window.getClientHeight() - popupPanel.getOffsetHeight()
+ Window.getScrollTop();
newPoz = true;
} else {
top = (int) (top * app.getArticleElement().getScaleY());
}
if (newPoz || !Kernel.isEqual(1, app.getArticleElement().getScaleX())) {
popupPanel.setPopupPosition(left, top);
// App.debug(left + "x" + top);
}
}
/**
* Shows the popup menu at the p point, independently of there is enough
* place for the popup menu. (Maybe some details of the popup menu won't be
* visible.)
*/
public void showAtPoint(GPoint p) {
popupPanel.setPopupPosition(p.getX(), p.getY());
popupPanel.show();
}
public void show(Canvas c, int x, int y) {
show(new GPoint(
(int) (c.getAbsoluteLeft()
/ app.getArticleElement().getScaleX() + x),
(int) (c.getAbsoluteTop() / app.getArticleElement().getScaleY() + y)));
}
public void show(Widget c, int x, int y) {
show(new GPoint(c.getAbsoluteLeft() + x, c.getAbsoluteTop() + y));
}
@Override
public void removeFromDOM() {
removeSubPopup();
popupPanel.removeFromParent();
}
public void clearItems() {
popupMenu.clearItems();
}
public int getComponentCount() {
return popupMenuSize;
}
public void addSeparator() {
popupMenu.addSeparator();
}
public void addVerticalSeparator() {
MenuItemSeparator separator = new MenuItemSeparator();
separator.getElement().getFirstChildElement().setClassName("Separator");
popupMenu.addSeparator(separator);
}
private void addHideCommandFor(MenuItem item) {
MenuBar submenu = item.getSubMenu();
if (submenu == null) {
final ScheduledCommand oldCmd = item.getScheduledCommand();
ScheduledCommand cmd = new ScheduledCommand() {
@Override
public void execute() {
oldCmd.execute();
popupPanel.hide();
}
};
item.setScheduledCommand(cmd);
} else {
// CloseHandler<PopupPanel> closehandler = new
// CloseHandler<PopupPanel>(){
// public void onClose(CloseEvent<PopupPanel> event) {
// App.debug("popuppanel closed");
// }
// };
// submenu.addCloseHandler(closehandler);
// submenu.addHandler(closehandler, CloseEvent.getType());
submenu.addHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
popupPanel.hide();
}
}, ClickEvent.getType());
}
}
private static ImageResource getSubMenuIcon(boolean isRTL,
boolean isNewDesign) {
if (isNewDesign) {
return isRTL
? MaterialDesignResources.INSTANCE.arrow_drop_left_black()
: MaterialDesignResources.INSTANCE.arrow_drop_right_black();
}
return isRTL ? GuiResources.INSTANCE.menuBarSubMenuIconRTL()
: GuiResources.INSTANCE.menuBarSubMenuIconLTR();
}
// public void addItem(final MenuItem item) {
// addHideCommandFor(item);
// popupMenu.addItem(item);
// popupMenuSize++;
// }
public void addItem(final MenuItem item) {
final MenuBar subMenu = item.getSubMenu();
addHideCommandFor(item);
if (subMenu == null) {
popupMenu.addItem(item);
} else {
// The submenu is not added for the menu as submenu,
// but this will be placed on a different popup panel.
// In this way we can set this popup panel's position easily.
String itemHTML = item.getHTML();
ScheduledCommand itemCommand = null;
final MenuItem newItem = new MenuItem(itemHTML, true, itemCommand);
newItem.setStyleName(item.getStyleName());
newItem.getElement().setAttribute("hasPopup", "true");
popupMenu.addItem(newItem);
itemCommand = new ScheduledCommand() {
@Override
public void execute() {
int xCord, yCord;
if (subPopup != null) {
subPopup.removeFromDOM();
}
subPopup = new GPopupMenuW(subMenu, app);
subPopup.setVisible(true);
int xPercent = 0;
// Calculate the position of the "submenu", and show it
if (LocaleInfo.getCurrentLocale().isRTL()) {
xCord = getLeftSubPopupXCord();
if (xCord < 0) {
xCord = getRightSubPopupXCord();
} else {
xPercent = 100;
}
} else {
xCord = getRightSubPopupXCord();
if (xCord + getSubPopupWidth() > Window
.getClientWidth()) {
xCord = getLeftSubPopupXCord();
xPercent = 100;
}
}
yCord = Math.min(newItem.getAbsoluteTop(),
Window.getClientHeight() - getSubPopupHeight());
Browser.scale(subPopup.getPopupPanel().getElement(), app
.getArticleElement().getScaleX(), xPercent, 0);
subPopup.showAtPoint(new GPoint(xCord, yCord));
}
};
newItem.setScheduledCommand(itemCommand);
// adding arrow for the menuitem
Element td = DOM.createTD();
DOM.setElementProperty(td, "vAlign", "middle");
td.addClassName("subMenuIcon");
ImageResource imgRes = getSubMenuIcon(LocaleInfo.getCurrentLocale()
.isRTL(), app.has(Feature.NEW_TOOLBAR));
td.setInnerSafeHtml(AbstractImagePrototype.create(imgRes)
.getSafeHtml());
newItem.getElement().setAttribute("colspan", "1");
DOM.appendChild((Element) newItem.getElement().getParentNode(), td);
}
popupMenuSize++;
item.addStyleName("gPopupMenu_item");
}
/**
* @return the width of the submenu.
*/
public int getSubPopupWidth() {
int width;
boolean shown = subPopup.popupPanel.isShowing();
if (!shown) {
subPopup.popupPanel.show();
}
width = subPopup.popupPanel.getOffsetWidth();
if (!shown) {
subPopup.popupPanel.hide();
}
return width;
}
/**
* @return the height of the submenu.
*/
public int getSubPopupHeight() {
int ret;
boolean shown = subPopup.popupPanel.isShowing();
if (!shown) {
subPopup.popupPanel.show();
}
ret = subPopup.popupPanel.getOffsetHeight();
if (!shown) {
subPopup.popupPanel.hide();
}
return ret;
}
/**
* Gets the submenu's suggested absolute left position in pixels, as
* measured from the browser window's client area, in case of the submenu is
* on the left side of its parent menu.
*
* @return submenu's left position in pixels
*/
public int getLeftSubPopupXCord() {
int xCord;
xCord = popupPanel.getAbsoluteLeft() - getSubPopupWidth();
return xCord;
}
/**
* Gets the submenu's suggested absolute left position in pixels, as
* measured from the browser window's client area, in case of the submenu is
* on the right side of its parent menu.
*
* @return submenu's left position in pixels
*/
public int getRightSubPopupXCord() {
return popupPanel.getAbsoluteLeft()
+ (int) (popupPanel.getOffsetWidth() * app.getArticleElement()
.getScaleX());
}
public void addItem(GCheckBoxMenuItem item) {
addItem(item.getMenuItem());
}
public void addItem(String s, ScheduledCommand c) {
addItem(new MenuItem(s, c));
}
public void hide() {
popupPanel.hide();
}
public MenuBar getPopupMenu() {
return popupMenu;
}
public GPopupPanel getPopupPanel() {
return popupPanel;
}
public void removeSubPopup() {
if (subPopup != null) {
subPopup.removeFromDOM();
subPopup = null;
}
}
private class PopupMenuBar extends MenuBar {
public PopupMenuBar(boolean vertical) {
super(vertical);
}
private MenuItem findItem(Element hItem) {
for (MenuItem item : getItems()) {
if (DOM.isOrHasChild(item.getElement(), hItem)) {
return item;
}
}
return null;
}
@Override
public void onBrowserEvent(Event event) {
switch (DOM.eventGetType(event)) {
case Event.ONMOUSEOVER: {
MenuItem item = findItem(DOM.eventGetTarget(event));
if (item != null) {
if ("true".equals(item.getElement()
.getAttribute("hasPopup"))) {
item.getScheduledCommand().execute();
} else {
removeSubPopup();
}
}
break;
}
}
super.onBrowserEvent(event);
}
}
}