package lu.tudor.santec.gecamed.formeditor.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.ListSelectionModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.CaretEvent;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.text.JTextComponent;

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.IconFetcher;
import lu.tudor.santec.gecamed.core.gui.utils.GradientFactory;
import lu.tudor.santec.gecamed.core.gui.widgets.FileChooserPreview;
import lu.tudor.santec.gecamed.core.gui.widgets.NamedComponent;
import lu.tudor.santec.gecamed.formeditor.ejb.entity.beans.FormTemplate;
import lu.tudor.santec.gecamed.formeditor.gui.component.BackgroundPanel;
import lu.tudor.santec.gecamed.formeditor.gui.component.EditableComponent;
import lu.tudor.santec.gecamed.formeditor.gui.controller.AbstractListener;
import lu.tudor.santec.gecamed.formeditor.gui.controller.ComponentSettingsController;
import lu.tudor.santec.gecamed.formeditor.gui.controller.MenuPanelController;
import lu.tudor.santec.gecamed.formeditor.gui.model.FormEditorModel;
import lu.tudor.santec.gecamed.formeditor.gui.model.FormModel;
import lu.tudor.santec.gecamed.formeditor.gui.view.FormEditorSettingsPlugin;
import lu.tudor.santec.gecamed.formeditor.gui.view.FormTemplateListRenderer;
import lu.tudor.santec.gecamed.formeditor.gui.view.TemplateSettingsPanel;
import lu.tudor.santec.gecamed.formeditor.gui.view.editormenu.BorderSettingsPanel;
import lu.tudor.santec.gecamed.formeditor.gui.view.editormenu.ComponentSettingsPanel;
import lu.tudor.santec.gecamed.formeditor.gui.view.editormenu.DummySettingsPanel;
import lu.tudor.santec.gecamed.formeditor.gui.view.editormenu.MenuSettingsPanel;
import lu.tudor.santec.gecamed.patient.gui.PatientButtonPanel;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;


/*$$                ###  $$$                ###
 $$$$$               ###$$$               #####
 $$$$$$              #$#$#$              ######
 $$$$$$            $$$#$#$#$#            ######
 $$$$$$$        $$$$$$$$########        #######
  $$$$$$$     $$$$$$$$$  #########     #######
  $$$$$$$    $$$$$$$$      ########    #######
  $$$$$$$  $$$$$$$$$        #########  #######
    $$$$$ $$$$$$              ######## ######
     $$$$$$$$                   ############
      $$$$$$$$$$$$$          ##############
    $$$$$$$$$$$$$$$$$      #################
    $$$$$$$$$$$$   $$$    ###   ############
   $$$$$$$$$$$$$  $$$$$  ####  #############
   $$$$$$$$$$$$$$$$$$$$$#####################
    $$$$$$$$$$$$$$$$$$$  ###################
     $$$$$$$$$$$$$$$$$    #################
        $$$$$$$$$$            ##########
      $$$$$$$$$$$$$          ############*/
  

//public class FormEditorModule extends JPanel {
/**
 * @version
 * $Log: FormEditorModule.java,v $
 * Revision 1.62  2013-12-27 18:09:26  donak
 * Cleanup of imports
 *
 * Revision 1.61  2013-07-15 06:18:37  ferring
 * logging changed
 *
 * Revision 1.60  2012-11-23 07:38:36  kutscheid
 * test commit
 *
 *
 */
public class FormEditorModule extends GECAMedModule { // only for testing
	/**
	 * @author Jens Ferring 2009-11-16
	 * 
	 *         This class represents the main part of the form-editor. It is
	 *         the model and the view, containing most of the dynamic data
	 *         used by the Formeditor.
	 */
	
	
	/** the logger Object for this class */

	private static Logger logger = Logger.getLogger(FormEditorModule.class.getName());
	
	public static String MODULE_NAME 				= "Form-Editor";
	public static String ROLE_FORMEDITOR_ADMIN 		= MODULE_NAME + "Module.formAdmin";
	public static String PERMISSION_VIEW_FORMEDITOR = MODULE_NAME + "Module.viewEditor";

	// the type is the position in the String array "definition.split(":")"
	
	private static final long serialVersionUID = 1L;
	
	/**
	 * Icons:
	 */
	public static final String FORMEDITOR_ICON 		= "form_editor.png";
	public static final String NEW_ICON 			= "new.png";
	public static final String COLUMN_ICON 			= "column.png";
	public static final String ROW_ICON 			= "row.png";
	public static final String COLUMN_SIZE_ICON 	= "column_size.png";
	public static final String ROW_SIZE_ICON 		= "row_size.png";
//	public static final String KEY_ICON 			= "key.png";
	public static final String SCRIPTEDITOR_ICON 	= "script_editor.png";
	public static final String INITSCRIPT_ICON 		= "init_script.png";
	public static final String LISTENER_METHOD_ICON = "listener_method.png";
	public static final String FUNCTION_ICON 		= "function.png";
	public static final String SAVE_ALL_ICON 		= "save_all.png";
	public static final String REPLACE_ICON 		= "replace.png";
	public static final String REPLACE_ALL_ICON 	= "replace_all.png";
	public static final String VALUE_ICON 			= "value.png";

	public static final int EDIT_PANEL_START_WITH 	= 8;
	public static final int EDIT_PANEL_START_HEIGHT = 15;
	// the default formatting for the columns / rows
	public static final String EDIT_PANEL_DEFAULT_COLSPEC 			= "fill:75px:none";
	public static final String EDIT_PANEL_DEFAULT_ROWSPEC 			= "fill:25px:none";
	public static final String EDIT_PANEL_DEFAULT_BORDER_COLSPEC 	= "center:p:none";
	public static final String EDIT_PANEL_DEFAULT_BORDER_ROWSPEC 	= "center:p:none";

	public static final Color MARK_OK_COLOR 		= new Color(180, 255, 180, 255);
	public static final Color MARK_WRONG_COLOR 		= new Color(255, 180, 180, 255);
	public static final Color BUTTON_PANEL_COLOR 	= new Color(64, 119, 152); 
												// new Color(196, 228, 255);
	
	public static final int LIST_TAB 	= 0;
	public static final int EDITOR_TAB 	= 1;
	public static final int PREVIEW_TAB = 2;
	
	/**
	 * editPanel
	 * 
	 * represents actual editor. It contains the dummy- and
	 * component-elements and the border around them.
	 */
	private JPanel 			mainPanel;

	private FormEditorModel model;
	
//	private JLabel backgroundTitleLabel;
	private JList 			templateList;
	
//	private Vector<ComboBoxElement<Integer>> templateListModel;
	private BackgroundPanel editPnl;
	
	private JScrollPane 	editSP;
	
	// this is the JTabbedPabe, that lies around the editor
	private JTabbedPane 	tabbedPane;
	
	// the layout for the editPanel
	private FormLayout 		editPanelLayout;
	
	// contains all components, including border and dummy elements
	// contains the layout for the columns / rows of the FormLayout of the
	// editPnl
	private ArrayList<String> formLayoutColDefinition = new ArrayList<String>();
	private ArrayList<String> formLayoutRowDefinition = new ArrayList<String>();
	
	private Map<String, EditableComponent> editPanelComponents = new HashMap<String, EditableComponent>();

	/**
	 * MenuPanel:
	 */
	
