X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=Addressbook%2Fsrc%2Forg%2Fmxchange%2Faddressbook%2Fclient%2Fgui%2FAddressbookFrame.java;h=2c9494ba812137d68af8c272ef71db5380a245dc;hb=b584ed016789504e50546d3b43e2b202ff823fba;hp=1a629c03fffe1ab7d50bf5594f61a5de0f19f4be;hpb=27f135983830bf9fc71b909db6c0fb97c618fccc;p=addressbook-swing.git diff --git a/Addressbook/src/org/mxchange/addressbook/client/gui/AddressbookFrame.java b/Addressbook/src/org/mxchange/addressbook/client/gui/AddressbookFrame.java index 1a629c0..2c9494b 100644 --- a/Addressbook/src/org/mxchange/addressbook/client/gui/AddressbookFrame.java +++ b/Addressbook/src/org/mxchange/addressbook/client/gui/AddressbookFrame.java @@ -16,144 +16,498 @@ */ package org.mxchange.addressbook.client.gui; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.mxchange.addressbook.application.Application; +import org.mxchange.addressbook.model.gender.GenderComboBoxModel; +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.text.MessageFormat; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.border.TitledBorder; +import javax.swing.table.TableModel; +import org.mxchange.addressbook.BaseFrameworkSystem; +import org.mxchange.addressbook.application.AddressbookApplication; import org.mxchange.addressbook.client.Client; -import org.mxchange.addressbook.manager.contact.ManageableContact; +import org.mxchange.addressbook.exceptions.FrameAlreadyInitializedException; +import org.mxchange.addressbook.model.contact.ContactTableModel; /** * * @author Roland Haeder */ -public class AddressbookFrame extends javax.swing.JFrame implements ClientFrame { - /** - * Class' logger - */ - private final Logger LOG; - - /** - * Client instance - */ - private final Client client; - - /** - * Initialize object - */ - { - LOG = LogManager.getLogger(this); - } - - /** - * Creates an instance of this frame with a client instance - * @param client - */ - public AddressbookFrame (final Client client) { - // Debug line - this.getLogger().debug("Initializing Swing frame ..."); - - // Init components - initComponents(); - - // Set client here - this.client = client; - } - - @Override - public Application getApplication () { - throw new UnsupportedOperationException("Not implemented."); - } - - @Override - public final Client getClient () { - return this.client; - } - - @Override - public ManageableContact getContactManager () { - throw new UnsupportedOperationException("Not implemented."); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings ("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 400, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 300, Short.MAX_VALUE) - ); - - pack(); - }// //GEN-END:initComponents - - /** - * Initializes the frame - */ - @Override - public void initFrame (final Client client) { - /* - * Set the Nimbus look and feel - */ - // - /* - * If Nimbus (introduced in Java SE 6) is not available, stay with the - * default look and feel. For details see - * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html - */ - try { - for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { - if ("Nimbus".equals(info.getName())) { - javax.swing.UIManager.setLookAndFeel(info.getClassName()); - break; +public class AddressbookFrame extends BaseFrameworkSystem implements ClientFrame { + + /** + * Own instance + */ + private static ClientFrame self; + + /** + * Singelton getter for this frame instance. + * + * @param client Client instance + * @return Returns a singelton instance of this frame + */ + public static final ClientFrame getSelfInstance (final Client client) { + // Is it set? + if (!(self instanceof ClientFrame)) { + // Create new instance + self = new AddressbookFrame(client); + } + + // Return instance + return self; + } + + /** + * Dialog box "add contact" + */ + private JDialog addContact; + + /** + * Frame instance for "add own data" + */ + private JMenuItem addOwnItem; + + /** + * Instance to table model + */ + private TableModel dataModel; + + /** + * Table instance + */ + private JTable dataTable; + + /** + * Frame instance for "edit own data" + */ + private JMenuItem editOwnItem; + + /** + * Frame instance + */ + private final JFrame frame; + + /** + * Whether this frame has been initialized + */ + private boolean isInitialized; + + /** + * Status label needs to be updated + */ + private JLabel statusLabel; + + /** + * Creates an instance of this frame with a client instance + * + * @param client + */ + private AddressbookFrame (final Client client) { + // Debug line + this.getLogger().trace(MessageFormat.format("client={0}: CALLED!", client)); + + // Set frame instance + this.frame = new JFrame(); + this.frame.setTitle(this.generateFrameTitle("main")); + + // Set client here + this.setClient(client); + } + + /** + * Shutdown this frame + */ + @Override + public void doShutdown () { + // First only show shutdown status + this.updateStatus("shutdown"); + } + + /** + * Setups the frame, do not set isInitialized here + * + * @param client Client instance + */ + @Override + public void setupFrame (final Client client) { + // Debug line + this.getLogger().trace(MessageFormat.format("client={0}: CALLED!", client)); + + // Has the user entered own data? + if (this.getClient().getContactManager().isOwnContactAdded()) { + // Debug message + this.getLogger().debug("Disabling menus: isOwnContactAdded()=false"); + + // Not entered yet, so disable "add" menu + this.addOwnItem.setEnabled(false); + } else { + // Disable "edit" + this.editOwnItem.setEnabled(false); + } + + // Make the frame visible + this.frame.setVisible(true); + + // All done here + this.updateStatus("done"); + } + + /** + * Initalizes this frame. Having initComponents() exposed (publicly + * accessible) means that any other object can initialize components which + * you may not want. + * + * @throws + * org.mxchange.addressbook.exceptions.FrameAlreadyInitializedException If + * this method has been called twice + */ + @Override + public void init () throws FrameAlreadyInitializedException { + // Debug line + this.getLogger().trace("CALLED!"); + + // Has this frame been initialized? + if (this.isInitialized()) { + // Throw exception + throw new FrameAlreadyInitializedException(); + } + + // Init components + this.initComponents(); + + // Set flag + this.isInitialized = true; + } + + /** + * Returns field isInitialized. This flag indicates whether this frame has + * been initialized or not. + * + * @return Field isInitialized + */ + @Override + public final boolean isInitialized () { + return this.isInitialized; + } + + /** + * Shuts down the application. + */ + @Override + public void shutdownApplication () { + // To do this, the frame must be initialized + if (!this.isInitialized()) { + // Not initalized, so bad call + this.getLogger().fatal("Bad call of shutdownApplication(). Please report this."); + return; + } + this.getClient().getApplication().doShutdown(); + } + + /** + * Generates a title for borders + * @param key Key part to look for + * @return Human-readable title + */ + private String generateBorderTitle (final String key) { + // Call bundle instance + return this.getBundle().getString(String.format("AddressbookFrame.border.%s.title.text", key)); + } + + /** + * Generates a title for all frames based on given sub title key. If null is + * given, the sub title is not generated. + * + * @param subKey Key for sub title resource + * @return A full application title + */ + private String generateFrameTitle (final String subKey) { + // Base title + String title = AddressbookApplication.printableTitle(); + + // Is key given? + if (subKey != null) { + // Add sub title + title = String.format("%s - %s", title, this.getBundle().getString(String.format("AddressbookFrame.%s.title.text", subKey))); } - } - } catch (final ClassNotFoundException ex) { - this.getLogger().catching(ex); - } catch (final InstantiationException ex) { - this.getLogger().catching(ex); - } catch (final IllegalAccessException ex) { - this.getLogger().catching(ex); - } catch (final javax.swing.UnsupportedLookAndFeelException ex) { - this.getLogger().catching(ex); - } - // - - // Debug line - this.getLogger().debug("Displaying form ..."); - - /* - * Create and display the form - */ - java.awt.EventQueue.invokeLater(new Runnable() { - @Override - public void run () { - new AddressbookFrame(client).setVisible(true); - } - }); - } - - /** - * Getter for logger - * - * @return Logger - */ - protected final Logger getLogger () { - return this.LOG; - } - - // Variables declaration - do not modify//GEN-BEGIN:variables - // End of variables declaration//GEN-END:variables + + // Return it + return title; + } + + /** + * Initializes "add contact" dialog + */ + private void initAddContactDialog () { + // Instance dialog and set title + this.addContact = new JDialog(); + this.addContact.setTitle(this.generateFrameTitle("dialog.addContact")); + this.addContact.setLayout(new GridLayout(4, 1)); + + // Only hide it on close and make it appear in middle of screen + this.addContact.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + this.addContact.setLocationRelativeTo(null); + + // Set always on top and auto-focus + this.addContact.setAlwaysOnTop(true); + this.addContact.setAutoRequestFocus(true); + + // Initial dimension + this.addContact.setSize(400, 300); + + /* + * Add listener which asks for confirmation, if data has been entered + * but not saved yet. The user may appriciate this ... ;-) + * + * @TODO Unfinished + */ + + // Init 3 panels: + // 1) Panel "name" input boxes + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + + // Set border to titled version + panel.setBorder(new TitledBorder(this.generateBorderTitle("name"))); + + // Add some input boxes for "name" panel + JComboBox gender = new JComboBox<>(new GenderComboBoxModel(this.getClient())); + + // Finally add panel to dialog + this.addContact.add(panel); + + // Only for developing: + /* DEBUG: */ this.addContact.setVisible(true); + } + + /** + * Initialize components + */ + private void initComponents () { + // Debug line + this.getLogger().trace("CALLED!"); + + // Set default close operation + this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + // Register shutdown listener + this.frame.addWindowListener(new WindowAdapter() { + /** + * Invoked when a window has been closed. + */ + @Override + public void windowClosed (final WindowEvent e) { + // Shutdown application cleanly + self.shutdownApplication(); + } + + /** + * Invoked when a window is in the process of being closed. The + * close operation can be overridden at this point. + */ + @Override + public void windowClosing (final WindowEvent e) { + // Also shutdown cleanly here + self.shutdownApplication(); + } + }); + + // Setup layout manager + this.frame.setLayout(new BorderLayout(2, 2)); + + // Set window size + this.frame.setSize(700, 400); + + // Center window in middle of screen, instead of top-left corner + this.frame.setLocationRelativeTo(null); + + // Init menu system + initMenuSystem(); + + // Init table + initTable(); + + // Init status panel + initStatusPanel(); + + // Init other windows + initOtherDialogs(); + } + + /** + * Initializes the menu system + */ + private void initMenuSystem () { + // Init menu bar, menu and item instances + JMenuBar menuBar = new JMenuBar(); + JMenu menu; + JMenuItem item; + + // Init some menus: + // 1) File menu + menu = new JMenu(this.getBundle().getString("AddressbookFrame.menu.file.text")); + + // Add menu items: + // 1.x) Exit program (should be last) + item = new JMenuItem(this.getBundle().getString("AddressbookFrame.menuItem.exitProgram.text")); + item.setToolTipText(this.getBundle().getString("AddressbookFrame.menuItem.exitProgram.toolTipText")); + + // Add listener to exit menu + item.addActionListener(new ActionListener() { + /** + * If the user has performed this action + * + * @param e An instance of an ActionEvent class + */ + @Override + public void actionPerformed (final ActionEvent e) { + self.shutdownApplication(); + } + }); + + // Add item -> menu + menu.add(item); + + // Add menu -> menu bar + menuBar.add(menu); + + // Init some menus: + // 2) Addressbook menu + menu = new JMenu(this.getBundle().getString("AddressbookFrame.menu.addressbook.text")); + + // 2.1) Add own data + this.addOwnItem = new JMenuItem(this.getBundle().getString("AddressbookFrame.menuItem.addOwnData.text")); + this.addOwnItem.setToolTipText(this.getBundle().getString("AddressbookFrame.menuItem.addOwnData.toolTipText")); + + // Add listener to exit menu + this.addOwnItem.addActionListener(new ActionListener() { + /** + * If the user has performed this action + * + * @param e An instance of an ActionEvent class + */ + @Override + public void actionPerformed (final ActionEvent e) { + self.getClient().getContactManager().doEnterOwnData(); + } + }); + + // Add item -> menu + menu.add(this.addOwnItem); + + // 2.2) Edit own data + this.editOwnItem = new JMenuItem(this.getBundle().getString("AddressbookFrame.menuItem.editOwnData.text")); + this.editOwnItem.setToolTipText(this.getBundle().getString("AddressbookFrame.menuItem.editOwnData.toolTipText")); + + // Add listener to exit menu + this.editOwnItem.addActionListener(new ActionListener() { + /** + * If the user has performed this action + * + * @param e An instance of an ActionEvent class + */ + @Override + public void actionPerformed (final ActionEvent e) { + self.getClient().getContactManager().doChangeOwnData(); + } + }); + + // Add item -> menu + menu.add(this.editOwnItem); + + // Add menu -> menu bar + menuBar.add(menu); + + // Add menu bar -> frame + this.frame.add(menuBar, BorderLayout.NORTH); + } + + /** + * Initialize other dialogs (e.g. "Add contact") + */ + private void initOtherDialogs () { + // Init other windows: + // 1) Add contact + initAddContactDialog(); + } + + /** + * Initializes status panel + */ + private void initStatusPanel () { + // Init status label (which needs to be updated + this.statusLabel = new JLabel(); + this.updateStatus("initializing"); + + // Init status bar in south + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); + panel.add(this.statusLabel); + panel.setBorder(BorderFactory.createEtchedBorder()); + + // Add panel to frame + this.frame.add(panel, BorderLayout.SOUTH); + } + + /** + * Initializes the table which will show all contacts + */ + private void initTable () { + // Instance table model + this.dataModel = new ContactTableModel(this.getClient()); + + // Instance table + this.dataTable = new JTable(this.dataModel); + + // Add mouse listener + this.dataTable.addMouseListener(new MouseAdapter() { + /** + * If the user peformed a click on a cell + * + * @param e Mouse event instance + */ + @Override + public void mouseClicked (final MouseEvent e) { + throw new UnsupportedOperationException("Unfinished."); + } + }); + + // Instance scroll pane + JScrollPane scroller = new JScrollPane(); + + // Add table to scroll pane + scroller.setViewportView(this.dataTable); + scroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + + // Add pane to frame + this.frame.add(scroller, BorderLayout.CENTER); + } + + /** + * Updates status to given type + * + * @param type Status type + */ + private void updateStatus (final String type) { + // Set status message + this.statusLabel.setText(this.getBundle().getString(String.format("AddressbookFrame.statusLabel.%s.text", type))); + } }