/** * 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 org.waveprotocol.wave.client.widget.popup; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.StyleInjector; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.Widget; import org.waveprotocol.wave.client.common.webdriver.DebugClassHelper; import java.util.ArrayList; import java.util.List; /** * Class implementing UniversalPopup for mobile clients. * * * TODO(user) rename this class SmallScreenUniversalPopup */ class MobileUniversalPopup implements UniversalPopup { /** Internal class used to implement popups on mobile */ static final class InternalPopup extends ComplexPanel { private final Element container; private final Element shadow; private final Element content; /** Command to be executed when user clicks on shadow. */ private final Command hideCommand; /** Resources used by this widget. */ interface Resources extends ClientBundle { /** CSS */ @Source("MobileUniversalPopup.css") Css css(); } /** CSS for this widget. */ interface Css extends CssResource { String container(); String shadow(); String content(); } /** The singleton instance of resources. */ private static final Resources RESOURCES = GWT.create(Resources.class); static { StyleInjector.inject(RESOURCES.css().getText()); } /** Helper function to create a DivElement with a given style name */ private Element createDiv(String style) { DivElement x = Document.get().createDivElement(); x.setClassName(style); return (Element) Element.as(x); } /** Create a new InternalPanel */ public InternalPopup(Command hideCommand) { this.hideCommand = hideCommand; container = createDiv(RESOURCES.css().container()); container.appendChild(shadow = createDiv(RESOURCES.css().shadow())); container.appendChild(content = createDiv(RESOURCES.css().content())); setElement(container); sinkEvents(Event.ONCLICK); } /** Insert widget as first child */ public void insertFirst(Widget child) { super.insert(child, content, 0, true); } /** {@inheritDoc} */ @Override public void add(Widget child) { super.add(child, content); } @Override public void onBrowserEvent(Event event) { if (event.getTypeInt() == Event.ONCLICK && event.getTarget() == shadow) { hideCommand.execute(); } else { super.onBrowserEvent(event); } } } /** Our instance of InternalPopup */ private final InternalPopup popup = new InternalPopup(new Command() { public void execute() { hide(); } }); /** List of PopupEventListeners */ private final List<PopupEventListener> listeners = new ArrayList<PopupEventListener>(); /** The root panel we add to when show is called */ private final Panel root; // TODO(user) replace with a mobile implementation. private DesktopTitleBar titleBar; // visibility state of this popup. private boolean showing = false; /** * Create a new MobileUniversalPopup. * @param root The root panel to which popups will be added when show is called. */ MobileUniversalPopup(Panel root) { this.root = root; DebugClassHelper.addDebugClass(popup, DEBUG_CLASS); } /** * {@inheritDoc} */ public void hide() { showing = true; root.remove(popup); for (PopupEventListener l : listeners) { l.onHide(this); } } /** * {@inheritDoc} */ public void show() { showing = false; root.add(popup); for (PopupEventListener l : listeners) { l.onShow(this); } } /** * {@inheritDoc} */ public void move() { // Do nothing } /** * {@inheritDoc} */ public void addPopupEventListener(PopupEventListener listener) { listeners.add(listener); } /** * {@inheritDoc} */ public void removePopupEventListener(PopupEventListener listener) { listeners.remove(listener); } /** * {@inheritDoc} */ public TitleBar getTitleBar() { if (titleBar == null) { titleBar = new DesktopTitleBar(); popup.insertFirst(titleBar); } return titleBar; } /** * {@inheritDoc} */ public boolean isShowing() { return showing; } /** * {@inheritDoc} */ public void add(Widget w) { popup.add(w); } /** * {@inheritDoc} */ public void clear() { popup.clear(); } /** * {@inheritDoc} */ public boolean remove(Widget w) { return popup.remove(w); } /** * {@inheritDoc} */ public void associateWidget(Widget w) { // Ignore on mobiles, where no auto-hiding takes place } @Override public void setMaskEnabled(boolean isMaskEnabled) { throw new IllegalStateException("masking is not defined for MobileUniversalPopup."); } @Override // TODO(user): change this method name to addDebugClass public void setDebugClass(String dcName) { if (dcName != null) { DebugClassHelper.addDebugClass(popup.getElement(), dcName); } } }