org.primordion.xholon.io.XholonGuiClassic.java Source code

Java tutorial

Introduction

Here is the source code for org.primordion.xholon.io.XholonGuiClassic.java

Source

/* Xholon Runtime Framework - executes event-driven & dynamic applications
 * Copyright (C) 2013 Ken Webb
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 */

package org.primordion.xholon.io;

//import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
//import com.google.gwt.dom.client.TextAreaElement;

import com.google.gwt.user.client.Command;
//import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;

import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DockPanel;
//import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HorizontalPanel;
//import com.google.gwt.user.client.ui.HTML;
//import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.Image;
//import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MenuBar;
//import com.google.gwt.user.client.ui.MenuItem;
//import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
//import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
//import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

//import com.google.gwt.event.dom.client.BlurHandler;
//import com.google.gwt.event.dom.client.BlurEvent;

//import com.google.gwt.event.dom.client.ChangeHandler;
//import com.google.gwt.event.dom.client.ChangeEvent;

import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.ClickEvent;

//import com.google.gwt.event.dom.client.DoubleClickHandler;
//import com.google.gwt.event.dom.client.DoubleClickEvent;

//import com.google.gwt.event.dom.client.ContextMenuHandler;
//import com.google.gwt.event.dom.client.ContextMenuEvent;

import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;

import com.google.gwt.resources.client.ImageResource;

import org.client.GwtEnvironment;
import org.client.JavaApp2Workbook;
import org.client.RCImages;
//import org.primordion.xholon.app.Application;
import org.primordion.xholon.app.ApplicationNull;
import org.primordion.xholon.app.IApplication;
import org.primordion.xholon.base.IDecoration;
//import org.primordion.xholon.base.IMessage;
//import org.primordion.xholon.base.IReflection;
//import org.primordion.xholon.base.ISignal;
import org.primordion.xholon.base.IXholon;
import org.primordion.xholon.base.IXholonClass;
//import org.primordion.xholon.base.ReflectionFactory;
//import org.primordion.xholon.base.XholonClass;
import org.primordion.xholon.common.mechanism.CeControl;
//import org.primordion.xholon.common.mechanism.CeStateMachineEntity;
//import org.primordion.xholon.exception.XholonConfigurationException;
//import org.primordion.xholon.io.IViewer;
//import org.primordion.xholon.service.IXholonService;
//import org.primordion.xholon.service.NodeSelectionService;
//import org.primordion.xholon.util.ClassHelper;

/**
 * Optional GUI for a Xholon GWT-based application.
 * Uses the Java GWT class Tree.
 * @author <a href="mailto:ken@primordion.com">Ken Webb</a>
 * @see <a href="http://www.primordion.com/Xholon">Xholon Project website</a>
 * @since 0.9.0 (Created on July 22, 2013)
 */
public class XholonGuiClassic extends AbstractXholonGui { //DockPanel {
    private static final long serialVersionUID = 1L;
    private TreeItem tiRoot;
    private XholonGuiClassicTree tree;
    private TextBox currentSelectionField;

    protected String modelDirectory = "./config/"; // default model directory

    // icons for Controller nodes
    private static final Image ICON_START = rcImages("Control_control_play_blue");
    private static final Image ICON_PAUSE = rcImages("Control_control_pause_blue");
    private static final Image ICON_STEP = rcImages("Control_control_fastforward_blue");
    private static final Image ICON_STOP = rcImages("Control_control_stop_blue");
    private static final Image ICON_REFRESH = rcImages("Control_control_repeat_blue");

    /**
     * A service that will keep track of which IXholon node(s) are currently selected.
     * This will allow other services or xholons to act on those nodes.*/
    //protected IXholon nodeSelectionService = null;

    /**
     * A service that provides additional methods for IXholon instances.
     */
    //protected IXholon xholonHelperService = null;

    /**
     * Constructor.
     */
    public XholonGuiClassic() {
    }

    public Object getGuiRoot() {
        return tiRoot;
    }

    protected static Image rcImages(String resourceName) {
        return new Image((ImageResource) RCImages.INSTANCE.getResource(resourceName));
    }

