/* ********************************************************************** **
** Copyright notice **
** **
** (c) 2005-2009 RSSOwl Development Team **
** http://www.rssowl.org/ **
** **
** 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.rssowl.org/legal/epl-v10.html **
** **
** A copy is found in the file epl-v10.html and important notices to the **
** license from the team is found in the textfile LICENSE.txt distributed **
** in this package. **
** **
** This copyright notice MUST APPEAR in all copies of the file! **
** **
** Contributors: **
** RSSOwl Development Team - initial API and implementation **
** **
** ********************************************************************** */
package org.rssowl.ui.internal.notifier;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.RGB;
import org.rssowl.core.persist.IBookMark;
import org.rssowl.core.persist.ILabel;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.persist.reference.FeedLinkReference;
import org.rssowl.core.persist.reference.NewsReference;
import org.rssowl.core.util.CoreUtils;
import org.rssowl.core.util.DateUtils;
import org.rssowl.core.util.StringUtils;
import org.rssowl.ui.internal.OwlUI;
import org.rssowl.ui.internal.actions.OpenInBrowserAction;
import org.rssowl.ui.internal.actions.OpenNewsAction;
import java.util.Date;
import java.util.Set;
/**
* Instance of {@link NotificationItem} to display new {@link INews} in the
* Notifier.
*
* @author bpasero
*/
public class NewsNotificationItem extends NotificationItem {
/* Max. length of the Description Excerpt */
private static final int MAX_DESCRIPTION_LENGTH = 500;
private final String fNewsLink;
private final FeedLinkReference fFeedReference;
private final NewsReference fNewsReference;
private final Date fRecentNewsDate;
private boolean fIsNewsSticky;
private boolean fIsNewsRead;
private String fCachedDescriptionExcerpt;
private String fCachedOrigin;
private ImageDescriptor fImage;
private RGB fColor;
/**
* @param news The news that is to be displayed in the Notifier.
*/
public NewsNotificationItem(INews news) {
this(news, null);
}
/**
* @param news The news that is to be displayed in the Notifier.
* @param color The color for the news in the Notifier or <code>null</code> if
* none.
*/
public NewsNotificationItem(INews news, RGB color) {
super(makeText(news), OwlUI.BOOKMARK); //We resolve the real favicon later lazily
fNewsLink = CoreUtils.getLink(news);
fFeedReference = news.getFeedReference();
fNewsReference = new NewsReference(news.getId());
fRecentNewsDate = DateUtils.getRecentDate(news);
fIsNewsSticky = news.isFlagged();
fIsNewsRead = (INews.State.READ == news.getState());
if (color != null)
fColor = color;
else {
Set<ILabel> labels = CoreUtils.getSortedLabels(news);
if (!labels.isEmpty())
fColor = OwlUI.getRGB(labels.iterator().next());
}
}
private String extractDescriptionExcerpt(INews news) {
if (news == null)
return null;
String description = news.getDescription();
if (!StringUtils.isSet(description))
return null;
String content = StringUtils.stripTags(description, true);
content = StringUtils.normalizeString(content);
content = StringUtils.smartTrim(content, MAX_DESCRIPTION_LENGTH);
if (content.contains("&")) //$NON-NLS-1$
content = StringUtils.replaceAll(content, "&", "&&"); //$NON-NLS-1$ //$NON-NLS-2$
return content.length() > 0 ? content : null;
}
private static ImageDescriptor makeImage(FeedLinkReference feedReference) {
IBookMark bookMark = CoreUtils.getBookMark(feedReference);
if (bookMark != null) {
ImageDescriptor favicon = OwlUI.getFavicon(bookMark);
if (favicon != null)
return favicon;
}
return OwlUI.BOOKMARK;
}
/*
* @see org.rssowl.ui.internal.notifier.NotificationItem#getImage()
*/
@Override
public ImageDescriptor getImage() {
if (fImage == null)
fImage = makeImage(fFeedReference);
return fImage;
}
private static String makeText(INews news) {
String headline = CoreUtils.getHeadline(news, true);
if (headline.contains("&")) //$NON-NLS-1$
headline = StringUtils.replaceAll(headline, "&", "&&"); //$NON-NLS-1$ //$NON-NLS-2$
return headline;
}
/*
* @see org.rssowl.ui.internal.notifier.NotificationItem#getDescription()
*/
@Override
public String getDescription() {
if (fCachedDescriptionExcerpt == null)
fCachedDescriptionExcerpt = extractDescriptionExcerpt(fNewsReference.resolve());
return fCachedDescriptionExcerpt;
}
/*
* @see org.rssowl.ui.internal.notifier.NotificationItem#setColor(org.eclipse.swt.graphics.RGB)
*/
@Override
public void setColor(RGB color) {
fColor = color;
}
/*
* @see org.rssowl.ui.internal.notifier.NotificationItem#getColor()
*/
@Override
public RGB getColor() {
return fColor;
}
/*
* @see org.rssowl.ui.internal.notifier.NotificationItem#getOrigin()
*/
@Override
public String getOrigin() {
if (fCachedOrigin == null) {
IBookMark bookMark = CoreUtils.getBookMark(fFeedReference);
if (bookMark != null)
fCachedOrigin = bookMark.getName();
}
return fCachedOrigin;
}
/*
* @see org.rssowl.ui.internal.notifier.NotificationItem#open()
*/
@Override
public void open(MouseEvent e) {
/* Open Link in Browser if Modifier Key is pressed */
if ((e.stateMask & SWT.MOD1) != 0) {
new OpenInBrowserAction(new StructuredSelection(fNewsLink)).run();
}
/* Open Link in Feed View */
else {
INews news = fNewsReference.resolve();
if (news != null) {
OpenNewsAction action = new OpenNewsAction(new StructuredSelection(news));
action.setRestoreWindow(true);
action.setPreferActiveFeedView();
action.run();
}
}
}
/*
* @see org.rssowl.ui.internal.notifier.NotificationItem#supportsSticky()
*/
@Override
public boolean supportsSticky() {
return true;
}
/*
* @see org.rssowl.ui.internal.notifier.NotificationItem#isSticky()
*/
@Override
public boolean isSticky() {
return fIsNewsSticky;
}
/*
* @see org.rssowl.ui.internal.notifier.NotificationItem#makeSticky(boolean)
*/
@Override
public void setSticky(boolean sticky) {
fIsNewsSticky = sticky;
INews news = fNewsReference.resolve();
if (news != null && news.isVisible()) {
news.setFlagged(sticky);
DynamicDAO.save(news);
}
}
/*
* @see org.rssowl.ui.internal.notifier.NotificationItem#supportsMarkRead()
*/
@Override
public boolean supportsMarkRead() {
return true;
}
/*
* @see org.rssowl.ui.internal.notifier.NotificationItem#setRead(boolean)
*/
@Override
public void setRead(boolean read) {
fIsNewsRead = read;
INews news = fNewsReference.resolve();
if (news != null && news.isVisible()) {
news.setState(read ? INews.State.READ : INews.State.NEW);
DynamicDAO.save(news);
}
}
/*
* @see org.rssowl.ui.internal.notifier.NotificationItem#isRead()
*/
@Override
public boolean isRead() {
return fIsNewsRead;
}
/*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(NotificationItem o) {
/* Compare with other News Item */
if (o instanceof NewsNotificationItem) {
/* Return 0 if the Items Equal */
if (equals(o))
return 0;
/* Compare by Date */
Date date1 = fRecentNewsDate;
Date date2 = ((NewsNotificationItem) o).fRecentNewsDate;
int res = date2.compareTo(date1);
return (res != 0) ? res : -1;
}
/* Otherwise sort to Bottom */
return 1;
}
/*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((fNewsReference == null) ? 0 : fNewsReference.hashCode());
return result;
}
/*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
NewsNotificationItem other = (NewsNotificationItem) obj;
if (fNewsReference == null) {
if (other.fNewsReference != null)
return false;
} else if (!fNewsReference.equals(other.fNewsReference))
return false;
return true;
}
}