/*
* 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);
}
}
}