    /**
      * Show the entire IXholon tree as a Tree.
      * @param node Node from which to start showing the tree.
      */
    public void showTree(IXholon node) {
        if (tiRoot != null) { // an existing model is already running
            //removeAll();
        }
        if (app == null) {
            app = node.getApp();
        }
        xhRoot = node;
        tiRoot = new TreeItem();
        createNode(xhRoot, tiRoot, null);
        tree = new XholonGuiClassicTree(this);
        tree.addItem(tiRoot);

        tree.addSelectionHandler(new SelectionHandler<TreeItem>() {
            public void onSelection(SelectionEvent<TreeItem> event) {
                TreeItem ti = event.getSelectedItem();
                handleNodeSelection(ti.getText(), ti, tree.isCtrlPressed());
            }
        });

        ScrollPanel scrollPanel = new ScrollPanel(tree);
        scrollPanel.setSize("500px", "500px");

        DockPanel panel = new DockPanel(); //this;
        panel.setStylePrimaryName("xhgui");

        panel.add(scrollPanel, DockPanel.CENTER);
        currentSelectionField = new TextBox();
        currentSelectionField.setVisibleLength(60); // 58
        currentSelectionField.setMaxLength(200);
        currentSelectionField.setText("Click on any node to show details");
        panel.add(currentSelectionField, DockPanel.SOUTH);

        // main menu at top of GUI
        MenuBar mainMenu = new MenuBar();
        mainMenu.setStylePrimaryName("mainMenu");

        // File
        MenuBar fileMenu = new MenuBar(true);
        MenuBar localStorageMenu = new MenuBar(true);
        boolean enableFileItems = true;
        //consoleLog(enableFileItems);
        //consoleLog(Window.Location.getParameter("src"));
        if ("gist".equals(Window.Location.getParameter("src"))) {
            //consoleLog("setting to false");
            enableFileItems = false;
        }
        //consoleLog(enableFileItems);
        localStorageMenu.addItem("Save", new Command() {
            @Override
            public void execute() {
                IApplication lsApp = new ApplicationNull();
                String configFileName = app.getConfigFileName();
                lsApp.setConfigFileName(configFileName);
                JavaApp2Workbook app2Wb = new JavaApp2Workbook();
                app2Wb.setWinName("_blank"); // open in new tab or window
                app2Wb.save(configFileName, lsApp);
            }
        }).setEnabled(enableFileItems);
        // save to localStorage using a new name
        /*localStorageMenu.addItem("Save as", new Command() {
          @Override
          public void execute() {
                
          }
        }).setEnabled(enableFileItems);*/
        localStorageMenu.addItem("Edit", new Command() {
            @Override
            public void execute() {
                IApplication lsApp = new ApplicationNull();
                String configFileName = app.getConfigFileName();
                lsApp.setConfigFileName(configFileName);
                JavaApp2Workbook app2Wb = new JavaApp2Workbook();
                app2Wb.setWinName("_blank"); // open in new tab or window
                app2Wb.edit(configFileName, lsApp);
            }
        }).setEnabled(enableFileItems);
        localStorageMenu.addItem("Restart from", new Command() {
            @Override
            public void execute() {
                // restart the current app by reloading the HTML page (equivalent to browser F5)
                // the reloaded app will automatically include the edited changes in localStorage
                Window.Location.reload();
            }
        }).setEnabled(enableFileItems);
        // remove from localStorage
        /*localStorageMenu.addItem("Remove from", new Command() {
          @Override
          public void execute() {
                
          }
        }).setEnabled(enableFileItems);*/
        fileMenu.addItem("localStorage", localStorageMenu);
        mainMenu.addItem("File", fileMenu);

        // Application
        mainMenu.addItem("Application", new Command() {
            @Override
            public void execute() {
                if (app == null) {
                    //app.println("Application not yet loaded.");
                } else {
                    app.about();
                }
            }
        });

        // Help
        MenuBar helpMenu = new MenuBar(true);
        helpMenu.addItem("About", new Command() {
            @Override
            public void execute() {
                if (app == null) {
                    //app.println("Application not yet loaded.");
                } else {
                    app.about();
                }
            }
        });
        helpMenu.addItem("Getting Started", new Command() {
            @Override
            public void execute() {
                gettingStarted("Getting Started with Xholon", splashText, 375, 475);
            }
        });
        helpMenu.addItem("Information", new Command() {
            @Override
            public void execute() {
                if (app == null) {
                    //app.println("Application not yet loaded.");
                } else {
                    app.information();
                }
            }
        });
        helpMenu.addItem("JavaScript API", new Command() {
            @Override
            public void execute() {
                Window.open(GwtEnvironment.gwtHostPageBaseURL + "jsapidoc/modules/XholonJsApi.html", "_blank", "");
            }
        });
        mainMenu.addItem("Help", helpMenu);
        HorizontalPanel mainMenuHp = new HorizontalPanel();
        mainMenuHp.setStylePrimaryName("mainMenu");
        mainMenuHp.add(mainMenu);

        // toolbar with Controller buttons just below main menu
        HorizontalPanel toolbar = new HorizontalPanel();
        toolbar.setStylePrimaryName("toolbar");
        IXholon controlNode = app.getControlRoot().getFirstChild();
        while (controlNode != null) {
            toolbar.add(makeToolbarWidget(controlNode));
            controlNode = controlNode.getNextSibling();
        }

        VerticalPanel topVp = new VerticalPanel();
        topVp.setStylePrimaryName("mainMenu");
        topVp.setWidth("500px"); // 474
        topVp.add(mainMenuHp);
        topVp.add(toolbar);
        panel.add(topVp, DockPanel.NORTH);

        RootPanel xhgui = RootPanel.get("xhgui");
        if (xhgui == null) {
            node.consoleLog("WARNING xhgui element does not exist");
        } else {
            xhgui.add(panel);
        }

        //((Application)app).clearConsole();
        // clear the contents of the xhconsole
        /*Element element = Document.get().getElementById("xhconsole").getFirstChildElement();
        if (element != null) {
            TextAreaElement textfield = element.cast();
            textfield.setValue("");
        }*/
    }

