tkwatch.WatchlistPanel.java Source code

Java tutorial

Introduction

Here is the source code for tkwatch.WatchlistPanel.java

Source

/*
 * Created Apr 3, 2011
 * Copyright (c) 2011, Mike Radovich (maradovich@loyola.edu).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice, 
 *       this list of conditions and the following disclaimer.
 * 
 *     * Redistributions in binary form must reproduce the above copyright 
 *       notice, this list of conditions and the following disclaimer in the 
 *       documentation and/or other materials provided with the distribution.
 * 
 *     * Neither the name of George Wright nor the name of Loyola College
 *       may be used to endorse or promote products derived from this software 
 *       without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * To learn more about open source licenses, please visit: 
 * http://opensource.org/index.php
 */

package tkwatch;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;

/**
 * The panel for working with annotated watchlists.
 * <p>
 * Contest version.
 */
public class WatchlistPanel extends TradekingPanel {
    /**
     * The entry tab managed. Passed as an argument to spawned windows, to wit,
     * the item add window.
     */
    WatchlistPanel tabReference = null;

    /*
     * Label for the list of instruments appearing in the watchlist. Spaces are
     * to set the width of the symbol column.
     */
    private final JLabel instrumentListLabel = new JLabel("   Symbol   ");

    /**
     * List model for the list of stock market symbols in the watchlist.
     */
    final DefaultListModel instrumentListModel = new DefaultListModel();

    /**
     * The list of stock market symbols. This allows the user to select an
     * instrument for display and then deletion or update.
     */
    final JList instrumentList = new JList(instrumentListModel);

    /*
     * Allows long instrument lists to scroll.
     */
    private final JScrollPane instrumentListScrollPane = new JScrollPane(instrumentList);

    /*
     * Label for the cost basis input/display field.
     */
    final private JLabel costBasisLabel = new JLabel("Cost Basis");

    /*
     * The cost basis input/display field.
     */
    final private JTextField costBasisField = new JTextField(Constants.FIELD_WIDTH_NARROW);

    /*
     * Label for the quantity input/display field.
     */
    final private JLabel quantityLabel = new JLabel("Quantity");

    /*
     * The quantity input/display field.
     */
    final private JTextField quantityField = new JTextField(Constants.FIELD_WIDTH_NARROW);

    /*
     * Label for the notation display/entry field.
     */
    final private JLabel notationLabel = new JLabel("Notation");

    /*
     * The field used to enter, display, and edit the notation the user adds to
     * a watchlist item.
     */
    final private JEditorPane notationField = new JEditorPane();

    /*
     * Allows the notation field to scroll.
     */
    final private JScrollPane notationFieldScrollPane = new JScrollPane(getNotationField());

    /*
     * Clicked by the user to delete the selected instrument from the watch
     * list.
     */
    final private JButton buttonDelete = getButton("Delete", "Delete selected instrument from the watchlist.");

    /*
     * Clicked by the user to open the window that supports adding a new
     * instrument to the watchlist.
     */
    final private JButton buttonAdd = getButton("Add", "Add an instrument to the watchlist.");

    /*
     * Clicked by the user to save any changes made to cost basis, quantity, or
     * notation to the database.
     */
    final private JButton buttonUpdate = getButton("Update", "Record changes to local watchlist.");

    /*
     * Labels the check box to enable tweeting.
     */
    private final JLabel tweetLabel = new JLabel();

    /**
     * Selects whether or not to tweet adds and deletes to/from the watchlist.
     */
    final JCheckBox tweet = new JCheckBox();

