SwingMLRenderer.java :  » XML-UI » SwingML » org » swingml » Java Open Source

Java Open Source » XML UI » SwingML 
SwingML » org » swingml » SwingMLRenderer.java
/*
 * SwingML Copyright (C) 2002 SwingML Team 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 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. Authors: Ezequiel Cuellar
 * <ecuellar@crosslogic.com> Robert Morris <robertj@morris.net> Alessandro
 * Dibella <alessandro.dibella@fuurou.org>
 */
package org.swingml;

import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.*;
import java.net.*;
import java.util.*;
import java.util.List;

import javax.swing.*;

import org.swingml.action.*;
import org.swingml.component.*;
import org.swingml.errors.*;
import org.swingml.errors.handlers.*;
import org.swingml.event.*;
import org.swingml.registry.*;
import org.swingml.server.*;
import org.swingml.system.*;
import org.swingml.view.*;
import org.swingml.xml.*;
import org.w3c.dom.*;


/**
 * This class represents the heart of the SwingML system. Use this class as
 * either an application or applet. The two most significant methods are the
 * submit() and render() methods.
 * 
 * @author <a href="mailto:ecuellar@crosslogic.com">Ezequiel Cuellar</a>
 * @author <a href="mailto:robertj@morris.net">Robert J. Morris</a>
 */
public class SwingMLRenderer extends JApplet {

    private static boolean isRendering = false;
    protected static SwingMLRenderer renderer = null;
    private static List renderingListeners = new ArrayList();
    private static SwingMLDesktop theFrame = null;
    private static String windowIconURL;

    public static void addRenderingListener (IRenderListener aListener) {
        if (!getRenderingListeners().contains(aListener)) {
            getRenderingListeners().add(aListener);
        }
    }

    static void endRendering (Node xmlNode) {
        setRendering(false);
        notifyRenderingEnd(xmlNode);
    }

    public static SwingMLDesktop getDesktop () {
        return theFrame;
    }

    public static SwingMLRenderer getRenderer () {
        if (renderer == null) {
            renderer = new SwingMLRenderer();
        }
        return renderer;
    }

    public static List getRenderingListeners () {
        return renderingListeners;
    }

    public static String getWindowIconURL () {
        return windowIconURL;
    }

    public static boolean isRendering () {
        return isRendering;
    }

    /**
     * When this class is used as the entry point for an application. This
     * method expects that the 0th element in the args[] parameter contains the
     * URL of the SwingML document to render.
     */
    public static void main (String args[]) throws SwingMLInitializationError {
        if (args.length != 0) {
            theFrame = new SwingMLDesktop();
        
            theFrame.addWindowListener(new WindowAdapter() {

                public void windowClosing (WindowEvent e) {
                    System.exit(0);
                    ExternalEventManager.flush();
                }
            });
            try {
                theFrame.setSize(Integer.parseInt(args[1]), Integer.parseInt(args[2]));
            } catch (Exception e) {
                theFrame.setSize(550, 500);
            }
            Dimension theScreenSize = Toolkit.getDefaultToolkit().getScreenSize();
            Dimension theFrameSize = theFrame.getSize();
            int theHorizontalPosition = (int) (theScreenSize.getWidth() - theFrameSize.getWidth()) / 2;
            int theVerticalPosition = (int) (theScreenSize.getHeight() - theFrameSize.getHeight()) / 2;
            theFrame.setLocation(theHorizontalPosition, theVerticalPosition);
            // set code base if supplied
            if (args.length > 3) {
                try {
                    HttpSubmitController.setCodeBase(new URL(args[3]));
                } catch (MalformedURLException x) {
                    SwingMLLogger.getInstance().log("Error setting code base: " + args[3]);
                }
            }
            if (args.length > 4) {
                theFrame.setTitle(args[4]);
            }

            HttpSubmitController.processDocumentBase(args[0]);
            if (HttpSubmitController.getServerURL() != null) {
                theFrame.getContentPane().add(getRenderer());
                SwingMLServerResponse response = HttpSubmitController.getSpec(args[0], getRenderer().getContentPane());
                if (response != null) {
                    getRenderer().render(response.getSwingMLSpec(), getRenderer().getContentPane(), true);
                    getRenderer().updateContentPane();
                    if (!response.hasErrors()) {
                        if (args.length > 5) {
                            if (args[5].toUpperCase().startsWith("MAX")) {
                                theFrame.setExtendedState(Frame.MAXIMIZED_BOTH);
                            }
                        }

                        if (args.length > 6) {
                            setWindowIconURL(args[6]);
                            theFrame.setIconImage(IconFactory.getIconImage(getWindowIconURL()));
                        }

                        theFrame.setPropsDirectoryName(SwingMLLogger.getLogDirectory());
                        if (theFrame.hasSettings()) {
                            theFrame.applySettings();
                        }

                    
                        theFrame.setVisible(true);
                    } else {
                        // iterate errors, building up a message and throw an Initialization error.
                        String message = "There was an error initializing the application.";
                        ISwingMLError errors[] = response.getErrors();
                        if (errors != null) {
                            for (int x = 0; x < errors.length; x++) {
                                ISwingMLError error = errors[x];
                                message += "\n" + error.getText();
                            }
                        }
                        throw new SwingMLInitializationError(message);
                    }
                } else {
                    throw new SwingMLInitializationError("Unable to connect to the server");
                }
            }
        } else {
            SwingMLLogger.getInstance().log("Specification URL missing.");
        }
    }

