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

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

/*   **********************************************************************  **
**   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.Assert;
import org.eclipse.jface.viewers.ContentViewer;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.rssowl.core.Owl;
import org.rssowl.core.persist.IModelFactory;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.ISearchCondition;
import org.rssowl.core.persist.ISearchField;
import org.rssowl.core.persist.SearchSpecifier;
import org.rssowl.core.util.StringUtils;
import org.rssowl.core.util.URIUtils;
import org.rssowl.ui.internal.ApplicationServer;
import org.rssowl.ui.internal.CBrowser;
import org.rssowl.ui.internal.ILinkHandler;
import org.rssowl.ui.internal.dialogs.SearchNewsDialog;

import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

/**
* @author bpasero
* @author Kay Patzwald <kay_patzwald@users.sourceforge.net>
*/
public class NewsBrowserViewer extends ContentViewer implements ILinkHandler {

  /* ID for Link Handlers */
  static final String AUTHOR_HANDLER_ID = "org.rssowl.ui.search.Author";
  static final String CATEGORY_HANDLER_ID = "org.rssowl.ui.search.Category";
  static final String LABEL_HANDLER_ID = "org.rssowl.ui.search.Label";

  private Object fInput;
  private CBrowser fBrowser;
  private ApplicationServer fServer;
  private String fId;
  private boolean fBlockRefresh;
  private IModelFactory fFactory;

  /* This viewer's sorter. <code>null</code> means there is no sorter. */
  private ViewerComparator fSorter;

  /* This viewer's filters (element type: <code>ViewerFilter</code>). */
  private List<ViewerFilter> filters;

  /**
   * @param parent
   * @param style
   */
  public NewsBrowserViewer(Composite parent, int style) {
    this(new CBrowser(parent, style));
  }

  /**
   * @param browser
   */
  public NewsBrowserViewer(CBrowser browser) {
    hookControl(browser.getControl());
    fBrowser = browser;
    fId = String.valueOf(hashCode());
    fServer = ApplicationServer.getDefault();
    fServer.register(fId, this);
    fFactory = Owl.getModelFactory();

    /* Register Link Handler */
    fBrowser.addLinkHandler(AUTHOR_HANDLER_ID, this);
    fBrowser.addLinkHandler(CATEGORY_HANDLER_ID, this);
    fBrowser.addLinkHandler(LABEL_HANDLER_ID, this);
  }

  void setBlockRefresh(boolean block) {
    fBlockRefresh = block;
  }

  /*
   * @see org.rssowl.ui.internal.ILinkHandler#handle(java.lang.String,
   * java.net.URI)
   */
  public void handle(String id, URI link) {

    /* Extract Query Part */
    String query = link.getQuery();
    if (!StringUtils.isSet(query))
      return;

    /* Decode Value */
    query = URIUtils.urlDecode(query).trim();

    List<ISearchCondition> conditions = new ArrayList<ISearchCondition>(1);
    String entity = INews.class.getName();

    /* Search on Author */
    if (AUTHOR_HANDLER_ID.equals(id)) {
      StringTokenizer tokenizer = new StringTokenizer(query);
      while (tokenizer.hasMoreTokens()) {
        String token = tokenizer.nextToken();
        ISearchField field = fFactory.createSearchField(INews.AUTHOR, entity);
        ISearchCondition condition = fFactory.createSearchCondition(field, SearchSpecifier.CONTAINS, token);
        conditions.add(condition);
      }
    }

    /* Search on Category */
    else if (CATEGORY_HANDLER_ID.equals(id)) {
      ISearchField field = fFactory.createSearchField(INews.CATEGORIES, entity);
      ISearchCondition condition = fFactory.createSearchCondition(field, SearchSpecifier.IS, query);
      conditions.add(condition);
    }

    /* Search on Label */
    else if (LABEL_HANDLER_ID.equals(id)) {
      ISearchField field = fFactory.createSearchField(INews.LABEL, entity);
      ISearchCondition condition = fFactory.createSearchCondition(field, SearchSpecifier.IS, query);
      conditions.add(condition);
    }

    /* Open Dialog and Search */
    if (conditions.size() >= 1 && !fBrowser.getControl().isDisposed()) {
      boolean matchAllConditions = AUTHOR_HANDLER_ID.equals(id);
      SearchNewsDialog dialog = new SearchNewsDialog(fBrowser.getControl().getShell(), conditions, matchAllConditions, true);
      dialog.open();
    }
  }

  /*
   * @see org.eclipse.jface.viewers.ContentViewer#setContentProvider(org.eclipse.jface.viewers.IContentProvider)
   */
  @Override
  public void setContentProvider(IContentProvider contentProvider) {
    fBlockRefresh = true;
    try {
      super.setContentProvider(contentProvider);
    } finally {
      fBlockRefresh = false;
    }
  }

