| <?xml version="1.0" encoding="UTF-8"?> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to you under the Apache License, |
| Version 2.0 (the "License"); you may not use this file except in |
| compliance with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <document id="scripting"> |
| <properties> |
| <title>Scripting</title> |
| </properties> |
| |
| <body> |
| <p> |
| Pivot applications can take |
| advantage of the JVM scripting support provided by the <tt>javax.script</tt> 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. |
| </p> |
| |
| <p> |
| Script blocks can be defined in BXML files in three different ways: |
| </p> |
| |
| <ul> |
| <li> |
| Inline in a <tt><bxml:script></tt> tag |
| </li> |
| <li> |
| As an external file included by a <tt><bxml:script></tt> with a <tt>src</tt> |
| attribute |
| </li> |
| <li> |
| In an event listener attribute |
| </li> |
| <li> |
| In a <tt><bxml:script></tt> tag defined in an event listener element |
| </li> |
| </ul> |
| |
| <p> |
| Though the first and last methods may seem similar, they are actually handled slightly |
| differently. All four methods are discussed in more detail below. |
| </p> |
| |
| <p> |
| The following application demonstrate's Pivot's scripting support: |
| </p> |
| |
| <application class="org.apache.pivot.tutorials.scripting.Scripting" |
| width="480" height="360"> |
| <libraries> |
| <library>core</library> |
| <library>wtk</library> |
| <library>wtk-terra</library> |
| <library>tutorials</library> |
| </libraries> |
| </application> |
| |
| <p> |
| 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: |
| </p> |
| |
| <source type="java" location="org/apache/pivot/tutorials/scripting/Scripting.java"> |
| <![CDATA[ |
| 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); |
| } |
| } |
| ]]> |
| </source> |
| |
| <p> |
| Notice how the <tt>startup()</tt> method calls <tt>put()</tt> on the |
| <tt>BXMLSerializer</tt> instance. <tt>BXMLSerializer</tt>'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. |
| </p> |
| |
| <p> |
| The BXML source is shown below: |
| </p> |
| |
| <source type="xml" location="org/apache/pivot/tutorials/scripting/Scripting.java"> |
| <![CDATA[ |
| <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> |
| ]]> |
| </source> |
| |
| <p> |
| This code demonstrates the various means by which script code can be used in BXML: |
| </p> |
| |
| <ul> |
| <li> |
| <p> |
| <i>Inline in a <tt><bxml:script></tt> tag.</i> The first |
| <tt><bxml:script></tt> tag defines its content inline. This code is |
| executed as it is processed by the BXML serializer. This example first outputs |
| the "bar" value set by the application, then declares two variables |
| (<tt>x</tt> and <tt>y</tt>) and a function (<tt>buttonClicked()</tt>. These |
| values are visible to all other script code declared within the page. |
| </p> |
| </li> |
| <li> |
| <p> |
| <i>As an external file included by a <tt><bxml:script></tt> with a |
| <tt>src</tt> attribute.</i> The second <tt><bxml:script></tt> tag |
| includes an externally defined script into the page. The contents of the script |
| are defined in "example.js", which is shown below. Any previously defined |
| values will be visible to the script, and any variables declared by the script |
| will be visible to other script blocks declared by the page. |
| </p> |
| </li> |
| <li> |
| <p> |
| <i>In an event listener attribute.</i> Event listeners can be declared in |
| attributes, using a syntax similar to that used for static property setters. |
| The attribute name for an event listener consists of the name of the interface |
| that defines the event plus the name of the event, separated by a period. The |
| BXML source contains several examples of attribute-based listeners: |
| </p> |
| <ul> |
| <li> |
| <tt>WindowStateListener.windowOpened</tt> |
| </li> |
| <li> |
| <tt>WindowStateListener.windowClosed</tt> |
| </li> |
| <li> |
| <tt>ButtonPressListener.buttonPressed</tt> |
| </li> |
| </ul> |
| </li> |
| <li> |
| <p> |
| <i>In a <tt><bxml:script></tt> tag defined in an event listener |
| element.</i> Attribute-based event handlers are convenient for simple one-line |
| listeners, but are not particuarly well suited to anything much more complex. |
| Pivot also provides the ability to define event listeners within a listener |
| list element. For example, the <tt>buttonPressListeners</tt> sub-element of |
| the "Click Me!" push button defines a <tt>buttonPressed()</tt> function that |
| is invoked when the corresponding button press event is fired by the button. |
| Because the script for element-based listeners doesn't need to fit within a |
| single XML attribute, more sophisticated handler code can be defined, while |
| still maintaining proximity to the element to which the handler applies. |
| </p> |
| <p> |
| Though it isn't obvious from this simple example, script-based event handlers |
| are not required to provide implementations for every method defined by the |
| listener interface. Any omitted methods are simply processed by a default no-op |
| handler. |
| </p> |
| </li> |
| </ul> |
| |
| <p> |
| 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). |
| </p> |
| |
| <p> |
| The "example.js" file is defined as follows: |
| </p> |
| |
| <source type="jscript" location="org/apache/pivot/tutorials/scripting/example.js"> |
| <![CDATA[ |
| 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"); |
| ]]> |
| </source> |
| |
| <p> |
| 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 <tt>ListView</tt> defined by |
| the BXML file. |
| </p> |
| </body> |
| </document> |