Package org.freeplane.features.styles

Source Code of org.freeplane.features.styles.LogicalStyleController

/*
*  Freeplane - mind map editor
*  Copyright (C) 2009 Dimitry
*
*  This file author is Dimitry
*
*  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.styles;

import java.awt.Component;
import java.awt.EventQueue;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;

import org.freeplane.core.extension.IExtension;
import org.freeplane.core.io.IAttributeHandler;
import org.freeplane.core.io.IAttributeWriter;
import org.freeplane.core.io.ITreeWriter;
import org.freeplane.core.io.ReadManager;
import org.freeplane.core.io.WriteManager;
import org.freeplane.core.resources.NamedObject;
import org.freeplane.core.resources.ResourceController;
import org.freeplane.core.undo.IActor;
import org.freeplane.core.util.HtmlUtils;
import org.freeplane.core.util.TextUtils;
import org.freeplane.features.filter.condition.ASelectableCondition;
import org.freeplane.features.map.IMapChangeListener;
import org.freeplane.features.map.INodeChangeListener;
import org.freeplane.features.map.ITooltipProvider;
import org.freeplane.features.map.MapChangeEvent;
import org.freeplane.features.map.MapController;
import org.freeplane.features.map.MapModel;
import org.freeplane.features.map.NodeBuilder;
import org.freeplane.features.map.NodeChangeEvent;
import org.freeplane.features.map.NodeModel;
import org.freeplane.features.map.NodeWriter;
import org.freeplane.features.mode.CombinedPropertyChain;
import org.freeplane.features.mode.Controller;
import org.freeplane.features.mode.IPropertyHandler;
import org.freeplane.features.mode.ModeController;
import org.freeplane.features.styles.ConditionalStyleModel.Item;

/**
* @author Dimitry Polivaev
* 28.09.2009
*/
public class LogicalStyleController implements IExtension {
//   final private ModeController modeController;

  private static final int STYLE_TOOLTIP = 0;
  private WeakReference<NodeModel> cachedNode;
  private Collection<IStyle>  cachedStyle;
  final private CombinedPropertyChain<Collection<IStyle>, NodeModel> styleHandlers;

  public LogicalStyleController(ModeController modeController) {
//      this.modeController = modeController;
    styleHandlers = new CombinedPropertyChain<Collection<IStyle>, NodeModel>(false);
    createBuilder();
    registerChangeListener();
    addStyleGetter(IPropertyHandler.NODE, new IPropertyHandler<Collection<IStyle>, NodeModel>() {
      public Collection<IStyle> getProperty(NodeModel node, Collection<IStyle> currentValue) {
        final MapStyleModel styleModel = MapStyleModel.getExtension(node.getMap());
        add(node, styleModel, currentValue, new StyleNode(node));
        return currentValue;
      }
    });
    addStyleGetter(IPropertyHandler.STYLE, new IPropertyHandler<Collection<IStyle>, NodeModel>() {
      public Collection<IStyle> getProperty(NodeModel node, Collection<IStyle> currentValue) {
        IStyle style = LogicalStyleModel.getStyle(node);
        if(style != null){
          add(node, currentValue, style);
        }
        final MapStyleModel styleModel = MapStyleModel.getExtension(node.getMap());
        Collection<IStyle> condStyles = styleModel.getConditionalStyleModel().getStyles(node);
        clearCache();
        addAll(node, styleModel, currentValue, condStyles);
        return currentValue;
      }
    });
    addStyleGetter(IPropertyHandler.DEFAULT, new IPropertyHandler<Collection<IStyle>, NodeModel>() {
      public Collection<IStyle> getProperty(NodeModel node, Collection<IStyle> currentValue) {
        add(node, currentValue, MapStyleModel.DEFAULT_STYLE);
        return currentValue;
      }
    });
    modeController.addToolTipProvider(STYLE_TOOLTIP, new ITooltipProvider() {
      public String getTooltip(ModeController modeController, NodeModel node, Component view) {
        if(!ResourceController.getResourceController().getBooleanProperty("show_styles_in_tooltip"))
          return null;
        final Collection<IStyle> styles = getStyles(node);
        if(styles.size() > 0)
          styles.remove(styles.iterator().next());
        final String label = TextUtils.getText("node_styles");
        return HtmlUtils.plainToHTML(label + ": " + getStyleNames(styles, ", "));
      }
    });
  }

  protected Collection<IStyle> getResursively(NodeModel node, Collection<IStyle> collection) {
    final MapStyleModel styleModel = MapStyleModel.getExtension(node.getMap());
    Collection<IStyle> set = new LinkedHashSet<IStyle>();
    addAll(node, styleModel, set, collection);
    return set;
  }

  protected void addAll(NodeModel node, MapStyleModel styleModel, Collection<IStyle> currentValue, Collection<IStyle> collection) {
    for(IStyle styleKey : collection){
      add(node, styleModel, currentValue, styleKey);
    }
    }

