Package org.freeplane.features.mode

Source Code of org.freeplane.features.mode.ModeController

/*
*  Freeplane - mind map editor
*  Copyright (C) 2008 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitry Polivaev
*
*  This file is modified 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.mode;

import java.awt.Component;
import java.awt.Container;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.freeplane.core.extension.ExtensionContainer;
import org.freeplane.core.extension.IExtension;
import org.freeplane.core.ui.AFreeplaneAction;
import org.freeplane.core.ui.IMenuContributor;
import org.freeplane.core.ui.IUserInputListenerFactory;
import org.freeplane.core.ui.MenuBuilder;
import org.freeplane.core.undo.IActor;
import org.freeplane.core.undo.IUndoHandler;
import org.freeplane.features.map.IExtensionCopier;
import org.freeplane.features.map.ITooltipProvider;
import org.freeplane.features.map.MapController;
import org.freeplane.features.map.MapModel;
import org.freeplane.features.map.NodeModel;
import org.freeplane.features.ui.INodeViewLifeCycleListener;

/**
* Derive from this class to implement the Controller for your mode. Overload
* the methods you need for your data model, or use the defaults. There are some
* default Actions you may want to use for easy editing of your model. Take
* MindMapController as a sample.
*/
public class ModeController extends AController {
// //   final private Controller controller;
  private final ExtensionContainer extensionContainer;
  private final Collection<IExtensionCopier> copiers;
  private boolean isBlocked = false;
  private MapController mapController;
  final private Map<Integer, ITooltipProvider> toolTip = new TreeMap<Integer, ITooltipProvider>();
  final private List<IMenuContributor> menuContributors = new LinkedList<IMenuContributor>();
  /**
   * The model, this controller belongs to. It may be null, if it is the
   * default controller that does not show a map.
   */
  final private List<INodeViewLifeCycleListener> nodeViewListeners = new LinkedList<INodeViewLifeCycleListener>();
  /**
   * Take care! This listener is also used for modelpopups (as for graphical
   * links).
   */
  private IUserInputListenerFactory userInputListenerFactory;
  final private Controller controller;

  /**
   * Instantiation order: first me and then the model.
   */
  public ModeController(final Controller controller) {
    this.controller = controller;
    extensionContainer = new ExtensionContainer(new HashMap<Class<? extends IExtension>, IExtension>());
    copiers = new LinkedList<IExtensionCopier>();
  }

  @Override
  public void addAction(final AFreeplaneAction action) {
    super.addAction(action);
    if (mapController != null) {
      mapController.addListenerForAction(action);
    }
  }

  public void addExtension(final Class<? extends IExtension> clazz, final IExtension extension) {
    extensionContainer.addExtension(clazz, extension);
  }

  public void registerExtensionCopier(final IExtensionCopier copier) {
    copiers.add(copier);
  }

  public void unregisterExtensionCopier(final IExtensionCopier copier) {
    copiers.remove(copier);
  }

  public void copyExtensions(final Object key, final NodeModel from, final NodeModel to) {
    for (final IExtensionCopier copier : copiers) {
      copier.copy(key, from, to);
    }
  }

  public void undoableCopyExtensions(final Object key, final NodeModel from, final NodeModel to) {
    final MapModel map = to.getMap();
    if (map == null) {
      copyExtensions(key, from, to);
      return;
    }
    final IUndoHandler undoHandler = map.getExtension(IUndoHandler.class);
    if (undoHandler == null) {
      copyExtensions(key, from, to);
      return;
    }
    final NodeModel backup = new NodeModel(null);
    copyExtensions(key, to, backup);
    final IActor actor = new IActor() {
      public void undo() {
        removeExtensions(key, to);
        copyExtensions(key, backup, to);
        getMapController().nodeChanged(to);
      }

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

      public void act() {
        copyExtensions(key, from, to);
        getMapController().nodeChanged(to);
      }
    };
    execute(actor, map);
  }