	/*
	 * editorResizePanel: The panel, that sets the column and row count of
	 * the editor
	 */
	private JSpinner colCountSpnr;
	private JSpinner rowCountSpnr;
	
	private ChangeListener editorSizeListener;
	
//	private JCheckBox dummyOpaqueBox;
	
	// The spinnerModels contain the value for the size of the editPanel
	// (column size and row size)
	private SpinnerNumberModel editPanelColModel = new SpinnerNumberModel(
			EDIT_PANEL_START_WITH, 1, 250, 1);
	private SpinnerNumberModel editPanelRowModel = new SpinnerNumberModel(
			EDIT_PANEL_START_HEIGHT, 1, 250, 1);
	/*
	 * settingsPanel: Depending on which kind of component is selected, the
	 * settings panel shows different options like add, remove, change size
	 */
	private JPanel 					menuPnl;
	private JPanel 					settingsPnl;
	private JPanel 					propertiesPnl;
	private MenuSettingsPanel 		borderSettingsPanel;
	private MenuSettingsPanel 		dummySettingsPanel;
	private MenuSettingsPanel 		componentSettingsPanel;
	private PatientButtonPanel 		globalSettingsButtonPanel;
	private PatientButtonPanel 		layoutButtonPanel;
	private PatientButtonPanel 		settingsButtonPanel;
	private TemplateSettingsPanel 	templateSettingsButtonPanel;
	
	
	/*
	 * formPanel: This panel contains the buttons to show a preview and to
	 * save, load, export and import the form
	 */
	private JButton refreshTemplateListBtn;
	private JButton addTemplateBtn;
	private JButton removeTemplateBtn;
	private JButton removeBackgroundButton;
	private JButton openScriptEditorBtn;
	private JButton importTemplateBtn;
//	private JButton exportTemplateBtn;
	private JButton previewBtn;
	private JButton saveTemplateBtn;
	
	private boolean modified = false;
	private AbstractListener modifiedListener = new AbstractListener() {
		/* ======================================== */
		@Override
		public void actionPerformed(ActionEvent e) {
			setModified(true);
		}
		@Override
		public void keyReleased (KeyEvent e) {
			setModified(true);
		}
		@Override
		public void stateChanged(ChangeEvent e) {
			setModified(true);
		}
		@Override
		public void valueChanged(ListSelectionEvent e) {
			setModified(true);
		}
		@Override
		public void caretUpdate(CaretEvent e) {
			setModified(true);
		}
		/* ======================================== */
	};

	/***************************************************************
	 ***************** CONSTRUCTOR AND INIT-METHOD *****************
	 **************************************************************/

	public FormEditorModule() {
		/* ======================================== */
		super(MODULE_NAME,
				IconFetcher.getScaledIcon(FormEditorModule.class,
						FORMEDITOR_ICON, NORMALPIX),
						BUTTON_PANEL_COLOR /*new Color(242, 236, 63)*/);
		
		Translatrix.addBundle(
				"lu.tudor.santec.gecamed.formeditor.gui.resources.WidgetResources");

		if (isJavaVersionOK()) {
			// initialize the model
			model = new FormEditorModel(this);
			
			componentSettingsPanel 	= new ComponentSettingsPanel(model);
			dummySettingsPanel 		= new DummySettingsPanel(model);
			borderSettingsPanel 	= new BorderSettingsPanel(model);
			
			try 
			{
				FormEditorSettingsPlugin formEditorSettingsPlugin = new FormEditorSettingsPlugin();
				this.addSettingsPlugin(formEditorSettingsPlugin);
			}
			catch (Exception e) 
			{
				logger.log(Level.ERROR, "Couldn't create the form editor settings", e);
			}
		} 
		else 
		{
			this.getModuleButton().setIcon(
					FormEditorModule.getScaledIcon("form_editor_gray.png", NORMALPIX));
			this.getModuleButton().setToolTipText(
					Translatrix.getTranslationString("formeditor.wrongJavaVersion_tooltipp"));
		}
		/* ======================================== */
	}

	/**
	 * Create the main, menu and edit panel used for the initialization, not
	 * for repaint (-> only called in the constructor)
	 */
	protected void initModule() {
		// Content
		mainPanel = new JPanel(new FormLayout(
				"f:50px:g, 2dlu, c:185px, 0dlu", "50px:g"));
		mainPanel.setOpaque(false);
		this.setContentPanel(GradientFactory.makeGradient(mainPanel));
		
		
		if (!isJavaVersionOK()) {
			mainPanel.setLayout(new FormLayout("75px, c:450px:g, 75px", "50px, c:300px:g, 100px"));
			
			JLabel l = new JLabel("<html><font size=6" +
					Translatrix.getTranslationString("formeditor.wrongJavaVersion")
							.replace("$VERSION", System.getProperty("java.version")));
			l.setOpaque(false);
			
			mainPanel.add(l, new CellConstraints(2, 2));
			
			return;
		}
		
		/*
		 * define the menuPanel (in mainPanel)
		 * 
		 * the menu panel contains the editorResizePanel, where you can set
		 * the number of columns and rows of the editor, the settingsPanel,
		 * where you can set the options for the different types of
		 * components and the saveLoadPanel, which contains the buttons to
		 * save, load, import, export and create a preview.
		 */
		menuPnl = new JPanel(new FormLayout("f:p:g", "f:p, f:p, f:p, f:p, 0px:g"));
		menuPnl.setAlignmentX(CENTER_ALIGNMENT);
		menuPnl.setOpaque(false);
		CellConstraints cc = new CellConstraints();
		
		/*
		 * define editorResizePanel (in menuPanel - NORTH)
		 */
		JPanel globalSettingsPnl = new JPanel(new FormLayout(
				"5px, 75px, 5px, 75px, 0px",
				"p, 5px, p, 5px, p, 5px"));
		globalSettingsPnl.setOpaque(false);
//			JLabel l = new JLabel(Translatrix
//					.getTranslationString("formeditor.columns")
//					+ ":");
//			l.setToolTipText(Translatrix
//					.getTranslationString("formeditor.columns")
//					+ ":");
//			editorResizePnl.add(l, new CellConstraints(2, 2));

		final MenuPanelController editorSizeCtrl = new MenuPanelController(model);
//				MenuPanelController.REARRANGE_PANEL);
		editorSizeListener = new ChangeListener() {
			
			public void stateChanged(ChangeEvent e) {
				editorSizeCtrl.changePanelSize((JSpinner)e.getSource(), e.getSource() == colCountSpnr);
			}
		};
		// the spinner buttons define the column- and row-size of the editor
		colCountSpnr = new JSpinner(editPanelColModel);
//		colCountSpnr.addChangeListener(editorSizeCtrl);
//		colCountSpnr.addChangeListener(editorSizeListener);
		
		
		globalSettingsPnl.add(new NamedComponent(
				Translatrix.getTranslationString("formeditor.columns"), 
				colCountSpnr), new CellConstraints(2, 1));
		
		rowCountSpnr = new JSpinner(editPanelRowModel);
//		rowCountSpnr.addChangeListener(editorSizeCtrl);
//		rowCountSpnr.addChangeListener(editorSizeListener);
		
		globalSettingsPnl.add(new NamedComponent(
				Translatrix.getTranslationString("formeditor.rows"),
				rowCountSpnr), new CellConstraints(4, 1));
		
		this.installSpinnerListeners(true);
		
		// BACKGROUND
		final JFileChooser backgroundChooser = new JFileChooser();
		backgroundChooser.setAccessory(new FileChooserPreview(backgroundChooser));
		backgroundChooser.setFileFilter(new FileFilter() {
			/* ---------------------------------------- */
			@Override
			public String getDescription() {
				return ".bmp, .png, .jpg, .gif, .xbm";
			}				
			@Override
			public boolean accept(File f) {
				return f.isDirectory()
						|| f.getName().endsWith(".png")
						|| f.getName().endsWith(".jpg")
						|| f.getName().endsWith(".jpeg")
						|| f.getName().endsWith(".gif")
						|| f.getName().endsWith(".xbm");
			}
			/* ---------------------------------------- */
		});
		
//		this.backgroundTitleLabel = new JLabel(model.getBackgroundTitle());
//		this.backgroundTitleLabel.setOpaque(false);
		
		
		removeBackgroundButton = new JButton(
				GECAMedModule.getSmallIcon(GECAMedIconNames.CANCEL));
		removeBackgroundButton.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent e) {
				backgroundChooser.setSelectedFile(null);
				model.setBackground(null);
				
				setModified(true);
			}
		});
		removeBackgroundButton.setEnabled(false);
		
		JButton openBackgroundChooserButton = new JButton(
				Translatrix.getTranslationString("formeditor.background_pic"));
		openBackgroundChooserButton.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent e) {
				int buttonPressed = backgroundChooser.showOpenDialog(FormEditorModule.this);
				FileInputStream	fis;
				
				if (buttonPressed == JFileChooser.APPROVE_OPTION) {
					File imgFile = backgroundChooser.getSelectedFile();
					if (imgFile == null || !imgFile.exists()) {
						return;
					}
					
					// get the bytes of the image file make a background out of it
					try {
						byte[] background = new byte[(int)imgFile.length()];
						fis	= new FileInputStream(imgFile);
						fis.read(background);
						model.setBackground(background);
						
						setModified(true);
					} catch (FileNotFoundException e1) {
						logger.log(Level.ERROR, e1.getMessage(), e1);
					} catch (IOException e1) {
						logger.log(Level.ERROR, e1.getMessage(), e1);
					}
				}
			}
		});
		
		JPanel backgroundPanel = new JPanel (new FormLayout("32px, 2px, 1px:g", "32px"));
		backgroundPanel.setOpaque(false);