    @Override
    protected void setText(String text) {
        currentSelectionField.setText(text);
    }

    /**
      * Configure one IXholon node, and recursively create all left children and right siblings.
      * @param xhNode Current IXholon node.
      * @param tiNode Current TreeItem.
      * @param parent Parent of current TreeItem.
      */
    protected void createNode(IXholon xhNode, TreeItem tiNode, TreeItem parent) {
        tiNode.setWidget(makeTreeItemWidget(xhNode));
        TreeItem node;
        IXholon leftChild = xhNode.getFirstChild();
        IXholon rightSibling = xhNode.getNextSibling();
        if (leftChild != null) {
            node = new TreeItem();
            tiNode.addItem(node);
            createNode(leftChild, node, tiNode);
        }
        if (rightSibling != null) {
            node = new TreeItem();
            parent.addItem(node);
            createNode(rightSibling, node, parent);
        }
    }

    /**
    * Create one TreeItem node, and recursively create all children.
    * @param xhNode Current IXholon node.
    * @param tiNode Current TreeItem.
    */
    protected void createNodeChildren(IXholon xhNode, TreeItem tiNode) {
        tiNode.setWidget(makeTreeItemWidget(xhNode));
        TreeItem node;
        IXholon leftChild = xhNode.getFirstChild();
        if (leftChild != null) {
            node = new TreeItem();
            tiNode.addItem(node);
            createNode(leftChild, node, tiNode);
        }
    }

    /**
     * Make a toolbar widget.
     */
    protected Widget makeToolbarWidget(IXholon node) {
        final String nodeName = node.getName();
        IXholonClass xhcNode = node.getXhc();
        Image icon = null;
        if (xhcNode.getId() == CeControl.ControlCE) {
            if ("Start".equals(node.getRoleName())) {
                icon = rcImages("Control_control_play_blue");
            } else if ("Pause".equals(node.getRoleName())) {
                icon = rcImages("Control_control_pause_blue");
            } else if ("Step".equals(node.getRoleName())) {
                icon = rcImages("Control_control_fastforward_blue");
            } else if ("Stop".equals(node.getRoleName())) {
                icon = rcImages("Control_control_stop_blue");
            } else if ("Refresh".equals(node.getRoleName())) {
                icon = rcImages("Control_control_repeat_blue");
            }
        }
        if (icon == null) {
            icon = rcImages("Control_bullet_blue");
        }

        HorizontalPanel hp = new HorizontalPanel();
        hp.add(icon);
        final IXholon nnode = node;
        Button button = new Button(nodeName, new ClickHandler() {
            public void onClick(ClickEvent event) {
                //String actionCommand = null; //event.getActionCommand();
                if ("Refresh".equals(nodeName)) {
                    refresh();
                } else {
                    //IXholon node = xpath.evaluate("descendant-or-self::*[@name='" + actionCommand + "']", xhRoot);
                    nnode.handleNodeSelection();
                }
            }
        });
        button.setStylePrimaryName("controlButton");
        hp.add(button);
        return hp;
    }

