/*
* 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.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.Map.Entry;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreeSelectionModel;
import org.freeplane.core.ui.MenuBuilder;
import org.freeplane.core.ui.components.UITools;
import org.freeplane.core.util.TextUtils;
import org.freeplane.core.util.collection.SortedComboBoxModel;
import org.freeplane.features.attribute.AttributeRegistry;
import org.freeplane.features.attribute.AttributeRegistryElement;
import org.freeplane.features.icon.IconStore;
import org.freeplane.features.icon.factory.IconStoreFactory;
import org.freeplane.features.map.MapModel;
import org.freeplane.features.mode.Controller;
import org.freeplane.features.ui.IMapViewManager;
class ImportAttributesDialog extends JDialog implements TreeSelectionListener {
private static final IconStore STORE = IconStoreFactory.create();
static private class AttributeTreeNodeInfo extends TreeNodeInfo {
final private boolean restricted;
public AttributeTreeNodeInfo(final String info, final boolean restricted) {
super(info);
this.restricted = restricted;
}
boolean isRestricted() {
return restricted;
}
}
static private class MyRenderer extends DefaultTreeCellRenderer {
static final Icon iconFull = STORE.getUIIcon("ok_button.png").getIcon();
static final Icon iconNotSelected = STORE.getUIIcon("cancel_button.png").getIcon();
static final Icon iconPartial = STORE.getUIIcon("forward.png").getIcon();
/**
*
*/
private static final long serialVersionUID = 1L;
public MyRenderer() {
}
@Override
public Component getTreeCellRendererComponent(final JTree tree, final Object value, final boolean sel,
final boolean expanded, final boolean leaf, final int row,
final boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, false, expanded, leaf, row, false);
final DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
final TreeNodeInfo info = (TreeNodeInfo) node.getUserObject();
switch (info.getSelected()) {
case TreeNodeInfo.FULL_SELECTED:
setIcon(MyRenderer.iconFull);
break;
case TreeNodeInfo.PARTIAL_SELECTED:
setIcon(MyRenderer.iconPartial);
break;
case TreeNodeInfo.NOT_SELECTED:
setIcon(MyRenderer.iconNotSelected);
break;
}
return this;
}
}
static private class TreeNodeInfo {
static final private int FULL_SELECTED = 0;
static final private int NOT_SELECTED = 2;
static final private int PARTIAL_SELECTED = 1;
final private String info;
private int selected;
public TreeNodeInfo(final String info) {
this.info = info;
selected = TreeNodeInfo.NOT_SELECTED;
}
String getInfo() {
return info;
}
int getSelected() {
return selected;
}
void setSelected(final int selected) {
this.selected = selected;
}
@Override
public String toString() {
return info;
}
}
/**
*
*/
private static final long serialVersionUID = 1L;
// // final private Controller controller;
private AttributeRegistry currentAttributes;
final private Component parentComponent;
MyRenderer renderer = null;
final private JScrollPane scrollPane;
final private DefaultMutableTreeNode topNode;
final private JTree tree;
final private DefaultTreeModel treeModel;
public ImportAttributesDialog( final Component parentComponent) {
super(Controller.getCurrentController().getViewController().getFrame(), TextUtils
.getText("attributes_import"), true);
// this.controller = controller;
this.parentComponent = parentComponent;
final TreeNodeInfo nodeInfo = new TreeNodeInfo(TextUtils.getText("attribute_top"));
topNode = new DefaultMutableTreeNode(nodeInfo);
treeModel = new DefaultTreeModel(topNode);
tree = new JTree(treeModel);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(this);
scrollPane = new JScrollPane();
scrollPane.setViewportView(tree);
scrollPane.setPreferredSize(new Dimension(600, 300));
getContentPane().add(scrollPane, BorderLayout.CENTER);
final Box buttons = Box.createHorizontalBox();
buttons.setBorder(new EmptyBorder(5, 5, 5, 5));
final JButton okBtn = new JButton();
MenuBuilder.setLabelAndMnemonic(okBtn, TextUtils.getRawText("ok"));
okBtn.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
performImport(topNode);
dispose();
}
});
final JButton cancelBtn = new JButton();
MenuBuilder.setLabelAndMnemonic(cancelBtn, TextUtils.getRawText("cancel"));
cancelBtn.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
dispose();
}
});
buttons.add(Box.createHorizontalGlue());
buttons.add(okBtn);
buttons.add(Box.createHorizontalGlue());
buttons.add(cancelBtn);
buttons.add(Box.createHorizontalGlue());
getContentPane().add(buttons, BorderLayout.SOUTH);
UITools.addEscapeActionToDialog(this);
}
private void createAttributeSubTrees(final DefaultMutableTreeNode mapInfo, final AttributeRegistry attributes) {
if (attributes == null) {
return;
}
for (int i = 0; i < attributes.size(); i++) {
final AttributeRegistryElement element = attributes.getElement(i);
final TreeNodeInfo treeNodeInfo = new AttributeTreeNodeInfo(element.getKey().toString(), element
.isRestricted());
final DefaultMutableTreeNode attributeInfo = new DefaultMutableTreeNode(treeNodeInfo);
createValueSubTrees(attributeInfo, element, currentAttributes);
if (attributeInfo.getChildCount() != 0) {
mapInfo.add(attributeInfo);
}
}
}
private void createMapSubTrees(final DefaultMutableTreeNode top) {
top.removeAllChildren();
final TreeNodeInfo topInfo = (TreeNodeInfo) top.getUserObject();
topInfo.setSelected(TreeNodeInfo.NOT_SELECTED);
Controller controller = Controller.getCurrentController();
final IMapViewManager mapViewManager = controller.getMapViewManager();
final MapModel currentMap = controller.getMap();
currentAttributes = AttributeRegistry.getRegistry(currentMap);
final Iterator<Entry<String, MapModel>> iterator = mapViewManager.getMaps().entrySet().iterator();
while (iterator.hasNext()) {
final Entry<String, MapModel> entry = iterator.next();
final String nextmapName = entry.getKey();
final MapModel nextMap = entry.getValue();
if (nextMap == currentMap) {
continue;
}
final TreeNodeInfo treeNodeInfo = new TreeNodeInfo(nextmapName);
final DefaultMutableTreeNode mapInfo = new DefaultMutableTreeNode(treeNodeInfo);
createAttributeSubTrees(mapInfo, AttributeRegistry.getRegistry(nextMap));
if (mapInfo.getChildCount() != 0) {
top.add(mapInfo);
}
}
}
private void createValueSubTrees(final DefaultMutableTreeNode attributeInfo,
final AttributeRegistryElement element, final AttributeRegistry currentAttributes) {
final String attributeName = element.getKey().toString();
final SortedComboBoxModel values = element.getValues();
for (int i = 0; i < values.getSize(); i++) {
final Object nextElement = values.getElementAt(i);
if (!currentAttributes.exist(attributeName, nextElement)) {
final TreeNodeInfo treeNodeInfo = new TreeNodeInfo(nextElement.toString());
final DefaultMutableTreeNode valueInfo = new DefaultMutableTreeNode(treeNodeInfo);
attributeInfo.add(valueInfo);
}
}
}
private void performImport(final DefaultMutableTreeNode node) {
final TreeNodeInfo info = (TreeNodeInfo) node.getUserObject();
if (info.getSelected() == TreeNodeInfo.NOT_SELECTED) {
return;
}
final String name = info.getInfo();
boolean attributeNameRegistered = false;
for (int i = 0; i < node.getChildCount(); i++) {
final DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) node.getChildAt(i);
if (childNode.isLeaf()) {
if (attributeNameRegistered == false) {
attributeNameRegistered = true;
if (-1 == currentAttributes.indexOf(name)) {
currentAttributes.getAttributeController().performRegistryAttribute(name);
final int index = currentAttributes.indexOf(name);
currentAttributes.getAttributeController().performSetRestriction(index,
((AttributeTreeNodeInfo) info).isRestricted());
}
}
final TreeNodeInfo childInfo = (TreeNodeInfo) childNode.getUserObject();
if (childInfo.getSelected() == TreeNodeInfo.FULL_SELECTED) {
final String value = childInfo.getInfo();
currentAttributes.getAttributeController().performRegistryAttributeValue(name, value, true);
}
}
else {
performImport(childNode);
}
}
}
private void setParentSelectionType(final DefaultMutableTreeNode selectedNode, final int newSelectionType) {
final TreeNode parentNode = selectedNode.getParent();
if (parentNode == null) {
return;
}
final DefaultMutableTreeNode defaultMutableParentNode = (DefaultMutableTreeNode) parentNode;
final TreeNodeInfo info = (TreeNodeInfo) (defaultMutableParentNode).getUserObject();
if (newSelectionType == TreeNodeInfo.PARTIAL_SELECTED) {
if (info.getSelected() != TreeNodeInfo.PARTIAL_SELECTED) {
info.setSelected(TreeNodeInfo.PARTIAL_SELECTED);
treeModel.nodeChanged(defaultMutableParentNode);
}
setParentSelectionType(defaultMutableParentNode, TreeNodeInfo.PARTIAL_SELECTED);
return;
}
for (int i = 0; i < defaultMutableParentNode.getChildCount(); i++) {
final TreeNodeInfo childInfo = (TreeNodeInfo) ((DefaultMutableTreeNode) defaultMutableParentNode
.getChildAt(i)).getUserObject();
if (childInfo.getSelected() != newSelectionType) {
if (info.getSelected() != TreeNodeInfo.PARTIAL_SELECTED) {
info.setSelected(TreeNodeInfo.PARTIAL_SELECTED);
treeModel.nodeChanged(defaultMutableParentNode);
}
setParentSelectionType(defaultMutableParentNode, TreeNodeInfo.PARTIAL_SELECTED);
return;
}
}
if (info.getSelected() != newSelectionType) {
info.setSelected(newSelectionType);
treeModel.nodeChanged(defaultMutableParentNode);
}
setParentSelectionType(defaultMutableParentNode, newSelectionType);
}
private void setSelectionType(final TreeNode selectedNode, final int newSelectionType) {
final TreeNodeInfo info = (TreeNodeInfo) ((DefaultMutableTreeNode) selectedNode).getUserObject();
if (info.getSelected() != newSelectionType) {
info.setSelected(newSelectionType);
treeModel.nodeChanged(selectedNode);
}
for (int i = 0; i < selectedNode.getChildCount(); i++) {
setSelectionType(selectedNode.getChildAt(i), newSelectionType);
}
}
@Override
public void show() {
createMapSubTrees(topNode);
if (topNode.getChildCount() == 0) {
JOptionPane.showMessageDialog(parentComponent, TextUtils.getText("attributes_no_import_candidates_found"),
getTitle(), JOptionPane.INFORMATION_MESSAGE);
return;
}
treeModel.reload();
if (renderer == null) {
renderer = new MyRenderer();
}
tree.setCellRenderer(renderer);
setLocationRelativeTo(parentComponent);
pack();
super.show();
}
public void valueChanged(final TreeSelectionEvent e) {
final DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
if (selectedNode == null) {
return;
}
final TreeNodeInfo info = (TreeNodeInfo) selectedNode.getUserObject();
int newSelectionType;
switch (info.getSelected()) {
case TreeNodeInfo.FULL_SELECTED:
newSelectionType = TreeNodeInfo.NOT_SELECTED;
break;
default:
newSelectionType = TreeNodeInfo.FULL_SELECTED;
break;
}
setSelectionType(selectedNode, newSelectionType);
setParentSelectionType(selectedNode, newSelectionType);
tree.clearSelection();
}
}