//		backgroundPanel.add(backgroundTitleLabel, cc.xy(1, 1));
		backgroundPanel.add(removeBackgroundButton, cc.xy(1, 1));
		backgroundPanel.add(openBackgroundChooserButton, cc.xy(3, 1));
		
		
		globalSettingsPnl.add(backgroundPanel, cc.xywh(2, 3, 3, 1));
		
		
//		// DUMMY OPAQUE CHECKBOX
//		dummyOpaqueBox = new JCheckBox(new AbstractAction("<html>" + 
//				Translatrix.getTranslationString("make the dummies opaque")) {
//			private static final long serialVersionUID = 1L;
//			
//			public void actionPerformed(ActionEvent e) {
//				setDummiesOpaque(dummyOpaqueBox.isSelected());
//			}
//		});
//		dummyOpaqueBox.setOpaque(false);
//		dummyOpaqueBox.setSelected(false);
//		setDummiesOpaque(false);
//		
//		globalSettingsPnl.add(dummyOpaqueBox, cc.xyw(2, 5, 3));
		
		// editorResizePnl.add(resetEditPanelBtn, new CellConstraints(1, 5,
		// 3, 1));
		// p = new JPanel(new FormLayout("2dlu, 40px, p:g", "40px"));
		// p.add(resetEditPanelBtn, new CellConstraints(2, 1));
//			editorResizePnl.add(resetEditPanelBtn, new CellConstraints(6, 2, 1,
//					3));
		
		templateSettingsButtonPanel = new TemplateSettingsPanel(model,
				Translatrix.getTranslationString("formeditor.template_settings_title"), 
				BUTTON_PANEL_COLOR);
		templateSettingsButtonPanel.setOpaque(false);
		menuPnl.add(templateSettingsButtonPanel, cc.xy(1, 1));
		
		globalSettingsButtonPanel = new PatientButtonPanel(
				Translatrix.getTranslationString("formeditor.global_settings"),
				BUTTON_PANEL_COLOR, globalSettingsPnl);
		globalSettingsButtonPanel.setOpaque(false);
		menuPnl.add(globalSettingsButtonPanel, cc.xy(1, 2));

		/*
		 * define settingsPanel (in menuPanel - CENTER)
		 */
		settingsPnl = new JPanel(new BorderLayout());
		settingsPnl.setOpaque(false);
		settingsButtonPanel = new PatientButtonPanel(
				Translatrix.getTranslationString("formeditor.component_settings"), 
				BUTTON_PANEL_COLOR, settingsPnl);
		settingsButtonPanel.setVisible(false);
		menuPnl.add(settingsButtonPanel, cc.xy(1, 3));
		
		propertiesPnl = new JPanel();
		propertiesPnl.setOpaque(false);
		
		layoutButtonPanel = new PatientButtonPanel(
				Translatrix.getTranslationString("formeditor.layout_settings"),
				BUTTON_PANEL_COLOR, propertiesPnl);
		layoutButtonPanel.setOpaque(false);
		layoutButtonPanel.setVisible(false);
		menuPnl.add(layoutButtonPanel, cc.xy(1, 4));
		
		menuPnl.setOpaque(false);
		
		
		// TitleBar:
		MenuPanelController saveLoadController = new MenuPanelController(
				model);
		
		saveTemplateBtn = new JButton(IconFetcher.getScaledIcon(
				GECAMedIconNames.class, GECAMedIconNames.SAVE, 32));
		saveTemplateBtn.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent e) 
			{
				model.saveTemplate();
			}
		});
		saveTemplateBtn.setToolTipText(Translatrix
				.getTranslationString("formeditor.save_template"));
		
		previewBtn = new JButton(IconFetcher.getScaledIcon(
				GECAMedIconNames.class, GECAMedIconNames.TEMPLATE, 32));
		previewBtn.setActionCommand(MenuPanelController.PREVIEW_BUTTON);
		previewBtn.addActionListener(saveLoadController);
		previewBtn.setToolTipText(Translatrix.getTranslationString("formeditor.show_preview"));
		
		
		// this JButton removes all components from the panel and replaces
		// them by dummy-components
		addTemplateBtn = new JButton(GECAMedModule.getScaledIcon(GECAMedIconNames.ADD, 32));
		addTemplateBtn.setToolTipText(Translatrix.getTranslationString("formeditor.add_template"));
		addTemplateBtn.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent e) 
			{
				String name = model.getValidFormTemplateName("");
				if (name == null) {
					return;
				}
				
				StringBuffer cols = new StringBuffer("f:p:n");
				StringBuffer rows = new StringBuffer("f:p:n");
				
				for (int i = 0; i < 10; i++) 
				{
					cols.append(",f:75px:n");
					rows.append(",f:25px:n");
				}
				
				FormModel formModel = FormModel.getInstance(cols.toString(), rows.toString(), null, 
						new HashMap<String, EditableComponent>(), "", new HashMap<String, String>(), FormModel.TYPE_EDITOR);
				formModel.setName(name);
				formModel.getTemplate().setName(name);
				formModel.getTemplate().setId(null);
				formModel.saveTemplate(null);
				
				model.updateTemplateListModel();
				templateList.setSelectedValue(formModel.getTemplate(), true);
				FormEditorModule.this.validate();
			}
		});
