You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by gb...@apache.org on 2009/07/16 20:34:29 UTC

svn commit: r794772 - in /incubator/pivot/trunk/tutorials: src/org/apache/pivot/tutorials/stocktracker/ www/ www/stock_tracker/

Author: gbrown
Date: Thu Jul 16 18:34:28 2009
New Revision: 794772

URL: http://svn.apache.org/viewvc?rev=794772&view=rev
Log:
Finish migrating tutorials out of Wiki to tutorials/www.

Added:
    incubator/pivot/trunk/tutorials/www/stock_tracker/
    incubator/pivot/trunk/tutorials/www/stock_tracker.data_binding.template.html
    incubator/pivot/trunk/tutorials/www/stock_tracker.events.template.html
    incubator/pivot/trunk/tutorials/www/stock_tracker.localization.template.html
    incubator/pivot/trunk/tutorials/www/stock_tracker.template.html
    incubator/pivot/trunk/tutorials/www/stock_tracker.ui.template.html
    incubator/pivot/trunk/tutorials/www/stock_tracker.web_queries.template.html
    incubator/pivot/trunk/tutorials/www/stock_tracker/form.png   (with props)
    incubator/pivot/trunk/tutorials/www/stock_tracker/table_pane.png   (with props)
    incubator/pivot/trunk/tutorials/www/stock_tracker/table_view.png   (with props)
Modified:
    incubator/pivot/trunk/tutorials/src/org/apache/pivot/tutorials/stocktracker/stocktracker.detail.wtkx
    incubator/pivot/trunk/tutorials/www/accordions.template.html
    incubator/pivot/trunk/tutorials/www/hello_world.template.html
    incubator/pivot/trunk/tutorials/www/index.html
    incubator/pivot/trunk/tutorials/www/platform_overview.template.html
    incubator/pivot/trunk/tutorials/www/tutorial.css

Modified: incubator/pivot/trunk/tutorials/src/org/apache/pivot/tutorials/stocktracker/stocktracker.detail.wtkx
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/src/org/apache/pivot/tutorials/stocktracker/stocktracker.detail.wtkx?rev=794772&r1=794771&r2=794772&view=diff
==============================================================================
--- incubator/pivot/trunk/tutorials/src/org/apache/pivot/tutorials/stocktracker/stocktracker.detail.wtkx (original)
+++ incubator/pivot/trunk/tutorials/src/org/apache/pivot/tutorials/stocktracker/stocktracker.detail.wtkx Thu Jul 16 18:34:28 2009
@@ -21,15 +21,21 @@
     xmlns="org.apache.pivot.wtk">
     <Label textKey="companyName" styles="{fontBold:true, fontSize:12}" />
     <Separator />
-    <Form styles="{rightAlignLabels:true, fieldAlignment:'right'}">
+    <Form styles="{rightAlignLabels:true, fill:true}">
         <sections>
             <Form.Section>
-                <Label Form.name="%value" textKey="value" />
-                <Label wtkx:id="changeLabel" Form.name="%change" textKey="change" />
-                <Label Form.name="%openingValue" textKey="openingValue" />
-                <Label Form.name="%highValue" textKey="highValue" />
-                <Label Form.name="%lowValue" textKey="lowValue" />
-                <Label Form.name="%volume" textKey="volume" />
+                <Label Form.name="%value" textKey="value"
+                    styles="{horizontalAlignment:'right'}"/>
+                <Label wtkx:id="changeLabel" Form.name="%change" textKey="change"
+                    styles="{horizontalAlignment:'right'}"/>
+                <Label Form.name="%openingValue" textKey="openingValue"
+                    styles="{horizontalAlignment:'right'}"/>
+                <Label Form.name="%highValue" textKey="highValue"
+                    styles="{horizontalAlignment:'right'}"/>
+                <Label Form.name="%lowValue" textKey="lowValue"
+                    styles="{horizontalAlignment:'right'}"/>
+                <Label Form.name="%volume" textKey="volume"
+                    styles="{horizontalAlignment:'right'}"/>
             </Form.Section>
         </sections>
     </Form>