    /**
     * Constructor with title argument.
     * 
     * @param string
     *            The title of the watchlist panel.
     */
    public WatchlistPanel(String string) {
        tabReference = this;
        try {
            Database.connectToDatabase();
        } catch (ClassNotFoundException e) {
            TradekingException.handleException(e);
        } catch (SQLException e) {
            TradekingException.handleException(e);
        }
        final ArrayList<WatchlistItem> items = getItemsArrayList();
        final Iterator<WatchlistItem> itemIterator = items.iterator();
        while (itemIterator.hasNext()) {
            instrumentListModel.addElement(itemIterator.next().getInstrument());
        }
        instrumentList.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (instrumentList.getSelectedValue() != null) {
                    final String symbol = instrumentList.getSelectedValue().toString();
                    final WatchlistItem item = WatchlistItem.retrieve(symbol);
                    getCostBasisField().setText(Double.toString(item.getCostBasis()));
                    getQuantityField().setText(Double.toString(item.getQuantity()));
                    getNotationField().setText(Utilities.unPrep(item.getNotation()));
                }
            }

        });
        instrumentList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        instrumentList.setLayoutOrientation(JList.VERTICAL);
        instrumentList.setFont(Constants.DEFAULT_FONT);
        instrumentList.setFixedCellWidth(Constants.FIELD_WIDTH_NARROW);
        if (instrumentList.getComponentCount() >= 0)
            instrumentList.setSelectedIndex(0);

        JPanel costQuantityPanel = new JPanel(new GridBagLayout());
        costQuantityPanel.add(costBasisLabel, Utilities.getConstraints(0, 0, 1, 1, GridBagConstraints.SOUTH));
        costQuantityPanel.add(quantityLabel, Utilities.getConstraints(1, 0, 1, 1, GridBagConstraints.SOUTH));
        costQuantityPanel.add(getCostBasisField(), Utilities.getConstraints(0, 1, 1, 1, GridBagConstraints.CENTER));
        costQuantityPanel.add(getQuantityField(), Utilities.getConstraints(1, 1, 1, 1, GridBagConstraints.CENTER));
        costQuantityPanel.add(notationLabel, Utilities.getConstraints(0, 2, 2, 1, GridBagConstraints.SOUTH));

        JPanel buttonPanel = new JPanel(new GridBagLayout());
        buttonAdd.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                // TODO Currently opens a new window; use a panel in the main frame instead.
                final ItemAddPanel addWindow = new ItemAddPanel(tabReference);
                final JFrame frame = new JFrame();
                frame.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.getContentPane().add(addWindow);
                frame.pack();
                frame.setSize(Constants.INITIAL_FRAME_WIDTH, Constants.INITIAL_FRAME_HEIGHT);
                Utilities.centerWindow(frame);
                frame.setVisible(true);
            }
        });
        buttonPanel.add(buttonAdd, Utilities.getConstraints(0, 0, 1, 1, GridBagConstraints.CENTER));
        buttonUpdate.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                final String instrumentSelected = (String) instrumentList.getSelectedValue();
                final int response = JOptionPane.showConfirmDialog(null,
                        "Really update " + instrumentSelected + " in the database?");
                if (response != JOptionPane.YES_OPTION)
                    return;
                final WatchlistItem itemToUpdate = WatchlistItem.retrieve(instrumentSelected);
                itemToUpdate.setCostBasis(Double.parseDouble(getCostBasisField().getText()));
                itemToUpdate.setNotation(Utilities.prep(getNotationField().getText()));
                itemToUpdate.setQuantity(Double.parseDouble(getQuantityField().getText()));
                if (!WatchlistItem.update(itemToUpdate)) {
                    Utilities.errorMessage("Couldn't update " + instrumentSelected);
                    return;
                }
                synchWatchlistWithTk();
            }
        });
        buttonPanel.add(buttonUpdate, Utilities.getConstraints(1, 0, 1, 1, GridBagConstraints.CENTER));
        buttonDelete.addActionListener(new ActionListener() {
            // TODO deleting all instruments leaves last instrument's data in
            // cost basis, quantity and notation windows.
            public void actionPerformed(final ActionEvent e) {
                final String symbolToDelete = (String) instrumentList.getSelectedValue();
                final int response = JOptionPane.showConfirmDialog(null,
                        "Really delete " + symbolToDelete + " from the watchlist?");
                if (response != JOptionPane.YES_OPTION)
                    return;
                if (!WatchlistItem.delete(symbolToDelete)) {
                    Utilities.errorMessage("Couldn't delete item " + symbolToDelete);
                    return;
                }
                instrumentListModel.removeElementAt(instrumentList.getSelectedIndex());
                if (tweet.isSelected()) {
                    final Twitter twitter = new TwitterFactory().getInstance();
                    final String update;
                    try {
                        update = "Stopped watching " + symbolToDelete + " on @TradeKing.";
                        twitter.updateStatus(update);
                    } catch (TwitterException e1) {
                        Utilities.errorMessage(e1.getMessage());
                    }
                }
                if (instrumentList.getComponentCount() >= 0)
                    instrumentList.setSelectedIndex(0);
                synchWatchlistWithTk();
            }
        });
        buttonPanel.add(buttonDelete, Utilities.getConstraints(2, 0, 1, 1, GridBagConstraints.CENTER));

        final JPanel tweetPanel = new JPanel(new FlowLayout());
        final ImageIcon iconColor = new ImageIcon("twitterColor.gif");
        final ImageIcon iconGray = new ImageIcon("twitterGray.gif");
        getTweetLabel().setIcon(iconColor);
        tweet.setSelected(true);
        tweet.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent arg0) {
                if (tweet.isSelected()) {
                    getTweetLabel().setIcon(iconColor);
                    // to tweet or not to tweet is decided by tweet.isSelected()
                } else {
                    getTweetLabel().setIcon(iconGray);
                }
            }
        });
        tweetPanel.add(tweet);
        tweetPanel.add(getTweetLabel());

        final JPanel bottomPanel = new JPanel(new BorderLayout());
        bottomPanel.add(buttonPanel, BorderLayout.NORTH);
        bottomPanel.add(tweetPanel, BorderLayout.SOUTH);

        final JPanel managementPanel = new JPanel(new BorderLayout());
        managementPanel.add(costQuantityPanel, BorderLayout.NORTH);
        managementPanel.add(notationFieldScrollPane, BorderLayout.CENTER);
        managementPanel.add(bottomPanel, BorderLayout.SOUTH);

        final JPanel symbolPanel = new JPanel(new BorderLayout());
        symbolPanel.add(instrumentListLabel, BorderLayout.NORTH);
        symbolPanel.add(instrumentListScrollPane, BorderLayout.CENTER);

        this.setLayout(new BorderLayout(Constants.GAP, Constants.GAP));
        this.add(symbolPanel, BorderLayout.WEST);
        this.add(managementPanel, BorderLayout.CENTER);
    }

    /**
     * Returns a standard-size button.
     * 
     * @param label
     *            The button label.
     * @param toolTip
     *            The tool tip for the button.
     */
    private final JButton getButton(final String label, final String toolTip) {
        final JButton result = new JButton(label);
        result.setSize(Constants.BUTTON_WIDTH, Constants.BUTTON_HEIGHT);
        result.setToolTipText(toolTip);
        return result;
    }

    /**
     * Gets the cost basis.
     * 
     * @return the costBasisField
     */
    public final JTextField getCostBasisField() {
        return costBasisField;
    }

    /**
     * Sets up the ArrayList of watchlist items. (If for nothing else, this is
     * needed for testing.)
     * 
     * @return Returns the ArrayList, populated with all the items in the watch
     *         list database.
     */
    public final ArrayList<WatchlistItem> getItemsArrayList() {
        final ArrayList<WatchlistItem> result = WatchlistItem.getAll();
        return result;
    }

    /**
     * Gets the notation.
     * 
     * @return the notationField
     */
    public final JEditorPane getNotationField() {
        return notationField;
    }

    /**
     * Gets the quantity.
     * 
     * @return the quantityField
     */
    public final JTextField getQuantityField() {
        return quantityField;
    }

    /**
     * Getter for the (graphic) caption of the tweet check box. This becomes
     * colored icon image when checked, a grayed-out icon image when unchecked.
     * 
     * @return the tweetLabel
     */
    public JLabel getTweetLabel() {
        return tweetLabel;
    }

    /**
     * Refreshes the list of instrument symbols from the database.
     * 
     * @return Returns the list.
     */
    final JList refreshInstrumentList() {
        final ArrayList<WatchlistItem> items = getItemsArrayList();
        final Vector<String> symbols = new Vector<String>();
        final Iterator<WatchlistItem> itemIterator = items.iterator();
        while (itemIterator.hasNext()) {
            symbols.add(itemIterator.next().getInstrument());
        }
        final JList result = new JList(symbols);
        result.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent arg0) {
                final String symbol = result.getSelectedValue().toString();
                final WatchlistItem item = WatchlistItem.retrieve(symbol);
                getCostBasisField().setText(Double.toString(item.getCostBasis()));
                getQuantityField().setText(Double.toString(item.getQuantity()));
                getNotationField().setText(Utilities.unPrep(item.getNotation()));
            }
        });
        result.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        result.setLayoutOrientation(JList.VERTICAL);
        result.setFont(Constants.DEFAULT_FONT);
        result.setFixedCellWidth(Constants.FIELD_WIDTH_NARROW);
        if (result.getComponentCount() >= 0)
            result.setSelectedIndex(0);
        return result;
    }
}