/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
/**
 * @author Martin Heinemann martin.heinemann@tudor.lu
 *
 *
 *
 * @version
 * <br>$Log: GECAMedBaseDialog.java,v $
 * <br>Revision 1.36  2014-02-12 12:14:17  ferring
 * <br>resizing options corrected
 * <br>
 * <br>Revision 1.35  2014-01-07 13:19:44  donak
 * <br>Adding initial version of pdf preview dialog
 * <br>Several bug fixes
 * <br>
 * <br>Revision 1.34  2013-11-27 07:57:49  ferring
 * <br>No Exception thrown, when connection is canceled by user
 * <br>
 * <br>Revision 1.33  2013-11-12 09:32:55  ferring
 * <br>apply option value changed
 * <br>
 * <br>Revision 1.32  2013-08-20 10:54:55  ferring
 * <br>constructor now hands over parameters correctly to next constructor
 * <br>
 * <br>Revision 1.31  2013-08-05 08:21:02  ferring
 * <br>Default resizing is NONE
 * <br>
 * <br>Revision 1.30  2013-06-10 08:09:37  ferring
 * <br>Access on button panel from subclasses enabled
 * <br>
 * <br>Revision 1.29  2013-05-21 07:12:07  ferring
 * <br>All GECAMedBaseDialogs will be resizable at first
 * <br>
 * <br>Revision 1.28  2013-03-27 14:16:19  ferring
 * <br>Dialog and Frame positioning improved
 * <br>
 * <br>Revision 1.27  2013-03-22 10:27:59  ferring
 * <br>default resizing option changed to resize location instead of location and size
 * <br>
 * <br>Revision 1.26  2013-03-21 07:18:53  ferring
 * <br>showCenteredDialog will also use the resize option
 * <br>
 * <br>Revision 1.25  2013-03-14 15:30:25  ferring
 * <br>normally unneeded information changed to private
 * <br>
 * <br>Revision 1.24  2013-03-11 07:47:34  ferring
 * <br>GECAMedDialog saves the last location and size by default
 * <br>
 * <br>Revision 1.23  2013-03-08 10:55:27  ferring
 * <br>Implemented resizing options
 * <br>
 * <br>Revision 1.22  2013-03-06 17:04:58  troth
 * <br>Add close Button.
 * <br>
 * <br>Revision 1.21  2013-02-21 15:43:53  ferring
 * <br>GECAMedBaseDialog extended
 * <br>
 * <br>Revision 1.20  2012-05-09 06:50:32  ferring
 * <br>Dialog is now centred on owner
 * <br>
 * <br>Revision 1.19  2012-05-07 12:49:20  ferring
 * <br>FormEditorDialog removed. All occurences replaced with the GECAMedBaseDialogImpl
 * <br>
 * <br>Revision 1.18  2012-05-04 11:43:27  ferring
 * <br>Exception will be thrown, if the button mode is unknown
 * <br>
 * <br>Revision 1.17  2012-04-03 07:40:54  ferring
 * <br>Button mode constants of GECAMedBaseDialog changed
 * <br>
 * <br>Revision 1.16  2011-08-29 07:30:04  ferring
 * <br>apply button added
 * <br>
 * <br>Revision 1.15  2011-08-17 08:32:38  ferring
 * <br>Button usage improved
 * <br>
 * <br>Revision 1.14  2011-03-28 12:33:23  ferring
 * <br>New method added, making it possible to easily change what the actions of the buttons will do.
 * <br>
 * <br>Revision 1.13  2011-02-01 13:14:51  ferring
 * <br>Error messages added for the labo module
 * <br>
 * <br>Revision 1.12  2010-03-30 10:55:46  troth
 * <br>Redesign of the prescription view
 * <br>
 * <br>Revision 1.11  2010-03-23 15:06:16  troth
 * <br>add method addButton to add buttons to the bottom left of the dialog
 * <br>
 * <br>Revision 1.10  2010-02-09 12:07:22  ferring
 * <br>Forms added to PatientTab
 * <br>
 * <br>Revision 1.9  2010-01-25 12:54:24  ferring
 * <br>Yes-No-Cancel-Options added
 * <br>
 * <br>Revision 1.8  2008-12-17 15:23:06  heinemann
 * <br>initial commit after merging of branch new prescription
 * <br>
 * <br>Revision 1.7.2.1  2008-12-15 14:08:21  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.7  2008-11-12 17:16:33  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.6  2008-09-25 09:43:06  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.5  2008-09-15 12:06:45  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.4  2008-08-27 15:34:53  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.3  2008-05-07 14:39:53  heinemann
 * <br>new waitingroom
 * <br>
 * <br>Revision 1.2  2008-04-29 14:17:38  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.1  2008-03-11 17:17:11  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.3  2007-12-17 14:59:59  heinemann
 * <br>plugins and file store and open
 * <br>
 * <br>Revision 1.2  2007-10-16 08:23:27  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.1  2007/08/09 14:10:34  heinemann
 * <br>*** empty log message ***
 * <br>
 *   
 */
