package listener;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.border.EtchedBorder;

public class ListenerInnerClass {
	// Static variable that the whole class can access.
	private static JLabel messageLabel = new JLabel("This is a message label");
	
	public static void main(String[] args) {
		JFrame frame = new JFrame("Demo of Anonymous Inner Class for Listener");
		frame.setLocationRelativeTo(null);
		frame.setLayout(new BorderLayout());
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		placeComponents(frame);
		frame.pack();
		frame.setVisible(true);
	}

	private static void placeComponents(JFrame frame) {
		frame.setLayout(new BorderLayout());

		// Overall Panel
		JPanel framePanel = new JPanel(new BorderLayout());
		framePanel.setAlignmentX(Component.RIGHT_ALIGNMENT);
		
		// Panel for User Input Area
		JPanel dataEntryArea = new JPanel();	
		dataEntryArea.setLayout(new BoxLayout(dataEntryArea, BoxLayout.X_AXIS));
		dataEntryArea.setBorder(new EtchedBorder());
		dataEntryArea.setToolTipText("This is where you enter your information");
		dataEntryArea.setAlignmentX(Component.RIGHT_ALIGNMENT);
		
			// SubPanel for Labels
			Box labelPanel = Box.createVerticalBox();
			
			Box userBox = Box.createHorizontalBox();
			JLabel userLabel = new JLabel("User: ");
			userBox.add(Box.createRigidArea(new Dimension(5,0))); 		// 5 pixel left padding
			userBox.add(Box.createHorizontalGlue());					// to force right alignment
			userBox.add(userLabel);
			
			Box passwordBox = Box.createHorizontalBox();			
			JLabel passwordLabel = new JLabel("Password: ");
			passwordBox.add(Box.createRigidArea(new Dimension(5,0))); 	// 5 pixel left padding
			passwordBox.add(Box.createHorizontalGlue());				// to force right alignment
			passwordBox.add(passwordLabel);
			
			labelPanel.add(Box.createRigidArea(new Dimension(0,5)));	// Add 5 px vertical padding
			labelPanel.add(userBox);
			labelPanel.add(Box.createRigidArea(new Dimension(0,5)));  	// Add 5 px vertical padding
			labelPanel.add(passwordBox);
			labelPanel.add(Box.createRigidArea(new Dimension(0,5)));	// Add 5 px vertical padding
	
			// SubPanel for Text Fields
			Box fieldPanel = Box.createVerticalBox();;
			JTextField userText = new JTextField(20);
			JPasswordField passwordText = new JPasswordField(20);
			fieldPanel.add(Box.createRigidArea(new Dimension(0,5)));	// Add 5 px vertical padding
			fieldPanel.add(userText);
			fieldPanel.add(Box.createRigidArea(new Dimension(0,5)));	// Add 5 px vertical padding
			fieldPanel.add(passwordText);
			fieldPanel.add(Box.createRigidArea(new Dimension(0,5)));	// Add 5 px vertical padding
		
		// Use East and West of userInputArea
		dataEntryArea.add(labelPanel, BorderLayout.WEST);
		dataEntryArea.add(fieldPanel, BorderLayout.CENTER);  // Why the center, rather than EAST?
		
		// *** This becomes the North panel of the frame
		framePanel.add(dataEntryArea, BorderLayout.NORTH);
		
		JCheckBox chkMember = new JCheckBox("Member?");
		JButton loginButton = new JButton("login");
		JButton registerButton = new JButton("register");
		JButton helpButton = new JButton("help");
		JButton rightClickButton = 
				new JButton("right, left or center click me");
		JButton doubleClickButton = new JButton("double click me");
		
		// Boxes are like JPanels with a Box Layout
		Box buttonArea = new Box(BoxLayout.X_AXIS);
		buttonArea.add(Box.createHorizontalGlue());  // Horizontal glue on each side will center!
		buttonArea.add(loginButton);
		buttonArea.add(registerButton);
		buttonArea.add(Box.createRigidArea(new Dimension(30, 0))); // spaces Help button out
		buttonArea.add(helpButton);
		buttonArea.add(rightClickButton);
		buttonArea.add(doubleClickButton);
		buttonArea.add(chkMember);
		buttonArea.add(Box.createHorizontalGlue());  // Horizontal glue on each side will center!
		
		// *** This becomes the South panel of the frame
		framePanel.add(buttonArea, BorderLayout.SOUTH);
		
		// Throw our special message in the East of the frame
		framePanel.add(messageLabel, BorderLayout.EAST);
	
		// Finally add the framePanel to the frame
		frame.add(framePanel);

		/* ******************************************************
		 *  Here is the anonymous inner class.  It is anonymous
		 *  because it does not have a class header.  
		 *  
		 *  Why not name this inner class?
		 *    - We only need to use the inner class once, so
		 *      the class body (i.e., the overloaded method)
		 *      will only appear once.
		 *      
		 *    - If we planned on creating multiple instances
		 *      of an inner class, where we wanted to reuse
		 *      the class body, we should name the class so
		 *      we don't have to always specify the class body.
		 */
		ActionListener myButtonListener = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JButton source = (JButton) e.getSource();
				JOptionPane.showMessageDialog(source, source.getText()
						+ " button has been pressed");
			}
		};
		
		ActionListener myCheckboxActionListener = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JOptionPane.showMessageDialog(
						null, 
						"The source is " + e.getSource(),
						"Action Listener fired",
						JOptionPane.INFORMATION_MESSAGE);	
			}
		};
		
		ItemListener myCheckboxItemListener = new ItemListener() {
			@Override
			public void itemStateChanged(final ItemEvent e) {
/*				JOptionPane.showMessageDialog(
						(Component) e.getSource(), 
						e.getSource().toString(),
						"Item Listener fired",
						JOptionPane.INFORMATION_MESSAGE);	
						*/
/*				JOptionPane.showMessageDialog(
						(Component) e.getSource(), "hi");
						*/
			
//				JOptionPane.showMessageDialog(null, "hi");
				
				// When a JOptionPane runs in the same thread as
				// the JFrame, strange behavior can occur as seen
				// in the commented code above (the ItemListener
				// will fire TWICE, and deselect the JCheckBox that
				// you have selected.
		        javax.swing.SwingUtilities.invokeLater(new Runnable() {
		            @Override
		            public void run() {
		            	// ItemEvent e must be final in the enclosing scope.
		            	JOptionPane.showMessageDialog(
								(Component) e.getSource(), 
								e.getSource(),
								"Item Listener fired",
								JOptionPane.INFORMATION_MESSAGE);	
		            }
		        });	
		        
/*				JOptionPane.showMessageDialog(null, e.getStateChange(),
						"Deselected = 2; Selected = 1",
						JOptionPane.INFORMATION_MESSAGE);	
						*/			
				System.out.println("hello");
			}
		};
		
		MouseListener myDoubleClickMouseListener = new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				// Mouse Events have more information.
				if (e.getClickCount() == 2)
					JOptionPane.showMessageDialog(null, "You clicked twice?"); 	 		 			
			}
		};
		
		MouseListener myClickMouseListener = new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent e) {
				// Mouse Events have more information.
				JOptionPane.showMessageDialog(null, "You pressed " +
					MouseEvent.getMouseModifiersText(e.getModifiersEx()));
			}
		};
		
		/* ****************** end inner class *********************/
		
		loginButton.addActionListener(myButtonListener);
		registerButton.addActionListener(myButtonListener);
		rightClickButton.addMouseListener(myClickMouseListener);
		doubleClickButton.addMouseListener(myDoubleClickMouseListener);
//		chkMember.addActionListener(myCheckboxActionListener);
		chkMember.addItemListener(myCheckboxItemListener);
		
		
		/* This also creates an anonymous inner class 
		 * 
		 * What are the advantages of independent listeners like
		 * this one, versus a consolidated listener?
		 */
		ActionListener helpActionListener = new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// This label was static so every method could access it.
				messageLabel.setText("Help is on the way.");
				messageLabel.setForeground(Color.RED);
			}
		};
		helpButton.addActionListener(helpActionListener);

		
		
	}

}