    /**
     * Make a TreeItem widget.
     */
    protected Widget makeTreeItemWidget(IXholon node) {
        // must create a new Image for each new panel; can't reuse ICON_ constants
        String nodeName = node.getName();
        IXholonClass xhcNode = node.getXhc();
        String color = null;
        String font = null;
        Image icon = null;
        String toolTip = null;
        if (xhcNode == null) {
            if ("Application".equals(nodeName)) {
                icon = rcImages("Control_application_side_tree");
            } else if (isInInheritanceHierarchy(node)) {
                xhcNode = xhRoot.getClassNode(nodeName);
                //System.out.println("makeTreeItemWidget( isInInheritanceHierarchy1 for " + nodeName + " " + xhcNode);
                if (xhcNode == null) {
                } else {
                    color = getColor((IDecoration) xhcNode);
                    if (color == null) {
                        color = getColor((IDecoration) xhcNode.getMechanism());
                    }
                    font = getFont((IDecoration) xhcNode);
                    if (font == null) {
                        font = getFont((IDecoration) xhcNode.getMechanism());
                    }
                    icon = getImageIcon((IDecoration) xhcNode);
                    if (icon == null) {
                        icon = getImageIcon((IDecoration) xhcNode.getMechanism());
                    }
                    toolTip = getToolTip((IDecoration) xhcNode);
                    if (toolTip == null) {
                        toolTip = getToolTip((IDecoration) xhcNode.getMechanism());
                    }
                }
            } else {
                System.out.println("makeTreeItemWidget( xhcNode = null for " + nodeName);
            }
        } else if (xhcNode.getId() == CeControl.ControlCE) {
            if ("Controller".equals(node.getRoleName())) {
                icon = rcImages("Control_controller");
            } else if ("View".equals(node.getRoleName())) {
                icon = rcImages("Control_rainbow");
            } else if ("Model".equals(node.getRoleName())) {
                icon = rcImages("Control_bricks");
            } else if ("Start".equals(node.getRoleName())) {
                icon = ICON_START;
            } else if ("Pause".equals(node.getRoleName())) {
                icon = ICON_PAUSE;
            } else if ("Step".equals(node.getRoleName())) {
                icon = ICON_STEP;
            } else if ("Stop".equals(node.getRoleName())) {
                icon = ICON_STOP;
            } else if ("Refresh".equals(node.getRoleName())) {
                icon = ICON_REFRESH;
            } else {
                icon = rcImages("Control_layout_content");
            }
        } else if (isInMechanismHierarchy(node)) {
            IXholon mechNode = app.getMechRoot();
            mechNode = xpath.evaluate("descendant-or-self::*[@name='" + nodeName + "']", mechNode);
            if (mechNode == null) {
            } else {
                color = getColor((IDecoration) mechNode);
                font = getFont((IDecoration) mechNode);
                icon = getImageIcon((IDecoration) node);
                toolTip = getToolTip((IDecoration) mechNode);
            }
        }

        if (icon == null) {
            //icon = new Image("images/Control/bullet_blue.png");
            color = getColor((IDecoration) xhcNode);
            if (color == null) {
                color = getColor((IDecoration) xhcNode.getMechanism());
            }
            font = getFont((IDecoration) xhcNode);
            if (font == null) {
                font = getFont((IDecoration) xhcNode.getMechanism());
            }
            icon = getImageIcon((IDecoration) xhcNode);
            if (icon == null) {
                icon = getImageIcon((IDecoration) xhcNode.getMechanism());
            }
            toolTip = getToolTip((IDecoration) xhcNode);
            if (toolTip == null) {
                toolTip = getToolTip((IDecoration) xhcNode.getMechanism());
            }
        }

        HorizontalPanel hp = new HorizontalPanel();
        hp.add(icon);
        Label label = new Label(nodeName);
        if ((color != null) || (font != null)) {
            // TODO set the label's color
            setStyle(label.getElement(), color, font);
        }
        hp.add(label);
        if (toolTip != null) {
            hp.setTitle(toolTip);
        }
        return hp;
    }

    protected native void setStyle(Element element, String color, String font) /*-{
                                                                               if (color) {element.style.color = color;}
                                                                               if (font) {element.style.font = font;}
                                                                               }-*/;

    /**
     * Get the icon of a node.
     * ex iconFileName: "images/StateMachineEntity/stateMachine.png"
     * ex rcImages    : "StateMachineEntity_stateMachine"
     * @param node An instance of IXholonClass or IMechanism or other type that implements IDecoration.
     * @return A GWT image specific to that xhcNode, or the default GWT image.
     */
    protected Image getImageIcon(IDecoration node) {
        Image icon = null;
        String iconFileName = ((IDecoration) node).getIcon();
        if (iconFileName != null) {
            if (iconFileName.startsWith("images/")) {
                icon = rcImages(iconFileName.substring(7, iconFileName.length() - 4).replace("/", "_"));
            }
        } else {
            if (node instanceof IXholonClass) {
                IXholon p = ((IXholonClass) node).getParentNode();
                if ((p != null) && (p instanceof IXholonClass)) {
                    // try to get an icon from the parent class
                    return getImageIcon((IDecoration) p);
                }
            }
        }
        if (icon == null) {
            icon = rcImages("Control_bullet_blue");
        }
        return icon;
    }

