package org.tessell.widgets;
import static org.tessell.widgets.Widgets.newFocusPanel;
import static org.tessell.widgets.Widgets.newPopupPanel;
import static org.tessell.widgets.Widgets.newTimer;
import org.tessell.gwt.user.client.IsTimer;
import org.tessell.gwt.user.client.ui.IsFocusPanel;
import org.tessell.gwt.user.client.ui.IsPopupPanel;
import org.tessell.gwt.user.client.ui.IsWidget;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasAllMouseHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
/** Renders a main content widget and pops up a detail panel on mouse over. */
public class AbstractPopupBox<T extends HasClickHandlers & HasAllMouseHandlers & IsWidget, U extends IsWidget> extends CompositeIsWidget {
private static final int HIDE_DELAY_MILLIS = 500;
protected final IsPopupPanel popupPanel = newPopupPanel();
protected final IsFocusPanel popupFocus = newFocusPanel();
protected final IsTimer hidePopupTimer = newTimer(new Runnable() {
public void run() {
hidePopupIfNeeded();
}
});
protected final T mainContent;
protected final U popupContent;
protected AbstractPopupBox(final T mainContent, final U popupContent) {
this.mainContent = mainContent;
this.popupContent = popupContent;
setWidget(mainContent);
popupPanel.add(popupFocus);
popupFocus.add(popupContent);
final MouseHandler m = new MouseHandler();
popupFocus.addMouseOverHandler(m);
popupFocus.addMouseOutHandler(m);
mainContent.addMouseOverHandler(m);
mainContent.addMouseOutHandler(m);
mainContent.addClickHandler(m);
}
protected final void showPopupIfNeeded() {
if (!popupPanel.isShowing()) {
showPopup();
}
hidePopupTimer.cancel();
}
protected final void hidePopupIfNeeded() {
if (popupPanel.isShowing()) {
hidePopup();
}
hidePopupTimer.cancel();
}
/** Shows the popup panel, setting it's top/left relative to the textbox's position. */
protected void showPopup() {
final int left = mainContent.getAbsoluteLeft();
final int top = mainContent.getAbsoluteTop() + mainContent.getOffsetHeight() + 5;
popupPanel.setPopupPosition(left, top);
popupPanel.show();
}
/** Hides the popup panel. */
protected void hidePopup() {
popupPanel.hide();
}
/** On click/mouseover show the popup; on mouseout, start the timer to hide it. */
private final class MouseHandler implements MouseOverHandler, MouseOutHandler, ClickHandler {
@Override
public void onMouseOver(final MouseOverEvent event) {
showPopupIfNeeded();
}
@Override
public void onClick(ClickEvent event) {
showPopupIfNeeded();
}
@Override
public void onMouseOut(final MouseOutEvent event) {
hidePopupTimer.schedule(HIDE_DELAY_MILLIS);
}
}
public T getMainContent() {
return mainContent;
}
public U getPopupContent() {
return popupContent;
}
public IsPopupPanel getPopupPanel() {
return popupPanel;
}
}