package lu.tudor.santec.gecamed.core.gui.widgets;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;

import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.gui.GECAMedIconNames;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.i18n.Translatrix;

import com.jgoodies.forms.builder.ButtonBarBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

/**
 * A basic dialog with ok and cancel button and a header
 * 
 * @author martin.heinemann@tudor.lu
 * 02.08.2007
 * 15:05:06
 *
 *
 * @version
 * <br>$Log: GECAMedBaseDialog.java,v $
 * <br>Revision 1.36  2014-02-12 12:14:17  ferring
 * <br>resizing options corrected
 * <br>
 * <br>Revision 1.35  2014-01-07 13:19:44  donak
 * <br>Adding initial version of pdf preview dialog
 * <br>Several bug fixes
 * <br>
 * <br>Revision 1.34  2013-11-27 07:57:49  ferring
 * <br>No Exception thrown, when connection is canceled by user
 * <br>
 * <br>Revision 1.33  2013-11-12 09:32:55  ferring
 * <br>apply option value changed
 * <br>
 * <br>Revision 1.32  2013-08-20 10:54:55  ferring
 * <br>constructor now hands over parameters correctly to next constructor
 * <br>
 * <br>Revision 1.31  2013-08-05 08:21:02  ferring
 * <br>Default resizing is NONE
 * <br>
 * <br>Revision 1.30  2013-06-10 08:09:37  ferring
 * <br>Access on button panel from subclasses enabled
 * <br>
 * <br>Revision 1.29  2013-05-21 07:12:07  ferring
 * <br>All GECAMedBaseDialogs will be resizable at first
 * <br>
 * <br>Revision 1.28  2013-03-27 14:16:19  ferring
 * <br>Dialog and Frame positioning improved
 * <br>
 * <br>Revision 1.27  2013-03-22 10:27:59  ferring
 * <br>default resizing option changed to resize location instead of location and size
 * <br>
 * <br>Revision 1.26  2013-03-21 07:18:53  ferring
 * <br>showCenteredDialog will also use the resize option
 * <br>
 * <br>Revision 1.25  2013-03-14 15:30:25  ferring
 * <br>normally unneeded information changed to private
 * <br>
 * <br>Revision 1.24  2013-03-11 07:47:34  ferring
 * <br>GECAMedDialog saves the last location and size by default
 * <br>
 * <br>Revision 1.23  2013-03-08 10:55:27  ferring
 * <br>Implemented resizing options
 * <br>
 * <br>Revision 1.22  2013-03-06 17:04:58  troth
 * <br>Add close Button.
 * <br>
 * <br>Revision 1.21  2013-02-21 15:43:53  ferring
 * <br>GECAMedBaseDialog extended
 * <br>
 * <br>Revision 1.20  2012-05-09 06:50:32  ferring
 * <br>Dialog is now centred on owner
 * <br>
 * <br>Revision 1.19  2012-05-07 12:49:20  ferring
 * <br>FormEditorDialog removed. All occurences replaced with the GECAMedBaseDialogImpl
 * <br>
 * <br>Revision 1.18  2012-05-04 11:43:27  ferring
 * <br>Exception will be thrown, if the button mode is unknown
 * <br>
 * <br>Revision 1.17  2012-04-03 07:40:54  ferring
 * <br>Button mode constants of GECAMedBaseDialog changed
 * <br>
 * <br>Revision 1.16  2011-08-29 07:30:04  ferring
 * <br>apply button added
 * <br>
 * <br>Revision 1.15  2011-08-17 08:32:38  ferring
 * <br>Button usage improved
 * <br>
 * <br>Revision 1.14  2011-03-28 12:33:23  ferring
 * <br>New method added, making it possible to easily change what the actions of the buttons will do.
 * <br>
 * <br>Revision 1.13  2011-02-01 13:14:51  ferring
 * <br>Error messages added for the labo module
 * <br>
 * <br>Revision 1.12  2010-03-30 10:55:46  troth
 * <br>Redesign of the prescription view
 * <br>
 * <br>Revision 1.11  2010-03-23 15:06:16  troth
 * <br>add method addButton to add buttons to the bottom left of the dialog
 * <br>
 * <br>Revision 1.10  2010-02-09 12:07:22  ferring
 * <br>Forms added to PatientTab
 * <br>
 * <br>Revision 1.9  2010-01-25 12:54:24  ferring
 * <br>Yes-No-Cancel-Options added
 * <br>
 * <br>Revision 1.8  2008-12-17 15:23:06  heinemann
 * <br>initial commit after merging of branch new prescription
 * <br>
 * <br>Revision 1.7.2.1  2008-12-15 14:08:21  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.7  2008-11-12 17:16:33  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.6  2008-09-25 09:43:06  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.5  2008-09-15 12:06:45  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.4  2008-08-27 15:34:53  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.3  2008-05-07 14:39:53  heinemann
 * <br>new waitingroom
 * <br>
 * <br>Revision 1.2  2008-04-29 14:17:38  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.1  2008-03-11 17:17:11  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.3  2007-12-17 14:59:59  heinemann
 * <br>plugins and file store and open
 * <br>
 * <br>Revision 1.2  2007-10-16 08:23:27  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.1  2007/08/09 14:10:34  heinemann
 * <br>*** empty log message ***
 * <br>
 *   
 */
