Definition:  Commands are executed when the user presses one of the buttons on the button panel.  The buttons are for such functions as “Save”, “Cancel”, “Find”, etc.  This action is executed on the panel which implements the Actionable interface.  Not all buttons are present on every screen, but those which are present, must be able to notify the Actionable panel to perform the action.  In the case of “Save”, for example, each of the input elements on the Actionable panel must save their input to the appropriate place.  The “Cancel” button may do something like ask for confirmation, then close the Window, JFrame, or JDialog.

Issue:  Since there are a large number of input screens, and a corresponding number of button panels, many with the same or similar buttons and commands to be executed, I needed a way to simplify this.  I decided to use the Command Pattern to solve this problem.

Requirements:  Here are the requirements to accomplish this task:

Solution:  My first solution was to create an enum of the buttons/actions needed.  I called this enum “ButtonCommands” and it looked like this:

	public enum ButtonCommands {
		SAVE, EXIT, CANCEL, FIND;
		
		JButton getButton(ActionListener al) {
			JButton button = new JButton(...);
			button.addActionListener(al);
			button.setActionCommand(name());
			...
			return button;
		}
		
		void execute(String name, Actionable a) {
			ButtonCommands command = ButtonCommands.valueOf(name);
			switch(command) {
				case SAVE: { a.save(); break; }
				case EXIT: { a.exit(); break; }
				case CANCEL: { a.cancel(); break; }
				case FIND: { a.find(); break; }
				default:
			}
		}
	}  //  end enum ButtonCommands

There are far more commands than the four shown here, but I just want to get the process across, and not go into every detail.  The constructor for CommandButtons, which is not shown for simplicity, retrieves the internationalized name and saves it, and also computes the size of the largest (widest) button, then applies that size to all future buttons.  The getButton() method creates an actual button, with the appropriate ActionListener, text, and the ActionCommand text.  This is the actual button which is placed on the button panel.  The ActionListener is usually the button panel.  Here is a short look at the button panel:
	public class ButtonPanel implements ActionListener {
		Actionable a;
		
		public ButtonPanel(Actionable a, ButtonCommands[] b) {
			this.a = a;
			// the buttons are laid out on the panel
		}
		
		public void actionPerformed(ActionEvent ae) {
			String cmd = ae.getActionCommand();
			if (ButtonCommands.isCommand(cmd) && a != null) {
				ButtonCommands.execute(cmd, a);
			}
		}
	}  //  end class ButtonPanel

The key here is that the ButtonPanel is the listener for the buttons it contains, then calls the execute() method for the appropriate command based on the ActionCommand name, and the Actionable object provided when the ButtonPanel is created.  The ButtonCommands.isCommand(cmd) method, which was not shown or described above, just looks up the ActionCommand among the values() of ButtonCommands to verify it is a valid ButtonCommands name.  Here is how the input panel looks, in short:
	public class InputPanel extends ActionablePanel {
		ButtonCommands[] buttons = { ButtonCommands.SAVE, ButtonCommands.EXIT};
		ButtonPanel bp = new ButtonPanel(this, buttons);
		JTextField input = new JTextField("data here");
		...
		@Override public void save() {
			//  save the input field data
		}
		@Override public void exit() {
			//  exit
		}
	}  //  end class InputPanel

The InputPanel extends the ActionablePanel which is a plain JPanel which implements Actionable by using a “stub” method for each of the commands.  The “stub” method does nothing, so only the needed commands, in this case SAVE and EXIT, need to be overridden on this InputPanel to do anything.

So here is what happens when the user presses (clicks on) the “Save” button.


I found one thing that bothers me about this method.  That is, it relies on the ActionCommand to execute the correct command.  I decided to try a different approach, which you can see here.