Package org.rssowl.ui.internal.dialogs

Source Code of org.rssowl.ui.internal.dialogs.PreviewFeedDialog

/*   **********************************************************************  **
**   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;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
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.eclipse.swt.widgets.Shell;
import org.rssowl.core.Owl;
import org.rssowl.core.connection.ConnectionException;
import org.rssowl.core.connection.IProtocolHandler;
import org.rssowl.core.interpreter.InterpreterException;
import org.rssowl.core.interpreter.ParserException;
import org.rssowl.core.persist.IBookMark;
import org.rssowl.core.persist.IFeed;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.reference.FeedLinkReference;
import org.rssowl.core.util.CoreUtils;
import org.rssowl.core.util.StringUtils;
import org.rssowl.ui.internal.Activator;
import org.rssowl.ui.internal.Application;
import org.rssowl.ui.internal.OwlUI;
import org.rssowl.ui.internal.actions.OpenInBrowserAction;
import org.rssowl.ui.internal.editors.feed.NewsBrowserLabelProvider;
import org.rssowl.ui.internal.util.CBrowser;
import org.rssowl.ui.internal.util.JobRunner;
import org.rssowl.ui.internal.util.LayoutUtils;
import org.rssowl.ui.internal.util.UIBackgroundJob;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URI;
import java.util.List;

/**
* The {@link PreviewFeedDialog} can be used to preview a {@link IBookMark}s
* contents without adding it to the list of subscriptions.
*
* @author bpasero
*/
public class PreviewFeedDialog extends Dialog {

  /* Windows only: Mark of the Web */
  private static final String IE_MOTW = "<!-- saved from url=(0014)about:internet -->"; //$NON-NLS-1$

  private static final int DIALOG_WIDTH_DLUS = 600;
  private static final int DIALOG_HEIGHT_DLUS = 400;
  private static final String DIALOG_SETTINGS_KEY = "org.rssowl.ui.internal.dialogs.PreviewFeedDialog"; //$NON-NLS-1$

  private static final int MAX_NEWS_SHOWN = 50;

  private IBookMark fBookmark;
  private FeedLinkReference fFeedReference;
  private IFeed fLoadedFeed;
  private CBrowser fBrowser;
  private boolean fFirstTimeOpen;
  private NewsBrowserLabelProvider fLabelProvider;
  private String fNewsFontFamily;
  private String fNormalFontCSS;
  private Link fStatusLabel;

  /**
   * @param parentShell
   * @param bookmark
   */
  public PreviewFeedDialog(Shell parentShell, IBookMark bookmark) {
    this(parentShell, bookmark, null, null);
  }

  /**
   * @param parentShell
   * @param bookmark
   * @param feedReference
   */
  public PreviewFeedDialog(Shell parentShell, IBookMark bookmark, FeedLinkReference feedReference) {
    this(parentShell, bookmark, null, feedReference);
  }

  /**
   * @param parentShell
   * @param bookmark
   * @param feed
   */
  public PreviewFeedDialog(Shell parentShell, IBookMark bookmark, IFeed feed) {
    this(parentShell, bookmark, feed, null);
  }

  PreviewFeedDialog(Shell parentShell, IBookMark bookmark, IFeed feed, FeedLinkReference feedReference) {
    super(parentShell);
    fBookmark = bookmark;
    fLoadedFeed = feed;
    fFeedReference = feedReference;
    fFirstTimeOpen = (Activator.getDefault().getDialogSettings().getSection(DIALOG_SETTINGS_KEY) == null);
    createFonts();
  }

  /* Init the Theme Font (from UI Thread) */
  private void createFonts() {
    int fontHeight = 10;
    Font newsFont = OwlUI.getThemeFont(OwlUI.NEWS_TEXT_FONT_ID, SWT.NORMAL);
    FontData[] fontData = newsFont.getFontData();
    if (fontData.length > 0) {
      fNewsFontFamily = fontData[0].getName();
      fontHeight = fontData[0].getHeight();
    }

    int normal = fontHeight;
    String fontUnit = "pt"; //$NON-NLS-1$
    fNormalFontCSS = "font-size: " + normal + fontUnit + ";"; //$NON-NLS-1$ //$NON-NLS-2$
  }