public abstract class GECAMedBaseDialog extends JDialog implements GECAMedDialogActionListener {

	private static final long serialVersionUID = 1L;
	
	// Options for the ButtonMode
	public static final int NO_BUTTON_MODE 				= 0;
	public static final int OK_BUTTON_MODE 				= 1;
	public static final int OK_CANCEL_BUTTON_MODE 		= 2;
	public static final int YES_NO_BUTTON_MODE 			= 3;
	public static final int YES_NO_CANCEL_BUTTON_MODE 	= 4;
	public static final int OK_CANCEL_APPLY_BUTTON_MODE = 5;
	public static final int CLOSE_BUTTON_MODE 			= 6;
	
	public static final int CLOSED_OPTION 				= JOptionPane.CLOSED_OPTION;
	public static final int OK_OPTION 					= JOptionPane.OK_OPTION;
	public static final int YES_OPTION 					= JOptionPane.YES_OPTION;
	public static final int NO_OPTION 					= JOptionPane.NO_OPTION;
	public static final int CANCEL_OPTION 				= JOptionPane.CANCEL_OPTION;
	public static final int APPLY_OPTION 				= Integer.MAX_VALUE;
	
	// resizing options
	private static final int RESIZING_OPTION_SAVE_X			= 1<<0;
	private static final int RESIZING_OPTION_SAVE_Y			= 1<<1;
	private static final int RESIZING_OPTION_SAVE_WIDTH		= 1<<2;
	private static final int RESIZING_OPTION_SAVE_HEIGHT	= 1<<3;
	private static final int RESIZING_OPTION_LOAD_X			= 1<<4;
	private static final int RESIZING_OPTION_LOAD_Y			= 1<<5;
	private static final int RESIZING_OPTION_LOAD_WIDTH		= 1<<6;
	private static final int RESIZING_OPTION_LOAD_HEIGHT	= 1<<7;
	
	public static final int RESIZING_LOCATION				= RESIZING_OPTION_SAVE_X 
															| RESIZING_OPTION_SAVE_Y 
															| RESIZING_OPTION_LOAD_X 
															| RESIZING_OPTION_LOAD_Y;
	public static final int RESIZING_SIZE					= RESIZING_OPTION_SAVE_WIDTH
															| RESIZING_OPTION_SAVE_HEIGHT
															| RESIZING_OPTION_LOAD_WIDTH
															| RESIZING_OPTION_LOAD_HEIGHT;
	public static final int RESIZING_ALL					= RESIZING_LOCATION | RESIZING_SIZE;
	public static final int RESIZING_NONE					= 0;
	
	
	
	private   String 			headerText = "";
	protected JLabel 			headerLabel;
	protected JButton 			okButton;
	protected JButton 			cancelButton;
	protected JButton 			yesButton;
	protected JButton 			noButton;
	protected JButton 			applyButton;
	protected JButton 			closeButton;
	protected AbstractAction 	cancelAction;
	protected AbstractAction 	okAction;
	protected AbstractAction 	yesAction;
	protected AbstractAction 	noAction;
	protected AbstractAction 	applyAction;
	protected AbstractAction 	closeAction;
	protected KeyStroke 		strokeEnter;
	protected KeyStroke 		strokeEsc;
	protected JPanel 			header;
	protected int 				buttonMode;
	protected boolean 			createOkButton;
	protected boolean 			createCancelButton;
	protected boolean 			createYesButton;
	protected boolean 			createNoButton;
	protected boolean 			createApplyButton;
	protected boolean 			createCloseButton;
	
	// options for store and reloading the location and size of this dialog 
	protected int				resizingOptions	= RESIZING_NONE;
	
	private   boolean 			devMode = false;

	protected JPanel 			actionPanel;
	
	protected int 				buttonOption = -1;
	
	protected GECAMedDialogActionListener dialogActionListener = this;
	
	
	public GECAMedBaseDialog(String title) {
		/* ================================================== */
		this(title, true);
		/* ================================================== */
	}
	