//		addTemplateBtn.setActionCommand(MenuPanelController.RESET_EDIT_PANEL);
		
		removeTemplateBtn = new JButton(new AbstractAction("", 
				GECAMedModule.getScaledIcon(GECAMedIconNames.REMOVE, 32)) {
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				/* ---------------------------------------- */
				if (templateList.getSelectedIndex() >= 0)
					model.deleteSelectedFormTemplate();
				/* ---------------------------------------- */
			}
		});
//		removeTemplateBtn.setEnabled(false);
		removeTemplateBtn.setToolTipText(
				Translatrix.getTranslationString("formeditor.delete_template"));
		
		refreshTemplateListBtn = new JButton(new AbstractAction("", 
				GECAMedModule.getScaledIcon(GECAMedIconNames.RELOAD, 32))
		{
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e)
			{
				model.updateTemplateListModel();
			}
		});
		refreshTemplateListBtn.setToolTipText(Translatrix.getTranslationString(""));
		
		// open-script-editor-button
		ComponentSettingsController btnController = new ComponentSettingsController(
				model);
		openScriptEditorBtn = new JButton(IconFetcher.getScaledIcon(
				FormEditorModule.class, SCRIPTEDITOR_ICON, 32));
		openScriptEditorBtn.addActionListener(btnController);
		openScriptEditorBtn
				.setActionCommand(ComponentSettingsController.OPEN_FORMULA_EDITOR);
		openScriptEditorBtn.setToolTipText(Translatrix
				.getTranslationString("formeditor.open_script-editor"));
		openScriptEditorBtn.setEnabled(true);
		
		// import template button
		importTemplateBtn = new JButton(GECAMedModule.getScaledIcon(GECAMedIconNames.IMPORT, 32));
		importTemplateBtn.addActionListener(new ActionListener() {
			/* ======================================== */
			public void actionPerformed(ActionEvent e) {
				/* ---------------------------------------- */
				model.importTemplate(null);
				
				model.updateTemplateListModel();
				FormEditorModule.this.validate();
				FormEditorModule.this.templateList.validate();
				/* ---------------------------------------- */
			}
			/* ======================================== */
		});
		importTemplateBtn.setToolTipText(
				Translatrix.getTranslationString("formeditor.import_template"));
		
		// add to titleBar
		super.addTopButton(refreshTemplateListBtn);
		super.addTopButton(addTemplateBtn);
		super.addTopButton(removeTemplateBtn);
		super.addTopButton(importTemplateBtn);
		super.addTopButton(openScriptEditorBtn);
		super.addTopButton(previewBtn);
		super.addTopButton(saveTemplateBtn);
		
		// add script- and saveLoad-panel in menu panel SOUTH
//			menuPnl.add(menuSouthPnl, BorderLayout.SOUTH);
		JScrollPane menuScrollPane = new JScrollPane(menuPnl);
		menuScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		menuScrollPane.getViewport().setBackground(
				GECAMedColors.c_GECAMedBackground);
		menuScrollPane.setBorder(BorderFactory.createRaisedBevelBorder());
		mainPanel.add(menuScrollPane, new CellConstraints(3, 1,
				CellConstraints.FILL, CellConstraints.FILL));

		/* **********  define the overviewPanel  ********** */
		JPanel overviewPnl = new JPanel(new FormLayout("10px, f:p:g, 10px", "10px, f:p, 15px, f:p:g, 10px"));
		overviewPnl.setOpaque(false);
		
		JLabel templateListHeadline = new JLabel(
				Translatrix.getTranslationString("formeditor.templateListHeadline"));
		overviewPnl.add(templateListHeadline, cc.xy(2, 2));
		
		// define the template list model:
		
		templateList = new JList(model.getTemplateListModel());
		templateList.addMouseListener(new MouseListener() {
			/* ======================================== */
			public void mouseExited(MouseEvent e) {}
			public void mouseEntered(MouseEvent e) {}
			
			public void mouseReleased(MouseEvent e) {
				showPopup(e);
				}
			public void mousePressed(MouseEvent e) {
				showPopup(e);
				}
			public void mouseClicked(MouseEvent e) {
				templateListClicked(e);
			}
			/* ======================================== */
		});
		
		templateList.addListSelectionListener(new ListSelectionListener() 
		{
			public void valueChanged(ListSelectionEvent e) 
			{
				removeTemplateBtn.setEnabled(templateList.getSelectedIndex() >= 0 
						&& tabbedPane.getSelectedIndex() == LIST_TAB);
				
				if (!e.getValueIsAdjusting()) 
					templateSettingsButtonPanel.rearrange();
			}
		});
		templateList.setCellRenderer(new FormTemplateListRenderer());
		templateList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		
		overviewPnl.add(new JScrollPane(templateList), cc.xy(2, 4));
		
		model.updateTemplateListModel();
		/* **************************************** */
		
		/*
		 * define editPanel (in mainPanel)
		 * 
		 * define the columns and rows of the edit panel
		 */
		String colSpecs = createEditPanelColSpecs(getEditorColumnCount());
		String rowSpecs = createEditPanelRowSpecs(getEditorRowCount());
		editPanelLayout = new FormLayout(colSpecs, rowSpecs);
		editPnl = new BackgroundPanel(editPanelLayout);
		editPnl.setOpaque(false);

		/*
		 * insert dummy labels and border-bar
		 */
//		clearMapAndPanel();
		editSP = new JScrollPane(editPnl);
		editSP.getVerticalScrollBar().setUnitIncrement(16);
		editSP.getViewport().setBackground(
				GECAMedColors.c_GECAMedBackground);
		tabbedPane = new JTabbedPane();
		tabbedPane.setOpaque(false);
		tabbedPane.setBackground(GECAMedColors.c_GECAMedBackground);
		tabbedPane.add(overviewPnl, 0);
		tabbedPane.add(editSP, 1);
		mainPanel.add(tabbedPane, new CellConstraints(1, 1,
				CellConstraints.FILL, CellConstraints.FILL));
		tabbedPane.setTitleAt(0, Translatrix
				.getTranslationString("formeditor.templateOverview"));
//		tabbedPane.setIconAt(0, IconFetcher.getMiniIcon(
//				FormEditorModule.class, ));
		tabbedPane.setTitleAt(1, Translatrix
				.getTranslationString("formeditor.editor"));
		tabbedPane.setIconAt(1, IconFetcher.getMiniIcon(
				FormEditorModule.class, FORMEDITOR_ICON));
		tabbedPane.addChangeListener(saveLoadController);
		
		enableMenuPanel(tabbedPane.getSelectedIndex());
		templateSettingsButtonPanel.rearrange();
		setDummiesOpaque(false);
