/*FreeMind - A Program for creating and viewing Mindmaps *Copyright (C) 2000-2006 Joerg Mueller, Daniel Polansky, Christian Foltin and others. *See COPYING for Details * *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, write to the Free Software *Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package freemind.modes.mindmapmode; import java.awt.Color; import java.awt.Component; import java.awt.Point; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.lang.reflect.Constructor; import java.net.MalformedURLException; import java.net.URL; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Properties; import java.util.Set; import java.util.Vector; import java.util.logging.Logger; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ButtonGroup; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JRadioButtonMenuItem; import javax.swing.JToolBar; import javax.swing.KeyStroke; import javax.swing.filechooser.FileFilter; import javax.swing.text.BadLocationException; import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.HTMLEditorKit; import org.jibx.runtime.IUnmarshallingContext; import org.jibx.runtime.JiBXException; import freemind.common.OptionalDontShowMeAgainDialog; import freemind.common.XmlBindingTools; import freemind.controller.MenuBar; import freemind.controller.MenuItemEnabledListener; import freemind.controller.MindMapNodesSelection; import freemind.controller.StructuredMenuHolder; import freemind.controller.actions.generated.instance.EditNoteToNodeAction; import freemind.controller.actions.generated.instance.MenuActionBase; import freemind.controller.actions.generated.instance.MenuCategoryBase; import freemind.controller.actions.generated.instance.MenuCheckedAction; import freemind.controller.actions.generated.instance.MenuRadioAction; import freemind.controller.actions.generated.instance.MenuSeparator; import freemind.controller.actions.generated.instance.MenuStructure; import freemind.controller.actions.generated.instance.MenuSubmenu; import freemind.controller.actions.generated.instance.Pattern; import freemind.controller.actions.generated.instance.PatternEdgeColor; import freemind.controller.actions.generated.instance.PatternEdgeStyle; import freemind.controller.actions.generated.instance.PatternEdgeWidth; import freemind.controller.actions.generated.instance.PatternIcon; import freemind.controller.actions.generated.instance.PatternNodeBackgroundColor; import freemind.controller.actions.generated.instance.PatternNodeColor; import freemind.controller.actions.generated.instance.PatternNodeFontBold; import freemind.controller.actions.generated.instance.PatternNodeFontItalic; import freemind.controller.actions.generated.instance.PatternNodeFontName; import freemind.controller.actions.generated.instance.PatternNodeFontSize; import freemind.controller.actions.generated.instance.PatternNodeStyle; import freemind.controller.actions.generated.instance.PatternNodeText; import freemind.controller.actions.generated.instance.WindowConfigurationStorage; import freemind.controller.actions.generated.instance.XmlAction; import freemind.extensions.HookFactory; import freemind.extensions.HookFactory.RegistrationContainer; import freemind.extensions.HookRegistration; import freemind.extensions.ModeControllerHook; import freemind.extensions.NodeHook; import freemind.extensions.PermanentNodeHook; import freemind.extensions.UndoEventReceiver; import freemind.main.ExampleFileFilter; import freemind.main.FixedHTMLWriter; import freemind.main.FreeMind; import freemind.main.FreeMindCommon; import freemind.main.HtmlTools; import freemind.main.Resources; import freemind.main.Tools; import freemind.main.XMLElement; import freemind.modes.ControllerAdapter; import freemind.modes.EdgeAdapter; import freemind.modes.FreeMindFileDialog; import freemind.modes.MapAdapter; import freemind.modes.MindIcon; import freemind.modes.MindMap; import freemind.modes.MindMap.MapSourceChangedObserver; import freemind.modes.MindMapArrowLink; import freemind.modes.MindMapLink; import freemind.modes.MindMapNode; import freemind.modes.Mode; import freemind.modes.ModeController; import freemind.modes.NodeAdapter; import freemind.modes.NodeDownAction; import freemind.modes.StylePatternFactory; import freemind.modes.attributes.Attribute; import freemind.modes.attributes.AttributeController; import freemind.modes.attributes.NodeAttributeTableModel; import freemind.modes.common.CommonNodeKeyListener; import freemind.modes.common.CommonNodeKeyListener.EditHandler; import freemind.modes.common.GotoLinkNodeAction; import freemind.modes.common.actions.FindAction; import freemind.modes.common.actions.FindAction.FindNextAction; import freemind.modes.common.actions.NewMapAction; import freemind.modes.common.listeners.CommonNodeMouseMotionListener; import freemind.modes.mindmapmode.actions.AddArrowLinkAction; import freemind.modes.mindmapmode.actions.AddLocalLinkAction; import freemind.modes.mindmapmode.actions.ApplyPatternAction; import freemind.modes.mindmapmode.actions.BoldAction; import freemind.modes.mindmapmode.actions.ChangeArrowLinkEndPoints; import freemind.modes.mindmapmode.actions.ChangeArrowsInArrowLinkAction; import freemind.modes.mindmapmode.actions.CloudAction; import freemind.modes.mindmapmode.actions.ColorArrowLinkAction; import freemind.modes.mindmapmode.actions.CompoundActionHandler; import freemind.modes.mindmapmode.actions.CopyAction; import freemind.modes.mindmapmode.actions.CopySingleAction; import freemind.modes.mindmapmode.actions.CutAction; import freemind.modes.mindmapmode.actions.DeleteChildAction; import freemind.modes.mindmapmode.actions.EdgeColorAction; import freemind.modes.mindmapmode.actions.EdgeStyleAction; import freemind.modes.mindmapmode.actions.EdgeWidthAction; import freemind.modes.mindmapmode.actions.EditAction; import freemind.modes.mindmapmode.actions.ExportBranchAction; import freemind.modes.mindmapmode.actions.FontFamilyAction; import freemind.modes.mindmapmode.actions.FontSizeAction; import freemind.modes.mindmapmode.actions.HookAction; import freemind.modes.mindmapmode.actions.IconAction; import freemind.modes.mindmapmode.actions.ImportExplorerFavoritesAction; import freemind.modes.mindmapmode.actions.ImportFolderStructureAction; import freemind.modes.mindmapmode.actions.ItalicAction; import freemind.modes.mindmapmode.actions.JoinNodesAction; import freemind.modes.mindmapmode.actions.MindMapActions; import freemind.modes.mindmapmode.actions.MindMapControllerHookAction; import freemind.modes.mindmapmode.actions.ModeControllerActionHandler; import freemind.modes.mindmapmode.actions.MoveNodeAction; import freemind.modes.mindmapmode.actions.NewChildAction; import freemind.modes.mindmapmode.actions.NewPreviousSiblingAction; import freemind.modes.mindmapmode.actions.NewSiblingAction; import freemind.modes.mindmapmode.actions.NodeBackgroundColorAction; import freemind.modes.mindmapmode.actions.NodeBackgroundColorAction.RemoveNodeBackgroundColorAction; import freemind.modes.mindmapmode.actions.NodeColorAction; import freemind.modes.mindmapmode.actions.NodeColorBlendAction; import freemind.modes.mindmapmode.actions.NodeGeneralAction; import freemind.modes.mindmapmode.actions.NodeHookAction; import freemind.modes.mindmapmode.actions.NodeStyleAction; import freemind.modes.mindmapmode.actions.NodeUpAction; import freemind.modes.mindmapmode.actions.PasteAction; import freemind.modes.mindmapmode.actions.PasteAsPlainTextAction; import freemind.modes.mindmapmode.actions.RedoAction; import freemind.modes.mindmapmode.actions.RemoveAllIconsAction; import freemind.modes.mindmapmode.actions.RemoveArrowLinkAction; import freemind.modes.mindmapmode.actions.RemoveIconAction; import freemind.modes.mindmapmode.actions.RevertAction; import freemind.modes.mindmapmode.actions.SelectAllAction; import freemind.modes.mindmapmode.actions.SelectBranchAction; import freemind.modes.mindmapmode.actions.SetLinkByTextFieldAction; import freemind.modes.mindmapmode.actions.SingleNodeOperation; import freemind.modes.mindmapmode.actions.ToggleChildrenFoldedAction; import freemind.modes.mindmapmode.actions.ToggleFoldedAction; import freemind.modes.mindmapmode.actions.UnderlinedAction; import freemind.modes.mindmapmode.actions.UndoAction; import freemind.modes.mindmapmode.actions.UsePlainTextAction; import freemind.modes.mindmapmode.actions.UseRichFormattingAction; import freemind.modes.mindmapmode.actions.xml.ActionFactory; import freemind.modes.mindmapmode.actions.xml.ActionPair; import freemind.modes.mindmapmode.actions.xml.UndoActionHandler; import freemind.modes.mindmapmode.attributeactors.AssignAttributeDialog; import freemind.modes.mindmapmode.attributeactors.MindMapModeAttributeController; import freemind.modes.mindmapmode.hooks.MindMapHookFactory; import freemind.modes.mindmapmode.listeners.MindMapMouseMotionManager; import freemind.modes.mindmapmode.listeners.MindMapNodeDropListener; import freemind.modes.mindmapmode.listeners.MindMapNodeMotionListener; import freemind.view.MapModule; import freemind.view.mindmapview.MainView; import freemind.view.mindmapview.MapView; import freemind.view.mindmapview.NodeView; import freemind.view.mindmapview.attributeview.AttributePopupMenu; public class MindMapController extends ControllerAdapter implements MindMapActions, MapSourceChangedObserver { private static final String ACCESSORIES_PLUGINS_NODE_NOTE = "accessories.plugins.NodeNote"; /** * @author foltin * @date 24.01.2012 */ private final class MapSourceChangeDialog implements Runnable { /** * */ private boolean mReturnValue = true; /** * @param pReturnValue */ private MapSourceChangeDialog() { } public void run() { int showResult = new OptionalDontShowMeAgainDialog( getFrame().getJFrame(), getSelectedView(), "file_changed_on_disk_reload", "confirmation", MindMapController.this, new OptionalDontShowMeAgainDialog.StandardPropertyHandler( getController(), FreeMind.RESOURCES_RELOAD_FILES_WITHOUT_QUESTION), OptionalDontShowMeAgainDialog.BOTH_OK_AND_CANCEL_OPTIONS_ARE_STORED) .show().getResult(); if (showResult != JOptionPane.OK_OPTION) { getFrame().out( Tools.expandPlaceholders(getText("file_not_reloaded"), getMap().getFile().toString())); mReturnValue = false; return; } revertAction.actionPerformed(null); } public boolean getReturnValue() { return mReturnValue; } } protected class AssignAttributesAction extends AbstractAction { public AssignAttributesAction() { super(getText("attributes_assign_dialog")); } public void actionPerformed(ActionEvent e) { if (assignAttributeDialog == null) { assignAttributeDialog = new AssignAttributeDialog(getView()); } assignAttributeDialog.show(); } } public interface MindMapControllerPlugin { } private static final String RESOURCE_UNFOLD_ON_PASTE = "unfold_on_paste"; private static Logger logger; // for MouseEventHandlers private HashSet mRegisteredMouseWheelEventHandler = new HashSet(); private ActionFactory actionFactory; private Vector hookActions; // Mode mode; private MindMapPopupMenu popupmenu; // private JToolBar toolbar; private MindMapToolBar toolbar; private boolean addAsChildMode = false; private Clipboard clipboard = null; private Clipboard selection = null; private HookFactory nodeHookFactory; /** * This handler evaluates the compound xml actions. Don't delete it! */ private CompoundActionHandler compound = null; public ApplyPatternAction patterns[] = new ApplyPatternAction[0]; // Make // sure // it is // initialized public Action newMap = new NewMapAction(this); public Action open = new OpenAction(this); public Action save = new SaveAction(this); public Action saveAs = new SaveAsAction(this); public Action exportToHTML = new ExportToHTMLAction(this); public Action exportBranchToHTML = new ExportBranchToHTMLAction(this); public Action editLong = new EditLongAction(); public Action editAttributes = new EditAttributesAction(); protected AssignAttributeDialog assignAttributeDialog = null; public Action assignAttributes = new AssignAttributesAction(); public Action newSibling = new NewSiblingAction(this); public Action newPreviousSibling = new NewPreviousSiblingAction(this); public Action setLinkByFileChooser = new SetLinkByFileChooserAction(); public Action setImageByFileChooser = new SetImageByFileChooserAction(); public Action followLink = new FollowLinkAction(); public Action openLinkDirectory = new OpenLinkDirectoryAction(); public Action exportBranch = new ExportBranchAction(this); public Action importBranch = new ImportBranchAction(); public Action importLinkedBranch = new ImportLinkedBranchAction(); public Action importLinkedBranchWithoutRoot = new ImportLinkedBranchWithoutRootAction(); public Action showAttributeManagerAction = null; public Action propertyAction = null; public Action increaseNodeFont = new NodeGeneralAction(this, "increase_node_font_size", null, new SingleNodeOperation() { public void apply(MindMapMapModel map, MindMapNodeModel node) { increaseFontSize(node, 1); } }); public Action decreaseNodeFont = new NodeGeneralAction(this, "decrease_node_font_size", null, new SingleNodeOperation() { public void apply(MindMapMapModel map, MindMapNodeModel node) { increaseFontSize(node, -1); } }); public UndoAction undo = null; public RedoAction redo = null; public CopyAction copy = null; public Action copySingle = null; public CutAction cut = null; public PasteAction paste = null; public PasteAsPlainTextAction pasteAsPlainText = null; public BoldAction bold = null; public ItalicAction italic = null; public UnderlinedAction underlined = null; public FontSizeAction fontSize = null; public FontFamilyAction fontFamily = null; public NodeColorAction nodeColor = null; public EditAction edit = null; public NewChildAction newChild = null; public DeleteChildAction deleteChild = null; public ToggleFoldedAction toggleFolded = null; public ToggleChildrenFoldedAction toggleChildrenFolded = null; public UseRichFormattingAction useRichFormatting = null; public UsePlainTextAction usePlainText = null; public NodeUpAction nodeUp = null; public NodeDownAction nodeDown = null; public EdgeColorAction edgeColor = null; public EdgeWidthAction EdgeWidth_WIDTH_PARENT = null; public EdgeWidthAction EdgeWidth_WIDTH_THIN = null; public EdgeWidthAction EdgeWidth_1 = null; public EdgeWidthAction EdgeWidth_2 = null; public EdgeWidthAction EdgeWidth_4 = null; public EdgeWidthAction EdgeWidth_8 = null; public EdgeWidthAction edgeWidths[] = null; public EdgeStyleAction EdgeStyle_linear = null; public EdgeStyleAction EdgeStyle_bezier = null; public EdgeStyleAction EdgeStyle_sharp_linear = null; public EdgeStyleAction EdgeStyle_sharp_bezier = null; public EdgeStyleAction edgeStyles[] = null; public NodeColorBlendAction nodeColorBlend = null; public NodeStyleAction fork = null; public NodeStyleAction bubble = null; public CloudAction cloud = null; public freemind.modes.mindmapmode.actions.CloudColorAction cloudColor = null; public AddArrowLinkAction addArrowLinkAction = null; public RemoveArrowLinkAction removeArrowLinkAction = null; public ColorArrowLinkAction colorArrowLinkAction = null; public ChangeArrowsInArrowLinkAction changeArrowsInArrowLinkAction = null; public NodeBackgroundColorAction nodeBackgroundColor = null; public RemoveNodeBackgroundColorAction removeNodeBackgroundColor = null; public IconAction unknownIconAction = null; public RemoveIconAction removeLastIconAction = null; public RemoveAllIconsAction removeAllIconsAction = null; public SetLinkByTextFieldAction setLinkByTextField = null; public AddLocalLinkAction addLocalLinkAction = null; public GotoLinkNodeAction gotoLinkNodeAction = null; public JoinNodesAction joinNodes = null; public MoveNodeAction moveNodeAction = null; public ImportExplorerFavoritesAction importExplorerFavorites = null; public ImportFolderStructureAction importFolderStructure = null; public ChangeArrowLinkEndPoints changeArrowLinkEndPoints = null; public FindAction find = null; public FindNextAction findNext = null; public NodeHookAction nodeHookAction = null; public RevertAction revertAction = null; public SelectBranchAction selectBranchAction = null; public SelectAllAction selectAllAction = null; // Extension Actions public Vector iconActions = new Vector(); // fc FileFilter filefilter = new MindMapFilter(); private MenuStructure mMenuStructure; private List mRegistrations; private List mPatternsList = new Vector(); private long mGetEventIfChangedAfterThisTimeInMillies = 0; public MindMapController(Mode mode) { super(mode); if (logger == null) { logger = getFrame().getLogger(this.getClass().getName()); } // create action factory: actionFactory = new ActionFactory(getController()); // create compound handler, that evaluates the compound xml actions. compound = new CompoundActionHandler(this); init(); } protected void init() { logger.info("createIconActions"); // create standard actions: createStandardActions(); // icon actions: createIconActions(); logger.info("createNodeHookActions"); // node hook actions: createNodeHookActions(); logger.info("mindmap_menus"); // load menus: try { InputStream in; in = this.getFrame().getResource("mindmap_menus.xml").openStream(); mMenuStructure = updateMenusFromXml(in); } catch (IOException e) { // TODO Auto-generated catch block freemind.main.Resources.getInstance().logException(e); } logger.info("MindMapPopupMenu"); popupmenu = new MindMapPopupMenu(this); logger.info("MindMapToolBar"); toolbar = new MindMapToolBar(this); // addAsChildMode (use old model of handling CtrN) (PN) addAsChildMode = Resources.getInstance() .getBoolProperty("add_as_child"); mRegistrations = new Vector(); attributeController = new MindMapModeAttributeController(this); showAttributeManagerAction = getController().showAttributeManagerAction; propertyAction = getController().propertyAction; } private void createStandardActions() { // prepare undo: undo = new UndoAction(this); redo = new RedoAction(this); // register default action handler: // the executor must be the first here, because it is executed last // then. getActionFactory().registerHandler( new ModeControllerActionHandler(getActionFactory())); getActionFactory().registerUndoHandler( new UndoActionHandler(this, undo, redo)); // debug: // getActionFactory().registerHandler( // new freemind.modes.mindmapmode.actions.xml.PrintActionHandler( // this)); cut = new CutAction(this); paste = new PasteAction(this); pasteAsPlainText = new PasteAsPlainTextAction(this); copy = new CopyAction(this); copySingle = new CopySingleAction(this); bold = new BoldAction(this); italic = new ItalicAction(this); underlined = new UnderlinedAction(this); fontSize = new FontSizeAction(this); fontFamily = new FontFamilyAction(this); edit = new EditAction(this); useRichFormatting = new UseRichFormattingAction(this); usePlainText = new UsePlainTextAction(this); newChild = new NewChildAction(this); deleteChild = new DeleteChildAction(this); toggleFolded = new ToggleFoldedAction(this); toggleChildrenFolded = new ToggleChildrenFoldedAction(this); nodeUp = new NodeUpAction(this); nodeDown = new NodeDownAction(this); edgeColor = new EdgeColorAction(this); nodeColor = new NodeColorAction(this); nodeColorBlend = new NodeColorBlendAction(this); fork = new NodeStyleAction(this, MindMapNode.STYLE_FORK); bubble = new NodeStyleAction(this, MindMapNode.STYLE_BUBBLE); // this is an unknown icon and thus corrected by mindicon: removeLastIconAction = new RemoveIconAction(this); // this action handles the xml stuff: (undo etc.) unknownIconAction = new IconAction(this, MindIcon.factory((String) MindIcon.getAllIconNames().get(0)), removeLastIconAction); removeLastIconAction.setIconAction(unknownIconAction); removeAllIconsAction = new RemoveAllIconsAction(this, unknownIconAction); // load pattern actions: loadPatternActions(); EdgeWidth_WIDTH_PARENT = new EdgeWidthAction(this, EdgeAdapter.WIDTH_PARENT); EdgeWidth_WIDTH_THIN = new EdgeWidthAction(this, EdgeAdapter.WIDTH_THIN); EdgeWidth_1 = new EdgeWidthAction(this, 1); EdgeWidth_2 = new EdgeWidthAction(this, 2); EdgeWidth_4 = new EdgeWidthAction(this, 4); EdgeWidth_8 = new EdgeWidthAction(this, 8); edgeWidths = new EdgeWidthAction[] { EdgeWidth_WIDTH_PARENT, EdgeWidth_WIDTH_THIN, EdgeWidth_1, EdgeWidth_2, EdgeWidth_4, EdgeWidth_8 }; EdgeStyle_linear = new EdgeStyleAction(this, EdgeAdapter.EDGESTYLE_LINEAR); EdgeStyle_bezier = new EdgeStyleAction(this, EdgeAdapter.EDGESTYLE_BEZIER); EdgeStyle_sharp_linear = new EdgeStyleAction(this, EdgeAdapter.EDGESTYLE_SHARP_LINEAR); EdgeStyle_sharp_bezier = new EdgeStyleAction(this, EdgeAdapter.EDGESTYLE_SHARP_BEZIER); edgeStyles = new EdgeStyleAction[] { EdgeStyle_linear, EdgeStyle_bezier, EdgeStyle_sharp_linear, EdgeStyle_sharp_bezier }; cloud = new CloudAction(this); cloudColor = new freemind.modes.mindmapmode.actions.CloudColorAction( this); addArrowLinkAction = new AddArrowLinkAction(this); removeArrowLinkAction = new RemoveArrowLinkAction(this, null); addArrowLinkAction.setRemoveAction(removeArrowLinkAction); colorArrowLinkAction = new ColorArrowLinkAction(this, null); changeArrowsInArrowLinkAction = new ChangeArrowsInArrowLinkAction(this, "none", null, null, true, true); nodeBackgroundColor = new NodeBackgroundColorAction(this); removeNodeBackgroundColor = new RemoveNodeBackgroundColorAction(this); setLinkByTextField = new SetLinkByTextFieldAction(this); addLocalLinkAction = new AddLocalLinkAction(this); gotoLinkNodeAction = new GotoLinkNodeAction(this, null); moveNodeAction = new MoveNodeAction(this); joinNodes = new JoinNodesAction(this); importExplorerFavorites = new ImportExplorerFavoritesAction(this); importFolderStructure = new ImportFolderStructureAction(this); changeArrowLinkEndPoints = new ChangeArrowLinkEndPoints(this); find = new FindAction(this); findNext = new FindNextAction(this, find); nodeHookAction = new NodeHookAction("no_title", this); revertAction = new RevertAction(this); selectBranchAction = new SelectBranchAction(this); selectAllAction = new SelectAllAction(this); } /** * Tries to load the user patterns and proposes an update to the new format, * if they are old fashioned (this is determined by having an exception * while reading the pattern file). */ private void loadPatternActions() { try { loadPatterns(getPatternReader()); } catch (Exception ex) { System.err.println("Patterns not loaded:" + ex); // repair old patterns: String repairTitle = "Repair patterns"; File patternsFile = getFrame().getPatternsFile(); int result = JOptionPane .showConfirmDialog( null, "<html>The pattern file format has changed, <br>" + "and it seems, that your pattern file<br>" + "'" + patternsFile.getAbsolutePath() + "'<br> is formatted in the old way. <br>" + "Should I try to repair the pattern file <br>" + "(otherwise, you should update it by hand or delete it)?", repairTitle, JOptionPane.YES_NO_OPTION); if (result == JOptionPane.YES_OPTION) { // try xslt script: boolean success = false; try { loadPatterns(Tools.getUpdateReader( Tools.getReaderFromFile(patternsFile), "patterns_updater.xslt", getFrame())); // save patterns directly: StylePatternFactory.savePatterns(new FileWriter( patternsFile), mPatternsList); success = true; } catch (Exception e) { freemind.main.Resources.getInstance().logException(e); } if (success) { JOptionPane.showMessageDialog(null, "Successfully repaired the pattern file.", repairTitle, JOptionPane.PLAIN_MESSAGE); } else { JOptionPane.showMessageDialog(null, "An error occured repairing the pattern file.", repairTitle, JOptionPane.WARNING_MESSAGE); } } } } /** * @throws FileNotFoundException * @throws IOException */ public Reader getPatternReader() throws FileNotFoundException, IOException { Reader reader = null; File patternsFile = getFrame().getPatternsFile(); if (patternsFile != null && patternsFile.exists()) { reader = new FileReader(patternsFile); } else { System.out.println("User patterns file " + patternsFile + " not found."); reader = new InputStreamReader(getResource("patterns.xml") .openStream()); } return reader; } public boolean isUndoAction() { return undo.isUndoAction() || redo.isUndoAction(); } public boolean load(String xmlMapContents, String filePrefix) { try { File tempFile = File.createTempFile(filePrefix, freemind.main.FreeMindCommon.FREEMIND_FILE_EXTENSION, new File(getFrame().getFreemindDirectory())); FileWriter fw = new FileWriter(tempFile); fw.write(xmlMapContents); fw.close(); load(tempFile); return true; } catch (Exception e) { freemind.main.Resources.getInstance().logException(e); } return false; } /** * Creates the patterns actions (saved in array patterns), and the pure * patterns list (saved in mPatternsList). * * @throws Exception */ public void loadPatterns(Reader reader) throws Exception { createPatterns(StylePatternFactory.loadPatterns(reader)); } private void createPatterns(List patternsList) throws Exception { mPatternsList = patternsList; patterns = new ApplyPatternAction[patternsList.size()]; for (int i = 0; i < patterns.length; i++) { Pattern actualPattern = (Pattern) patternsList.get(i); patterns[i] = new ApplyPatternAction(this, actualPattern); // search icons for patterns: PatternIcon patternIcon = actualPattern.getPatternIcon(); if (patternIcon != null && patternIcon.getValue() != null) { patterns[i].putValue(Action.SMALL_ICON, MindIcon.factory(patternIcon.getValue()).getIcon()); } } } /** * This method is called after and before a change of the map module. Use it * to perform the actions that cannot be performed at creation time. * */ public void startupController() { super.startupController(); getToolBar().startup(); HookFactory hookFactory = getHookFactory(); List pluginRegistrations = hookFactory.getRegistrations(); logger.fine("mScheduledActions are executed: " + pluginRegistrations.size()); for (Iterator i = pluginRegistrations.iterator(); i.hasNext();) { // call constructor: try { RegistrationContainer container = (RegistrationContainer) i .next(); Class registrationClass = container.hookRegistrationClass; Constructor hookConstructor = registrationClass .getConstructor(new Class[] { ModeController.class, MindMap.class }); HookRegistration registrationInstance = (HookRegistration) hookConstructor .newInstance(new Object[] { this, getMap() }); // register the instance to enable basePlugins. hookFactory.registerRegistrationContainer(container, registrationInstance); registrationInstance.register(); mRegistrations.add(registrationInstance); } catch (Exception e) { freemind.main.Resources.getInstance().logException(e); } } invokeHooksRecursively((NodeAdapter) getRootNode(), getMap()); // register mouse motion handler: getController().getMapMouseMotionListener().register( new MindMapMouseMotionManager(this)); getController().getNodeDropListener().register( new MindMapNodeDropListener(this)); getController().getNodeKeyListener().register( new CommonNodeKeyListener(this, new EditHandler() { public void edit(KeyEvent e, boolean addNew, boolean editLong) { MindMapController.this.edit(e, addNew, editLong); } })); getController().getNodeMotionListener().register( new MindMapNodeMotionListener(this)); getController().getNodeMouseMotionListener().register( new CommonNodeMouseMotionListener(this)); getMap().registerMapSourceChangedObserver(this, mGetEventIfChangedAfterThisTimeInMillies); } public void shutdownController() { super.shutdownController(); for (Iterator i = mRegistrations.iterator(); i.hasNext();) { HookRegistration registrationInstance = (HookRegistration) i.next(); registrationInstance.deRegister(); } getHookFactory().deregisterAllRegistrationContainer(); mRegistrations.clear(); // deregister motion handler getController().getMapMouseMotionListener().deregister(); getController().getNodeDropListener().deregister(); getController().getNodeKeyListener().deregister(); getController().getNodeMotionListener().deregister(); getController().getNodeMouseMotionListener().deregister(); mGetEventIfChangedAfterThisTimeInMillies = getMap() .deregisterMapSourceChangedObserver(this); getToolBar().shutdown(); } public MapAdapter newModel(ModeController modeController) { return new MindMapMapModel(getFrame(), modeController); } private void createIconActions() { Vector iconNames = MindIcon.getAllIconNames(); File iconDir = new File(Resources.getInstance().getFreemindDirectory(), "icons"); if (iconDir.exists()) { String[] userIconArray = iconDir.list(new FilenameFilter() { public boolean accept(File dir, String name) { return name.matches(".*\\.png"); } }); if (userIconArray != null) for (int i = 0; i < userIconArray.length; ++i) { String iconName = userIconArray[i]; iconName = iconName.substring(0, iconName.length() - 4); if (iconName.equals("")) { continue; } iconNames.add(iconName); } } for (int i = 0; i < iconNames.size(); ++i) { String iconName = ((String) iconNames.get(i)); MindIcon myIcon = MindIcon.factory(iconName); IconAction myAction = new IconAction(this, myIcon, removeLastIconAction); iconActions.add(myAction); } } /** * */ protected void createNodeHookActions() { if (hookActions == null) { hookActions = new Vector(); // HOOK TEST MindMapHookFactory factory = (MindMapHookFactory) getHookFactory(); List nodeHookNames = factory.getPossibleNodeHooks(); for (Iterator i = nodeHookNames.iterator(); i.hasNext();) { String hookName = (String) i.next(); // create hook action. NodeHookAction action = new NodeHookAction(hookName, this); hookActions.add(action); } List modeControllerHookNames = factory .getPossibleModeControllerHooks(); for (Iterator i = modeControllerHookNames.iterator(); i.hasNext();) { String hookName = (String) i.next(); MindMapControllerHookAction action = new MindMapControllerHookAction( hookName, this); hookActions.add(action); } // HOOK TEST END } } public FileFilter getFileFilter() { return filefilter; } public void nodeChanged(MindMapNode n) { super.nodeChanged(n); final MapModule mapModule = getController().getMapModule(); // only for the selected node (fc, 2.5.2004) if (mapModule != null && n == mapModule.getModeController().getSelected()) { updateToolbar(n); } } /* (non-Javadoc) * @see freemind.modes.ControllerAdapter#onFocusNode(freemind.view.mindmapview.NodeView) */ public void onFocusNode(NodeView pNode) { super.onFocusNode(pNode); updateToolbar(pNode.getModel()); } private void updateToolbar(MindMapNode n) { toolbar.selectFontSize(n.getFontSize()); toolbar.selectFontName(n.getFontFamilyName()); } // fc, 14.12.2004: changes, such that different models can be used: private NewNodeCreator myNewNodeCreator = null; private MindMapModeAttributeController attributeController; /** * A general list of MindMapControllerPlugin s. Members need to be tested * for the right class and casted to be applied. */ private HashSet mPlugins = new HashSet(); public interface NewNodeCreator { MindMapNode createNode(Object userObject, MindMap map); } public class DefaultMindMapNodeCreator implements NewNodeCreator { public MindMapNode createNode(Object userObject, MindMap map) { return new MindMapNodeModel(userObject, getFrame(), map); } } public void setNewNodeCreator(NewNodeCreator creator) { myNewNodeCreator = creator; } public MindMapNode newNode(Object userObject, MindMap map) { // singleton default: if (myNewNodeCreator == null) { myNewNodeCreator = new DefaultMindMapNodeCreator(); } return myNewNodeCreator.createNode(userObject, map); } // fc, 14.12.2004: end "different models" change // get/set methods /** */ public void updateMenus(StructuredMenuHolder holder) { processMenuCategory(holder, mMenuStructure.getListChoiceList(), ""); /* * MenuBar * . * MENU_BAR_PREFIX */ // add hook actions to this holder. // hooks, fc, 1.3.2004: MindMapHookFactory hookFactory = (MindMapHookFactory) getHookFactory(); for (int i = 0; i < hookActions.size(); ++i) { AbstractAction hookAction = (AbstractAction) hookActions.get(i); String hookName = ((HookAction) hookAction).getHookName(); hookFactory.decorateAction(hookName, hookAction); List hookMenuPositions = hookFactory.getHookMenuPositions(hookName); for (Iterator j = hookMenuPositions.iterator(); j.hasNext();) { String pos = (String) j.next(); holder.addMenuItem( hookFactory.getMenuItem(hookName, hookAction), pos); } } // update popup and toolbar: popupmenu.update(holder); toolbar.update(holder); // editMenu.add(getExtensionMenu()); String formatMenuString = MenuBar.FORMAT_MENU; createPatternSubMenu(holder, formatMenuString); // editMenu.add(getIconMenu()); addIconsToMenu(holder, MenuBar.INSERT_MENU + "icons"); } public void addIconsToMenu(StructuredMenuHolder holder, String iconMenuString) { JMenu iconMenu = holder.addMenu(new JMenu(getText("icon_menu")), iconMenuString + "/."); holder.addAction(removeLastIconAction, iconMenuString + "/removeLastIcon"); holder.addAction(removeAllIconsAction, iconMenuString + "/removeAllIcons"); holder.addSeparator(iconMenuString); for (int i = 0; i < iconActions.size(); ++i) { JMenuItem item = holder.addAction((Action) iconActions.get(i), iconMenuString + "/" + i); } } /** */ public void createPatternSubMenu(StructuredMenuHolder holder, String formatMenuString) { for (int i = 0; i < patterns.length; ++i) { JMenuItem item = holder.addAction(patterns[i], formatMenuString + "patterns/patterns/" + i); item.setAccelerator(KeyStroke .getKeyStroke(getFrame().getAdjustableProperty( "keystroke_apply_pattern_" + (i + 1)))); } } public MenuStructure updateMenusFromXml(InputStream in) { // get from resources: try { IUnmarshallingContext unmarshaller = XmlBindingTools.getInstance() .createUnmarshaller(); MenuStructure menus = (MenuStructure) unmarshaller .unmarshalDocument(in, null); return menus; } catch (JiBXException e) { freemind.main.Resources.getInstance().logException(e); throw new IllegalArgumentException( "Menu structure could not be read."); } } /** */ public void processMenuCategory(StructuredMenuHolder holder, List list, String category) { String categoryCopy = category; ButtonGroup buttonGroup = null; for (Iterator i = list.iterator(); i.hasNext();) { Object obj = (Object) i.next(); if (obj instanceof MenuCategoryBase) { MenuCategoryBase cat = (MenuCategoryBase) obj; String newCategory = categoryCopy + "/" + cat.getName(); holder.addCategory(newCategory); if (cat instanceof MenuSubmenu) { MenuSubmenu submenu = (MenuSubmenu) cat; holder.addMenu(new JMenu(getText(submenu.getNameRef())), newCategory + "/."); } processMenuCategory(holder, cat.getListChoiceList(), newCategory); } else if (obj instanceof MenuActionBase) { MenuActionBase action = (MenuActionBase) obj; String field = action.getField(); String name = action.getName(); if (name == null) { name = field; } String keystroke = action.getKeyRef(); try { Action theAction = (Action) Tools.getField(new Object[] { this, getController() }, field); String theCategory = categoryCopy + "/" + name; if (obj instanceof MenuCheckedAction) { addCheckBox(holder, theCategory, theAction, keystroke); } else if (obj instanceof MenuRadioAction) { final JRadioButtonMenuItem item = (JRadioButtonMenuItem) addRadioItem( holder, theCategory, theAction, keystroke, ((MenuRadioAction) obj).getSelected()); if (buttonGroup == null) buttonGroup = new ButtonGroup(); buttonGroup.add(item); } else { add(holder, theCategory, theAction, keystroke); } } catch (Exception e1) { freemind.main.Resources.getInstance().logException(e1); } } else if (obj instanceof MenuSeparator) { holder.addSeparator(categoryCopy); } /* else exception */ } } public JPopupMenu getPopupMenu() { return popupmenu; } /** * Link implementation: If this is a link, we want to make a popup with at * least removelink available. */ public JPopupMenu getPopupForModel(java.lang.Object obj) { if (obj instanceof MindMapArrowLinkModel) { // yes, this is a link. MindMapArrowLinkModel link = (MindMapArrowLinkModel) obj; JPopupMenu arrowLinkPopup = new JPopupMenu(); // block the screen while showing popup. arrowLinkPopup.addPopupMenuListener(this.popupListenerSingleton); removeArrowLinkAction.setArrowLink(link); arrowLinkPopup.add(new RemoveArrowLinkAction(this, link)); arrowLinkPopup.add(new ColorArrowLinkAction(this, link)); arrowLinkPopup.addSeparator(); /* The arrow state as radio buttons: */ JRadioButtonMenuItem itemnn = new JRadioButtonMenuItem( new ChangeArrowsInArrowLinkAction(this, "none", "images/arrow-mode-none.png", link, false, false)); JRadioButtonMenuItem itemnt = new JRadioButtonMenuItem( new ChangeArrowsInArrowLinkAction(this, "forward", "images/arrow-mode-forward.png", link, false, true)); JRadioButtonMenuItem itemtn = new JRadioButtonMenuItem( new ChangeArrowsInArrowLinkAction(this, "backward", "images/arrow-mode-backward.png", link, true, false)); JRadioButtonMenuItem itemtt = new JRadioButtonMenuItem( new ChangeArrowsInArrowLinkAction(this, "both", "images/arrow-mode-both.png", link, true, true)); itemnn.setText(null); itemnt.setText(null); itemtn.setText(null); itemtt.setText(null); arrowLinkPopup.add(itemnn); arrowLinkPopup.add(itemnt); arrowLinkPopup.add(itemtn); arrowLinkPopup.add(itemtt); // select the right one: boolean a = !link.getStartArrow().equals("None"); boolean b = !link.getEndArrow().equals("None"); itemtt.setSelected(a && b); itemnt.setSelected(!a && b); itemtn.setSelected(a && !b); itemnn.setSelected(!a && !b); arrowLinkPopup.addSeparator(); arrowLinkPopup.add(new GotoLinkNodeAction(this, link.getSource())); arrowLinkPopup.add(new GotoLinkNodeAction(this, link.getTarget())); arrowLinkPopup.addSeparator(); // add all links from target and from source: HashSet NodeAlreadyVisited = new HashSet(); NodeAlreadyVisited.add(link.getSource()); NodeAlreadyVisited.add(link.getTarget()); Vector links = getMindMapMapModel().getLinkRegistry().getAllLinks( link.getSource()); links.addAll(getMindMapMapModel().getLinkRegistry().getAllLinks( link.getTarget())); for (int i = 0; i < links.size(); ++i) { MindMapArrowLinkModel foreign_link = (MindMapArrowLinkModel) links .get(i); if (NodeAlreadyVisited.add(foreign_link.getTarget())) { arrowLinkPopup.add(new GotoLinkNodeAction(this, foreign_link.getTarget())); } if (NodeAlreadyVisited.add(foreign_link.getSource())) { arrowLinkPopup.add(new GotoLinkNodeAction(this, foreign_link.getSource())); } } return arrowLinkPopup; } return null; } // convenience methods public MindMapMapModel getMindMapMapModel() { return (MindMapMapModel) getMap(); } public JToolBar getModeToolBar() { return getToolBar(); } MindMapToolBar getToolBar() { return toolbar; } public Component getLeftToolBar() { return toolbar.getLeftToolBar(); } /** * Enabled/Disabled all actions that are dependent on whether there is a map * open or not. */ protected void setAllActions(boolean enabled) { logger.fine("setAllActions:" + enabled); super.setAllActions(enabled); // own actions increaseNodeFont.setEnabled(enabled); decreaseNodeFont.setEnabled(enabled); exportBranch.setEnabled(enabled); exportBranchToHTML.setEnabled(enabled); editLong.setEnabled(enabled); newSibling.setEnabled(enabled); newPreviousSibling.setEnabled(enabled); setLinkByFileChooser.setEnabled(enabled); setImageByFileChooser.setEnabled(enabled); followLink.setEnabled(enabled); for (int i = 0; i < iconActions.size(); ++i) { ((Action) iconActions.get(i)).setEnabled(enabled); } save.setEnabled(enabled); saveAs.setEnabled(enabled); getToolBar().setAllActions(enabled); exportBranch.setEnabled(enabled); exportToHTML.setEnabled(enabled); importBranch.setEnabled(enabled); importLinkedBranch.setEnabled(enabled); importLinkedBranchWithoutRoot.setEnabled(enabled); // hooks: for (int i = 0; i < hookActions.size(); ++i) { ((Action) hookActions.get(i)).setEnabled(enabled); } cut.setEnabled(enabled); copy.setEnabled(enabled); copySingle.setEnabled(enabled); paste.setEnabled(enabled); pasteAsPlainText.setEnabled(enabled); undo.setEnabled(enabled); redo.setEnabled(enabled); edit.setEnabled(enabled); newChild.setEnabled(enabled); toggleFolded.setEnabled(enabled); toggleChildrenFolded.setEnabled(enabled); setLinkByTextField.setEnabled(enabled); italic.setEnabled(enabled); bold.setEnabled(enabled); find.setEnabled(enabled); findNext.setEnabled(enabled); addArrowLinkAction.setEnabled(enabled); addLocalLinkAction.setEnabled(enabled); nodeColorBlend.setEnabled(enabled); nodeUp.setEnabled(enabled); nodeBackgroundColor.setEnabled(enabled); nodeDown.setEnabled(enabled); importExplorerFavorites.setEnabled(enabled); importFolderStructure.setEnabled(enabled); joinNodes.setEnabled(enabled); deleteChild.setEnabled(enabled); cloud.setEnabled(enabled); cloudColor.setEnabled(enabled); // normalFont.setEnabled(enabled); nodeColor.setEnabled(enabled); edgeColor.setEnabled(enabled); removeLastIconAction.setEnabled(enabled); removeAllIconsAction.setEnabled(enabled); selectAllAction.setEnabled(enabled); selectBranchAction.setEnabled(enabled); removeNodeBackgroundColor.setEnabled(enabled); moveNodeAction.setEnabled(enabled); revertAction.setEnabled(enabled); for (int i = 0; i < edgeWidths.length; ++i) { edgeWidths[i].setEnabled(enabled); } fork.setEnabled(enabled); bubble.setEnabled(enabled); for (int i = 0; i < edgeStyles.length; ++i) { edgeStyles[i].setEnabled(enabled); } for (int i = 0; i < patterns.length; ++i) { patterns[i].setEnabled(enabled); } useRichFormatting.setEnabled(enabled); usePlainText.setEnabled(enabled); editAttributes.setEnabled(enabled); assignAttributes.setEnabled(enabled); } // // Actions // _______________________________________________________________________________ // This may later be moved to ControllerAdapter. So far there is no reason // for it. protected class ExportToHTMLAction extends AbstractAction { MindMapController c; public ExportToHTMLAction(MindMapController controller) { super(getText("export_to_html")); c = controller; } public void actionPerformed(ActionEvent e) { // from // https://sourceforge.net/tracker2/?func=detail&atid=307118&aid=1789765&group_id=7118 if (getMap().getFile() == null) { JOptionPane.showMessageDialog(getFrame().getContentPane(), getText("map_not_saved"), "FreeMind", JOptionPane.WARNING_MESSAGE); return; } try { File file = new File(c.getMindMapMapModel().getFile() + ".html"); saveHTML((MindMapNodeModel) c.getMindMapMapModel().getRoot(), file); loadURL(file.toString()); } catch (IOException ex) { freemind.main.Resources.getInstance().logException(ex); } } } protected class ExportBranchToHTMLAction extends AbstractAction { MindMapController c; public ExportBranchToHTMLAction(MindMapController controller) { super(getText("export_branch_to_html")); c = controller; } public void actionPerformed(ActionEvent e) { File mindmapFile = getMap().getFile(); if (mindmapFile == null) { JOptionPane.showMessageDialog(getFrame().getContentPane(), getText("map_not_saved"), "FreeMind", JOptionPane.WARNING_MESSAGE); return; } try { File file = File.createTempFile( mindmapFile.getName().replace( FreeMindCommon.FREEMIND_FILE_EXTENSION, "_"), ".html", mindmapFile.getParentFile()); saveHTML((MindMapNodeModel) getSelected(), file); loadURL(file.toString()); } catch (IOException ex) { } } } private class ImportBranchAction extends AbstractAction { ImportBranchAction() { super(getText("import_branch")); } public void actionPerformed(ActionEvent e) { MindMapNodeModel parent = (MindMapNodeModel) getSelected(); if (parent == null) { return; } FreeMindFileDialog chooser = getFileChooser(); int returnVal = chooser.showOpenDialog(getFrame().getContentPane()); if (returnVal == JFileChooser.APPROVE_OPTION) { try { MindMapNodeModel node = getMindMapMapModel().loadTree( chooser.getSelectedFile()); paste(node, parent); invokeHooksRecursively(node, getMindMapMapModel()); } catch (Exception ex) { handleLoadingException(ex); } } } } private class ImportLinkedBranchAction extends AbstractAction { ImportLinkedBranchAction() { super(getText("import_linked_branch")); } public void actionPerformed(ActionEvent e) { MindMapNodeModel selected = (MindMapNodeModel) getSelected(); if (selected == null || selected.getLink() == null) { JOptionPane.showMessageDialog(getView(), getText("import_linked_branch_no_link")); return; } URL absolute = null; try { String relative = selected.getLink(); absolute = new URL(Tools.fileToUrl(getMap().getFile()), relative); } catch (MalformedURLException ex) { JOptionPane.showMessageDialog(getView(), "Couldn't create valid URL for:" + getMap().getFile()); freemind.main.Resources.getInstance().logException(ex); return; } try { MindMapNodeModel node = getMindMapMapModel().loadTree( Tools.urlToFile(absolute)); paste(node, selected); invokeHooksRecursively(node, getMindMapMapModel()); } catch (Exception ex) { handleLoadingException(ex); } } } /** * This is exactly the opposite of exportBranch. */ private class ImportLinkedBranchWithoutRootAction extends AbstractAction { ImportLinkedBranchWithoutRootAction() { super(getText("import_linked_branch_without_root")); } public void actionPerformed(ActionEvent e) { MindMapNodeModel selected = (MindMapNodeModel) getSelected(); if (selected == null || selected.getLink() == null) { JOptionPane.showMessageDialog(getView(), getText("import_linked_branch_no_link")); return; } URL absolute = null; try { String relative = selected.getLink(); absolute = new URL(Tools.fileToUrl(getMap().getFile()), relative); } catch (MalformedURLException ex) { JOptionPane.showMessageDialog(getView(), "Couldn't create valid URL."); return; } try { MindMapNodeModel node = getMindMapMapModel().loadTree( Tools.urlToFile(absolute)); for (ListIterator i = node.childrenUnfolded(); i.hasNext();) { MindMapNodeModel importNode = (MindMapNodeModel) i.next(); paste(importNode, selected); invokeHooksRecursively(importNode, getMindMapMapModel()); } } // getModel().setLink(parent, null); } catch (Exception ex) { handleLoadingException(ex); } } } /* * MindMapController.java private class NodeViewStyleAction extends * AbstractAction { NodeViewStyleAction(final String style) { * super(getText(style)); m_style = style; } public void * actionPerformed(ActionEvent e) { for(ListIterator it = * getSelecteds().listIterator();it.hasNext();) { MindMapNodeModel selected * = (MindMapNodeModel)it.next(); getModel().setNodeStyle(selected, * m_style); }} private String m_style;} * * private class EdgeStyleAction extends AbstractAction { String style; * EdgeStyleAction(String style) { super(getText(style)); this.style = * style; } public void actionPerformed(ActionEvent e) { for(ListIterator it * = getSelecteds().listIterator();it.hasNext();) { MindMapNodeModel * selected = (MindMapNodeModel)it.next(); getModel().setEdgeStyle(selected, * style); }}} * * private class ApplyPatternAction extends AbstractAction { StylePattern * pattern; ApplyPatternAction(StylePattern pattern) { * super(pattern.getName()); this.pattern=pattern; } public void * actionPerformed(ActionEvent e) { for(ListIterator it = * getSelecteds().listIterator();it.hasNext();) { MindMapNodeModel selected * = (MindMapNodeModel)it.next(); * ((MindMapMapModel)getModel()).applyPattern(selected, pattern); }}} * * * * * // Nonaction classes // * ________________________________________________________________________ */ private class MindMapFilter extends FileFilter { public boolean accept(File f) { if (f.isDirectory()) return true; String extension = Tools.getExtension(f.getName()); if (extension != null) { if (extension .equals(freemind.main.FreeMindCommon.FREEMIND_FILE_EXTENSION_WITHOUT_DOT)) { return true; } else { return false; } } return false; } public String getDescription() { return getText("mindmaps_desc"); } } public void setBold(MindMapNode node, boolean bolded) { bold.setBold(node, bolded); } public void setItalic(MindMapNode node, boolean isItalic) { italic.setItalic(node, isItalic); } public void setCloud(MindMapNode node, boolean enable) { cloud.setCloud(node, enable); } public void setCloudColor(MindMapNode node, Color color) { cloudColor.setCloudColor(node, color); } // Node editing public void setFontSize(MindMapNode node, String fontSizeValue) { fontSize.setFontSize(node, fontSizeValue); } /** * */ public void increaseFontSize(MindMapNode node, int increment) { int newSize = Integer.valueOf(node.getFontSize()).intValue() + increment; if (newSize > 0) { setFontSize(node, Integer.toString(newSize)); } } public void setFontFamily(MindMapNode node, String fontFamilyValue) { fontFamily.setFontFamily(node, fontFamilyValue); } public void setNodeColor(MindMapNode node, Color color) { nodeColor.setNodeColor(node, color); } public void setNodeBackgroundColor(MindMapNode node, Color color) { nodeBackgroundColor.setNodeBackgroundColor(node, color); } public void blendNodeColor(MindMapNode node) { Color mapColor = getView().getBackground(); Color nodeColor = node.getColor(); if (nodeColor == null) { nodeColor = MapView.standardNodeTextColor; } setNodeColor(node, new Color((3 * mapColor.getRed() + nodeColor.getRed()) / 4, (3 * mapColor.getGreen() + nodeColor.getGreen()) / 4, (3 * mapColor.getBlue() + nodeColor.getBlue()) / 4)); } public void setEdgeColor(MindMapNode node, Color color) { edgeColor.setEdgeColor(node, color); } public void applyPattern(MindMapNode node, String patternName) { for (int i = 0; i < patterns.length; i++) { ApplyPatternAction patternAction = patterns[i]; if (patternAction.getPattern().getName().equals(patternName)) { patternAction.applyPattern(node, patternAction.getPattern()); break; } } } public void applyPattern(MindMapNode node, Pattern pattern) { if (patterns.length > 0) { patterns[0].applyPattern(node, pattern); } else { throw new IllegalArgumentException("No pattern defined."); } } public void addIcon(MindMapNode node, MindIcon icon) { unknownIconAction.addIcon(node, icon); } public void removeAllIcons(MindMapNode node) { removeAllIconsAction.removeAllIcons(node); } public int removeLastIcon(MindMapNode node) { return removeLastIconAction.removeLastIcon(node); } /** * */ public void addLink(MindMapNode source, MindMapNode target) { addArrowLinkAction.addLink(source, target); } public void removeReference(MindMapLink arrowLink) { removeArrowLinkAction.removeReference(arrowLink); } public void setArrowLinkColor(MindMapLink arrowLink, Color color) { colorArrowLinkAction.setArrowLinkColor(arrowLink, color); } /** * */ public void changeArrowsOfArrowLink(MindMapArrowLinkModel arrowLink, boolean hasStartArrow, boolean hasEndArrow) { changeArrowsInArrowLinkAction.changeArrowsOfArrowLink(arrowLink, hasStartArrow, hasEndArrow); } public void setArrowLinkEndPoints(MindMapArrowLink link, Point startPoint, Point endPoint) { changeArrowLinkEndPoints.setArrowLinkEndPoints(link, startPoint, endPoint); } public void setLink(MindMapNode node, String link) { setLinkByTextField.setLink(node, link); } // edit begins with home/end or typing (PN 6.2) public void edit(KeyEvent e, boolean addNew, boolean editLong) { edit.edit(e, addNew, editLong); } public void setNodeText(MindMapNode selected, String newText) { edit.setNodeText(selected, newText); } /** * */ public void setEdgeWidth(MindMapNode node, int width) { EdgeWidth_1.setEdgeWidth(node, width); } /** * */ public void setEdgeStyle(MindMapNode node, String style) { EdgeStyle_bezier.setEdgeStyle(node, style); } /** * */ public void setNodeStyle(MindMapNode node, String style) { fork.setStyle(node, style); } public Transferable copy(MindMapNode node, boolean saveInvisible) { StringWriter stringWriter = new StringWriter(); try { ((MindMapNodeModel) node).save(stringWriter, getMap() .getLinkRegistry(), saveInvisible, true); } catch (IOException e) { } Vector nodeList = Tools.getVectorWithSingleElement(getNodeID(node)); return new MindMapNodesSelection(stringWriter.toString(), null, null, null, null, null, null, nodeList); } public Transferable cut() { return cut(getView().getSelectedNodesSortedByY()); } public Transferable cut(List nodeList) { return cut.cut(nodeList); } public void paste(Transferable t, MindMapNode parent) { paste(t, /* target= */parent, /* asSibling= */false, parent.isNewChildLeft()); } /* (non-Javadoc) * @see freemind.modes.mindmapmode.actions.MindMapActions#paste(java.awt.datatransfer.Transferable, freemind.modes.MindMapNode, boolean, boolean) */ public boolean paste(Transferable t, MindMapNode target, boolean asSibling, boolean isLeft) { if (!asSibling && target.isFolded() && Resources.getInstance().getBoolProperty( RESOURCE_UNFOLD_ON_PASTE)) { setFolded(target, false); } return paste.paste(t, target, asSibling, isLeft); } public void paste(MindMapNode node, MindMapNode parent) { paste.paste(node, parent); } public MindMapNode addNew(final MindMapNode target, final int newNodeMode, final KeyEvent e) { edit.stopEditing(); return newChild.addNew(target, newNodeMode, e); } public MindMapNode addNewNode(MindMapNode parent, int index, boolean newNodeIsLeft) { return newChild.addNewNode(parent, index, newNodeIsLeft); } public void deleteNode(MindMapNode selectedNode) { deleteChild.deleteNode(selectedNode); } public void toggleFolded() { toggleFolded.toggleFolded(); } public void setFolded(MindMapNode node, boolean folded) { toggleFolded.setFolded(node, folded); } public void moveNodes(MindMapNode selected, List selecteds, int direction) { nodeUp.moveNodes(selected, selecteds, direction); } public void joinNodes(MindMapNode selectedNode, List selectedNodes) { joinNodes.joinNodes(selectedNode, selectedNodes); } protected void setLinkByFileChooser() { String relative = getLinkByFileChooser(null); if (relative != null) setLink((NodeAdapter) getSelected(), relative); } protected void setImageByFileChooser() { ExampleFileFilter filter = new ExampleFileFilter(); filter.addExtension("jpg"); filter.addExtension("jpeg"); filter.addExtension("png"); filter.addExtension("gif"); filter.setDescription("JPG, PNG and GIF Images"); String relative = getLinkByFileChooser(filter); if (relative != null) { String strText = "<html><body><img src=\"" + relative + "\"/></body></html>"; setNodeText((MindMapNode) getSelected(), strText); } } protected String getLinkByFileChooser(FileFilter fileFilter) { String relative = null; File input; FreeMindFileDialog chooser = getFileChooser(fileFilter); if (getMap().getFile() == null) { JOptionPane.showMessageDialog(getFrame().getContentPane(), getText("not_saved_for_link_error"), "FreeMind", JOptionPane.WARNING_MESSAGE); return null; // In the previous version Freemind automatically displayed save // dialog. It happened very often, that user took this save // dialog to be an open link dialog; as a result, the new map // overwrote the linked map. } int returnVal = chooser.showOpenDialog(getFrame().getContentPane()); if (returnVal == JFileChooser.APPROVE_OPTION) { input = chooser.getSelectedFile(); relative = Tools.fileToRelativeUrlString(input, getMap().getFile()); } return relative; } public void loadURL(String relative) { if (getMap().getFile() == null) { getFrame().out("You must save the current map first!"); boolean result = save(); // canceled?? if (!result) { return; } } super.loadURL(relative); } public void addHook(MindMapNode focussed, List selecteds, String hookName, Properties pHookProperties) { nodeHookAction.addHook(focussed, selecteds, hookName, pHookProperties); } public void removeHook(MindMapNode focussed, List selecteds, String hookName) { nodeHookAction.removeHook(focussed, selecteds, hookName); } protected class SetLinkByFileChooserAction extends AbstractAction { public SetLinkByFileChooserAction() { super(getText("set_link_by_filechooser")); } public void actionPerformed(ActionEvent e) { setLinkByFileChooser(); } } protected class SetImageByFileChooserAction extends AbstractAction { public SetImageByFileChooserAction() { super(getText("set_image_by_filechooser")); } public void actionPerformed(ActionEvent e) { setImageByFileChooser(); getController().obtainFocusForSelected(); } } protected abstract class LinkActionBase extends AbstractAction implements MenuItemEnabledListener { public LinkActionBase(String pText) { super(pText); } public boolean isEnabled(JMenuItem pItem, Action pAction) { for (Iterator iterator = getSelecteds().iterator(); iterator .hasNext();) { MindMapNode selNode = (MindMapNode) iterator.next(); if (selNode.getLink() != null) return true; } return false; } } protected class FollowLinkAction extends LinkActionBase { public FollowLinkAction() { super(getText("follow_link")); } public void actionPerformed(ActionEvent e) { for (Iterator iterator = getSelecteds().iterator(); iterator .hasNext();) { MindMapNode selNode = (MindMapNode) iterator.next(); if (selNode.getLink() != null) { loadURL(selNode.getLink()); } } } } protected class OpenLinkDirectoryAction extends LinkActionBase { public OpenLinkDirectoryAction() { super(getText("open_link_directory")); } public void actionPerformed(ActionEvent event) { String link = ""; for (Iterator iterator = getSelecteds().iterator(); iterator .hasNext();) { MindMapNode selNode = (MindMapNode) iterator.next(); link = selNode.getLink(); if (link != null) { // as link is an URL, '/' is the only correct one. final int i = link.lastIndexOf('/'); if (i >= 0) { link = link.substring(0, i + 1); } logger.info("Opening link for directory " + link); loadURL(link); } } } } public void moveNodePosition(MindMapNode node, int parentVGap, int hGap, int shiftY) { moveNodeAction.moveNodeTo(node, parentVGap, hGap, shiftY); } // /////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////// public void plainClick(MouseEvent e) { /* perform action only if one selected node. */ if (getSelecteds().size() != 1) return; final MainView component = (MainView) e.getComponent(); if (component.isInFollowLinkRegion(e.getX())) { loadURL(); } else { MindMapNode node = (component).getNodeView().getModel(); if (!node.hasChildren()) { // then emulate the plain click. doubleClick(e); return; } toggleFolded(); } } public HookFactory getHookFactory() { // lazy creation. if (nodeHookFactory == null) { nodeHookFactory = new MindMapHookFactory(getFrame()); } return nodeHookFactory; } public NodeHook createNodeHook(String hookName, MindMapNode node, MindMap map) { HookFactory hookFactory = getHookFactory(); NodeHook hook = (NodeHook) hookFactory.createNodeHook(hookName); hook.setController(this); hook.setMap(map); if (hook instanceof PermanentNodeHook) { PermanentNodeHook permHook = (PermanentNodeHook) hook; if (hookFactory.getInstanciationMethod(hookName).isSingleton()) { // search for already instanciated hooks of this type: PermanentNodeHook otherHook = hookFactory.getHookInNode(node, hookName); if (otherHook != null) { return otherHook; } } node.addHook(permHook); } return hook; } public void invokeHook(ModeControllerHook hook) { try { hook.setController(this); // initialize: // the main invocation: hook.startupMapHook(); // and good bye. hook.shutdownMapHook(); } catch (Exception e) { freemind.main.Resources.getInstance().logException(e); } } public ActionFactory getActionFactory() { return actionFactory; } protected class EditLongAction extends AbstractAction { public EditLongAction() { super(getText("edit_long_node")); } public void actionPerformed(ActionEvent e) { edit(null, false, true); } } static public void saveHTML(MindMapNodeModel rootNodeOfBranch, File file) throws IOException { BufferedWriter fileout = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(file), FreeMind.DEFAULT_CHARSET)); MindMapHTMLWriter htmlWriter = new MindMapHTMLWriter(fileout); htmlWriter.saveHTML(rootNodeOfBranch); } static public void saveHTML(List mindMapNodes, Writer fileout) throws IOException { MindMapHTMLWriter htmlWriter = new MindMapHTMLWriter(fileout); htmlWriter.saveHTML(mindMapNodes); } /** */ public void splitNode(MindMapNode node, int caretPosition, String newText) { if (node.isRoot()) { return; } // If there are children, they go to the node below String futureText = newText != null ? newText : node.toString(); String[] strings = getContent(futureText, caretPosition); if (strings == null) { // do nothing return; } String newUpperContent = strings[0]; String newLowerContent = strings[1]; setNodeText(node, newUpperContent); MindMapNode parent = node.getParentNode(); MindMapNode lowerNode = addNewNode(parent, parent.getChildPosition(node) + 1, node.isLeft()); lowerNode.setColor(node.getColor()); lowerNode.setFont(node.getFont()); setNodeText(lowerNode, newLowerContent); } private String[] getContent(String text, int pos) { if (pos <= 0) { return null; } String[] strings = new String[2]; if (text.startsWith("<html>")) { HTMLEditorKit kit = new HTMLEditorKit(); HTMLDocument doc = new HTMLDocument(); StringReader buf = new StringReader(text); try { kit.read(buf, doc, 0); final char[] firstText = doc.getText(0, pos).toCharArray(); int firstStart = 0; int firstLen = pos; while ((firstStart < firstLen) && (firstText[firstStart] <= ' ')) { firstStart++; } while ((firstStart < firstLen) && (firstText[firstLen - 1] <= ' ')) { firstLen--; } int secondStart = 0; int secondLen = doc.getLength() - pos; final char[] secondText = doc.getText(pos, secondLen) .toCharArray(); while ((secondStart < secondLen) && (secondText[secondStart] <= ' ')) { secondStart++; } while ((secondStart < secondLen) && (secondText[secondLen - 1] <= ' ')) { secondLen--; } if (firstStart == firstLen || secondStart == secondLen) { return null; } StringWriter out = new StringWriter(); new FixedHTMLWriter(out, doc, firstStart, firstLen - firstStart) .write(); strings[0] = out.toString(); out = new StringWriter(); new FixedHTMLWriter(out, doc, pos + secondStart, secondLen - secondStart).write(); strings[1] = out.toString(); return strings; } catch (IOException e) { // TODO Auto-generated catch block freemind.main.Resources.getInstance().logException(e); } catch (BadLocationException e) { // TODO Auto-generated catch block freemind.main.Resources.getInstance().logException(e); } } else { if (pos >= text.length()) { return null; } strings[0] = text.substring(0, pos); strings[1] = text.substring(pos); } return strings; } protected void updateNode(MindMapNode node) { super.updateNode(node); recursiveCallUpdateHooks((MindMapNode) node, (MindMapNode) node /* * self * update */); } /** */ private void recursiveCallUpdateHooks(MindMapNode node, MindMapNode changedNode) { // Tell any node hooks that the node is changed: if (node instanceof MindMapNode) { for (Iterator i = ((MindMapNode) node).getActivatedHooks() .iterator(); i.hasNext();) { PermanentNodeHook hook = (PermanentNodeHook) i.next(); if ((!isUndoAction()) || hook instanceof UndoEventReceiver) { if (node == changedNode) hook.onUpdateNodeHook(); else hook.onUpdateChildrenHook(changedNode); } } } if (!node.isRoot() && node.getParentNode() != null) recursiveCallUpdateHooks(node.getParentNode(), changedNode); } public void doubleClick(MouseEvent e) { /* perform action only if one selected node. */ if (getSelecteds().size() != 1) return; MindMapNode node = ((MainView) e.getComponent()).getNodeView() .getModel(); // edit the node only if the node is a leaf (fc 0.7.1), or the root node // (fc 0.9.0) if (!e.isAltDown() && !e.isControlDown() && !e.isShiftDown() && !e.isPopupTrigger() && e.getButton() == MouseEvent.BUTTON1 && (node.getLink() == null)) { edit(null, false, false); } } public boolean extendSelection(MouseEvent e) { NodeView newlySelectedNodeView = ((MainView) e.getComponent()) .getNodeView(); // MindMapNode newlySelectedNode = newlySelectedNodeView.getModel(); boolean extend = e.isControlDown(); // Fixes Cannot select multiple single nodes * // https://sourceforge.net/tracker/?func=detail&atid=107118&aid=1675829&group_id=7118 if (Tools.isMacOsX()) { extend |= e.isMetaDown(); } boolean range = e.isShiftDown(); boolean branch = e.isAltGraphDown() || e.isAltDown(); /* * windows alt, * linux altgraph * .... */ boolean retValue = false; if (extend || range || branch || !getView().isSelected(newlySelectedNodeView)) { if (!range) { if (extend) getView().toggleSelected(newlySelectedNodeView); else select(newlySelectedNodeView); retValue = true; } else { retValue = getView().selectContinuous(newlySelectedNodeView); // /* fc, 25.1.2004: replace getView by controller methods.*/ // if (newlySelectedNodeView != getView().getSelected() && // newlySelectedNodeView.isSiblingOf(getView().getSelected())) { // getView().selectContinuous(newlySelectedNodeView); // retValue = true; // } else { // /* if shift was down, but no range can be selected, then the // new node is simply selected: */ // if(!getView().isSelected(newlySelectedNodeView)) { // getView().toggleSelected(newlySelectedNodeView); // retValue = true; // } } if (branch) { getView().selectBranch(newlySelectedNodeView, extend); retValue = true; } } if (retValue) { e.consume(); // Display link in status line String link = newlySelectedNodeView.getModel().getLink(); link = (link != null ? link : " "); getController().getFrame().out(link); } logger.fine("MouseEvent: extend:" + extend + ", range:" + range + ", branch:" + branch + ", event:" + e + ", retValue:" + retValue); obtainFocusForSelected(); return retValue; } public void registerMouseWheelEventHandler(MouseWheelEventHandler handler) { logger.fine("Registered MouseWheelEventHandler " + handler); mRegisteredMouseWheelEventHandler.add(handler); } public void deRegisterMouseWheelEventHandler(MouseWheelEventHandler handler) { logger.fine("Deregistered MouseWheelEventHandler " + handler); mRegisteredMouseWheelEventHandler.remove(handler); } public Set getRegisteredMouseWheelEventHandler() { return Collections.unmodifiableSet(mRegisteredMouseWheelEventHandler); } public String marshall(XmlAction action) { return Tools.marshall(action); } public XmlAction unMarshall(String inputString) { return Tools.unMarshall(inputString); } public void storeDialogPositions(JDialog dialog, WindowConfigurationStorage pStorage, String window_preference_storage_property) { XmlBindingTools.getInstance().storeDialogPositions(getController(), dialog, pStorage, window_preference_storage_property); } public WindowConfigurationStorage decorateDialog(JDialog dialog, String window_preference_storage_property) { return XmlBindingTools.getInstance().decorateDialog(getController(), dialog, window_preference_storage_property); } public AttributeController getAttributeController() { return attributeController; } public AttributePopupMenu getAttributeTablePopupMenu() { return new AttributePopupMenu(); } public XMLElement createXMLElement() { return new MindMapXMLElement(this); } public void setAttribute(MindMapNode pNode, int pPosition, Attribute pAttribute) { pNode.createAttributeTableModel(); pNode.getAttributes().setValueAt(pAttribute.getName(), pPosition, 0); pNode.getAttributes().setValueAt(pAttribute.getValue(), pPosition, 1); } public void removeAttribute(MindMapNode pNode, int pPosition) { pNode.createAttributeTableModel(); pNode.getAttributes().getAttributeController() .performRemoveRow(pNode.getAttributes(), pPosition); } public int addAttribute(MindMapNode node, Attribute pAttribute) { node.createAttributeTableModel(); NodeAttributeTableModel attributes = node.getAttributes(); int rowCount = attributes.getRowCount(); attributes.getAttributeController().performInsertRow(attributes, rowCount, pAttribute.getName(), pAttribute.getValue()); return rowCount; } public int editAttribute(MindMapNode pNode, String pName, String pNewValue) { pNode.createAttributeTableModel(); Attribute newAttribute = new Attribute(pName, pNewValue); NodeAttributeTableModel attributes = pNode.getAttributes(); for (int i = 0; i < attributes.getRowCount(); i++) { if (pName.equals(attributes.getAttribute(i).getName())) { if (pNewValue != null) { setAttribute(pNode, i, newAttribute); } else { // remove the attribute: removeAttribute(pNode, i); } return i; } } if (pNewValue == null) { // nothing to remove found. return -1; } return addAttribute(pNode, newAttribute); } public void insertNodeInto(MindMapNode newNode, MindMapNode parent, int index) { getModel().setSaved(false); super.insertNodeInto(newNode, parent, index); } public void removeNodeFromParent(MindMapNode selectedNode) { getModel().setSaved(false); // first deselect, and then remove. NodeView nodeView = getView().getNodeView(selectedNode); getView().deselect(nodeView); getModel().removeNodeFromParent(selectedNode); } public void nodeStyleChanged(MindMapNode node) { nodeChanged(node); final ListIterator childrenFolded = node.childrenFolded(); while (childrenFolded.hasNext()) { MindMapNode child = (MindMapNode) childrenFolded.next(); if (!(child.hasStyle() && child.getEdge().hasStyle())) { nodeStyleChanged(child); } } } public void repaintMap() { getView().repaint(); } public void clearNodeContents(MindMapNode pNode) { Pattern erasePattern = new Pattern(); erasePattern.setPatternEdgeColor(new PatternEdgeColor()); erasePattern.setPatternEdgeStyle(new PatternEdgeStyle()); erasePattern.setPatternEdgeWidth(new PatternEdgeWidth()); erasePattern.setPatternIcon(new PatternIcon()); erasePattern .setPatternNodeBackgroundColor(new PatternNodeBackgroundColor()); erasePattern.setPatternNodeColor(new PatternNodeColor()); erasePattern.setPatternNodeFontBold(new PatternNodeFontBold()); erasePattern.setPatternNodeFontItalic(new PatternNodeFontItalic()); erasePattern.setPatternNodeFontName(new PatternNodeFontName()); erasePattern.setPatternNodeFontSize(new PatternNodeFontSize()); erasePattern.setPatternNodeStyle(new PatternNodeStyle()); erasePattern.setPatternNodeText(new PatternNodeText()); applyPattern(pNode, erasePattern); List attributeKeyList = pNode.getAttributeKeyList(); for (Iterator iterator = attributeKeyList.iterator(); iterator .hasNext();) { String key = (String) iterator.next(); this.getAttributeController().performRemoveAttribute(key); } setNoteText(pNode, null); } public EditNoteToNodeAction createEditNoteToNodeAction(MindMapNode node, String text) { EditNoteToNodeAction nodeAction = new EditNoteToNodeAction(); nodeAction.setNode(node.getObjectId(this)); if (text != null && (HtmlTools.htmlToPlain(text).length() != 0 || text .indexOf("<img") >= 0)) { nodeAction.setText(text); } else { nodeAction.setText(null); } return nodeAction; } public void setNoteText(MindMapNode node, String text) { String oldNoteText = node.getNoteText(); if (Tools.safeEquals(text, oldNoteText)) { // they are equal. return; } logger.fine("Old Note Text:'" + oldNoteText + ", new:'" + text + "'."); logger.fine(Tools.compareText(oldNoteText, text)); EditNoteToNodeAction doAction = createEditNoteToNodeAction(node, text); EditNoteToNodeAction undoAction = createEditNoteToNodeAction(node, oldNoteText); getActionFactory().doTransaction(ACCESSORIES_PLUGINS_NODE_NOTE, new ActionPair(doAction, undoAction)); } public void registerPlugin(MindMapControllerPlugin pPlugin) { mPlugins.add(pPlugin); } public void deregisterPlugin(MindMapControllerPlugin pPlugin) { mPlugins.remove(pPlugin); } public Set getPlugins() { return Collections.unmodifiableSet(mPlugins); } /** */ public Transferable getClipboardContents() { getClipboard(); return clipboard.getContents(this); } protected void getClipboard() { if (clipboard == null) { Toolkit toolkit = Toolkit.getDefaultToolkit(); selection = toolkit.getSystemSelection(); clipboard = toolkit.getSystemClipboard(); } } /** */ public void setClipboardContents(Transferable t) { getClipboard(); clipboard.setContents(t, null); if (selection != null) { selection.setContents(t, null); } } public void showThisMap() { getController().getMapModuleManager().changeToMapModule(getMapModule()); } public boolean mapSourceChanged(MindMap pMap) throws Exception { // ask the user, if he wants to reload the map. MapSourceChangeDialog runnable = new MapSourceChangeDialog(); Tools.invokeAndWait(runnable); return runnable.getReturnValue(); } public void setNodeHookFactory(HookFactory pNodeHookFactory) { nodeHookFactory = pNodeHookFactory; } /* * (non-Javadoc) * * @see * freemind.modes.mindmapmode.actions.MindMapActions#createModeControllerHook * (java.lang.String) */ public void createModeControllerHook(String pHookName) { HookFactory hookFactory = getHookFactory(); // two different invocation methods:single or selecteds ModeControllerHook hook = hookFactory .createModeControllerHook(pHookName); hook.setController(this); invokeHook(hook); } /** * Delegate method to Controller. Must be called after cut.s */ public void obtainFocusForSelected() { getController().obtainFocusForSelected(); } public boolean doTransaction(String pName, ActionPair pPair) { return actionFactory.doTransaction(pName, pPair); } }