  public void add(NodeModel node, Collection<IStyle> currentValue, IStyle style) {
    final MapStyleModel styleModel = MapStyleModel.getExtension(node.getMap());
    add(node, styleModel, currentValue, style);
    }

  protected void add(NodeModel node, MapStyleModel styleModel, Collection<IStyle> currentValue, IStyle styleKey) {
      if(!currentValue.add(styleKey)){
        return;
      }
      final NodeModel styleNode = styleModel.getStyleNode(styleKey);
      if (styleNode == null) {
        return;
      }
      if(styleKey instanceof StyleNode){
        IStyle style = LogicalStyleModel.getStyle(styleNode);
        if(style != null){
          add(node, styleModel, currentValue, style);
        }
      }
      final ConditionalStyleModel conditionalStyleModel = styleNode.getExtension(ConditionalStyleModel.class);
      if(conditionalStyleModel == null)
        return;
      Collection<IStyle> styles = conditionalStyleModel.getStyles(node);
      cachedNode = null;
      addAll(node, styleModel, currentValue, styles);
    }

  private void registerChangeListener() {
    ModeController modeController = Controller.getCurrentModeController();
    final MapController mapController = modeController.getMapController();
    mapController.addMapChangeListener(new IMapChangeListener() {
      public void onPreNodeMoved(NodeModel oldParent, int oldIndex, NodeModel newParent, NodeModel child, int newIndex) {
        clearCache();
      }

      public void onPreNodeDelete(NodeModel oldParent, NodeModel selectedNode, int index) {
        clearCache();
      }

      public void onNodeMoved(NodeModel oldParent, int oldIndex, NodeModel newParent, NodeModel child, int newIndex) {
        clearCache();
      }

      public void onNodeInserted(NodeModel parent, NodeModel child, int newIndex) {
        clearCache();
      }

      public void onNodeDeleted(NodeModel parent, NodeModel child, int index) {
        clearCache();
      }

      public void mapChanged(MapChangeEvent event) {
        clearCache();
      }
    });
    mapController.addNodeChangeListener(new INodeChangeListener() {
      public void nodeChanged(NodeChangeEvent event) {
        clearCache();
      }
    });

    }

  private void createBuilder() {
    ModeController modeController = Controller.getCurrentModeController();
    final MapController mapController = modeController.getMapController();
    final ReadManager readManager = mapController.getReadManager();
    readManager.addAttributeHandler(NodeBuilder.XML_NODE, "STYLE_REF", new IAttributeHandler() {
      public void setAttribute(final Object node, final String value) {
        final LogicalStyleModel extension = LogicalStyleModel.createExtension((NodeModel) node);
        extension.setStyle(StyleFactory.create(value));
      }
    });
    readManager.addAttributeHandler(NodeBuilder.XML_NODE, "LOCALIZED_STYLE_REF", new IAttributeHandler() {
      public void setAttribute(final Object node, final String value) {
        final LogicalStyleModel extension = LogicalStyleModel.createExtension((NodeModel) node);
        extension.setStyle(StyleFactory.create(NamedObject.format(value)));
      }
    });
    final WriteManager writeManager = mapController.getWriteManager();
    writeManager.addAttributeWriter(NodeBuilder.XML_NODE, new IAttributeWriter() {
      public void writeAttributes(final ITreeWriter writer, final Object node, final String tag) {
        if(! NodeWriter.shouldWriteSharedContent(writer))
          return;
        final LogicalStyleModel extension = LogicalStyleModel.getExtension((NodeModel) node);
        if (extension == null) {
          return;
        }
        final IStyle style = extension.getStyle();
        if (style == null) {
          return;
        }
        final String value = StyleNamedObject.toKeyString(style);
        if (style instanceof StyleNamedObject) {
          writer.addAttribute("LOCALIZED_STYLE_REF", value);
        }
        else {
          writer.addAttribute("STYLE_REF", value);
        }
      }
    });
    }

  public static void install( final LogicalStyleController logicalStyleController) {
    final ModeController modeController = Controller.getCurrentModeController();
    modeController.addExtension(LogicalStyleController.class, logicalStyleController);
  }

  public static LogicalStyleController getController() {
    final ModeController modeController = Controller.getCurrentModeController();
    return getController(modeController);
  }

  public static LogicalStyleController getController(ModeController modeController) {
    return modeController.getExtension(LogicalStyleController.class);
    }
  public void refreshMap(final MapModel map) {
    final IActor actor = new IActor() {
      public void undo() {
        refreshMapLater(map);
      }

      public String getDescription() {
        return "refreshMap";
      }

      public void act() {
        refreshMapLater(map);
      }
    };
    Controller.getCurrentModeController().execute(actor, map);
  }

  private static Map<MapModel, Integer> mapsToRefresh = new HashMap<MapModel, Integer>();