Modified: incubator/pivot/trunk/tutorials/www/accordions.template.html
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/accordions.template.html?rev=794772&r1=794771&r2=794772&view=diff
==============================================================================
--- incubator/pivot/trunk/tutorials/www/accordions.template.html (original)
+++ incubator/pivot/trunk/tutorials/www/accordions.template.html Thu Jul 16 18:34:28 2009
@@ -111,7 +111,7 @@
             // transition looks smoother
             if (selectedIndex != -1) {
                 int previousSelectedIndex = accordion.getSelectedIndex();
-                if (selectedIndex > previousSelectedIndex) {
+                if (selectedIndex &gt; previousSelectedIndex) {
                     accordion.getPanels().get(selectedIndex).setEnabled(true);
                 } else {
                     accordion.getPanels().get(previousSelectedIndex).setEnabled(false);
@@ -191,7 +191,7 @@
     private void updateAccordion() {
         int selectedIndex = accordion.getSelectedIndex();
 
-        Sequence<Component> panels = accordion.getPanels();
+        Sequence&lt;Component&gt; panels = accordion.getPanels();
         for (int i = 0, n = panels.getLength(); i &lt; n; i++) {
             panels.get(i).setEnabled(i &lt;= selectedIndex);
         }

Modified: incubator/pivot/trunk/tutorials/www/hello_world.template.html
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/hello_world.template.html?rev=794772&r1=794771&r2=794772&view=diff
==============================================================================
--- incubator/pivot/trunk/tutorials/www/hello_world.template.html (original)
+++ incubator/pivot/trunk/tutorials/www/hello_world.template.html Thu Jul 16 18:34:28 2009
@@ -121,7 +121,7 @@
 
 <p>A Pivot application can be run in the browser using the <tt>&lt;applet&gt;</tt> tag, as shown below; the class name of the Pivot application is specified by the "applicationClassName" applet parameter:</p>
 
-<pre style="padding-left:24px">
+<pre class="snippet">
 &lt;applet code="org.apache.pivot.wtk.BrowserApplicationContext$HostApplet"
     archive="lib/pivot-core-@version@.jar,lib/pivot-wtk-@version@.jar,
     lib/pivot-wtk-@version@.terra.jar, lib/pivot-tutorials-@version@.jar"

Modified: incubator/pivot/trunk/tutorials/www/index.html
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/index.html?rev=794772&r1=794771&r2=794772&view=diff
==============================================================================
--- incubator/pivot/trunk/tutorials/www/index.html (original)
+++ incubator/pivot/trunk/tutorials/www/index.html Thu Jul 16 18:34:28 2009
@@ -52,12 +52,13 @@
 <a href="localization.html">Localization</a><br>
 <a href="scripting.html">Scripting</a><br>
 <a href="stock_tracker.html">Stock Tracker</a><br>
-<p/>
-<a href="wtkx_primer.html">WTKX Primer</a><br>
 
-<p>Readers who want a quicker introduction to the platform may prefer to jump directly to the <a href="stocktracker.html">final section</a>, which walks through the implementation of a simple but practical sample application called Stock Tracker. Stock Tracker demonstrates a number of key features used by many "real world" applications, including UI markup, event handling, web queries, data binding, and localization, among others.</p>
+<p>Readers who want a quicker introduction to the platform may prefer to jump directly to the <a href="stock_tracker.html">final section</a>, which walks through the implementation of a simple but practical sample application called Stock Tracker. Stock Tracker demonstrates a number of key features used by many "real world" applications, including UI markup, event handling, web queries, data binding, and localization, among others.</p>
 
 <p>All source code in this tutorial is governed by the <a href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache License, Version 2.0</a>.</p>
+
+<p>Next: <a href="sample_application.html">Sample Application</a></p>
+
 </body>
 </html>
 

Modified: incubator/pivot/trunk/tutorials/www/platform_overview.template.html
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/platform_overview.template.html?rev=794772&r1=794771&r2=794772&view=diff
==============================================================================
--- incubator/pivot/trunk/tutorials/www/platform_overview.template.html (original)
+++ incubator/pivot/trunk/tutorials/www/platform_overview.template.html Thu Jul 16 18:34:28 2009
@@ -356,7 +356,7 @@
 </tbody>
 </table>
 
-<p>These operations, sometimes referred to as "CRUD", form the basis of the <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">Representational State Transfer</a> (REST) model of building web services. Pivot web queries are designed primarily to facilitate interaction with JSON-based REST services. However, they are sufficiently generic to support communication with any type of HTTP-based service, using any data format (for example, XML). This renders the classes in the org.apache.pivot.web package applicable to a broad range of server communication scenarios.</p>
+<p>These operations, sometimes referred to as "CRUD", form the basis of the <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">Representational State Transfer</a> (REST) model of building web services. Pivot web queries are designed primarily to facilitate interaction with JSON-based REST services. However, they are sufficiently generic to support communication with any type of HTTP-based service, using any data format (for example, XML). This renders the classes in the <tt>org.apache.pivot.web</tt> package applicable to a broad range of server communication scenarios.</p>
 
 <p>In addition to the client APIs defined in <tt>org.apache.pivot.web</tt>, the <tt>org.apache.pivot.web.server</tt> package provides classes that simplify the task of implementing and interacting with HTTP web services. <tt>QueryServlet</tt> provides an abstract base class for implementing web query servlets, and <tt>ProxyServlet</tt> provides an HTTP proxy that allows an unsigned applet to issue web queries to services outside of its origin server.</p>
 

Added: incubator/pivot/trunk/tutorials/www/stock_tracker.data_binding.template.html
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/stock_tracker.data_binding.template.html?rev=794772&view=auto
==============================================================================
--- incubator/pivot/trunk/tutorials/www/stock_tracker.data_binding.template.html (added)
+++ incubator/pivot/trunk/tutorials/www/stock_tracker.data_binding.template.html Thu Jul 16 18:34:28 2009
@@ -0,0 +1,179 @@
+<!--
+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.
+-->
+
+<html>
+<head>
+<title>Stock Tracker - Data Binding</title>
+<link rel="stylesheet" href="tutorial.css">
+
+<!-- NOTE: Syntax highlighting script is LGPL -->
+<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js"></script>
+<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js"></script>
+<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js"></script>
+<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css"/>
+<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css"/>
+<script type="text/javascript">
+    SyntaxHighlighter.all();
+</script>
+</head>
+<body>
+<h1>Data Binding</h1>
+
+<p>Data binding is the process of automatically mapping values between a set of user interface elements and an internal data representation; for example, from a order entry form to a collection of database fields or vice versa. Data binding can help simplify development by eliminating some or all of the tedious boilerplate code that often goes along with this type of programming.</p>
+
+<p>In Pivot, data binding is controlled by the <tt>load()</tt> and <tt>store()</tt> methods of the <tt>Component</tt> class:</p>
+
+<p>
+<tt>public void load(Dictionary<String, Object> context) {...}</tt><br>
+<tt>public void store(Dictionary<String, Object> context) {...}</tt><br>
+</p>
+
+<p>The <tt>Dictionary</tt> argument passed to these methods provides the "bind context": a collection of name/value pairs representing the data to which the components are bound. Each bindable component can be assigned a "bind key" that associates the component with a value in the context. The default implementations do nothing; components that support data binding override them to import data to the component from the context during a load, and export data from the component to the context during a store.</p>
+
+<p>Data binding is most often supported by components that accept and present user input (such as a text field), but it can also be implemented by read-only components, such as labels and progress meters. Most components allow a caller to bind only to a single value (such as the "text" property of a label), though some support additional bindings (for example, a checked list view that allows a caller to bind to both its items' checked and selected states).</p>
+
+<p>It is important to note that it is not possible to bind to a container directly. However, containers may act as nested bind contexts - when a bind key is assigned to a container, it is assumed to point to a nested <tt>Dictionary</tt> instance representing a subordinate bind context. This enables complex JSON object graphs returned from a web query to be seamlessly mapped to a set of data-bound components arranged in a non-trivial layout, for example.</p>
+
+<h2>Data Binding in the Stock Tracker Demo</h2>
+
+<p>The Stock Tracker demo isn't quite that sophisticated. It uses a single, flat bind context to populate the fields in the quote detail view. The bind context is actually the row data retrieved from the web query for the selected stock. This is why we requested more data than we seemed to need from the GET query: the extra fields are used to fill in the data in the detail form.</p>
+
+<p>The bound components, in this case, are read-only labels - Stock Tracker uses a one-way binding to map the retrieved quote data to the text property of each. We specified the name of the key to use for each label in the <tt>stocktracker.detail.wtkx</tt> file:</p>
+
+<pre class="snippet">
+...
+<Label Form.label="%value" textKey="value"/>
+...
+</pre>
+
+<p>The actual binding occurs when the selection changes in the table view; as we saw in the <a href="stock_tracker.events.html">Event Handling</a> section, the selection change handler calls the <tt>refreshDetail()</tt> method in response to a selection change event. The code for this method is as follows:</p>
+
+<pre class="snippet">
+private void refreshDetail() {
+    int firstSelectedIndex = stocksTableView.getFirstSelectedIndex();
+    removeSymbolsButton.setEnabled(firstSelectedIndex != -1);
+
+    StockQuote stockQuote = null;
+    Form.setFlag(detailChangeLabel, (Form.Flag)null);
+
+    if (firstSelectedIndex != -1) {
+        int lastSelectedIndex = stocksTableView.getLastSelectedIndex();
+
+        if (firstSelectedIndex == lastSelectedIndex) {
+            List&lt;StockQuote&gt; tableData = (List&lt;StockQuote&gt;)stocksTableView.getTableData();
+            stockQuote = tableData.get(firstSelectedIndex);
+
+            if (stockQuote.getChange() &lt; 0) {
+                Form.setFlag(detailChangeLabel, new Form.Flag(MessageType.ERROR));
+            }
+        }
+    }
+
+    if (stockQuote == null) {
+        detailRootPane.load(new HashMap&lt;String, Object&gt;());
+    } else {
+        StockQuoteView stockQuoteView = new StockQuoteView(stockQuote);
+        detailRootPane.load(stockQuoteView);
+    }
+}
+</pre>
+
+<p>The method does the following:</p>
+
+<ul>
+<li><p>Obtains the first selected index in the table (if more than one item is selected, we don't want to show anything in the detail)</p></li>
+<li><p>Clears the "flag" attribute from the detail change label (the <tt>Form</tt> container allows a caller to tag fields with a flag value, for use in data validation or just simple notification - here, a flag is used to indicate a negative change in the stock value)</p></li>
+<li><p>Gets a reference to the table view's data model and then to the data for the selected row</p></li>
+<li><p>If the change percentage is negative, shows a red "error" flag next to the detail label</p></li>
+<li><p>Wraps the row data in an instance of <tt>StockQuoteView</tt> and calls <tt>load()</tt>, populating the form with data from the selected quote</p></li>
+</ul>
+
+<p><tt>StockQuoteView</tt> is a "decorator" (in the <a href="http://en.wikipedia.org/wiki/Design_pattern_(computer_science)">design pattern</a> sense, not the WTK sense) - it ensures that it is formatted and presented in a readable manner in the detail view:</p>
+
+<pre class="brush:java">
+package pivot.tutorials.stocktracker;
+
+import java.text.DecimalFormat;
+
+import pivot.beans.BeanDictionary;
+
+public class StockQuoteView extends BeanDictionary {
+    private static final DecimalFormat valueFormat = new DecimalFormat("$0.00");
+    private static final DecimalFormat changeFormat = new DecimalFormat("+0.00;-0.00");
+    private static final DecimalFormat volumeFormat = new DecimalFormat();
+
+    public StockQuoteView(StockQuote stockQuote) {
+        super(stockQuote);
+    }
+
+    public Object get(String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key is null.");
+        }
+
+        Object value = null;
+        StockQuote stockQuote = (StockQuote)getBean();
+
+        if (stockQuote == null) {
+            value = "";
+        } else {
+            value = super.get(key);
+
+            if (key.equals("value")
+                || key.equals("openingValue")
+                || key.equals("highValue")
+                || key.equals("lowValue")) {
+                try {
+                    Float floatValue = (Float)value;
+                    if (floatValue.isNaN()) {
+                        value = "n/a";
+                    } else {
+                        value = valueFormat.format(floatValue);
+                    }
+                } catch(Exception exception) {
+                    value = "";
+                }
+            } else if (key.equals("change")) {
+                try {
+                    value = changeFormat.format((Number)value);
+                } catch(Exception exception) {
+                    value = "";
+                }
+            } else if (key.equals("volume")) {
+                try {
+                    value = volumeFormat.format((Number)value);
+                } catch(Exception exception) {
+                    value = "";
+                }
+            } else {
+                if (value != null) {
+                    value = value.toString();
+                }
+            }
+        }
+
+        return value;
+    }
+}
+</pre>
+
+<p>Note that the <tt>load()</tt> method is actually called on the parent container of the <tt>Form</tt>, rather than on the form itself. This is because we also want to bind to the label that contains the company name, which is not a child of the <tt>Form</tt>. A nested container does not automatically imply the existence of a sub-context - sub-contexts are created only when a nested container is assigned its own bind key. Because a bind key is not defined for it, the form simply inherits the bind context that was passed to its parent.</p>
+
+<p>Next: <a href="stock_tracker.localization.html">Localization</a></p>
+</body>
+</html>
+

Added: incubator/pivot/trunk/tutorials/www/stock_tracker.events.template.html
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/stock_tracker.events.template.html?rev=794772&view=auto
==============================================================================
--- incubator/pivot/trunk/tutorials/www/stock_tracker.events.template.html (added)
+++ incubator/pivot/trunk/tutorials/www/stock_tracker.events.template.html Thu Jul 16 18:34:28 2009
@@ -0,0 +1,116 @@
+<!--
+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.
+-->
+
+<html>
+<head>
+<title>Stock Tracker - Event Handling</title>
+<link rel="stylesheet" href="tutorial.css">
+</head>
+<body>
+<h1>Event Handling</h1>
+
+<p>While WTKX is used to declare the <i>structure</i> of an application, the application's <i>behavior</i> is defined in code (either Java or a JVM-compatible scripting language). Most of this logic is executed in response to an "event" triggered by some external source, such as user input or the completion of an asynchronous operation running in a background thread.</p>
+
+<p>In general, a Pivot application will load its user interface and wire up event handlers in the <tt>startup()</tt> method of the main application class. This method, along with the <tt>shutdown()</tt>, <tt>suspend()</tt>, and <tt>resume()</tt> methods, is defined by the <tt>Application</tt> interface, which all Pivot applications must implement.</p>
+
+<h2>Loading the UI</h2>
+
+<p>The <tt>Application</tt> interface in the Stock Tracker demo is implemented by the <tt>StockTracker</tt> class. The code in this file is referred to throughout the course of this section. A snippet of code from <tt>StockTracker</tt>'s <tt>startup()</tt> method is shown below:</p>
+
+<pre class="snippet">
+// Set the locale
+String language = properties.get(LANGUAGE_PROPERTY_NAME);
+if (language != null) {
+    Locale.setDefault(new Locale(language));
+}
+
+// Load and bind to the WTKX source
+Resources resources = new Resources(this);
+WTKXSerializer wtkxSerializer = new WTKXSerializer(resources);
+window = (Window)wtkxSerializer.readObject(this, "stocktracker.wtkx");
+wtkxSerializer.bind(this, StockTracker.class);
+</pre>
+
+<p>This code does the following:</p>
+
+<ul>
+<li><p>Retrieves the "langauge" argument that was provided to the application context when it was created - for desktop applications, this is a command-line argument; in the browser, it is either passed via an applet parameter</p></li>
+<li><p>Sets the default locale to an instance corresponding to the language argument</p></li>
+<li><p>Loads the application resources</p></li>
+<li><p>Creates an instance of <tt>WTKXSerializer</tt> and loads the WTKX source</p></li>
+</ul>
+
+<p>Finally, the code calls the <tt>bind()</tt> method on the serializer, which associates annotated member variables with corresponding IDs in the WTKX file:</p>
+
+<pre class="snippet">
+@WTKX private TableView stocksTableView;
+@WTKX private TextInput symbolTextInput;
+@WTKX private Button addSymbolButton;
+@WTKX private Button removeSymbolsButton;
+...
+</pre>
+
+<p>These annotations eliminate much of the boilerplate code required when loading WTKX contents manually via an instance of <tt>WTKXSerializer</tt>. However, since they rely on reflection code that may need to set private member variables, they can only be used by trusted code, such as a locally installed application or a signed applet or Web Start application.</p>
+
+<h2>Adding Event Listeners</h2>
+
+<p>At this point, the entire UI has been created, but it is not yet visible. Even if it was, it wouldn't do much, since no event handlers have been added. The next thing <tt>startup()</tt> does is add a number of event handlers:</p>
+
+<pre class="snippet">
+stocksTableView.getTableViewSelectionListeners().add(new TableViewSelectionListener.Adapter() {
+    public void selectedRangesChanged(TableView tableView, Sequence&lt;Span&gt; previousSelectedRanges) {
+        refreshDetail();
+    }
+});
+...
+
+addSymbolButton.getButtonPressListeners().add(new ButtonPressListener() {
+    public void buttonPressed(Button button) {
+        addSymbol();
+    }
+});
+...
+</pre>
+
+<p>A caller signals its interest in a particular event by implementing an interface that defines an event handler method and adding itself as an event lister on the event source. In the example above, two event handlers are created: a selection change listener on the stock quote table view and a button press listener on the "add symbol" button. Some listener interfaces, such as those shown here, define only a single event handler method, but others define more than one and serve as a grouping of related events. Interfaces with multiple handler methods generally define an inner Adapter class that can be used to simplify subclassing, as shown above.</p>
+
+<p>Note that, though these handlers are implemented as anonymous inner classes, this is not required - any class that implements the appropriate listener interface can register as a listener. It is also possible to define listeners in script within the WTKX file itself; this is discussed in more detail in the <a href="scripting.html">Scripting</a> section.</p>
+
+<h2>Displaying the Content</h2>
+
+<p>Finally, the window loaded from the WTKX files is opened, making the application visible and allowing the user to begin interacting with it (note that the window's "maximized" property is set to "true" in the WTKX file so that, when opened, the window will be sized to fit the entire display area):</p>
+
+<pre class="snippet">
+window.open();
+
+refreshTable();
+
+ApplicationContext.setInterval(new Runnable() {
+    public void run() {
+        refreshTable();
+    }
+}, REFRESH_INTERVAL);
+
+symbolTextInput.requestFocus();
+</pre>
+
+<p>The code then calls <tt>refreshTable()</tt> to load the stock quote data and sets a timer interval to reload the data every 15 seconds. Finally, it sets the focus to the symbol text input, so a user can easily add a new stock to track.</p>
+
+<p>Next: <a href="stock_tracker.web_queries.html">Web Queries</a></p>
+</body>
+</html>
+

Added: incubator/pivot/trunk/tutorials/www/stock_tracker.localization.template.html
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/stock_tracker.localization.template.html?rev=794772&view=auto
==============================================================================
--- incubator/pivot/trunk/tutorials/www/stock_tracker.localization.template.html (added)
+++ incubator/pivot/trunk/tutorials/www/stock_tracker.localization.template.html Thu Jul 16 18:34:28 2009
@@ -0,0 +1,133 @@
+<!--
+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.
+-->
+
+<html>
+<head>
+<title>Stock Tracker - Localization</title>
+<link rel="stylesheet" href="tutorial.css">
+
+<!-- NOTE: Syntax highlighting script is LGPL -->
+<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js"></script>
+<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js"></script>
+<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js"></script>
+<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js"></script>
+<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css"/>
+<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css"/>
+<script type="text/javascript">
+    SyntaxHighlighter.all();
+</script>
+</head>
+<body>
+<h1>Localization</h1>
+
+<p>In Java, any translatable text is generally stored in a set of localized property files called "resource bundles". The appropriate file is loaded at runtime for either the default locale or an explicitly selected non-default locale. While it is possible to use standard Java resource bundles in a Pivot application, Pivot adds support for JSON-based resource bundles that are slightly more flexible the built-in properties-based bundles. JSON resource bundles allow developers to more easily work with UTF-8 encoded resource strings, and also natively support hierarchical data, which can only be simulated when using properties files.</p>
+
+<p>Stock Tracker provides two resource files, one for English users and one for French-speaking users:</p>
+
+<pre class="brush:jscript">
+{   stockTracker: "Pivot Stock Tracker",
+    symbol: "Symbol",
+    companyName: "Company",
+    value: "Value",
+    openingValue: "Open",
+    highValue: "High",
+    lowValue: "Low",
+    change: "Change",
+    volume: "Volume",
+    addSymbol: "Add symbol",
+    removeSymbol: "Remove selected symbols",
+    lastUpdate: "Last Update",
+    dataProvidedBy: "Data provided by",
+    yahooFinance: "Yahoo! Finance"
+}
+</pre>
+<p class="caption">StockTracker.json</p>
+
+<pre class="brush:jscript">
+{   stockTracker: "La Bourse Pivot",
+    symbol: "Code",
+    companyName: "SociŽtŽ",
+    value: "Cours",
+    openingValue: "Ouverture",
+    highValue: "+ Haut",
+    lowValue: "+ Bas",
+    change: "Variation",
+    volume: "Volume",
+    addSymbol: "Ajouter un code",
+    removeSymbol: "Enlever codes sŽlectionnŽs",
+    lastUpdate: "Dernier Žchange",
+    dataProvidedBy: "DonnŽes fournies par",
+    yahooFinance: "Yahoo! Finance"
+}
+</pre>
+<p class="caption">StockTracker_fr.json</p>
+
+<p>As we've seen, references to these string resources can be embedded directly within a WTKX file:</p>
+
+<pre class="snippet">
+&lt;Form styles="{rightAlignLabels:true, fill:true}"&gt;
+    &lt;sections&gt;
+        &lt;Form.Section&gt;
+            &lt;Label Form.name="%value" textKey="value"
+                styles="{horizontalAlignment:'right'}"/&gt;
+            &lt;Label wtkx:id="changeLabel" Form.name="%change" textKey="change"
+                styles="{horizontalAlignment:'right'}"/&gt;
+            &lt;Label Form.name="%openingValue" textKey="openingValue"
+                styles="{horizontalAlignment:'right'}"/&gt;
+            &lt;Label Form.name="%highValue" textKey="highValue"
+                styles="{horizontalAlignment:'right'}"/&gt;
+            &lt;Label Form.name="%lowValue" textKey="lowValue"
+                styles="{horizontalAlignment:'right'}"/&gt;
+            &lt;Label Form.name="%volume" textKey="volume"
+                styles="{horizontalAlignment:'right'}"/&gt;
+        &lt;/Form.Section&gt;
+    &lt;/sections&gt;
+&lt;/Form&gt;
+</pre>
+
+<p>The application loads the resources for the appropriate locale at startup, and the WTKX serializer handles the details of resource substitution so the developer doesn't have to worry about it. The following applet demonstrates the Stock Tracker application run using the "fr" locale. No code changes are required; the same JAR files are used to execute both the English and French versions:</p>
+
+<script>
+var attributes = {code:"org.apache.pivot.wtk.BrowserApplicationContext$HostApplet",
+    archive:"lib/@project_name@-core-@version@.signed.jar,lib/@project_name@-web-@version@.signed.jar,lib/@project_name@-wtk-@version@.signed.jar,lib/@project_name@-wtk-@version@.terra.signed.jar,lib/@project_name@-tutorials-@version@.signed.jar",
+    width:480,
+    height:360
+};
+var parameters = {application_class_name:"org.apache.pivot.tutorials.stocktracker.StockTracker",
+    startup_properties:"language:fr",
+    codebase_lookup:false
+};
+deployJava.writeAppletTag(attributes, parameters);
+</script>
+
+<p>Not all localization requirements can be handled by WTKX alone, however. For example, Stock Tracker needs to manually handle the localization of the "last updated" message:</p>
+
+<pre class="snippet">
+DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,
+    DateFormat.MEDIUM, Locale.getDefault());
+lastUpdateLabel.setText(dateFormat.format(new Date()));
+</pre>
+
+<p>However, most static localization can be addressed in the WTKX source itself, making it very easy to build internationalized applications in Pivot.</p>
+
+<h2>Summary</h2>
+
+<p>The examples in this section demonstrate the implementation of a simple but complete application implemented in Pivot. They discuss features common to many "real-world" applications, including UI markup, event handling, server communication, data binding, and internationalization, and should provide a good starting point for any developer interested in working with Pivot.</p>
+
+</body>
+</html>
+

Added: incubator/pivot/trunk/tutorials/www/stock_tracker.template.html
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/stock_tracker.template.html?rev=794772&view=auto
==============================================================================
--- incubator/pivot/trunk/tutorials/www/stock_tracker.template.html (added)
+++ incubator/pivot/trunk/tutorials/www/stock_tracker.template.html Thu Jul 16 18:34:28 2009
@@ -0,0 +1,57 @@
+<!--
+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.
+-->
+
+<html>
+<head>
+<title>Stock Tracker</title>
+<link rel="stylesheet" href="tutorial.css">
+<script src="http://java.com/js/deployJava.js"></script>
+</head>
+<body>
+<h1>Stock Tracker</h1>
+
+<p>This section walks through the implementation of a simple but practical "stock tracker" sample application. It demonstrates a number of key features used by many "real world" applications, including:</p>
+
+<ul>
+<li>UI markup using WTKX</li>
+<li>Event handling</li>
+<li>Web queries</li>
+<li>Data binding</li>
+<li>Localization</li>
+</ul>
+
+<p>The sample application is shown below. The application retrieves live (delayed by 15 minutes) stock quote data from <a href="http://finance.yahoo.com/">Yahoo! Finance</a> as a CSV file and presents it in a table view component (the applet is signed to allow it to communicate with the Yahoo web service):</p>
+
+<script>
+var attributes = {code:"org.apache.pivot.wtk.BrowserApplicationContext$HostApplet",
+    archive:"lib/@project_name@-core-@version@.signed.jar,lib/@project_name@-web-@version@.signed.jar,lib/@project_name@-wtk-@version@.signed.jar,lib/@project_name@-wtk-@version@.terra.signed.jar,lib/@project_name@-tutorials-@version@.signed.jar",
+    width:480,
+    height:360
+};
+var parameters = {application_class_name:"org.apache.pivot.tutorials.stocktracker.StockTracker",
+    startup_properties:"language:en",
+    codebase_lookup:false
+};
+deployJava.writeAppletTag(attributes, parameters);
+</script>
+
+<p>Users can add or remove stock symbols using the text input and buttons at the bottom of the applet. Selecting a row in the table shows additional information about the stock in the form on the right. The data is automatically updated every 15 seconds.</p>
+
+<p>Next: <a href="stock_tracker.markup.html">UI Markup Using WTKX</a></p>
+</body>
+</html>
+

Added: incubator/pivot/trunk/tutorials/www/stock_tracker.ui.template.html
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/stock_tracker.ui.template.html?rev=794772&view=auto
==============================================================================
--- incubator/pivot/trunk/tutorials/www/stock_tracker.ui.template.html (added)
+++ incubator/pivot/trunk/tutorials/www/stock_tracker.ui.template.html Thu Jul 16 18:34:28 2009
@@ -0,0 +1,248 @@
+<!--
+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.
+-->
+
+<html>
+<head>
+<title>Stock Tracker - UI Markup Using WTKX</title>
+<link rel="stylesheet" href="tutorial.css">
+
+<!-- NOTE: Syntax highlighting script is LGPL -->
+<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js"></script>
+<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js"></script>
+<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js"></script>
+<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css"/>
+<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css"/>
+<script type="text/javascript">
+    SyntaxHighlighter.all();
+</script>
+</head>
+<body>
+<h1>UI Markup Using WTKX</h1>
+
+<p>The user interface of a Pivot application is often defined using XML markup rather than Java code. The hierarchical structure of an XML document more closely parallels the structure of the component hierarchy, which makes it easier to visualize the resulting output.</p>
+
+<p>Pivot allows developers to split the definition of the user interface into multiple WTKX files. This allows each piece to vary independently and makes the overall structure easier to manage. The layout of the Stock Tracker application is divided into two WTKX documents; <tt>stocktracker.wtkx</tt>, which sets up the main structure of the application, and <tt>stocktracker.detail.wtkx</tt>, which defines the layout for the quote detail. We'll take a look at the top-level markup in <tt>stocktracker.wtkx first</tt>, concentrating on the two main page elements, <tt>TablePane</tt> and <tt>TableView</tt>. Then we'll investigate the markup for the stock quote detail, which uses the <tt>Form</tt> container and lays the ground work for the data binding support we'll discuss in a later section.</p>
+
+<h2>TablePane</h2>
+
+<p>The root node of <tt>stocktracker.wtkx</tt> is a <tt>TablePane</tt> element. A table pane is a type of layout container that arranges its children in a manner similar to an HTML table.</p>
+
+<p>Like HTML tables, <tt>TablePane</tt> contents are organized into rows and columns. Unlike HTML, however, which may attempt to infer a table structure from its contents, a table pane's structure must be explicitly defined, as shown below:</p>
+
+<pre class="snippet">
+&lt;TablePane styles="{padding:8, horizontalSpacing:6}"&gt;
+    &lt;columns&gt;
+        &lt;TablePane.Column width="244"/&gt;
+        &lt;TablePane.Column width="1*"/&gt;
+    &lt;/columns&gt;
+    &lt;rows&gt;
+        &lt;TablePane.Row height="-1"&gt;
+        ...
+        &lt;/TablePane.Row&gt;
+        &lt;TablePane.Row height="1*"&gt;
+        ...
+        &lt;/TablePane.Row&gt;
+        &lt;TablePane.Row height="-1"&gt;
+        ...
+        &lt;/TablePane.Row&gt;
+        &lt;TablePane.Row height="-1"&gt;
+        ...
+        &lt;/TablePane.Row&gt;
+    &lt;/rows&gt;
+&lt;/TablePane&gt;
+</pre>
+
+<p><tt>TablePane</tt> row heights and column widths can be specified as either automatic, absolute, or relative:</p>
+
+<ul>
+<li><p>A value of -1 specifies an automatic size; the table pane will determine the height of the row as the maximum preferred height of all components in that row; the same applies to automatic column widths.</p></li>
+<li><p>An explicit, non-negative value defines an absolute width or height, specified in pixels.</p></li>
+<li><p>A number followed by an asterisk specifies a relative size; the width or height is determined by applying a weighted percentage of the space left over after subtracting the width or height of all automatic and absolute columns and rows (which may be 0).</p></li>
+</ul>
+
+<p>In the example above, the second row is given a relative height that will assign it all of the available space once the other rows are accounted for; all other rows are given an automatic height. The first column is given an explicit width of 244 pixels, and the second column is given 100% of the remaining width.</p>
+
+<p>The following graphic shows the resulting layout (the blue lines represent the table cell boundaries):</p>
+
+<p><img src="stock_tracker/table_pane.png"></p>
+<p class="caption">Stock Tracker table pane cells.</p>
+
+<h3>Styles</h3>
+
+<p>Note the styles attribute of the <tt>TablePane</tt> element. Styles are used to customize the appearance of a component, and are specified in WTKX as a JSON-formatted collection of name/value pairs. All WTKX elements support the styles attribute, but each element may support a different set of styles depending on its current skin.</p>
+
+<p>In this example, the table pane is assigned a "padding" value of 8 and a "horizontalSpacing" value of 6. Padding represents the amount of space that the table pane will leave around its components, and horizontal spacing is the size of the gap the table pane will leave between columns.</p>
+
+<h3>Table Pane Cells</h3>
+
+The actual content of a table pane is specified in the <tt><rows></tt> element. Each immediate child element of the <tt><rows></tt> element is an element representing a complete row; each child of the <tt><TablePane.Row></tt> element is considered a table cell, as shown below:
+
+<pre class="snippet">
+&lt;TablePane.Row height="-1"&gt;
+    &lt;Label text="%stockTracker"
+        styles="{font:'Verdana bold 14', verticalAlignment:'center'}"/&gt;
+&lt;/TablePane.Row&gt;
+</pre>
+
+<p>Note the use of the percent symbol in the text attribute value. This tells the WTKX component loader that the value of the label's text property should be provided by a string resource with the specified name, minus the percent sign. This is discussed in more detail in the Localization section.</p>
+
+<h2>TableView</h2>
+
+<p>The <tt>TableView</tt> component is used to present tabular data in a grid of rows and columns. While it bears a superficial resemblance to <tt>TablePane</tt>, the purpose of the two components is quite different: <tt>TablePane</tt> is a container; its primary purpose is to lay out sub-components, and its structure is most often defined at design time. <tt>TableView</tt> is a component that acts as a view on a set of model data and is most often populated at run time.</p>
+
+<p>Like <tt>TablePane</tt>, <tt>TableView</tt>'s columns must be defined up front. However, since the contents of a table view are generally not known until run time, it is not necessary to define a table view's row structure - this is provided by the table view's model data when the table view is populated.</p>
+
+<p><tt>TableView</tt> is used by the Stock Tracker demo to display a selectable list of stock quote data. The following listing shows the markup used by the demo to create the table view:</p>
+
+<pre class="snippet">
+&lt;TableView wtkx:id="stocksTableView" selectMode="multi"
+    styles="{showHorizontalGridLines:false}"&gt;
+    &lt;columns&gt;
+        &lt;TableView.Column name="symbol" headerData="%symbol" width="80"/&gt;
+        &lt;TableView.Column name="value" headerData="%value" width="80"&gt;
+            &lt;cellRenderer&gt;
+                &lt;content:TableViewNumberCellRenderer
+                    styles="{horizontalAlignment:'right'}"
+                    numberFormat="$$0.00"/&gt;
+            &lt;/cellRenderer&gt;
+        &lt;/TableView.Column&gt;
+        &lt;TableView.Column name="change" headerData="%change" width="80"&gt;
+            &lt;cellRenderer&gt;
+                &lt;stocktracker:ChangeCellRenderer
+                    styles="{horizontalAlignment:'right'}"
+                    numberFormat="+0.00;-0.00"/&gt;
+            &lt;/cellRenderer&gt;
+        &lt;/TableView.Column&gt;
+    &lt;/columns&gt;
+&lt;/TableView&gt;
+</pre>
+
+<p>Note that the <tt>TableView</tt> element includes a <tt>wtkx:id</tt> attribute value with a value of "stocksTableView". This is used to associate the table view with an instance of <tt>TableViewHeader</tt>, which is discussed in the next section. ID values are also used to gain access to WTKX components from Java code when wiring up event handlers. This is discussed in more detail in the <a href="stock_tracker.events.html">Event Handling</a> section.</p>
+
+<p>Setting the <tt>selectMode</tt> attribute to "multi" specifies that a user may select multiple rows in this table view. Other possible values for <tt>selectMode</tt> are "single" and "none". Setting <tt>showHorizontalGridLines</tt> to false tells the table view not to draw horizontal grid lines separating its cells. Vertical grid lines will still be drawn; however, these can be turned off as well by setting <tt>showVerticalGridLines</tt> to false.</p>
+
+<h3>TableView Columns</h3>
+
+<p>The application defines three columns for the table view: one for the stock ticker symbol, another for the stock's current value, and a third for the change percentage. The name attribute defines the name of the column. It is not visible to the user, but is used as a key to map values in each row to their appropriate place in the table view; the value of the headerData attribute is what is actually shown to the user in the table view header. Note that the header data for each column is specified as a resource name so the header text can be localized.</p>
+
+<p>The width of each column in this example is set to an absolute value of 80 pixels. Table view columns can also be assigned a relative width, but they do not support the automatic widths supported by the TablePane component.</p>
+
+<p>The "value" and "change" columns define several additional attributes related to cell renderers. By default, table cells are drawn using a renderer that presents the cell's contents as a text string. Custom cell renderers can be used to present cell data formatted as a number, date, or otherwise. The Stock Tracker demo uses the built-in number cell renderer to format the value column and a custom renderer to display the values in the change column using either red or green text depending on the change direction. A complete discussion of cell renderers is outside the scope of this tutorial, but the source code for the custom renderer is as follows:</p>
+
+<pre class="brush:java">
+package pivot.tutorials.stocktracker;
+
+import java.awt.Color;
+
+import pivot.wtk.TableView;
+import pivot.wtk.content.TableViewNumberCellRenderer;
+
+public class ChangeCellRenderer extends TableViewNumberCellRenderer {
+    public static final Color UP_COLOR = new Color(0x00, 0x80, 0x00);
+    public static final Color DOWN_COLOR = new Color(0xff, 0x00, 0x00);
+
+    public void render(Object value, TableView tableView, TableView.Column column,
+        boolean rowSelected, boolean rowHighlighted, boolean rowDisabled) {
+        super.render(value, tableView, column, rowSelected, rowHighlighted, rowDisabled);
+
+        if (value != null
+            && !rowSelected) {
+            StockQuote stockQuote = (StockQuote)value;
+            float change = stockQuote.getChange();
+            getStyles().put("color", change &lt; 0 ? DOWN_COLOR : UP_COLOR);
+        }
+    }
+}
+</pre>
+
+<h3>TableViewHeader</h3>
+
+<p>Pivot's <tt>TableView</tt> component does not include built-in header support; rather, support for column headings and resizing is provided by a separate <tt>TableViewHeader</tt> component. This is because <tt>TableView</tt> (and other similar components including <tt>ListView</tt> and <tt>TreeView</tt>) do not include built-in support for scrolling. Scrolling is provided by the <tt>ScrollPane</tt> class, which is discussed in the next section.</p>
+
+<p><img src="stock_tracker/table_view.png"></p>
+<p class="caption">Stock Tracker table view and table view header.</p>
+
+<p>The following markup is used to declare the table view header component for the Stock Tracker demo:</p>
+
+<pre class="snippet">
+&lt;TableViewHeader tableView="$stocksTableView"/&gt;
+</pre>
+
+<p>That's it! The header automatically associates itself with the table view instance identified by the <tt>tableView</tt> attribute - no additional markup or coding is necessary.</p>
+
+<p>Though it is not shown in the Stock Tracker demo, TableViewHeader can also be used to provide support for column sorting. An example of this is shown in the "kitchen sink" demo application.</p>
+
+<h3>ScrollPane and Border</h3>
+
+<p>Pivot components do not manage scrolling internally - all scrolling in Pivot is handled by the <tt>ScrollPane</tt> class (more specifically, by an instance of the <tt>Viewport</tt> class, but the distinction is not relevant to this discussion). A scroll pane provides a windowed view onto another component and allows a user to select which part of the component is shown by dragging a horizontal or vertical scroll bar.</p>
+
+<p>The component being scrolled is called the "view", and is specified as a child of the scroll pane's <tt><view></tt> element. <tt>ScrollPane</tt> also provides support for fixed row and column headers that scroll with the view but always remain visible. These are defined using <tt>ScrollPane</tt>'s <tt><rowHeader></tt> and <tt><columnHeader></tt> sub-elements. A <tt>TableViewHeader</tt> is often used as a column header for a <tt>TableView</tt> instance, but a row or column header can be an instance of any type of component - for example, an application developer might create a "ruler" component to use as a header in a drawing program to help a designer visualize the scale of a large scrollable image.</p>
+
+<h2>Stock Quote Detail</h2>
+
+<p>The <tt>stocktracker.wtkx</tt> file defines the overall structure of the application, and the layout of the quote detail content is defined separately in <tt>stocktracker.detail.wtkx</tt>. Yet, when the application is run, it appears as though the entire application was defined in a single WTKX file. How does this work? The key is the <tt>wtkx:include</tt> tag:</p>
+
+<pre class="snippet">
+&lt;wtkx:include namespace="detail" src="stocktracker.detail.wtkx"/&gt;
+</pre>
+
+<p>The <tt>wtkx:include</tt> tag tells the WTKX serializer that a component should be placed here, but that the component's content is not defined in this file. The location of the actual content is specified by the src tag and is either an absolute (beginning with a slash character) or relative (no slash) path to another WTKX file. Relative paths are resolved in the context of the current WTKX file, and absolute paths are resolved in the context of the application's classpath. Fully-qualified URLs (those that begin with a protocol) are not supported.</p>
+
+<p>In addition to the <tt>src</tt> attribute, the <tt>wtkx:include</tt> tag accepts an optional <tt>wtkx:id</tt> attribute. This is used to partition the ID values defined in each WTKX file into separate namespaces, allowing developers to avoid naming collisions. Components are referenced by concatenating the include IDs with the component's ID; for example, the path "detail.changeLabel" refers to the <tt>Label</tt> with ID "changeLabel" defined in the <tt>stocktracker.detail.wtkx</tt> file.</p>
+
+<h3>Forms</h3>
+
+<p>Though the top-level element of the detail page is a <tt>FlowPane</tt>, most of the layout is handled by the <tt>Form</tt> container. Forms arrange their children in a vertical stack, similar to a vertical <tt>FlowPane</tt>, prepending a text label to each field.</p>
+
+<p><img src="stock_tracker/form.png"></p>
+<p class="caption">Stock Tracker detail view using Form container.</p>
+
+<p>A field's label is defined by a <tt>Form.name</tt> attribute attached to the child element, as shown below:</p>
+
+<pre class="snippet">
+&lt;Form styles="{rightAlignLabels:true, fill:true}"&gt;
+    &lt;sections&gt;
+        &lt;Form.Section&gt;
+            &lt;Label Form.name="%value" textKey="value"
+                styles="{horizontalAlignment:'right'}"/&gt;
+            &lt;Label wtkx:id="changeLabel" Form.name="%change" textKey="change"
+                styles="{horizontalAlignment:'right'}"/&gt;
+            &lt;Label Form.name="%openingValue" textKey="openingValue"
+                styles="{horizontalAlignment:'right'}"/&gt;
+            &lt;Label Form.name="%highValue" textKey="highValue"
+                styles="{horizontalAlignment:'right'}"/&gt;
+            &lt;Label Form.name="%lowValue" textKey="lowValue"
+                styles="{horizontalAlignment:'right'}"/&gt;
+            &lt;Label Form.name="%volume" textKey="volume"
+                styles="{horizontalAlignment:'right'}"/&gt;
+        &lt;/Form.Section&gt;
+    &lt;/sections&gt;
+&lt;/Form&gt;
+</pre>
+
+<p>Since the quote data is read-only, the "fields" in this example are actually themselves Label instances. Their form label values are specified as string resources so they can be easily translated.</p>
+
+<h3>Data Binding</h3>
+
+<p>Each <tt>Label</tt> in the form defines a <tt>textKey</tt> attribute. This attribute specifies the name of the property from which the label will obtain its text value during data binding. Specifically, it is the name of the value's key in the "bind context", an instance of <tt>Dictionary<String, Object></tt> that is passed to the <tt>load()</tt> method of the <tt>Form</tt> instance, and then recursively to the <tt>Label</tt>s themselves. This is discussed in more detail in the data binding section.</p>
+
+<p>Though data binding is often used to populate a <tt>Form</tt>'s contents, there is nothing special about the Form class itself that supports data binding - it is supported by all container types and many component classes.</p>
+
+<p>Next: <a href="stock_tracker.events.html">Event Handling</a></p>
+</body>
+</html>
+

Added: incubator/pivot/trunk/tutorials/www/stock_tracker.web_queries.template.html
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/stock_tracker.web_queries.template.html?rev=794772&view=auto
==============================================================================
--- incubator/pivot/trunk/tutorials/www/stock_tracker.web_queries.template.html (added)
+++ incubator/pivot/trunk/tutorials/www/stock_tracker.web_queries.template.html Thu Jul 16 18:34:28 2009
@@ -0,0 +1,302 @@
+<!--
+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.
+-->
+
+<html>
+<head>
+<title>Stock Tracker - Web Queries</title>
+<link rel="stylesheet" href="tutorial.css">
+
+<!-- NOTE: Syntax highlighting script is LGPL -->
+<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js"></script>
+<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js"></script>
+<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js"></script>
+<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css"/>
+<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css"/>
+<script type="text/javascript">
+    SyntaxHighlighter.all();
+</script>
+</head>
+<body>
+<h1>Web Queries</h1>
+
+<p>"Web queries" are Pivot's native means of communicating with remote data services. They are designed primarily to facilitate interaction with JSON-based REST services. However, they are sufficiently generic to support communication with any type of HTTP-based service, using any data format.</p>
+
+<p>For example, the data presented by the Stock Tracker application is retrieved from Yahoo! Finance as a comma-separated value (CSV) file:</p>
+
+<p>
+<tt>"AAPL","APPLE INC",171.06,169.59,172.17,166.00,+2.88,12995693</tt><br>
+<tt>"AMZN","AMAZON.COM INC",72.54,72.35,73.83,70.52,+1.10,2748930</tt><br>
+<tt>"EBAY","EBAY INC",27.09,27.35,27.44,27.04,-0.02,3426369</tt></br>
+</p>
+
+<p>This data is returned by submitting an HTTP GET request to <a href="http://download.finance.yahoo.com/d/quotes.csv/">http://download.finance.yahoo.com/d/quotes.csv/</a> with an appropriate set of query string arguments. For example, the Stock Tracker application passes the following arguments to the service URL:</p>
+
+<ul>
+<li><b>s</b> - A comma-separated list of stock symbols representing the quotes to retrieve.</li>
+<li><b>f</b> - the requested format for the resulting CSV file; this is a string of characters representing the various data fields returned by the query. The format used by the Stock Tracker application is "snl1ohgc1v":
+<ul>
+<li><i>s</i> - symbol</li>
+<li><i>n</i> - company name</li>
+<li><i>l1</i> - most recent value</li>
+<li><i>o</i> - opening value</li>
+<li><i>h</i> - high value</li>
+<li><i>g</i> - low value</li>
+<li><i>c1</i> - change percentage</li>
+<li><i>v</i> - volume</li>
+</ul></li>
+</ul>
+
+<p>Note that this query actually returns more data than can be displayed in the table view. The other data fields are used by the quote detail view, which is discussed in more detail in the <a href="stock_tracker.data_binding.html">data binding</a> section.</p>
+
+<h2>Constructing the Web Query</h2>
+
+<p>In order to display the stock quotes to the user, Stock Tracker must execute a web query to retrieve the data from the Yahoo! Finance web service and then populate the stock quote table view with the results of the query. The query is executed in the <tt>refreshTable()</tt> method, and the table is populated by a callback handler implemented as an anonymous inner class defined in this method. This code is defined in the <tt>StockTracker</tt> class.</p>
+
+<p>First, the web query is created:</p>
+
+<pre class="snippet">
+getQuery = new GetQuery(SERVICE_HOSTNAME, SERVICE_PATH);
+</pre>
+
+<p>Then, the value of the "s" argument is constructed by joining the values in the symbol list with commas, and the query arguments are applied:</p>
+
+<pre class="snippet">
+StringBuilder symbolsArgumentBuilder = new StringBuilder();
+for (int i = 0, n = symbols.getLength(); i < n; i++) {
+    if (i > 0) {
+        symbolsArgumentBuilder.append(",");
+    }
+
+    symbolsArgumentBuilder.append(symbols.get(i));
+}
+
+String symbolsArgument = symbolsArgumentBuilder.toString();
+
+getQuery.getArguments().put("s", symbolsArgument);
+getQuery.getArguments().put("f", "snl1ohgc1v");
+</pre>
+
+<p>The resulting query URL would be similar to:</p>
+
+<p style="padding-left:24px"><a href="http://download.finance.yahoo.com/d/quotes.csv?s=aapl,amzn,ebay&f=snl1ohgc1v">http://download.finance.yahoo.com/d/quotes.csv?s=aapl,amzn,ebay&f=snl1ohgc1v</a></p>
+
+<p>Next, an instance of CSVSerializer is created and configured:</p>
+
+<pre class="snippet">
+CSVSerializer quoteSerializer = new CSVSerializer();
+quoteSerializer.getKeys().add("symbol");
+quoteSerializer.getKeys().add("companyName");
+quoteSerializer.getKeys().add("value");
+quoteSerializer.getKeys().add("openingValue");
+quoteSerializer.getKeys().add("highValue");
+quoteSerializer.getKeys().add("lowValue");
+quoteSerializer.getKeys().add("change");
+quoteSerializer.getKeys().add("volume");
+</pre>
+
+<p>By default, the <tt>GetQuery</tt> class uses an instance of <tt>org.apache.pivot.core.serialization.JSONSerializer</tt> to deserialize data returned by a GET request. However, the quote data from Yahoo! Finance is returned as a CSV file; <tt>CSVSerializer</tt> is an implementation of the <tt>org.apache.pivot.core.serialization.Serializer</tt> interface that parses a CSV data stream into a sequence of name/value pairs.</p>
+
+<p>By default, <tt>CSVSerializer</tt> creates an instance of <tt>org.apache.pivot.collections.HashMap&lt;String, Object&gt;</tt> for each row it encounters in the CSV stream. However, a caller can specify the name of a different class using the <tt>setItemClass()</tt> method. This avoids the performance penalty of traversing the data twice: once to read it from the CSV stream and again to convert it to the appropriate type:</p>
+
+<pre class="snippet">
+quoteSerializer.setItemClass(StockQuote.class);
+</pre>
+
+<p>If the item class implements the <tt>pivot.collections.Dictionary</tt> interface, the parsed values are <tt>put()</tt> directly into the item instance; otherwise, the item is wrapped in a <tt>pivot.beans.BeanDictionary</tt> into which the values are <tt>put()</tt> (<tt>BeanDictionary</tt> is a handy class that allows a caller to treat a JavaBean object as if it were a dictionary). </p>
+
+<p>Stock Tracker uses the <tt>StockQuote</tt> class to represent the rows in the CSV file:</p>
+
+<pre class="brush:java">
+package pivot.tutorials.stocktracker;
+
+public class StockQuote {
+    private String symbol = null;
+    private String companyName = null;
+    private float value = 0;
+    private float openingValue = 0;
+    private float highValue = 0;
+    private float lowValue = 0;
+    private float change = 0;
+    private float volume = 0;
+
+    public String getSymbol() {
+        return symbol;
+    }
+
+    public void setSymbol(String symbol) {
+        this.symbol = symbol;
+    }
+
+    public String getCompanyName() {
+        return companyName;
+    }
+
+    public void setCompanyName(String companyName) {
+        this.companyName = companyName;
+    }
+
+    public float getValue() {
+        return value;
+    }
+
+    public void setValue(float value) {
+        this.value = value;
+    }
+
+    public void setValue(String value) {
+        setValue(Float.parseFloat(value));
+    }
+
+    public float getOpeningValue() {
+        return openingValue;
+    }
+
+    public void setOpeningValue(float openingValue) {
+        this.openingValue = openingValue;
+    }
+
+    public void setOpeningValue(String openingValue) {
+        setOpeningValue(Float.parseFloat(openingValue));
+    }
+
+    public float getHighValue() {
+        return highValue;
+    }
+
+    public void setHighValue(float highValue) {
+        this.highValue = highValue;
+    }
+
+    public void setHighValue(String highValue) {
+        setHighValue(Float.parseFloat(highValue));
+    }
+
+    public float getLowValue() {
+        return lowValue;
+    }
+
+    public void setLowValue(float lowValue) {
+        this.lowValue = lowValue;
+    }
+
+    public void setLowValue(String lowValue) {
+        setLowValue(Float.parseFloat(lowValue));
+    }
+
+    public float getChange() {
+        return change;
+    }
+
+    public void setChange(float change) {
+        this.change = change;
+    }
+
+    public void setChange(String change) {
+        setChange(Float.parseFloat(change));
+    }
+
+    public float getVolume() {
+        return volume;
+    }
+
+    public void setVolume(float volume) {
+        this.volume = volume;
+    }
+
+    public void setVolume(String volume) {
+        setVolume(Float.parseFloat(volume));
+    }
+}
+</pre>
+
+<p>The cell renderers assigned to the columns in the WTKX file ensure that the data represented by this class is formatted and presented correctly.</p>
+
+<p>Finally, the query is executed:</p>
+
+<pre class="snippet">
+getQuery.setSerializer(quoteSerializer);
+
+getQuery.execute(new TaskAdapter<Object>(new TaskListener<Object>() {
+    ...
+}
+</pre>
+
+<p>The argument passed to the <tt>execute()</tt> method is a <tt>TaskAdapter</tt> wrapped around an anonymous inner class implementation of <tt>TaskListener&lt;Object>&gt;</tt>. <tt>TaskListener</tt> is an interface defined in the <tt>pivot.util.concurrent</tt> package and serves as a callback handler for asynchronous operations implemented by the <tt>pivot.util.concurrent.Task</tt> class, of which <tt>GetQuery</tt> is a subclass. <tt>TaskAdapter</tt> is defined in the <tt>pivot.wtk</tt> package and ensures that the callback occurs on the UI thread (otherwise, the listener is called in the context of the background thread).</p>
+
+<p><tt>TaskListener</tt> defines two methods:</p>
+
+<p>
+<tt>public void taskExecuted(Task<V> task);</tt><br>
+<tt>public void executeFailed(Task<V> task);</tt><br>
+</p>
+
+<p>The template parameter <tt>V</tt> is defined by the <tt>Task</tt> class and represents the (optional) return value of the operation. The first method is called if the task completes successfully, and the second is called if the task failed for any reason.</p>
+
+<p>StockTracker's success handler is defined as follows:</p>
+
+<pre class="snippet">
+public void taskExecuted(Task&lt;Object&gt; task) {
+    if (task == getQuery) {
+        Sequence&lt;Span&gt; selectedRanges = stocksTableView.getSelectedRanges();
+
+        List&lt;StockQuote&gt; quotes = (List&lt;StockQuote&gt;)task.getResult();
+        stocksTableView.setTableData(quotes);
+
+        if (selectedRanges.getLength() &gt; 0) {
+            stocksTableView.setSelectedRanges(selectedRanges);
+        } else {
+            if (quotes.getLength() &gt; 0) {
+                stocksTableView.setSelectedIndex(0);
+            }
+        }
+
+        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,
+            DateFormat.MEDIUM, Locale.getDefault());
+        lastUpdateLabel.setText(dateFormat.format(new Date()));
+
+        getQuery = null;
+    }
+}
+</pre>
+
+<p>If the source of the event is the currently executing task, the handler does the following:</p>
+
+<ul>
+<li><p>Caches the current selection state of the quote table view</p></li>
+<li><p>Gets the result of the query and casts it to the appropriate type (<tt>List<StockQuote></tt>)</p></li>
+<li><p>Sets the list as the model data for the table view</p></li>
+<li><p>Restores any selection state (which would have been lost when the model data was reset)</p></li>
+<li><p>Updates the value of the "last updated" label to reflect the current time, in a manner appropriate for the current locale</p></li>
+</ul>
+
+<p>In the case of a failure, the handler simply logs the exception to the console:</p>
+
+<pre class="snippet">
+public void executeFailed(Task<Object> task) {
+    if (task == getQuery) {
+        System.out.println(task.getFault());
+        getQuery = null;
+    }
+}
+</pre>
+
+<p>This example demonstrates the use of <tt>GetQuery</tt> only, but Pivot also provides support for HTTP POST, PUT, and DELETE operations using the <tt>PostQuery</tt>, <tt>PutQuery</tt>, and <tt>DeleteQuery</tt> classes, respectively. This makes it very easy to built a complete REST client using Pivot.</p>
+
+<p>Next: <a href="stock_tracker.data_binding.html">Data Binding</a></p>
+</body>
+</html>
+

Added: incubator/pivot/trunk/tutorials/www/stock_tracker/form.png
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/stock_tracker/form.png?rev=794772&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/pivot/trunk/tutorials/www/stock_tracker/form.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/pivot/trunk/tutorials/www/stock_tracker/table_pane.png
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/stock_tracker/table_pane.png?rev=794772&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/pivot/trunk/tutorials/www/stock_tracker/table_pane.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/pivot/trunk/tutorials/www/stock_tracker/table_view.png
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/stock_tracker/table_view.png?rev=794772&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/pivot/trunk/tutorials/www/stock_tracker/table_view.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: incubator/pivot/trunk/tutorials/www/tutorial.css
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/tutorials/www/tutorial.css?rev=794772&r1=794771&r2=794772&view=diff
==============================================================================
--- incubator/pivot/trunk/tutorials/www/tutorial.css (original)
+++ incubator/pivot/trunk/tutorials/www/tutorial.css Thu Jul 16 18:34:28 2009
@@ -1,17 +1,15 @@
 p.caption {
     font-style:italic;
+    padding-top:0px;
 }
 
 p.command {
     padding-left:24px;
 }
 
-pre.java {
+pre.snippet {
+    margin-left:24px;
+    margin-right:24px;
     padding:4px;
-    border:solid 1px #999999;
-}
-
-pre.xml {
-    padding:4px;
-    border:solid 1px #999999;
+    background-color:#eeeeee;
 }