/** * 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.wavepanel.impl.toolbar.attachment; import com.google.common.base.Preconditions; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.dom.client.Style.Visibility; import com.google.gwt.dom.client.StyleInjector; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; import com.google.gwt.resources.client.ImageResource; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FileUpload; import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent; import com.google.gwt.user.client.ui.FormPanel.SubmitEvent; import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.Hidden; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import org.waveprotocol.wave.client.common.util.UserAgent; import org.waveprotocol.wave.client.scheduler.ScheduleCommand; import org.waveprotocol.wave.client.scheduler.Scheduler; import org.waveprotocol.wave.client.wavepanel.view.AttachmentPopupView; import org.waveprotocol.wave.client.widget.popup.CenterPopupPositioner; import org.waveprotocol.wave.client.widget.popup.PopupChrome; import org.waveprotocol.wave.client.widget.popup.PopupChromeFactory; import org.waveprotocol.wave.client.widget.popup.PopupEventListener; import org.waveprotocol.wave.client.widget.popup.PopupEventSourcer; import org.waveprotocol.wave.client.widget.popup.PopupFactory; import org.waveprotocol.wave.client.widget.popup.RelativePopupPositioner; import org.waveprotocol.wave.client.widget.popup.UniversalPopup; import org.waveprotocol.wave.media.model.AttachmentId; /** * Widget implementation of a blip link info popup. * * @author yurize@apache.org (Yuri Zelikov) */ public final class AttachmentPopupWidget extends Composite implements AttachmentPopupView, PopupEventListener { interface Binder extends UiBinder<HTMLPanel, AttachmentPopupWidget> { } /** Resources used by this widget. */ public interface Resources extends ClientBundle { /** CSS */ @Source("AttachmentPopupWidget.css") Style style(); @Source("spinner.gif") ImageResource spinner(); } interface Style extends CssResource { String self(); String title(); String spinnerPanel(); String spinner(); String status(); String error(); String done(); } private final static Binder BINDER = GWT.create(Binder.class); @UiField(provided = true) final static Style style = GWT.<Resources> create(Resources.class).style(); private static final String UPLOAD_ACTION_URL = "/attachment/"; static { // StyleInjector's default behaviour of deferred injection messes up // popups, which do synchronous layout queries for positioning. Therefore, // we force synchronous injection. StyleInjector.inject(style.getText(), true); } @UiField FileUpload fileUpload; @UiField Button uploadBtn; @UiField FormPanel form; @UiField Hidden formAttachmentId; @UiField HorizontalPanel spinnerPanel; @UiField Label status; @UiField Image spinnerImg; /** Popup containing this widget. */ private final UniversalPopup popup; /** Optional listener for view events. */ private Listener listener; private AttachmentId attachmentId; /** * Creates link info popup. */ public AttachmentPopupWidget() { initWidget(BINDER.createAndBindUi(this)); // Because we're going to add a FileUpload widget, we'll need to set the // form to use the POST method, and multipart MIME encoding. form.setEncoding(FormPanel.ENCODING_MULTIPART); form.setMethod(FormPanel.METHOD_POST); // Add an event handler to the form. form.addSubmitHandler(new FormPanel.SubmitHandler() { @Override public void onSubmit(SubmitEvent event) { } }); form.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() { @Override public void onSubmitComplete(SubmitCompleteEvent event) { // When the form submission is successfully completed, this // event is fired. Assuming the service returned a response of type // text/html, we can get the result text here (see the FormPanel // documentation for further explanation). spinnerImg.setVisible(false); String results = event.getResults(); if (results != null && results.contains("OK")) { status.setText("Done!"); status.addStyleName(style.done()); listener.onDone(attachmentId.getId(), fileUpload.getFilename()); hide(); } else { status.setText("Error!"); status.addStyleName(style.error()); } } }); uploadBtn.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { String filename = fileUpload.getFilename(); if (filename.length() == 0) { Window.alert("Error!"); } else { spinnerPanel.setVisible(true); formAttachmentId.setValue(attachmentId.getId()); form.submit(); } } }); // Wrap in a popup. PopupChrome chrome = PopupChromeFactory.createPopupChrome(); if (UserAgent.isFirefox()) { popup = PopupFactory.createPopup(this.getElement(), new RelativePopupPositioner() { @Override public void setPopupPositionAndMakeVisible(Element relative, final Element p) { ScheduleCommand.addCommand(new Scheduler.Task() { @Override public void execute() { p.getStyle().setLeft((RootPanel.get().getOffsetWidth() - p.getOffsetWidth()) / 2, Unit.PX); int top = (RootPanel.get().getOffsetHeight() - p.getOffsetHeight()) / 4; p.getStyle().setTop(Math.max(top, 280), Unit.PX); p.getStyle().setVisibility(Visibility.VISIBLE); } }); } }, chrome, true); } else { popup = PopupFactory.createPopup(null, new CenterPopupPositioner(), chrome, true); } popup.add(this); popup.addPopupEventListener(this); } @Override public void init(Listener listener) { Preconditions.checkState(this.listener == null); Preconditions.checkArgument(listener != null); this.listener = listener; } @Override public void reset() { Preconditions.checkState(this.listener != null); this.listener = null; } @Override public void show() { Preconditions.checkState(this.attachmentId != null); form.setAction(UPLOAD_ACTION_URL + attachmentId.getId()); spinnerPanel.setVisible(false); popup.show(); } @Override public void hide() { popup.hide(); } @Override public void onShow(PopupEventSourcer source) { if (listener != null) { listener.onShow(); } } @Override public void onHide(PopupEventSourcer source) { if (listener != null) { listener.onHide(); } } @Override public void setAttachmentId(AttachmentId id) { attachmentId = id; } }