//		editPnl.validate();
	}
	
	@Override
	public boolean isShown () {
		/* ======================================== */
		return GECAMedModule.userHasPermission(FormEditorModule.PERMISSION_VIEW_FORMEDITOR);
		/* ======================================== */
	}

	/**************************************************
	 ***************** PUBLIC-METHODS *****************
	 *************************************************/

	/**
	 * rearranges the edit panel after sth has been changed
	 */
	public void rearrangeEditPanel() {
		/*
		 * removes all components, to have them added again
		 */
		editPnl.removeAll();
		// the new number of columns and rows
		int x = getEditorColumnCount();
		int y = getEditorRowCount();
		// the old number of columns and rows
		Point oldDimension = new Point(editPanelLayout
				.getColumnCount(), editPanelLayout.getRowCount());
		/*
		 * only for FormLayout - create the specs
		 * 
		 * creates the new column- and row-specifications if an old format
		 * is present it is used, otherwise a new column / row was added,
		 * which gets the default format
		 */
		String colSpecs = createEditPanelColSpecs(x);
		String rowSpecs = createEditPanelRowSpecs(y);
		editPanelLayout = new FormLayout(colSpecs, rowSpecs);
		editPnl.setLayout(editPanelLayout);
		
		/*
		 * test if the editPanel was enlarged -> add new dummy-components to
		 * the new row / column
		 */
		if (oldDimension.x < x) {
			/* ---------------------------------------- */
			for (int col = (int)oldDimension.x + 1; col <= x; col++) {
				model.addComponent(model.createBorderBarElement(col, 1));
				for (int row = 2; row <= y; row++) {
					// editPanelComponents.put(i+":"+j, createDummy(i, j));
					model.addComponent(model.createDummy(col, row));
				}
			}
			
			// fills the lower left corner, which wasn't filled if the row count has increased, too
			if (oldDimension.y < y) {
				for (int row =(int)oldDimension.y + 1; row <= y; row++) {
					model.addComponent(model.createBorderBarElement(1, row));
					for (int col = 2; col <= oldDimension.x; col++) {
						model.addComponent(model.createDummy(col, row));
					}
				}
			}
			/* ---------------------------------------- */
		} else if (oldDimension.y < y) {
			/* ---------------------------------------- */
			for (int row = (int)oldDimension.y + 1; row <= y; row++) {
				model.addComponent(model.createBorderBarElement(1, row));
				for (int col = 2; col <= x; col++) {
					// editPanelComponents.put(j+":"+i, createDummy(j, i));
					model.addComponent(model.createDummy(col, row));
				}
			}
			/* ---------------------------------------- */
		}
		
		
		/*
		 * reenter components
		 * 
		 * all keys are taken and the value of every key is added into the
		 * panel again
		 */
		ArrayList<EditableComponent> toRemove = new ArrayList<EditableComponent>();
		for (EditableComponent ec : editPanelComponents.values()) {
			if (ec == null) {
				continue;
			}
			// the name of the key contains the position in the panel
			// (<<column>>:<<row>>)
			if (ec.getColumn() + ec.getColumnWidth() - 1 > x
					|| ec.getRow() + ec.getRowHeight() - 1 > y) {
				/*
				 * panel has been shrinked, the components aren't in range
				 * anymore the redundant keys are buffered in a list and
				 * will be removed afterwards
				 * 
				 * !! mustn't be removed directly, because it's the item the
				 * iterator currently points at
				 */
				toRemove.add(ec);
			} else {
				/*
				 * enter the components from the map into the panel
				 * 
				 * "false" because, the components mustn't be entered into
				 * the map
				 */
				model.addComponent(ec, false);
			}
		}
		
		/*
		 * the redundant items are removed
		 */
		for (Iterator<EditableComponent> iter = toRemove.iterator(); iter
				.hasNext();) {
			EditableComponent ec = iter.next();
			if (ec.isRealComponent()) {
				model.removeComponent(ec);
			} else {
				editPanelComponents.remove(ec.getName());
			}
		}
		
		setEditPanelBackgroundSettings();
		
		setDummiesOpaque(false);
		setEditPanelBackgroundSettings();
		
		editSP.validate();
		editSP.repaint();
	}

	/**
	 * a new and empty editPanel with the specified size will be created.
	 * The main work is done in the clearMapAndPanel-method, the other
	 * methods are only for clearing the existing and updating the changes.
	 */
	public void resetEditPanelComponents() {
		formLayoutColDefinition.clear();
		formLayoutRowDefinition.clear();
		// model.destructScriptEditor();
		// model.destructFormModel();
		clearMapAndPanel();
		rearrangeEditPanel();
		rearrangeSettingsPanel();
		editPnl.repaint();
		model.setCurrentlySelectedComponent(null);
	}

	/**
	 * deletes the components from the maps, containing the inserted
	 * elements, and editor panel and reenters dummies into map and panel
	 */
	public void clearMapAndPanel() {
		/* ======================================== */
		model.destructScriptEditor();
		model.destructFormModel();
		model.getEditableComponents().clear();
		editPanelComponents.clear();
		editPnl.setBackgroundImage(null);
		
		// creates the border-bar
		addBorderBar();
		
		/*
		 * creates the dummy-elements from the second row / column (because
		 * the first contains a border-element) to the last row / column.
		 */
		for (int i = 2; i <= getEditorColumnCount(); i++) {
			for (int j = 2; j <= getEditorRowCount(); j++) {
				model.addComponent(model.createDummy(i, j));
			}
		}
		/* ======================================== */
	}

	/**
	 * a public access to repaint the editPanel
	 */
	public void repaintEditPanel() {
		editPnl.repaint();
	}

	/**
	 * reloads the settingsPnl with the necessary settings, depending on
	 * which kind of component is currently selected
	 */
	public void rearrangeSettingsPanel() {
		/* ======================================== */
		propertiesPnl.removeAll();
		layoutButtonPanel.setVisible(false);
		
		settingsPnl.removeAll();
		if (model.getCurrentlySelectedComponent() == null) 
		{
			/*
			 * no component selected
			 */
			settingsButtonPanel.setVisible(false);
			return;
		}
		
		MenuSettingsPanel menuSettingsPanel;
		if (model.getCurrentlySelectedComponent().getType() == EditableComponent.BORDER_COMPONENT) 
		{
			/*
			 * currently selected Component is a border
			 */
			menuSettingsPanel = borderSettingsPanel;
		} 
		else if (model.getCurrentlySelectedComponent().getType() == EditableComponent.DUMMY_COMPONENT) 
		{
			/*
			 * currently selected component is a dummy
			 */
			menuSettingsPanel = dummySettingsPanel;
		} 
		else 
		{
			/*
			 * currently selected component is a component
			 */
			menuSettingsPanel = componentSettingsPanel;
			
			JComponent propertyPanel = model.getCurrentlySelectedComponent().getPropertyPanel();
			
			if (propertyPanel != null) 
			{
				layoutButtonPanel.setVisible(true);
				propertiesPnl.add(propertyPanel);
			} 
			else 
				layoutButtonPanel.setVisible(false);
			addModifieListener(propertiesPnl);
			/* ---------------------------------------- */
		}
		menuSettingsPanel.preparePanelForSelectedComponent(model.getCurrentlySelectedComponent());
		settingsPnl.add(menuSettingsPanel, BorderLayout.CENTER);
		
		settingsButtonPanel.setVisible(true);
		
		this.repaint();
		this.validate();
		/* ======================================== */
	}
	
	/**
	 * This method enables or disables the menu panel. That is need, if a
	 * preview tab is clicked. Because, while a preview tab is chosen, the
	 * editor panel cannot be resized, saved, loaded, ...
	 */
	public void enableMenuPanel(int choosenTab) {
		/* ======================================== */
		if (choosenTab == EDITOR_TAB 
				&& model.getFormModel() == null) 
		{
			choosenTab = PREVIEW_TAB;
		}
		
		switch (choosenTab) {
		case LIST_TAB:
			templateSettingsButtonPanel.setVisible(true);
			globalSettingsButtonPanel.setVisible(false);
//			colCountSpnr.setEnabled(false);
//			rowCountSpnr.setEnabled(false);
			saveTemplateBtn.setEnabled(false);
			previewBtn.setEnabled(false);
			refreshTemplateListBtn.setEnabled(true);
			addTemplateBtn.setEnabled(true);
			removeTemplateBtn.setEnabled(templateList.getSelectedIndex() >= 0);
			importTemplateBtn.setEnabled(true);
			openScriptEditorBtn.setEnabled(false);
			super.titlePanel.setColor(BUTTON_PANEL_COLOR);
			break;
			
		case EDITOR_TAB:
			templateSettingsButtonPanel.setVisible(false);
			globalSettingsButtonPanel.setVisible(true);
//			colCountSpnr.setEnabled(false);
//			rowCountSpnr.setEnabled(false);
//			saveTemplateBtn.setEnabled(isModified());
			saveTemplateBtn.setEnabled(true);
			previewBtn.setEnabled(true);
			openScriptEditorBtn.setEnabled(true);
			refreshTemplateListBtn.setEnabled(false);
			addTemplateBtn.setEnabled(false);
			removeTemplateBtn.setEnabled(false);
			importTemplateBtn.setEnabled(false);
			if (isModified()) {
				super.titlePanel.setColor(Color.YELLOW);
			} else {
				super.titlePanel.setColor(Color.WHITE);
			}
			break;
			
		default:
			templateSettingsButtonPanel.setVisible(false);
			globalSettingsButtonPanel.setVisible(false);
			saveTemplateBtn.setEnabled(false);
			previewBtn.setEnabled(false);
			refreshTemplateListBtn.setEnabled(false);
			addTemplateBtn.setEnabled(false);
			removeTemplateBtn.setEnabled(false);
			importTemplateBtn.setEnabled(false);
			openScriptEditorBtn.setEnabled(false);
			super.titlePanel.setColor(BUTTON_PANEL_COLOR);
		}
	}

	/**
	 * these two methods create a String for the editor panel layout, which
	 * contains the default definition for the columns and rows
	 */
	public String createEditPanelColSpecs(int colCount) {
		String colSpecs = "";
		for (int i = 1; i <= colCount; i++) {
			try {
				colSpecs += formLayoutColDefinition.get(i - 1)
						+ (i < colCount ? ", " : "");
			} catch (IndexOutOfBoundsException e) {
				// the list isn't big enough, a new entry will be add
				if (i == 1) {
					// it's a border, that's why the default border format
					// will be add
					formLayoutColDefinition
							.add(EDIT_PANEL_DEFAULT_BORDER_COLSPEC);
				} else {
					formLayoutColDefinition.add(EDIT_PANEL_DEFAULT_COLSPEC);
				}
				colSpecs += formLayoutColDefinition.get(i - 1)
						+ (i < colCount ? ", " : "");
			}
		}
		return colSpecs;
	}

	public String createEditPanelRowSpecs(int rowCount) {
		String rowSpecs = "";
		for (int i = 1; i <= rowCount; i++) {
			try {
				rowSpecs += formLayoutRowDefinition.get(i - 1)
						+ (i < rowCount ? ", " : "");
			} catch (IndexOutOfBoundsException e) {
				// the list isn't big enough, a new entry will be add
				if (i == 1) {
					// it's a border, that's why the default border format
					// will be add
					formLayoutRowDefinition
							.add(EDIT_PANEL_DEFAULT_BORDER_ROWSPEC);
				} else {
					formLayoutRowDefinition.add(EDIT_PANEL_DEFAULT_ROWSPEC);
				}
				rowSpecs += formLayoutRowDefinition.get(i - 1)
						+ (i < rowCount ? ", " : "");
			}
		}
		return rowSpecs;
	}

	/***************************************************
	 ****************** HELP METHODS: ******************
	 **************************************************/

	/**
	 * creates the hole border-bar and adds it to the panel
	 */
	private void addBorderBar() {
		// creates the edge-border-bar-element
		model.addComponent(model.createBorderBarElement(1, 1));
		for (int i = 2; i <= editPanelLayout.getColumnCount(); i++) {
			// creates the horizontal border-bar-elements
			model.addComponent(model.createBorderBarElement(i, 1));
		}
		for (int i = 2; i <= editPanelLayout.getRowCount(); i++) {
			// creates the vertical border-bar-elements
			model.addComponent(model.createBorderBarElement(1, i));
		}
	}
	
	


	/****************************************************
	 **************** GETTER AND SETTER: ****************
	 ***************************************************/

	
	public void setDummiesOpaque (boolean opaque) {
		/* ======================================== */
		for (EditableComponent ec : editPanelComponents.values())  {
			if (ec != null && ec.isDummy()) {
				ec.setOpaque(opaque);
				ec.setComponentOpaq(opaque);
			}
		}
		
		if (editPnl != null) {
			editPnl.validate();
			editPnl.repaint();
		}
		/* ======================================== */
	}
	
