com.digitalgeneralists.assurance.ui.MainWindow.java Source code

Java tutorial

Introduction

Here is the source code for com.digitalgeneralists.assurance.ui.MainWindow.java

Source

/*
 * Assurance
 * 
 * Created by Mark Johnson
 * 
 * Copyright (c) 2015 Digital Generalists, LLC.
 * 
 */
/*
 * Copyright 2015 Digital Generalists, LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */

package com.digitalgeneralists.assurance.ui;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;

import javax.swing.ButtonGroup;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.digitalgeneralists.assurance.Application;
import com.digitalgeneralists.assurance.IApplicationDelegate;
import com.digitalgeneralists.assurance.model.entities.ApplicationConfiguration;
import com.digitalgeneralists.assurance.notification.IEventObserver;
import com.digitalgeneralists.assurance.notification.events.ApplicationConfigurationLoadedEvent;
import com.digitalgeneralists.assurance.notification.events.ApplicationConfigurationSavedEvent;
import com.digitalgeneralists.assurance.notification.events.IAssuranceEvent;
import com.digitalgeneralists.assurance.notification.events.ScanCompletedEvent;
import com.digitalgeneralists.assurance.notification.events.ScanStartedEvent;
import com.digitalgeneralists.assurance.notification.events.SetScanDefinitionMenuStateEvent;
import com.digitalgeneralists.assurance.notification.events.SetScanResultsMenuStateEvent;
import com.digitalgeneralists.assurance.ui.components.AssuranceActions;
import com.digitalgeneralists.assurance.ui.components.ResultsPanel;
import com.digitalgeneralists.assurance.ui.components.ScanHistoryPanel;
import com.digitalgeneralists.assurance.ui.components.ScanLaunchPanel;
import com.digitalgeneralists.assurance.ui.factories.IDialogFactory;
import com.digitalgeneralists.assurance.utils.AssuranceUtils;
import com.digitalgeneralists.assurance.utils.Platform;

@Component("ApplicationUI")
public class MainWindow extends JFrame implements IApplicationUI, IEventObserver, ActionListener {
    private Logger logger = Logger.getLogger(MainWindow.class);

    private boolean initialized = false;

    private int scanMenuIndex = 0;
    private int resultsMenuIndex = 1;
    private int viewMenuIndex = 2;
    private int toolsMenuIndex = 3;

    private int viewHistoryMenuItemIndex = 1;

    private JMenuBar menuBar;
    private JRadioButtonMenuItem viewScanMenuItem;
    private JRadioButtonMenuItem viewHistoryMenuItem;

    @Autowired
    private IApplicationDelegate applicationDelegate;

    @Autowired
    private ScanLaunchPanel scanLaunchPanel;

    @Autowired
    private ScanHistoryPanel scanHistoryPanel;

    @Autowired
    private ResultsPanel resultsPanel;

    @Autowired
    IDialogFactory dialogFactory;

    private JTabbedPane topArea;

    private ApplicationConfiguration applicationConfiguration = null;

    // NOTE:  Since these are statics, using a SB to construct the labels is more complex than
    // the possible benefit may warrant.
    private static String quitApplicationMenuLabel = "Quit " + Application.applicationShortName;
    private static String aboutApplicationMenuLabel = "About " + Application.applicationShortName;
    private static String settingsMenuLabel = "Settings...";
    private static String newScanDefinitonMenuLabel = "New Scan Definition...";
    private static String deleteScanDefinitonMenuLabel = "Delete Scan Definition";
    private static String scanMenuLabel = "Scan";
    private static String scanAndMergeMenuLabel = "Scan & Merge";
    private static String replaceSourceMenuLabel = "Replace Source";
    private static String replaceTargetMenuLabel = "Replace Target";
    private static String sourceAttributesMenuLabel = "View Source Attributes...";
    private static String targetAttributesMenuLabel = "View Target Attributes...";
    private static String viewScanMenuLabel = "View Scan";
    private static String viewHistoryMenuLabel = "View History";

