Package com.google.livingstories.client.ui

Source Code of com.google.livingstories.client.ui.AutoHidePopupPanel

/**
* Copyright 2010 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.livingstories.client.ui;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.livingstories.client.lsp.views.Resources;
import com.google.livingstories.client.util.LivingStoryControls;
import com.google.livingstories.client.util.ObjectElementScrubber;

/**
* A PopupPanel that hides itself whenever the user clicks outside of it (optionally)
* or on a link inside of it.
*/
public class AutoHidePopupPanel extends PopupPanel {
  public static String NON_HIDING_CLASS = "nonhiding";
 
  private boolean wholePopupIsLink;

  private ObjectElementScrubber scrubber = GWT.create(ObjectElementScrubber.class);
  private boolean scrubbed;
 
  private boolean skipHide = false;
 
  public AutoHidePopupPanel() {
    this(true);
  }
 
  public AutoHidePopupPanel(boolean autoHide) {
    super(autoHide);
  }

  @Override
  public void setWidget(Widget w) {
    super.setWidget(w);
    scrubbed = false;
  }
 
  // the superclass add() method calls into setWidget, and thus needn't be overridden separately.
 
  @Override
  public void show() {
    if (scrubbed) {
      if (GWT.isScript()) {
        // just hide the dialog. The user's encountered a bug, but we don't want to put them
        // in a position where we need to instruct them what to do next.
        LivingStoryControls.showGlass(false);
        super.hide();
      } else {
        // show a better error to developers:
        setAutoHideEnabled(true);
        super.setWidget(new Label("Error: the widget within this element was cleaned and cannot"
            + " safely be reshown without having its content reset first"));
      }
    } else {
      super.show();
    }
  }
 
  @Override
  public void hide(boolean autoClosed) {
    if (skipHide) {
      skipHide = false;
      return;
    }
    if (getWidget() != null) {
      // clear the "data" attribute of all HTML objects within the widget, so that no playback
      // persists.
      NodeList<Element> objects = getWidget().getElement().getElementsByTagName("object");
      for (int i = 0, len = objects.getLength(); i < len; i++) {
        scrubber.scrub(objects.getItem(i));
        scrubbed = true;
        // in point of fact, we're safe in FF, but this indicates an implementation problem where
        // a popup is reused that shouldn't be, and we want to catch this on _all_ browsers.
      }
    }
    super.hide(autoClosed);
  }
 
  public void setWholePopupIsLink(boolean wholePopupIsLink) {
    this.wholePopupIsLink = wholePopupIsLink;
  }
 
  @Override
  protected void onPreviewNativeEvent(NativePreviewEvent event) {
    super.onPreviewNativeEvent(event);
    Event nativeEvent = Event.as(event.getNativeEvent());
    if (nativeEvent.getTypeInt() == Event.ONMOUSEDOWN) {
      // This is a hack to make the popup panel not hide when the user drags
      // the window scrollbar thumb.
      // Since we are unable to override relevant methods to achieve this effect,
      // we just tell the hide() method to skip the next call it sees.
      if (nativeEvent.getClientX() > Window.getClientWidth()
          || nativeEvent.getClientY() > Window.getClientHeight()) {
        skipHide = true;
      }
    } else if (nativeEvent.getTypeInt() == Event.ONCLICK) {
      Element source = Element.as(nativeEvent.getEventTarget());
      if (source.getClassName().contains(NON_HIDING_CLASS)) {
        return;
      }
      if (wholePopupIsLink
          || source.getTagName().equalsIgnoreCase("A")
          || source.getClassName().contains("primaryLink")
          || source.getClassName().contains("secondaryLink")
          || source.getClassName().contains(Resources.INSTANCE.css().clickable())) {
        // Need to use a deferred command here because if we hide the panel immediately,
        // it somehow prevents the link from seeing the event.
        DeferredCommand.addCommand(new Command() {
          @Override
          public void execute() {
            hide();
          }
        });
      }
    } else if (nativeEvent.getTypeInt() == Event.ONKEYUP
        && nativeEvent.getKeyCode() == KeyCodes.KEY_ESCAPE) {
      // also hide the dialog if that happens. Handy to provide this, in case the close
      // button somehow gets hidden offscreen.
      hide();
    }   
  }
}
TOP

Related Classes of com.google.livingstories.client.ui.AutoHidePopupPanel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.