/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.doodad.attachment;
import org.waveprotocol.wave.client.doodad.attachment.render.ImageThumbnailRenderer;
import org.waveprotocol.wave.client.doodad.attachment.render.ImageThumbnailView;
import org.waveprotocol.wave.client.editor.content.ContentElement;
import org.waveprotocol.wave.media.model.Attachment;
import org.waveprotocol.wave.media.model.Attachment.ImageMetadata;
import org.waveprotocol.wave.media.model.Attachment.Status;
import org.waveprotocol.wave.model.util.CollectionUtils;
import org.waveprotocol.wave.model.util.IdentityMap;
import org.waveprotocol.wave.model.util.Preconditions;
/**
* Handler for the attachment logic for thumbnail doodads.
*
* @author danilatos@google.com (Daniel Danilatos)
*/
public class ImageThumbnailAttachmentHandler implements SimpleAttachmentManager.Listener {
// @NotInternationalized
private static final String attachmentLoadingFailedTooltip = "Loading attachment failed.";
private static final String attachmentMalwareDetected =
"The file contains a virus or other malware and has been disabled.";
// Memory leak? Should be OK if this handler is per-wavelet
private final IdentityMap<Attachment, ContentElement> doodads =
CollectionUtils.createIdentityMap();
private ImageThumbnailRenderer renderer;
/** NOTE(patcoleman): Not in ctor due to circular dependency. */
void setRenderer(ImageThumbnailRenderer renderer) {
Preconditions.checkArgument(renderer != null, "can't bind attachment handler to a null renderer");
Preconditions.checkState(this.renderer == null, "renderer should only be set once");
this.renderer = renderer;
}
/**
* Set up attachment handling for the given element
*
* @param e the element
* @param attachment the attachment
*/
public void init(ContentElement e, Attachment attachment) {
doodads.put(attachment, e);
onContentUpdated(attachment);
onThumbnailUpdated(attachment);
onUploadStatusUpdated(attachment);
}
/**
* Inverse of {@link #init}.
*/
public void cleanup(ContentElement e, Attachment a) {
doodads.remove(a);
}
private ContentElement getElement(Attachment c) {
ContentElement e = doodads.get(c);
if (e != null) {
if (!e.isContentAttached()) {
// Lazy removal. Perhaps do it from the node mutation event handler?
doodads.remove(c);
} else {
return e;
}
}
return null;
}
@Override
public void onContentUpdated(Attachment c) {
ContentElement e = getElement(c);
// TODO(nigeltao): can e ever be null?
if (e == null) {
return;
}
String url = c.getAttachmentUrl();
if (url != null) {
renderer.getView(e).setAttachmentUrl(url);
}
ImageMetadata metadata = c.getContentImageMetadata();
if (metadata != null) {
renderer.getView(e).setAttachmentSize(metadata.getWidth(), metadata.getHeight());
}
}
@Override
public void onThumbnailUpdated(Attachment c) {
ContentElement e = getElement(c);
if (e == null) {
return;
}
if (c.isMalware()) {
renderer.getView(e).displayDeadImage(attachmentMalwareDetected);
return;
}
String url = c.getThumbnailUrl();
if (url != null) {
renderer.getView(e).setThumbnailUrl(url);
}
ImageMetadata metadata = c.getThumbnailImageMetadata();
if (metadata != null) {
renderer.getView(e).setThumbnailSize(metadata.getWidth(), metadata.getHeight());
}
if (metadata == null && c.getStatus() == Status.FAILED_AND_NOT_RETRYABLE) {
renderer.getView(e).displayDeadImage(
attachmentLoadingFailedTooltip);
}
}
@Override
public void onUploadStatusUpdated(Attachment c) {
ContentElement e = getElement(c);
if (e == null) {
return;
}
ImageThumbnailView v = renderer.getView(e);
switch (c.getStatus()) {
case NOT_UPLOADING:
case SUCCEEDED:
v.hideUploadProgress();
break;
case IN_PROGRESS:
case FAILED_AND_RETRYABLE:
v.setUploadProgress(((double)c.getUploadedByteCount())/c.getSize());
v.showUploadProgress();
break;
case FAILED_AND_NOT_RETRYABLE:
v.hideUploadProgress();
v.displayDeadImage(attachmentLoadingFailedTooltip);
break;
default:
throw new IllegalStateException();
}
}
}