Package com.salas.bb.dialogs

Source Code of com.salas.bb.dialogs.DirectFeedPropertiesDialog

// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2006 by R. Pito Salas
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software Foundation;
// either version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program;
// if not, write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// Contact: R. Pito Salas
// mailto:pitosalas@users.sourceforge.net
// More information: about BlogBridge
// http://www.blogbridge.com
// http://sourceforge.net/projects/blogbridge
//
// $Id: DirectFeedPropertiesDialog.java,v 1.40 2008/03/05 16:34:17 spyromus Exp $
//

package com.salas.bb.dialogs;

import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.factories.ButtonBarFactory;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.uif.AbstractDialog;
import com.jgoodies.uif.util.Resizer;
import com.salas.bb.core.FeedFormatter;
import com.salas.bb.core.GlobalController;
import com.salas.bb.core.GlobalModel;
import com.salas.bb.core.ScoresCalculator;
import com.salas.bb.domain.DirectFeed;
import com.salas.bb.domain.FeedHandlingType;
import com.salas.bb.domain.prefs.StarzPreferences;
import com.salas.bb.utils.BrowserLauncher;
import com.salas.bb.utils.Constants;
import com.salas.bb.utils.DateUtils;
import com.salas.bb.utils.StringUtils;
import com.salas.bb.utils.i18n.Strings;
import com.salas.bb.utils.uif.BBFormBuilder;
import com.salas.bb.utils.uif.ComponentsFactory;
import com.salas.bb.utils.uif.HeaderPanelExt;
import com.salas.bb.utils.uif.LinkLabel;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Displays properties of channel.
*/
public class DirectFeedPropertiesDialog extends AbstractDialog
{
    private static final Logger LOG = Logger.getLogger(DirectFeedPropertiesDialog.class.getName());

    private static final Pattern PAT_EMAIL = Pattern.compile(
        "(^|[\\s\\[\\(\\{\\<])([a-zA-Z]\\w*(([_-]+|\\.)\\w+)*@[\\w-_]{2,}(\\.[\\w-_]{2,})+)($|[\\s\\]\\)\\}\\>])");

    private static final int MAX_HEADER_TITLE_LENGTH = 40;

    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#0.00");

    private DirectFeed          feed;

    private JTextField          tfXmlUrl;
    private JTextField          tfTitle;
    private JTextField          tfAuthor;
    private JTextArea           taDescription;
    private JTextField          tfPurgeLimit;

    private JLabel              lbFinalScore;
    private int                 blogStarzScore;
    private int                 rating;

    private String              initialTitle;
    private String              initialAuthor;
    private String              initialDescription;
    private int                 initialPurgeLimit;
    private long                initialUpdatePeriod;

    private JButton                     btnCancel;
    private LinkLabel                   tfSiteUrl;
    private JButton                     btnSendEmail;
    private DisplayPropertiesTabPanel   displayTab;
    private FeedUpdatePeriodPanel       pnlFeedUpdatePeriod;
    private FeedAutoSavePanel           pnlFeedAutoSave;
    private JComboBox                   cbHandlingType;

    /**
     * Creates new properties dialog.
     *
     * @param owner owning frame for this Dialog.
     * @param aFeed feed for which we are showing properties.
     */
    public DirectFeedPropertiesDialog(Frame owner, DirectFeed aFeed)
    {
        super(owner, Strings.message("show.feed.properties.dialog.title.directfeed"));
        setResizable();

        feed = aFeed;
    }

    /**
     * Builds a pretty XP-style white header.
     *
     * @return header object.
     */
    protected JComponent buildHeader()
    {
        String title = feed.getTitle();
        if (title != null && title.length() > MAX_HEADER_TITLE_LENGTH)
            title = title.substring(0, MAX_HEADER_TITLE_LENGTH) + ("\u2026");

        return new HeaderPanelExt(
            Strings.message("show.feed.properties.dialog.title.directfeed"),
            MessageFormat.format(Strings.message("show.feed.properties.dialog.header.direct"), title));
    }