    private static final long serialVersionUID = 1L;

    public MainWindow() {
        if (AssuranceUtils.getPlatform() != Platform.MAC) {
            this.scanMenuIndex = 1;
            this.resultsMenuIndex = 2;
            this.viewMenuIndex = 3;
            this.toolsMenuIndex = 4;
        }
    }

    private void initializeComponent() {
        if (!this.initialized) {
            logger.info("Initializing the main window.");

            if (AssuranceUtils.getPlatform() == Platform.MAC) {

                System.setProperty("apple.laf.useScreenMenuBar", "true");
                com.apple.eawt.Application macApplication = com.apple.eawt.Application.getApplication();
                MacApplicationAdapter macAdapter = new MacApplicationAdapter(this);
                macApplication.addApplicationListener(macAdapter);
                macApplication.setEnabledPreferencesMenu(true);
            }

            this.setTitle(Application.applicationShortName);

            this.setDefaultCloseOperation(EXIT_ON_CLOSE);

            GridBagLayout gridbag = new GridBagLayout();
            this.setLayout(gridbag);

            this.topArea = new JTabbedPane();

            this.scanLaunchPanel.setPreferredSize(new Dimension(600, 150));

            this.scanHistoryPanel.setPreferredSize(new Dimension(600, 150));

            this.topArea.addTab("Scan", this.scanLaunchPanel);

            this.topArea.addTab("History", this.scanHistoryPanel);

            this.resultsPanel.setPreferredSize(new Dimension(600, 400));

            this.topArea.addChangeListener(new ChangeListener() {
                public void stateChanged(ChangeEvent e) {
                    resultsPanel.resetPanel();
                    // NOTE:  This isn't ideal.  It feels brittle.
                    if (topArea.getSelectedIndex() == viewHistoryMenuItemIndex) {
                        viewHistoryMenuItem.setSelected(true);
                    } else {
                        viewScanMenuItem.setSelected(true);
                    }
                }
            });

            GridBagConstraints topPanelConstraints = new GridBagConstraints();
            topPanelConstraints.anchor = GridBagConstraints.NORTH;
            topPanelConstraints.fill = GridBagConstraints.BOTH;
            topPanelConstraints.gridx = 0;
            topPanelConstraints.gridy = 0;
            topPanelConstraints.weightx = 1.0;
            topPanelConstraints.weighty = 0.33;
            topPanelConstraints.gridheight = 1;
            topPanelConstraints.gridwidth = 1;
            topPanelConstraints.insets = new Insets(0, 0, 0, 0);

            this.getContentPane().add(this.topArea, topPanelConstraints);

            GridBagConstraints resultsPanelConstraints = new GridBagConstraints();
            resultsPanelConstraints.anchor = GridBagConstraints.SOUTH;
            resultsPanelConstraints.fill = GridBagConstraints.BOTH;
            resultsPanelConstraints.gridx = 0;
            resultsPanelConstraints.gridy = 1;
            resultsPanelConstraints.weightx = 1.0;
            resultsPanelConstraints.weighty = 0.67;
            resultsPanelConstraints.gridheight = 1;
            resultsPanelConstraints.gridwidth = 1;
            resultsPanelConstraints.insets = new Insets(0, 0, 0, 0);

            this.getContentPane().add(this.resultsPanel, resultsPanelConstraints);

            this.applicationDelegate.addEventObserver(ScanStartedEvent.class, this);
            this.applicationDelegate.addEventObserver(ScanCompletedEvent.class, this);
            this.applicationDelegate.addEventObserver(SetScanDefinitionMenuStateEvent.class, this);
            this.applicationDelegate.addEventObserver(SetScanResultsMenuStateEvent.class, this);
            this.applicationDelegate.addEventObserver(ApplicationConfigurationLoadedEvent.class, this);

            JMenu menu;
            JMenuItem menuItem;

            menuBar = new JMenuBar();

            StringBuilder accessiblityLabel = new StringBuilder(128);
            if (AssuranceUtils.getPlatform() != Platform.MAC) {
                menu = new JMenu(Application.applicationShortName);
                menu.getAccessibleContext().setAccessibleDescription(accessiblityLabel.append("Actions for ")
                        .append(Application.applicationShortName).append(" application").toString());
                accessiblityLabel.setLength(0);
                menuBar.add(menu);

                menuItem = new JMenuItem(MainWindow.quitApplicationMenuLabel, KeyEvent.VK_Q);
                menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK));
                menuItem.getAccessibleContext().setAccessibleDescription(accessiblityLabel.append("Close the ")
                        .append(Application.applicationShortName).append(" application").toString());
                accessiblityLabel.setLength(0);
                menuItem.addActionListener(this);
                menuItem.setActionCommand(AssuranceActions.quitApplicationAction);
                menu.add(menuItem);

                menu.addSeparator();

                menuItem = new JMenuItem(MainWindow.aboutApplicationMenuLabel);
                menuItem.getAccessibleContext().setAccessibleDescription(
                        accessiblityLabel.append("Display information about this version of ")
                                .append(Application.applicationShortName).append(".").toString());
                accessiblityLabel.setLength(0);
                menuItem.addActionListener(this);
                menuItem.setActionCommand(AssuranceActions.aboutApplicationAction);
                menu.add(menuItem);
            }