  private void refreshMapLater(final MapModel map) {
    final Integer count = mapsToRefresh.get(map);
    if (count == null) {
      mapsToRefresh.put(map, 0);
    }
    else {
      mapsToRefresh.put(map, count + 1);
    }
    EventQueue.invokeLater(new Runnable() {
      public void run() {
        final Integer count = mapsToRefresh.get(map);
        if (count > 0) {
          mapsToRefresh.put(map, count - 1);
          return;
        }
        mapsToRefresh.remove(map);
          final MapStyleModel extension = MapStyleModel.getExtension(map);
          extension.refreshStyles();
        final MapController mapController = Controller.getCurrentModeController().getMapController();
        mapController.fireMapChanged(
            new MapChangeEvent(this, map, MapStyle.MAP_STYLES, null, null));
      }
    });
  }

  public IStyle getFirstStyle(final NodeModel node){
    final Collection<IStyle> styles = getStyles(node);
    boolean found = false;
    for(IStyle style:styles){
      if(found){
        return style;
      }
      if((style instanceof StyleNode)){
        found = true;
      }
    }
    return MapStyleModel.DEFAULT_STYLE;
  }
  public Collection<IStyle>  getStyles(final NodeModel node) {
    if(cachedNode != null && node.equals(cachedNode.get())){
      return cachedStyle;
    }
    cachedStyle = null;
    cachedStyle = styleHandlers.getProperty(node, new LinkedHashSet<IStyle>());
    cachedNode = new WeakReference<NodeModel>(node);
    return cachedStyle;
  }

  public void moveConditionalStyleDown(final ConditionalStyleModel conditionalStyleModel, int index) {
      conditionalStyleModel.moveDown(index);
    }

  public void moveConditionalStyleUp(final ConditionalStyleModel conditionalStyleModel, int index) {
      conditionalStyleModel.moveUp(index);
    }

  public void addConditionalStyle(final ConditionalStyleModel conditionalStyleModel, boolean isActive,
                                    ASelectableCondition condition, IStyle style, boolean isLast) {
      conditionalStyleModel.addCondition(isActive, condition, style, isLast);
    }

  public void insertConditionalStyle(final ConditionalStyleModel conditionalStyleModel, int index, boolean isActive,
                                       ASelectableCondition condition, IStyle style, boolean isLast) {
      conditionalStyleModel.insertCondition(index, isActive, condition, style, isLast);
    }

  public Item removeConditionalStyle(final ConditionalStyleModel conditionalStyleModel, int index) {
      return conditionalStyleModel.removeCondition(index);
    }

  private void clearCache() {
      cachedStyle = null;
      cachedNode = null;
    }

  public IPropertyHandler<Collection<IStyle>, NodeModel> addStyleGetter(
    final Integer key,
    final IPropertyHandler<Collection<IStyle>, NodeModel> getter) {
    return styleHandlers.addGetter(key, getter);
  }

  public IPropertyHandler<Collection<IStyle>, NodeModel> removeStyleGetter(
    final Integer key,
    final IPropertyHandler<Collection<IStyle>, NodeModel> getter) {
    return styleHandlers.addGetter(key, getter);
  }

  public String getStyleNames(final Collection<IStyle> styles, String separator) {
      StringBuilder sb = new StringBuilder();
      int i = 0;
      for(IStyle style :styles){
        if(i > 0)
          sb.append(separator);
        sb.append(style.toString());
        i++;
      }
      return sb.toString();
    }

  public Collection<IStyle>  getConditionalMapStyles(final NodeModel node) {
    final MapStyleModel styleModel = MapStyleModel.getExtension(node.getMap());
    Collection<IStyle> condStyles = styleModel.getConditionalStyleModel().getStyles(node);
    clearCache();
    return getResursively(node, condStyles);
  }

  public Collection<IStyle>  getConditionalNodeStyles(final NodeModel node) {
    final Collection<IStyle> condStyles = new LinkedHashSet<IStyle>();
    IStyle style = LogicalStyleModel.getStyle(node);
    if(style != null){
      condStyles.add(style);
    }

    final ConditionalStyleModel conditionalStyleModel = node.getExtension(ConditionalStyleModel.class);
    if(conditionalStyleModel != null) {
      Collection<IStyle> styles = conditionalStyleModel.getStyles(node);
      clearCache();
      condStyles.addAll(styles);
    }
    final Collection<IStyle> all = getResursively(node, condStyles);
    if(style != null){
      all.remove(style);
    }
    return all;
  }

  public String getNodeStyleNames(NodeModel node, String separator) {
    return getStyleNames(getConditionalNodeStyles(node), separator);
    }

  public String getMapStyleNames(NodeModel node, String separator) {
    return getStyleNames(getConditionalMapStyles(node), separator);
    }
}
TOP

Related Classes of org.freeplane.features.styles.LogicalStyleController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.