    private static void notifyRenderingEnd (Node xmlNode) {
        List listeners = new ArrayList(getRenderingListeners());
        Iterator schmiterator = listeners.iterator();
        while (schmiterator.hasNext()) {
            // Only notify listeners listening for components inside this
            // container, or those listening for all components.
            boolean shouldBeNotified = true;
            IRenderListener listener = (IRenderListener) schmiterator.next();
            if (listener.getComponentName() != null) {
                shouldBeNotified = SwingMLComponentUtilities.nodeContains(xmlNode, listener.getComponentName());
            }

            if (shouldBeNotified) {
                listener.renderingEnded();
            }
        }
    }

    private static void notifyRenderingStart (Node xmlNode) {
        List listeners = new ArrayList(getRenderingListeners());
        Iterator schmiterator = listeners.iterator();
        while (schmiterator.hasNext()) {
            // Only notify listeners listening for components inside this
            // container, or those listening for all components.
            boolean shouldBeNotified = true;
            IRenderListener listener = (IRenderListener) schmiterator.next();
            if (listener.getComponentName() != null) {
                shouldBeNotified = SwingMLComponentUtilities.nodeContains(xmlNode, listener.getComponentName());
            }

            if (shouldBeNotified) {
                listener.renderingStarted();
            }

        }
    }

    public static void removeRenderingListener (Object aListener) {
        if (getRenderingListeners().contains(aListener)) {
            getRenderingListeners().remove(aListener);
        }
    }

    protected static void setRenderer (SwingMLRenderer aRenderer) {
        renderer = aRenderer;
    }

    private static void setRendering (boolean rendering) {
        SwingMLRenderer.isRendering = rendering;
    }

    public static void setWindowIconURL (String windowIconURL) {
        SwingMLRenderer.windowIconURL = windowIconURL;
    }

    private static void startRendering (Node rootNode) {
        setRendering(true);
        notifyRenderingStart(rootNode);
    }

    public SwingMLRenderer () { 
    
    }

    public void destroy () {
        ExternalEventManager.flush(this);
    }

    /**
     * Executes the given action.
     * 
     * @param response
     * @param action
     * @param aContainer
     */
    public void executeRemoteAction (SwingMLServerResponse response, RemoteAction action, Container aContainer) {
        if (response != null && response.getSwingMLSpec() != null && response.getSwingMLSpec().length() > 0) {
            try {
                ExternalEventManager.flush(this);
                MapperUtil theMapperUtil = new MapperUtil();
                Node theNode = theMapperUtil.parse(response.getSwingMLSpec());
                action.parseResponse(theNode);
            } catch (Exception e) {
                // Execution of remote action failed.
                // TODO - Should we render a dialog here? Probably so.
                SwingMLLogger.getInstance().log(SwingMLLogger.ERROR, e.getMessage());
                e.printStackTrace();
            }
        }
    }

    public URL getCodeBase () {
        return HttpSubmitController.getCodeBase();
    }

    public URL getDocumentBase () {
        URL result = null;
        try {
            result = new URL(HttpSubmitController.getServerURL());
        } catch (MalformedURLException e) {
            SwingMLLogger.getInstance().log(SwingMLLogger.ERROR, e);
        }
        return result;
    }

