/**
* 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.box.webclient.search;
import static cc.kune.polymer.client.Layout.*;
import java.util.LinkedList;
import java.util.List;
import org.waveprotocol.box.webclient.search.i18n.DigestDomMessages;
import org.waveprotocol.wave.client.account.Profile;
import org.waveprotocol.wave.client.common.safehtml.SafeHtml;
import org.waveprotocol.wave.client.common.safehtml.SafeHtmlBuilder;
import org.waveprotocol.wave.client.uibuilder.BuilderHelper;
import cc.kune.common.client.log.Log;
import cc.kune.common.client.tooltip.Tooltip;
import cc.kune.common.shared.i18n.I18n;
import cc.kune.core.client.dnd.KuneDragController;
import cc.kune.core.client.services.ClientFileDownloadUtils;
import cc.kune.core.shared.dto.GroupDTO;
import cc.kune.initials.AvatarComposite;
import cc.kune.initials.AvatarCompositeFactory;
import cc.kune.polymer.client.PolymerUtils;
import com.allen_sauer.gwt.dnd.client.HasDragHandle;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
public final class CustomDigestDomImpl extends Composite implements DigestView, HasDragHandle {
interface Binder extends UiBinder<Widget, CustomDigestDomImpl> {
}
interface Css extends CssResource {
String avatar();
String avatars();
String digest();
String info();
String inner();
String selected();
String unread();
String unreadCount();
}
/** Resources used by this widget. */
interface Resources extends ClientBundle {
/** CSS */
@Source("mock/digest.css")
Css css();
}
private final static Binder BINDER = GWT.create(Binder.class);
/** HTML attribute used to hold an id unique within digest widgets. */
static String DIGEST_ID_ATTRIBUTE = "di";
private static int idCounter;
private static final DigestDomMessages messages = GWT.create(DigestDomMessages.class);
@UiField
Element avatarsAndUnreadDiv;
@UiField
FlowPanel avatarsDiv;
@UiField
SimplePanel avatarsSummary;
private List<Profile> currentProfiles;
private final ClientFileDownloadUtils downUtils;
private final KuneDragController dragController;
private boolean draggable;
@UiField
SimplePanel groupAvatarContainer;
@UiField
Element main;
@UiField
Element mainLeft;
@UiField
HTMLPanel mainPanel;
@UiField
Element mainRight;
@UiField
InlineLabel msgs;
@UiField
InlineLabel position;
private final Element self;
@UiField
InlineLabel snippet;
@UiField
InlineLabel time;
@UiField
InlineLabel title;
@UiField
FlowPanel unreadDiv;
private String waveUri;
public CustomDigestDomImpl(final KuneDragController dragController,
final ClientFileDownloadUtils downUtils) {
this.dragController = dragController;
this.downUtils = downUtils;
initWidget(BINDER.createAndBindUi(this));
self = this.getElement();
self.setAttribute(BuilderHelper.KIND_ATTRIBUTE, "digest");
self.setAttribute(DIGEST_ID_ATTRIBUTE, "D" + idCounter++);
PolymerUtils.addLayout(main, HORIZONTAL, LAYOUT, FLEX);
PolymerUtils.addLayout(mainLeft, VERTICAL, LAYOUT);
PolymerUtils.addLayout(mainRight, VERTICAL, LAYOUT, FLEX);
PolymerUtils.addLayout(avatarsAndUnreadDiv, VERTICAL, LAYOUT);
PolymerUtils.addLayout(avatarsDiv, HORIZONTAL, JUSTIFIED, LAYOUT);
Tooltip.to(this, "");
position.setVisible(false); // only for test
}
private void createGroupAvatar(final String url) {
groupAvatarContainer.clear();
final Image groupAvatar = new Image();
groupAvatar.addLoadHandler(new LoadHandler() {
@Override
public void onLoad(final LoadEvent event) {
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
if (groupAvatar.getWidth() == 1) {
// If the server loads an avatar, is already published in a group.
// if not, the servelt returns a 1x1 transparent pixel, so the
// wave
// can be dragged to a folder publish it.
draggable = true;
} else {
draggable = false;
}
// Log.info("Inbox group avatar size: " + groupAvatar.getWidth() +
// "x"
// + groupAvatar.getHeight());
groupAvatar.setSize("41px", "41px");
}
});
}
});
groupAvatarContainer.add(groupAvatar);
groupAvatar.setUrl(url);
}
private DragableImageParticipant createImageDragable(final String imageUrl, final String address) {
final DragableImageParticipant participant = new DragableImageParticipant(imageUrl, address);
dragController.makeDraggable(participant);
return participant;
}
private DragableInitialParticipant createInitialDragable(final String address) {
final DragableInitialParticipant participant = new DragableInitialParticipant(address);
dragController.makeDraggable(participant);
return participant;
}
@Override
public void deselect() {
self.removeClassName("k-digest-selected");
makeNotDraggable();
}
@Override
public Widget getDragHandle() {
return this;
}
String getId() {
return getElement().getAttribute(DIGEST_ID_ATTRIBUTE);
}
public String getWaveUri() {
return waveUri;
}
private void makeDragable() {
Tooltip.to(this, I18n.t("Drag and drop into a group or personal folder to publish"));
dragController.makeDraggable(CustomDigestDomImpl.this, title);
dragController.makeDraggable(CustomDigestDomImpl.this, snippet);
}
public void makeNotDraggable() {
removeTooltip();
try {
dragController.makeNotDraggable(this);
} catch (final RuntimeException e) {
// gwt-dd don't have a way to check if some widget is dragable, and as
// this Digest are reusable, then sometimes are dragables when is not
// necessary
Log.debug("We tried to remove a not (yet) dragable widget");
}
}
@Override
public void remove() {
// TODO
self.removeFromParent();
setVisible(false);
}
public void removeTooltip() {
Tooltip.to(this, "");
}
private SafeHtml renderReadMessages(final int total) {
final SafeHtmlBuilder html = new SafeHtmlBuilder();
html.appendHtmlConstant(String.valueOf(total));
html.appendHtmlConstant(" " + messages.msgs());
return html.toSafeHtml();
}
private SafeHtml renderUnreadMessages(final int unread, final int total) {
final SafeHtmlBuilder html = new SafeHtmlBuilder();
html.appendHtmlConstant("<span class='" + "k-digest-unread-count" + "'>");
html.appendHtmlConstant(String.valueOf(unread));
html.appendHtmlConstant("</span>");
html.appendHtmlConstant(" " + messages.of(total));
return html.toSafeHtml();
}
public void reset() {
title.setText("");
snippet.setText("");
time.setText("");
// remove avatars
groupAvatarContainer.clear();
msgs.setText("");
self.removeClassName("k-digest-selected");
makeNotDraggable();
setVisible(false);
draggable = false;
currentProfiles = null;
avatarsSummary.clear();
position.setText("");
}
@Override
public void select() {
self.addClassName("k-digest-selected");
if (draggable) {
// Log.info("Digests is dragable");
makeDragable();
} else {
makeNotDraggable();
// Log.info("Digests is not dragable");
}
}
@Override
public void setAvatars(final List<Profile> profiles) {
if (currentProfiles != null && profiles.size() == currentProfiles.size()) {
// Same participants, same avatars
Log.debug("SearchPanel same avatars");
return;
}
Log.debug("SearchPanel different avatars");
currentProfiles = profiles;
final LinkedList<IsWidget> names = new LinkedList<IsWidget>();
for (final Profile profile : profiles) {
final String imageUrl = profile.getImageUrl();
final String address = profile.getAddress();
final Widget avatar = imageUrl.contains("iniavatars") ? createInitialDragable(address)
: createImageDragable(imageUrl, address);
Tooltip.to(avatar, profile.getFullName());
// FIXME: seems that this not work for some reason. Maybe some work should
// be done in AvatarComposite
// new DragableImageParticipant(imageUrl, address)
// FIXME: Last connected?
// Try to use MediumAvatarDecorator or similar
names.add(avatar);
}
final AvatarComposite composite = AvatarCompositeFactory.get40().build(names);
composite.addStyleName("k-digest-avatar");
avatarsSummary.clear();
avatarsSummary.add(composite);
}
public void setGroup(final GroupDTO group) {
createGroupAvatar(downUtils.getGroupLogo(group));
}
@Override
public void setMessageCounts(final int unread, final int total) {
// TODO Auto-generated method stub
if (unread == 0) {
msgs.getElement().setInnerHTML(renderReadMessages(total).asString());
title.removeStyleName("k-digest-unread");
time.removeStyleName("k-digest-unread");
} else {
msgs.getElement().setInnerHTML(renderUnreadMessages(unread, total).asString());
title.addStyleName("k-digest-unread");
time.addStyleName("k-digest-unread");
}
}
public void setPosition(final String text) {
position.setText(text);
}
@Override
public void setSnippet(final String text) {
snippet.setText(text);
}
@Override
public void setTimestamp(final String text) {
time.setText(text);
}
@Override
public void setTitleText(final String text) {
title.setText(text);
}
public void setWaveUri(final String waveUri) {
this.waveUri = waveUri;
createGroupAvatar(downUtils.getGroupLogoFromWaveUri(waveUri));
}
}