  /*
   * @see org.eclipse.jface.viewers.Viewer#refresh()
   */
  @Override
  public void refresh() {
    if (!fBlockRefresh)
      fBrowser.getControl().refresh();
  }

  /*
   * @see org.eclipse.jface.viewers.ContentViewer#handleDispose(org.eclipse.swt.events.DisposeEvent)
   */
  @Override
  protected void handleDispose(DisposeEvent event) {
    fServer.unregister(fId);
    super.handleDispose(event);
  }

  /*
   * @see org.eclipse.jface.viewers.ContentViewer#setInput(java.lang.Object)
   */
  @Override
  public void setInput(Object input) {
    setInput(input, false);
  }

  private void setInput(Object input, boolean force) {

    /* Ignore this Input if its already set */
    if (!force && sameInput(input))
      return;

    /* Remember Input */
    fInput = input;

    /* Stop any other Website if required */
    String url = fBrowser.getControl().getUrl();
    if (!"".equals(url)) //$NON-NLS-1$
      fBrowser.getControl().stop();

    /* Input is a URL - display it */
    if (input instanceof String) {
      fBrowser.getControl().setUrl((String) input);
      return;
    }

    /* Set URL if its not already showing and contains a display-operation */
    String inputUrl = fServer.toUrl(fId, input);
    if (fServer.isDisplayOperation(inputUrl) && !inputUrl.equals(url))
      fBrowser.setUrl(inputUrl);

    /* Hide the Browser as soon as the input is set to Null */
    if (input == null && fBrowser.getControl().getVisible())
      fBrowser.getControl().setVisible(false);
  }

  /* Checks wether the given Input is same to the existing one */
  private boolean sameInput(Object input) {
    if (fInput instanceof Object[])
      return input instanceof Object[] && Arrays.equals((Object[]) fInput, (Object[]) input);

    if (fInput != null)
      return fInput.equals(input);

    return false;
  }

  /*
   * @see org.eclipse.jface.viewers.ContentViewer#getInput()
   */
  @Override
  public Object getInput() {
    return fInput;
  }

  /**
   * Adds the given filter to this viewer, and triggers refiltering and
   * resorting of the elements.
   *
   * @param filter a viewer filter
   */
  public void addFilter(ViewerFilter filter) {
    if (filters == null)
      filters = new ArrayList<ViewerFilter>();

    filters.add(filter);
    refresh();
  }

  /**
   * Removes the given filter from this viewer, and triggers refiltering and
   * resorting of the elements if required. Has no effect if the identical
   * filter is not registered.
   *
   * @param filter a viewer filter
   */
  public void removeFilter(ViewerFilter filter) {
    Assert.isNotNull(filter);
    if (filters != null) {
      for (Iterator<ViewerFilter> i = filters.iterator(); i.hasNext();) {
        Object o = i.next();
        if (o == filter) {
          i.remove();
          refresh();
          if (filters.size() == 0)
            filters = null;

          return;
        }
      }
    }
  }

  /**
   * @param comparator
   */
  public void setComparator(ViewerComparator comparator) {
    if (fSorter != comparator) {
      fSorter = comparator;
      refresh();
    }
  }

  /*
   * @see org.eclipse.jface.viewers.Viewer#getControl()
   */
  @Override
  public Control getControl() {
    return fBrowser.getControl();
  }

  /**
   * @return The wrapped Browser (CBrowser).
   */
  public CBrowser getBrowser() {
    return fBrowser;
  }

  /*
   * @see org.eclipse.jface.viewers.Viewer#getSelection()
   */
  @Override
  public ISelection getSelection() {
    /* Not Supported */
    return null;
  }

  /*
   * @see org.eclipse.jface.viewers.Viewer#setSelection(org.eclipse.jface.viewers.ISelection,
   * boolean)
   */
  @Override
  public void setSelection(ISelection selection, boolean reveal) {
  /* Not Supported */
  }

  /**
   * Shows the intial Input in the Browser.
   */
  public void home() {
    setInput(fInput, true);
  }

  private Object[] getSortedChildren(Object parent) {
    Object[] result = getFilteredChildren(parent);
    if (fSorter != null) {

      /* be sure we're not modifying the original array from the model */
      result = result.clone();
      fSorter.sort(this, result);
    }
    return result;
  }

  private Object[] getFilteredChildren(Object parent) {
    Object[] result = getRawChildren(parent);

    /* Never filter a selected News, thereby return here */
    if (fInput instanceof INews)
      return result;

    /* Run Filters over result */
    if (filters != null) {
      for (Object filter : filters) {
        ViewerFilter f = (ViewerFilter) filter;
        result = f.filter(this, parent, result);
      }
    }
    return result;
  }