	/**
	 * @param title
	 * @param createButtons create ok and cancel button
	 */
	public GECAMedBaseDialog (String title, boolean createButtons) 
	{
		this(MainFrame.getInstance(), title, createButtons);
	}
	
	
	/**
	 * @param title
	 * @param createButtons create ok and cancel button
	 */
	public GECAMedBaseDialog(JDialog parent, String title, boolean createButtons) {
		/* ================================================== */
		super(parent,
				title,
				true);
		initComponent();
//		if (createButtons) {
			/* ------------------------------------------------------- */
			this.createOkButton = createButtons;
			this.createCancelButton = createButtons;
			// add the ok and cancel button
			initButtonPanel();
			initButtonActions(createButtons);
			/* ------------------------------------------------------- */
//		}
		/* ================================================== */
	}
	
	/**
	 * @param title
	 * @param createButtons create ok and cancel button
	 */
	public GECAMedBaseDialog(JFrame parent, String title, boolean createButtons) {
		/* ================================================== */
		super(parent == null ? MainFrame.getInstance() : parent,
				title,
				true);
		initComponent();
//		if (createButtons) {
			/* ------------------------------------------------------- */
			this.createOkButton = createButtons;
			this.createCancelButton = createButtons;
			// add the ok and cancel button
			initButtonPanel();
			initButtonActions(createButtons);
			/* ------------------------------------------------------- */
//		}
		/* ================================================== */
	}
	
	
	/**
	 * @param title
	 * @param createOkButton
	 * @param createCancelButton
	 */
	public GECAMedBaseDialog(String title, boolean createOkButton, boolean createCancelButton) {
		/* ================================================== */
		this(title, createOkButton, createCancelButton, true);
		/* ================================================== */	
	}
	

	/**
	 * @param title
	 * @param createOkButton
	 * @param createCancelButton
	 * @param initButtonAction add actions to the buttons
	 */
	public GECAMedBaseDialog(String title, boolean createOkButton, boolean createCancelButton, boolean initButtonAction) {
		/* ================================================== */
		super(MainFrame.getInstance(),
				title,
				true);
		initComponent();
		this.createOkButton = createOkButton;
		this.createCancelButton = createCancelButton;
		
			/* ------------------------------------------------------- */
			// add the ok and cancel button
			initButtonPanel();
			
			initButtonActions(initButtonAction);
			
			/* ------------------------------------------------------- */
		
		/* ================================================== */
	}
	
	public GECAMedBaseDialog (JDialog parent, String title, int buttonMode) {
		super(parent, title);
		initBaseDialogWithButtonMode(buttonMode);
	}
	
	public GECAMedBaseDialog (JFrame parent, String title, int buttonMode) {
		super(parent, title);
		initBaseDialogWithButtonMode(buttonMode);
	}
	
	private void initBaseDialogWithButtonMode (int buttonMode) {

		setModal(true);
		initComponent();
		/* ------------------------------------------------------- */
//		if (buttonMode != NO_BUTTON_MODE) {
			// select with buttons shall be added
			setButtonMode(buttonMode);
			// add the selected buttons
			initButtonPanel();
			
			initButtonActions(buttonMode != NO_BUTTON_MODE);
//		}		
		/* ------------------------------------------------------- */
	}
	
	
	/**
	 * Set the text for the header
	 * 
	 * @param headerTitle
	 */
	protected void setHeaderTitle(String headerTitle) {
		/* ================================================== */
		setNoHtmlHeaderTitle("<html>"+headerTitle);
//		this.headerText = headerTitle;
//		headerLabel.setText("<html>"+headerText);
//		headerLabel.updateUI();
		/* ================================================== */
	}
	
	
	protected void setNoHtmlHeaderTitle(String headerTitle) {
		/* ================================================== */
		this.headerText = headerTitle;
		this.headerLabel.setText(headerText);
		this.headerLabel.updateUI();
		/* ================================================== */
	}
	
	
	/**
	 * Replaces the normal JLabels as header with the component of your choice.
	 * The methods setHeaderTitle etc will have no effect anymore.
	 * @param component
	 */
	protected void setHeaderComponent(JComponent component) {
		/* ================================================== */
		// try to remove old label
		/* ------------------------------------------------------- */
		try {
			/* --------------------------------------------- */
			this.header.remove(headerLabel);
			/* --------------------------------------------- */
		} catch (Exception e) {}
		/* ------------------------------------------------------- */
		CellConstraints cc = new CellConstraints();
		header.add(component, cc.xy(2, 2));
		/* ================================================== */
	}
	
	/**
	 * Set the icon for the header
	 * 
	 * @param headerIcon
	 */
	protected void setHeaderIcon(Icon headerIcon) {
		/* ================================================== */
		headerLabel.setIcon(headerIcon);
		headerLabel.updateUI();
		/* ================================================== */
	}
	