  void removeExtensions(final Object key, final NodeModel from, final NodeModel which) {
    if (from.equals(which)) {
      for (final IExtensionCopier copier : copiers) {
        copier.remove(key, from);
      }
      return;
    }
    for (final IExtensionCopier copier : copiers) {
      copier.remove(key, from, which);
    }
  }

  public void undoableRemoveExtensions(final Object key, final NodeModel from, final NodeModel which) {
    final MapModel map = from.getMap();
    if (map == null) {
      removeExtensions(key, from, which);
      return;
    }
    final IUndoHandler undoHandler = map.getExtension(IUndoHandler.class);
    if (undoHandler == null) {
      removeExtensions(key, from, which);
      return;
    }
    final NodeModel backup = new NodeModel(null);
    copyExtensions(key, from, backup);
    final IActor actor = new IActor() {
      public void undo() {
        copyExtensions(key, backup, from);
        getMapController().nodeChanged(from);
      }

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

      public void act() {
        removeExtensions(key, from, which);
        getMapController().nodeChanged(from);
      }
    };
    execute(actor, map);
  }

  public void resolveParentExtensions(final Object key, final NodeModel to) {
    for (final IExtensionCopier copier : copiers) {
      copier.resolveParentExtensions(key, to);
    }
  }

  public void undoableResolveParentExtensions(final Object key,  final NodeModel to) {
    final MapModel map = to.getMap();
    if (map == null) {
      resolveParentExtensions(key, to);
      return;
    }
    final IUndoHandler undoHandler = map.getExtension(IUndoHandler.class);
    if (undoHandler == null) {
      resolveParentExtensions(key, to);
      return;
    }
    final NodeModel backup = new NodeModel(null);
    copyExtensions(key, to, backup);
    final IActor actor = new IActor() {
      public void undo() {
        copyExtensions(key, backup, to);
        getMapController().nodeChanged(to);
      }

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

      public void act() {
        resolveParentExtensions(key, to);
        getMapController().nodeChanged(to);
      }
    };
    execute(actor, map);
  }

  void removeExtensions(final Object key, final NodeModel from) {
    for (final IExtensionCopier copier : copiers) {
      copier.remove(key, from, from);
    }
  }

  public void addINodeViewLifeCycleListener(final INodeViewLifeCycleListener listener) {
    nodeViewListeners.add(listener);
  }

  public void addMenuContributor(final IMenuContributor contributor) {
    menuContributors.add(contributor);
  }

  public void commit() {
  }

  public boolean isUndoAction() {
    return false;
  }

  public void execute(final IActor actor, final MapModel map) {
    actor.act();
  }

  @Override
  public AFreeplaneAction getAction(final String key) {
    final AFreeplaneAction action = super.getAction(key);
    if (action != null) {
      return action;
    }
    return getController().getAction(key);
  }

  public Controller getController() {
    return controller;
  }

  public <T extends IExtension> T getExtension(final Class<T> clazz) {
    return extensionContainer.getExtension(clazz);
  }

  public boolean containsExtension(final Class<? extends IExtension> clazz) {
    return extensionContainer.containsExtension(clazz);
  }

  public void removeExtension(Class<? extends IExtension> clazz) {
    extensionContainer.removeExtension(clazz);
  }
  public MapController getMapController() {
    return mapController;
  }

  public String getModeName() {
    return null;
  }

  public IUserInputListenerFactory getUserInputListenerFactory() {
    return userInputListenerFactory;
  }

  public boolean hasOneVisibleChild(final NodeModel parent) {
    int count = 0;
    for (final NodeModel child : getMapController().childrenUnfolded(parent)) {
      if (child.isVisible()) {
        count++;
      }
      if (count == 2) {
        return false;
      }
    }
    return count == 1;
  }

  public boolean isBlocked() {
    return isBlocked;
  }

  public void onViewCreated(final Container node) {
    for (final INodeViewLifeCycleListener hook : nodeViewListeners) {
      hook.onViewCreated(node);
    }
  }

