/* * Freeplane - mind map editor * Copyright (C) 2008 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitry Polivaev * * This file is created by Dimitry Polivaev in 2008. * * 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.nodestyle.mindmapmode; import java.awt.Color; import java.awt.event.ActionEvent; import java.util.Collection; import org.freeplane.core.ui.AMultipleNodeAction; import org.freeplane.core.undo.IActor; import org.freeplane.features.map.IExtensionCopier; import org.freeplane.features.map.MapController; import org.freeplane.features.map.NodeModel; import org.freeplane.features.mode.Controller; import org.freeplane.features.mode.ModeController; import org.freeplane.features.nodestyle.NodeSizeModel; import org.freeplane.features.nodestyle.NodeStyleController; import org.freeplane.features.nodestyle.NodeStyleModel; import org.freeplane.features.styles.LogicalStyleKeys; /** * @author Dimitry Polivaev */ public class MNodeStyleController extends NodeStyleController { private static class StyleCopier implements IExtensionCopier { final private ModeController modeController; public StyleCopier(ModeController modeController) { this.modeController = modeController; } public void copy(final Object key, final NodeModel from, final NodeModel to) { if (!key.equals(LogicalStyleKeys.NODE_STYLE)) { return; } copy(from, to); } public void copy(final NodeModel from, final NodeModel to) { final NodeStyleModel fromStyle = from.getExtension(NodeStyleModel.class); if (fromStyle != null) { fromStyle.copyTo(NodeStyleModel.createNodeStyleModel(to)); } final NodeSizeModel fromSize = from.getExtension(NodeSizeModel.class); if (fromSize != null) { fromSize.copyTo(NodeSizeModel.createNodeSizeModel(to)); } } public void remove(final Object key, final NodeModel from) { if (!key.equals(LogicalStyleKeys.NODE_STYLE)) { return; } from.removeExtension(NodeStyleModel.class); from.removeExtension(NodeSizeModel.class); } public void remove(final Object key, final NodeModel from, final NodeModel which) { removeStyleData(key, from, which); removeSizeData(key, from, which); } private void removeSizeData(Object key, NodeModel from, NodeModel which) { if (!key.equals(LogicalStyleKeys.NODE_STYLE)) { return; } final NodeSizeModel whichData = which.getExtension(NodeSizeModel.class); if (whichData == null) { return; } final NodeSizeModel fromData = from.getExtension(NodeSizeModel.class); if (fromData == null) { return; } if (NodeSizeModel.NOT_SET != whichData.getMaxNodeWidth()) { fromData.setMaxNodeWidth(NodeSizeModel.NOT_SET); } if (NodeSizeModel.NOT_SET != whichData.getMinNodeWidth()) { fromData.setMinNodeWidth(NodeSizeModel.NOT_SET); } } private void removeStyleData(Object key, NodeModel from, NodeModel which) { if (!key.equals(LogicalStyleKeys.NODE_STYLE)) { return; } final NodeStyleModel whichStyle = (NodeStyleModel) which.getExtension(NodeStyleModel.class); if (whichStyle == null) { return; } final NodeStyleModel fromStyle = (NodeStyleModel) from.getExtension(NodeStyleModel.class); if (fromStyle == null) { return; } if (null != whichStyle.isBold()) { fromStyle.setBold(null); } if (null != whichStyle.isItalic()) { fromStyle.setItalic(null); } if (null != whichStyle.getFontFamilyName()) { fromStyle.setFontFamilyName(null); } if (null != whichStyle.getFontSize()) { fromStyle.setFontSize(null); } if (null != whichStyle.getShape()) { fromStyle.setShape(null); } if (null != whichStyle.getColor()) { fromStyle.setColor(null); } if (null != whichStyle.getBackgroundColor()) { fromStyle.setBackgroundColor(null); } if (null != whichStyle.getNodeFormat()) { fromStyle.setNodeFormat(null); } if (null != whichStyle.getNodeNumbering()) { fromStyle.setNodeNumbering(null); } } public void resolveParentExtensions(Object key, NodeModel to) { if (!key.equals(LogicalStyleKeys.NODE_STYLE)) { return; } resolveShape(to); } private void resolveShape(NodeModel to) { if (hasOwnShape(to)) return; for(NodeModel source = to.getParentNode(); source != null; source = source.getParentNode() ){ if(hasOwnShape(source)){ final String shape = getShape(source); NodeStyleModel.createNodeStyleModel(to).setShape(shape); return; } } } private boolean hasOwnShape(NodeModel to) { return ! NodeStyleModel.SHAPE_AS_PARENT.equals(getShape(to)); } private String getShape(NodeModel node) { return modeController.getExtension(NodeStyleController.class).getShape(node); } } public MNodeStyleController(final ModeController modeController) { super(modeController); modeController.registerExtensionCopier(new StyleCopier(modeController)); modeController.addAction(new BoldAction()); modeController.addAction(new ItalicAction()); modeController.addAction(new CopyFormat()); modeController.addAction(new PasteFormat()); modeController.addAction(new RemoveFormatAction()); final AMultipleNodeAction increaseNodeFont = new AMultipleNodeAction("IncreaseNodeFontAction") { private static final long serialVersionUID = 1L; @Override protected void actionPerformed(final ActionEvent e, final NodeModel node) { increaseFontSize(node, 1); } }; modeController.addAction(increaseNodeFont); final AMultipleNodeAction decreaseNodeFont = new AMultipleNodeAction("DecreaseNodeFontAction") { private static final long serialVersionUID = 1L; @Override protected void actionPerformed(final ActionEvent e, final NodeModel node) { increaseFontSize(node, -1); } }; modeController.addAction(decreaseNodeFont); modeController.addAction(new NodeColorAction()); modeController.addAction(new NodeColorBlendAction()); modeController.addAction(new NodeBackgroundColorAction()); modeController.addAction(new NodeShapeAction(NodeStyleModel.STYLE_FORK)); modeController.addAction(new NodeShapeAction(NodeStyleModel.STYLE_BUBBLE)); modeController.addAction(new NodeWidthAction()); } public void copyStyle(final NodeModel source, final NodeModel target) { copyStyleModel(source, target); copySizeModel(source, target); } protected void copyStyleModel(final NodeModel source, final NodeModel target) { final NodeStyleModel sourceStyleModel = NodeStyleModel.getModel(source); if (sourceStyleModel != null) { setColor(target, sourceStyleModel.getColor()); setBackgroundColor(target, sourceStyleModel.getBackgroundColor()); setShape(target, sourceStyleModel.getShape()); setFontFamily(target, sourceStyleModel.getFontFamilyName()); setFontSize(target, sourceStyleModel.getFontSize()); setBold(target, sourceStyleModel.isBold()); setItalic(target, sourceStyleModel.isItalic()); setNodeFormat(target, sourceStyleModel.getNodeFormat()); setNodeNumbering(target, sourceStyleModel.getNodeNumbering()); } } protected void copySizeModel(final NodeModel source, final NodeModel target) { final NodeSizeModel sourceSizeModel = NodeSizeModel.getModel(source); if (sourceSizeModel != null) { setMaxNodeWidth(target, sourceSizeModel.getMaxNodeWidth()); setMinNodeWidth(target, sourceSizeModel.getMinNodeWidth()); } } private NodeStyleModel createOwnStyleModel(final NodeModel node) { { final NodeStyleModel styleModel = NodeStyleModel.getModel(node); if (styleModel != null) { return styleModel; } } final ModeController modeController = Controller.getCurrentModeController(); final IActor actor = new IActor() { public void act() { node.addExtension(new NodeStyleModel()); } public String getDescription() { return null; } public void undo() { node.removeExtension(NodeStyleModel.class); } }; modeController.execute(actor, node.getMap()); return NodeStyleModel.getModel(node); } private NodeSizeModel createOwnSizeModel(final NodeModel node) { { final NodeSizeModel sizeModel = NodeSizeModel.getModel(node); if (sizeModel != null) { return sizeModel; } } final ModeController modeController = Controller.getCurrentModeController(); final IActor actor = new IActor() { public void act() { node.addExtension(new NodeSizeModel()); } public String getDescription() { return null; } public void undo() { node.removeExtension(NodeSizeModel.class); } }; modeController.execute(actor, node.getMap()); return NodeSizeModel.getModel(node); } /** * */ public void increaseFontSize(final NodeModel node, final int increment) { final int newSize = getFontSize(node) + increment; if (newSize > 0) { setFontSize(node, newSize); } } public void setBackgroundColor(final NodeModel node, final Color color) { final ModeController modeController = Controller.getCurrentModeController(); final Color oldColor = NodeStyleModel.getBackgroundColor(node); if (color == oldColor || color != null && color.equals(oldColor)) { return; } final IActor actor = new IActor() { public void act() { NodeStyleModel.setBackgroundColor(node, color); Controller.getCurrentModeController().getMapController().nodeChanged(node); } public String getDescription() { return "setBackgroundColor"; } public void undo() { NodeStyleModel.setBackgroundColor(node, oldColor); Controller.getCurrentModeController().getMapController().nodeChanged(node); } }; modeController.execute(actor, node.getMap()); } /** * @param bold */ public void setBold(final NodeModel node, final Boolean bold) { final Boolean oldBold = NodeStyleModel.isBold(node); if (oldBold == bold || oldBold != null && oldBold.equals(bold)) { return; } createOwnStyleModel(node); final ModeController modeController = Controller.getCurrentModeController(); final IActor actor = new IActor() { public void act() { final NodeStyleModel styleModel = NodeStyleModel.getModel(node); styleModel.setBold(bold); Controller.getCurrentModeController().getMapController().nodeChanged(node); } public String getDescription() { return "setBold"; } public void undo() { final NodeStyleModel styleModel = NodeStyleModel.getModel(node); styleModel.setBold(oldBold); Controller.getCurrentModeController().getMapController().nodeChanged(node); } }; modeController.execute(actor, node.getMap()); } public void setColor(final NodeModel node, final Color color) { final ModeController modeController = Controller.getCurrentModeController(); final Color oldColor = NodeStyleModel.getColor(node); if (oldColor == color || oldColor != null && oldColor.equals(color)) { return; } final IActor actor = new IActor() { public void act() { NodeStyleModel.setColor(node, color); Controller.getCurrentModeController().getMapController().nodeChanged(node); } public String getDescription() { return "setColor"; } public void undo() { NodeStyleModel.setColor(node, oldColor); Controller.getCurrentModeController().getMapController().nodeChanged(node); } }; modeController.execute(actor, node.getMap()); } /** * @param fontFamily */ public void setFontFamily(final NodeModel node, final String fontFamily) { final String oldFontFamily = NodeStyleModel.getFontFamilyName(node); if (oldFontFamily == fontFamily || oldFontFamily != null && oldFontFamily.equals(fontFamily)) { return; } createOwnStyleModel(node); final ModeController modeController = Controller.getCurrentModeController(); final IActor actor = new IActor() { public void act() { final NodeStyleModel styleModel = NodeStyleModel.getModel(node); styleModel.setFontFamilyName(fontFamily); Controller.getCurrentModeController().getMapController().nodeChanged(node); } public String getDescription() { return "setFontFamily"; } public void undo() { final NodeStyleModel styleModel = NodeStyleModel.getModel(node); styleModel.setFontFamilyName(oldFontFamily); Controller.getCurrentModeController().getMapController().nodeChanged(node); } }; modeController.execute(actor, node.getMap()); } public void setFontFamily(final String fontFamily) { for (final NodeModel selected : Controller.getCurrentModeController().getMapController().getSelectedNodes()) { setFontFamily(selected, fontFamily); } } public void setFontSize(final int size) { final Collection<NodeModel> selectedNodes = Controller.getCurrentModeController().getMapController().getSelectedNodes(); for (final NodeModel selected : selectedNodes) { setFontSize(selected, size); } } /** * @param fontSize */ public void setFontSize(final NodeModel node, final Integer fontSize) { final Integer oldFontSize = NodeStyleModel.getFontSize(node); if (oldFontSize == fontSize || oldFontSize != null && oldFontSize.equals(fontSize)) { return; } createOwnStyleModel(node); final ModeController modeController = Controller.getCurrentModeController(); final IActor actor = new IActor() { public void act() { final NodeStyleModel styleModel = NodeStyleModel.getModel(node); styleModel.setFontSize(fontSize); Controller.getCurrentModeController().getMapController().nodeChanged(node); } public String getDescription() { return "setFontSize"; } public void undo() { final NodeStyleModel styleModel = NodeStyleModel.getModel(node); styleModel.setFontSize(oldFontSize); Controller.getCurrentModeController().getMapController().nodeChanged(node); } }; modeController.execute(actor, node.getMap()); } /** * @param italic */ public void setItalic(final NodeModel node, final Boolean italic) { final Boolean oldItalic = NodeStyleModel.isItalic(node); if (oldItalic == italic || oldItalic != null && oldItalic.equals(italic)) { return; } createOwnStyleModel(node); final ModeController modeController = Controller.getCurrentModeController(); final IActor actor = new IActor() { public void act() { final NodeStyleModel styleModel = NodeStyleModel.getModel(node); styleModel.setItalic(italic); Controller.getCurrentModeController().getMapController().nodeChanged(node); } public String getDescription() { return "setItalic"; } public void undo() { final NodeStyleModel styleModel = NodeStyleModel.getModel(node); styleModel.setItalic(oldItalic); Controller.getCurrentModeController().getMapController().nodeChanged(node); } }; modeController.execute(actor, node.getMap()); } public void setNodeNumbering(final NodeModel node, final Boolean enableNodeNumbering) { final ModeController modeController = Controller.getCurrentModeController(); final Boolean oldValue = NodeStyleModel.getNodeNumbering(node); final IActor actor = new IActor() { public void act() { NodeStyleModel.setNodeNumbering(node, enableNodeNumbering); final MapController mapController = modeController.getMapController(); mapController.setSaved(node.getMap(), false); mapController.delayedNodeRefresh(node, NodeStyleController.NODE_NUMBERING, oldValue, enableNodeNumbering); } public String getDescription() { return "setNodeNumbering"; } public void undo() { NodeStyleModel.setNodeNumbering(node, oldValue); final MapController mapController = modeController.getMapController(); mapController.setSaved(node.getMap(), false); modeController.getMapController().delayedNodeRefresh(node, NodeStyleController.NODE_NUMBERING, enableNodeNumbering, oldValue); } }; modeController.execute(actor, node.getMap()); } public void setNodeFormat(final NodeModel node, final String format) { final ModeController modeController = Controller.getCurrentModeController(); final String oldFormat = NodeStyleModel.getNodeFormat(node); final IActor actor = new IActor() { public void act() { NodeStyleModel.setNodeFormat(node, format); modeController.getMapController().nodeChanged(node); } public String getDescription() { return "setNodeFormat"; } public void undo() { NodeStyleModel.setNodeFormat(node, oldFormat); modeController.getMapController().nodeChanged(node); } }; modeController.execute(actor, node.getMap()); } public void setShape(final NodeModel node, final String shape) { final ModeController modeController = Controller.getCurrentModeController(); final String oldShape = NodeStyleModel.getShape(node); final IActor actor = new IActor() { public void act() { NodeStyleModel.setShape(node, shape); modeController.getMapController().nodeChanged(node); childShapeRefresh(node); } public String getDescription() { return "setShape"; } private void childShapeRefresh(final NodeModel node) { for (final NodeModel child : modeController.getMapController().childrenFolded(node)) { if(child.getViewers().isEmpty()) continue; final String childShape = NodeStyleModel.getShape(child); if (childShape == null || NodeStyleModel.SHAPE_AS_PARENT.equals(childShape)) { modeController.getMapController().nodeRefresh(child); childShapeRefresh(child); } } } public void undo() { NodeStyleModel.setShape(node, oldShape); modeController.getMapController().nodeChanged(node); childShapeRefresh(node); } }; modeController.execute(actor, node.getMap()); } public void setMinNodeWidth(final NodeModel node, final int minNodeWidth) { final NodeSizeModel sizeModel = createOwnSizeModel(node); final int oldValue = NodeSizeModel.getMinNodeWidth(node); final IActor actor = new IActor() { public void act() { sizeModel.setMinNodeWidth(minNodeWidth); final MapController mapController = getModeController().getMapController(); mapController.nodeChanged(node); } public String getDescription() { return "setMinNodeWidth"; } public void undo() { sizeModel.setMinNodeWidth(oldValue); final MapController mapController = getModeController().getMapController(); mapController.nodeChanged(node); } }; getModeController().execute(actor, node.getMap()); final int maxWidth = getMaxWidth(node); if(maxWidth < minNodeWidth){ setMaxNodeWidth(node, minNodeWidth); } } public void setMaxNodeWidth(final NodeModel node, final int maxNodeWidth) { final NodeSizeModel sizeModel = createOwnSizeModel(node); final int oldValue = NodeSizeModel.getNodeMaxNodeWidth(node); final IActor actor = new IActor() { public void act() { sizeModel.setMaxNodeWidth(maxNodeWidth); final MapController mapController = getModeController().getMapController(); mapController.nodeChanged(node); } public String getDescription() { return "setMaxNodeWidth"; } public void undo() { sizeModel.setMaxNodeWidth(oldValue); final MapController mapController = getModeController().getMapController(); mapController.nodeChanged(node); } }; getModeController().execute(actor, node.getMap()); final int minNodeWidth = getMinWidth(node); if(maxNodeWidth < minNodeWidth){ setMinNodeWidth(node, maxNodeWidth); } } }