package hirondelle.stocks.main;
import hirondelle.stocks.portfolio.CurrentPortfolio;
import hirondelle.stocks.portfolio.EditSaver;
import hirondelle.stocks.portfolio.PortfolioDAO;
import hirondelle.stocks.preferences.GeneralLookPreferencesEditor;
import hirondelle.stocks.preferences.LoggingPreferencesEditor;
import hirondelle.stocks.preferences.OptionPaneExceptionHandler;
import hirondelle.stocks.util.Consts;
import hirondelle.stocks.file.FileDeleteAction;
import hirondelle.stocks.file.FileSaveAction;
import hirondelle.stocks.file.FileSaveAsAction;
import hirondelle.stocks.file.FileNewAction;
import hirondelle.stocks.file.FileCloseAction;
import hirondelle.stocks.file.FileOpenAction;
import hirondelle.stocks.file.FileExitAction;
import hirondelle.stocks.export.ImportAction;
import hirondelle.stocks.export.ExportAction;
import hirondelle.stocks.quotes.FetchQuotesAction;
import hirondelle.stocks.help.HelpAction;
import hirondelle.stocks.help.AboutAction;
import hirondelle.stocks.portfolio.EditPortfolioAction;
import hirondelle.stocks.preferences.EditUserPreferencesAction;
import hirondelle.stocks.table.QuoteTable;
import hirondelle.stocks.preferences.QuoteTablePreferencesEditor;
import hirondelle.stocks.quotes.SummaryView;
import hirondelle.stocks.table.QuoteFilterFactory;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import java.util.logging.Logger;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.metal.MetalTheme;
import hirondelle.stocks.preferences.PreferencesEditor;
import hirondelle.stocks.util.Util;
import hirondelle.stocks.util.ui.Theme;
import hirondelle.stocks.util.ui.UiConsts;
import hirondelle.stocks.util.ui.UiUtil;
final class StocksMonitorMainWindow implements Observer {
public StocksMonitorMainWindow() {
initCurrentPortfolio();
initGuiPieces();
initFrame();
initActions();
initMainGui();
broadcastCurrentPortfolioUpdate();
showMainWindow();
OptionPaneExceptionHandler.attachToRootLogger();
}
@Override public void update(Observable aObservable, Object aData) {
fLogger.fine("Notify being broadcast...");
if (aObservable == fCurrentPortfolio) {
fLogger.fine("Notified by Current Portfolio...");
synchTitleBarWithCurrentPortfolio();
}
else if (aObservable == fGeneralLookPrefs) {
fLogger.fine("Notified by General Look...");
synchGuiWithGeneralLookPrefs();
}
}
private JFrame fFrame;
private CurrentPortfolio fCurrentPortfolio;
private GeneralLookPreferencesEditor fGeneralLookPrefs;
private QuoteTable fQuoteTable;
private QuoteTablePreferencesEditor fQuoteTablePrefsEditor;
private QuoteFilterFactory fQuoteFilterFactory;
private SummaryView fSummaryView;
private Action fExitAction;
private Action fEditUserPreferencesAction;
private FetchQuotesAction fFetchQuotesAction;
private Action fFileNewAction;
private Action fFileOpenAction;
private Action fFileCloseAction;
private Action fFileSaveAction;
private Action fFileSaveAsAction;
private Action fFileDeleteAction;
private JToolBar fToolbar;
private static final Dimension MAIN_PANEL_SIZE = new Dimension(400, 300);
private static final String ICON = "favicon.gif";
private static final Logger fLogger = Util.getLogger(StocksMonitorMainWindow.class);
private void initCurrentPortfolio() {
fLogger.info("Initializing the current portfolio");
PortfolioDAO dao = new PortfolioDAO();
fCurrentPortfolio = new CurrentPortfolio(dao.fetchDefaultPortfolio(),
CurrentPortfolio.NeedsSave.FALSE);
fCurrentPortfolio.addObserver(this);
}
private void initGuiPieces() {
fLogger.info("Initializing main pieces of the GUI.");
fQuoteFilterFactory = new QuoteFilterFactory(fCurrentPortfolio);
fSummaryView = new SummaryView(fCurrentPortfolio, fQuoteFilterFactory);
fQuoteTablePrefsEditor = new QuoteTablePreferencesEditor();
fQuoteTable = new QuoteTable(fQuoteTablePrefsEditor, fQuoteFilterFactory);
fGeneralLookPrefs = new GeneralLookPreferencesEditor();
fGeneralLookPrefs.addObserver(this);
}
private void initFrame() {
fFrame = new JFrame();
ImageIcon imageIcon = UiUtil.getImageIcon(ICON, this.getClass());
fFrame.setIconImage(imageIcon.getImage());
}
private void initActions() {
fLogger.info("Initializing Actions.");
fFileDeleteAction = new FileDeleteAction(fCurrentPortfolio, fFrame);
fFileSaveAction = new FileSaveAction(fCurrentPortfolio);
fFileSaveAsAction = new FileSaveAsAction(fCurrentPortfolio, fFrame);
EditSaver editSaver = new EditSaver(fFileSaveAction, fFileSaveAsAction, fFrame);
fFileNewAction = new FileNewAction(fCurrentPortfolio, fFrame, editSaver);
fFileOpenAction = new FileOpenAction(fCurrentPortfolio, fFrame, editSaver);
fFileCloseAction = new FileCloseAction(fCurrentPortfolio, editSaver);
java.util.List<PreferencesEditor> prefEditors = new ArrayList<>();
prefEditors.add(fGeneralLookPrefs);
prefEditors.add(new LoggingPreferencesEditor());
prefEditors.add(fQuoteTablePrefsEditor);
fEditUserPreferencesAction = new EditUserPreferencesAction(fFrame, prefEditors);
fExitAction = new FileExitAction(fCurrentPortfolio, editSaver);
fFetchQuotesAction = new FetchQuotesAction(
fCurrentPortfolio, fQuoteTablePrefsEditor, fQuoteTable, fSummaryView
);
fFetchQuotesAction.startTimer();
}
private void initMainGui() {
fLogger.info("Initializing larges pieces of the GUI.");
JSplitPane splitPane = new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT, fQuoteFilterFactory, getStocksTableAndSummary()
);
splitPane.setOneTouchExpandable(true);
fFrame.setJMenuBar(getMenuBar());
fToolbar = getToolBar();
fFrame.getContentPane().add(fToolbar, BorderLayout.NORTH);
fFrame.getContentPane().add(splitPane, BorderLayout.CENTER);
fFrame.addWindowListener(new WindowAdapter() {
@Override public void windowClosing(WindowEvent e) {
fExitAction.actionPerformed(null);
}
});
}
private void broadcastCurrentPortfolioUpdate() {
fCurrentPortfolio.notifyObservers();
}
private JMenuBar getMenuBar() {
JMenuBar menubar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F);
fileMenu.add(fFileNewAction);
fileMenu.add(fFileOpenAction);
fileMenu.add(fFileCloseAction);
fileMenu.addSeparator();
fileMenu.add(fFileSaveAction);
fileMenu.add(fFileSaveAsAction);
fileMenu.add(fFileDeleteAction);
fileMenu.addSeparator();
fileMenu.add(fEditUserPreferencesAction);
fileMenu.addSeparator();
fileMenu.add(new ImportAction(fFrame));
fileMenu.add(new ExportAction(fFrame));
fileMenu.addSeparator();
fileMenu.add(fExitAction);
menubar.add(fileMenu);
JMenu editMenu = new JMenu("Edit");
editMenu.setMnemonic(KeyEvent.VK_E);
editMenu.add(new EditPortfolioAction(fCurrentPortfolio, fFrame));
editMenu.add(fFetchQuotesAction);
menubar.add(editMenu);
JMenu helpMenu = new JMenu("Help");
helpMenu.setMnemonic(KeyEvent.VK_H);
helpMenu.add(new HelpAction(
fFrame, "Contents", KeyEvent.VK_C, null, HelpAction.View.CONTENTS)
);
helpMenu.add(new HelpAction(
fFrame, "Index", KeyEvent.VK_I, null, HelpAction.View.INDEX)
);
helpMenu.add(
new HelpAction(fFrame, "Search...", KeyEvent.VK_S, null, HelpAction.View.SEARCH)
);
helpMenu.add(new JSeparator());
helpMenu.add(new AboutAction(fFrame));
menubar.add(helpMenu);
return menubar;
}
private JToolBar getToolBar() {
JToolBar toolbar = new JToolBar();
toolbar.setRollover(true);
toolbar.add(fFileNewAction);
toolbar.add(fFileOpenAction);
toolbar.add(fFileSaveAction);
toolbar.add(fFileSaveAsAction);
toolbar.add(fFileDeleteAction);
toolbar.addSeparator();
toolbar.add(fFetchQuotesAction);
return toolbar;
}
private JComponent getStocksTableAndSummary() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(fQuoteTable);
panel.add(Box.createVerticalStrut(UiConsts.ONE_SPACE));
panel.add(fSummaryView);
panel.setPreferredSize(MAIN_PANEL_SIZE);
return panel;
}
private void showMainWindow() {
fLogger.info("Showing the main window.");
if (!Theme.hasLargeFont(fGeneralLookPrefs.getTheme())) {
synchGuiWithGeneralLookPrefs();
UiUtil.centerAndShow(fFrame);
}
else {
UiUtil.centerAndShow(fFrame);
synchGuiWithGeneralLookPrefs();
}
}
private void synchTitleBarWithCurrentPortfolio() {
StringBuilder title = new StringBuilder(Consts.APP_NAME);
title.append(Consts.SPACE);
title.append(Consts.APP_VERSION);
title.append(" - Portfolio : ");
if (fCurrentPortfolio.isUntitled()) {
title.append("(Untitled)");
}
else {
title.append(fCurrentPortfolio.getName());
}
if (fCurrentPortfolio.getNeedsSave()) {
title.append(" *");
}
fFrame.setTitle(title.toString());
}
private void synchGuiWithGeneralLookPrefs() {
if (fGeneralLookPrefs.hasShowToolBar()) {
fToolbar.setVisible(true);
}
else {
fQuoteFilterFactory.requestFocusInWindow();
fToolbar.setVisible(false);
}
MetalTheme preferredTheme = fGeneralLookPrefs.getTheme();
MetalLookAndFeel.setCurrentTheme(preferredTheme);
try {
UIManager.setLookAndFeel(new MetalLookAndFeel());
}
catch (UnsupportedLookAndFeelException ex) {
fLogger.severe("Cannot set new Theme for Java Look and Feel.");
}
SwingUtilities.updateComponentTreeUI(fFrame);
}
}