            menu = new JMenu("Scan");
            menu.setMnemonic(KeyEvent.VK_S);
            menu.getAccessibleContext().setAccessibleDescription("Actions for file scans");
            menuBar.add(menu);

            menuItem = new JMenuItem(MainWindow.newScanDefinitonMenuLabel, KeyEvent.VK_N);
            menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
            menuItem.getAccessibleContext().setAccessibleDescription("Create a new scan definition");
            menuItem.addActionListener(this.scanLaunchPanel);
            menuItem.setActionCommand(AssuranceActions.newScanDefinitonAction);
            menu.add(menuItem);

            menuItem = new JMenuItem(MainWindow.deleteScanDefinitonMenuLabel, KeyEvent.VK_D);
            menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, ActionEvent.CTRL_MASK));
            menuItem.getAccessibleContext().setAccessibleDescription("Delete the selected scan definition");
            menuItem.addActionListener(this.scanLaunchPanel);
            menuItem.setActionCommand(AssuranceActions.deleteScanDefinitonAction);
            menu.add(menuItem);

            menu.addSeparator();

            menuItem = new JMenuItem(MainWindow.scanMenuLabel, KeyEvent.VK_S);
            menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
            menuItem.getAccessibleContext()
                    .setAccessibleDescription("Launch a scan using the selected scan definition");
            menuItem.addActionListener(this.scanLaunchPanel);
            menuItem.setActionCommand(AssuranceActions.scanAction);
            menu.add(menuItem);

            menuItem = new JMenuItem(MainWindow.scanAndMergeMenuLabel, KeyEvent.VK_M);
            menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, ActionEvent.CTRL_MASK));
            menuItem.getAccessibleContext().setAccessibleDescription(
                    "Launch a scan using the selected scan definition and merge the results");
            menuItem.addActionListener(this.scanLaunchPanel);
            menuItem.setActionCommand(AssuranceActions.scanAndMergeAction);
            menu.add(menuItem);

            menu = new JMenu("Results");
            menu.setMnemonic(KeyEvent.VK_R);
            menu.getAccessibleContext().setAccessibleDescription("Actions for scan results");
            menuBar.add(menu);

            menuItem = new JMenuItem(MainWindow.replaceSourceMenuLabel, KeyEvent.VK_O);
            menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
            menuItem.getAccessibleContext()
                    .setAccessibleDescription("Replace the source file with the target file");
            menuItem.addActionListener(this.resultsPanel.getResultMenuListener());
            menuItem.setActionCommand(AssuranceActions.replaceSourceAction);
            menu.add(menuItem);

            menuItem = new JMenuItem(MainWindow.replaceTargetMenuLabel, KeyEvent.VK_T);
            menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, ActionEvent.CTRL_MASK));
            menuItem.getAccessibleContext()
                    .setAccessibleDescription("Replace the target file with the source file");
            menuItem.addActionListener(this.resultsPanel.getResultMenuListener());
            menuItem.setActionCommand(AssuranceActions.replaceTargetAction);
            menu.add(menuItem);

            menu.addSeparator();

            menuItem = new JMenuItem(MainWindow.sourceAttributesMenuLabel);
            menuItem.getAccessibleContext().setAccessibleDescription("View the source file attributes");
            menuItem.addActionListener(this.resultsPanel.getResultMenuListener());
            menuItem.setActionCommand(AssuranceActions.sourceAttributesAction);
            menu.add(menuItem);

            menuItem = new JMenuItem(MainWindow.targetAttributesMenuLabel);
            menuItem.getAccessibleContext().setAccessibleDescription("View the target file attributes");
            menuItem.addActionListener(this.resultsPanel.getResultMenuListener());
            menuItem.setActionCommand(AssuranceActions.targetAttributesAction);
            menu.add(menuItem);

            menu = new JMenu("View");
            menu.setMnemonic(KeyEvent.VK_V);
            menu.getAccessibleContext().setAccessibleDescription(
                    accessiblityLabel.append("Views within ").append(Application.applicationShortName).toString());
            accessiblityLabel.setLength(0);
            menuBar.add(menu);

            ButtonGroup group = new ButtonGroup();

            this.viewScanMenuItem = new JRadioButtonMenuItem(MainWindow.viewScanMenuLabel);
            this.viewScanMenuItem.addActionListener(this);
            this.viewScanMenuItem.setActionCommand(AssuranceActions.viewScanAction);
            this.viewScanMenuItem.setSelected(true);
            group.add(this.viewScanMenuItem);
            menu.add(this.viewScanMenuItem);

            this.viewHistoryMenuItem = new JRadioButtonMenuItem(MainWindow.viewHistoryMenuLabel);
            this.viewHistoryMenuItem.addActionListener(this);
            this.viewHistoryMenuItem.setActionCommand(AssuranceActions.viewHistoryAction);
            this.viewHistoryMenuItem.setSelected(true);
            group.add(this.viewHistoryMenuItem);
            menu.add(this.viewHistoryMenuItem);

            if (AssuranceUtils.getPlatform() != Platform.MAC) {
                menu = new JMenu("Tools");
                menu.getAccessibleContext()
                        .setAccessibleDescription(accessiblityLabel.append("Additional actions for ")
                                .append(Application.applicationShortName).append(" application").toString());
                accessiblityLabel.setLength(0);
                menuBar.add(menu);

                menuItem = new JMenuItem(MainWindow.settingsMenuLabel, KeyEvent.VK_COMMA);
                menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_COMMA, ActionEvent.CTRL_MASK));
                menuItem.getAccessibleContext()
                        .setAccessibleDescription(accessiblityLabel.append("Change settings for the ")
                                .append(Application.applicationShortName).append(" application").toString());
                accessiblityLabel.setLength(0);
                menuItem.addActionListener(this);
                menuItem.setActionCommand(AssuranceActions.displaySettingsAction);
                menu.add(menuItem);
            }

            this.setJMenuBar(menuBar);

            this.initialized = true;
        }
    }

    public void display() {
        this.initializeComponent();

        this.pack();
        this.setVisible(true);

        this.setMenuState(this.scanMenuIndex, false);
        this.setMenuState(this.resultsMenuIndex, false);

        this.applicationDelegate.loadApplicationInitializationState();
    }

    public void notify(IAssuranceEvent event) {
        if (event instanceof ScanStartedEvent) {
            this.topArea.setSelectedIndex(0);

            this.topArea.setEnabled(false);

            this.setMenuState(this.scanMenuIndex, false, true);
            this.setMenuState(this.resultsMenuIndex, false, true);
            this.setMenuState(this.viewMenuIndex, false, true);
            this.setMenuState(this.toolsMenuIndex, false, true);
        }

        if (event instanceof ApplicationConfigurationLoadedEvent) {
            ApplicationConfiguration config = ((ApplicationConfigurationLoadedEvent) event)
                    .getApplicationConfiguration();
            this.setApplicationCongifuration(config);
        }

        if (event instanceof ApplicationConfigurationSavedEvent) {
            this.setApplicationCongifuration((ApplicationConfiguration) event.getSource());
        }

        if (event instanceof ScanCompletedEvent) {
            this.topArea.setEnabled(true);

            // NOTE:  I don't like how Swing manages menus.  This feels like
            // it could be done better.
            this.setMenuState(this.scanMenuIndex, true, true);
            this.setMenuState(this.viewMenuIndex, true, true);
            this.setMenuState(this.toolsMenuIndex, true, true);

            this.applicationDelegate.loadScanDefinitions();
        }

        if ((event instanceof SetScanDefinitionMenuStateEvent) || (event instanceof SetScanResultsMenuStateEvent)) {
            Boolean enabled = (Boolean) event.getSource();
            int menuIndex = this.scanMenuIndex;
            if (event instanceof SetScanResultsMenuStateEvent) {
                menuIndex = this.resultsMenuIndex;
            }
            this.setMenuState(menuIndex, enabled);
            enabled = null;
        }
    }

    private void setMenuState(int menuIndex, Boolean enabled) {
        this.setMenuState(menuIndex, enabled, false);
    }

    private void setMenuState(int menuIndex, Boolean enabled, Boolean ignoreExceptions) {
        JMenu relevantMenu = this.menuBar.getMenu(menuIndex);

        if (relevantMenu != null) {
            for (int i = 0; i < relevantMenu.getItemCount(); i++) {
                JMenuItem item = relevantMenu.getItem(i);
                // NOTE: I don't like how Swing manages menus.
                if (item != null) {
                    if (ignoreExceptions
                            || (!AssuranceActions.newScanDefinitonAction.equals(item.getActionCommand()))) {
                        item.setEnabled(enabled);
                    }
                }
            }
        }
    }

    public void actionPerformed(ActionEvent e) {
        if (AssuranceActions.viewScanAction.equals(e.getActionCommand())) {
            this.topArea.setSelectedIndex(0);
            this.setMenuState(this.resultsMenuIndex, false);
        }
        if (AssuranceActions.viewHistoryAction.equals(e.getActionCommand())) {
            this.topArea.setSelectedIndex(1);
            this.setMenuState(this.scanMenuIndex, false);
        }
        if (AssuranceActions.quitApplicationAction.equals(e.getActionCommand())) {
            this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
        }
        if (AssuranceActions.aboutApplicationAction.equals(e.getActionCommand())) {
            this.displayAboutDialog();
        }
        if (AssuranceActions.displaySettingsAction.equals(e.getActionCommand())) {
            this.displayPreferencesDialog();
        }
    }

    public void displayAboutDialog() {
        JDialog aboutApplicationDialog = dialogFactory.createAboutDialogInstance(this,
                ModalityType.APPLICATION_MODAL);
        aboutApplicationDialog.setVisible(true);
    }

    public void displayPreferencesDialog() {
        JDialog settingsDialog = dialogFactory.createSettingsDialogInstance(this, ModalityType.APPLICATION_MODAL,
                this.applicationConfiguration);
        settingsDialog.setVisible(true);
    }

    private void setApplicationCongifuration(ApplicationConfiguration config) {
        this.applicationConfiguration = config;
    }

    public ApplicationConfiguration getApplicationCongifuration() {
        return this.applicationConfiguration;
    }
}