package org.ovirt.engine.ui.common.presenter; import org.ovirt.engine.ui.common.auth.UserLoginChangeEvent; import org.ovirt.engine.ui.common.utils.ElementTooltipUtils; import org.ovirt.engine.ui.common.widget.dialog.PopupNativeKeyPressHandler; import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.event.dom.client.HasClickHandlers; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.shared.EventBus; import com.gwtplatform.mvp.client.PopupView; import com.gwtplatform.mvp.client.PresenterWidget; /** * Base class for presenter widgets meant to be revealed as popups. * * @param <V> * Popup view type. */ public abstract class AbstractPopupPresenterWidget<V extends AbstractPopupPresenterWidget.ViewDef> extends PresenterWidget<V> { public interface ViewDef extends PopupView { /** * @return Button used to hide the pop-up view (can be {@code null}). */ HasClickHandlers getCloseButton(); /** * @return The header button (X) that can close the pop-up view. */ HasClickHandlers getCloseIconButton(); /** * Used to handle native key press events that occur within pop-ups. */ void setPopupKeyPressHandler(PopupNativeKeyPressHandler handler); } // Number of popups currently active (visible) private static int activePopups = 0; // Indicates whether the handlers registered by the popup have been released private boolean destroyed = false; public AbstractPopupPresenterWidget(EventBus eventBus, V view) { super(eventBus, view); } @Override protected void onBind() { super.onBind(); HasClickHandlers closeButton = getView().getCloseButton(); if (closeButton != null) { registerHandler(closeButton.addClickHandler(event -> AbstractPopupPresenterWidget.this.onClose())); } HasClickHandlers closeIconButton = getView().getCloseIconButton(); if (closeIconButton != null) { registerHandler(closeIconButton.addClickHandler(event -> AbstractPopupPresenterWidget.this.onClose())); } getView().setPopupKeyPressHandler(event -> AbstractPopupPresenterWidget.this.onKeyPress(event)); registerHandler(getEventBus().addHandler(UserLoginChangeEvent.getType(), event -> { if (isVisible()) { getView().hide(); } })); } @Override protected void onReveal() { super.onReveal(); activePopups++; } @Override protected void onHide() { super.onHide(); activePopups--; if (activePopups == 0) { // No popups active, reap tooltips attached to popup content. Scheduler.get().scheduleDeferred(() -> ElementTooltipUtils.reapPopupContentTooltips()); } } protected int getActivePopupCount() { return activePopups; } /** * By default, closing the popup will release its registered handlers. * <p> * Alternatively, override this method to return {@code false} and call * {@link #hideAndUnbind} to manually hide and dispose of the popup. */ protected boolean shouldDestroyOnClose() { return true; } /** * Close action callback, hides the popup view by default. */ protected void onClose() { if (shouldDestroyOnClose()) { hideAndUnbind(); } else { getView().hide(); } } /** * Hides the popup view and releases all handlers registered via {@link #registerHandler}. * <p> * This method is applicable to non-singleton presenter widgets only. */ public void hideAndUnbind() { if (!destroyed) { getView().hide(); unbind(); destroyed = true; } } protected void onKeyPress(NativeEvent event) { if (KeyCodes.KEY_ENTER == event.getKeyCode()) { handleEnterKey(); } else if (KeyCodes.KEY_ESCAPE == event.getKeyCode()) { handleEscapeKey(); event.preventDefault(); } } /** * Does nothing by default. */ protected void handleEnterKey() { // No-op, override as necessary } /** * Calls {@link #onClose} by default. */ protected void handleEscapeKey() { onClose(); } }