	/**
	 * Show the header
	 * 
	 * @param b
	 */
	protected void showHeader(boolean b) {
		/* ================================================== */
		/* ------------------------------------------------------- */
		// header
		this.header = new JPanel(new FormLayout("3dlu, fill:pref:grow, 3dlu" , "3dlu, fill:pref, 3dlu"));
		header.setOpaque(false);
		/* ------------------------------------------------------- */
		this.headerLabel = new JLabel("<html>"+this.headerText);
		headerLabel.setOpaque(true);
		headerLabel.setBackground(Color.WHITE);
		headerLabel.setBorder(BorderFactory.createTitledBorder(""));
		/* ------------------------------------------------------- */
		headerLabel.setVerticalTextPosition(SwingConstants.TOP);
		headerLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
		CellConstraints cc = new CellConstraints();
		header.add(headerLabel, cc.xy(2, 2));
		/* ------------------------------------------------------- */
		
		this.add(header, BorderLayout.NORTH);
		/* ------------------------------------------------------- */
		this.getContentPane().validate();
		/* ================================================== */
	}
	
	/**
	 * Add a panel to the center of the dialog.
	 * 
	 * @param mainPanel
	 */
	public void addMainPanel(JComponent mainPanel) {
		/* ================================================== */
		this.add(mainPanel, BorderLayout.CENTER);
		/* ================================================== */
	}

	/**
	 * Add a button to the bottom left of the dialog.
	 * 
	 * @param action
	 */
	public void addButton(AbstractButton button) {
		/* ================================================== */
		this.actionPanel.add(button);
		/* ================================================== */
	}
	
	/**
	 * 
	 */
	private void initComponent() {
		/* ====================================================== */
//		enableDevMode(true);
		this.setLayout(new BorderLayout());
		this.getContentPane().setBackground(Color.WHITE);
		this.getContentPane().setBackground(GECAMedColors.c_GECAMedBackground);
		/* ------------------------------------------------------- */
		/* ====================================================== */
	}
	
