// Copyright (c) Keith D Gregory, all rights reserved
package com.kdgregory.example.swingController;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import net.sf.swinglib.layout.CompactGridLayout;


/**
 *  Constructs and manages a login dialog. Demonstrates creation of GUI via
 *  composition rather than inheritance, lazy creation of GUI components,
 *  and use of inner classes for listeners.
 *  <p>
 *  In a real application, the method {@link #doLogin} would invoke an
 *  operation class (see "Asynchronous Operations in Swing"), and potentially
 *  display error messages.
 */
public class LoginDialogController
{
    // these variables are passed into the constructor
    private JFrame _owner;

    // the dialog itself; will be lazily constructed by show()
    private JDialog _dialog;

    // these fields act as the model for this particular controller,
    // as well as the view
    private JTextField _fUsername;
    private JPasswordField _fPassword;

    // for this example, these actions do not need to be stored as fields,
    // since we never touch them after construction; in a real app, we would
    // want to enable/disable actions based on the dialog's state
    private Action _aLogin;
    private Action _aCancel;


    /**
     *  Creates a new instance of the controller; does <em>not</em> create
     *  the actual dialog.
     *
     *  @param  owner   Main frame of the application; dialog will be modal
     *                  within this frame.
     */
    public LoginDialogController(JFrame owner)
    {
        _owner = owner;
    }


//----------------------------------------------------------------------------
//  Public methods
//----------------------------------------------------------------------------

    /**
     *  Displays the dialog, lazily instantiating it. This is a modal dialog;
     *  control will not return until the user either successfully logs in or
     *  cancels.
     */
    public void show()
    {
        if (_dialog == null)
            constructDialog();
        _dialog.setVisible(true);
    }


//----------------------------------------------------------------------------
//  Internals
//----------------------------------------------------------------------------

    private void constructDialog()
    {
        _fUsername = new JTextField(20);
        _fPassword = new JPasswordField(20);

        // CompactGrid layout is from http://sourceforge.net/projects/swinglib/
        JPanel pFields = new JPanel(new CompactGridLayout(2, 6, 12));
        pFields.add(new JLabel("Username:"));
        pFields.add(_fUsername);
        pFields.add(new JLabel("Password:"));
        pFields.add(_fPassword);
        pFields.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));

        _aLogin = new LoginAction();
        _aCancel = new CancelAction();

        JPanel pButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
        pButtons.add(new JButton(_aLogin));
        pButtons.add(new JButton(_aCancel));

        JPanel pContent = new JPanel(new BorderLayout());
        pContent.add(pFields, BorderLayout.CENTER);
        pContent.add(pButtons, BorderLayout.SOUTH);

        _dialog = new JDialog(_owner, "Login", true);
        _dialog.setContentPane(pContent);
        _dialog.pack();
    }


    private class LoginAction
    extends AbstractAction
    {
        private static final long serialVersionUID = 1L;

        public LoginAction()
        {
            super("Login");
        }

        public void actionPerformed(ActionEvent e)
        {
            // in a real app, this action would retrieve the contents
            // of the username and password fields, and invoke an
            // operation that would perform the actual login
            _dialog.dispose();
        }
    }


    private class CancelAction
    extends AbstractAction
    {
        private static final long serialVersionUID = 1L;

        public CancelAction()
        {
            super("Cancel");
        }

        public void actionPerformed(ActionEvent e)
        {
            _dialog.dispose();
        }
    }
}
