/* * 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; import java.io.IOException; import java.util.NoSuchElementException; import javax.swing.ComboBoxModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.EventListenerList; import org.freeplane.core.extension.IExtension; import org.freeplane.core.io.ITreeWriter; import org.freeplane.core.util.collection.IListModel; import org.freeplane.core.util.collection.SortedComboBoxModel; import org.freeplane.core.util.collection.SortedMapVector; import org.freeplane.features.map.MapController; import org.freeplane.features.map.MapModel; import org.freeplane.features.map.NodeModel; import org.freeplane.features.mode.Controller; import org.freeplane.n3.nanoxml.XMLElement; /** * @author Dimitry Polivaev */ public class AttributeRegistry implements IExtension { static public final int GLOBAL = -1; private static final int TABLE_FONT_SIZE = 9; public static AttributeRegistry getRegistry(final MapModel map) { AttributeRegistry registry = (AttributeRegistry) map.getExtension(AttributeRegistry.class); if (registry == null) { final AttributeController attributeController = AttributeController.getController(); registry = new AttributeRegistry(attributeController); map.addExtension(AttributeRegistry.class, registry); final NodeModel rootNode = map.getRootNode(); if(rootNode != null) registry.registryAttributes(Controller.getCurrentModeController().getMapController(), rootNode); } return registry; } private AttributeController attributeController; private ChangeEvent attributesEvent; private String attributeViewType; private ChangeEvent changeEvent; protected SortedMapVector elements; private int fontSize = AttributeRegistry.TABLE_FONT_SIZE; protected boolean isAttributeLayoutChanged; private boolean isRestricted; private EventListenerList listenerList = null; private AttributeRegistryComboBoxColumnModel myComboBoxColumnModel = null; private AttributeRegistryTableModel myTableModel = null; private Boolean restrictionModel; protected int visibleElementsNumber; /** * */ public AttributeRegistry() { super(); } public AttributeRegistry(final AttributeController attributeController) { super(); listenerList = new EventListenerList(); isAttributeLayoutChanged = false; this.attributeController = attributeController; visibleElementsNumber = 0; elements = new SortedMapVector(); myTableModel = new AttributeRegistryTableModel(this); isRestricted = false; restrictionModel = Boolean.FALSE; attributeViewType = AttributeTableLayoutModel.SHOW_ALL; } public void addAttributesListener(final IAttributesListener l) { listenerList.add(IAttributesListener.class, l); } public void addChangeListener(final ChangeListener l) { listenerList.add(ChangeListener.class, l); } public void applyChanges() { if (isAttributeLayoutChanged == false) { return; } getAttributeController().performSetRestriction(AttributeRegistry.GLOBAL, restrictionModel.booleanValue()); for (int i = 0; i < elements.size(); i++) { final AttributeRegistryElement element = getElement(i); getAttributeController().performSetVisibility(i, element.getVisibilityModel().booleanValue()); getAttributeController().performSetRestriction(i, element.getRestriction().booleanValue()); } isAttributeLayoutChanged = false; } public boolean containsElement(final String name) { return elements.containsKey(name); } public void decrementVisibleElementsNumber() { visibleElementsNumber--; } public boolean exist(final String attributeName, final Object element) { final int index = indexOf(attributeName); if (index == -1) { return false; } final SortedComboBoxModel values = getElement(index).getValues(); for (int i = 0; i < values.getSize(); i++) { if (element.equals(values.getElementAt(i))) { return true; } } return false; } public void fireAttributeLayoutChanged() { fireStateChanged(); } protected void fireAttributesChanged() { final Object[] listeners = listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == IAttributesListener.class) { if (attributesEvent == null) { attributesEvent = new ChangeEvent(this); } ((IAttributesListener) listeners[i + 1]).attributesChanged(changeEvent); } } } public void fireStateChanged() { final Object[] listeners = listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == ChangeListener.class) { if (changeEvent == null) { changeEvent = new ChangeEvent(this); } ((ChangeListener) listeners[i + 1]).stateChanged(changeEvent); } } } public AttributeController getAttributeController() { return attributeController; } public String getAttributeViewType() { return attributeViewType; } private AttributeRegistryComboBoxColumnModel getCombinedModel() { if (myComboBoxColumnModel == null) { myComboBoxColumnModel = new AttributeRegistryComboBoxColumnModel(this); } return myComboBoxColumnModel; } public ComboBoxModel getComboBoxModel() { return getCombinedModel(); } public ComboBoxModel getDefaultComboBoxModel(final Comparable<?> attrName) { try { final AttributeRegistryElement elem = getElement(attrName); return elem.getValues(); } catch (final NoSuchElementException ex) { return getComboBoxModel(); } } public AttributeRegistryElement getElement(final Comparable<?> attrName) { final AttributeRegistryElement elem = (AttributeRegistryElement) elements.getValue(attrName); return elem; } public AttributeRegistryElement getElement(final int index) { return (AttributeRegistryElement) elements.getValue(index); } public SortedMapVector getElements() { return elements; } /** * @return Returns the fontSize. */ public int getFontSize() { return fontSize; } public Comparable<?> getKey(final int index) { return elements.getKey(index); } public IListModel getListBoxModel() { return getCombinedModel(); } Boolean getRestriction(final int row) { if (row == AttributeRegistry.GLOBAL) { return restrictionModel; } else { return getElement(row).getRestriction(); } } /** */ public AttributeRegistryTableModel getTableModel() { return myTableModel; } /** */ public IListModel getValues(final int row) { if (row == AttributeRegistry.GLOBAL) { return getListBoxModel(); } return getElement(row).getValues(); } public int getVisibleElementsNumber() { return visibleElementsNumber; } public void incrementVisibleElementsNumber() { visibleElementsNumber++; } /** */ public int indexOf(final String string) { return elements.indexOf(string); } /** */ public boolean isRestricted() { return isRestricted; } public boolean isRestricted(final String s) { return getRestriction(indexOf(s)).booleanValue(); } public void registry(final Attribute newAttribute) { final String name = newAttribute.getName(); if (name.equals("")) { return; } final Object value = newAttribute.getValue(); try { final AttributeRegistryElement elem = getElement(name); elem.addValue(value); } catch (final NoSuchElementException ex) { final AttributeRegistryElement attributeRegistryElement = new AttributeRegistryElement(this, name); attributeRegistryElement.addValue(value); final int index = getElements().add(name, attributeRegistryElement); getTableModel().fireTableRowsInserted(index, index); }; fireAttributesChanged(); } public void registry(final String name) { final AttributeRegistryElement attributeRegistryElement = new AttributeRegistryElement(this, name); final int index = getElements().add(name, attributeRegistryElement); getTableModel().fireTableRowsInserted(index, index); } private void registryAttributes(final MapController mapController, final NodeModel node) { final NodeAttributeTableModel model = NodeAttributeTableModel.getModel(node); if (model == null) { return; } for (int i = 0; i < model.getRowCount(); i++) { registry(model.getAttribute(i)); } for (final NodeModel child : mapController.childrenUnfolded(node)) { registryAttributes(mapController, child); } } /** */ void removeAtribute(final Object o) { getAttributeController().performRemoveAttribute(o.toString()); } public void removeAttributesListener(final IAttributesListener l) { listenerList.remove(IAttributesListener.class, l); } public void removeChangeListener(final ChangeListener l) { listenerList.remove(ChangeListener.class, l); } /** */ public void resetChanges() { if (isAttributeLayoutChanged == false) { return; } restrictionModel = Boolean.valueOf(isRestricted); for (int i = 0; i < elements.size(); i++) { final AttributeRegistryElement element = getElement(i); element.setVisibilityModel(Boolean.valueOf(element.isVisible())); element.setRestrictionModel(Boolean.valueOf(element.isRestricted())); } isAttributeLayoutChanged = false; } public void setAttributeLayoutChanged() { isAttributeLayoutChanged = true; } public void setAttributeViewType(final String attributeViewType) { this.attributeViewType = attributeViewType; fireStateChanged(); } public void setFontSize(final int size) { if (fontSize != size) { fontSize = size; fireAttributeLayoutChanged(); } } /** */ public void setRestricted(final boolean b) { isRestricted = b; restrictionModel = Boolean.valueOf(isRestricted); fireAttributesChanged(); } /** */ private void setRestricted(final int row, final boolean b) { getElement(row).setRestriction(b); } public void setRestricted(final String s, final boolean b) { setRestricted(indexOf(s), b); } /** */ public void setRestrictionModel(final int row, final Boolean value) { if (row == AttributeRegistry.GLOBAL) { restrictionModel = value; } else { getElement(row).setRestrictionModel(value); } setAttributeLayoutChanged(); myTableModel.fireRestrictionsUpdated(row); } public void setVisibilityModel(final int row, final Boolean visible) { final AttributeRegistryElement element = getElement(row); if (!element.getVisibilityModel().equals(visible)) { element.setVisibilityModel(visible); setAttributeLayoutChanged(); myTableModel.fireVisibilityUpdated(row); } } public int size() { return elements.size(); } public void unregistry(final String name) { final int index = elements.indexOf(name); if (getElement(index).isVisible()) { decrementVisibleElementsNumber(); } elements.remove(index); getTableModel().fireTableRowsDeleted(index, index); fireAttributesChanged(); } /** * @throws IOException */ public void write(final ITreeWriter writer) throws IOException { final XMLElement attributeRegistry = new XMLElement(); boolean toBeSaved = false; if (isRestricted()) { attributeRegistry.setAttribute("RESTRICTED", "true"); toBeSaved = true; } if (!attributeViewType.equals(AttributeTableLayoutModel.SHOW_ALL)) { attributeRegistry.setAttribute("SHOW_ATTRIBUTES", attributeViewType); toBeSaved = true; } if (getFontSize() != AttributeRegistry.TABLE_FONT_SIZE) { attributeRegistry.setAttribute("FONT_SIZE", Integer.toString(getFontSize())); toBeSaved = true; } for (int i = 0; i < size(); i++) { final AttributeRegistryElement element = getElement(i); if (element.isRestricted() || element.isVisible() || element.isManual()) { final XMLElement attributeData = element.save(); attributeRegistry.addChild(attributeData); toBeSaved = true; } } if (toBeSaved) { attributeRegistry.setName(AttributeBuilder.XML_NODE_ATTRIBUTE_REGISTRY); writer.addElement(this, attributeRegistry); } } }