Package org.rssowl.ui.internal.editors.feed

Source Code of org.rssowl.ui.internal.editors.feed.NewsTableControl

/*   **********************************************************************  **
**   Copyright notice                                                       **
**                                                                          **
**   (c) 2005-2006 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.editors.feed;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IElementComparer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.OwnerDrawLabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.rssowl.core.Owl;
import org.rssowl.core.internal.persist.pref.DefaultPreferences;
import org.rssowl.core.persist.IBookMark;
import org.rssowl.core.persist.IEntity;
import org.rssowl.core.persist.ILabel;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.ISearchMark;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.persist.pref.IPreferenceScope;
import org.rssowl.core.persist.reference.ModelReference;
import org.rssowl.core.persist.reference.SearchMarkReference;
import org.rssowl.core.util.ITask;
import org.rssowl.core.util.TaskAdapter;
import org.rssowl.ui.internal.ApplicationWorkbenchWindowAdvisor;
import org.rssowl.ui.internal.CColumnLayoutData;
import org.rssowl.ui.internal.CTree;
import org.rssowl.ui.internal.EntityGroup;
import org.rssowl.ui.internal.OwlUI;
import org.rssowl.ui.internal.StatusLineUpdater;
import org.rssowl.ui.internal.actions.LabelAction;
import org.rssowl.ui.internal.actions.MakeTypesStickyAction;
import org.rssowl.ui.internal.actions.OpenInBrowserAction;
import org.rssowl.ui.internal.actions.OpenNewsAction;
import org.rssowl.ui.internal.util.JobRunner;
import org.rssowl.ui.internal.util.JobTracker;
import org.rssowl.ui.internal.util.ModelUtils;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* Part of the FeedView to display News in a TableViewer.
*
* @author bpasero
*/
public class NewsTableControl implements IFeedViewPart {

  /* ID to associate a Column with its ID */
  private static final String COL_ID = "org.rssowl.ui.internal.editors.feed.ColumnIdentifier";

  /* Workaround for unknown Dateo-Col Width */
  private static int DATE_COL_WIDTH = -1;

  /* TODO Developer's flag to enable / disable COD */
  static final boolean USE_CUSTOM_OWNER_DRAWN = true;

  /* Indices of Columns in the Tree-Viewer */
  static final int COL_TITLE = 0;
  static final int COL_PUBDATE = 1;
  static final int COL_AUTHOR = 2;
  static final int COL_CATEGORY = 3;
  static final int COL_STICKY = 4;

  /** Supported Columns of the Viewer */
  public enum Columns {

    /** Title of the News */
    TITLE(true, true),

    /** Date of the News */
    DATE(false, true),

    /** Author of the News */
    AUTHOR(true, true),

    /** Category of the News */
    CATEGORY(true, true),

    /** Sticky-State of the News */
    STICKY(false, false),

    /** Score of a News */
    SCORE(false, false);

    boolean fPrefersAcending;
    boolean fShowSortIndicator;

    Columns(boolean prefersAscending, boolean showSortIndicator) {
      fPrefersAcending = prefersAscending;
      fShowSortIndicator = showSortIndicator;
    }

    /**
     * @return Returns <code>TRUE</code> if this Column prefers to be sorted
     * ascending and <code>FALSE</code> otherwise.
     */
    public boolean prefersAscending() {
      return fPrefersAcending;
    }

    /**
     * @return Returns <code>TRUE</code> if this Column prefers showing a
     * sort-indicator and <code>FALSE</code> otherwise.
     */
    public boolean showSortIndicator() {
      return fShowSortIndicator;
    }
  }

  /* Tracker to Mark selected news as Read */
  private class MarkReadTracker extends JobTracker {
    MarkReadTracker(int delay, boolean showProgress) {
      super(delay, showProgress, ITask.Priority.INTERACTIVE);
    }

    @Override
    protected int getDelay() {
      return fPreferences.getInteger(DefaultPreferences.MARK_READ_IN_MILLIS);
    }
  }

  private IEditorSite fEditorSite;
  private JobTracker fNewsStateTracker;
  private NewsTableViewer fViewer;
  private ISelectionChangedListener fSelectionChangeListener;
  private CTree fCustomTree;
  private LocalResourceManager fResources;
  private NewsComparator fNewsSorter;
  private Cursor fHandCursor;
  private boolean fShowsHandCursor;
  private AtomicBoolean fBlockNewsStateTracker = new AtomicBoolean(false);

  /* Settings */
  private IPreferenceScope fPreferences;
  private Columns fInitialSortColumn = Columns.DATE;
  private boolean fInitialAscending = false;

