lost.tok.html.Menu.java Source code

Java tutorial

Introduction

Here is the source code for lost.tok.html.Menu.java

Source

/* Tree of Knowledge - An information management Eclipse plugin
 * Copyright (C) 2007 Team Lost
 * 
 * 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., 51 Franklin Street, Fifth Floor, 
 * Boston, MA  02110-1301, USA.
 */

package lost.tok.html;

import java.util.HashMap;

import lost.tok.GeneralFunctions;
import lost.tok.Link;
import lost.tok.Messages;
import lost.tok.ToK;
import lost.tok.sorter.Sorter;

import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;

/**
 * Creates and handles the navigation menu at the side of pages
 * @author Team Lost
 *
 */
public class Menu {

    /** The ToK of the project */
    private ToK tok;
    /** The next available id of the tree */
    private int freeId;
    /** The page we are generating a menu for */
    private HTMLPage menuOwner;
    /** The id of the menuOwner in the tree, if there is one.
     *  Initialized when its node is generated, 0 if not found */
    private int ownerId;

    /** A map from the path of a source file to its HTMLPage */
    private HashMap<String, SourcePage> srcPathToPage;
    /** A map from the name of a discussion file to its HTMLPage */
    private HashMap<String, DiscussionPage> discNameToPage;
    /** The path to the icons directory for the dTree */
    private String imgBase;

    /**
     * Creates a new side menu item
     * @param tok the tok related to this menu
     * @param page the page this menu is generated for
     * @param srcPathToPage A map from the path of the project's sources to their HTMLPage
     * @param discNameToPage A map from the name of the project's discussion's names to thier HTMLPage
     */
    public Menu(ToK tok, HTMLPage page, HashMap<String, SourcePage> srcPathToPage,
            HashMap<String, DiscussionPage> discNameToPage) {
        this.tok = tok;
        this.freeId = 0;
        this.menuOwner = page;
        this.ownerId = 0;
        this.srcPathToPage = srcPathToPage;
        this.discNameToPage = discNameToPage;
        this.imgBase = GeneralFunctions.isLTR() ? ToK.HTML_FOLDER + "/other/menu/img/" //$NON-NLS-1$
                : ToK.HTML_FOLDER + "/other/menu/imgRTL/"; //$NON-NLS-1$
    }

    /** Returns the line importing the menu javascript (should be in the html title) */
    public String getScriptLine() {
        String pathToJS = menuOwner.getPathTo(ToK.HTML_FOLDER + "/other/menu/dtree.js"); //$NON-NLS-1$
        return "<script type=\"text/javascript\" src=\"" + pathToJS + "\"></script>"; //$NON-NLS-1$ //$NON-NLS-2$
    }

    /** Returns the html's div element of the menu */
    public Element getMenuDiv() {
        //Element div = DocumentHelper.createElement("div");
        Element script = DocumentHelper.createElement("script"); //$NON-NLS-1$
        script.addAttribute("type", "text/javascript"); //$NON-NLS-1$ //$NON-NLS-2$

        script.addComment(getDTreeCode());
        return script;
    }

