/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.ide.notification; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import org.eclipse.che.ide.Resources; import org.eclipse.che.ide.api.notification.Notification; import org.eclipse.che.ide.api.notification.NotificationObserver; import org.eclipse.che.ide.api.notification.StatusNotification; import org.eclipse.che.ide.notification.NotificationManagerView.NotificationActionDelegate; import org.vectomatic.dom.svg.ui.SVGImage; import org.vectomatic.dom.svg.ui.SVGResource; import javax.validation.constraints.NotNull; import java.util.Date; /** * Widget for showing notification in the notification panel. * <p/> * {@link Notification} may be instance of {@link StatusNotification}. Each rendered notification consists of: * <ul> * <li>Icon</li> * <li>Title</li> * <li>Message content (optional)</li> * <li>Close control</li> * </ul> * * @author Andrey Plotnikov * @author Vlad Zhukovskyi */ public class NotificationContainerItem extends Composite implements NotificationObserver { public static final String MESSAGE_WRAPPER_DBG_ID = "message-wrapper"; public static final String NOTIFICATION_WRAPPER_DBG_ID = "notification-wrapper"; public static final String TITLE_DBG_ID = "title"; public static final String CONTENT_DBG_ID = "content"; public static final String ICON_DBG_ID = "icon"; public static final String CLOSE_ICON_DBG_ID = "close-icon"; private static final DateTimeFormat DATA_FORMAT = DateTimeFormat.getFormat("h:mm a"); private SimplePanel titlePanel; private SimplePanel messagePanel; private SimplePanel iconPanel; private Resources resources; private Notification notification; private NotificationActionDelegate delegate; private int clickCount = 0; /** * Create notification item. * * @param resources * core resources * @param notification * notification which should be wrapped into widget */ public NotificationContainerItem(final Notification notification, @NotNull Resources resources) { notification.addObserver(this); this.resources = resources; this.notification = notification; iconPanel = new SimplePanel(); FlowPanel contentWrapper = new FlowPanel(); contentWrapper.add(titlePanel = createTitleWidget()); contentWrapper.add(messagePanel = createContentWidget()); contentWrapper.ensureDebugId(CONTENT_DBG_ID + notification.getId()); contentWrapper.setStyleName(resources.notificationCss().notificationContentWrapper()); FlowPanel notificationWrapper = new FlowPanel(); notificationWrapper.add(iconPanel = createIconWidget()); notificationWrapper.add(contentWrapper); notificationWrapper.add(createCloseWidget()); notificationWrapper.ensureDebugId(NOTIFICATION_WRAPPER_DBG_ID + notification.getId()); notificationWrapper.setStyleName(resources.notificationCss().notification()); update(); sinkEvents(Event.ONCLICK | Event.ONDBLCLICK); initWidget(notificationWrapper); } /** {@inheritDoc} */ @Override public void onBrowserEvent(Event event) { super.onBrowserEvent(event); switch (DOM.eventGetType(event)) { case Event.ONCLICK: clickCount++; if (clickCount == 1) { Timer timer = new Timer() { @Override public void run() { if (clickCount == 1) { clickCount = 0; delegate.onClick(notification); } } }; timer.schedule(200); } break; case Event.ONDBLCLICK: clickCount = 0; delegate.onDoubleClick(notification); break; } } /** * Create icon wrapper that contains an icon. * * @return {@link SimplePanel} as icon wrapper */ private SimplePanel createIconWidget() { SimplePanel iconWrapper = new SimplePanel(); iconWrapper.setStyleName(resources.notificationCss().notificationIconWrapper()); iconWrapper.ensureDebugId(ICON_DBG_ID + notification.getId()); return iconWrapper; } /** * Create close icon widget that contains an close notification icon. * * @return {@link SimplePanel} as close icon wrapper */ private SimplePanel createCloseWidget() { SimplePanel closeWrapper = new SimplePanel(); SVGImage closeImage = new SVGImage(resources.closeIcon()); closeImage.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { delegate.onClose(notification); } }); closeWrapper.add(closeImage); closeWrapper.setStyleName(resources.notificationCss().notificationCloseButtonWrapper()); closeImage.ensureDebugId(CLOSE_ICON_DBG_ID + notification.getId()); return closeWrapper; } /** * Create title widget that contains notification title. * * @return {@link SimplePanel} as title wrapper */ private SimplePanel createTitleWidget() { SimplePanel titleWrapper = new SimplePanel(); Label titleLabel = new Label(); titleWrapper.add(titleLabel); titleWrapper.setStyleName(resources.notificationCss().notificationTitleWrapper()); titleWrapper.ensureDebugId(TITLE_DBG_ID + notification.getId()); return titleWrapper; } /** * Create message widget that contains notification message. * * @return {@link SimplePanel} as message wrapper */ private SimplePanel createContentWidget() { SimplePanel messageWrapper = new SimplePanel(); Label messageLabel = new Label(); messageWrapper.add(messageLabel); messageWrapper.setStyleName(resources.notificationCss().notificationMessageWrapper()); messageWrapper.ensureDebugId(MESSAGE_WRAPPER_DBG_ID + notification.getId()); return messageWrapper; } /** {@inheritDoc} */ @Override public Widget asWidget() { return super.asWidget(); } /** * Sets the delegate for receiving events from this view. */ public void setDelegate(NotificationActionDelegate delegate) { this.delegate = delegate; } /** * Return an icon based on {@link org.eclipse.che.ide.api.notification.StatusNotification.Status}. * * @return SVG image that represents icon status */ private SVGImage getIconBaseOnStatus() { final SVGResource icon; final String status; switch (((StatusNotification)notification).getStatus()) { case PROGRESS: icon = resources.progress(); status = "progress"; break; case SUCCESS: icon = resources.success(); status = "success"; break; case FAIL: icon = resources.fail(); status = "fail"; break; case WARNING: icon = resources.warning(); status = "warning"; break; default: throw new IllegalArgumentException("Can't determine notification icon"); } SVGImage image = new SVGImage(icon); image.getElement().setAttribute("name", status); return image; } /** {@inheritDoc} */ @Override public void onValueChanged() { update(); } /** * Update notification's widget values. * <p/> * Widget consumes: * <ul> * <li>{@link Notification#title}</li> * <li>{@link Notification#content}</li> * <li>Icon and background color based on {@link StatusNotification.Status}</li> * </ul> */ private void update() { Widget titleWidget = titlePanel.getWidget(); if (titleWidget != null && titleWidget instanceof Label) { ((Label)titleWidget).setText(notification.getTitle()); StringBuilder infoBuilder = new StringBuilder(); if (notification.getProject() != null) { infoBuilder.append("Project: ").append(notification.getProject().getName()).append(". "); } infoBuilder.append(DATA_FORMAT.format(new Date(notification.getTime()))); titlePanel.getElement().setAttribute("info", infoBuilder.toString()); } Widget messageWidget = messagePanel.getWidget(); if (messageWidget != null && messageWidget instanceof Label) { ((Label)messageWidget).setText(notification.getContent()); } if (notification instanceof StatusNotification) { iconPanel.setWidget(getIconBaseOnStatus()); } } }