/*
 * Copyright 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.user.client.ui;

import com.google.gwt.animation.client.Animation;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.HasCloseHandlers;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventPreview;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
import com.google.gwt.user.client.ui.impl.PopupImpl;

import java.util.ArrayList;
import java.util.List;

/**
 * A panel that can "pop up" over other widgets. It overlays the browser's
 * client area (and any previously-created popups).
 *
 * <p>
 * A PopupPanel should not generally be added to other panels; rather, it should
 * be shown and hidden using the {@link #show()} and {@link #hide()} methods.
 * </p>
 * <p>
 * The width and height of the PopupPanel cannot be explicitly set; they are
 * determined by the PopupPanel's widget. Calls to {@link #setWidth(String)} and
 * {@link #setHeight(String)} will call these methods on the PopupPanel's
 * widget.
 * </p>
 * <p>
 * <img class='gallery' src='doc-files/PopupPanel.png'/>
 * </p>
 *
 * <p>
 * The PopupPanel can be optionally displayed with a "glass" element behind it,
 * which is commonly used to gray out the widgets behind it. It can be enabled
 * using {@link #setGlassEnabled(boolean)}. It has a default style name of
 * "gwt-PopupPanelGlass", which can be changed using
 * {@link #setGlassStyleName(String)}.
 * </p>
 *
 * <p>
 * <h3>Example</h3>
 * {@example com.google.gwt.examples.PopupPanelExample}
 * </p>
 * <h3>CSS Style Rules</h3>
 * <dl>
 * <dt>.gwt-PopupPanel</dt>
 * <dd>the outside of the popup</dd>
 * <dt>.gwt-PopupPanel .popupContent</dt>
 * <dd>the wrapper around the content</dd>
 * <dt>.gwt-PopupPanelGlass</dt>
 * <dd>the glass background behind the popup</dd>
 * </dl>
 */