  /*
   * @see org.rssowl.ui.internal.editors.feed.IFeedViewPart#init(org.eclipse.ui.IEditorSite)
   */
  public void init(IEditorSite editorSite) {
    fEditorSite = editorSite;
    fPreferences = Owl.getPreferenceService().getGlobalScope();
    fNewsStateTracker = new MarkReadTracker(fPreferences.getInteger(DefaultPreferences.MARK_READ_IN_MILLIS), false);
    fResources = new LocalResourceManager(JFaceResources.getResources());
  }

  /*
   * @see org.rssowl.ui.internal.editors.feed.IFeedViewPart#onInputChanged(org.rssowl.ui.internal.editors.feed.FeedViewInput)
   */
  public void onInputChanged(FeedViewInput input) {
  /* Ignore */
  }

  /*
   * @see org.rssowl.ui.internal.editors.feed.IFeedViewPart#createViewer(org.eclipse.swt.widgets.Composite)
   */
  public NewsTableViewer createViewer(Composite parent) {
    int style = SWT.MULTI | SWT.FULL_SELECTION;

    fCustomTree = new CTree(parent, style);
    fCustomTree.getControl().setHeaderVisible(true);

    fViewer = new NewsTableViewer(fCustomTree.getControl());
    fViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    fViewer.setUseHashlookup(true);
    fViewer.getControl().setData(ApplicationWorkbenchWindowAdvisor.FOCUSLESS_SCROLL_HOOK, new Object());
    fViewer.getControl().setFont(OwlUI.getThemeFont(OwlUI.HEADLINES_FONT_ID, SWT.NORMAL));

    /* TODO This is a Workaround until we remember expanded Groups */
    fViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);

    fHandCursor = parent.getDisplay().getSystemCursor(SWT.CURSOR_HAND);

