gt: 		final Box replaceBox = Box.createHorizontalBox();
context: /*FreeMind - A Program for creating and viewing Mindmaps
   *Copyright (C) 2000-2006 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitri Polivaev and others.
   *
   *See COPYING for Details
   *
   *This program is free software; you can redistribute it and/or
   *modify it under the terms of the GNU General Public License
   *as published by the Free Software Foundation; either version 2
   *of the License, or (at your option) any later version.
   *
   *This program is distributed in the hope that it will be useful,
   *but WITHOUT ANY WARRANTY; without even the implied warranty of
   *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *GNU General Public License for more details.
   *
   *You should have received a copy of the GNU General Public License
   *along with this program; if not, write to the Free Software
   *Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   */
  /*
   * Created on 10.12.2005
   * Copyright (C) 2005 Dimitri Polivaev
   */
  package freemind.modes.mindmapmode.attributeactors;
  
  import java.awt.BorderLayout;
  import java.awt.Color;
  import java.awt.Component;
  import java.awt.Dimension;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.awt.event.ItemEvent;
  import java.awt.event.ItemListener;
  import java.util.LinkedList;
  import java.util.ListIterator;
  import java.util.NoSuchElementException;
  
  import javax.swing.AbstractListModel;
  import javax.swing.Box;
  import javax.swing.ButtonGroup;
  import javax.swing.ComboBoxModel;
  import javax.swing.DefaultComboBoxModel;
  import javax.swing.JButton;
  import javax.swing.JCheckBox;
  import javax.swing.JComboBox;
  import javax.swing.JDialog;
  import javax.swing.JLabel;
  import javax.swing.JOptionPane;
  import javax.swing.JRadioButton;
  import javax.swing.border.Border;
  import javax.swing.border.EmptyBorder;
  import javax.swing.border.MatteBorder;
  import javax.swing.event.ChangeEvent;
  import javax.swing.event.ListDataEvent;
  import javax.swing.event.ListDataListener;
  
  import freemind.controller.MapModuleManager.MapModuleChangeObserver;
  import freemind.main.Resources;
  import freemind.main.Tools;
  import freemind.modes.MindMap;
  import freemind.modes.MindMapNode;
  import freemind.modes.Mode;
  import freemind.modes.attributes.Attribute;
  import freemind.modes.attributes.AttributeRegistry;
  import freemind.modes.attributes.AttributeRegistryElement;
  import freemind.modes.attributes.NodeAttributeTableModel;
  import freemind.modes.mindmapmode.MindMapMode;
  import freemind.view.MapModule;
  import freemind.view.mindmapview.MapView;
  import freemind.view.mindmapview.NodeView;
  
  public class AssignAttributeDialog extends JDialog implements
  		AttributesListener, MapModuleChangeObserver {
  	private static class ClonedComboBoxModel extends AbstractListModel
  			implements ComboBoxModel {
  		private AbstractListModel sharedListModel;
  		private Object selectedItem;
  		private ListDataEvent ev = null;
  
  		public ClonedComboBoxModel(ComboBoxModel sharedListModel) {
  			super();
  			this.sharedListModel = (AbstractListModel) sharedListModel;
  		}
  
  		public void addListDataListener(ListDataListener l) {
  			super.addListDataListener(l);
  			sharedListModel.addListDataListener(l);
  		}
  
  		public Object getElementAt(int index) {
  			return sharedListModel.getElementAt(index);
  		}
  
  		public int getSize() {
  			return sharedListModel.getSize();
  		}
  
  		public void removeListDataListener(ListDataListener l) {
  			super.removeListDataListener(l);
  			sharedListModel.removeListDataListener(l);
  		}
  
  		public void setSelectedItem(Object anItem) {
  			selectedItem = anItem;
  			fireContentsChanged(this, -1, -1);
  		}
  
  		private ListDataEvent getContentChangedEvent() {
  			if (ev == null) {
  				ev = new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED,
  						-1, -1);
  			}
  			return ev;
  		}
  
  		public Object getSelectedItem() {
  			return selectedItem;
  		}
  	}
  
  	private abstract class IteratingAction implements ActionListener {
  		public void actionPerformed(ActionEvent e) {
  			try {
  				if (selectedBtn.getModel().isSelected()) {
  					LinkedList selecteds = mapView.getSelecteds();
  					ListIterator iterator = selecteds.listIterator();
  					while (iterator.hasNext()) {
  						NodeView selectedNodeView = (NodeView) iterator.next();
  						performAction(selectedNodeView);
  					}
  					return;
  				}
  				final NodeView nodeView = mapView.getRoot();
  				iterate(nodeView);
  			} catch (NullPointerException ex) {
  
  			}
  		}
  
  		private void iterate(final NodeView nodeView) {
  			int n = nodeView.getComponentCount();
  			if (nodeView.isVisible()) {
  				performAction(nodeView);
  			}
  			for (int i = 0; i < n; i++) {
  				Component component = nodeView.getComponent(i);
  				if (component instanceof NodeView) {
  					iterate((NodeView) component);
  				}
  			}
  		}
  
  		private void performAction(NodeView selectedNodeView) {
  			if (!selectedNodeView.isRoot() || !skipRootBtn.isSelected())
  				performAction(selectedNodeView.getModel());
  		}
  
  		abstract protected void performAction(MindMapNode model);
  
  		protected void showEmptyStringErrorMessage() {
  			JOptionPane.showMessageDialog(
  					AssignAttributeDialog.this,
  					Resources.getInstance().getResourceString(
  							"attributes_adding_empty_attribute_error"),
  					Resources.getInstance().getResourceString("error"),
  					JOptionPane.ERROR_MESSAGE);
  		}
  	}
  
  	private class AddAction extends IteratingAction {
  		private String name;
  		private String value;
  
  		protected void performAction(MindMapNode model) {
  			model.createAttributeTableModel();
  			NodeAttributeTableModel attributes = model.getAttributes();
  			attributes.getAttributeController().performInsertRow(attributes,
  					attributes.getRowCount(), name, value);
  		}
  
  		public void actionPerformed(ActionEvent e) {
  			if (attributeNames.getSelectedItem() == null) {
  				showEmptyStringErrorMessage();
  				return;
  			}
  
  			name = attributeNames.getSelectedItem().toString();
  			if (name.equals("")) {
  				showEmptyStringErrorMessage();
  				return;
  			}
  			Object valueSelectedItem = attributeValues.getSelectedItem();
  			value = valueSelectedItem != null ? valueSelectedItem.toString()
  					: "";
  
  			super.actionPerformed(e);
  			if (valueSelectedItem == null) {
  				selectedAttributeChanged(name, attributeValues);
  			}
  		}
  
  	}
  
  	private class DeleteAttributeAction extends IteratingAction {
  		private String name;
  
  		public void actionPerformed(ActionEvent e) {
  			final Object selectedItem = attributeNames.getSelectedItem();
  			if (selectedItem == null) {
  				showEmptyStringErrorMessage();
  				return;
  			}
  			name = selectedItem.toString();
  			if (name.equals("")) {
  				showEmptyStringErrorMessage();
  				return;
  			}
  			super.actionPerformed(e);
  		}
  
  		protected void performAction(MindMapNode model) {
  			NodeAttributeTableModel attributes = model.getAttributes();
  			for (int i = attributes.getRowCount() - 1; i >= 0; i--) {
  				if (attributes.getAttribute(i).getName().equals(name)) {
  					attributes.getAttributeController().performRemoveRow(
  							attributes, i);
  				}
  			}
  		}
  	}
  
  	private class DeleteValueAction extends IteratingAction {
  		private String name;
  		private String value;
  
  		public void actionPerformed(ActionEvent e) {
  			if (attributeNames.getSelectedItem() == null) {
  				showEmptyStringErrorMessage();
  				return;
  			}
  
  			name = attributeNames.getSelectedItem().toString();
  			if (name.equals("")) {
  				showEmptyStringErrorMessage();
  				return;
  			}
  			Object valueSelectedItem = attributeValues.getSelectedItem();
  			value = valueSelectedItem != null ? valueSelectedItem.toString()
  					: "";
  
  			super.actionPerformed(e);
  		}
  
  		protected void performAction(MindMapNode model) {
  			NodeAttributeTableModel attributes = model.getAttributes();
  			for (int i = attributes.getRowCount() - 1; i >= 0; i--) {
  				Attribute attribute = attributes.getAttribute(i);
  				if (attribute.getName().equals(name)
  						&& attribute.getValue().equals(value)) {
  					attributes.getAttributeController().performRemoveRow(
  							attributes, i);
  				}
  			}
  		}
  	}
  
  	private class ReplaceValueAction extends IteratingAction {
  		private String name;
  		private String value;
  		private String replacingName;
  		private String replacingValue;
  
  		public void actionPerformed(ActionEvent e) {
  			if (attributeNames.getSelectedItem() == null) {
  				showEmptyStringErrorMessage();
  				return;
  			}
  			if (replacingAttributeNames.getSelectedItem() == null) {
  				showEmptyStringErrorMessage();
  				return;
  			}
  			name = attributeNames.getSelectedItem().toString();
  			if (name.equals("")) {
  				showEmptyStringErrorMessage();
  				return;
  			}
  			replacingName = replacingAttributeNames.getSelectedItem()
  					.toString();
  			if (replacingName.equals("")) {
  				showEmptyStringErrorMessage();
  				return;
  			}
  			Object valueSelectedItem = attributeValues.getSelectedItem();
  			value = valueSelectedItem != null ? valueSelectedItem.toString()
  					: "";
  			Object replacingValueSelectedItem = replacingAttributeValues
  					.getSelectedItem();
  			replacingValue = replacingValueSelectedItem != null ? replacingValueSelectedItem
  					.toString() : "";
  			super.actionPerformed(e);
  		}
  
  		protected void performAction(MindMapNode model) {
  			NodeAttributeTableModel attributes = model.getAttributes();
  			for (int i = attributes.getRowCount() - 1; i >= 0; i--) {
  				Attribute attribute = attributes.getAttribute(i);
  				if (attribute.getName().equals(name)
  						&& attribute.getValue().equals(value)) {
  					attributes.getAttributeController().performRemoveRow(
  							attributes, i);
  					attributes.insertRow(i, replacingName, replacingValue);
  				}
  			}
  		}
  	}
  
  	private static final Dimension maxButtonDimension = new Dimension(1000,
  			1000);
  
  	private MapView mapView;
  	private JComboBox attributeNames;
  	private JComboBox attributeValues;
  	private JComboBox replacingAttributeNames;
  	private JComboBox replacingAttributeValues;
  
  	private JRadioButton selectedBtn;
  
  	private JRadioButton visibleBtn;
  
  	private JCheckBox skipRootBtn;
  
  	public AssignAttributeDialog(MapView mapView) {
  		super(JOptionPane.getFrameForComponent(mapView), Tools
  				.removeMnemonic(Resources.getInstance().getResourceString(
  						"attributes_assign_dialog")), false);
  
  		final Border actionBorder = new MatteBorder(2, 2, 2, 2, Color.BLACK);
  		final Border emptyBorder = new EmptyBorder(5, 5, 5, 5);
  		final Border btnBorder = new EmptyBorder(2, 2, 2, 2);
  
  		selectedBtn = new JRadioButton();
  		Tools.setLabelAndMnemonic(selectedBtn, Resources.getInstance()
  				.getResourceString("attributes_for_selected"));
  		selectedBtn.setSelected(true);
  		visibleBtn = new JRadioButton();
  		Tools.setLabelAndMnemonic(visibleBtn, Resources.getInstance()
  				.getResourceString("attributes_for_visible"));
  		final ButtonGroup group = new ButtonGroup();
  		group.add(selectedBtn);
  		group.add(visibleBtn);
  
  		skipRootBtn = new JCheckBox();
  		Tools.setLabelAndMnemonic(skipRootBtn, Resources.getInstance()
  				.getResourceString("attributes_skip_root"));
  		skipRootBtn.setSelected(true);
  
  		final Box selectionBox = Box.createHorizontalBox();
  		selectionBox.setBorder(emptyBorder);
  		selectionBox.add(Box.createHorizontalGlue());
  		selectionBox.add(selectedBtn);
  		selectionBox.add(Box.createHorizontalGlue());
  		selectionBox.add(visibleBtn);
  		selectionBox.add(Box.createHorizontalGlue());
  		selectionBox.add(skipRootBtn);
  		selectionBox.add(Box.createHorizontalGlue());
  
  		getContentPane().add(selectionBox, BorderLayout.NORTH);
  
  		final JButton addBtn = new JButton();
  		Tools.setLabelAndMnemonic(addBtn, Resources.getInstance()
  				.getResourceString("filter_add"));
  		addBtn.addActionListener(new AddAction());
  		addBtn.setMaximumSize(maxButtonDimension);
  
  		JButton deleteAttributeBtn = new JButton();
  		Tools.setLabelAndMnemonic(deleteAttributeBtn, Resources.getInstance()
  				.getResourceString("attribute_delete"));
  		deleteAttributeBtn.addActionListener(new DeleteAttributeAction());
  		deleteAttributeBtn.setMaximumSize(maxButtonDimension);
  
  		JButton deleteAttributeValueBtn = new JButton();
  		Tools.setLabelAndMnemonic(deleteAttributeValueBtn, Resources
  				.getInstance().getResourceString("attribute_delete_value"));
  		deleteAttributeValueBtn.addActionListener(new DeleteValueAction());
  		deleteAttributeValueBtn.setMaximumSize(maxButtonDimension);
  
  		JButton replaceBtn = new JButton();
  		Tools.setLabelAndMnemonic(replaceBtn, Resources.getInstance()
  				.getResourceString("attribute_replace"));
  		replaceBtn.addActionListener(new ReplaceValueAction());
  		replaceBtn.setMaximumSize(maxButtonDimension);
  
  		Tools.addEscapeActionToDialog(this);
  
  		final String pattern = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
  		final JLabel patternLabel = new JLabel(pattern);
  		final Dimension comboBoxMaximumSize = patternLabel.getPreferredSize();
  		comboBoxMaximumSize.width += 4;
  		comboBoxMaximumSize.height += 4;
  		attributeNames = new JComboBox();
  		attributeNames.setMaximumSize(comboBoxMaximumSize);
  		attributeNames.setPreferredSize(comboBoxMaximumSize);
  		attributeNames.addItemListener(new ItemListener() {
  			public void itemStateChanged(ItemEvent e) {
  				selectedAttributeChanged(e.getItem(), attributeValues);
  			}
  		});
  		attributeValues = new JComboBox();
  		attributeValues.setMaximumSize(comboBoxMaximumSize);
  		attributeValues.setPreferredSize(comboBoxMaximumSize);
  		replacingAttributeNames = new JComboBox();
  		replacingAttributeNames.setMaximumSize(comboBoxMaximumSize);
  		replacingAttributeNames.setPreferredSize(comboBoxMaximumSize);
  		replacingAttributeNames.addItemListener(new ItemListener() {
  			public void itemStateChanged(ItemEvent e) {
  				selectedAttributeChanged(e.getItem(), replacingAttributeValues);
  			}
  		});
  		replacingAttributeValues = new JComboBox();
  		replacingAttributeValues.setMaximumSize(comboBoxMaximumSize);
  		replacingAttributeValues.setPreferredSize(comboBoxMaximumSize);
  
  		final Box addDeleteBtnBox = Box.createVerticalBox();
  		addDeleteBtnBox.setBorder(btnBorder);
  		addDeleteBtnBox.add(Box.createVerticalGlue());
  		addDeleteBtnBox.add(addBtn);
  		addDeleteBtnBox.add(deleteAttributeBtn);
  		addDeleteBtnBox.add(deleteAttributeValueBtn);
  		addDeleteBtnBox.add(Box.createVerticalGlue());
  
  		final Box addDeleteBox = Box.createHorizontalBox();
  		addDeleteBox.setBorder(actionBorder);
  		addDeleteBox.add(Box.createHorizontalGlue());
  		addDeleteBox.add(addDeleteBtnBox);
  		addDeleteBox.add(Box.createHorizontalStrut(5));
  		addDeleteBox.add(attributeNames);
  		addDeleteBox.add(Box.createHorizontalStrut(5));
  		addDeleteBox.add(attributeValues);
  		addDeleteBox.add(Box.createHorizontalStrut(5));
  
  		final Box outerReplaceBox = Box.createVerticalBox();
  		outerReplaceBox.setBorder(actionBorder);
  
  