	/**
	 * 
	 */
	private void initButtonPanel() {
		/* ================================================== */
		/* ------------------------------------------------------- */
		// ==========================================================
		// button panel
		// ==========================================================
		this.okButton 		= new JButton();
		this.cancelButton 	= new JButton();
		this.yesButton 		= new JButton();
		this.noButton 		= new JButton();
		this.applyButton 	= new JButton();
		this.closeButton 	= new JButton();
		ButtonBarBuilder bb = new ButtonBarBuilder();
		/* ------------------------------------------------------- */
		
		this.actionPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 3,3));
		this.actionPanel.setOpaque(false);
		
		bb.addGlue();
		bb.addRelatedGap();
		if (createOkButton) {
			bb.addGridded(okButton);
			bb.addRelatedGap();
		}
		if (createYesButton) {
			bb.addGridded(yesButton);
			bb.addRelatedGap();
		}
		if (createNoButton) {
			bb.addGridded(noButton);
			bb.addRelatedGap();
		}
		if (createCancelButton) {
			bb.addGridded(cancelButton);
			bb.addRelatedGap();
		}
		if (createApplyButton) {
			bb.addGridded(applyButton);
			bb.addRelatedGap();
		}
		if(createCloseButton) {
			bb.addGridded(closeButton);
			bb.addRelatedGap();
		}
			
		/* ------------------------------------------------------- */
		bb.getPanel().setOpaque(false);
		/* ------------------------------------------------------- */
		// a panel to make a gap between the dialog border and the buttons
		JPanel gapPanel = new JPanel(new BorderLayout(5,5));
		gapPanel.setOpaque(true);
		gapPanel.setBackground(Color.WHITE);
		gapPanel.add(this.actionPanel, BorderLayout.WEST);
		gapPanel.add(bb.getPanel(), BorderLayout.CENTER);
		gapPanel.add(new JLabel(""), BorderLayout.SOUTH);
		gapPanel.add(new JLabel(""), BorderLayout.EAST);
		gapPanel.add(new JLabel(""), BorderLayout.NORTH);
		/* ------------------------------------------------------- */

		this.add(gapPanel, BorderLayout.SOUTH);
		/* ================================================== */
	}
	
	
	/**
	 * 
	 */
	public void initButtonActions(boolean b) {
		/* ================================================== */
		if (b) {
			this.cancelAction = new AbstractAction(Translatrix.getTranslationString("core.cancel"),
					GECAMedModule.getSmallIcon(GECAMedIconNames.CANCEL)) {
	
				private static final long serialVersionUID = 1L;
	
				public void actionPerformed(ActionEvent e) {
					/* ====================================================== */
					if (dialogActionListener != null)
						dialogActionListener.cancelActionCalled();
					/* ====================================================== */
				}
			};
			/* ------------------------------------------------------- */
			this.okAction = new AbstractAction(Translatrix.getTranslationString("core.ok"),
					GECAMedModule.getSmallIcon(GECAMedIconNames.OK)) {
	
				private static final long serialVersionUID = 1L;
	
				public void actionPerformed(ActionEvent e) {
					/* ====================================================== */
					if (dialogActionListener != null)
						dialogActionListener.okActionCalled();
					/* ====================================================== */
				}
			};
			this.yesAction = new AbstractAction(Translatrix.getTranslationString("core.yes"),
					GECAMedModule.getSmallIcon(GECAMedIconNames.OK)) {
				
				private static final long serialVersionUID = 1L;

				public void actionPerformed(ActionEvent e) {
					/* ====================================================== */
					if (dialogActionListener != null)
						dialogActionListener.yesActionCalled();
					/* ====================================================== */
				}
			};
			this.noAction = new AbstractAction(Translatrix.getTranslationString("core.no"),
					GECAMedModule.getSmallIcon(GECAMedIconNames.NO)) {
				
				private static final long serialVersionUID = 1L;

				public void actionPerformed(ActionEvent e) {
					/* ====================================================== */
					if (dialogActionListener != null)
						dialogActionListener.noActionCalled();
					/* ====================================================== */
				}
			};
			this.applyAction = new AbstractAction(Translatrix.getTranslationString("core.apply"),
					GECAMedModule.getSmallIcon(GECAMedIconNames.OK)) {
				
				private static final long serialVersionUID = 1L;

				public void actionPerformed(ActionEvent e) {
					/* ====================================================== */
					if (dialogActionListener != null)
						dialogActionListener.applyActionCalled();
					/* ====================================================== */
				}
			};
			this.closeAction = new AbstractAction(Translatrix.getTranslationString("core.close"),
					GECAMedModule.getSmallIcon(GECAMedIconNames.CANCEL)) {
	
				private static final long serialVersionUID = 1L;
	
				public void actionPerformed(ActionEvent e) {
					/* ====================================================== */
					if (dialogActionListener != null)
						dialogActionListener.closeActionCalled();
					/* ====================================================== */
				}
			};
			
			this.okButton.setAction(okAction);
			this.cancelButton.setAction(cancelAction);
			this.yesButton.setAction(yesAction);
			this.noButton.setAction(noAction);
			this.applyButton.setAction(applyAction);
			this.closeButton.setAction(closeAction);
			
			this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
			this.addWindowListener(new WindowListener() 
			{
				public void windowClosing(WindowEvent e) 
				{
					if (dialogActionListener != null)
						dialogActionListener.closeActionCalled();
				}
				
				public void windowOpened(WindowEvent e) {}
				public void windowIconified(WindowEvent e) {}
				public void windowDeiconified(WindowEvent e) {}
				public void windowDeactivated(WindowEvent e) {}
				public void windowClosed(WindowEvent e) {}
				public void windowActivated(WindowEvent e) {}
			});
		} else {
			// just set the icon and the text
			okButton.setText(Translatrix.getTranslationString("core.ok"));
			cancelButton.setText(Translatrix.getTranslationString("core.cancel"));
			yesButton.setText(Translatrix.getTranslationString("core.yes"));
			noButton.setText(Translatrix.getTranslationString("core.no"));
			applyButton.setText(Translatrix.getTranslationString("core.apply"));
			closeButton.setText(Translatrix.getTranslationString("core.close"));
			
			okButton.setIcon(GECAMedModule.getSmallIcon(GECAMedIconNames.OK));
			cancelButton.setIcon(GECAMedModule.getSmallIcon(GECAMedIconNames.CANCEL));
			yesButton.setIcon(GECAMedModule.getSmallIcon(GECAMedIconNames.OK));
			noButton.setIcon(GECAMedModule.getSmallIcon(GECAMedIconNames.NO));
			applyButton.setIcon(GECAMedModule.getSmallIcon(GECAMedIconNames.OK));
			closeButton.setIcon(GECAMedModule.getSmallIcon(GECAMedIconNames.CANCEL));
		}
		// =================================================================


		// =================================================================
		// define dialog wide key mappings
		// =================================================================
		// ESC will close the dialog
		this.strokeEsc = KeyStroke.getKeyStroke("ESCAPE");
		enableCancelKeyMapping(true);
		/* ------------------------------------------------------- */
		// Enter will close the dialog and confirm something
		this.strokeEnter = KeyStroke.getKeyStroke("ENTER");
		enableOkKeyMapping(true);
		/* ================================================== */
	}
	
	
	/**
	 * Enabled the okButton action when ENTER is pressed
	 * 
	 * @param b
	 */
	protected void enableOkKeyMapping(boolean b) {
		/* ================================================== */
		if (b) {
			/* ------------------------------------------------------- */
			// add keymapping
			((JPanel) this.getContentPane()).getInputMap(
					JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
					.put(this.strokeEnter, "ok");
			((JPanel) this.getContentPane()).getActionMap().put("ok", okAction);
			/* ------------------------------------------------------- */
		} else {
			/* ------------------------------------------------------- */
			// remove keymapping
			((JPanel) this.getContentPane()).getInputMap(
					JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
					.remove(this.strokeEnter);
			((JPanel) this.getContentPane()).getActionMap().remove("ok");
			/* ------------------------------------------------------- */
		}
		/* ================================================== */
	}
	
	/**
	 * Enabled the cancelButton action when ESC is pressed
	 * 
	 * @param b
	 */
	protected void enableCancelKeyMapping(boolean b) {
		/* ================================================== */
		if (b) {
			/* ------------------------------------------------------- */
			// add keymapping
			((JPanel) this.getContentPane()).getInputMap(
					JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
					.put(this.strokeEsc, "cancel");
			((JPanel) this.getContentPane()).getActionMap().put("cancel", cancelAction);
			/* ------------------------------------------------------- */
		} else {
			/* ------------------------------------------------------- */
			// remove keymapping
			((JPanel) this.getContentPane()).getInputMap(
					JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
					.remove(this.strokeEsc);
			((JPanel) this.getContentPane()).getActionMap().remove("cancel");
			/* ------------------------------------------------------- */
		}
		/* ================================================== */
	}
	
	
	/**
	 * enables dev mode
	 * 
	 * @param b
	 */
	public void enableDevMode(boolean b) {
		/* ================================================== */
		this.devMode = b;
		if (devMode) {
			/* ------------------------------------------------------- */
			this.addComponentListener(new ComponentListener() {

				public void componentHidden(ComponentEvent e) {
					/* ====================================================== */
					// TODO Auto-generated method stub
					/* ====================================================== */
				}

				public void componentMoved(ComponentEvent e) {
					/* ====================================================== */
					System.out.println("Dialog position: [" + GECAMedBaseDialog.this.getX()
							+", "+GECAMedBaseDialog.this.getY()+"]");
					/* ====================================================== */
				}

				public void componentResized(ComponentEvent e) {
					/* ====================================================== */
					System.out.println("Dialog size: " + GECAMedBaseDialog.this.getSize().width+"x"+
							GECAMedBaseDialog.this.getSize().height);
					/* ====================================================== */
				}

				public void componentShown(ComponentEvent e) {
					/* ====================================================== */
					System.out.println("Dialog position: [" + GECAMedBaseDialog.this.getX()
							+", "+GECAMedBaseDialog.this.getY()+"]");
					System.out.println("Dialog size: " + GECAMedBaseDialog.this.getSize().width+"x"+
							GECAMedBaseDialog.this.getSize().height);
					/* ====================================================== */
				}
				
			});
			/* ------------------------------------------------------- */
		}
		/* ================================================== */
	}
	
	/**
	 * sets the create-button values to true or false, depending on the chosen mode
	 * @param mode
	 */
	public void setButtonMode (int mode) {
		buttonMode = mode;
		// reset buttons
		createOkButton 		= false;
		createCancelButton 	= false;
		createYesButton 	= false;
		createNoButton 		= false;
		createApplyButton 	= false;
		createCloseButton 	= false;
		
		// activate buttons depending on case
		switch (mode) {
		case NO_BUTTON_MODE:
			break;
		case OK_CANCEL_APPLY_BUTTON_MODE:
			createApplyButton = true;
		case OK_CANCEL_BUTTON_MODE:
			createCancelButton = true;
		case OK_BUTTON_MODE:
			createOkButton = true;
			break;
		case YES_NO_CANCEL_BUTTON_MODE:
			createCancelButton = true;
		case YES_NO_BUTTON_MODE:
			createYesButton = true;
			createNoButton = true;
			break;
		case CLOSE_BUTTON_MODE:
			createCloseButton = true;
			break;
		default:
			throw new RuntimeException("Unknown button mode \""+mode+"\" set for GECAMedBaseDialog.");
		}
	}
	
	
	public JButton getOKButton ()
	{
		return okButton;
	}
	
	
	public JButton getYesButton ()
	{
		return yesButton;
	}
	
	
	public JButton getNoButton ()
	{
		return noButton;
	}
	
	
	public JButton getCancelButton ()
	{
		return cancelButton;
	}
	
	
	public JButton getApplyButton ()
	{
		return applyButton;
	}
	
	public JButton getCloseButton ()
	{
		return closeButton;
	}
	
	
	public void setDialogActionListener (GECAMedDialogActionListener l)
	{
		dialogActionListener = l;
	}
	
	public int getButtonOption ()
	{
		return this.buttonOption;
	}
	
	public boolean dialogConfirmed ()
	{
		return buttonOption == OK_OPTION; // || buttonOption == YES_OPTION -> YES & OK are both == 0
	}

	public void yesActionCalled() 
	{
		buttonOption = YES_OPTION;
		setVisible(false);
	}
	
	public void okActionCalled() 
	{
		buttonOption = OK_OPTION;
		setVisible(false);
	}
	
	public void noActionCalled() 
	{
		buttonOption = NO_OPTION;
		setVisible(false);
	}
	
	public void closeActionCalled() 
	{
		buttonOption = CLOSED_OPTION;
		setVisible(false);
	}
	
	public void cancelActionCalled() 
	{
		buttonOption = CANCEL_OPTION;
		setVisible(false);
	}
	
	public void applyActionCalled() 
	{
		buttonOption = APPLY_OPTION;
//		setVisible(false);
	}
	
	public void prepareToShowUp ()
	{
		buttonOption	= -1;
	}
	
	
	public int showCenteredDialog ()
	{
		loadResizeValues();	// this will keep only the size, as the location is overwritten by centerWindowOnOwner();
		centerWindowOnOwner();
		prepareToShowUp();
		setVisible(true);
		
		return getButtonOption();
	}
	
	
	public void centerWindowOnOwner () 
	{
		Window owner = getOwner();
		
		setLocation(owner.getX() + owner.getWidth()  / 2 - this.getWidth()  / 2, 
					owner.getY() + owner.getHeight() / 2 - this.getHeight() / 2);
	}
	
	
	public static Window getParentWindow (Component c)
	{
		while (c != null && !(c instanceof Window))
			c = c.getParent();
		
		return (Window) c;
	}
	
	
	@Override
	public void setVisible(boolean b)
	{
		if (b && dialogActionListener != null)
			prepareToShowUp();
		
		if (b)
			loadResizeValues();
		else
			saveResizeValues();
		
		super.setVisible(b);
	}
	
	
	public void saveResizeValues ()
	{
		if (resizingOptions == 0)
			return;
		
		String key	= getClass().getCanonicalName() + "_";
		
		
		if (resizeOptionSet(RESIZING_OPTION_SAVE_X))
			MainFrame.setMachineSetting(key+"X", String.valueOf(getX()));
		if (resizeOptionSet(RESIZING_OPTION_SAVE_Y))
			MainFrame.setMachineSetting(key+"Y", String.valueOf(getY()));
		if (resizeOptionSet(RESIZING_OPTION_LOAD_WIDTH))
			MainFrame.setMachineSetting(key+"WIDTH", String.valueOf(getWidth()));
		if (resizeOptionSet(RESIZING_OPTION_LOAD_HEIGHT))
			MainFrame.setMachineSetting(key+"HEIGHT", String.valueOf(getHeight()));
	}
	
	
	public void loadResizeValues ()
	{
		if (resizingOptions == 0)
			return;
		
		
		MainFrame.adjustWindow(this, 
				restoreResizingValue("X"), 
				restoreResizingValue("Y"), 
				restoreResizingValue("WIDTH"), 
				restoreResizingValue("HEIGHT"));
	}
	
	
	public void saveAndRestoreSize ()
	{
		resizingOptions	= RESIZING_SIZE;
	}
	
	
	public void saveAndRestoreLocation ()
	{
		resizingOptions = RESIZING_LOCATION;
	}
	
	
	public void saveAndRestoreSizeAndLocation ()
	{
		resizingOptions = RESIZING_ALL;
	}
	
	
	public void setResizingOptions (int option)
	{
		this.resizingOptions	= option;
	}
	
	
	protected void storeResizingValue (String keyEnding, int value)
	{
		MainFrame.setMachineSetting(getClass().getCanonicalName() + "_" + keyEnding, 
				String.valueOf(value));
	}
	
	
	private Integer restoreResizingValue (String keyEnding)
	{
		try
		{
			String value	= MainFrame.getMachineSetting(getClass().getCanonicalName() + "_" + keyEnding);
			if (value == null) 
				return null;
			else
				return Integer.valueOf(value);
		}
		catch (NumberFormatException e)
		{
			return null;
		}
	}
	
	
	private boolean resizeOptionSet (int option)
	{
		return (resizingOptions & option) == option;
	}
	
	
	/**
	 * After adding the resize options, all dialogs shell be resizable 
	 * in order to set them to the correct size, if a dialog was sized
	 * incorrect.<br>
	 * For those dialog that really not shell be resizable, you can use
	 * this method.
	 * @param resizable Defines whether the dialog is resizable or not.
	 */
	public void setGECAMedDialogResizable (boolean resizable)
	{
		super.setResizable(resizable);
	}
	
	
	/**
	 * Use <method>setGECAMedDialogResizable(boolean)</method> instead.
	 */
	@Override
	@Deprecated
	public void setResizable(boolean resizable)
	{
		super.setResizable(true);
	}
	
	
	
	public static void main(String[] args) throws InterruptedException
	{
//		int width	= 0;
//		int height	= 0;
//		GraphicsDevice[]	devices	= GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
//		for (GraphicsDevice d : devices)
//		{
//			width	+= d.getDisplayMode().getWidth();
//			if (d.getDisplayMode().getHeight() > height)
//				height	= d.getDisplayMode().getHeight();
//		}
//		Rectangle r = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
//		System.out.println(r);
//		System.out.println("("+r.x+":"+r.y+","+r.width+":"+r.height+")");
		
//		while (true)
//		{
//			Thread.sleep(1000);
//			System.out.println(MouseInfo.getPointerInfo().getLocation());
//		}
	}
}