    /** Returns the code for creating the menu tree (dtree js) */
    private String getDTreeCode() {
        StringBuffer sb = new StringBuffer(1000);

        sb.append("\n"); //$NON-NLS-1$
        sb.append("d = new dTree('d');\n"); //$NON-NLS-1$
        sb.append("d.config.folderLinks = true;\n"); //$NON-NLS-1$
        sb.append("d.config.inOrder = true;\n"); //$NON-NLS-1$

        sb.append("d.icon.root = '" + menuOwner.getPathTo(imgBase + "tree1.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        sb.append("d.icon.folder = '" + menuOwner.getPathTo(imgBase + "folder.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        sb.append("d.icon.folderOpen = '" + menuOwner.getPathTo(imgBase + "folderopen.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        sb.append("d.icon.node = '" + menuOwner.getPathTo(imgBase + "page.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        sb.append("d.icon.empty = '" + menuOwner.getPathTo(imgBase + "empty.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        sb.append("d.icon.line = '" + menuOwner.getPathTo(imgBase + "line.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        sb.append("d.icon.join = '" + menuOwner.getPathTo(imgBase + "join.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        sb.append("d.icon.joinBottom = '" + menuOwner.getPathTo(imgBase + "joinbottom.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        sb.append("d.icon.plus = '" + menuOwner.getPathTo(imgBase + "plus.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        sb.append("d.icon.plusBottom = '" + menuOwner.getPathTo(imgBase + "plusbottom.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        sb.append("d.icon.minus = '" + menuOwner.getPathTo(imgBase + "minus.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        sb.append("d.icon.minusBottom = '" + menuOwner.getPathTo(imgBase + "minusbottom.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        sb.append("d.icon.nlPlus = '" + menuOwner.getPathTo(imgBase + "nolines_plus.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        sb.append("d.icon.nlMinus = '" + menuOwner.getPathTo(imgBase + "nolines_minus.gif") + "';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

        sb.append(getAddCode(0, -1, Messages.getString("Menu.ToK"), //$NON-NLS-1$
                menuOwner.getPathTo(ToK.HTML_FOLDER + "/index.html"), Messages.getString("Menu.BackToMain"))); //$NON-NLS-1$ //$NON-NLS-2$
        freeId = 1;

        sb.append(getAddSourcesCode(tok.getRootsFolder(), 0));
        sb.append(getAddSourcesCode(tok.getSourcesFolder(), 0));

        sb.append(getAddDiscsCode(0));

        sb.append("document.write(d);\n"); //$NON-NLS-1$
        sb.append("d.openTo(" + ownerId + ",true);\n"); //$NON-NLS-1$ //$NON-NLS-2$
        sb.append("d.openAll();\n"); //$NON-NLS-1$

        return sb.toString();
    }

    /**
     * Returns the dtree js code for adding the sources into the tree
     * @param srcFolder The folder which we want to add
     * @param parentID the id of the parent element
     * @return js code which adds the element in the source dir to the dtree
     */
    private String getAddSourcesCode(IFolder srcFolder, int parentID) {
        StringBuffer sb = new StringBuffer();
        int myId = freeId;
        freeId++;

        String iconPath = menuOwner.getPathTo(imgBase + "folder.gif"); //$NON-NLS-1$
        String iconOpenPath = menuOwner.getPathTo(imgBase + "folderopen.gif"); //$NON-NLS-1$

        sb.append(getAddCode(myId, parentID, srcFolder.getName(), null, null, null, iconPath, iconOpenPath, null));

        Sorter sorter = new Sorter(srcFolder);
        IResource[] resourses = sorter.getSorted();

        for (IResource res : resourses) {
            if ((res instanceof IFile) && (((IFile) res).getName().equals("order.xml")))
                continue;

            if ((res instanceof IFile) && (((IFile) res).getFileExtension().equals("src")))
                sb.append(getAddSourceCode((IFile) res, myId));

            else if (res instanceof IFolder)
                sb.append(getAddSourcesCode((IFolder) res, myId));

            else
                System.err.println("Unexpected resource: " + res); //$NON-NLS-1$
        }

        return sb.toString();
    }

    /** 
     * Returns the js code for adding a link to source to the dtree
     * @param srcFile the file to add
     * @param parentID the id of its parent (dtree node id)
     * @return the js code for adding a link to source to the dtree
     */
    private String getAddSourceCode(IFile srcFile, int parentID) {
        String srcPath = srcFile.getProjectRelativePath().toString();

        SourcePage sPage = srcPathToPage.get(srcPath);

        // TODO(Shay, medium-low): different icons for roots

        int myId = freeId;
        freeId++;

        if (sPage == menuOwner)
            ownerId = myId;

        // TODO(Shay): JS escape the strings
        String title = sPage.getSourcDoc().getTitle();
        String link = menuOwner.getPathTo(sPage);
        String tooltip = title + Messages.getString("Menu.by") + sPage.getSourcDoc().getAuthor(); //$NON-NLS-1$

        String iconPath = menuOwner.getPathTo(imgBase + (sPage.isSrcRoot() ? "root.png" : "source.png")); //$NON-NLS-1$ //$NON-NLS-2$

        return getAddCode(myId, parentID, title, link, tooltip, null, iconPath, null, null);
    }

    /**
     * Returns the dtree js code for adding the discussions into the tree
     * @param parentID the id of the parent element
     * @return js code which adds the discussions dir to the dtree
     */
    private String getAddDiscsCode(int parentId) {
        StringBuffer sb = new StringBuffer();

        int myId = freeId;
        freeId++;

        String iconPath = menuOwner.getPathTo(imgBase + "folder.gif"); //$NON-NLS-1$
        String iconOpenPath = menuOwner.getPathTo(imgBase + "folderopen.gif"); //$NON-NLS-1$

        sb.append(
                getAddCode(myId, parentId, ToK.DISCUSSION_FOLDER, null, null, null, iconPath, iconOpenPath, null));

        for (String discName : discNameToPage.keySet()) {
            sb.append(getAddDiscussionCode(discName, myId));
        }

        return sb.toString();
    }

    /**
     * Returns the js code for adding the selected discussion to the tree
     * @param discussionName the name of the discussion to add
     * @param parentId the parent of the said discussion
     * @return js code which adds the selected discussion to the menu
     */
    private String getAddDiscussionCode(String discussionName, int parentId) {
        int myId = freeId;
        freeId++;

        DiscussionPage dPage = discNameToPage.get(discussionName);

        if (dPage == menuOwner)
            ownerId = myId;

        String urlLink = menuOwner.getPathTo(dPage);

        Link dLink = dPage.getDiscussion().getLink();
        String tooltip = discussionName + Messages.getString("Menu.by") + dPage.getDiscussion().getCreatorName() //$NON-NLS-1$
                + ", "; //$NON-NLS-1$

        if (dLink != null)
            tooltip += dLink.getDisplayLinkType();
        else
            tooltip += Messages.getString("Menu.unlinked"); //$NON-NLS-1$

        String iconPath = menuOwner.getPathTo(imgBase + "disc.png"); //$NON-NLS-1$

        return getAddCode(myId, parentId, discussionName, urlLink, tooltip, null, iconPath, null, null);
    }

    /**
     * Returns the code for a dtree js add command
     * @param id Unique identity number.
     * @param pid Number refering to the parent node. The value for the root node has to be -1.
     * @param name Text label for the node.
     * @param url Url for the node.
     * @param title   Title for the node.
     */
    private String getAddCode(int id, int pid, String name, String url, String title) {
        return getAddCode(id, pid, name, url, title, null, null, null, null);
    }

    /**
     * Returns the code for a dtree js add command
     * @param id Unique identity number.
     * @param pid Number refering to the parent node. The value for the root node has to be -1.
     * @param name Text label for the node.
     * @param url Url for the node.
     * @param title   Title for the node.
     * @param target Target for the node.
     * @param icon Image file to use as the icon. Uses default if not specified.
     * @param iconOpen Image file to use as the open icon. Uses default if not specified.
     * @param open Is the node open.
     */
    private String getAddCode(int id, int pid, String name, String url, String title, String target, String icon,
            String iconOpen, Boolean open) {
        StringBuffer sb = new StringBuffer(100);

        sb.append("d.add("); //$NON-NLS-1$
        sb.append(id);
        sb.append(',');
        sb.append(pid);
        sb.append(',');
        sb.append(jsEscape(name));
        sb.append(',');
        sb.append(jsEscape(url));
        sb.append(',');
        sb.append(jsEscape(title));
        sb.append(',');
        sb.append(jsEscape(target));
        sb.append(',');
        sb.append(jsEscape(icon));
        sb.append(',');
        sb.append(jsEscape(iconOpen));
        sb.append(',');
        sb.append(open == null ? "''" : open.toString()); //$NON-NLS-1$
        sb.append(");\n"); //$NON-NLS-1$

        return sb.toString();
    }

    /** Escapes a string so it could be embedded in js code */
    private String jsEscape(String str) {
        if (str != null)
            return "'" + str.replaceAll("'", "\\\\'") + "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
        else
            return "''"; //$NON-NLS-1$
    }

}