Scripting

Because Pivot requires a minimum of Java 6 update 10, Pivot applications can take advantage of the JVM scripting support provided by the javax.script package included with JDK versions 1.6 and later. While these APIs can be used on their own to script Pivot applications, Pivot includes platform support for easily embedding script code in BXML files.

Script blocks can be defined in BXML files in three different ways:

Though the first and last methods may seem similar, they are actually handled slightly differently. All four methods are discussed in more detail below.

The following application demonstrate's Pivot's scripting support:

This application is completely contrived - it doesn't present any practical example, but instead serves only to demonstrate the various means of using scripting in a BXML file. The Java source code for the application is shown below:

            
            package org.apache.pivot.tutorials.scripting;

            import org.apache.pivot.beans.BXMLSerializer;
            import org.apache.pivot.collections.List;
            import org.apache.pivot.collections.Map;
            import org.apache.pivot.wtk.Application;
            import org.apache.pivot.wtk.Button;
            import org.apache.pivot.wtk.ButtonPressListener;
            import org.apache.pivot.wtk.DesktopApplicationContext;
            import org.apache.pivot.wtk.Display;
            import org.apache.pivot.wtk.Window;

            public class Scripting implements Application {
                public static class MyButtonPressListener implements ButtonPressListener {
                    @Override
                    public void buttonPressed(Button button) {
                        System.out.println("[Java] A button was clicked.");
                    }
                }

                private Window window = null;

                private String foo;
                private List<?> listData;

                @Override
                public void startup(Display display, Map<String, String> properties)
                    throws Exception {
                    BXMLSerializer bxmlSerializer = new BXMLSerializer();
                    bxmlSerializer.getNamespace().put("bar", "12345");

                    window = (Window)bxmlSerializer.readObject(Scripting.class, "scripting.bxml");
                    foo = (String)bxmlSerializer.getNamespace().get("foo");
                    listData = (List<?>)bxmlSerializer.getNamespace().get("listData");

                    System.out.println("foo = " + foo);
                    System.out.println("listData.getLength() = " + listData.getLength());

                    window.open(display);
                }

                @Override
                public boolean shutdown(boolean optional) {
                    if (window != null) {
                        window.close();
                    }

                    return false;
                }

                @Override
                public void suspend() {
                }

                @Override
                public void resume() {
                }

                public static void main(String[] args) {
                    DesktopApplicationContext.main(Scripting.class, args);
                }
            }
            
        

Notice how the startup() method calls put() on the BXMLSerializer instance. BXMLSerializer's dictionary methods allow a caller to manipulate the script namespace before the BXML is loaded and retrieve values from it afterwards. In this example, the "bar" variable is pre-populated with the value "12345", which is later written to the console by script defined in "scripting.bxml". Similarly, the values of "foo" and "listData" are obtained from the serializer and written to the console after the BXML file has been read.

The BXML source is shown below:

            
            <Window title="Scripting Demo" maximized="true"
                WindowStateListener.windowOpened="java.lang.System.out.println('Window opened: ' + x)"
                WindowStateListener.windowClosed="java.lang.System.out.println('Window closed: ' + y)"
                xmlns:bxml="http://pivot.apache.org/bxml"
                xmlns:scripting="org.apache.pivot.demos.scripting"
                xmlns="org.apache.pivot.wtk">
                <bxml:script>
                importClass(java.lang.System);
                importPackage(org.apache.pivot.wtk);
                System.out.println("bar = " + bar);

                var x = 10;
                var y = 20;

                function buttonClicked(button) {
                    Prompt.prompt("y = " + y, button.window);
                }
                </bxml:script>

                <bxml:script src="example.js"/>

                <Border styles="{padding:2}">
                    <BoxPane orientation="vertical" styles="{padding:6}">
                        <PushButton buttonData="Click Me!">
                            <buttonPressListeners>
                                importPackage(org.apache.pivot.wtk);
                                function buttonPressed(button) {
                                    Prompt.prompt("x = " + x, button.getWindow());
                                }
                            </buttonPressListeners>
                        </PushButton>

                        <PushButton buttonData="No, Click Me!"
                            ButtonPressListener.buttonPressed="buttonClicked(arguments[0])"/>

                        <Border styles="{color:10}">
                            <ListView listData="$listData" selectedIndex="0"/>
                        </Border>
                    </BoxPane>
                </Border>
            </Window>
            
        

This code demonstrates the various means by which script code can be used in BXML:

Note that a special scope is created for event listener scripts that is local to the listener; although all page-level variables remain visible to the listener code, any variables defined within the listener (including functions) are only visible within that block. This prevents listener script from "polluting" the global page namespace. While this is generally not an issue for attribute-based listeners (which tend to be focused and short), can easily become an issue for element-based listeners, which may declare multiple functions with the same name (for example, when multiple button press handlers are defined within the same page).

The "example.js" file is defined as follows:

            
            importClass(java.lang.System);
            importPackage(org.apache.pivot.collections);

            System.out.println("Executing external script block; x = " + x);

            var foo = "ABCDE";

            var listData = new ArrayList();
            listData.add("One");
            listData.add("Two");
            listData.add("Three");
            
        

This script declares the "foo" value that is later output by the Java application code, and also defines the list data that is used by the example ListView defined by the BXML file.

Next: Summary