    /**
     * Parse the given xml and return the root node.
     * 
     * @param xml
     * @return Node - the root node
     */
    public Node getDocumentNode (String xml) {
        Node result = null;

        try {
            MapperUtil theMapperUtil = new MapperUtil();
            result = theMapperUtil.parse(xml);
        } catch (Exception e) {
            result = null;
            SwingMLLogger.getInstance().log(e);
        }

        return result;
    }

    /**
     * Called when a SwingMLRenderer instance is displayed or run as an applet.
     */
    public void init () {
        HttpSubmitController.setCodeBase(super.getCodeBase());
        String theSpecLocation = getParameter("SPEC");

        HttpSubmitController.processDocumentBase(theSpecLocation);
        if (this.getDocumentBase() != null) {
            SwingMLServerResponse response = HttpSubmitController.getSpec(theSpecLocation, this.getContentPane());
            if (response != null) {
                render(response.getSwingMLSpec(), getContentPane());
                if (response.hasErrors()) {
                    render(ErrorHandlerUtilities.getDialogFor(response.getErrors()), getContentPane());
                }
            } else {
                render(HttpSubmitController.getConnectionErrorSpec(), getContentPane());
            }
        }
    }

    public void processAndRender (String xml, Container containerToReplace, boolean repaint) {
        processAndRender(xml, containerToReplace, repaint, false);
    }

    /**
     * **NOTE** - Render the new components and then remove their old counterparts afterwards.  
     * This reduces the flashing on screen caused by first removing components and then re-rendering them.
     * @param xml
     * @param containerToReplace
     * @param repaint
     * @param renderImmediately
     */
    public void processAndRender (String xml, Container containerToReplace, boolean repaint, boolean renderImmediately) {
        if (xml != null && xml.length() > 0) {
            Container parent = null;
            if (repaint) {
                parent = containerToReplace.getParent();
                if (parent != null) {
                    parent.remove(containerToReplace);
                    AbstractSwingMLModel replaceModel = SwingMLModelToContainerRegistry.getModel(containerToReplace);
                    AbstractSwingMLModel parentModel = replaceModel.getParent();
                    parentModel.removeChild(replaceModel);
                    replaceModel.unregister(replaceModel.getContainer());
                  
                }
            }

            render(xml, parent, renderImmediately);
        }
    }

    /**
     * Screens should be rendered on background thread as to not lock up the UI.
     * 
     * @param xml
     * @param aContainer
     */
    public void render (String aSpec, Container aContainer) {
        render(aSpec, aContainer, false);
    }

    public void render (final String xml, final Container parent, boolean renderImmediately) {
        if (xml != null && xml.length() > 0) {
            ExternalEventManager.flush(this);

            // FIXME - This needs to be refactored to find the appropriate parent model and then iterate/render the new model we map from the XML
            final SwingMLModel bogus = new SwingMLModel();
            MapperUtil theMapperUtil = new MapperUtil();
            final Node theNode = getDocumentNode(xml);
            theMapperUtil.iterate(theNode, bogus, parent);

            // Create a runnable for the rendering portion, in case it needs to
            // be done in the background.
            Runnable bgRenderer = new Runnable() {

                public void run () {
                    // Perform the render
                    RendererUtil theRendererUtil = new RendererUtil();
                    theRendererUtil.iterate(bogus, parent);

                    // Update the UI
                    if (parent != null) {
                        JComponent theContainer = (JComponent) parent;
                        theContainer.updateUI();
                    }

                    // Notify listeners of rendering completion.
                    endRendering(theNode);
                }
            };

            // Notify listeners and start rendering
            startRendering(theNode);
            if (renderImmediately) {
                try {
                    SwingUtilities.invokeAndWait(bgRenderer);
                } catch (InterruptedException e) {
                    SwingMLLogger.getInstance().log(e);
                } catch (InvocationTargetException e) {
                    SwingMLLogger.getInstance().log(e);
                }
            } else {
                SwingUtilities.invokeLater(bgRenderer);
            }
        }
    }

    public void updateContentPane () {
        Container contentPane = getContentPane();
        StatusBar statusBar = new StatusBar(SwingMLRenderer.this);
        StatusBar.register(statusBar, contentPane);
        contentPane.add(statusBar.getBar(), BorderLayout.SOUTH);
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.