//	public boolean getDummiesOpaque () {
//		return dummyOpaqueBox.isSelected();
//	}
	
	
	
	/**
	 * puts a new EditableComponent into the map with all components.
	 * 
	 * @return returns the EditableCOmponent, which was saved under the key
	 *         before
	 */
	public EditableComponent putComponent(String key,
			EditableComponent value) 
	{
//			if (value == null) {
//				EditableComponent oldValue = editPanelComponents.get(key); 
//				editPanelComponents.remove(key);
//				return oldValue;
//			}
		return editPanelComponents.put(key, value);
	}

	/**
	 * Returns the component with this name. Can be dummy, border or
	 * "real"-component
	 * 
	 * @param name
	 * @return
	 */
	public EditableComponent getComponent(String name) {
		return editPanelComponents.get(name);
	}
	
	public Collection<EditableComponent> getEditPanelComponents () {
		return editPanelComponents.values();
	}

	/*
	 * === PANELS ===
	 */
	public BackgroundPanel getEditPanel() {
		return editPnl;
	}

	/**
	 * returns the layout of the editor
	 */
	public FormLayout getEditPanelLayout() {
		return editPanelLayout;
	}

	/**
	 * get and set layouts
	 */
	public String getFormLayoutColDefinition(int index) {
		return formLayoutColDefinition.get(index - 1);
	}

	public void setFormLayoutColDefinition(int index, String value) {
		formLayoutColDefinition.set(index - 1, value);
	}
	
	public void addFormLayoutColDefinition (ColumnSpec spec)
	{
		formLayoutColDefinition.add(spec.toShortString());
	}

	public String getFormLayoutRowDefinition(int index) {
		return formLayoutRowDefinition.get(index - 1);
	}

	public void setFormLayoutRowDefinition(int index, String value) {
		formLayoutRowDefinition.set(index - 1, value);
	}
	
	public void addFormLayoutRowDefinition (RowSpec spec)
	{
		formLayoutRowDefinition.add(spec.toShortString());
	}

	public void setFormLayoutDefinition(String colSpec, String rowSpec) {
		String[] colSpecArray = colSpec.split(",");
		String[] rowSpecArray = rowSpec.split(",");
		formLayoutColDefinition = new ArrayList<String>();
		formLayoutRowDefinition = new ArrayList<String>();
		formLayoutColDefinition.add(EDIT_PANEL_DEFAULT_BORDER_COLSPEC);
		formLayoutRowDefinition.add(EDIT_PANEL_DEFAULT_BORDER_ROWSPEC);
		for (int index = 1; index < colSpecArray.length
				|| index < rowSpecArray.length; index++) {
			if (index < colSpecArray.length) {
				formLayoutColDefinition.add(colSpecArray[index]);
			}
			if (index < rowSpecArray.length) {
				formLayoutRowDefinition.add(rowSpecArray[index]);
			}
		}
	}

	public int getEditorColumnCount() {
		return (Integer) editPanelColModel.getValue() + 1;
	}

	public int getEditorRowCount() {
		return (Integer) editPanelRowModel.getValue() + 1;
	}

	public void setEditorColumnCount(int count) {
		editPanelColModel.setValue(count - 1);
	}

	public void setEditorRowCount(int count) {
		editPanelRowModel.setValue(count - 1);
	}

	public JTabbedPane getTabbedPane() {
		return tabbedPane;
	}
	
	public JList getTemplateList () {
		return templateList;
	}
	
