/* * Freeplane - mind map editor * Copyright (C) 2008 Dimitry Polivaev * * This file author is Dimitry Polivaev * * 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, see <http://www.gnu.org/licenses/>. */ package org.freeplane.features.attribute.mindmapmode; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.Collection; import java.util.Iterator; 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.JRadioButton; import javax.swing.border.Border; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ListDataListener; import org.freeplane.core.ui.MenuBuilder; import org.freeplane.core.ui.components.TypedListCellRenderer; import org.freeplane.core.ui.components.UITools; import org.freeplane.core.util.TextUtils; import org.freeplane.features.attribute.Attribute; import org.freeplane.features.attribute.AttributeController; import org.freeplane.features.attribute.AttributeRegistry; import org.freeplane.features.attribute.AttributeRegistryElement; import org.freeplane.features.attribute.IAttributesListener; import org.freeplane.features.attribute.NodeAttributeTableModel; import org.freeplane.features.map.IMapSelection; import org.freeplane.features.map.IMapSelectionListener; import org.freeplane.features.map.MapModel; import org.freeplane.features.map.NodeModel; import org.freeplane.features.mode.Controller; class AssignAttributeDialog extends JDialog implements IAttributesListener, IMapSelectionListener { private class AddAction extends IteratingAction { private String name; private String value; @Override public void actionPerformed(final ActionEvent e) { if (attributeNames.getSelectedItem() == null) { UITools.showAttributeEmptyStringErrorMessage(); return; } name = attributeNames.getSelectedItem().toString(); if (name.equals("")) { UITools.showAttributeEmptyStringErrorMessage(); return; } final Object valueSelectedItem = attributeValues.getSelectedItem(); value = valueSelectedItem != null ? valueSelectedItem.toString() : ""; super.actionPerformed(e); if (valueSelectedItem == null) { selectedAttributeChanged(name, attributeValues); } } @Override protected void performAction(final NodeModel model) { attributeController.createAttributeTableModel(model); final NodeAttributeTableModel attributes = NodeAttributeTableModel.getModel(model); attributeController.performInsertRow(attributes, attributes.getRowCount(), name, value); } } protected static class ClonedComboBoxModel extends AbstractListModel implements ComboBoxModel { /** * */ private static final long serialVersionUID = 1L; private Object selectedItem; final private AbstractListModel sharedListModel; public ClonedComboBoxModel(final ComboBoxModel sharedListModel) { super(); this.sharedListModel = (AbstractListModel) sharedListModel; } @Override public void addListDataListener(final ListDataListener l) { super.addListDataListener(l); sharedListModel.addListDataListener(l); } public Object getElementAt(final int index) { return sharedListModel.getElementAt(index); } public Object getSelectedItem() { return selectedItem; } public int getSize() { return sharedListModel.getSize(); } @Override public void removeListDataListener(final ListDataListener l) { super.removeListDataListener(l); sharedListModel.removeListDataListener(l); } public void setSelectedItem(final Object anItem) { selectedItem = anItem; fireContentsChanged(this, -1, -1); } } private class DeleteAttributeAction extends IteratingAction { private String name; @Override public void actionPerformed(final ActionEvent e) { final Object selectedItem = attributeNames.getSelectedItem(); if (selectedItem == null) { UITools.showAttributeEmptyStringErrorMessage(); return; } name = selectedItem.toString(); if (name.equals("")) { UITools.showAttributeEmptyStringErrorMessage(); return; } super.actionPerformed(e); } @Override protected void performAction(final NodeModel model) { final NodeAttributeTableModel attributes = NodeAttributeTableModel.getModel(model); for (int i = attributes.getRowCount() - 1; i >= 0; i--) { if (attributes.getAttribute(i).getName().equals(name)) { attributeController.performRemoveRow(attributes, i); } } } } private class DeleteValueAction extends IteratingAction { private String name; private String value; @Override public void actionPerformed(final ActionEvent e) { if (attributeNames.getSelectedItem() == null) { UITools.showAttributeEmptyStringErrorMessage(); return; } name = attributeNames.getSelectedItem().toString(); if (name.equals("")) { UITools.showAttributeEmptyStringErrorMessage(); return; } final Object valueSelectedItem = attributeValues.getSelectedItem(); value = valueSelectedItem != null ? valueSelectedItem.toString() : ""; super.actionPerformed(e); } @Override protected void performAction(final NodeModel model) { final NodeAttributeTableModel attributes = NodeAttributeTableModel.getModel(model); for (int i = attributes.getRowCount() - 1; i >= 0; i--) { final Attribute attribute = attributes.getAttribute(i); if (attribute.getName().equals(name) && attribute.getValue().equals(value)) { attributeController.performRemoveRow(attributes, i); } } } } private abstract class IteratingAction implements ActionListener { public void actionPerformed(final ActionEvent e) { try { if (selectedBtn.getModel().isSelected()) { final Collection<NodeModel> selecteds = mapSelection.getSelection(); final Iterator<NodeModel> iterator = selecteds.iterator(); while (iterator.hasNext()) { final NodeModel selectedNodeView = iterator.next(); performAction(selectedNodeView); } return; } final NodeModel nodeView = Controller.getCurrentController().getMap().getRootNode(); iterate(nodeView); } catch (final NullPointerException ex) { } } private void iterate(final NodeModel node) { if (node.isVisible()) { if (!node.isRoot() || !skipRootBtn.isSelected()) { performAction(node); } } if (node.isFolded()) { return; } final Iterator<NodeModel> iterator = node.getChildren().iterator(); while (iterator.hasNext()) { iterate(iterator.next()); } } abstract protected void performAction(NodeModel model); } private class ReplaceValueAction extends IteratingAction { private String name; private String replacingName; private String replacingValue; private String value; @Override public void actionPerformed(final ActionEvent e) { if (attributeNames.getSelectedItem() == null) { UITools.showAttributeEmptyStringErrorMessage(); return; } if (replacingAttributeNames.getSelectedItem() == null) { UITools.showAttributeEmptyStringErrorMessage(); return; } name = attributeNames.getSelectedItem().toString(); if (name.equals("")) { UITools.showAttributeEmptyStringErrorMessage(); return; } replacingName = replacingAttributeNames.getSelectedItem().toString(); if (replacingName.equals("")) { UITools.showAttributeEmptyStringErrorMessage(); return; } final Object valueSelectedItem = attributeValues.getSelectedItem(); value = valueSelectedItem != null ? valueSelectedItem.toString() : ""; final Object replacingValueSelectedItem = replacingAttributeValues.getSelectedItem(); replacingValue = replacingValueSelectedItem != null ? replacingValueSelectedItem.toString() : ""; super.actionPerformed(e); } @Override protected void performAction(final NodeModel model) { final NodeAttributeTableModel attributes = NodeAttributeTableModel.getModel(model); for (int i = attributes.getRowCount() - 1; i >= 0; i--) { final Attribute attribute = attributes.getAttribute(i); if (attribute.getName().equals(name) && attribute.getValue().equals(value)) { attributeController.performRemoveRow(attributes, i); attributeController.performInsertRow(attributes, i, replacingName, replacingValue); } } } } private static final Dimension maxButtonDimension = new Dimension(1000, 1000); /** * */ private static final long serialVersionUID = 1L; final private AttributeController attributeController; final private JComboBox attributeNames; final private JComboBox attributeValues; private IMapSelection mapSelection; final private JComboBox replacingAttributeNames; final private JComboBox replacingAttributeValues; final private JRadioButton selectedBtn; final private JCheckBox skipRootBtn; final private JRadioButton visibleBtn; public AssignAttributeDialog(final AttributeController attributeController, final Frame frame) { super(frame, TextUtils.getText("attributes_assign_dialog"), false); this.attributeController = attributeController; mapSelection = Controller.getCurrentController().getSelection(); final Border actionBorder = new CompoundBorder(new EmptyBorder(5, 10, 0, 10), new CompoundBorder( new EtchedBorder(), new EmptyBorder(5, 5, 5, 5))); final Border emptyBorder = new EmptyBorder(5, 5, 5, 5); final Border btnBorder = new EmptyBorder(2, 2, 2, 2); selectedBtn = new JRadioButton(); MenuBuilder.setLabelAndMnemonic(selectedBtn, TextUtils.getRawText("attributes_for_selected")); selectedBtn.setSelected(true); visibleBtn = new JRadioButton(); MenuBuilder.setLabelAndMnemonic(visibleBtn, TextUtils.getRawText("attributes_for_visible")); final ButtonGroup group = new ButtonGroup(); group.add(selectedBtn); group.add(visibleBtn); skipRootBtn = new JCheckBox(); MenuBuilder.setLabelAndMnemonic(skipRootBtn, TextUtils.getRawText("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(); MenuBuilder.setLabelAndMnemonic(addBtn, TextUtils.getRawText("filter_add")); addBtn.addActionListener(new AddAction()); addBtn.setMaximumSize(AssignAttributeDialog.maxButtonDimension); final JButton deleteAttributeBtn = new JButton(); MenuBuilder.setLabelAndMnemonic(deleteAttributeBtn, TextUtils.getRawText("attribute_delete")); deleteAttributeBtn.addActionListener(new DeleteAttributeAction()); deleteAttributeBtn.setMaximumSize(AssignAttributeDialog.maxButtonDimension); final JButton deleteAttributeValueBtn = new JButton(); MenuBuilder.setLabelAndMnemonic(deleteAttributeValueBtn, TextUtils.getRawText("attribute_delete_value")); deleteAttributeValueBtn.addActionListener(new DeleteValueAction()); deleteAttributeValueBtn.setMaximumSize(AssignAttributeDialog.maxButtonDimension); final JButton replaceBtn = new JButton(); MenuBuilder.setLabelAndMnemonic(replaceBtn, TextUtils.getRawText("attribute_replace")); replaceBtn.addActionListener(new ReplaceValueAction()); replaceBtn.setMaximumSize(AssignAttributeDialog.maxButtonDimension); UITools.addEscapeActionToDialog(this); // Size of JComboBoxes (30 chars) final String pattern = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; final JLabel patternLabel = new JLabel(pattern); final Dimension comboBoxMaximumSize = patternLabel.getPreferredSize(); comboBoxMaximumSize.width += 4; comboBoxMaximumSize.height += 10; attributeNames = new JComboBox(); attributeNames.setMaximumSize(comboBoxMaximumSize); attributeNames.setPreferredSize(comboBoxMaximumSize); attributeNames.addItemListener(new ItemListener() { public void itemStateChanged(final ItemEvent e) { selectedAttributeChanged(e.getItem(), attributeValues); } }); attributeValues = new JComboBox(); attributeValues.setRenderer(new TypedListCellRenderer()); attributeValues.setMaximumSize(comboBoxMaximumSize); attributeValues.setPreferredSize(comboBoxMaximumSize); replacingAttributeNames = new JComboBox(); replacingAttributeNames.setMaximumSize(comboBoxMaximumSize); replacingAttributeNames.setPreferredSize(comboBoxMaximumSize); replacingAttributeNames.addItemListener(new ItemListener() { public void itemStateChanged(final ItemEvent e) { selectedAttributeChanged(e.getItem(), replacingAttributeValues); } }); replacingAttributeValues = new JComboBox(); replacingAttributeValues.setRenderer(new TypedListCellRenderer()); 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); final Box replaceBox = Box.createHorizontalBox(); replaceBox.setBorder(btnBorder); replaceBox.add(Box.createHorizontalGlue()); replaceBox.add(replaceBtn); replaceBox.add(Box.createHorizontalStrut(5)); replaceBox.add(replacingAttributeNames); replaceBox.add(Box.createHorizontalStrut(5)); replaceBox.add(replacingAttributeValues); replaceBox.add(Box.createHorizontalStrut(5)); outerReplaceBox.add(Box.createVerticalGlue()); outerReplaceBox.add(replaceBox); outerReplaceBox.add(Box.createVerticalGlue()); final Box actionBox = Box.createVerticalBox(); actionBox.add(Box.createVerticalGlue()); actionBox.add(addDeleteBox); actionBox.add(Box.createVerticalStrut(5)); actionBox.add(outerReplaceBox); actionBox.add(Box.createVerticalGlue()); getContentPane().add(actionBox, BorderLayout.CENTER); final JButton closeBtn = new JButton(); MenuBuilder.setLabelAndMnemonic(closeBtn, TextUtils.getRawText("simplyhtml.closeBtnName")); closeBtn.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { dispose(); } }); final Box bottomBox = Box.createHorizontalBox(); bottomBox.setBorder(emptyBorder); bottomBox.add(Box.createHorizontalGlue()); bottomBox.add(closeBtn); bottomBox.add(Box.createHorizontalGlue()); getContentPane().add(bottomBox, BorderLayout.SOUTH); pack(); comboBoxMaximumSize.width = 1000; attributeNames.setMaximumSize(comboBoxMaximumSize); attributeValues.setMaximumSize(comboBoxMaximumSize); replacingAttributeNames.setMaximumSize(comboBoxMaximumSize); replacingAttributeValues.setMaximumSize(comboBoxMaximumSize); afterMapChange(null, Controller.getCurrentController().getMap()); Controller.getCurrentController().getMapViewManager().addMapSelectionListener(this); } public void afterMapChange(final MapModel oldMap, final MapModel newMap) { if (oldMap != null) { final AttributeRegistry attributes = AttributeRegistry.getRegistry(oldMap); if (attributes != null) { attributes.removeAttributesListener(this); } } if (newMap == null) { setVisible(false); return; } mapSelection = Controller.getCurrentController().getSelection(); final AttributeRegistry attributes = AttributeRegistry.getRegistry(newMap); if (attributes == null) { setVisible(false); return; } attributes.addAttributesListener(this); attributesChanged(); } private void attributesChanged() { final MapModel map = Controller.getCurrentController().getMap(); final AttributeRegistry attributes = AttributeRegistry.getRegistry(map); final ComboBoxModel names = attributes.getComboBoxModel(); attributeNames.setModel(new ClonedComboBoxModel(names)); attributeNames.setEditable(!attributes.isRestricted()); replacingAttributeNames.setModel(new ClonedComboBoxModel(names)); replacingAttributeNames.setEditable(!attributes.isRestricted()); if (attributes.size() > 0) { final Object first = names.getElementAt(0); attributeNames.setSelectedItem(first); replacingAttributeNames.setSelectedItem(first); selectedAttributeChanged(attributeNames.getSelectedItem(), attributeValues); selectedAttributeChanged(replacingAttributeNames.getSelectedItem(), replacingAttributeValues); } else { attributeValues.setModel(new DefaultComboBoxModel()); attributeValues.setEditable(false); replacingAttributeValues.setModel(new DefaultComboBoxModel()); replacingAttributeValues.setEditable(false); } } public void attributesChanged(final ChangeEvent e) { attributesChanged(); } public void beforeMapChange(final MapModel oldMap, final MapModel newMap) { } private void selectedAttributeChanged(final Object selectedAttributeName, final JComboBox values) { final MapModel map = Controller.getCurrentController().getMap(); final AttributeRegistry attributes = AttributeRegistry.getRegistry(map); try { final AttributeRegistryElement element = attributes.getElement(selectedAttributeName.toString()); final ComboBoxModel selectedValues = element.getValues(); values.setModel(new ClonedComboBoxModel(selectedValues)); try { final Object firstValue = selectedValues.getElementAt(0); values.setSelectedItem(firstValue); } catch (final ArrayIndexOutOfBoundsException ex) { } values.setEditable(!element.isRestricted()); } catch (final NoSuchElementException ex) { values.setEditable(!selectedAttributeName.toString().equals("")); } } }