From 47a081440e1de8364d9645f1570e248f6e3ad813 Mon Sep 17 00:00:00 2001
From: "piotr.gawron" <piotr.gawron@uni-new>
Date: Fri, 30 Sep 2016 14:15:24 +0200
Subject: [PATCH] editor refactoring to match merge species and alias

---
 .../gui/detailstab/ElementDetailsPanel.java   | 1594 ++++++++---------
 1 file changed, 797 insertions(+), 797 deletions(-)

diff --git a/editor/src/main/java/lcsb/mapviewer/editor/gui/detailstab/ElementDetailsPanel.java b/editor/src/main/java/lcsb/mapviewer/editor/gui/detailstab/ElementDetailsPanel.java
index 092ca4092b..e544119e74 100644
--- a/editor/src/main/java/lcsb/mapviewer/editor/gui/detailstab/ElementDetailsPanel.java
+++ b/editor/src/main/java/lcsb/mapviewer/editor/gui/detailstab/ElementDetailsPanel.java
@@ -1,797 +1,797 @@
-package lcsb.mapviewer.editor.gui.detailstab;
-
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.FocusEvent;
-import java.awt.event.FocusListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.swing.DefaultListModel;
-import javax.swing.JButton;
-import javax.swing.JColorChooser;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JPopupMenu;
-import javax.swing.JScrollPane;
-import javax.swing.JTextArea;
-import javax.swing.JTextField;
-import javax.swing.text.JTextComponent;
-
-import lcsb.mapviewer.commands.CommandExecutionException;
-import lcsb.mapviewer.commands.ModelCommand;
-import lcsb.mapviewer.common.exception.InvalidArgumentException;
-import lcsb.mapviewer.common.exception.InvalidStateException;
-import lcsb.mapviewer.common.exception.NotImplementedException;
-import lcsb.mapviewer.editor.gui.ElementModifiedEvent;
-import lcsb.mapviewer.editor.gui.ElementModifiedEventListener;
-import lcsb.mapviewer.editor.gui.GuiStyle;
-import lcsb.mapviewer.editor.gui.MiriamDataCellRender;
-import lcsb.mapviewer.editor.gui.objectedit.MiriamDataDialog;
-import lcsb.mapviewer.editor.gui.objectedit.ObjectEditDialog;
-import lcsb.mapviewer.editor.gui.objectedit.StringEditDialog;
-import lcsb.mapviewer.model.map.MiriamData;
-import lcsb.mapviewer.model.map.layout.alias.Alias;
-import lcsb.mapviewer.model.map.layout.alias.CompartmentAlias;
-import lcsb.mapviewer.model.map.layout.alias.ComplexAlias;
-import lcsb.mapviewer.model.map.model.Model;
-import lcsb.mapviewer.model.map.reaction.Reaction;
-
-import org.apache.log4j.Logger;
-
-/**
- * {@link JPanel} with detail information about selected {@link Alias} or
- * {@link Reaction}.
- * 
- * @author Piotr Gawron
- *
- */
-public class ElementDetailsPanel extends JPanel {
-
-	/**
-	 * X ratio between label and field that contains data in a single row. (take a
-	 * look at {@link GridBagConstraints#weightx}).
-	 */
-	private static final double													GRID_RATIO						 = 0.5;
-
-	/**
-	 * 
-	 */
-	private static final long														serialVersionUID			 = 1L;
-
-	/**
-	 * Default class logger.
-	 */
-	private final Logger																 logger								 = Logger.getLogger(ElementDetailsPanel.class);
-
-	/**
-	 * Label for {@link lcsb.mapviewer.model.map.Element#name} parameter.
-	 */
-	private JLabel																			 nameLabel;
-
-	/**
-	 * Label for {@link lcsb.mapviewer.model.map.Element#getElementId()}
-	 * parameter.
-	 */
-	private JLabel																			 idLabel;
-
-	/**
-	 * Label for complex parameter.
-	 */
-	private JLabel																			 complexLabel;
-
-	/**
-	 * Label for {@link Alias#compartmentAlias} parameter.
-	 */
-	private JLabel																			 compartmentLabel;
-
-	/**
-	 * Label for {@link Alias#fontSize} parameter.
-	 */
-	private JLabel																			 fontSizeLabel;
-
-	/**
-	 * Label for {@link Alias#color} parameter.
-	 */
-	private JLabel																			 colorLabel;
-
-	/**
-	 * Label for {@link lcsb.mapviewer.model.map.Element#notes} parameter.
-	 */
-	private JLabel																			 notesLabel;
-
-	/**
-	 * Label for {@link lcsb.mapviewer.model.map.Element#symbol} parameter.
-	 */
-	private JLabel																			 symbolLabel;
-
-	/**
-	 * Label for {@link lcsb.mapviewer.model.map.Element#fullName} parameter.
-	 */
-	private JLabel																			 fullNameLabel;
-
-	/**
-	 * Label for {@link lcsb.mapviewer.model.map.Element#abbreviation} parameter.
-	 */
-	private JLabel																			 abbreviationLabel;
-
-	/**
-	 * Label for {@link lcsb.mapviewer.model.map.Element#formula} parameter.
-	 */
-	private JLabel																			 formulaLabel;
-
-	/**
-	 * Label for {@link lcsb.mapviewer.model.map.Element#synonyms} parameter.
-	 */
-	private JLabel																			 synonymsLabel;
-
-	/**
-	 * Label for {@link lcsb.mapviewer.model.map.Element#formerSymbols} parameter.
-	 */
-	private JLabel																			 formerSymbolsLabel;
-
-	/**
-	 * Label for {@link lcsb.mapviewer.model.map.Element#symbol} parameter.
-	 */
-	private JLabel																			 miriamDataLabel;
-
-	/**
-	 * {@link JTextField} for {@link lcsb.mapviewer.model.map.Element#name}
-	 * parameter.
-	 */
-	private JTextField																	 nameText;
-
-	/**
-	 * {@link JTextField} for {@link lcsb.mapviewer.model.map.Element#name}
-	 * parameter.
-	 */
-	private JTextField																	 idText;
-
-	/**
-	 * {@link JTextField} for complex parameter.
-	 */
-	private JTextField																	 complexText;
-
-	/**
-	 * {@link JTextField} for {@link Alias#compartmentAlias} parameter.
-	 */
-	private JTextField																	 compartmentText;
-
-	/**
-	 * {@link JTextField} for {@link Alias#fontSize} parameter.
-	 */
-	private JTextField																	 fontSizeText;
-
-	/**
-	 * {@link JTextField} for {@link Alias#color} parameter.
-	 */
-	private JButton																			colorButton;
-
-	/**
-	 * {@link JTextField} for {@link lcsb.mapviewer.model.map.Element#notes}
-	 * parameter.
-	 */
-	private JTextArea																		notesText;
-
-	/**
-	 * {@link JTextField} for {@link lcsb.mapviewer.model.map.Element#symbol}
-	 * parameter.
-	 */
-	private JTextField																	 symbolText;
-
-	/**
-	 * {@link JTextField} for {@link lcsb.mapviewer.model.map.Element#fullName}
-	 * parameter.
-	 */
-	private JTextField																	 fullNameText;
-
-	/**
-	 * {@link JTextField} for
-	 * {@link lcsb.mapviewer.model.map.Element#abbreviation} parameter.
-	 */
-	private JTextField																	 abbreviationText;
-
-	/**
-	 * {@link JTextField} for {@link lcsb.mapviewer.model.map.Element#formula}
-	 * parameter.
-	 */
-	private JTextField																	 formulaText;
-
-	/**
-	 * {@link JList} for {@link lcsb.mapviewer.model.map.Element#synonyms}
-	 * parameter.
-	 */
-	private JList<String>																synonymsList;
-
-	/**
-	 * {@link JList} for
-	 * {@link lcsb.mapviewer.model.map.Element#formerSymbols} parameter.
-	 */
-	private JList<String>																formerSymbolsList;
-
-	/**
-	 * {@link JList} for {@link lcsb.mapviewer.model.map.Element#miriamData}
-	 * parameter.
-	 */
-	private JList<MiriamData>														miriamDataList;
-
-	/**
-	 * List of synonyms in {@link lcsb.mapviewer.model.map.Element#synonyms}.
-	 * 
-	 * @see {@link #synonymsList}
-	 */
-	private DefaultListModel<String>										 synonymsListModel			= new DefaultListModel<>();
-
-	/**
-	 * List of synonyms in {@link lcsb.mapviewer.model.map.Element#formerSymbols}.
-	 * 
-	 * @see {@link #formerSymbolsList}
-	 */
-	private DefaultListModel<String>										 formerSymbolsListModel = new DefaultListModel<>();
-
-	/**
-	 * List of synonyms in {@link lcsb.mapviewer.model.map.Element#miriamData}.
-	 * 
-	 * @see {@link #miriamDataList}
-	 */
-	private DefaultListModel<MiriamData>								 miriamDataListModel		= new DefaultListModel<>();
-
-	/**
-	 * {@link Alias} or {@link Reaction} that is currently selected.
-	 */
-	private Object																			 element;
-
-	/**
-	 * List of listeners that should be thrown when some properties of selected
-	 * {@link Alias} is changed.
-	 */
-	private List<ElementModifiedEventListener<Alias>>		aliasListeners				 = new ArrayList<>();
-
-	/**
-	 * List of listeners that should be thrown when some properties of selected
-	 * {@link Reaction} is changed.
-	 */
-	private List<ElementModifiedEventListener<Reaction>> reactionListeners			= new ArrayList<>();
-
-	/**
-	 * This flag value is set when data in the panel is updated from newly
-	 * selected element.
-	 */
-	private boolean																			updatingData					 = false;
-
-	/**
-	 * Default constructor.
-	 */
-	public ElementDetailsPanel() {
-		GridBagLayout gridLayout = new GridBagLayout();
-		setLayout(gridLayout);
-		setPreferredSize(new Dimension(GuiStyle.DETAIL_PANEL_WIDTH, GuiStyle.DETAIL_PANEL_HEIGHT));
-
-		nameLabel = new JLabel("Name: ");
-		idLabel = new JLabel("ID: ");
-		complexLabel = new JLabel("Parent complex: ");
-		compartmentLabel = new JLabel("Parent compartment: ");
-		fontSizeLabel = new JLabel("Font size: ");
-		colorLabel = new JLabel("Color: ");
-		notesLabel = new JLabel("Notes: ");
-		symbolLabel = new JLabel("Symbol: ");
-		fullNameLabel = new JLabel("Full name: ");
-		abbreviationLabel = new JLabel("Abbreviation: ");
-		formulaLabel = new JLabel("Formula: ");
-		synonymsLabel = new JLabel("Synonyms: ");
-		formerSymbolsLabel = new JLabel("Former symbols: ");
-		miriamDataLabel = new JLabel("Annotations: ");
-
-		nameText = new JTextField();
-		idText = new JTextField();
-		idText.setEditable(false);
-		idText.setEnabled(false);
-		complexText = new JTextField();
-		complexText.setEditable(false);
-		complexText.setEnabled(false);
-		compartmentText = new JTextField();
-		compartmentText.setEditable(false);
-		compartmentText.setEnabled(false);
-		fontSizeText = new JTextField();
-		colorButton = new JButton("Change");
-		notesText = new JTextArea();
-		notesText.setLineWrap(true);
-		notesText.setWrapStyleWord(true);
-		symbolText = new JTextField();
-		fullNameText = new JTextField();
-		abbreviationText = new JTextField();
-		formulaText = new JTextField();
-		synonymsList = new JList<>(synonymsListModel);
-		formerSymbolsList = new JList<>(formerSymbolsListModel);
-		miriamDataList = new JList<>(miriamDataListModel);
-		miriamDataList.setCellRenderer(new MiriamDataCellRender());
-
-		assignCommandToField(nameText, new CreateChangeNameCommand(nameText));
-		assignCommandToField(fontSizeText, new CreateChangeFontSizeCommand(fontSizeText));
-		assignCommandToField(notesText, new CreateChangeNotesCommand(notesText));
-		assignCommandToField(symbolText, new CreateChangeSymbolCommand(symbolText));
-		assignCommandToField(fullNameText, new CreateChangeFullNameCommand(fullNameText));
-		assignCommandToField(abbreviationText, new CreateChangeAbbreviationCommand(abbreviationText));
-		assignCommandToField(formulaText, new CreateChangeFormulaCommand(formulaText));
-		assignColorCommandToField(colorButton, new CreateChangeColorCommand(colorButton));
-		assignCommandToList(synonymsList, new CreateChangeSynonymCommand(synonymsList), "Synonym", String.class);
-		assignCommandToList(formerSymbolsList, new CreateChangeFormerSymbolCommand(formerSymbolsList), "Former symbol", String.class);
-		assignCommandToList(miriamDataList, new CreateChangeMiriamDataCommand(miriamDataList), "Miriam data", MiriamData.class);
-	}
-
-	/**
-	 * Creates listener that will handle changes on list parameter. It assigns
-	 * {@link CreateListPropertyChangeCommand<T>} object that will create a proper
-	 * {@link ModelCommand} when changes are made to the parameter field.
-	 * 
-	 * @param list
-	 *          component where changes can be made
-	 * @param dialogTitle
-	 *          title of the dialog used for editing property
-	 * @param clazz
-	 *          class type of the property
-	 * @param createCommandObject
-	 *          object that will create apropriate {@link ModelCommand}
-	 * @param <T>
-	 *          type of the objects included in the parameter list
-	 */
-	private <T> void assignCommandToList(JList<T> list, CreateListPropertyChangeCommand<T> createCommandObject, String dialogTitle, Class<T> clazz) {
-		list.addMouseListener(new MouseAdapter() {
-			@Override
-			public void mousePressed(MouseEvent e) {
-				logger.debug("Mouse pressed");
-				if (e.isPopupTrigger()) {
-					doPop(e);
-				}
-			}
-
-			@Override
-			public void mouseReleased(MouseEvent e) {
-				if (e.isPopupTrigger()) {
-					doPop(e);
-				}
-			}
-
-			private void doPop(MouseEvent e) {
-				JPopupMenu menu = new JPopupMenu();
-				JMenuItem addItem = new JMenuItem("Add");
-				menu.add(addItem);
-				addItem.addActionListener(new ActionListener() {
-					@Override
-					public void actionPerformed(ActionEvent e) {
-						ObjectEditDialog<T> editDialog = createEditDialog(dialogTitle, clazz);
-						editDialog.addOkListener(new ElementModifiedEventListener<T>() {
-
-							@Override
-							public void actionPerformed(ElementModifiedEvent<T> e) throws CommandExecutionException {
-								T s = e.getElement();
-								List<T> values = new ArrayList<>();
-								values.add(s);
-								ModelCommand modelCommand = createCommandObject.createAddCommand(getModel(), (Alias) element, values);
-								processCommand(modelCommand);
-								((DefaultListModel<T>) list.getModel()).addElement(s);
-							}
-						});
-						editDialog.editObject(null);
-					}
-
-				});
-				if (list.getSelectedIndices().length == 1) {
-					JMenuItem editItem = new JMenuItem("Edit");
-					menu.add(editItem);
-					editItem.addActionListener(new ActionListener() {
-						@Override
-						public void actionPerformed(ActionEvent e) {
-							ObjectEditDialog<T> editDialog = createEditDialog(dialogTitle, clazz);
-							editDialog.addOkListener(new ElementModifiedEventListener<T>() {
-								@Override
-								public void actionPerformed(ElementModifiedEvent<T> e) throws CommandExecutionException {
-									T s = e.getElement();
-									ModelCommand modelCommand = createCommandObject.createChangeCommand(getModel(), (Alias) element, s, list.getSelectedValue());
-									processCommand(modelCommand);
-									((DefaultListModel<T>) list.getModel()).set(list.getSelectedIndices()[0], s);
-								}
-							});
-							editDialog.editObject(list.getSelectedValue());
-						}
-					});
-				}
-				if (list.getSelectedIndices().length > 0) {
-					JMenuItem removeItem = new JMenuItem("Remove");
-					menu.add(removeItem);
-					removeItem.addActionListener(new ActionListener() {
-						@Override
-						public void actionPerformed(ActionEvent e) {
-							List<T> elements = new ArrayList<>();
-							for (T string : list.getSelectedValuesList()) {
-								elements.add(string);
-							}
-							ModelCommand modelCommand = createCommandObject.createRemoveCommand(getModel(), (Alias) element, elements);
-							try {
-								processCommand(modelCommand);
-								for (T string : elements) {
-									((DefaultListModel<T>) list.getModel()).removeElement(string);
-								}
-							} catch (CommandExecutionException exception) {
-								JOptionPane.showMessageDialog(null, exception.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
-							}
-						}
-					});
-				}
-				menu.show(e.getComponent(), e.getX(), e.getY());
-			}
-		});
-	}
-
-	/**
-	 * Creates listener that will handle changes on color button parameter. It
-	 * assigns {@link CreateListPropertyChangeCommand<T>} object that will create
-	 * a proper {@link ModelCommand} when changes are made to the parameter field.
-	 * 
-	 * @param colorButton
-	 *          component where changes can be made
-	 * @param createCommandObject
-	 *          object that will create apropriate {@link ModelCommand}
-	 */
-	private void assignColorCommandToField(JButton colorButton, CreatePropertyChangeCommand createCommandObject) {
-		colorButton.addActionListener(new ActionListener() {
-			@Override
-			public void actionPerformed(ActionEvent e) {
-				if (!updatingData && element != null) {
-					Color newColor = JColorChooser.showDialog(ElementDetailsPanel.this, "Choose Color", colorButton.getBackground());
-					if (newColor != null) {
-						colorButton.setBackground(newColor);
-						ModelCommand modelCommand = createCommandObject.createCommand(getModel(), (Alias) element);
-						try {
-							processCommand(modelCommand);
-						} catch (CommandExecutionException exception) {
-							JOptionPane.showMessageDialog(null, exception.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
-						}
-					}
-				}
-			}
-
-		});
-	}
-
-	/**
-	 * Executes parameter {@link ModelCommand} and fires appropraite listeners.
-	 * 
-	 * @param modelCommand
-	 *          command to be executed
-	 * @throws CommandExecutionException
-	 *           thrown when modelCommand cannot be executed due to some
-	 *           problematic input data
-	 */
-	public void processCommand(ModelCommand modelCommand) throws CommandExecutionException {
-		modelCommand.execute();
-		if (modelCommand != null) {
-			if (element instanceof Alias) {
-				ElementModifiedEvent<Alias> event = new ElementModifiedEvent<Alias>(this, (Alias) element, modelCommand);
-				for (ElementModifiedEventListener<Alias> listener : aliasListeners) {
-					listener.actionPerformed(event);
-				}
-			} else if (element instanceof Reaction) {
-				ElementModifiedEvent<Reaction> event = new ElementModifiedEvent<Reaction>(this, (Reaction) element, modelCommand);
-				for (ElementModifiedEventListener<Reaction> listener : reactionListeners) {
-					listener.actionPerformed(event);
-				}
-			} else {
-				throw new NotImplementedException("Don't know how to handle: " + element.getClass());
-			}
-		}
-	}
-
-	/**
-	 * Creates listener that will handle changes on {@link JTextComponent}
-	 * parameter. It assigns {@link CreateListPropertyChangeCommand<T>} object
-	 * that will create a proper {@link ModelCommand} when changes are made to the
-	 * parameter field.
-	 * 
-	 * @param field
-	 *          component where changes can be made
-	 * @param createCommandObject
-	 *          object that will create apropriate {@link ModelCommand}
-	 */
-	private void assignCommandToField(JTextComponent field, CreatePropertyChangeCommand createCommandObject) {
-		field.addFocusListener(new FocusListener() {
-			public void focusGained(FocusEvent e) {
-			}
-
-			public void focusLost(FocusEvent e) {
-				if (!updatingData && element != null) {
-					ModelCommand modelCommand = createCommandObject.createCommand(getModel(), (Alias) element);
-					try {
-						processCommand(modelCommand);
-					} catch (CommandExecutionException exception) {
-						JOptionPane.showMessageDialog(null, exception.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
-					}
-				}
-			}
-		});
-		if (field instanceof JTextField) {
-			((JTextField) field).addActionListener(new ActionListener() {
-				@Override
-				public void actionPerformed(ActionEvent e) {
-					if (!updatingData && element != null) {
-						ModelCommand modelCommand = createCommandObject.createCommand(getModel(), (Alias) element);
-						try {
-							processCommand(modelCommand);
-						} catch (CommandExecutionException exception) {
-							JOptionPane.showMessageDialog(null, exception.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
-						}
-					}
-				}
-			});
-		}
-
-	}
-
-	/**
-	 * Sets {@link #element}.
-	 * 
-	 * @param object
-	 *          new {@link #element} value
-	 */
-	public void setElement(Object object) {
-		this.element = object;
-
-		updateData(object);
-	}
-
-	/**
-	 * Updates data in the panel using parameter object as a data source.
-	 * 
-	 * @param object
-	 *          object for which data details should be available
-	 */
-	private void updateData(Object object) {
-		updatingData = true;
-		removeAll();
-		try {
-			if (object instanceof Alias) {
-				createAliasPanel((Alias) object);
-			} else if (object instanceof Reaction) {
-				createReactionPanel((Reaction) object);
-			} else if (object != null) {
-				throw new InvalidArgumentException("Cannot provide details for object: " + object);
-			}
-			validate();
-			repaint();
-		} finally {
-			updatingData = false;
-		}
-
-	}
-
-	/**
-	 * Creates property details panel for reaction.
-	 * 
-	 * @param object
-	 *          reaction for which panel will be created
-	 */
-	private void createReactionPanel(Reaction object) {
-		throw new NotImplementedException();
-
-	}
-
-	/**
-	 * Creates property details panel for alias.
-	 * 
-	 * @param alias
-	 *          {@link Alias} for which panel will be created
-	 */
-	private void createAliasPanel(Alias alias) {
-		int row = 0;
-		add(nameLabel, createLayoutConstraints(0, row));
-		add(nameText, createLayoutConstraints(1, row));
-		nameText.setText(alias.getElement().getName());
-		row++;
-
-		add(idLabel, createLayoutConstraints(0, row));
-		add(idText, createLayoutConstraints(1, row));
-		idText.setText(alias.getAliasId());
-		row++;
-
-		add(complexLabel, createLayoutConstraints(0, row));
-		add(complexText, createLayoutConstraints(1, row));
-		if (alias.getParent() instanceof ComplexAlias) {
-			complexText.setText(alias.getParent().getAliasId());
-		} else {
-			complexText.setText("N/A");
-		}
-		row++;
-
-		add(compartmentLabel, createLayoutConstraints(0, row));
-		add(compartmentText, createLayoutConstraints(1, row));
-		if (alias.getCompartmentAlias() instanceof CompartmentAlias) {
-			compartmentText.setText(alias.getCompartmentAlias().getAliasId());
-		} else {
-			compartmentText.setText("N/A");
-		}
-		row++;
-
-		add(fontSizeLabel, createLayoutConstraints(0, row));
-		add(fontSizeText, createLayoutConstraints(1, row));
-		fontSizeText.setText(alias.getFontSize() + "");
-		row++;
-
-		add(colorLabel, createLayoutConstraints(0, row));
-		add(colorButton, createLayoutConstraints(1, row));
-		colorButton.setBackground(alias.getColor());
-		row++;
-
-		add(notesLabel, createLayoutConstraints(0, row));
-		JScrollPane notesScrollContainer = new JScrollPane();
-		notesScrollContainer.setViewportView(notesText);
-		notesScrollContainer.setWheelScrollingEnabled(true);
-		notesScrollContainer.setMinimumSize(new Dimension(GuiStyle.DETAIL_PANEL_WIDTH / 2, GuiStyle.SCROLL_LIST_HEIGHT));
-
-		add(notesScrollContainer, createLayoutConstraints(1, row));
-		notesText.setText(alias.getElement().getNotes());
-		row++;
-
-		add(symbolLabel, createLayoutConstraints(0, row));
-		add(symbolText, createLayoutConstraints(1, row));
-		symbolText.setText(alias.getElement().getSymbol());
-		row++;
-
-		add(fullNameLabel, createLayoutConstraints(0, row));
-		add(fullNameText, createLayoutConstraints(1, row));
-		fullNameText.setText(alias.getElement().getFullName());
-		row++;
-
-		add(abbreviationLabel, createLayoutConstraints(0, row));
-		add(abbreviationText, createLayoutConstraints(1, row));
-		abbreviationText.setText(alias.getElement().getAbbreviation());
-		row++;
-
-		add(formulaLabel, createLayoutConstraints(0, row));
-		add(formulaText, createLayoutConstraints(1, row));
-		formulaText.setText(alias.getElement().getFormula());
-		row++;
-
-		add(synonymsLabel, createLayoutConstraints(0, row));
-		JScrollPane synonymsScrollPane = new JScrollPane(synonymsList);
-		synonymsScrollPane.setMinimumSize(new Dimension(GuiStyle.DETAIL_PANEL_WIDTH / 2, GuiStyle.SCROLL_LIST_HEIGHT));
-		add(synonymsScrollPane, createLayoutConstraints(1, row));
-		synonymsListModel.removeAllElements();
-		for (String string : alias.getElement().getSynonyms()) {
-			synonymsListModel.addElement(string);
-		}
-		row++;
-
-		add(formerSymbolsLabel, createLayoutConstraints(0, row));
-		JScrollPane formerSymbolsPane = new JScrollPane(formerSymbolsList);
-		formerSymbolsPane.setMinimumSize(new Dimension(GuiStyle.DETAIL_PANEL_WIDTH / 2, GuiStyle.SCROLL_LIST_HEIGHT));
-		add(formerSymbolsPane, createLayoutConstraints(1, row));
-		formerSymbolsListModel.removeAllElements();
-		for (String string : alias.getElement().getFormerSymbols()) {
-			formerSymbolsListModel.addElement(string);
-		}
-		row++;
-
-		add(miriamDataLabel, createLayoutConstraints(0, row));
-		JScrollPane miriamDataPane = new JScrollPane(miriamDataList);
-		miriamDataPane.setMinimumSize(new Dimension(GuiStyle.DETAIL_PANEL_WIDTH / 2, GuiStyle.SCROLL_LIST_HEIGHT));
-		add(miriamDataPane, createLayoutConstraints(1, row));
-		miriamDataListModel.removeAllElements();
-		for (MiriamData md : alias.getElement().getMiriamData()) {
-			miriamDataListModel.addElement(md);
-		}
-		row++;
-
-		addFooterForAlignment(row++);
-	}
-
-	/**
-	 * Adds footer on bottom of the panel to make proper alignments.
-	 * 
-	 * @param row
-	 *          row in which the last element should appear
-	 */
-	private void addFooterForAlignment(int row) {
-		JLabel button = new JLabel("");
-		GridBagConstraints c = new GridBagConstraints();
-		c.fill = GridBagConstraints.HORIZONTAL;
-		c.ipady = 0; // reset to default
-		c.weighty = 1.0; // request any extra vertical space
-		c.anchor = GridBagConstraints.PAGE_END; // bottom of space
-		c.gridx = 1; // aligned with button 2
-		c.gridwidth = 2; // 2 columns wide
-		c.gridy = row; // third row
-		add(button, c);
-	}
-
-	/**
-	 * Create constraints for element located on x,y positions in
-	 * {@link GridBagLayout}.
-	 * 
-	 * @param x
-	 *          column
-	 * @param y
-	 *          row
-	 * @return {@link GridBagConstraints} for object at specified coordinates
-	 */
-	public GridBagConstraints createLayoutConstraints(int x, int y) {
-		GridBagConstraints c = new GridBagConstraints();
-		c.fill = GridBagConstraints.HORIZONTAL;
-		c.anchor = GridBagConstraints.NORTH;
-		c.weightx = GRID_RATIO;
-		c.gridx = x;
-		c.gridy = y;
-		return c;
-	}
-
-	/**
-	 * Adds listener to be thrown when properties of the {@link #element edited
-	 * Alias} is changing.
-	 * 
-	 * @param e
-	 *          {@link ElementModifiedEventListener listener} to add
-	 */
-	public void addAliasModifiedEventListener(ElementModifiedEventListener<Alias> e) {
-		aliasListeners.add(e);
-	}
-
-	/**
-	 * Adds listener to be thrown when properties of the {@link #element edited
-	 * Reaction} is changing.
-	 * 
-	 * @param e
-	 *          {@link ElementModifiedEventListener listener} to add
-	 */
-	public void addReactionModifiedEventListener(ElementModifiedEventListener<Reaction> e) {
-		reactionListeners.add(e);
-	}
-
-	/**
-	 * Returns {@link Model} where edited element is located.
-	 * 
-	 * @return {@link Model} where edited element is located
-	 */
-	private Model getModel() {
-		if (element instanceof Alias) {
-			return ((Alias) element).getModel();
-		} else if (element instanceof Reaction) {
-			return ((Reaction) element).getModel();
-		} else if (element != null) {
-			throw new InvalidStateException("Don't know how to handle object of class: " + element.getClass());
-		} else {
-			return null;
-		}
-	}
-
-	/**
-	 * Created {@link ObjectEditDialog} that can edit objects of type specified in
-	 * parameter.
-	 * 
-	 * @param dialogTitle
-	 *          title that should be used in a dialog
-	 * @param clazz
-	 *          class of a type of the object to edit
-	 * @return {@link ObjectEditDialog} that can edit objects of type specified in
-	 *         parameter
-	 * @param <T>
-	 *          type of the object to edit
-	 */
-	@SuppressWarnings("unchecked")
-	private <T> ObjectEditDialog<T> createEditDialog(String dialogTitle, Class<T> clazz) {
-		if (String.class.equals(clazz)) {
-			return (ObjectEditDialog<T>) new StringEditDialog(null, dialogTitle, dialogTitle);
-		} else 		if (MiriamData.class.equals(clazz)) {
-			return (ObjectEditDialog<T>) new MiriamDataDialog(null, dialogTitle, dialogTitle);
-		} else {
-			throw new NotImplementedException("Don't know how to handle: " + clazz);
-		}
-	}
-}
+package lcsb.mapviewer.editor.gui.detailstab;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JColorChooser;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.text.JTextComponent;
+
+import lcsb.mapviewer.commands.CommandExecutionException;
+import lcsb.mapviewer.commands.ModelCommand;
+import lcsb.mapviewer.common.exception.InvalidArgumentException;
+import lcsb.mapviewer.common.exception.InvalidStateException;
+import lcsb.mapviewer.common.exception.NotImplementedException;
+import lcsb.mapviewer.editor.gui.ElementModifiedEvent;
+import lcsb.mapviewer.editor.gui.ElementModifiedEventListener;
+import lcsb.mapviewer.editor.gui.GuiStyle;
+import lcsb.mapviewer.editor.gui.MiriamDataCellRender;
+import lcsb.mapviewer.editor.gui.objectedit.MiriamDataDialog;
+import lcsb.mapviewer.editor.gui.objectedit.ObjectEditDialog;
+import lcsb.mapviewer.editor.gui.objectedit.StringEditDialog;
+import lcsb.mapviewer.model.map.MiriamData;
+import lcsb.mapviewer.model.map.layout.alias.Alias;
+import lcsb.mapviewer.model.map.layout.alias.CompartmentAlias;
+import lcsb.mapviewer.model.map.layout.alias.ComplexAlias;
+import lcsb.mapviewer.model.map.model.Model;
+import lcsb.mapviewer.model.map.reaction.Reaction;
+
+import org.apache.log4j.Logger;
+
+/**
+ * {@link JPanel} with detail information about selected {@link Alias} or
+ * {@link Reaction}.
+ * 
+ * @author Piotr Gawron
+ *
+ */
+public class ElementDetailsPanel extends JPanel {
+
+	/**
+	 * X ratio between label and field that contains data in a single row. (take a
+	 * look at {@link GridBagConstraints#weightx}).
+	 */
+	private static final double													GRID_RATIO						 = 0.5;
+
+	/**
+	 * 
+	 */
+	private static final long														serialVersionUID			 = 1L;
+
+	/**
+	 * Default class logger.
+	 */
+	private final Logger																 logger								 = Logger.getLogger(ElementDetailsPanel.class);
+
+	/**
+	 * Label for {@link lcsb.mapviewer.model.map.Element#name} parameter.
+	 */
+	private JLabel																			 nameLabel;
+
+	/**
+	 * Label for {@link lcsb.mapviewer.model.map.Element#getElementId()}
+	 * parameter.
+	 */
+	private JLabel																			 idLabel;
+
+	/**
+	 * Label for complex parameter.
+	 */
+	private JLabel																			 complexLabel;
+
+	/**
+	 * Label for {@link Alias#compartmentAlias} parameter.
+	 */
+	private JLabel																			 compartmentLabel;
+
+	/**
+	 * Label for {@link Alias#fontSize} parameter.
+	 */
+	private JLabel																			 fontSizeLabel;
+
+	/**
+	 * Label for {@link Alias#color} parameter.
+	 */
+	private JLabel																			 colorLabel;
+
+	/**
+	 * Label for {@link lcsb.mapviewer.model.map.Element#notes} parameter.
+	 */
+	private JLabel																			 notesLabel;
+
+	/**
+	 * Label for {@link lcsb.mapviewer.model.map.Element#symbol} parameter.
+	 */
+	private JLabel																			 symbolLabel;
+
+	/**
+	 * Label for {@link lcsb.mapviewer.model.map.Element#fullName} parameter.
+	 */
+	private JLabel																			 fullNameLabel;
+
+	/**
+	 * Label for {@link lcsb.mapviewer.model.map.Element#abbreviation} parameter.
+	 */
+	private JLabel																			 abbreviationLabel;
+
+	/**
+	 * Label for {@link lcsb.mapviewer.model.map.Element#formula} parameter.
+	 */
+	private JLabel																			 formulaLabel;
+
+	/**
+	 * Label for {@link lcsb.mapviewer.model.map.Element#synonyms} parameter.
+	 */
+	private JLabel																			 synonymsLabel;
+
+	/**
+	 * Label for {@link lcsb.mapviewer.model.map.Element#formerSymbols} parameter.
+	 */
+	private JLabel																			 formerSymbolsLabel;
+
+	/**
+	 * Label for {@link lcsb.mapviewer.model.map.Element#symbol} parameter.
+	 */
+	private JLabel																			 miriamDataLabel;
+
+	/**
+	 * {@link JTextField} for {@link lcsb.mapviewer.model.map.Element#name}
+	 * parameter.
+	 */
+	private JTextField																	 nameText;
+
+	/**
+	 * {@link JTextField} for {@link lcsb.mapviewer.model.map.Element#name}
+	 * parameter.
+	 */
+	private JTextField																	 idText;
+
+	/**
+	 * {@link JTextField} for complex parameter.
+	 */
+	private JTextField																	 complexText;
+
+	/**
+	 * {@link JTextField} for {@link Alias#compartmentAlias} parameter.
+	 */
+	private JTextField																	 compartmentText;
+
+	/**
+	 * {@link JTextField} for {@link Alias#fontSize} parameter.
+	 */
+	private JTextField																	 fontSizeText;
+
+	/**
+	 * {@link JTextField} for {@link Alias#color} parameter.
+	 */
+	private JButton																			colorButton;
+
+	/**
+	 * {@link JTextField} for {@link lcsb.mapviewer.model.map.Element#notes}
+	 * parameter.
+	 */
+	private JTextArea																		notesText;
+
+	/**
+	 * {@link JTextField} for {@link lcsb.mapviewer.model.map.Element#symbol}
+	 * parameter.
+	 */
+	private JTextField																	 symbolText;
+
+	/**
+	 * {@link JTextField} for {@link lcsb.mapviewer.model.map.Element#fullName}
+	 * parameter.
+	 */
+	private JTextField																	 fullNameText;
+
+	/**
+	 * {@link JTextField} for
+	 * {@link lcsb.mapviewer.model.map.Element#abbreviation} parameter.
+	 */
+	private JTextField																	 abbreviationText;
+
+	/**
+	 * {@link JTextField} for {@link lcsb.mapviewer.model.map.Element#formula}
+	 * parameter.
+	 */
+	private JTextField																	 formulaText;
+
+	/**
+	 * {@link JList} for {@link lcsb.mapviewer.model.map.Element#synonyms}
+	 * parameter.
+	 */
+	private JList<String>																synonymsList;
+
+	/**
+	 * {@link JList} for
+	 * {@link lcsb.mapviewer.model.map.Element#formerSymbols} parameter.
+	 */
+	private JList<String>																formerSymbolsList;
+
+	/**
+	 * {@link JList} for {@link lcsb.mapviewer.model.map.Element#miriamData}
+	 * parameter.
+	 */
+	private JList<MiriamData>														miriamDataList;
+
+	/**
+	 * List of synonyms in {@link lcsb.mapviewer.model.map.Element#synonyms}.
+	 * 
+	 * @see {@link #synonymsList}
+	 */
+	private DefaultListModel<String>										 synonymsListModel			= new DefaultListModel<>();
+
+	/**
+	 * List of synonyms in {@link lcsb.mapviewer.model.map.Element#formerSymbols}.
+	 * 
+	 * @see {@link #formerSymbolsList}
+	 */
+	private DefaultListModel<String>										 formerSymbolsListModel = new DefaultListModel<>();
+
+	/**
+	 * List of synonyms in {@link lcsb.mapviewer.model.map.Element#miriamData}.
+	 * 
+	 * @see {@link #miriamDataList}
+	 */
+	private DefaultListModel<MiriamData>								 miriamDataListModel		= new DefaultListModel<>();
+
+	/**
+	 * {@link Alias} or {@link Reaction} that is currently selected.
+	 */
+	private Object																			 element;
+
+	/**
+	 * List of listeners that should be thrown when some properties of selected
+	 * {@link Alias} is changed.
+	 */
+	private List<ElementModifiedEventListener<Alias>>		aliasListeners				 = new ArrayList<>();
+
+	/**
+	 * List of listeners that should be thrown when some properties of selected
+	 * {@link Reaction} is changed.
+	 */
+	private List<ElementModifiedEventListener<Reaction>> reactionListeners			= new ArrayList<>();
+
+	/**
+	 * This flag value is set when data in the panel is updated from newly
+	 * selected element.
+	 */
+	private boolean																			updatingData					 = false;
+
+	/**
+	 * Default constructor.
+	 */
+	public ElementDetailsPanel() {
+		GridBagLayout gridLayout = new GridBagLayout();
+		setLayout(gridLayout);
+		setPreferredSize(new Dimension(GuiStyle.DETAIL_PANEL_WIDTH, GuiStyle.DETAIL_PANEL_HEIGHT));
+
+		nameLabel = new JLabel("Name: ");
+		idLabel = new JLabel("ID: ");
+		complexLabel = new JLabel("Parent complex: ");
+		compartmentLabel = new JLabel("Parent compartment: ");
+		fontSizeLabel = new JLabel("Font size: ");
+		colorLabel = new JLabel("Color: ");
+		notesLabel = new JLabel("Notes: ");
+		symbolLabel = new JLabel("Symbol: ");
+		fullNameLabel = new JLabel("Full name: ");
+		abbreviationLabel = new JLabel("Abbreviation: ");
+		formulaLabel = new JLabel("Formula: ");
+		synonymsLabel = new JLabel("Synonyms: ");
+		formerSymbolsLabel = new JLabel("Former symbols: ");
+		miriamDataLabel = new JLabel("Annotations: ");
+
+		nameText = new JTextField();
+		idText = new JTextField();
+		idText.setEditable(false);
+		idText.setEnabled(false);
+		complexText = new JTextField();
+		complexText.setEditable(false);
+		complexText.setEnabled(false);
+		compartmentText = new JTextField();
+		compartmentText.setEditable(false);
+		compartmentText.setEnabled(false);
+		fontSizeText = new JTextField();
+		colorButton = new JButton("Change");
+		notesText = new JTextArea();
+		notesText.setLineWrap(true);
+		notesText.setWrapStyleWord(true);
+		symbolText = new JTextField();
+		fullNameText = new JTextField();
+		abbreviationText = new JTextField();
+		formulaText = new JTextField();
+		synonymsList = new JList<>(synonymsListModel);
+		formerSymbolsList = new JList<>(formerSymbolsListModel);
+		miriamDataList = new JList<>(miriamDataListModel);
+		miriamDataList.setCellRenderer(new MiriamDataCellRender());
+
+		assignCommandToField(nameText, new CreateChangeNameCommand(nameText));
+		assignCommandToField(fontSizeText, new CreateChangeFontSizeCommand(fontSizeText));
+		assignCommandToField(notesText, new CreateChangeNotesCommand(notesText));
+		assignCommandToField(symbolText, new CreateChangeSymbolCommand(symbolText));
+		assignCommandToField(fullNameText, new CreateChangeFullNameCommand(fullNameText));
+		assignCommandToField(abbreviationText, new CreateChangeAbbreviationCommand(abbreviationText));
+		assignCommandToField(formulaText, new CreateChangeFormulaCommand(formulaText));
+		assignColorCommandToField(colorButton, new CreateChangeColorCommand(colorButton));
+		assignCommandToList(synonymsList, new CreateChangeSynonymCommand(synonymsList), "Synonym", String.class);
+		assignCommandToList(formerSymbolsList, new CreateChangeFormerSymbolCommand(formerSymbolsList), "Former symbol", String.class);
+		assignCommandToList(miriamDataList, new CreateChangeMiriamDataCommand(miriamDataList), "Miriam data", MiriamData.class);
+	}
+
+	/**
+	 * Creates listener that will handle changes on list parameter. It assigns
+	 * {@link CreateListPropertyChangeCommand<T>} object that will create a proper
+	 * {@link ModelCommand} when changes are made to the parameter field.
+	 * 
+	 * @param list
+	 *          component where changes can be made
+	 * @param dialogTitle
+	 *          title of the dialog used for editing property
+	 * @param clazz
+	 *          class type of the property
+	 * @param createCommandObject
+	 *          object that will create apropriate {@link ModelCommand}
+	 * @param <T>
+	 *          type of the objects included in the parameter list
+	 */
+	private <T> void assignCommandToList(JList<T> list, CreateListPropertyChangeCommand<T> createCommandObject, String dialogTitle, Class<T> clazz) {
+		list.addMouseListener(new MouseAdapter() {
+			@Override
+			public void mousePressed(MouseEvent e) {
+				logger.debug("Mouse pressed");
+				if (e.isPopupTrigger()) {
+					doPop(e);
+				}
+			}
+
+			@Override
+			public void mouseReleased(MouseEvent e) {
+				if (e.isPopupTrigger()) {
+					doPop(e);
+				}
+			}
+
+			private void doPop(MouseEvent e) {
+				JPopupMenu menu = new JPopupMenu();
+				JMenuItem addItem = new JMenuItem("Add");
+				menu.add(addItem);
+				addItem.addActionListener(new ActionListener() {
+					@Override
+					public void actionPerformed(ActionEvent e) {
+						ObjectEditDialog<T> editDialog = createEditDialog(dialogTitle, clazz);
+						editDialog.addOkListener(new ElementModifiedEventListener<T>() {
+
+							@Override
+							public void actionPerformed(ElementModifiedEvent<T> e) throws CommandExecutionException {
+								T s = e.getElement();
+								List<T> values = new ArrayList<>();
+								values.add(s);
+								ModelCommand modelCommand = createCommandObject.createAddCommand(getModel(), (Alias) element, values);
+								processCommand(modelCommand);
+								((DefaultListModel<T>) list.getModel()).addElement(s);
+							}
+						});
+						editDialog.editObject(null);
+					}
+
+				});
+				if (list.getSelectedIndices().length == 1) {
+					JMenuItem editItem = new JMenuItem("Edit");
+					menu.add(editItem);
+					editItem.addActionListener(new ActionListener() {
+						@Override
+						public void actionPerformed(ActionEvent e) {
+							ObjectEditDialog<T> editDialog = createEditDialog(dialogTitle, clazz);
+							editDialog.addOkListener(new ElementModifiedEventListener<T>() {
+								@Override
+								public void actionPerformed(ElementModifiedEvent<T> e) throws CommandExecutionException {
+									T s = e.getElement();
+									ModelCommand modelCommand = createCommandObject.createChangeCommand(getModel(), (Alias) element, s, list.getSelectedValue());
+									processCommand(modelCommand);
+									((DefaultListModel<T>) list.getModel()).set(list.getSelectedIndices()[0], s);
+								}
+							});
+							editDialog.editObject(list.getSelectedValue());
+						}
+					});
+				}
+				if (list.getSelectedIndices().length > 0) {
+					JMenuItem removeItem = new JMenuItem("Remove");
+					menu.add(removeItem);
+					removeItem.addActionListener(new ActionListener() {
+						@Override
+						public void actionPerformed(ActionEvent e) {
+							List<T> elements = new ArrayList<>();
+							for (T string : list.getSelectedValuesList()) {
+								elements.add(string);
+							}
+							ModelCommand modelCommand = createCommandObject.createRemoveCommand(getModel(), (Alias) element, elements);
+							try {
+								processCommand(modelCommand);
+								for (T string : elements) {
+									((DefaultListModel<T>) list.getModel()).removeElement(string);
+								}
+							} catch (CommandExecutionException exception) {
+								JOptionPane.showMessageDialog(null, exception.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
+							}
+						}
+					});
+				}
+				menu.show(e.getComponent(), e.getX(), e.getY());
+			}
+		});
+	}
+
+	/**
+	 * Creates listener that will handle changes on color button parameter. It
+	 * assigns {@link CreateListPropertyChangeCommand<T>} object that will create
+	 * a proper {@link ModelCommand} when changes are made to the parameter field.
+	 * 
+	 * @param colorButton
+	 *          component where changes can be made
+	 * @param createCommandObject
+	 *          object that will create apropriate {@link ModelCommand}
+	 */
+	private void assignColorCommandToField(JButton colorButton, CreatePropertyChangeCommand createCommandObject) {
+		colorButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				if (!updatingData && element != null) {
+					Color newColor = JColorChooser.showDialog(ElementDetailsPanel.this, "Choose Color", colorButton.getBackground());
+					if (newColor != null) {
+						colorButton.setBackground(newColor);
+						ModelCommand modelCommand = createCommandObject.createCommand(getModel(), (Alias) element);
+						try {
+							processCommand(modelCommand);
+						} catch (CommandExecutionException exception) {
+							JOptionPane.showMessageDialog(null, exception.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
+						}
+					}
+				}
+			}
+
+		});
+	}
+
+	/**
+	 * Executes parameter {@link ModelCommand} and fires appropraite listeners.
+	 * 
+	 * @param modelCommand
+	 *          command to be executed
+	 * @throws CommandExecutionException
+	 *           thrown when modelCommand cannot be executed due to some
+	 *           problematic input data
+	 */
+	public void processCommand(ModelCommand modelCommand) throws CommandExecutionException {
+		modelCommand.execute();
+		if (modelCommand != null) {
+			if (element instanceof Alias) {
+				ElementModifiedEvent<Alias> event = new ElementModifiedEvent<Alias>(this, (Alias) element, modelCommand);
+				for (ElementModifiedEventListener<Alias> listener : aliasListeners) {
+					listener.actionPerformed(event);
+				}
+			} else if (element instanceof Reaction) {
+				ElementModifiedEvent<Reaction> event = new ElementModifiedEvent<Reaction>(this, (Reaction) element, modelCommand);
+				for (ElementModifiedEventListener<Reaction> listener : reactionListeners) {
+					listener.actionPerformed(event);
+				}
+			} else {
+				throw new NotImplementedException("Don't know how to handle: " + element.getClass());
+			}
+		}
+	}
+
+	/**
+	 * Creates listener that will handle changes on {@link JTextComponent}
+	 * parameter. It assigns {@link CreateListPropertyChangeCommand<T>} object
+	 * that will create a proper {@link ModelCommand} when changes are made to the
+	 * parameter field.
+	 * 
+	 * @param field
+	 *          component where changes can be made
+	 * @param createCommandObject
+	 *          object that will create apropriate {@link ModelCommand}
+	 */
+	private void assignCommandToField(JTextComponent field, CreatePropertyChangeCommand createCommandObject) {
+		field.addFocusListener(new FocusListener() {
+			public void focusGained(FocusEvent e) {
+			}
+
+			public void focusLost(FocusEvent e) {
+				if (!updatingData && element != null) {
+					ModelCommand modelCommand = createCommandObject.createCommand(getModel(), (Alias) element);
+					try {
+						processCommand(modelCommand);
+					} catch (CommandExecutionException exception) {
+						JOptionPane.showMessageDialog(null, exception.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
+					}
+				}
+			}
+		});
+		if (field instanceof JTextField) {
+			((JTextField) field).addActionListener(new ActionListener() {
+				@Override
+				public void actionPerformed(ActionEvent e) {
+					if (!updatingData && element != null) {
+						ModelCommand modelCommand = createCommandObject.createCommand(getModel(), (Alias) element);
+						try {
+							processCommand(modelCommand);
+						} catch (CommandExecutionException exception) {
+							JOptionPane.showMessageDialog(null, exception.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
+						}
+					}
+				}
+			});
+		}
+
+	}
+
+	/**
+	 * Sets {@link #element}.
+	 * 
+	 * @param object
+	 *          new {@link #element} value
+	 */
+	public void setElement(Object object) {
+		this.element = object;
+
+		updateData(object);
+	}
+
+	/**
+	 * Updates data in the panel using parameter object as a data source.
+	 * 
+	 * @param object
+	 *          object for which data details should be available
+	 */
+	private void updateData(Object object) {
+		updatingData = true;
+		removeAll();
+		try {
+			if (object instanceof Alias) {
+				createAliasPanel((Alias) object);
+			} else if (object instanceof Reaction) {
+				createReactionPanel((Reaction) object);
+			} else if (object != null) {
+				throw new InvalidArgumentException("Cannot provide details for object: " + object);
+			}
+			validate();
+			repaint();
+		} finally {
+			updatingData = false;
+		}
+
+	}
+
+	/**
+	 * Creates property details panel for reaction.
+	 * 
+	 * @param object
+	 *          reaction for which panel will be created
+	 */
+	private void createReactionPanel(Reaction object) {
+		throw new NotImplementedException();
+
+	}
+
+	/**
+	 * Creates property details panel for alias.
+	 * 
+	 * @param alias
+	 *          {@link Alias} for which panel will be created
+	 */
+	private void createAliasPanel(Alias alias) {
+		int row = 0;
+		add(nameLabel, createLayoutConstraints(0, row));
+		add(nameText, createLayoutConstraints(1, row));
+		nameText.setText(alias.getName());
+		row++;
+
+		add(idLabel, createLayoutConstraints(0, row));
+		add(idText, createLayoutConstraints(1, row));
+		idText.setText(alias.getAliasId());
+		row++;
+
+		add(complexLabel, createLayoutConstraints(0, row));
+		add(complexText, createLayoutConstraints(1, row));
+		if (alias.getParent() instanceof ComplexAlias) {
+			complexText.setText(alias.getParent().getAliasId());
+		} else {
+			complexText.setText("N/A");
+		}
+		row++;
+
+		add(compartmentLabel, createLayoutConstraints(0, row));
+		add(compartmentText, createLayoutConstraints(1, row));
+		if (alias.getCompartmentAlias() instanceof CompartmentAlias) {
+			compartmentText.setText(alias.getCompartmentAlias().getAliasId());
+		} else {
+			compartmentText.setText("N/A");
+		}
+		row++;
+
+		add(fontSizeLabel, createLayoutConstraints(0, row));
+		add(fontSizeText, createLayoutConstraints(1, row));
+		fontSizeText.setText(alias.getFontSize() + "");
+		row++;
+
+		add(colorLabel, createLayoutConstraints(0, row));
+		add(colorButton, createLayoutConstraints(1, row));
+		colorButton.setBackground(alias.getColor());
+		row++;
+
+		add(notesLabel, createLayoutConstraints(0, row));
+		JScrollPane notesScrollContainer = new JScrollPane();
+		notesScrollContainer.setViewportView(notesText);
+		notesScrollContainer.setWheelScrollingEnabled(true);
+		notesScrollContainer.setMinimumSize(new Dimension(GuiStyle.DETAIL_PANEL_WIDTH / 2, GuiStyle.SCROLL_LIST_HEIGHT));
+
+		add(notesScrollContainer, createLayoutConstraints(1, row));
+		notesText.setText(alias.getNotes());
+		row++;
+
+		add(symbolLabel, createLayoutConstraints(0, row));
+		add(symbolText, createLayoutConstraints(1, row));
+		symbolText.setText(alias.getSymbol());
+		row++;
+
+		add(fullNameLabel, createLayoutConstraints(0, row));
+		add(fullNameText, createLayoutConstraints(1, row));
+		fullNameText.setText(alias.getFullName());
+		row++;
+
+		add(abbreviationLabel, createLayoutConstraints(0, row));
+		add(abbreviationText, createLayoutConstraints(1, row));
+		abbreviationText.setText(alias.getAbbreviation());
+		row++;
+
+		add(formulaLabel, createLayoutConstraints(0, row));
+		add(formulaText, createLayoutConstraints(1, row));
+		formulaText.setText(alias.getFormula());
+		row++;
+
+		add(synonymsLabel, createLayoutConstraints(0, row));
+		JScrollPane synonymsScrollPane = new JScrollPane(synonymsList);
+		synonymsScrollPane.setMinimumSize(new Dimension(GuiStyle.DETAIL_PANEL_WIDTH / 2, GuiStyle.SCROLL_LIST_HEIGHT));
+		add(synonymsScrollPane, createLayoutConstraints(1, row));
+		synonymsListModel.removeAllElements();
+		for (String string : alias.getSynonyms()) {
+			synonymsListModel.addElement(string);
+		}
+		row++;
+
+		add(formerSymbolsLabel, createLayoutConstraints(0, row));
+		JScrollPane formerSymbolsPane = new JScrollPane(formerSymbolsList);
+		formerSymbolsPane.setMinimumSize(new Dimension(GuiStyle.DETAIL_PANEL_WIDTH / 2, GuiStyle.SCROLL_LIST_HEIGHT));
+		add(formerSymbolsPane, createLayoutConstraints(1, row));
+		formerSymbolsListModel.removeAllElements();
+		for (String string : alias.getFormerSymbols()) {
+			formerSymbolsListModel.addElement(string);
+		}
+		row++;
+
+		add(miriamDataLabel, createLayoutConstraints(0, row));
+		JScrollPane miriamDataPane = new JScrollPane(miriamDataList);
+		miriamDataPane.setMinimumSize(new Dimension(GuiStyle.DETAIL_PANEL_WIDTH / 2, GuiStyle.SCROLL_LIST_HEIGHT));
+		add(miriamDataPane, createLayoutConstraints(1, row));
+		miriamDataListModel.removeAllElements();
+		for (MiriamData md : alias.getMiriamData()) {
+			miriamDataListModel.addElement(md);
+		}
+		row++;
+
+		addFooterForAlignment(row++);
+	}
+
+	/**
+	 * Adds footer on bottom of the panel to make proper alignments.
+	 * 
+	 * @param row
+	 *          row in which the last element should appear
+	 */
+	private void addFooterForAlignment(int row) {
+		JLabel button = new JLabel("");
+		GridBagConstraints c = new GridBagConstraints();
+		c.fill = GridBagConstraints.HORIZONTAL;
+		c.ipady = 0; // reset to default
+		c.weighty = 1.0; // request any extra vertical space
+		c.anchor = GridBagConstraints.PAGE_END; // bottom of space
+		c.gridx = 1; // aligned with button 2
+		c.gridwidth = 2; // 2 columns wide
+		c.gridy = row; // third row
+		add(button, c);
+	}
+
+	/**
+	 * Create constraints for element located on x,y positions in
+	 * {@link GridBagLayout}.
+	 * 
+	 * @param x
+	 *          column
+	 * @param y
+	 *          row
+	 * @return {@link GridBagConstraints} for object at specified coordinates
+	 */
+	public GridBagConstraints createLayoutConstraints(int x, int y) {
+		GridBagConstraints c = new GridBagConstraints();
+		c.fill = GridBagConstraints.HORIZONTAL;
+		c.anchor = GridBagConstraints.NORTH;
+		c.weightx = GRID_RATIO;
+		c.gridx = x;
+		c.gridy = y;
+		return c;
+	}
+
+	/**
+	 * Adds listener to be thrown when properties of the {@link #element edited
+	 * Alias} is changing.
+	 * 
+	 * @param e
+	 *          {@link ElementModifiedEventListener listener} to add
+	 */
+	public void addAliasModifiedEventListener(ElementModifiedEventListener<Alias> e) {
+		aliasListeners.add(e);
+	}
+
+	/**
+	 * Adds listener to be thrown when properties of the {@link #element edited
+	 * Reaction} is changing.
+	 * 
+	 * @param e
+	 *          {@link ElementModifiedEventListener listener} to add
+	 */
+	public void addReactionModifiedEventListener(ElementModifiedEventListener<Reaction> e) {
+		reactionListeners.add(e);
+	}
+
+	/**
+	 * Returns {@link Model} where edited element is located.
+	 * 
+	 * @return {@link Model} where edited element is located
+	 */
+	private Model getModel() {
+		if (element instanceof Alias) {
+			return ((Alias) element).getModel();
+		} else if (element instanceof Reaction) {
+			return ((Reaction) element).getModel();
+		} else if (element != null) {
+			throw new InvalidStateException("Don't know how to handle object of class: " + element.getClass());
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * Created {@link ObjectEditDialog} that can edit objects of type specified in
+	 * parameter.
+	 * 
+	 * @param dialogTitle
+	 *          title that should be used in a dialog
+	 * @param clazz
+	 *          class of a type of the object to edit
+	 * @return {@link ObjectEditDialog} that can edit objects of type specified in
+	 *         parameter
+	 * @param <T>
+	 *          type of the object to edit
+	 */
+	@SuppressWarnings("unchecked")
+	private <T> ObjectEditDialog<T> createEditDialog(String dialogTitle, Class<T> clazz) {
+		if (String.class.equals(clazz)) {
+			return (ObjectEditDialog<T>) new StringEditDialog(null, dialogTitle, dialogTitle);
+		} else 		if (MiriamData.class.equals(clazz)) {
+			return (ObjectEditDialog<T>) new MiriamDataDialog(null, dialogTitle, dialogTitle);
+		} else {
+			throw new NotImplementedException("Don't know how to handle: " + clazz);
+		}
+	}
+}
-- 
GitLab