/* ********************************************************************** ** ** 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.dialogs.properties; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.rssowl.core.internal.persist.NewsContainer; import org.rssowl.core.persist.IBookMark; import org.rssowl.core.persist.IEntity; import org.rssowl.core.persist.IFeed; import org.rssowl.core.persist.IFolder; import org.rssowl.core.persist.IFolderChild; import org.rssowl.core.persist.INews; import org.rssowl.core.persist.INewsBin; import org.rssowl.core.persist.INewsMark; import org.rssowl.core.persist.ISearchMark; import org.rssowl.core.util.StringUtils; import org.rssowl.core.util.SyncUtils; import org.rssowl.core.util.URIUtils; import org.rssowl.ui.dialogs.properties.IEntityPropertyPage; import org.rssowl.ui.dialogs.properties.IPropertyDialogSite; import org.rssowl.ui.internal.Activator; import org.rssowl.ui.internal.Controller; import org.rssowl.ui.internal.FolderNewsMark; import org.rssowl.ui.internal.OwlUI; import org.rssowl.ui.internal.actions.OpenInBrowserAction; import org.rssowl.ui.internal.util.JobRunner; import org.rssowl.ui.internal.util.LayoutUtils; import org.rssowl.ui.internal.util.UIBackgroundJob; import java.net.URI; import java.net.URISyntaxException; import java.text.DateFormat; import java.util.EnumSet; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; /** * Information about selected Entities. * * @author bpasero */ @SuppressWarnings("restriction") public class InformationPropertyPage implements IEntityPropertyPage { private List<IEntity> fEntities; private final DateFormat fDateFormat = OwlUI.getShortDateFormat(); private boolean fInfoComputed = false; private Composite fContainer; private Label fDescriptionLabel; private Link fHomepageLink; private IPropertyDialogSite fSite; /* * @see org.rssowl.ui.dialogs.properties.IEntityPropertyPage#init(org.rssowl.ui.dialogs.properties.IPropertyDialogSite, java.util.List) */ public void init(IPropertyDialogSite site, List<IEntity> entities) { Assert.isTrue(!entities.isEmpty()); fSite = site; fEntities = entities; } /* * @see org.rssowl.ui.dialogs.properties.IEntityPropertyPage#createContents(org.eclipse.swt.widgets.Composite) */ public Control createContents(Composite parent) { fContainer = new Composite(parent, SWT.NONE); fContainer.setLayout(LayoutUtils.createGridLayout(2, 10, 10)); IEntity entity = fEntities.get(0); /* Newsmark Info */ if (entity instanceof INewsMark) { INewsMark newsmark = (INewsMark) fEntities.get(0); /* Bookmark Info */ if (newsmark instanceof IBookMark) fillBookMarkInfo((IBookMark) fEntities.get(0)); /* Created */ if (newsmark.getCreationDate() != null) { createLabel(fContainer, Messages.InformationPropertyPage_CREATED, true); createLabel(fContainer, fDateFormat.format(newsmark.getCreationDate()), false); } /* Last Visited */ createLabel(fContainer, Messages.InformationPropertyPage_LAST_VISITED, true); if (newsmark.getLastVisitDate() != null) createLabel(fContainer, fDateFormat.format(newsmark.getLastVisitDate()), false); else createLabel(fContainer, Messages.InformationPropertyPage_NEVER, false); } /* Folder Info */ else if (entity instanceof IFolder) { IFolder folder = (IFolder) fEntities.get(0); AtomicInteger folders = new AtomicInteger(); AtomicInteger bookmarks = new AtomicInteger(); AtomicInteger newsbins = new AtomicInteger(); AtomicInteger searches = new AtomicInteger(); countFolderChilds(folder, folders, bookmarks, newsbins, searches); /* Show Counts */ createLabel(fContainer, Messages.InformationPropertyPage_FOLDERS, true); createLabel(fContainer, String.valueOf(folders.get()), false); createLabel(fContainer, Messages.InformationPropertyPage_BOOKMARKS, true); createLabel(fContainer, String.valueOf(bookmarks.get()), false); createLabel(fContainer, Messages.InformationPropertyPage_NEWSBINS, true); createLabel(fContainer, String.valueOf(newsbins.get()), false); createLabel(fContainer, Messages.InformationPropertyPage_SEARCHES, true); createLabel(fContainer, String.valueOf(searches.get()), false); } /* News Count */ createLabel(fContainer, Messages.InformationPropertyPage_NEWS_COUNT, true); return fContainer; } private void countFolderChilds(IFolder folder, AtomicInteger folders, AtomicInteger bookmarks, AtomicInteger newsbins, AtomicInteger searches) { List<IFolderChild> children = folder.getChildren(); for (IFolderChild child : children) { if (child instanceof IFolder) { folders.incrementAndGet(); countFolderChilds((IFolder) child, folders, bookmarks, newsbins, searches); } else if (child instanceof IBookMark) bookmarks.incrementAndGet(); else if (child instanceof ISearchMark) searches.incrementAndGet(); else if (child instanceof INewsBin) newsbins.incrementAndGet(); } } private void fillBookMarkInfo(final IBookMark bm) { boolean isSynchronized = SyncUtils.isSynchronized(bm); String message; /* Status */ createLabel(fContainer, Messages.InformationPropertyPage_STATUS, true); /* Error Loading */ if (bm.isErrorLoading()) { message = (String) bm.getProperty(Controller.LOAD_ERROR_KEY); if (!StringUtils.isSet(message)) message = isSynchronized ? Messages.InformationPropertyPage_LOAD_FAILED_UNKNOWN_SYNCED : Messages.InformationPropertyPage_LOAD_FAILED_UNKNOWN; else message = isSynchronized ? NLS.bind(Messages.InformationPropertyPage_LOAD_FAILED_REASON_SYNCED, message) : NLS.bind(Messages.InformationPropertyPage_LOAD_FAILED_REASON, message); } /* Never Loaded */ else if (bm.getMostRecentNewsDate() == null) message = isSynchronized ? Messages.InformationPropertyPage_NOT_SYNCED : Messages.InformationPropertyPage_NOT_LOADED; /* Successfully Loaded */ else message = isSynchronized ? Messages.InformationPropertyPage_SYNCED_OK : Messages.InformationPropertyPage_LOADED_OK; Label msgLabel = new Label(fContainer, SWT.WRAP); msgLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); ((GridData) msgLabel.getLayoutData()).widthHint = 200; msgLabel.setText(message); /* Link to "Find out more" in case of an error */ if (bm.isErrorLoading()) { new Label(fContainer, SWT.None); Link findOutMoreLink = new Link(fContainer, SWT.None); findOutMoreLink.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false)); findOutMoreLink.setText(Messages.InformationPropertyPage_FIND_OUT_MORE); findOutMoreLink.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { try { URI uri; Object errorLink = bm.getProperty(Controller.LOAD_ERROR_LINK_KEY); if (errorLink != null) uri = new URI(errorLink.toString()); else if (SyncUtils.isSynchronized(bm)) uri = new URI(SyncUtils.GOOGLE_READER_URL); else uri = new URI("http://www.feedvalidator.org/check.cgi?url=" + URIUtils.urlEncode(URIUtils.toHTTP(bm.getFeedLinkReference().getLinkAsText()))); //$NON-NLS-1$ OpenInBrowserAction action = new OpenInBrowserAction(); action.selectionChanged(null, new StructuredSelection(uri)); action.run(); } catch (URISyntaxException ex) { Activator.safeLogError(ex.getMessage(), ex); } } }); } /* Feed: Description */ createLabel(fContainer, Messages.InformationPropertyPage_DESCRIPTION, true); fDescriptionLabel = new Label(fContainer, SWT.WRAP); fDescriptionLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); ((GridData) fDescriptionLabel.getLayoutData()).widthHint = 200; /* Feed: Homepage */ createLabel(fContainer, Messages.InformationPropertyPage_HOMEPAGE, true); fHomepageLink = new Link(fContainer, SWT.NONE); fHomepageLink.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); } /* * @see org.rssowl.ui.dialogs.properties.IEntityPropertyPage#getImage() */ public ImageDescriptor getImage() { if (!fEntities.isEmpty() && fEntities.get(0) instanceof IBookMark && ((IBookMark) fEntities.get(0)).isErrorLoading()) return OwlUI.getImageDescriptor("icons/ovr16/error.gif"); //$NON-NLS-1$ return null; } private void createLabel(Composite parent, String text, boolean bold) { Label label = new Label(parent, SWT.None); label.setText(text); label.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false)); if (bold) label.setFont(OwlUI.getBold(JFaceResources.DIALOG_FONT)); } /* * @see org.rssowl.ui.dialogs.properties.IEntityPropertyPage#finish() */ public void finish() {} /* * @see org.rssowl.ui.dialogs.properties.IEntityPropertyPage#performOk(java.util.Set) */ public boolean performOk(Set<IEntity> entitiesToSave) { return true; } /* * @see org.rssowl.ui.dialogs.properties.IEntityPropertyPage#setFocus() */ public void setFocus() { if (!fInfoComputed) { fInfoComputed = true; /* Load from Background */ JobRunner.runUIUpdater(new UIBackgroundJob(fContainer) { private String description; private URI homepage; private int totalCount; private int newCount; private int unreadCount; private int updatedCount; @Override protected void runInBackground(IProgressMonitor monitor) { IEntity entity = fEntities.get(0); /* Resolve Bookmark Values */ if (entity instanceof IBookMark) { IFeed feed = ((IBookMark) entity).getFeedLinkReference().resolve(); if (feed != null) { description = StringUtils.stripTags(feed.getDescription(), true); homepage = feed.getHomepage(); /* News Counts */ List<INews> news = feed.getVisibleNews(); totalCount = news.size(); for (INews newsitem : news) { switch (newsitem.getState()) { case NEW: newCount++; break; case UNREAD: unreadCount++; break; case UPDATED: updatedCount++; break; } } } } /* Resolve news counts from news mark */ else if (entity instanceof INewsMark) { INewsMark newsmark = (INewsMark) entity; totalCount = newsmark.getNewsCount(INews.State.getVisible()); newCount = newsmark.getNewsCount(EnumSet.of(INews.State.NEW)); unreadCount = newsmark.getNewsCount(EnumSet.of(INews.State.UNREAD)); updatedCount = newsmark.getNewsCount(EnumSet.of(INews.State.UPDATED)); } /* Resolve news counts from folder */ else if (entity instanceof IFolder) { IFolder folder = (IFolder) entity; FolderNewsMark resolver = new FolderNewsMark(folder); NewsContainer newsContainer = resolver.resolveNewsContainer(monitor); totalCount = newsContainer.getNewsCount(INews.State.getVisible()); newCount = newsContainer.getNewsCount(EnumSet.of(INews.State.NEW)); unreadCount = newsContainer.getNewsCount(EnumSet.of(INews.State.UNREAD)); updatedCount = newsContainer.getNewsCount(EnumSet.of(INews.State.UPDATED)); } } @Override protected void runInUI(IProgressMonitor monitor) { /* Description (Bookmarks only) */ if (fEntities.get(0) instanceof IBookMark) fDescriptionLabel.setText(StringUtils.isSet(description) ? description : Messages.InformationPropertyPage_NONE); /* Homepage (Bookmarks only) */ if (fEntities.get(0) instanceof IBookMark) { fHomepageLink.setText(homepage != null ? "<a>" + homepage.toString() + "</a>" : Messages.InformationPropertyPage_NONE); //$NON-NLS-1$ //$NON-NLS-2$ if (homepage != null) { fHomepageLink.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { OpenInBrowserAction action = new OpenInBrowserAction(); action.selectionChanged(null, new StructuredSelection(homepage)); action.run(); } }); } } /* News Count */ if (newCount != 0 && unreadCount != 0 && updatedCount != 0) createLabel(fContainer, NLS.bind(Messages.InformationPropertyPage_N_NEW_UNREAD_UPDATED, new Object[] { totalCount, newCount, unreadCount, updatedCount }), false); else if (newCount != 0 && unreadCount != 0) createLabel(fContainer, NLS.bind(Messages.InformationPropertyPage_N_NEW_UNREAD, new Object[] { totalCount, newCount, unreadCount }), false); else if (unreadCount != 0 && updatedCount != 0) createLabel(fContainer, NLS.bind(Messages.InformationPropertyPage_N_UNREAD_UPDATED, new Object[] { totalCount, unreadCount, updatedCount }), false); else if (newCount != 0 && updatedCount != 0) createLabel(fContainer, NLS.bind(Messages.InformationPropertyPage_N_NEW_UPDATED, new Object[] { totalCount, newCount, updatedCount }), false); else if (newCount != 0) createLabel(fContainer, NLS.bind(Messages.InformationPropertyPage_N_NEW, new Object[] { totalCount, newCount }), false); else if (unreadCount != 0) createLabel(fContainer, NLS.bind(Messages.InformationPropertyPage_N_UNREAD, new Object[] { totalCount, unreadCount }), false); else if (updatedCount != 0) createLabel(fContainer, NLS.bind(Messages.InformationPropertyPage_N_UPDATED, new Object[] { totalCount, updatedCount }), false); else createLabel(fContainer, String.valueOf(totalCount), false); /* Update Layout */ fContainer.layout(true, true); fSite.contentsChanged(); } }); } } }