    /**
     * Returns the content of the dialog.
     *
     * @return contents.
     */
    protected JComponent buildContent()
    {
        JPanel content = new JPanel(new BorderLayout());

        content.add(buildBody(), BorderLayout.CENTER);
        content.add(buildButtonBar(), BorderLayout.SOUTH);

        return content;
    }

    /**
     * Builds buttons bar.
     *
     * @return bar.
     */
    private Component buildButtonBar()
    {
        JButton btnOk = createOKButton(true);
        btnCancel = createCancelButton();

        JPanel buttonPanel = ButtonBarFactory.buildOKCancelBar(btnOk, btnCancel);
        buttonPanel.setBorder(Borders.BUTTON_BAR_GAP_BORDER);

        return buttonPanel;
    }

    /**
     * Creates custom revert button.
     *
     * @return button.
     */
    private JButton createRevertButton()
    {
        JButton btnRevert = ComponentsFactory.createButton(
            Strings.message("show.feed.properties.revert.to.default"));

        btnRevert.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                tfTitle.setText(feed.getBaseTitle());
                tfAuthor.setText(feed.getBaseAuthor());
                taDescription.setText(feed.getBaseDescription());
            }
        });

        return btnRevert;
    }

    @Override
    public void setVisible(boolean b)
    {
        // Request focus for the title
        tfTitle.requestFocusInWindow();

        super.setVisible(b);
    }

    /**
     * Applies changes if some.
     */
    public void doApply()
    {
        String msg = pnlFeedAutoSave == null ? null : pnlFeedAutoSave.validateData();
        if (msg != null)
        {
            JOptionPane.showMessageDialog(this, msg, getTitle(), JOptionPane.ERROR_MESSAGE);
            return;
        }

        String newTitle = tfTitle.getText();
        String newAuthor = tfAuthor.getText();
        String newDescription = taDescription.getText();
        int newPurgeLimit = getFormPurgeLimit();
        long newUpdatePeriod = pnlFeedUpdatePeriod.getUpdatePeriod();

        if (!newTitle.equals(initialTitle == null ? Constants.EMPTY_STRING : initialTitle))
        {
            if (newTitle.equals(feed.getBaseTitle())) newTitle = null;
            feed.setCustomTitle(newTitle);
        }

        if (!newAuthor.equals(initialAuthor == null ? Constants.EMPTY_STRING : initialAuthor))
        {
            if (newAuthor.equals(feed.getBaseAuthor())) newAuthor = null;
            feed.setCustomAuthor(newAuthor);
        }

        if (!newDescription.equals(initialDescription == null
            ? Constants.EMPTY_STRING : initialDescription))
        {
            if (newDescription.equals(feed.getBaseDescription())) newDescription = null;
            feed.setCustomDescription(newDescription);
        }

        // Custom purge limit
        if (newPurgeLimit != initialPurgeLimit)
        {
            feed.setPurgeLimit(newPurgeLimit);
        }

        // Custom update period
        if (newUpdatePeriod != initialUpdatePeriod)
        {
            feed.setUpdatePeriod(newUpdatePeriod);
        }

        // Ratings
        if (rating != feed.getRating())
        {
            feed.setRating(rating);
        }

        // Feed type
        displayTab.commitChanges();
        if (pnlFeedAutoSave != null) pnlFeedAutoSave.commitChanges(feed);

        feed.setHandlingType((FeedHandlingType)cbHandlingType.getSelectedItem());

        // Put XML url if the feed is not initialized
        if (!feed.isInitialized())
        {
            String newUrl = tfXmlUrl.getText();
            if (newUrl.trim().length() == 0) newUrl = null;

            try
            {
                feed.setXmlURL(newUrl == null ? null : new URL(newUrl));
            } catch (MalformedURLException e)
            {
                // TODO possibly report an error or do some type validation
                LOG.log(Level.WARNING, MessageFormat.format(Strings.error("invalid.url"), newUrl), e);
            }
        }
    }

    /**
     * Returns purge limit setting from form.
     *
     * @return purge limit.
     */
    private int getFormPurgeLimit()
    {
        int purgeLimit = -1;

        String purgeLimitString = tfPurgeLimit.getText();
        if (purgeLimitString != null && purgeLimitString.trim().length() != 0)
        {
            purgeLimit = Integer.parseInt(purgeLimitString);
        }

        return purgeLimit;
    }

    /**
     * Sets new purge limit value.
     *
     * @param purgeLimit new purge limit.
     */
    private void setFormPurgeLimit(int purgeLimit)
    {
        String text = purgeLimit == -1 ? Constants.EMPTY_STRING : Integer.toString(purgeLimit);
        tfPurgeLimit.setText(text);
    }

    /**
     * Performs cancel operation only if cancel button is enbled.
     */
    public void doCancel()
    {
        if (btnCancel.isEnabled()) super.doCancel();
    }

    /**
     * Performs close operation only if cancel button is enbled.
     */
    public void doClose()
    {
        if (btnCancel.isEnabled()) super.doClose();
    }

    /**
     * Returns the JPanel which will be the body of this little dialog.
     *
     * @return JComponent body of this Dialog Box.
     */
    private JComponent buildBody()
    {
        initComponents();

        JPanel panel = new JPanel(new BorderLayout());
        JTabbedPane pane = new JTabbedPane();
        panel.add(pane, BorderLayout.CENTER);

        displayTab = new DisplayPropertiesTabPanel(feed);

        pane.addTab(Strings.message("show.feed.properties.tab.basic"), createBasicTab());
        pane.addTab(Strings.message("show.feed.properties.tab.display"), displayTab);
        pane.addTab(Strings.message("show.feed.properties.tab.blogstarz"), createBlogStarzTab());
        pane.addTab(Strings.message("show.feed.properties.tab.advanced"), createAdvancedTab());

        adjustReadOnly();

        return panel;
    }

    /**
     * Creates basic tab component.
     *
     * @return basic tab.
     */
    private Component createBasicTab()
    {
        JScrollPane spDescription = new JScrollPane(taDescription);

        BBFormBuilder builder = new BBFormBuilder("pref, 4dlu, 0:grow, 2dlu, p");
        builder.setDefaultDialogBorder();

        builder.append(Strings.message("show.feed.properties.tab.basic.title"), tfTitle, 3);
        builder.appendRelatedComponentsGapRow(2);
        builder.appendRow("50dlu");
        JLabel label = builder.append(Strings.message("show.feed.properties.tab.basic.description"), 1,
            CellConstraints.FILL, CellConstraints.TOP);
        label.setLabelFor(taDescription);
        builder.append(spDescription, 3, CellConstraints.FILL, CellConstraints.FILL);
        builder.append(Strings.message("show.feed.properties.tab.basic.author"), tfAuthor);
        builder.append(btnSendEmail);
        builder.append(Strings.message("show.feed.properties.tab.basic.siteurl"), tfSiteUrl, 3);
        builder.append(Strings.message("show.feed.properties.tab.basic.xmlurl"), tfXmlUrl, 3);
        builder.append(Strings.message("show.feed.properties.tab.basic.language"),
            new JLabel(convertLang2String(feed.getLanguage())), 3);
        builder.appendUnrelatedComponentsGapRow(2);
        builder.append(ButtonBarFactory.buildCenteredBar(createRevertButton()), 5);
        builder.appendRow("14dlu:grow");

        return builder.getPanel();
    }

    /**
     * Initializes components.
     */
    private void initComponents()
    {
        initialUpdatePeriod = feed.getUpdatePeriod();

        // Basic Tab
        initialTitle = feed.getTitle();
        tfTitle = new JTextField(initialTitle);

        initialAuthor = feed.getAuthor();
        tfAuthor = new JTextField(initialAuthor);
        tfAuthor.getDocument().addDocumentListener(new AuthorFieldUpdateListener());

        initialDescription = feed.getDescription();
        taDescription = new JTextArea(initialDescription);
        taDescription.setLineWrap(true);
        taDescription.setWrapStyleWord(true);

        URL siteURL = feed.getSiteURL();
        tfSiteUrl = new LinkLabel();
        tfSiteUrl.setText(siteURL == null ? null : siteURL.toString());
        tfSiteUrl.setLink(siteURL);
        URL xmlURL = feed.getXmlURL();
        tfXmlUrl = new JTextField(xmlURL == null ? null : xmlURL.toString());

        btnSendEmail = ComponentsFactory.createButton(Strings.message("show.feed.properties.tab.basic.send.email"));
        btnSendEmail.addActionListener(new SendEmailToAuthorAction());
        updateSendEmailButton();

        pnlFeedUpdatePeriod = new FeedUpdatePeriodPanel(feed.getUpdatePeriod());
        pnlFeedAutoSave = new FeedAutoSavePanel(feed, GlobalController.SINGLETON.getFeatureManager().isAutoSaving());
    }

    // Updates the state of the send email button
    private void updateSendEmailButton()
    {
        btnSendEmail.setEnabled(getAuthorEmail() != null);
    }

    /**
     * Returns first email mentioned in the author field.
     *
     * @return email or NULL if not found.
     */
    private String getAuthorEmail()
    {
        String email = null;

        String author = tfAuthor.getText();
        if (!StringUtils.isEmpty(author))
        {
            Matcher matcher = PAT_EMAIL.matcher(author);
            if (matcher.find()) email = matcher.group(2);
        }

        return email;
    }

    /**
     * Adjusts the state of components.
     */
    private void adjustReadOnly()
    {
        boolean feedInitialized = feed.isInitialized();

        tfXmlUrl.setEditable(!feedInitialized);
        tfAuthor.setEditable(feedInitialized);
        taDescription.setEditable(feedInitialized);
        tfTitle.setEditable(feedInitialized);
    }

    /**
     * Creates advanced tab.
     *
     * @return advanced tab.
     */
    private Component createAdvancedTab()
    {
        cbHandlingType = new JComboBox(FeedHandlingType.ALL_TYPES);
        cbHandlingType.setSelectedItem(feed.getHandlingType());

        initialPurgeLimit = feed.getPurgeLimitCombined();
        tfPurgeLimit = new JTextField();
        setFormPurgeLimit(initialPurgeLimit);

        JLabel lbArticleCount = new JLabel(Integer.toString(feed.getArticlesCount()));
        JLabel lbRetrievals = new JLabel(String.valueOf(feed.getRetrievals()));
        JLabel lbLastUpdate = new JLabel(DateUtils.dateToString(new Date(feed.getLastPollTime())));
        JLabel lbFormat = new JLabel(feed.getFormat());

        BBFormBuilder builder = new BBFormBuilder("pref, 4dlu, max(pref;40px), 2dlu, pref:grow");
        builder.setDefaultDialogBorder();

        builder.append(Strings.message("show.feed.properties.tab.advanced.articles"), lbArticleCount, 3);
        builder.append(Strings.message("show.feed.properties.tab.advanced.retrievals"), lbRetrievals, 3);
        builder.append(Strings.message("show.feed.properties.tab.advanced.last.update"), lbLastUpdate, 3);
        builder.append(Strings.message("show.feed.properties.tab.advanced.format"), lbFormat, 3);
        builder.append(Strings.message("show.feed.properties.tab.advanced.purge.limit"), tfPurgeLimit);
        builder.nextLine();
        builder.append(Strings.message("show.feed.properties.tab.advanced.handling.type"), cbHandlingType);
        builder.nextLine();
        builder.append(Strings.message("show.feed.properties.tab.advanced.update.period"), 1,
                CellConstraints.LEFT, CellConstraints.TOP);
        builder.append(pnlFeedUpdatePeriod, 3);

        if (pnlFeedAutoSave != null)
        {
            builder.appendUnrelatedComponentsGapRow(2);
            builder.append(pnlFeedAutoSave, 5);
        }

        return builder.getPanel();
    }

    /**
     * Creates blog starz tab.
     *
     * @return tab.
     */
    private Component createBlogStarzTab()
    {
        ScoresCalculator calc = GlobalModel.SINGLETON.getScoreCalculator();
        double activity = calc.calcActivity(feed);
        double inlinks = calc.calcInlinksScore(feed);
        double views = calc.calcFeedViewsScore(feed);
        double clickthroughs = calc.calcClickthroughsScore(feed);
        blogStarzScore = calc.calcBlogStarzScore(feed);
        rating = feed.getRating();

        StarzPreferences prefs = GlobalModel.SINGLETON.getStarzPreferences();
        int activityWeight = prefs.getActivityWeight();
        int inlinksWeight = prefs.getInlinksWeight();
        int viewsWeight = prefs.getFeedViewsWeight();
        int clickthroughsWeight = prefs.getClickthroughsWeight();

        String msg = feed.getTextualInboundLinks();

        lbFinalScore = new JLabel();
        lbFinalScore.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        lbFinalScore.addMouseListener(new FinalScoreStarzListener());
        updateFinalScoreIcon();

        JLabel lbTechnoratiInlinks = new JLabel(msg);
        JLabel lbActivity = new JLabel(MessageFormat.format(
            Strings.message("show.feed.properties.tab.blogstarz.0.weight.1"),
            DECIMAL_FORMAT.format(activity), activityWeight));
        JLabel lbInLinks = new JLabel(MessageFormat.format(
            Strings.message("show.feed.properties.tab.blogstarz.0.weight.1"),
            DECIMAL_FORMAT.format(inlinks), inlinksWeight));
        JLabel lbViews = new JLabel(MessageFormat.format(
            Strings.message("show.feed.properties.tab.blogstarz.0.weight.1"),
            DECIMAL_FORMAT.format(views), viewsWeight));
        JLabel lbClickthroughs = new JLabel(MessageFormat.format(
            Strings.message("show.feed.properties.tab.blogstarz.0.weight.1"),
            DECIMAL_FORMAT.format(clickthroughs), clickthroughsWeight));
        JLabel lbRecommendation = new JLabel(FeedFormatter.getStarzIcon(blogStarzScore, true));

        BBFormBuilder builder = new BBFormBuilder("pref, 4dlu, pref, 4dlu, pref:grow");
        builder.setDefaultDialogBorder();

        builder.append(Strings.message("show.feed.properties.tab.blogstarz.technorati.inlinks"), lbTechnoratiInlinks, 3);
        builder.append(Strings.message("show.feed.properties.tab.blogstarz.activity"), lbActivity, 3);
        builder.append(Strings.message("show.feed.properties.tab.blogstarz.inlinks"), lbInLinks, 3);
        builder.append(Strings.message("show.feed.properties.tab.blogstarz.views"), lbViews, 3);
        builder.append(Strings.message("show.feed.properties.tab.blogstarz.clickthroughs"), lbClickthroughs, 3);
        builder.append(Strings.message("show.feed.properties.tab.blogstarz.recommendation"), 1);
        builder.append(lbRecommendation, 1, CellConstraints.LEFT, CellConstraints.CENTER);
        builder.appendUnrelatedComponentsGapRow(2);
        builder.append(Strings.message("show.feed.properties.tab.blogstarz.final.rating"), 1);
        builder.append(lbFinalScore, 1, CellConstraints.LEFT, CellConstraints.CENTER);
        builder.append(new JButton(new RevertAction()), 1,
            CellConstraints.RIGHT, CellConstraints.CENTER);
        builder.appendRow("pref:grow");
        builder.append(ComponentsFactory.createWrappedMultilineLabel(
            Strings.message("show.feed.properties.tab.blogstarz.notes")), 5,
            CellConstraints.FILL, CellConstraints.BOTTOM);

        return builder.getPanel();
    }

    /**
     * Converts compressed language-country code into human-readable form.
     *
     * @param language language.
     *
     * @return string.
     */
    private static String convertLang2String(String language)
    {
        if (language == null) return null;
        language = language.replaceAll("-", "_");
        StringTokenizer st = new StringTokenizer(language, "_");
        String lang;
        String country = "";
        String variant = "";
        String display = language;

        if (language.length() > 0)
        {
            try
            {
                lang = st.nextToken();
                if (st.hasMoreTokens()) country = st.nextToken().toUpperCase();
                if (st.hasMoreTokens()) variant = st.nextToken();

                Locale l = new Locale(lang, country, variant);
                display = l.getDisplayName();
            } catch (Exception e)
            {
                if (LOG.isLoggable(Level.WARNING))
                {
                    LOG.log(Level.WARNING, MessageFormat.format(
                        Strings.error("failed.to.transform.the.language.into.printable.form"),
                        language), e);
                }
            }
        }
       
        return display;
    }

    // Updates the icon according to the rating setting.
    private void updateFinalScoreIcon()
    {
        if (rating == -1)
        {
            lbFinalScore.setIcon(FeedFormatter.getStarzIcon(blogStarzScore, true));
        } else
        {
            lbFinalScore.setIcon(FeedFormatter.getStarzIcon(rating, false));
        }
    }

    /**
     * Resizes the specified component. This method is called during the build process and enables
     * subclasses to achieve a better aspect ratio, by applying a resizer, e.g. the
     * <code>Resizer</code>.
     *
     * @param component the component to be resized
     */
    protected void resizeHook(JComponent component)
    {
        component.setPreferredSize(Resizer.ONE2ONE.fromHeight(component.getPreferredSize().height));
    }

    /**
     * Listens for clicks over the final score starz and updates the view by applying or
     * resetting user supplied rating.
     */
    private class FinalScoreStarzListener extends MouseAdapter
    {
        public void mouseClicked(MouseEvent e)
        {
            if ((e.getModifiers() & InputEvent.SHIFT_MASK) == 0)
            {
                rating = (int)(5.0 * e.getX() / lbFinalScore.getIcon().getIconWidth());
            } else
            {
                rating = -1;
            }

            updateFinalScoreIcon();
        }
    }

    /** Reverts rating to default value. */
    private class RevertAction extends AbstractAction
    {
        public RevertAction()
        {
            super(Strings.message("show.feed.properties.revert.to.recommendation"));
        }

        public void actionPerformed(ActionEvent e)
        {
            rating = -1;
            updateFinalScoreIcon();
        }
    }

    /**
     * Sends email to author mentioned in the author field.
     */
    private class SendEmailToAuthorAction implements ActionListener
    {
        /**
         * Invoked when an action occurs.
         */
        public void actionPerformed(ActionEvent e)
        {
            String email = getAuthorEmail();
            if (email != null)
            {
                String browser = GlobalModel.SINGLETON.getUserPreferences().getInternetBrowser();
                BrowserLauncher.emailThis(email, tfTitle.getText(), "", browser);
            }
        }
    }

    private class AuthorFieldUpdateListener implements DocumentListener
    {
        /**
         * Gives notification that there was an insert into the document.  The
         * range given by the DocumentEvent bounds the freshly inserted region.
         *
         * @param e the document event
         */
        public void insertUpdate(DocumentEvent e)
        {
            updateSendEmailButton();
        }

        /**
         * Gives notification that a portion of the document has been
         * removed.  The range is given in terms of what the view last
         * saw (that is, before updating sticky positions).
         *
         * @param e the document event
         */
        public void removeUpdate(DocumentEvent e)
        {
            updateSendEmailButton();
        }

        /**
         * Gives notification that an attribute or set of attributes changed.
         *
         * @param e the document event
         */
        public void changedUpdate(DocumentEvent e)
        {
            updateSendEmailButton();
        }
    }

}
TOP

Related Classes of com.salas.bb.dialogs.DirectFeedPropertiesDialog

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.