    return fViewer;
  }

  /*
   * @see org.rssowl.ui.internal.editors.feed.IFeedViewPart#getViewer()
   */
  public NewsTableViewer getViewer() {
    return fViewer;
  }

  /*
   * @see org.rssowl.ui.internal.editors.feed.IFeedViewPart#initViewer(org.eclipse.jface.viewers.IStructuredContentProvider,
   * org.eclipse.jface.viewers.ViewerFilter)
   */
  public void initViewer(IStructuredContentProvider contentProvider, ViewerFilter filter) {

    /* Headline Column */
    TreeViewerColumn col = new TreeViewerColumn(fViewer, SWT.LEFT);
    fCustomTree.manageColumn(col.getColumn(), new CColumnLayoutData(CColumnLayoutData.Size.FILL, 60), "Title", null, true, true);
    col.getColumn().setData(COL_ID, Columns.TITLE);
    if (fInitialSortColumn == Columns.TITLE) {
      fCustomTree.getControl().setSortColumn(col.getColumn());
      fCustomTree.getControl().setSortDirection(fInitialAscending ? SWT.UP : SWT.DOWN);
    }

    /* Date Column */
    int width = getInitialDateColumnWidth();
    col = new TreeViewerColumn(fViewer, SWT.LEFT);
    fCustomTree.manageColumn(col.getColumn(), new CColumnLayoutData(CColumnLayoutData.Size.FIXED, width), "Date", null, true, true);
    col.getColumn().setData(COL_ID, Columns.DATE);
    if (fInitialSortColumn == Columns.DATE) {
      fCustomTree.getControl().setSortColumn(col.getColumn());
      fCustomTree.getControl().setSortDirection(fInitialAscending ? SWT.UP : SWT.DOWN);
    }

    /* Author Column */
    col = new TreeViewerColumn(fViewer, SWT.LEFT);
    fCustomTree.manageColumn(col.getColumn(), new CColumnLayoutData(CColumnLayoutData.Size.FILL, 20), "Author", null, true, true);
    col.getColumn().setData(COL_ID, Columns.AUTHOR);
    if (fInitialSortColumn == Columns.AUTHOR) {
      fCustomTree.getControl().setSortColumn(col.getColumn());
      fCustomTree.getControl().setSortDirection(fInitialAscending ? SWT.UP : SWT.DOWN);
    }

    /* Category Column */
    col = new TreeViewerColumn(fViewer, SWT.LEFT);
    fCustomTree.manageColumn(col.getColumn(), new CColumnLayoutData(CColumnLayoutData.Size.FILL, 20), "Category", null, true, true);
    col.getColumn().setData(COL_ID, Columns.CATEGORY);
    if (fInitialSortColumn == Columns.CATEGORY) {
      fCustomTree.getControl().setSortColumn(col.getColumn());
      fCustomTree.getControl().setSortDirection(fInitialAscending ? SWT.UP : SWT.DOWN);
    }

    /* Sticky Column */
    col = new TreeViewerColumn(fViewer, SWT.LEFT);
    fCustomTree.manageColumn(col.getColumn(), new CColumnLayoutData(CColumnLayoutData.Size.FIXED, 18), null, null, true, false);
    col.getColumn().setData(COL_ID, Columns.STICKY);
    col.getColumn().setToolTipText("Sticky State");

    /* Apply ContentProvider */
    fViewer.setContentProvider(contentProvider);

    /* Create LabelProvider (Custom Owner Drawn enabled!) */
    if (USE_CUSTOM_OWNER_DRAWN)
      OwnerDrawLabelProvider.setUpOwnerDraw(fViewer);
    fViewer.setLabelProvider(new NewsTableLabelProvider());

    /* Create Sorter */
    fNewsSorter = new NewsComparator();
    fNewsSorter.setAscending(fInitialAscending);
    fNewsSorter.setSortBy(fInitialSortColumn);
    fViewer.setComparator(fNewsSorter);

    /* Set Comparer */
    fViewer.setComparer(getComparer());

    /* Add Filter */
    fViewer.addFilter(filter);

    /* Hook Contextual Menu */
    hookContextualMenu();

    /* Register Listeners */
    registerListeners();

    /* Propagate Selection Events */
    fEditorSite.setSelectionProvider(fViewer);
  }

  private int getInitialDateColumnWidth() {

    /* Check if Cached already */
    if (DATE_COL_WIDTH > 0)
      return DATE_COL_WIDTH;

    /* Calculate and Cache */
    DateFormat dF = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
    Calendar cal = Calendar.getInstance();
    cal.set(2006, Calendar.DECEMBER, 12, 12, 12, 12);
    String sampleDate = dF.format(cal.getTime());

    DATE_COL_WIDTH = OwlUI.getTextSize(fCustomTree.getControl(), OwlUI.getBold(JFaceResources.DEFAULT_FONT), sampleDate).x;
    DATE_COL_WIDTH += 30; // Bounds of TableColumn requires more space

    return DATE_COL_WIDTH;
  }

  private void registerListeners() {

    /* Open selected News Links in Browser on doubleclick */
    fViewer.addDoubleClickListener(new IDoubleClickListener() {
      public void doubleClick(DoubleClickEvent event) {
        onMouseDoubleClick(event);
      }
    });

    /* Hook into Statusline */
    fViewer.addSelectionChangedListener(new StatusLineUpdater(fEditorSite.getActionBars().getStatusLineManager()));

    /* Track Selections in the Viewer */
    fSelectionChangeListener = new ISelectionChangedListener() {
      public void selectionChanged(SelectionChangedEvent event) {
        onSelectionChanged(event);
      }
    };
    fViewer.addPostSelectionChangedListener(fSelectionChangeListener);

    /* Perform Action on Mouse-Down */
    fCustomTree.getControl().addListener(SWT.MouseDown, new Listener() {
      public void handleEvent(Event event) {
        onMouseDown(event);
      }
    });

    /* Update Cursor on Mouse-Move */
    fCustomTree.getControl().addListener(SWT.MouseMove, new Listener() {
      public void handleEvent(Event event) {
        onMouseMove(event);
      }
    });

    /* Enable Sorting adding listeners to Columns */
    TreeColumn[] columns = fCustomTree.getControl().getColumns();
    for (final TreeColumn column : columns) {
      column.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
          Columns oldSortBy = fNewsSorter.getSortBy();
          Columns newSortBy = (Columns) column.getData(COL_ID);
          boolean defaultAscending = newSortBy.prefersAscending();
          boolean ascending = (oldSortBy != newSortBy) ? defaultAscending : !fNewsSorter.isAscending();

          fNewsSorter.setSortBy(newSortBy);
          fNewsSorter.setAscending(ascending);

          /* Indicate Sort-Column in UI for Columns that have a certain width */
          if (newSortBy.showSortIndicator()) {
            fCustomTree.getControl().setSortColumn(column);
            fCustomTree.getControl().setSortDirection(ascending ? SWT.UP : SWT.DOWN);
          } else {
            fCustomTree.getControl().setSortColumn(null);
          }

          fViewer.refresh(false);
        }
      });
    }
  }

  private void onMouseDoubleClick(DoubleClickEvent event) {
    IStructuredSelection selection = (IStructuredSelection) event.getSelection();
    if (selection.isEmpty())
      return;

    Object firstElem = selection.getFirstElement();

    /* Open News */
    if (firstElem instanceof INews)
      new OpenInBrowserAction(selection).run();

    /* Toggle expanded State of Group */
    else if (firstElem instanceof EntityGroup)
      fViewer.setExpandedState(firstElem, !fViewer.getExpandedState(firstElem));
  }

  private void onSelectionChanged(SelectionChangedEvent event) {

    /* Check Flag and only consider Structured Selections */
    if (fBlockNewsStateTracker.get() || !(event.getSelection() instanceof IStructuredSelection))
      return;

    /* Check if settings disable the tracker */
    if (!fPreferences.getBoolean(DefaultPreferences.MARK_READ_STATE))
      return;

    /* Retrieve all NewsReferences of the Selection */
    IStructuredSelection selection = (IStructuredSelection) event.getSelection();

    /* Only responsible for single Selection of a News */
    if (selection.size() != 1 || !(selection.getFirstElement() instanceof INews)) {
      fNewsStateTracker.cancel();
      return;
    }

    /* Trigger the Tracker if news is not read already */
    final INews selectedNews = (INews) selection.getFirstElement();
    if (selectedNews.getState() != INews.State.READ && selectedNews.isVisible()) {
      fNewsStateTracker.run(new TaskAdapter() {
        public IStatus run(IProgressMonitor monitor) {
          setNewsState(Arrays.asList(new INews[] { selectedNews }), INews.State.READ);
          return Status.OK_STATUS;
        }
      });
    }

    /* Cancel any possible running JobTracker */
    else if (selectedNews.getState() == INews.State.READ) {
      fNewsStateTracker.cancel();
    }
  }

  private void onMouseDown(Event event) {
    boolean disableTrackerTemporary = false;
    Point p = new Point(event.x, event.y);
    TreeItem item = fCustomTree.getControl().getItem(p);

    /* Problem - return */
    if (item == null || item.isDisposed())
      return;

    /* Don't run Tracker if other Mouse Button is used */
    if (event.button != 1)
      disableTrackerTemporary = true;

    /* Mouse-Up over Read-State-Column */
    if (event.button == 1 && item.getImageBounds(COL_TITLE).contains(p)) {
      Object data = item.getData();

      /* Toggle State between Read / Unread */
      if (data instanceof INews) {
        INews news = (INews) data;
        disableTrackerTemporary = (news.getState() == INews.State.READ);
        INews.State newState = (news.getState() == INews.State.READ) ? INews.State.UNREAD : INews.State.READ;
        setNewsState(new ArrayList<INews>(Arrays.asList(new INews[] { news })), newState);
      }
    }

    /* Mouse-Up over Sticky-State-Column */
    else if (event.button == 1 && item.getImageBounds(COL_STICKY).contains(p)) {
      Object data = item.getData();

      /* Toggle State between Sticky / Not Sticky */
      if (data instanceof INews) {
        disableTrackerTemporary = false;
        new MakeTypesStickyAction(new StructuredSelection(data)).run();
      }
    }

    /*
     * This is a workaround: Immediately after the mouse-down-event has been
     * issued, a selection-event is triggered. This event is resulting in the
     * news-state-tracker to run and mark the selected news as read again. To
     * avoid this, we disable the tracker for a short while and set it back to
     * enabled again.
     */
    if (disableTrackerTemporary)
      JobRunner.runDelayedFlagInversion(200, fBlockNewsStateTracker);
  }

  private void onMouseMove(Event event) {
    Point p = new Point(event.x, event.y);
    TreeItem item = fCustomTree.getControl().getItem(p);

    /* Problem / Group hovered - reset */
    if (item == null || item.isDisposed() || item.getData() instanceof EntityGroup) {
      if (fShowsHandCursor && !fCustomTree.getControl().isDisposed()) {
        fCustomTree.getControl().setCursor(null);
        fShowsHandCursor = false;
      }
      return;
    }

    /* Show Hand-Cursor if action can be performed */
    boolean changeToHandCursor = item.getImageBounds(COL_TITLE).contains(p) || item.getImageBounds(COL_STICKY).contains(p);
    if (!fShowsHandCursor && changeToHandCursor) {
      fCustomTree.getControl().setCursor(fHandCursor);
      fShowsHandCursor = true;
    } else if (fShowsHandCursor && !changeToHandCursor) {
      fCustomTree.getControl().setCursor(null);
      fShowsHandCursor = false;
    }
  }

  /*
   * This Comparer is used to optimize some operations on the Viewer being used.
   * When deleting Entities, the Delete-Event is providing a reference to the
   * deleted Entity, which can not be resolved anymore. This Comparer will
   * return <code>TRUE</code> for a reference compared with an Entity that has
   * the same ID and is belonging to the same Entity. At any time, it _must_ be
   * avoided to call add, update or refresh with passing in a Reference!
   */
  private IElementComparer getComparer() {
    return new IElementComparer() {
      public boolean equals(Object a, Object b) {

        /* Quickyly check this common case */
        if (a == b)
          return true;

        if (a instanceof ModelReference && b instanceof IEntity)
          return ((ModelReference) a).references((IEntity) b);

        if (b instanceof ModelReference && a instanceof IEntity)
          return ((ModelReference) b).references((IEntity) a);

        return a.equals(b);
      }

      public int hashCode(Object element) {
        return element.hashCode();
      }
    };
  }

  private void hookContextualMenu() {
    MenuManager manager = new MenuManager();
    manager.setRemoveAllWhenShown(true);
    manager.addMenuListener(new IMenuListener() {
      public void menuAboutToShow(IMenuManager manager) {
        manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
        manager.add(new Separator("open"));
        manager.add(new Separator("mark"));
        manager.add(new Separator("edit"));
        manager.add(new Separator("copy"));
        manager.add(new Separator("label"));

        IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection();

        /* Need a Selection here */
        if (selection.isEmpty())
          return;

        /* Show in Feed (only for searchmarks) */
        if (fViewer.getInput() instanceof SearchMarkReference) {
          OpenNewsAction showInFeedAction = new OpenNewsAction(selection);
          showInFeedAction.setText("Show in Feed");
          manager.appendToGroup("open", showInFeedAction);
        }

        /* Sticky */
        manager.appendToGroup("label", new MakeTypesStickyAction(selection));

        /* Label */
        MenuManager labelMenu = new MenuManager("Label");
        manager.appendToGroup("label", labelMenu);

        /* Retrieve selected Labels from Selection (including NULL!) */
        Set<ILabel> selectedLabels = ModelUtils.getLabels(selection);
        ILabel commonLabel = null;
        if (selectedLabels.size() == 1)
          commonLabel = selectedLabels.iterator().next();

        IAction labelNone = new Action("None", IAction.AS_RADIO_BUTTON) {
          @Override
          public void run() {
            new LabelAction(null, (IStructuredSelection) fViewer.getSelection()).run();
          }
        };
        labelNone.setChecked(selectedLabels.size() == 0 || (selectedLabels.size() == 1 && commonLabel == null));

        labelMenu.add(labelNone);
        labelMenu.add(new Separator());

        Collection<ILabel> labels = DynamicDAO.loadAll(ILabel.class);
        for (final ILabel label : labels) {
          IAction labelAction = new Action(label.getName(), IAction.AS_RADIO_BUTTON) {
            @Override
            public void run() {
              new LabelAction(label, (IStructuredSelection) fViewer.getSelection()).run();
            }
          };

          labelAction.setChecked(label.equals(commonLabel));
          labelMenu.add(labelAction);
        }
      }
    });

    /* Create and Register with Workbench */
    Menu menu = manager.createContextMenu(fViewer.getControl());
    fViewer.getControl().setMenu(menu);
    fEditorSite.registerContextMenu(manager, fViewer);
  }

  /*
   * @see org.rssowl.ui.internal.editors.feed.IFeedViewPart#setInput(java.lang.Object)
   */
  public void setPartInput(Object input) {
    if (input instanceof IBookMark)
      fViewer.setInput(((IBookMark) input).getFeedLinkReference());
    else if (input instanceof ISearchMark)
      fViewer.setInput(new SearchMarkReference(((ISearchMark) input).getId()));
    else
      fViewer.setInput(input);
  }

  /*
   * @see org.rssowl.ui.internal.editors.feed.IFeedViewPart#setFocus()
   */
  public void setFocus() {
    fViewer.getControl().setFocus();
  }

  /*
   * @see org.rssowl.ui.internal.editors.feed.IFeedViewPart#dispose()
   */
  public void dispose() {
    fNewsStateTracker.cancel();
    fResources.dispose();
    unregisterListeners();
  }

  void setBlockNewsStateTracker(boolean block) {
    fBlockNewsStateTracker.set(block);
  }

  private void unregisterListeners() {
    fViewer.removePostSelectionChangedListener(fSelectionChangeListener);
  }

  private void setNewsState(List<INews> news, INews.State state) {
    Owl.getPersistenceService().getDAOService().getNewsDAO().setState(news, state, true, false);
  }
}
TOP

Related Classes of org.rssowl.ui.internal.editors.feed.NewsTableControl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.