//	public Vector<ComboBoxElement<Integer>> getTemplateListModel () {
//		return templateListModel;
//	}

	/**
	 * Calculates the maximum column width, with the current row height.
	 * Tests when any component comes in range or the end of the editor
	 * panel is reached, so the component cannot be enlarged anymore.
	 * 
	 * @param c
	 *            = the component, the max. width shell be calculated of
	 * @return Returns the maximum width, the component can gain, with the
	 *         current row height
	 */
	public int getMaxWidthWithCurrentHeight(EditableComponent c) {
		int width = c.getColumnWidth();
		int endColumn = c.getEndColumn();
		int endRow = c.getEndRow();
		if (c.isDummy() && c.getColumnSpinnerModel() != null) {
			width = (Integer) c.getColumnSpinnerModel().getValue();
			int height = (Integer) c.getRowSpinnerModel().getValue();
			endColumn = c.getColumn() + width - 1;
			endRow = c.getRow() + height - 1;
		}
		int count = width;
		for (int i = endColumn + 1; i <= getEditorColumnCount(); i++) {
			for (int j = c.getRow(); j <= endRow; j++) {
				EditableComponent tmp = editPanelComponents
						.get(i + ":" + j);
				if (tmp == null || !tmp.isDummy()) {
					return count;
				}
			}
			count++;
		}
		return count;
	}

	/**
	 * Calculates the maximum row Height, with the current column width.
	 * Tests when any component comes in range or the end of the editor
	 * panel is reached, so the component cannot be enlarged anymore.
	 * 
	 * @param c
	 *            = the component, the max. height shell be calculated of
	 * @return Returns the maximum height, the component can gain, with the
	 *         current column width
	 */
	public int getMaxHeightWithCurrentWidth(EditableComponent c) {
		int height = c.getRowHeight();
		int endColumn = c.getEndColumn();
		int endRow = c.getEndRow();
		if (c.isDummy() && c.getRowSpinnerModel() != null) {
			int width = (Integer) c.getColumnSpinnerModel().getValue();
			height = (Integer) c.getRowSpinnerModel().getValue();
			endColumn = c.getColumn() + width - 1;
			endRow = c.getRow() + height - 1;
		}
		int count = height;
		for (int i = endRow + 1; i <= getEditorRowCount(); i++) {
			for (int j = c.getColumn(); j <= endColumn; j++) {
				EditableComponent tmp = editPanelComponents
						.get(j + ":" + i);
				if (tmp == null || !tmp.isDummy()) {
					return count;
				}
			}
			count++;
		}
		return count;
	}
	
	public void updateTitle (String name) {
		/* ======================================== */
		super.titlePanel.setTopic(getTranslatedName() + 
				(name != null && name.length() > 0 
						? " - " + name 
						: ""));
		/* ======================================== */
	}

	public static ImageIcon getIcon(String p_IconName) {
	    return IconFetcher.getIcon(FormEditorModule.class, p_IconName);
	}

	// ---------------------------------------------------------------------------

	public static ImageIcon getScaledIcon(String p_IconName, int size) {
	    return IconFetcher.getScaledIcon(FormEditorModule.class, p_IconName, size);
	}

	// ---------------------------------------------------------------------------

	public static ImageIcon getMiniIcon(String p_IconName) {
	    return IconFetcher.getMiniIcon(FormEditorModule.class, p_IconName);
	}

	// ---------------------------------------------------------------------------

	public static ImageIcon getSmallIcon(String p_IconName) {
	    return IconFetcher.getSmallIcon(FormEditorModule.class, p_IconName);
	}

	// ---------------------------------------------------------------------------

	public static ImageIcon getMediumIcon(String p_IconName) {
	    return IconFetcher.getMediumIcon(FormEditorModule.class, p_IconName);
	}

	// ---------------------------------------------------------------------------

	public static ImageIcon getBigIcon(String p_IconName) {
	    return IconFetcher.getBigIcon(FormEditorModule.class, p_IconName);
	}
	