    /**
     * Get the toolTip of a node.
     * @param node
     * @return
     */
    protected String getToolTip(IDecoration node) {
        String toolTip = null;
        String toolTipStr = ((IDecoration) node).getToolTip();
        if (toolTipStr != null) {
            toolTip = toolTipStr;
        } else {
            if (node instanceof IXholonClass) {
                IXholon p = ((IXholonClass) node).getParentNode();
                if ((p != null) && (p instanceof IXholonClass)) {
                    // try to get a color from the parent class
                    return getToolTip((IDecoration) p);
                }
            }
        }
        return toolTip;
    }

    /**
     * Get the color of a node.
     * @param node
     * @return A color String (ex: "#2E8B57" "red").
     */
    protected String getColor(IDecoration node) {
        String color = ((IDecoration) node).getColor();
        if (color == null) {
            if (node instanceof IXholonClass) {
                IXholon p = ((IXholonClass) node).getParentNode();
                if ((p != null) && (p instanceof IXholonClass)) {
                    // try to get a color from the parent class
                    return getColor((IDecoration) p);
                }
            }
        }
        if (color != null) {
            if (color.startsWith("0x")) {
                color = "#" + color.substring(2);
            }
        }
        return color;
    }

    /**
     * Get the font of a node.
     * @param node
     * @return A font String (ex: "").
     */
    protected String getFont(IDecoration node) {
        String font = ((IDecoration) node).getFont();
        if (font == null) {
            if (node instanceof IXholonClass) {
                IXholon p = ((IXholonClass) node).getParentNode();
                if ((p != null) && (p instanceof IXholonClass)) {
                    // try to get a color from the parent class
                    return getFont((IDecoration) p);
                }
            }
        }
        if (font != null) {
            // the font is stored in <Font> tags in Java Font format (ex: "Arial-BOLD-18")
            // convert to CSS format (ex: "bold 18px arial,sans-serif")
            String[] fontFields = font.trim().toLowerCase().split("-");
            if (fontFields.length == 3) {
                font = fontFields[1] + " " + fontFields[2] + "px " + fontFields[0] + ",sans-serif";
            }
        }
        return font;
    }

    /**
     * Refresh the entire tree being displayed in the viewer.
     */
    public void refresh() {
        //System.out.println("refreshing the tree ...");
        setText("refreshing the tree ...");
        // create a new tree, starting from the same root as before
        tiRoot.removeItems(); // remove all children
        createNode(xhRoot, tiRoot, null);
        setText("tree refreshed");
    }

    /**
     * Refresh the current node, including its entire sub-tree.
     * @param ti The current Tree item.
     * @param node The current IXholon node.
     */
    public void refresh(Object guiItem, IXholon xhNode) {
        TreeItem ti = (TreeItem) guiItem;
        if (ti == null) {
            return;
        }
        if (xhNode == null) {
            return;
        }
        ti.removeItems();
        createNodeChildren(xhNode, ti);
    }

    protected String getGuiItemName(final Object guiItem) {
        final TreeItem ti = (TreeItem) guiItem;
        return (String) ti.getText();
    }

    protected Object getGuiItem(String nodeName) {
        // search recursively from tiRoot
        return getGuiItemRecurse(nodeName, tiRoot);
    }

    protected TreeItem getGuiItemRecurse(String nodeName, TreeItem ti) {
        if (nodeName.equals(ti.getText())) {
            return ti;
        }
        for (int i = 0; i < ti.getChildCount(); i++) {
            TreeItem tiChild = getGuiItemRecurse(nodeName, ti.getChild(i));
            if (tiChild != null) {
                return tiChild;
            }
        }
        return null;
    }

    protected boolean isInInheritanceHierarchy(Object guiItem) {
        TreeItem treeItem = (TreeItem) guiItem;
        while (treeItem != null) {
            if (treeItem.getText().equals("InheritanceHierarchy")) {
                return true;
            }
            treeItem = treeItem.getParentItem();
        }
        return false;
    }

    protected boolean isInMechanismHierarchy(Object guiItem) {
        TreeItem treeItem = (TreeItem) guiItem;
        while (treeItem != null) {
            if (treeItem.getText().equals("MechanismHierarchy")) {
                return true;
            }
            treeItem = treeItem.getParentItem();
        }
        return false;
    }

    public String getModelDirectory() {
        return modelDirectory;
    }

    public void setModelDirectory(String modelDirectory) {
        this.modelDirectory = modelDirectory;
    }

}