  public void onViewRemoved(final Container node) {
    for (final INodeViewLifeCycleListener hook : nodeViewListeners) {
      hook.onViewRemoved(node);
    }
  }

  @Override
  public AFreeplaneAction removeAction(final String key) {
    final AFreeplaneAction action = super.removeAction(key);
    if (mapController != null) {
      mapController.removeListenerForAction(action);
    }
    return action;
  }

  public void removeINodeViewLifeCycleListener(final INodeViewLifeCycleListener listener) {
    nodeViewListeners.remove(listener);
  }

  public void rollback() {
  }

  public void setBlocked(final boolean isBlocked) {
    this.isBlocked = isBlocked;
  }

  public void setMapController(final MapController mapController) {
    this.mapController = mapController;
    addExtension(MapController.class, mapController);
  }

  public void setUserInputListenerFactory(final IUserInputListenerFactory userInputListenerFactory) {
    this.userInputListenerFactory = userInputListenerFactory;
  }

  /*
   * (non-Javadoc)
   * @see freeplane.modes.ModeController#setVisible(boolean)
   */
  public void setVisible(final boolean visible) {
    final NodeModel node = getController().getSelection().getSelected();
    if (visible) {
      mapController.onSelect(node);
    }
    else {
      if (node != null) {
        mapController.onDeselect(node);
      }
    }
  }

  public void shutdown() {
  }

  public void startTransaction() {
  }
  public void forceNewTransaction() {
    }

  /**
   * This method is called after and before a change of the map mapView. Use
   * it to perform the actions that cannot be performed at creation time.
   */
  public void startup() {
  }

  public void updateMenus(String menuStructure, final Set<String> plugins) {
    final IUserInputListenerFactory userInputListenerFactory = getUserInputListenerFactory();
    userInputListenerFactory.getAcceleratorManager().loadDefaultAcceleratorPresets();
    userInputListenerFactory.updateMenus(menuStructure, plugins);
    final MenuBuilder menuBuilder = userInputListenerFactory.getMenuBuilder(MenuBuilder.class);
    final Iterator<IMenuContributor> iterator = menuContributors.iterator();
    while (iterator.hasNext()) {
      iterator.next().updateMenus(this, menuBuilder);
    }
  }

  public boolean canEdit() {
    return false;
  }
  public String createToolTip(final NodeModel node, Component view) {
    // perhaps we should use the solution presented in the 3rd answer at
    // http://stackoverflow.com/questions/3355469/1-pixel-table-border-in-jtextpane-using-html
    // html/css example: http://www.wer-weiss-was.de/theme35/article3555660.html
    final String style = "<style type='text/css'>" //
            + " body { font-size: 10pt; }" // FIXME: copy from NoteController.setNoteTooltip() ?
            + "</style>";
    final StringBuilder text = new StringBuilder("<html><head>"+style+"</head><body>");
    boolean tooltipSet = false;
    for (final ITooltipProvider provider : toolTip.values()) {
      String value = provider.getTooltip(this, node, view);
      if (value == null) {
        continue;
      }
      value = value.replace("<html>", "<div>");
      value = value.replaceAll("\\s*</?(body|head)>", "");
      value = value.replace("<td>", "<td style='background-color: white'>");
      value = value.replace("</html>", "</div>");
      if (tooltipSet) {
        text.append("<br>");
      }
      text.append(value);
      tooltipSet = true;
    }
    if (tooltipSet) {
      text.append("</body></html>");
//      System.err.println("tooltip=" + text);
      return text.toString();
    }
    return null;
  }

  /**
   */
  public void addToolTipProvider(final Integer key, final ITooltipProvider tooltip) {
    if (tooltip == null) {
      if (toolTip.containsKey(key)) {
        toolTip.remove(key);
      }
    }
    else {
      toolTip.put(key, tooltip);
    }
  }
}
TOP

Related Classes of org.freeplane.features.mode.ModeController

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.