//	public void setBackgroundTitle (String title) {
//		this.backgroundTitleLabel.setText(title);
//	}

	public void setModified(boolean modified) {
		/* ======================================== */
		if (this.modified != modified) {
			/* ---------------------------------------- */
			// only if smth has changed
			this.modified = modified;
//			saveTemplateBtn.setEnabled(modified);
//			saveTemplateBtn.setEnabled(true);
			if (tabbedPane.getSelectedIndex() == EDITOR_TAB) {
				if (modified) {
					super.titlePanel.setColor(Color.YELLOW);
				} else { 
					super.titlePanel.setColor(Color.WHITE);
				}
			}
			/* ---------------------------------------- */
		}
		/* ======================================== */
	}

	public boolean isModified() {
		return modified;
	}
	
	@Override
	public void setEnabled (boolean enabled) {
		super.setEnabled(enabled);
		
		// TODO: create a new panel and put it into the FormEditorModule-Panel
		
		// Content
		mainPanel = new JPanel(new FormLayout(
				"75px, c:1px:g, 75px", "50px, c:1px:g, 100px"));
		mainPanel.setOpaque(false);
		this.setContentPanel(GradientFactory.makeGradient(mainPanel));
		
		String javaVersion = System.getProperty("java.version");
		
		mainPanel.add(new JLabel("<html><font size=6>" + 
				Translatrix.getTranslationString("formeditor.wrongJavaVersion")
						.replace("$VERSION", javaVersion)), 
				new CellConstraints(2, 2));
	}
	
	public void enableRemoveBackgroundButton (boolean enable) {
		removeBackgroundButton.setEnabled(enable);
	}
	
	public AbstractListener getModifiedListener () {
		return modifiedListener;
	}
	
	public void addModifieListener (Component c) {
		/* ======================================== */
		if (c instanceof Container) 
		{
			for (Component panelComponent : ((Container)c).getComponents()) 
			{
				addModifieListener(panelComponent);
			}
		}
		
		if (c instanceof JSlider){
			((JSlider) c).addChangeListener(getModifiedListener());
		} else if (c instanceof JComboBox) {
			((JComboBox) c).addActionListener(getModifiedListener());
//		} else if (c instanceof JTextArea) {
//			((JTextArea) c).addCaretListener(getModifiedListener());
		} else if (c instanceof JTextComponent) {
			((JTextComponent) c).addKeyListener(getModifiedListener());
		} else if (c instanceof JCheckBox) {
			((JCheckBox) c).addActionListener(getModifiedListener());
		} else if (c instanceof JList) {
			((JList) c).addListSelectionListener(getModifiedListener());
		} else if (c instanceof AbstractButton) {
			((AbstractButton) c).addActionListener(getModifiedListener());
//		} else if (c instanceof JSpinner) {
//			((JSpinner) c).addChangeListener(getModifiedListener());
//		} else if (c instanceof ) {
//			(() c).add(getModifiedListener());
		}
	}

	public void setEditPanelBackgroundSettings() {
		/* ======================================== */
		EditableComponent cornerBorderElement = null;
		EditableComponent lastColumnBorderElement = null;
		EditableComponent lastRowBorderElement = null;
		
		for (EditableComponent ec : editPanelComponents.values()) {
			if (ec != null && ec.getType() == EditableComponent.BORDER_COMPONENT) {
				if (ec.getColumn() == 1 && ec.getRow() == 1) {
					cornerBorderElement = ec;
				} else if (ec.getColumn() == editPanelLayout.getColumnCount()) {
					lastColumnBorderElement = ec;
				} else if (ec.getRow() == editPanelLayout.getRowCount()) {
					lastRowBorderElement = ec;
				}
			}
		}
		
		if (cornerBorderElement == null
				|| lastRowBorderElement == null
				|| lastColumnBorderElement == null) {
			return;
		}
		
		int x = cornerBorderElement.getWidth();
		int y = cornerBorderElement.getHeight();
		int w = lastColumnBorderElement.getX() + lastColumnBorderElement.getWidth() - x;
		int h = lastRowBorderElement.getY() + lastRowBorderElement.getHeight() - y;
		
		editPnl.setBackgroundImageX(x);
		editPnl.setBackgroundImageY(y);
		editPnl.setBackgroundImageWidth(w);
		editPnl.setBackgroundImageHeight(h);
	}
	
	public void installSpinnerListeners (boolean install) {
		if (install) {
			colCountSpnr.addChangeListener(this.editorSizeListener);
			rowCountSpnr.addChangeListener(this.editorSizeListener);
		} else {
			colCountSpnr.removeChangeListener(this.editorSizeListener);
			rowCountSpnr.removeChangeListener(this.editorSizeListener);
		}
	}
	
	public void validateEditorScrollpane () {
		editSP.validate();
//		editSP.repaint();
	}
	
	
	public JPanel getSettingsPanel () {
		return settingsPnl;
	}
	
	public void showMenuPanel (boolean show) {
		menuPnl.setVisible(show);
	}
	
	
	/**
	 * Used for method isJavaVersionOK 
	 */
	private static Boolean javaVersionOK = null;
	
	/**
	 * Checks, if the Java version is higher than or equal to 1.6.0. <br>
	 * This version is necessary for the form editor, otherwise it cannot be used.
	 * 
	 * @return
	 * 		<code>true</code>, if the version of the used Java is high enough, else <code>false</code> 
	 */
	public static boolean isJavaVersionOK (){
		if (javaVersionOK == null) {
			/* ---------------------------------------- */
			// get the java version
			String javaVersion = System.getProperties().getProperty("java.version");
			String[] version = javaVersion.split("\\.");
			
			// check, if the version is higher than 1.6
			if (Integer.parseInt(version[0]) == 1
					&& Integer.parseInt(version[1]) < 6) {
				javaVersionOK = false;
				
				// log that, the java version is not high enough for the form editor
				logger.log(Level.INFO, "Necessary Java version for the FormEditor and its Tools is 1.6.0 or higher, " +
						"but current Java version is " + javaVersion);
				
			} else {
				javaVersionOK = true;
			}
			/* ---------------------------------------- */
		}
		
		return javaVersionOK.booleanValue();
	}
	
	
	private void showPopup (MouseEvent e)
	{
		if (e.isPopupTrigger())
		{
			/* ---------------------------------------- */
			templateList.setSelectedIndex(templateList.locationToIndex(e.getPoint()));
			if (templateList.getSelectedValue() == null) {
				return;
			}
			
			JPopupMenu menu = new JPopupMenu();
			
			// OPEN
			JMenuItem openItem = new JMenuItem(
					Translatrix.getTranslationString("core.open"),
					GECAMedModule.getMiniIcon(GECAMedIconNames.OPEN));
			openItem.addActionListener(new ActionListener() {
				
				public void actionPerformed (ActionEvent e) {
					/* ---------------------------------------- */
					FormTemplate template = (FormTemplate) templateList.getSelectedValue();
					model.chooseTemplate(template.getId());
					tabbedPane.setSelectedIndex(EDITOR_TAB);
//					((JPopupMenu)get()).setVisible(false);
					/* ---------------------------------------- */
				}
			});
			menu.add(openItem);
			
			
			// DELETE
			JMenuItem deleteItem = new JMenuItem(
					Translatrix.getTranslationString("core.delete"),
					GECAMedModule.getMiniIcon(GECAMedIconNames.REMOVE));
			deleteItem.addActionListener(new ActionListener() {
				
				public void actionPerformed(ActionEvent e) {
					/* ---------------------------------------- */
					model.deleteSelectedFormTemplate();
					/* ---------------------------------------- */
				}
			});
			menu.add(deleteItem);
			
			
			menu.addSeparator();
			
			
			// EXPORT
			JMenuItem exportItem = new JMenuItem(
					Translatrix.getTranslationString("formeditor.export"), 
					GECAMedModule.getMiniIcon(GECAMedIconNames.EXPORT));
			exportItem.addActionListener(new ActionListener() {
				/* ======================================== */
				public void actionPerformed(ActionEvent e) {
					/* ---------------------------------------- */
					FormTemplate template = (FormTemplate)templateList.getSelectedValue();
					model.exportTemplate(template);
					/* ---------------------------------------- */
				}
				/* ======================================== */
			});
			
			menu.add(exportItem);
			
			
			// IMPORT
			JMenuItem importItem = new JMenuItem(
					Translatrix.getTranslationString("formeditor.import"), 
					GECAMedModule.getMiniIcon(GECAMedIconNames.IMPORT));
			importItem.addActionListener(new ActionListener() {
				/* ======================================== */
				public void actionPerformed(ActionEvent e) {
					/* ---------------------------------------- */
					FormTemplate template = (FormTemplate)templateList.getSelectedValue();
					model.importTemplate(template);
					/* ---------------------------------------- */
				}
				/* ======================================== */
			});
			
			menu.add(importItem);
			
			
			menu.setLocation(e.getX(), e.getY());
			menu.show((JComponent)e.getSource(), e.getX(), e.getY());
			/* ---------------------------------------- */
		}
	}
	
	
	private void templateListClicked (MouseEvent e) {
		/* ======================================== */
		if (e.getButton() == MouseEvent.BUTTON1
				&& e.getClickCount() > 1) {
			/* ---------------------------------------- */
			// OPEN (double click)
			FormTemplate template = (FormTemplate) templateList.getSelectedValue();
			model.chooseTemplate(template.getId());
			/* ---------------------------------------- */
		} else {
			showPopup(e);
		}
		/* ======================================== */
	}
}
