FreeMind マップ分割機能の改善

昨日の記事にひき引き続き、FreeMindのソースの話です。昨日はソースから動作を確認するだけでしたが、今日はソースの修正に挑戦してみます。

FreeMindのマップ分割の記事で、エクスポート機能で枝から先を別マップに切り出せることがわかりましたが、切り出すマップのファイル名を自分で指定しなければいけないところがやや不満でした。そこで、この点を改善することに挑戦しました。

昨日と同じく、「Export Branch」などのワードの全文検索で関連のありそうな箇所を探します。その結果、freemind.modes.mindmapmode.actions.ExportBranchActionというクラスで該当処理を行っているようです。

以下がその処理の中核のメソッドとなります。

public void actionPerformed(ActionEvent e) {
    MindMapNodeModel node = (MindMapNodeModel) mMindMapController
            .getSelected();

    // if something is wrong, abort.
    if (mMindMapController.getMap() == null || node == null
            || node.isRoot()) {
        mMindMapController.getFrame().err("Could not export branch.");
        return;
    }
    // If the current map is not saved yet, save it first.
    if (mMindMapController.getMap().getFile() == null) {
        mMindMapController.getFrame().out(
                "You must save the current map first!");
        mMindMapController.save();
    }

    // Open FileChooser to choose in which file the exported
    // branch should be stored
    JFileChooser chooser;
    if (mMindMapController.getMap().getFile().getParentFile() != null) {
        chooser = new JFileChooser(mMindMapController.getMap().getFile()
                .getParentFile());
    } else {
        chooser = new JFileChooser();
    }
    // chooser.setLocale(currentLocale);
    if (mMindMapController.getFileFilter() != null) {
        chooser.addChoosableFileFilter(mMindMapController.getFileFilter());
    }
    // Set node text to chooser's selected file name
    chooser.setSelectedFile(new File(node.getText().trim()));
    
    int returnVal = chooser.showSaveDialog(mMindMapController.getSelectedView());
    if (returnVal == JFileChooser.APPROVE_OPTION) {
        File chosenFile = chooser.getSelectedFile();
        URL link;
        // Force the extension to be .mm
        String ext = Tools.getExtension(chosenFile.getName());
        if (!ext
                .equals(freemind.main.FreeMindCommon.FREEMIND_FILE_EXTENSION_WITHOUT_DOT)) {
            chosenFile = new File(chosenFile.getParent(), chosenFile
                    .getName()
                    + freemind.main.FreeMindCommon.FREEMIND_FILE_EXTENSION);
        }
        try {
            link = Tools.fileToUrl(chosenFile);
        } catch (MalformedURLException ex) {
            JOptionPane.showMessageDialog(mMindMapController.getView(),
                    "couldn't create valid URL!");
            return;
        }
        // Confirm overwrite if file exists.
        if (chosenFile.exists()) { // If file exists, ask before
                                    // overwriting.
            int overwriteMap = JOptionPane.showConfirmDialog(
                    mMindMapController.getView(), mMindMapController
                            .getText("map_already_exists"), "FreeMind",
                    JOptionPane.YES_NO_OPTION);
            if (overwriteMap != JOptionPane.YES_OPTION) {
                return;
            }
        }

        /*
         * Now make a copy from the node, remove the node from the map and
         * create a new Map with the node as root, store the new Map, add
         * the copy of the node to the parent, and set a link from the copy
         * to the new Map.
         */
        MindMapNodeModel parent = (MindMapNodeModel) node.getParentNode();
        try {
            // set a link from the new root to the old map
            String linkToNewMapString = Tools.toRelativeURL(Tools.fileToUrl(chosenFile), 
                    mMindMapController.getModel().getURL());
            mMindMapController.setLink(node, linkToNewMapString);
        } catch (MalformedURLException ex) {
            Resources.getInstance().logException(ex);
        }
        int nodePosition = parent.getChildPosition(node);
        mMindMapController.deleteNode(node);
        // save node:
        node.setParent(null);
        // unfold node
        node.setFolded(false);
        // construct new controller:
        ModeController newModeController = mMindMapController.getMode()
                .createModeController();
        MindMapMapModel map = new MindMapMapModel(node, mMindMapController
                .getFrame(), newModeController);
        map.save(chosenFile);
        // new node instead:
        MindMapNode newNode = mMindMapController.addNewNode(parent,
                nodePosition, node.isLeft());
        //TODO: Keep formatting of node.
        mMindMapController.setNodeText(newNode, node.getText());

        try {
            String linkString = Tools.toRelativeURL(mMindMapController
                    .getModel().getURL(), Tools.fileToUrl(chosenFile));
            mMindMapController.setLink(newNode, linkString);
        } catch (MalformedURLException ex) {
            Resources.getInstance().logException(ex);
        }
        mMindMapController.newMap(map);
        // old map should not be save automatically!!
    }
}

オリジナルのソースに対して、コード中ほどの「Set node text to chooser's selected file name」とコメントしている部分に1行処理を追加しています。ここでセーブダイアログを表示するオブジェクトChooserに、ノードのテキストをファイル名とするファイルオブジェクトを設定しています(文字列のファイル名としてのチェックなどはもう少ししたほうがいいのかもしれませんが)。

この修正を加えてビルドしたfreemind.jarを使用してFreeMindを起動することで、実際にセーブダイアログのファイル名のデフォルト値としてノードテキストが設定されることが確認できました。