@SuppressWarnings("deprecation")
public class PopupPanel extends SimplePanel implements SourcesPopupEvents,
    EventPreview, HasAnimation, HasCloseHandlers<PopupPanel> {

  /**
   * A callback that is used to set the position of a {@link PopupPanel} right
   * before it is shown.
   */
  public interface PositionCallback {

    /**
     * Provides the opportunity to set the position of the PopupPanel right
     * before the PopupPanel is shown. The offsetWidth and offsetHeight values
     * of the PopupPanel are made available to allow for positioning based on
     * its size.
     *
     * @param offsetWidth the offsetWidth of the PopupPanel
     * @param offsetHeight the offsetHeight of the PopupPanel
     * @see PopupPanel#setPopupPositionAndShow(PositionCallback)
     */
    void setPosition(int offsetWidth, int offsetHeight);
  }

  /**
   * The type of animation to use when opening the popup.
   *
   * <ul>
   * <li>CENTER - Expand from the center of the popup</li>
   * <li>ONE_WAY_CORNER - Expand from the top left corner, do not animate hiding
   * </li>
   * </ul>
   */
  static enum AnimationType {
    CENTER, ONE_WAY_CORNER, ROLL_DOWN
  }

  /**
   * An {@link Animation} used to enlarge the popup into view.
   */
  static class ResizeAnimation extends Animation {
    /**
     * The {@link PopupPanel} being affected.
     */
    private PopupPanel curPanel = null;

    /**
     * Indicates whether or not the {@link PopupPanel} is in the process of
     * unloading. If the popup is unloading, then the animation just does
     * cleanup.
     */
    private boolean isUnloading;

    /**
     * The offset height and width of the current {@link PopupPanel}.
     */
    private int offsetHeight, offsetWidth = -1;

    /**
     * A boolean indicating whether we are showing or hiding the popup.
     */
    private boolean showing;

    /**
     * The timer used to delay the show animation.
     */
    private Timer showTimer;

    /**
     * A boolean indicating whether the glass element is currently attached.
     */
    private boolean glassShowing;

    private HandlerRegistration resizeRegistration;

    /**
     * Create a new {@link ResizeAnimation}.
     *
     * @param panel the panel to affect
     */
    public ResizeAnimation(PopupPanel panel) {
      this.curPanel = panel;
    }

    /**
     * Open or close the content. This method always called immediately after
     * the PopupPanel showing state has changed, so we base the animation on the
     * current state.
     *
     * @param showing true if the popup is showing, false if not
     */
    public void setState(boolean showing, boolean isUnloading) {
      // Immediately complete previous open/close animation
      this.isUnloading = isUnloading;
      cancel();

      // If there is a pending timer to start a show animation, then just cancel
      // the timer and complete the show operation.
      if (showTimer != null) {
        showTimer.cancel();
        showTimer = null;
        onComplete();
      }

      // Update the logical state.
      curPanel.showing = showing;
      curPanel.updateHandlers();

      // Determine if we need to animate
      boolean animate = !isUnloading && curPanel.isAnimationEnabled;
      if (curPanel.animType != AnimationType.CENTER && !showing) {
        animate = false;
      }

      // Open the new item
      this.showing = showing;
      if (animate) {
        // impl.onShow takes some time to complete, so we do it before starting
        // the animation. If we move this to onStart, the animation will look
        // choppy or not run at all.
        if (showing) {
          maybeShowGlass();

          // Set the position attribute, and then attach to the DOM. Otherwise,
          // the PopupPanel will appear to 'jump' from its static/relative
          // position to its absolute position (issue #1231).
          DOM.setStyleAttribute(curPanel.getElement(), "position", "absolute");
          if (curPanel.topPosition != -1) {
            curPanel.setPopupPosition(curPanel.leftPosition,
                curPanel.topPosition);
          }
          impl.setClip(curPanel.getElement(), getRectString(0, 0, 0, 0));
          RootPanel.get().add(curPanel);
          impl.onShow(curPanel.getElement());

          // Wait for the popup panel and iframe to be attached before running
          // the animation. We use a Timer instead of a DeferredCommand so we
          // can cancel it if the popup is hidden synchronously.
          showTimer = new Timer() {
            @Override
            public void run() {
              showTimer = null;
              ResizeAnimation.this.run(ANIMATION_DURATION);
            }
          };
          showTimer.schedule(1);
        } else {
          run(ANIMATION_DURATION);
        }
      } else {
        onInstantaneousRun();
      }
    }

    @Override
    protected void onComplete() {
      if (!showing) {
        maybeShowGlass();
        if (!isUnloading) {
          RootPanel.get().remove(curPanel);
        }
        impl.onHide(curPanel.getElement());
      }
      impl.setClip(curPanel.getElement(), "rect(auto, auto, auto, auto)");
      DOM.setStyleAttribute(curPanel.getElement(), "overflow", "visible");
    }

    @Override
    protected void onStart() {
      offsetHeight = curPanel.getOffsetHeight();
      offsetWidth = curPanel.getOffsetWidth();
      DOM.setStyleAttribute(curPanel.getElement(), "overflow", "hidden");
      super.onStart();
    }

    @Override
    protected void onUpdate(double progress) {
      if (!showing) {
        progress = 1.0 - progress;
      }

      // Determine the clipping size
      int top = 0;
      int left = 0;
      int right = 0;
      int bottom = 0;
      int height = (int) (progress * offsetHeight);
      int width = (int) (progress * offsetWidth);
      switch (curPanel.animType) {
        case ROLL_DOWN:
          right = offsetWidth;
          bottom = height;
          break;
        case CENTER:
          top = (offsetHeight - height) >> 1;
          left = (offsetWidth - width) >> 1;
          right = left + width;
          bottom = top + height;
          break;
        case ONE_WAY_CORNER:
          if (LocaleInfo.getCurrentLocale().isRTL()) {
            left = offsetWidth - width;
          }
          right = left + width;
          bottom = top + height;
          break;
      }
      // Set the rect clipping
      impl.setClip(curPanel.getElement(), getRectString(top, right, bottom,
          left));
    }

    /**
     * Returns a rect string.
     */
    private String getRectString(int top, int right, int bottom, int left) {
      return "rect(" + top + "px, " + right + "px, " + bottom + "px, " + left
          + "px)";
    }

    /**
     * Show or hide the glass.
     */
    private void maybeShowGlass() {
      if (showing) {
        if (curPanel.isGlassEnabled) {
          Document.get().getBody().appendChild(curPanel.glass);
          impl.onShow(curPanel.glass);

          resizeRegistration = Window.addResizeHandler(curPanel.glassResizer);
          curPanel.glassResizer.onResize(null);

          glassShowing = true;
        }
      } else if (glassShowing) {
        Document.get().getBody().removeChild(curPanel.glass);
        impl.onHide(curPanel.glass);

        resizeRegistration.removeHandler();
        resizeRegistration = null;

        glassShowing = false;
      }
    }

    private void onInstantaneousRun() {
      maybeShowGlass();
      if (showing) {
        // Set the position attribute, and then attach to the DOM. Otherwise,
        // the PopupPanel will appear to 'jump' from its static/relative
        // position to its absolute position (issue #1231).
        DOM.setStyleAttribute(curPanel.getElement(), "position", "absolute");
        if (curPanel.topPosition != -1) {
          curPanel.setPopupPosition(curPanel.leftPosition, curPanel.topPosition);
        }
        RootPanel.get().add(curPanel);
        impl.onShow(curPanel.getElement());
      } else {
        if (!isUnloading) {
          RootPanel.get().remove(curPanel);
        }
        impl.onHide(curPanel.getElement());
      }
      DOM.setStyleAttribute(curPanel.getElement(), "overflow", "visible");
    }
  }

  /**
   * The duration of the animation.
   */
  private static final int ANIMATION_DURATION = 200;

  /**
   * The default style name.
   */
  private static final String DEFAULT_STYLENAME = "gwt-PopupPanel";

  private static final PopupImpl impl = GWT.create(PopupImpl.class);

  /**
   * Window resize handler used to keep the glass the proper size.
   */
  private ResizeHandler glassResizer = new ResizeHandler() {
    public void onResize(ResizeEvent event) {
      Style style = glass.getStyle();

      int winWidth = Window.getClientWidth();
      int winHeight = Window.getClientHeight();

      // Hide the glass while checking the document size. Otherwise it would
      // interfere with the measurement.
      style.setDisplay(Display.NONE);
      style.setWidth(0, Unit.PX);
      style.setHeight(0, Unit.PX);

      int width = Document.get().getScrollWidth();
      int height = Document.get().getScrollHeight();

      // Set the glass size to the larger of the window's client size or the
      // document's scroll size.
      style.setWidth(Math.max(width, winWidth), Unit.PX);
      style.setHeight(Math.max(height, winHeight), Unit.PX);

      // The size is set. Show the glass again.
      style.setDisplay(Display.BLOCK);
    }
  };

  /**
   * If true, animate the opening of this popup from the center. If false,
   * animate it open from top to bottom, and do not animate closing. Use false
   * to animate menus.
   */
  private AnimationType animType = AnimationType.CENTER;

  private boolean autoHide, previewAllNativeEvents, modal, showing;
  private boolean autoHideOnHistoryEvents;

  private List<Element> autoHidePartners;

  // Used to track requested size across changing child widgets
  private String desiredHeight;

  private String desiredWidth;

  /**
   * The glass element.
   */
  private Element glass;

  private String glassStyleName = "gwt-PopupPanelGlass";

  /**
   * A boolean indicating that a glass element should be used.
   */
  private boolean isGlassEnabled;

  private boolean isAnimationEnabled = false;

  // the left style attribute in pixels
  private int leftPosition = -1;

  private HandlerRegistration nativePreviewHandlerRegistration;
  private HandlerRegistration historyHandlerRegistration;

  /**
   * The {@link ResizeAnimation} used to open and close the {@link PopupPanel}s.
   */
  private ResizeAnimation resizeAnimation = new ResizeAnimation(this);

  // The top style attribute in pixels
  private int topPosition = -1;

  /**
   * Creates an empty popup panel. A child widget must be added to it before it
   * is shown.
   */
  public PopupPanel() {
    super();
    super.getContainerElement().appendChild(impl.createElement());

    // Default position of popup should be in the upper-left corner of the
    // window. By setting a default position, the popup will not appear in
    // an undefined location if it is shown before its position is set.
    setPopupPosition(0, 0);
    setStyleName(DEFAULT_STYLENAME);
    setStyleName(getContainerElement(), "popupContent");
  }

  /**
   * Creates an empty popup panel, specifying its "auto-hide" property.
   *
   * @param autoHide <code>true</code> if the popup should be automatically
   *          hidden when the user clicks outside of it or the history token
   *          changes.
   */
  public PopupPanel(boolean autoHide) {
    this();
    this.autoHide = autoHide;
    this.autoHideOnHistoryEvents = autoHide;
  }

  /**
   * Creates an empty popup panel, specifying its "auto-hide" and "modal"
   * properties.
   *
   * @param autoHide <code>true</code> if the popup should be automatically
   *          hidden when the user clicks outside of it or the history token
   *          changes.
   * @param modal <code>true</code> if keyboard or mouse events that do not
   *          target the PopupPanel or its children should be ignored
   */
  public PopupPanel(boolean autoHide, boolean modal) {
    this(autoHide);
    this.modal = modal;
  }

  /**
   * Mouse events that occur within an autoHide partner will not hide a panel
   * set to autoHide.
   *
   * @param partner the auto hide partner to add
   */
  public void addAutoHidePartner(Element partner) {
    assert partner != null : "partner cannot be null";
    if (autoHidePartners == null) {
      autoHidePartners = new ArrayList<Element>();
    }
    autoHidePartners.add(partner);
  }

  public HandlerRegistration addCloseHandler(CloseHandler<PopupPanel> handler) {
    return addHandler(handler, CloseEvent.getType());
  }

  /**
   * @deprecated Use {@link #addCloseHandler} instead
   */
  @Deprecated
  public void addPopupListener(final PopupListener listener) {
    ListenerWrapper.WrappedPopupListener.add(this, listener);
  }

  /**
   * Centers the popup in the browser window and shows it. If the popup was
   * already showing, then the popup is centered.
   */
  public void center() {
    boolean initiallyShowing = showing;
    boolean initiallyAnimated = isAnimationEnabled;

    if (!initiallyShowing) {
      setVisible(false);
      setAnimationEnabled(false);
      show();
    }

    // If left/top are set from a previous center() call, and our content
    // has changed, we may get a bogus getOffsetWidth because our new content
    // is wrapping (giving a lower offset width) then it would without the
    // previous left. Setting left/top back to 0 avoids this.
    Element elem = getElement();
    elem.getStyle().setPropertyPx("left", 0);
    elem.getStyle().setPropertyPx("top", 0);

    int left = (Window.getClientWidth() - getOffsetWidth()) >> 1;
    int top = (Window.getClientHeight() - getOffsetHeight()) >> 1;
    setPopupPosition(Math.max(Window.getScrollLeft() + left, 0), Math.max(
        Window.getScrollTop() + top, 0));

    if (!initiallyShowing) {
      setAnimationEnabled(initiallyAnimated);
      // Run the animation. The popup is already visible, so we can skip the
      // call to setState.
      if (initiallyAnimated) {
        impl.setClip(getElement(), "rect(0px, 0px, 0px, 0px)");
        setVisible(true);
        resizeAnimation.run(ANIMATION_DURATION);
      } else {
        setVisible(true);
      }
    }
  }

  /**
   * Gets the style name to be used on the glass element. By default, this is
   * "gwt-PopupPanelGlass".
   *
   * @return the glass element's style name
   */
  public String getGlassStyleName() {
    return glassStyleName;
  }

  /**
   * Gets the panel's offset height in pixels. Calls to
   * {@link #setHeight(String)} before the panel's child widget is set will not
   * influence the offset height.
   *
   * @return the object's offset height
   */
  @Override
  public int getOffsetHeight() {
    return super.getOffsetHeight();
  }

  /**
   * Gets the panel's offset width in pixels. Calls to {@link #setWidth(String)}
   * before the panel's child widget is set will not influence the offset width.
   *
   * @return the object's offset width
   */
  @Override
  public int getOffsetWidth() {
    return super.getOffsetWidth();
  }

  /**
   * Gets the popup's left position relative to the browser's client area.
   *
   * @return the popup's left position
   */
  public int getPopupLeft() {
    return DOM.getAbsoluteLeft(getElement());
  }

  /**
   * Gets the popup's top position relative to the browser's client area.
   *
   * @return the popup's top position
   */
  public int getPopupTop() {
    return DOM.getAbsoluteTop(getElement());
  }

  @Override
  public String getTitle() {
    return DOM.getElementProperty(getContainerElement(), "title");
  }

  /**
   * Hides the popup and detaches it from the page. This has no effect if it is
   * not currently showing.
   */
  public void hide() {
    hide(false);
  }

  /**
   * Hides the popup and detaches it from the page. This has no effect if it is
   * not currently showing.
   *
   * @param autoClosed the value that will be passed to
   *          {@link CloseHandler#onClose(CloseEvent)} when the popup is closed
   */
  public void hide(boolean autoClosed) {
    if (!isShowing()) {
      return;
    }
    resizeAnimation.setState(false, false);
    CloseEvent.fire(this, this, autoClosed);
  }

  public boolean isAnimationEnabled() {
    return isAnimationEnabled;
  }

  /**
   * Returns <code>true</code> if the popup should be automatically hidden when
   * the user clicks outside of it.
   *
   * @return true if autoHide is enabled, false if disabled
   */
  public boolean isAutoHideEnabled() {
    return autoHide;
  }

  /**
   * Returns <code>true</code> if the popup should be automatically hidden when
   * the history token changes, such as when the user presses the browser's back
   * button.
   *
   * @return true if enabled, false if disabled
   */
  public boolean isAutoHideOnHistoryEventsEnabled() {
    return autoHideOnHistoryEvents;
  }

  /**
   * Returns <code>true</code> if a glass element will be displayed under the
   * {@link PopupPanel}.
   *
   * @return true if enabled
   */
  public boolean isGlassEnabled() {
    return isGlassEnabled;
  }

  /**
   * Returns <code>true</code> if keyboard or mouse events that do not target
   * the PopupPanel or its children should be ignored.
   *
   * @return true if popup is modal, false if not
   */
  public boolean isModal() {
    return modal;
  }

  /**
   * Returns <code>true</code> if the popup should preview all native events,
   * even if the event has already been consumed by another popup.
   *
   * @return true if previewAllNativeEvents is enabled, false if disabled
   */
  public boolean isPreviewingAllNativeEvents() {
    return previewAllNativeEvents;
  }

  /**
   * Determines whether or not this popup is showing.
   *
   * @return <code>true</code> if the popup is showing
   * @see #show()
   * @see #hide()
   */
  public boolean isShowing() {
    return showing;
  }

  /**
   * Determines whether or not this popup is visible. Note that this just checks
   * the <code>visibility</code> style attribute, which is set in the
   * {@link #setVisible(boolean)} method. If you want to know if the popup is
   * attached to the page, use {@link #isShowing()} instead.
   *
   * @return <code>true</code> if the object is visible
   * @see #setVisible(boolean)
   */
  @Override
  public boolean isVisible() {
    return !"hidden".equals(getElement().getStyle().getProperty("visibility"));
  }

  /**
   * @deprecated Use {@link #onPreviewNativeEvent} instead
   */
  @Deprecated
  public boolean onEventPreview(Event event) {
    return true;
  }

  /**
   * Popups get an opportunity to preview keyboard events before they are passed
   * to a widget contained by the Popup.
   *
   * @param key the key code of the depressed key
   * @param modifiers keyboard modifiers, as specified in
   *          {@link com.google.gwt.event.dom.client.KeyCodes}.
   * @return <code>false</code> to suppress the event
   * @deprecated Use {@link #onPreviewNativeEvent} instead
   */
  @Deprecated
  public boolean onKeyDownPreview(char key, int modifiers) {
    return true;
  }

  /**
   * Popups get an opportunity to preview keyboard events before they are passed
   * to a widget contained by the Popup.
   *
   * @param key the unicode character pressed
   * @param modifiers keyboard modifiers, as specified in
   *          {@link com.google.gwt.event.dom.client.KeyCodes}.
   * @return <code>false</code> to suppress the event
   * @deprecated Use {@link #onPreviewNativeEvent} instead
   */
  @Deprecated
  public boolean onKeyPressPreview(char key, int modifiers) {
    return true;
  }

  /**
   * Popups get an opportunity to preview keyboard events before they are passed
   * to a widget contained by the Popup.
   *
   * @param key the key code of the released key
   * @param modifiers keyboard modifiers, as specified in
   *          {@link com.google.gwt.event.dom.client.KeyCodes}.
   * @return <code>false</code> to suppress the event
   * @deprecated Use {@link #onPreviewNativeEvent} instead
   */
  @Deprecated
  public boolean onKeyUpPreview(char key, int modifiers) {
    return true;
  }

  /**
   * Remove an autoHide partner.
   *
   * @param partner the auto hide partner to remove
   */
  public void removeAutoHidePartner(Element partner) {
    assert partner != null : "partner cannot be null";
    if (autoHidePartners != null) {
      autoHidePartners.remove(partner);
    }
  }

  /**
   * @deprecated Use the {@link HandlerRegistration#removeHandler} method on the
   *             object returned by {@link #addCloseHandler} instead
   */
  @Deprecated
  public void removePopupListener(PopupListener listener) {
    ListenerWrapper.WrappedPopupListener.remove(this, listener);
  }

  public void setAnimationEnabled(boolean enable) {
    isAnimationEnabled = enable;
  }

  /**
   * Enable or disable the autoHide feature. When enabled, the popup will be
   * automatically hidden when the user clicks outside of it.
   *
   * @param autoHide true to enable autoHide, false to disable
   */
  public void setAutoHideEnabled(boolean autoHide) {
    this.autoHide = autoHide;
  }

  /**
   * Enable or disable autoHide on history change events. When enabled, the
   * popup will be automatically hidden when the history token changes, such as
   * when the user presses the browser's back button. Disabled by default.
   *
   * @param enabled true to enable, false to disable
   */
  public void setAutoHideOnHistoryEventsEnabled(boolean enabled) {
    this.autoHideOnHistoryEvents = enabled;
  }

  /**
   * When enabled, the background will be blocked with a semi-transparent pane
   * the next time it is shown. If the PopupPanel is already visible, the glass
   * will not be displayed until it is hidden and shown again.
   *
   * @param enabled true to enable, false to disable
   */
  public void setGlassEnabled(boolean enabled) {
    this.isGlassEnabled = enabled;
    if (enabled && glass == null) {
      glass = Document.get().createDivElement();
      glass.setClassName(glassStyleName);

      glass.getStyle().setPosition(Position.ABSOLUTE);
      glass.getStyle().setLeft(0, Unit.PX);
      glass.getStyle().setTop(0, Unit.PX);
    }
  }

  /**
   * Sets the style name to be used on the glass element. By default, this is
   * "gwt-PopupPanelGlass".
   *
   * @param glassStyleName the glass element's style name
   */
  public void setGlassStyleName(String glassStyleName) {
    this.glassStyleName = glassStyleName;
    if (glass != null) {
      glass.setClassName(glassStyleName);
    }
  }

  /**
   * Sets the height of the panel's child widget. If the panel's child widget
   * has not been set, the height passed in will be cached and used to set the
   * height immediately after the child widget is set.
   *
   * <p>
   * Note that subclasses may have a different behavior. A subclass may decide
   * not to change the height of the child widget. It may instead decide to
   * change the height of an internal panel widget, which contains the child
   * widget.
   * </p>
   *
   * @param height the object's new height, in CSS units (e.g. "10px", "1em")
   */
  @Override
  public void setHeight(String height) {
    desiredHeight = height;
    maybeUpdateSize();
    // If the user cleared the size, revert to not trying to control children.
    if (height.length() == 0) {
      desiredHeight = null;
    }
  }

  /**
   * When the popup is modal, keyboard or mouse events that do not target the
   * PopupPanel or its children will be ignored.
   *
   * @param modal true to make the popup modal
   */
  public void setModal(boolean modal) {
    this.modal = modal;
  }

  /**
   * Sets the popup's position relative to the browser's client area. The
   * popup's position may be set before calling {@link #show()}.
   *
   * @param left the left position, in pixels
   * @param top the top position, in pixels
   */
  public void setPopupPosition(int left, int top) {
    // Save the position of the popup
    leftPosition = left;
    topPosition = top;

    // Account for the difference between absolute position and the
    // body's positioning context.
    left -= Document.get().getBodyOffsetLeft();
    top -= Document.get().getBodyOffsetTop();

    // Set the popup's position manually, allowing setPopupPosition() to be
    // called before show() is called (so a popup can be positioned without it
    // 'jumping' on the screen).
    Element elem = getElement();
    elem.getStyle().setPropertyPx("left", left);
    elem.getStyle().setPropertyPx("top", top);
  }

  /**
   * Sets the popup's position using a {@link PositionCallback}, and shows the
   * popup. The callback allows positioning to be performed based on the
   * offsetWidth and offsetHeight of the popup, which are normally not available
   * until the popup is showing. By positioning the popup before it is shown,
   * the popup will not jump from its original position to the new position.
   *
   * @param callback the callback to set the position of the popup
   * @see PositionCallback#setPosition(int offsetWidth, int offsetHeight)
   */
  public void setPopupPositionAndShow(PositionCallback callback) {
    setVisible(false);
    show();
    callback.setPosition(getOffsetWidth(), getOffsetHeight());
    setVisible(true);
  }

  /**
   * <p>
   * When enabled, the popup will preview all native events, even if another
   * popup was opened after this one.
   * </p>
   * <p>
   * If autoHide is enabled, enabling this feature will cause the popup to
   * autoHide even if another non-modal popup was shown after it. If this
   * feature is disabled, the popup will only autoHide if it was the last popup
   * opened.
   * </p>
   *
   * @param previewAllNativeEvents true to enable, false to disable
   */
  public void setPreviewingAllNativeEvents(boolean previewAllNativeEvents) {
    this.previewAllNativeEvents = previewAllNativeEvents;
  }

  @Override
  public void setTitle(String title) {
    Element containerElement = getContainerElement();
    if (title == null || title.length() == 0) {
      containerElement.removeAttribute("title");
    } else {
      containerElement.setAttribute("title", title);
    }
  }

  /**
   * Sets whether this object is visible. This method just sets the
   * <code>visibility</code> style attribute. You need to call {@link #show()}
   * to actually attached/detach the {@link PopupPanel} to the page.
   *
   * @param visible <code>true</code> to show the object, <code>false</code> to
   *          hide it
   * @see #show()
   * @see #hide()
   */
  @Override
  public void setVisible(boolean visible) {
    // We use visibility here instead of UIObject's default of display
    // Because the panel is absolutely positioned, this will not create
    // "holes" in displayed contents and it allows normal layout passes
    // to occur so the size of the PopupPanel can be reliably determined.
    DOM.setStyleAttribute(getElement(), "visibility", visible ? "visible"
        : "hidden");

    // If the PopupImpl creates an iframe shim, it's also necessary to hide it
    // as well.
    impl.setVisible(getElement(), visible);
    if (glass != null) {
      impl.setVisible(glass, visible);
      glass.getStyle().setProperty("visibility", visible ? "visible" : "hidden");
    }
  }

  @Override
  public void setWidget(Widget w) {
    super.setWidget(w);
    maybeUpdateSize();
  }

  /**
   * Sets the width of the panel's child widget. If the panel's child widget has
   * not been set, the width passed in will be cached and used to set the width
   * immediately after the child widget is set.
   *
   * <p>
   * Note that subclasses may have a different behavior. A subclass may decide
   * not to change the width of the child widget. It may instead decide to
   * change the width of an internal panel widget, which contains the child
   * widget.
   * </p>
   *
   * @param width the object's new width, in CSS units (e.g. "10px", "1em")
   */
  @Override
  public void setWidth(String width) {
    desiredWidth = width;
    maybeUpdateSize();
    // If the user cleared the size, revert to not trying to control children.
    if (width.length() == 0) {
      desiredWidth = null;
    }
  }

  /**
   * Shows the popup and attach it to the page. It must have a child widget
   * before this method is called.
   */
  public void show() {
    if (showing) {
      return;
    } else if (isAttached()) {
      // The popup is attached directly to another panel, so we need to remove
      // it from its parent before showing it. This is a weird use case, but
      // since PopupPanel is a Widget, its legal.
      this.removeFromParent();
    }
    resizeAnimation.setState(true, false);
  }

  /**
   * Normally, the popup is positioned directly below the relative target, with
   * its left edge aligned with the left edge of the target. Depending on the
   * width and height of the popup and the distance from the target to the
   * bottom and right edges of the window, the popup may be displayed directly
   * above the target, and/or its right edge may be aligned with the right edge
   * of the target.
   *
   * @param target the target to show the popup below
   */
  public final void showRelativeTo(final UIObject target) {
    // Set the position of the popup right before it is shown.
    setPopupPositionAndShow(new PositionCallback() {
      public void setPosition(int offsetWidth, int offsetHeight) {
        position(target, offsetWidth, offsetHeight);
      }
    });
  }

  @Override
  protected com.google.gwt.user.client.Element getContainerElement() {
    return impl.getContainerElement(getPopupImplElement()).cast();
  }

  /**
   * Get the glass element used by this {@link PopupPanel}. The element is not
   * created until it is enabled via {@link #setGlassEnabled(boolean)}.
   *
   * @return the glass element, or null if not created
   */
  protected Element getGlassElement() {
    return glass;
  }

  @Override
  protected com.google.gwt.user.client.Element getStyleElement() {
    return impl.getStyleElement(getPopupImplElement()).cast();
  }

  protected void onPreviewNativeEvent(NativePreviewEvent event) {
    // Cancel the event based on the deprecated onEventPreview() method
    if (event.isFirstHandler()
        && !onEventPreview(Event.as(event.getNativeEvent()))) {
      event.cancel();
    }
  }

  @Override
  protected void onUnload() {
    super.onUnload();

    // Just to be sure, we perform cleanup when the popup is unloaded (i.e.
    // removed from the DOM). This is normally taken care of in hide(), but it
    // can be missed if someone removes the popup directly from the RootPanel.
    if (isShowing()) {
      resizeAnimation.setState(false, true);
    }
  }

  /**
   * We control size by setting our child widget's size. However, if we don't
   * currently have a child, we record the size the user wanted so that when we
   * do get a child, we can set it correctly. Until size is explicitly cleared,
   * any child put into the popup will be given that size.
   */
  void maybeUpdateSize() {
    // For subclasses of PopupPanel, we want the default behavior of setWidth
    // and setHeight to change the dimensions of PopupPanel's child widget.
    // We do this because PopupPanel's child widget is the first widget in
    // the hierarchy which provides structure to the panel. DialogBox is
    // an example of this. We want to set the dimensions on DialogBox's
    // FlexTable, which is PopupPanel's child widget. However, it is not
    // DialogBox's child widget. To make sure that we are actually getting
    // PopupPanel's child widget, we have to use super.getWidget().
    Widget w = super.getWidget();
    if (w != null) {
      if (desiredHeight != null) {
        w.setHeight(desiredHeight);
      }
      if (desiredWidth != null) {
        w.setWidth(desiredWidth);
      }
    }
  }

  /**
   * Sets the animation used to animate this popup. Used by gwt-incubator to
   * allow DropDownPanel to override the default popup animation. Not protected
   * because the exact API may change in gwt 1.6.
   *
   * @param animation the animation to use for this popup
   */
  void setAnimation(ResizeAnimation animation) {
    resizeAnimation = animation;
  }

  /**
   * Enable or disable animation of the {@link PopupPanel}.
   *
   * @param type the type of animation to use
   */
  void setAnimationType(AnimationType type) {
    animType = type;
  }

  /**
   * Remove focus from an Element.
   *
   * @param elt The Element on which <code>blur()</code> will be invoked
   */
  private native void blur(Element elt) /*-{
    // Issue 2390: blurring the body causes IE to disappear to the background
    if (elt.blur && elt != $doc.body) {
      elt.blur();
    }
  }-*/;

  /**
   * Does the event target one of the partner elements?
   *
   * @param event the native event
   * @return true if the event targets a partner
   */
  private boolean eventTargetsPartner(NativeEvent event) {
    if (autoHidePartners == null) {
      return false;
    }

    EventTarget target = event.getEventTarget();
    if (Element.is(target)) {
      for (Element elem : autoHidePartners) {
        if (elem.isOrHasChild(Element.as(target))) {
          return true;
        }
      }
    }
    return false;
  }

  /**
   * Does the event target this popup?
   *
   * @param event the native event
   * @return true if the event targets the popup
   */
  private boolean eventTargetsPopup(NativeEvent event) {
    EventTarget target = event.getEventTarget();
    if (Element.is(target)) {
      return getElement().isOrHasChild(Element.as(target));
    }
    return false;
  }

  /**
   * Get the element that {@link PopupImpl} uses. PopupImpl creates an element
   * that goes inside of the outer element, so all methods in PopupImpl are
   * relative to the first child of the outer element, not the outer element
   * itself.
   *
   * @return the Element that {@link PopupImpl} creates and expects
   */
  private com.google.gwt.user.client.Element getPopupImplElement() {
    return DOM.getFirstChild(super.getContainerElement());
  }

  /**
   * Positions the popup, called after the offset width and height of the popup
   * are known.
   *
   * @param relativeObject the ui object to position relative to
   * @param offsetWidth the drop down's offset width
   * @param offsetHeight the drop down's offset height
   */
  private void position(final UIObject relativeObject, int offsetWidth,
      int offsetHeight) {
    // Calculate left position for the popup. The computation for
    // the left position is bidi-sensitive.

    int textBoxOffsetWidth = relativeObject.getOffsetWidth();

    // Compute the difference between the popup's width and the
    // textbox's width
    int offsetWidthDiff = offsetWidth - textBoxOffsetWidth;

    int left;

    if (LocaleInfo.getCurrentLocale().isRTL()) { // RTL case

      int textBoxAbsoluteLeft = relativeObject.getAbsoluteLeft();

      // Right-align the popup. Note that this computation is
      // valid in the case where offsetWidthDiff is negative.
      left = textBoxAbsoluteLeft - offsetWidthDiff;

      // If the suggestion popup is not as wide as the text box, always
      // align to the right edge of the text box. Otherwise, figure out whether
      // to right-align or left-align the popup.
      if (offsetWidthDiff > 0) {

        // Make sure scrolling is taken into account, since
        // box.getAbsoluteLeft() takes scrolling into account.
        int windowRight = Window.getClientWidth() + Window.getScrollLeft();
        int windowLeft = Window.getScrollLeft();

        // Compute the left value for the right edge of the textbox
        int textBoxLeftValForRightEdge = textBoxAbsoluteLeft
            + textBoxOffsetWidth;

        // Distance from the right edge of the text box to the right edge
        // of the window
        int distanceToWindowRight = windowRight - textBoxLeftValForRightEdge;

        // Distance from the right edge of the text box to the left edge of the
        // window
        int distanceFromWindowLeft = textBoxLeftValForRightEdge - windowLeft;

        // If there is not enough space for the overflow of the popup's
        // width to the right of the text box and there IS enough space for the
        // overflow to the right of the text box, then left-align the popup.
        // However, if there is not enough space on either side, stick with
        // right-alignment.
        if (distanceFromWindowLeft < offsetWidth
            && distanceToWindowRight >= offsetWidthDiff) {
          // Align with the left edge of the text box.
          left = textBoxAbsoluteLeft;
        }
      }
    } else { // LTR case

      // Left-align the popup.
      left = relativeObject.getAbsoluteLeft();

      // If the suggestion popup is not as wide as the text box, always align to
      // the left edge of the text box. Otherwise, figure out whether to
      // left-align or right-align the popup.
      if (offsetWidthDiff > 0) {
        // Make sure scrolling is taken into account, since
        // box.getAbsoluteLeft() takes scrolling into account.
        int windowRight = Window.getClientWidth() + Window.getScrollLeft();
        int windowLeft = Window.getScrollLeft();

        // Distance from the left edge of the text box to the right edge
        // of the window
        int distanceToWindowRight = windowRight - left;

        // Distance from the left edge of the text box to the left edge of the
        // window
        int distanceFromWindowLeft = left - windowLeft;

        // If there is not enough space for the overflow of the popup's
        // width to the right of hte text box, and there IS enough space for the
        // overflow to the left of the text box, then right-align the popup.
        // However, if there is not enough space on either side, then stick with
        // left-alignment.
        if (distanceToWindowRight < offsetWidth
            && distanceFromWindowLeft >= offsetWidthDiff) {
          // Align with the right edge of the text box.
          left -= offsetWidthDiff;
        }
      }
    }

    // Calculate top position for the popup

    int top = relativeObject.getAbsoluteTop();

    // Make sure scrolling is taken into account, since
    // box.getAbsoluteTop() takes scrolling into account.
    int windowTop = Window.getScrollTop();
    int windowBottom = Window.getScrollTop() + Window.getClientHeight();

    // Distance from the top edge of the window to the top edge of the
    // text box
    int distanceFromWindowTop = top - windowTop;

    // Distance from the bottom edge of the window to the bottom edge of
    // the text box
    int distanceToWindowBottom = windowBottom
        - (top + relativeObject.getOffsetHeight());

    // If there is not enough space for the popup's height below the text
    // box and there IS enough space for the popup's height above the text
    // box, then then position the popup above the text box. However, if there
    // is not enough space on either side, then stick with displaying the
    // popup below the text box.
    if (distanceToWindowBottom < offsetHeight
        && distanceFromWindowTop >= offsetHeight) {
      top -= offsetHeight;
    } else {
      // Position above the text box
      top += relativeObject.getOffsetHeight();
    }
    setPopupPosition(left, top);
  }

  /**
   * Preview the {@link NativePreviewEvent}.
   *
   * @param event the {@link NativePreviewEvent}
   */
  private void previewNativeEvent(NativePreviewEvent event) {
    // If the event has been canceled or consumed, ignore it
    if (event.isCanceled() || (!previewAllNativeEvents && event.isConsumed())) {
      // We need to ensure that we cancel the event even if its been consumed so
      // that popups lower on the stack do not auto hide
      if (modal) {
        event.cancel();
      }
      return;
    }

    // Fire the event hook and return if the event is canceled
    onPreviewNativeEvent(event);
    if (event.isCanceled()) {
      return;
    }

    // If the event targets the popup or the partner, consume it
    Event nativeEvent = Event.as(event.getNativeEvent());
    boolean eventTargetsPopupOrPartner = eventTargetsPopup(nativeEvent)
        || eventTargetsPartner(nativeEvent);
    if (eventTargetsPopupOrPartner) {
      event.consume();
    }

    // Cancel the event if it doesn't target the modal popup. Note that the
    // event can be both canceled and consumed.
    if (modal) {
      event.cancel();
    }

    // Switch on the event type
    int type = nativeEvent.getTypeInt();
    switch (type) {
      case Event.ONKEYDOWN: {
        if (!onKeyDownPreview((char) nativeEvent.getKeyCode(),
            KeyboardListenerCollection.getKeyboardModifiers(nativeEvent))) {
          event.cancel();
        }
        return;
      }
      case Event.ONKEYUP: {
        if (!onKeyUpPreview((char) nativeEvent.getKeyCode(),
            KeyboardListenerCollection.getKeyboardModifiers(nativeEvent))) {
          event.cancel();
        }
        return;
      }
      case Event.ONKEYPRESS: {
        if (!onKeyPressPreview((char) nativeEvent.getKeyCode(),
            KeyboardListenerCollection.getKeyboardModifiers(nativeEvent))) {
          event.cancel();
        }
        return;
      }

      case Event.ONMOUSEDOWN:
      case Event.ONTOUCHSTART:
        // Don't eat events if event capture is enabled, as this can
        // interfere with dialog dragging, for example.
        if (DOM.getCaptureElement() != null) {
          event.consume();
          return;
        }

        if (!eventTargetsPopupOrPartner && autoHide) {
          hide(true);
          return;
        }
        break;
      case Event.ONMOUSEUP:
      case Event.ONMOUSEMOVE:
      case Event.ONCLICK:
      case Event.ONDBLCLICK:
      case Event.ONTOUCHEND: {
        // Don't eat events if event capture is enabled, as this can
        // interfere with dialog dragging, for example.
        if (DOM.getCaptureElement() != null) {
          event.consume();
          return;
        }
        break;
      }

      case Event.ONFOCUS: {
        Element target = nativeEvent.getTarget();
        if (modal && !eventTargetsPopupOrPartner && (target != null)) {
          blur(target);
          event.cancel();
          return;
        }
        break;
      }
    }
  }

  /**
   * Register or unregister the handlers used by {@link PopupPanel}.
   */
  private void updateHandlers() {
    // Remove any existing handlers.
    if (nativePreviewHandlerRegistration != null) {
      nativePreviewHandlerRegistration.removeHandler();
      nativePreviewHandlerRegistration = null;
    }
    if (historyHandlerRegistration != null) {
      historyHandlerRegistration.removeHandler();
      historyHandlerRegistration = null;
    }

    // Create handlers if showing.
    if (showing) {
      nativePreviewHandlerRegistration = Event.addNativePreviewHandler(new NativePreviewHandler() {
        public void onPreviewNativeEvent(NativePreviewEvent event) {
          previewNativeEvent(event);
        }
      });
      historyHandlerRegistration = History.addValueChangeHandler(new ValueChangeHandler<String>() {
        public void onValueChange(ValueChangeEvent<String> event) {
          if (autoHideOnHistoryEvents) {
            hide();
          }
        }
      });
    }
  }
}