  private Object[] getRawChildren(Object parent) {
    Object[] result = null;
    if (parent != null) {
      IStructuredContentProvider cp = (IStructuredContentProvider) getContentProvider();
      if (cp != null)
        result = cp.getElements(parent);
    }
    return (result != null) ? result : new Object[0];
  }

  /**
   * @param input Can either be an Array of Feeds or News
   * @return An flattend array of Objects.
   */
  public Object[] getFlattendChildren(Object input) {

    /* Using NewsContentProvider */
    if (input != null && getContentProvider() instanceof NewsContentProvider) {
      NewsContentProvider cp = (NewsContentProvider) getContentProvider();

      /*
       * Flatten Children since Grouping is Enabled and the Parent is not
       * containing just News (so either Feed or ViewerGroups).
       */
      if (cp.isGroupingEnabled() && !isNews(input)) {
        List<Object> flatList = new ArrayList<Object>();

        /* Wrap into Object-Array */
        if (!(input instanceof Object[]))
          input = new Object[] { input };

        /* For each Group retrieve Children (sorted and filtered) */
        Object groups[] = (Object[]) input;
        for (Object group : groups) {

          /* Make sure this child has children */
          if (cp.hasChildren(group)) {
            Object sortedChilds[] = getSortedChildren(group);

            /* Only add if there are Childs */
            if (sortedChilds.length > 0) {
              flatList.add(group);
              flatList.addAll(Arrays.asList(sortedChilds));
            }
          }

          /* Otherwise just add */
          else {
            flatList.add(group);
          }
        }

        return flatList.toArray();
      }

      /* Grouping is not enabled, just return sorted Children */
      return getSortedChildren(input);
    }

    /* Structured ContentProvider */
    else if (input != null && getContentProvider() instanceof IStructuredContentProvider)
      return getSortedChildren(input);

    /* No Element to show */
    return new Object[0];
  }

  /* Returns TRUE if the Input consists only of INews */
  private boolean isNews(Object input) {
    if (input instanceof Object[]) {
      Object elements[] = (Object[]) input;
      for (Object element : elements) {
        if (!(element instanceof INews))
          return false;
      }
    } else if (!(input instanceof INews))
      return false;

    return true;
  }

  /**
   * @param parentElement
   * @param childElements
   */
  public void add(Object parentElement, Object[] childElements) {
    Assert.isNotNull(parentElement);
    assertElementsNotNull(childElements);

    refresh(); // TODO Optimize
  }

  /**
   * @param parentElement
   * @param childElement
   */
  public void add(Object parentElement, Object childElement) {
    Assert.isNotNull(parentElement);
    Assert.isNotNull(childElement);

    refresh(); // TODO Optimize
  }

  /**
   * @param elements
   * @param properties
   */
  public void update(Object[] elements, @SuppressWarnings("unused")
  String[] properties) {
    assertElementsNotNull(elements);

    /*
     * The update-event could have been sent out a lot faster than the Browser
     * having a chance to react. In this case, rather then refreshing a possible
     * blank page (or wrong page), re-set the input.
     */
    String inputUrl = fServer.toUrl(fId, fInput);
    String browserUrl = fBrowser.getControl().getUrl();
    boolean resetInput = browserUrl.length() == 0 || URIUtils.ABOUT_BLANK.equals(browserUrl);
    if (inputUrl.equals(browserUrl))
      refresh(); // TODO Optimize
    else if (fServer.isDisplayOperation(inputUrl) && resetInput)
      fBrowser.setUrl(inputUrl);
  }

  /**
   * @param element
   * @param properties
   */
  public void update(Object element, @SuppressWarnings("unused")
  String[] properties) {
    Assert.isNotNull(element);

    refresh(); // TODO Optimize
  }

  /**
   * @param objects
   */
  public void remove(Object[] objects) {
    assertElementsNotNull(objects);

    refresh(); // TODO Optimize
  }

  /**
   * @param element
   */
  public void remove(Object element) {
    Assert.isNotNull(element);

    refresh(); // TODO Optimize
  }

  private void assertElementsNotNull(Object[] elements) {
    Assert.isNotNull(elements);
    for (Object element : elements) {
      Assert.isNotNull(element);
    }
  }

  /**
   * TODO This is temporary API until Bug 627 is fixed using Lucene Token
   * Positions.
   *
   * @return Returns a List of Strings that should get highlighted per News that
   * is displayed.
   */
  protected List<String> getHighlightedWords() {
    return Collections.emptyList();
  }
}
TOP

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

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.