  /*
   * @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
   */
  @Override
  protected Control createDialogArea(Composite parent) {

    /* Composite to hold all components */
    Composite composite = new Composite(parent, SWT.NONE);
    composite.setLayout(LayoutUtils.createGridLayout(1, 0, 0));
    composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

    /* Browser to preview News */
    fBrowser = new CBrowser(composite, SWT.NONE);
    fBrowser.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    fBrowser.setScriptDisabled(true);
    fBrowser.getControl().addKeyListener(new KeyAdapter() {
      @Override
      public void keyPressed(KeyEvent e) {
        if (e.character == SWT.ESC)
          close();
      }
    });

    /* Label Provider to produce HTML per News */
    fLabelProvider = new NewsBrowserLabelProvider(fBrowser);

    /* Load and Display the Feed */
    loadFeed();

    /* Separator */
    new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));

    applyDialogFont(composite);

    return composite;
  }

  private void loadFeed() {

    /* Show Info that Feed is loading */
    if (fLoadedFeed == null || fLoadedFeed.getVisibleNews().isEmpty()) {
      if (StringUtils.isSet(fBookmark.getName()))
        showMessage(NLS.bind(Messages.PreviewFeedDialog_LOAD_FEED_N, fBookmark.getName()), false, true);
      else
        showMessage(Messages.PreviewFeedDialog_LOAD_FEED, false, true);
    }

    /* Load Feed in Background */
    JobRunner.runUIUpdater(new UIBackgroundJob(fBrowser.getControl()) {
      private IFeed feed;
      private Exception error;

      @Override
      protected void runInBackground(IProgressMonitor monitor) {

        /* First Check if a Feed was already provided */
        if (fLoadedFeed != null && !fLoadedFeed.getVisibleNews().isEmpty()) {
          feed = fLoadedFeed;
          return;
        }

        /* Otherwise Load Feed */
        try {

          /* Resolve Feed if existing */
          if (fFeedReference != null)
            feed = fFeedReference.resolve();

          /* Create Temporary Feed */
          if (feed == null || feed.getVisibleNews().isEmpty()) {
            feed = Owl.getModelFactory().createFeed(null, fBookmark.getFeedLinkReference().getLink());

            /* Return if dialog closed */
            if (monitor.isCanceled() || getShell().isDisposed() || fBrowser.getControl().isDisposed())
              return;

            /* Retrieve Stream */
            IProtocolHandler handler = Owl.getConnectionService().getHandler(feed.getLink());
            InputStream inS = handler.openStream(feed.getLink(), monitor, null);

            /* Return if dialog closed */
            if (monitor.isCanceled() || getShell().isDisposed() || fBrowser.getControl().isDisposed())
              return;

            /* Interpret Feed */
            Owl.getInterpreter().interpret(inS, feed, null);
          }
        } catch (ConnectionException e) {
          error = e;
          Activator.safeLogError(e.getMessage(), e);
        } catch (ParserException e) {
          error = e;
          Activator.safeLogError(e.getMessage(), e);
        } catch (InterpreterException e) {
          error = e;
          Activator.safeLogError(e.getMessage(), e);
        }
      }

      @Override
      protected void runInUI(IProgressMonitor monitor) {
        if (feed != null && error == null)
          showFeed(feed);
        else if (error != null) {
          String errorMessage = CoreUtils.toMessage(error);
          if (StringUtils.isSet(errorMessage))
            showMessage(NLS.bind(Messages.PreviewFeedDialog_UNABLE_LOAD_FEED, errorMessage), true, false);
        }
      }
    });
  }

  private void showMessage(String msg, boolean isError, boolean showProgress) {
    if (fBrowser.getControl().isDisposed())
      return;

    StringBuilder html = new StringBuilder();
    html.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"); //$NON-NLS-1$
    html.append("<html>\n"); //$NON-NLS-1$
    html.append("<body style=\"overflow: auto; font-family: ").append(fNewsFontFamily).append(",Verdanna,sans-serif; ").append(fNormalFontCSS).append("\">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

    if (showProgress)
      html.append("<img src=\"" + OwlUI.getImageUri("/icons/obj16/progress.gif", "progress.gif") + "\" />"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$

    if (isError)
      html.append("<span style=\"color: darkred;\">"); //$NON-NLS-1$
    else if (showProgress)
      html.append("<span style=\"padding-left:3px; vertical-align:top;\">"); //$NON-NLS-1$

    html.append(msg);

    if (isError || showProgress)
      html.append("</span>"); //$NON-NLS-1$

    html.append("</body>\n"); //$NON-NLS-1$
    html.append("</html>\n"); //$NON-NLS-1$

    fBrowser.getControl().setText(html.toString());
  }

  private void showFeed(final IFeed feed) {
    if (feed != null && !fBrowser.getControl().isDisposed()) {
      List<INews> news = feed.getNewsByStates(INews.State.getVisible());
      int newsCount= news.size();
      if (news.size() > MAX_NEWS_SHOWN)
        news = news.subList(0, MAX_NEWS_SHOWN);

      /* Start HTML */
      StringBuilder html = new StringBuilder();
      html.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"); //$NON-NLS-1$

      /* Windows only: Mark of the Web */
      if (Application.IS_WINDOWS) {
        html.append(IE_MOTW);
        html.append("\n"); //$NON-NLS-1$
      }

      /* Head */
      html.append("<html>\n  <head>\n"); //$NON-NLS-1$

      /* Append Base URI if available */
      URI base = (feed.getBase() != null) ? feed.getBase() : feed.getLink();
      if (base != null) {
        html.append("  <base href=\""); //$NON-NLS-1$
        html.append(base);
        html.append("\">"); //$NON-NLS-1$
      }

      /* Meta */
      html.append("\n  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"); //$NON-NLS-1$

      /* CSS */
      try {
        StringWriter writer = new StringWriter();
        fLabelProvider.writeCSS(writer, false);
        html.append(writer.toString());
      } catch (IOException e) {
        /* Will Never Happen */
      }

      /* Open Body */
      html.append("  </head>\n  <body id=\"owlbody\">\n"); //$NON-NLS-1$

      /* Title */
      if (StringUtils.isSet(fBookmark.getName()))
        html.append("<div class=\"group\">").append(fBookmark.getName()).append("</div>"); //$NON-NLS-1$ //$NON-NLS-2$

      /* Write News */
      for (INews item : news) {
        html.append(fLabelProvider.getText(item, false));
      }

      /* End HTML */
      html.append("\n  </body>\n</html>"); //$NON-NLS-1$

      /* Apply to Browser */
      fBrowser.getControl().setText(html.toString());

      /* Also Update Status */
      if (StringUtils.isSet(fBookmark.getName())) {
        StringBuilder str = new StringBuilder();
        if (feed.getHomepage() != null) {
          str.append(NLS.bind(Messages.PreviewFeedDialog_FOUND_N_NEWS_HOMEPAGE, newsCount, fBookmark.getName()));
          fStatusLabel.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
              new OpenInBrowserAction(new StructuredSelection(feed.getHomepage())).run();
            }
          });
        } else
          str.append(NLS.bind(Messages.PreviewFeedDialog_FOUND_N_NEWS, newsCount, fBookmark.getName()));

        fStatusLabel.setText(str.toString());
      }
    }
  }

  /*
   * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
   */
  @Override
  protected void configureShell(Shell shell) {
    super.configureShell(shell);

    if (StringUtils.isSet(fBookmark.getName()))
      shell.setText(NLS.bind(Messages.PreviewFeedDialog_PREVIEW_OF, fBookmark.getName()));
    else
      shell.setText(Messages.PreviewFeedDialog_PREVIEW);
  }

  /*
   * @see org.eclipse.jface.window.Window#getShellStyle()
   */
  @Override
  protected int getShellStyle() {
    int style = SWT.TITLE | SWT.BORDER | SWT.RESIZE | SWT.MIN | SWT.MAX | SWT.CLOSE | getDefaultOrientation();

    return style;
  }

  /*
   * @see org.eclipse.jface.dialogs.TrayDialog#createButtonBar(org.eclipse.swt.widgets.Composite)
   */
  @Override
  protected Control createButtonBar(Composite parent) {
    GridLayout layout = new GridLayout(1, false);
    layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
    layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
    layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
    layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);

    Composite buttonBar = new Composite(parent, SWT.NONE);
    buttonBar.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
    buttonBar.setLayout(layout);

    /* Status Label */
    fStatusLabel = new Link(buttonBar, SWT.NONE);
    applyDialogFont(fStatusLabel);
    fStatusLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
    if (StringUtils.isSet(fBookmark.getName()))
      fStatusLabel.setText(fBookmark.getName());

    /* Close */
    Button closeButton = createButton(buttonBar, IDialogConstants.CLOSE_ID, IDialogConstants.CLOSE_LABEL, false);
    closeButton.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        close();
      }
    });

    return buttonBar;
  }

  /*
   * @see org.eclipse.jface.dialogs.Dialog#getDialogBoundsSettings()
   */
  @Override
  protected IDialogSettings getDialogBoundsSettings() {
    IDialogSettings settings = Activator.getDefault().getDialogSettings();
    IDialogSettings section = settings.getSection(DIALOG_SETTINGS_KEY);
    if (section != null)
      return section;

    return settings.addNewSection(DIALOG_SETTINGS_KEY);
  }

  /*
   * @see org.eclipse.jface.dialogs.Dialog#getDialogBoundsStrategy()
   */
  @Override
  protected int getDialogBoundsStrategy() {
    return Dialog.DIALOG_PERSISTLOCATION | Dialog.DIALOG_PERSISTSIZE;
  }

  /*
   * @see org.eclipse.jface.dialogs.Dialog#initializeBounds()
   */
  @Override
  protected void initializeBounds() {
    super.initializeBounds();

    Shell shell = getShell();

    /* Minimum Size */
    int minWidth = convertHorizontalDLUsToPixels(DIALOG_WIDTH_DLUS);
    int minHeight = convertHorizontalDLUsToPixels(DIALOG_HEIGHT_DLUS);

    /* Required Size */
    Point requiredSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT);

    /* Set Size */
    shell.setSize(Math.max(minWidth, requiredSize.x), Math.max(minHeight, requiredSize.y));

    /* Set Location */
    if (fFirstTimeOpen)
      LayoutUtils.positionShell(shell);
  }
}
TOP

Related Classes of org.rssowl.ui.internal.dialogs.PreviewFeedDialog

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.