You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2007/05/25 03:02:07 UTC

svn commit: r541497 - in /tapestry/tapestry5/trunk/tapestry-core/src: images/ main/java/org/apache/tapestry/corelib/components/ main/java/org/apache/tapestry/internal/bindings/ main/java/org/apache/tapestry/internal/services/ main/java/org/apache/tapes...

Author: hlship
Date: Thu May 24 18:02:02 2007
New Revision: 541497

URL: http://svn.apache.org/viewvc?view=rev&rev=541497
Log:
TAPESTRY-1373: Recreate T4's Palette component for T5
Add AssetBindingFactory for "asset:" binding prefix
Javascript added to the page via PageRenderSupport.addScript() is now executed from window.onload().

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/images/
    tapestry/tapestry5/trunk/tapestry-core/src/images/deselect.psd   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/images/move_down.psd   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/images/move_up.psd   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/images/select.psd   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Palette.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/AssetBindingFactory.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/Palette.html
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/Palette.properties
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/deselect.png   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/move_down.png   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/move_up.png   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/palette.js
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/select.png   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/deselect.png   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/PaletteDemo.html
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/data/ProgrammingLanguage.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PaletteDemo.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DocumentScriptBuilderImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/util/EnumValueEncoder.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/parameters.apt
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/Start.html
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/add_script.txt

Added: tapestry/tapestry5/trunk/tapestry-core/src/images/deselect.psd
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/images/deselect.psd?view=auto&rev=541497
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/images/deselect.psd
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: tapestry/tapestry5/trunk/tapestry-core/src/images/move_down.psd
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/images/move_down.psd?view=auto&rev=541497
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/images/move_down.psd
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: tapestry/tapestry5/trunk/tapestry-core/src/images/move_up.psd
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/images/move_up.psd?view=auto&rev=541497
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/images/move_up.psd
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: tapestry/tapestry5/trunk/tapestry-core/src/images/select.psd
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/images/select.psd?view=auto&rev=541497
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/images/select.psd
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Palette.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Palette.java?view=auto&rev=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Palette.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Palette.java Thu May 24 18:02:02 2007
@@ -0,0 +1,412 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed 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.
+
+package org.apache.tapestry.corelib.components;
+
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newSet;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tapestry.Asset;
+import org.apache.tapestry.Binding;
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.OptionGroupModel;
+import org.apache.tapestry.OptionModel;
+import org.apache.tapestry.PageRenderSupport;
+import org.apache.tapestry.Renderable;
+import org.apache.tapestry.SelectModel;
+import org.apache.tapestry.ValueEncoder;
+import org.apache.tapestry.annotations.Environmental;
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.annotations.Parameter;
+import org.apache.tapestry.annotations.Path;
+import org.apache.tapestry.corelib.base.AbstractField;
+import org.apache.tapestry.ioc.internal.util.InternalUtils;
+import org.apache.tapestry.services.FormSupport;
+import org.apache.tapestry.services.Request;
+
+/**
+ * Multiple selection component. Generates a UI consisting of two <select> elements configured
+ * for multiple selection; the one on the left is the list of "available" elements, the one on the
+ * right is "selected". Elements can be moved between the lists by clicking a button, or double
+ * clicking an option (and eventually, via drag and drop).
+ * <p>
+ * Much of the look and feel is driven by CSS, the default Tapestry CSS is used to set up the
+ * columns, etc. By default, the &lt;select&gt; element's widths are driven by the length of the
+ * longest &lt;option&gt;, and it is common to override this:
+ * 
+ * <pre>
+ * &lt;style&gt;
+ * DIV.t-palette SELECT { width: 300px; }
+ * &lt;/style&gt;
+ * </pre>
+ */
+public class Palette extends AbstractField
+{
+    // These all started as anonymous inner classes, and were refactored out to here.
+    // I was chasing down one of those perplexing bytecode errors.
+
+    private final class AvailableRenderer implements Renderable
+    {
+        public void render(MarkupWriter writer)
+        {
+            writer.element(
+                    "select",
+                    "id",
+                    getClientId() + ":avail",
+                    "multiple",
+                    "multiple",
+                    "size",
+                    getSize(),
+                    "name",
+                    getElementName() + ":avail");
+
+            writeDisabled(writer, isDisabled());
+
+            for (Renderable r : _availableOptions)
+                r.render(writer);
+
+            writer.end();
+        }
+    }
+
+    private final class OptionGroupEnd implements Renderable
+    {
+        public void render(MarkupWriter writer)
+        {
+            writer.end();
+        }
+    }
+
+    private final class OptionGroupStart implements Renderable
+    {
+        private final OptionGroupModel _model;
+
+        private OptionGroupStart(OptionGroupModel model)
+        {
+            _model = model;
+        }
+
+        public void render(MarkupWriter writer)
+        {
+            writer.element("optgroup", "label", _model.getLabel());
+            writeDisabled(writer, _model.isDisabled());
+
+            writeAttributes(writer, _model.getAttributes());
+        }
+    }
+
+    private final class RenderOption implements Renderable
+    {
+        private final OptionModel _model;
+
+        private RenderOption(OptionModel model)
+        {
+            _model = model;
+        }
+
+        public void render(MarkupWriter writer)
+        {
+            renderOption(writer, _model);
+        }
+    }
+
+    private final class SelectedRenderer implements Renderable
+    {
+        public void render(MarkupWriter writer)
+        {
+            // TODO: Support disabled parameter
+
+            writer.element(
+                    "select",
+                    "id",
+                    getClientId(),
+                    "multiple",
+                    "multiple",
+                    "size",
+                    getSize(),
+                    "name",
+                    getElementName());
+
+            writeDisabled(writer, isDisabled());
+
+            for (Object value : getSelected())
+            {
+                OptionModel model = _valueToOptionModel.get(value);
+
+                renderOption(writer, model);
+            }
+
+            writer.end();
+        }
+    }
+
+    private List<Renderable> _availableOptions;
+
+    /**
+     * The image to use for the deselect button (the default is a left pointing arrow).
+     */
+    @Parameter(value = "asset:deselect.png")
+    private Asset _deselect;
+
+    @Parameter(required = true)
+    private ValueEncoder<Object> _encoder;
+
+    @Parameter(required = true)
+    private SelectModel _model;
+
+    /**
+     * The image to use for the move down button (the default is a downward pointing arrow).
+     */
+    @Parameter(value = "asset:move_down.png")
+    private Asset _moveDown;
+
+    /**
+     * The image to use for the move up button (the default is an upward pointing arrow).
+     */
+    @Parameter(value = "asset:move_up.png")
+    private Asset _moveUp;
+
+    @Inject
+    @Path("palette.js")
+    private Asset _paletteLibrary;
+
+    @Environmental
+    private PageRenderSupport _renderSupport;
+
+    @Inject
+    private Request _request;
+
+    /**
+     * The image to use for the select button (the default is a right pointing arrow).
+     */
+    @Parameter(value = "asset:select.png")
+    private Asset _select;
+
+    /**
+     * The list of selected values from the {@link SelectModel}. This will be updated when the form
+     * is submitted. If the value for the parameter is null, a new list will be created, otherwise
+     * the existing list will be cleared. If unbound, defaults to a property of the container
+     * matching this component's id.
+     */
+    @Parameter(required = true)
+    private List<Object> _selected;
+
+    private List<OptionModel> _selectedOptions;
+
+    private Map<Object, OptionModel> _valueToOptionModel;
+
+    /**
+     * Number of rows to display.
+     */
+    @Parameter(value = "10")
+    private int _size;
+
+    final Binding defaultSelected()
+    {
+        return createDefaultParameterBinding("value");
+    }
+
+    public Renderable getAvailableRenderer()
+    {
+        return new AvailableRenderer();
+    }
+
+    public Asset getDeselect()
+    {
+        return _deselect;
+    }
+
+    public Asset getMoveDown()
+    {
+        return _moveDown;
+    }
+
+    public Asset getMoveUp()
+    {
+        return _moveUp;
+    }
+
+    public Asset getSelect()
+    {
+        return _select;
+    }
+
+    public Renderable getSelectedRenderer()
+    {
+        return new SelectedRenderer();
+    }
+
+    @Override
+    protected void processSubmission(FormSupport formSupport, String elementName)
+    {
+        String values = _request.getParameter(elementName + ":values");
+
+        // Use a couple of local variables to cut down on access via bindings
+
+        List<Object> selected = _selected;
+
+        if (selected == null)
+            selected = newList();
+        else
+            selected.clear();
+
+        ValueEncoder encoder = _encoder;
+
+        if (InternalUtils.isNonBlank(values))
+        {
+            for (String value : values.split(";"))
+            {
+                Object objectValue = encoder.toValue(value);
+
+                selected.add(objectValue);
+            }
+        }
+
+        _selected = selected;
+    }
+
+    private void writeDisabled(MarkupWriter writer, boolean disabled)
+    {
+        if (disabled) writer.attributes("disabled", "disabled");
+    }
+
+    void beginRender(MarkupWriter writer)
+    {
+        String sep = "";
+        StringBuilder selectedValues = new StringBuilder();
+
+        for (OptionModel selected : _selectedOptions)
+        {
+
+            Object value = selected.getValue();
+            String clientValue = _encoder.toClient(value);
+
+            selectedValues.append(sep);
+            selectedValues.append(clientValue);
+
+            sep = ";";
+        }
+
+        String clientId = getClientId();
+
+        _renderSupport.addScriptLink(_paletteLibrary);
+
+        _renderSupport.addScript("new Tapestry.Palette('%s');", clientId);
+
+        writer.element(
+                "input",
+                "type",
+                "hidden",
+                "id",
+                clientId + ":values",
+                "name",
+                getElementName() + ":values",
+                "value",
+                selectedValues);
+        writer.end();
+    }
+
+    boolean beforeRenderBody()
+    {
+        return false;
+    }
+
+    void renderOption(MarkupWriter writer, OptionModel model)
+    {
+        String clientValue = _encoder.toClient(model.getValue());
+
+        writer.element("option", "value", clientValue);
+
+        writeDisabled(writer, model.isDisabled());
+
+        writeAttributes(writer, model.getAttributes());
+
+        writer.write(model.getLabel());
+        writer.end();
+    }
+
+    @SuppressWarnings("unchecked")
+    void setupRender()
+    {
+        _valueToOptionModel = newMap();
+        _availableOptions = newList();
+        _selectedOptions = newList();
+
+        Set selectedSet = newSet(getSelected());
+
+        SelectModel model = _model;
+
+        if (model.getOptionGroups() != null)
+        {
+            for (final OptionGroupModel groupModel : model.getOptionGroups())
+            {
+                _availableOptions.add(new OptionGroupStart(groupModel));
+
+                prerender(groupModel.getOptions(), selectedSet);
+
+                _availableOptions.add(new OptionGroupEnd());
+            }
+        }
+
+        prerender(_model.getOptions(), selectedSet);
+    }
+
+    private void prerender(List<OptionModel> options, Set<Object> selectedSet)
+    {
+        if (options == null) return;
+
+        for (final OptionModel model : options)
+        {
+            Object value = model.getValue();
+
+            boolean isSelected = selectedSet.contains(value);
+
+            if (isSelected)
+            {
+                _selectedOptions.add(model);
+                _valueToOptionModel.put(value, model);
+                continue;
+            }
+
+            _availableOptions.add(new RenderOption(model));
+        }
+    }
+
+    private void writeAttributes(MarkupWriter writer, Map<String, String> attributes)
+    {
+        if (attributes == null) return;
+
+        for (Map.Entry<String, String> e : attributes.entrySet())
+            writer.attributes(e.getKey(), e.getValue());
+    }
+
+    // Avoids a strange Javassist bytecode error, c'est lavie!
+    int getSize()
+    {
+        return _size;
+    }
+
+    List<Object> getSelected()
+    {
+        if (_selected == null) return Collections.emptyList();
+
+        return _selected;
+    }
+}

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/AssetBindingFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/AssetBindingFactory.java?view=auto&rev=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/AssetBindingFactory.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/AssetBindingFactory.java Thu May 24 18:02:02 2007
@@ -0,0 +1,49 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed 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.
+
+package org.apache.tapestry.internal.bindings;
+
+import org.apache.tapestry.Asset;
+import org.apache.tapestry.Binding;
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.ioc.Location;
+import org.apache.tapestry.ioc.Resource;
+import org.apache.tapestry.services.AssetSource;
+import org.apache.tapestry.services.BindingFactory;
+
+/**
+ * Binding factory where the expression is a reference to an asset.
+ * 
+ * @see AssetSource
+ */
+public class AssetBindingFactory implements BindingFactory
+{
+    private final AssetSource _source;
+
+    public AssetBindingFactory(final AssetSource source)
+    {
+        _source = source;
+    }
+
+    public Binding newBinding(String description, ComponentResources container,
+            ComponentResources component, String expression, Location location)
+    {
+        Resource baseResource = container.getBaseResource();
+
+        Asset asset = _source.findAsset(baseResource, expression, container.getLocale());
+
+        return new LiteralBinding(description, asset, location);
+
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DocumentScriptBuilderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DocumentScriptBuilderImpl.java?view=diff&rev=541497&r1=541496&r2=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DocumentScriptBuilderImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DocumentScriptBuilderImpl.java Thu May 24 18:02:02 2007
@@ -64,8 +64,14 @@
             Element e = body.element("script", "type", "text/javascript", "language", "javascript");
             e.raw("\n<!--\n");
 
+            // This assumes that Prototype is available.
+            
+            e.text("Event.observe(window, \"load\", function() {\n");
+            
             e.text(_scriptBlock.toString());
 
+            e.text("});\n");
+            
             e.raw("// -->\n");
         }
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java?view=diff&rev=541497&r1=541496&r2=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java Thu May 24 18:02:02 2007
@@ -924,20 +924,26 @@
      */
     private void invoke(boolean reverse, ComponentCallback callback)
     {
-        // Optimization: In the most general case (just the one component, no mixins)
-        // invoke the callback on the component and be done ... no iterators, no nothing.
+        try
+        { // Optimization: In the most general case (just the one component, no mixins)
+            // invoke the callback on the component and be done ... no iterators, no nothing.
 
-        if (_components == null)
-        {
-            callback.run(_coreComponent);
-            return;
-        }
+            if (_components == null)
+            {
+                callback.run(_coreComponent);
+                return;
+            }
 
-        Iterator<Component> i = reverse ? InternalUtils.reverseIterator(_components) : _components
-                .iterator();
+            Iterator<Component> i = reverse ? InternalUtils.reverseIterator(_components)
+                    : _components.iterator();
 
-        while (i.hasNext())
-            callback.run(i.next());
+            while (i.hasNext())
+                callback.run(i.next());
+        }
+        catch (Exception ex)
+        {
+            throw new TapestryException(ex.getMessage(), getLocation(), ex);
+        }
     }
 
     public boolean isLoaded()

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=541497&r1=541496&r2=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java Thu May 24 18:02:02 2007
@@ -58,6 +58,7 @@
 import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.internal.beaneditor.PrimitiveFieldConstraintGenerator;
 import org.apache.tapestry.internal.beaneditor.ValidateAnnotationConstraintGenerator;
+import org.apache.tapestry.internal.bindings.AssetBindingFactory;
 import org.apache.tapestry.internal.bindings.BlockBindingFactory;
 import org.apache.tapestry.internal.bindings.ComponentBindingFactory;
 import org.apache.tapestry.internal.bindings.LiteralBindingFactory;
@@ -257,13 +258,17 @@
      * to the Alias service to disambiguate. This ensures that a bare parameter (without an
      * InjectService annotation) will chose the correct value without being further qualified.
      * <dl>
-     * <dt>{@link ComponentEventResultProcessor} <dd> the master ComponentEventResultProcessor service
-     * (rather than one of the other services that exist to handle a specific type of result)</li>
-     * <dt>{@link ObjectRenderer} <dd> the master ObjectRenderer service (rather than the one of the
-     * other services that renders a specific type of object)</li>
-     * <dt>{@link ClassFactory} <dd> the <em>ComponentClassFactory</em> (which will be recreated if
-     * the component class loader is recreated, on a change to a component class)
-     * <dt>{@link DataTypeAnalyzer} <dd> the <em>DefaultDataTypeAnalyzer</em> service
+     * <dt>{@link ComponentEventResultProcessor}
+     * <dd> the master ComponentEventResultProcessor service (rather than one of the other services
+     * that exist to handle a specific type of result)</li>
+     * <dt>{@link ObjectRenderer}
+     * <dd> the master ObjectRenderer service (rather than the one of the other services that
+     * renders a specific type of object)</li>
+     * <dt>{@link ClassFactory}
+     * <dd> the <em>ComponentClassFactory</em> (which will be recreated if the component class
+     * loader is recreated, on a change to a component class)
+     * <dt>{@link DataTypeAnalyzer}
+     * <dd> the <em>DefaultDataTypeAnalyzer</em> service
      * </dl>
      */
     public static void contributeAlias(Configuration<AliasContribution> configuration,
@@ -308,12 +313,14 @@
     }
 
     /**
-     * Contributes the factory for serveral built-in binding prefixes ("literal", prop", "block",
-     * "component" "message", "validate", "translate").
+     * Contributes the factory for serveral built-in binding prefixes ("asset", "literal", prop",
+     * "block", "component" "message", "validate", "translate").
      */
     public static void contributeBindingSource(
             MappedConfiguration<String, BindingFactory> configuration,
 
+            AssetSource assetSource,
+
             @InjectService("PropBindingFactory")
             BindingFactory propBindingFactory,
 
@@ -328,6 +335,7 @@
         configuration.add("validate", new ValidateBindingFactory(fieldValidatorSource));
         configuration.add("translate", new TranslateBindingFactory(translatorSource));
         configuration.add("block", new BlockBindingFactory());
+        configuration.add("asset", new AssetBindingFactory(assetSource));
     }
 
     public static void contributeClasspathAssetAliasManager(

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/util/EnumValueEncoder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/util/EnumValueEncoder.java?view=diff&rev=541497&r1=541496&r2=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/util/EnumValueEncoder.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/util/EnumValueEncoder.java Thu May 24 18:02:02 2007
@@ -14,34 +14,34 @@
 
 package org.apache.tapestry.util;
 
+import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
+
 import org.apache.tapestry.ValueEncoder;
-import org.apache.tapestry.ioc.internal.util.Defense;
 
 /**
  * A value encoder that can be used for aribrary Enum types. The enum name is stored as the client
  * side value (the "primary key").
  */
-public class EnumValueEncoder implements ValueEncoder<Enum>
+public class EnumValueEncoder<E extends Enum<E>> implements ValueEncoder<E>
 {
-    private final Class<Enum> _enumType;
+    private final Class<E> _enumType;
 
-    public EnumValueEncoder(final Class<Enum> enumType)
+    public EnumValueEncoder(final Class<E> enumType)
     {
-        Defense.notNull(enumType, "enumType");
+        notNull(enumType, "enumType");
 
         _enumType = enumType;
     }
 
-    public String toClient(Enum value)
+    public String toClient(E value)
     {
         return value.name();
     }
 
     @SuppressWarnings("unchecked")
-    public Enum toValue(String clientValue)
+    public E toValue(String clientValue)
     {
-        if (clientValue == null)
-            return null;
+        if (clientValue == null) return null;
 
         return Enum.valueOf(_enumType, clientValue);
     }

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/Palette.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/Palette.html?view=auto&rev=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/Palette.html (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/Palette.html Thu May 24 18:02:02 2007
@@ -0,0 +1,25 @@
+<div class="t-palette" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+  <div class="t-palette-available">
+    <div class="t-palette-title">${message:available-label}</div>
+    <t:delegate to="availableRenderer"/>
+  </div>
+  <div class="t-palette-controls">
+    <button id="${clientId}:select" disabled="disabled">
+      <img src="${select}" alt="${message:select-label}"/>
+    </button>
+    <button id="${clientId}:deselect" disabled="disabled">
+      <img src="${deselect}" alt="${message:deselect-label}"/>
+    </button>
+    <button id="${clientId}:up" disabled="disabled">
+      <img src="${moveUp}" alt="${message:up-label}"/>
+    </button>
+    <button id="${clientId}:down" disabled="disabled">
+      <img src="${moveDown}" alt="${message:down-label}"/>
+    </button>
+  </div>
+  <div class="t-palette-selected">
+    <div class="t-palette-title">${message:selected-label}</div>
+    <t:delegate to="selectedRenderer"/>
+  </div>
+  <div class="t-palette-spacer"/>    
+</div>

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/Palette.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/Palette.properties?view=auto&rev=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/Palette.properties (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/Palette.properties Thu May 24 18:02:02 2007
@@ -0,0 +1,21 @@
+# Copyright 2007 The Apache Software Foundation
+#
+# Licensed 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.
+
+available-label=Available
+selected-label=Selected
+
+select-label=Select >
+deselect-label=< Deselect
+up-label=Move Up
+down-label=Move Down

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/deselect.png
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/deselect.png?view=auto&rev=541497
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/deselect.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/move_down.png
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/move_down.png?view=auto&rev=541497
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/move_down.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/move_up.png
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/move_up.png?view=auto&rev=541497
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/move_up.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/palette.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/palette.js?view=auto&rev=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/palette.js (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/palette.js Thu May 24 18:02:02 2007
@@ -0,0 +1,150 @@
+Tapestry.Palette = Class.create();
+
+Tapestry.Palette.prototype = {
+
+  // TODO: Make Move Up/Move Down optional (via a subclass?)
+  initialize : function(id) {
+    // The two selects:
+    
+	  this.avail = $(id + ":avail");
+	  this.selected = $(id);
+	  
+	  this.hidden = $(id + ":values");
+	  
+	  // Seperator used for values in the hidden field.
+	  this.sep = ";";
+	  
+	  // The four BUTTON elements:
+	  this.select = $(id + ":select");
+	  this.deselect = $(id + ":deselect");
+	  this.up = $(id + ":up");
+	  this.down = $(id + ":down");
+	  
+	  this.bindEvents();   
+  },  
+
+  bindEvents : function() {
+    var updateButtons = this.updateButtons.bindAsEventListener(this);
+    Event.observe(this.avail, "change", updateButtons);
+    Event.observe(this.selected, "change", updateButtons);
+    
+    var selectClicked = this.selectClicked.bindAsEventListener(this);
+    Event.observe(this.select, "click", selectClicked);
+    Event.observe(this.avail, "dblclick", selectClicked);
+          
+    var deselectClicked = this.deselectClicked.bindAsEventListener(this);      
+    Event.observe(this.deselect, "click", deselectClicked);
+    Event.observe(this.selected, "dblclick", deselectClicked);
+    
+    Event.observe(this.up, "click", this.moveUpClicked.bindAsEventListener(this));
+    Event.observe(this.down, "click", this.moveDownClicked.bindAsEventListener(this));
+  },
+  
+  updateButtons: function() {
+    this.select.disabled = this.avail.selectedIndex < 0;
+    
+    var nothingSelected = this.selected.selectedIndex < 0;
+    
+    this.deselect.disabled = nothingSelected;
+    this.up.disabled = nothingSelected || this.allSelectionsAtTop();
+    this.down.disabled = nothingSelected || this.allSelectionsAtBottom();
+  },  
+  
+  indexOfLastSelection : function(select) {
+    if (select.selectedIndex < 0) return -1;
+    
+    for (var i = select.options.length - 1; i >= select.selectedIndex; i--) {
+      if (select.options[i].selected) return i;
+    }
+    
+    return -1;
+  },
+  
+  allSelectionsAtTop: function() {
+    var last = this.indexOfLastSelection(this.selected);
+    var options = $A(this.selected.options);
+    
+    return ! options.slice(0, last).any(function (o) { return ! o.selected; });
+  },
+  
+  allSelectionsAtBottom : function() {
+    var options = $A(this.selected.options);
+
+    // Make sure that all elements from the (first) selectedIndex to the end are also selected.     
+    return options.slice(this.selected.selectedIndex).all(function(o) { return o.selected; });  
+  },
+  
+  selectClicked : function(event) {
+     this.transferOptions(this.avail, this.selected);
+  },
+  
+  deselectClicked : function(event) {
+     this.transferOptions(this.selected, this.avail);
+  }, 
+  
+  transferOptions : function (from, to) {
+    
+    var toOptions = $A(to.options);
+    var lastSelected = this.indexOfLastSelection(to);
+    var before = lastSelected < 0 ? null : toOptions[toOptions.indexOf(lastSelected) + 1];
+    
+    toOptions.each(function(option) { option.selected = false; });
+        
+    var movers = this.removeSelectedOptions(from);
+    this.moveOptions(movers, to, before);
+    
+  },
+  
+  updateHidden : function() {
+    // Every value in the selected list (whether enabled or not) is combined to form the value.
+    var values = $A(this.selected).map(function(o) { return o.value; });
+    
+    this.hidden.value = values.join(this.sep);
+  },
+  
+  moveUpClicked : function(event) {
+    var pos = this.selected.selectedIndex - 1;
+    var movers = this.removeSelectedOptions(this.selected);
+
+    var before = pos < 0 ? this.selected.options[0] : this.selected.options[pos];
+ 
+    this.moveOptions(movers, this.selected, before);
+    
+    Event.stop(event);
+  },
+  
+  removeSelectedOptions : function(select) {
+    var movers = [];
+    var options = select.options;
+    
+    for (var i = select.selectedIndex; i < select.length; i++) {
+      var option = options[i];
+      if (option.selected) {
+        select.remove(i--);
+        movers.push(option);  
+      }          
+    }
+    
+    return movers;
+  },
+  
+  moveOptions : function(movers, to, before) {
+    movers.each(function(option) { to.add(option, before); }.bind(this));
+    
+    this.updateHidden();  
+    this.updateButtons();
+  },
+  
+  moveDownClicked : function(event) {
+    var lastSelected = $A(this.selected.options).reverse(true).find(function (option) { return option.selected; });
+    var lastPos = lastSelected.index;
+    var before = this.selected.options[lastPos + 2];
+        
+    this.moveOptions(this.removeSelectedOptions(this.selected), this.selected, before);
+    
+    Event.stop(event);
+  }
+};
+
+
+

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/select.png
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/select.png?view=auto&rev=541497
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/select.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css?view=diff&rev=541497&r1=541496&r2=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css Thu May 24 18:02:02 2007
@@ -1,80 +1,61 @@
 /* Tapestry styles all start with "t-" */
-
 DIV.t-error {
-    border: 1px solid red;
-    padding: 0px;
-    margin: 4px 0px;
+  border: 1px solid red;
+  padding: 0px;
+  margin: 4px 0px;
 }
 DIV.t-error DIV {
-    padding: 2px;
-    display: block;
-    margin: 0px;
-    background-color: red;
-    color: white;
-    font-weight: bold;
+  padding: 2px;
+  display: block;
+  margin: 0px;
+  background-color: red;
+  color: white;
+  font-weight: bold;
 }
 DIV.t-error UL {
-    margin: 2px 0px;
-    background-color:white;
-    color:red;
+  margin: 2px 0px;
+  background-color:white;
+  color:red;
 }
 DIV.t-error LI {
-    margin-left: -20px;
+  margin-left: -20px;
 }
 .t-invisible {
-    display: none;
+  display: none;
 }
-
-LABEL.t-error
-{
+LABEL.t-error {
   color:red;
 }
-
-INPUT.t-error, TEXTAREA.t-error
-{
-    border-color: red;
-    font-style: italic;
-    color: red;
-}
-
-IMG.t-error-icon
-{
-	margin-left: 4px;
-}
-
-DIV.t-exception-message
-{
+INPUT.t-error, TEXTAREA.t-error {
+  border-color: red;
+  font-style: italic;
+  color: red;
+}
+IMG.t-error-icon {
+  margin-left: 4px;
+}
+DIV.t-exception-message {
   font-style: italic;
   font-size: 12pt;
   border: thin dotted silver;
   margin: 5px 0px;
   padding: 3px;
-} 
-
-DIV.t-exception-report, DIV.t-env-data
-{
-  font-family: "Trebuchet MS", Arial, sans-serif; 
-}
-
-DIV.t-exception-report LI
-{ 
+}
+DIV.t-exception-report, DIV.t-env-data {
+  font-family: "Trebuchet MS", Arial, sans-serif;
+}
+DIV.t-exception-report LI {
   margin-left: -40px;
 }
-
-DIV.t-exception-report DT, DIV.t-env-data DT
-{
+DIV.t-exception-report DT, DIV.t-env-data DT {
   color:green;
   padding-left: 2px;
   background-color: #FFFFCF;
 }
-
-DIV.t-exception-report LI
-{
+DIV.t-exception-report LI {
   list-style: none;
 }
-
-SPAN.t-exception-class-name
-{
+SPAN.t-exception-class-name {
   display: block;
   margin-top: 15px;
   font-size: 12pt;
@@ -83,79 +64,53 @@
   padding: 2px 3px;
   font-weight: bold;
 }
-
-UL.t-stack-trace LI
-{
+UL.t-stack-trace LI {
   font-family: Monaco, Times, monospace;
   font-size: 10pt;
   margin-left: -25px;
   list-style: square;
 }
-
-H1.t-exception-report
-{
-  font-family: "Trebuchet MS", Arial, sans-serif; 
+H1.t-exception-report {
+  font-family: "Trebuchet MS", Arial, sans-serif;
   color: red;
 }
-
-DIV.t-exception-report DT:after
-{
+DIV.t-exception-report DT:after {
   content: ":";
 }
-
-DIV.t-exception-report DD, DIV.t-env-data DD
-{
+DIV.t-exception-report DD, DIV.t-env-data DD {
   margin-left: 10px;
 }
-
-
-TABLE.t-data-table
-{
-  border-collapse: collapse;	
+TABLE.t-data-table {
+  border-collapse: collapse;
   margin: 0px;
-  padding: 2px; 
+  padding: 2px;
 }
-
-
-TABLE.t-data-table TH
-{
+TABLE.t-data-table TH {
   background-color: black;
   color: white;
 }
-
-TABLE.t-data-table TD
-{
+TABLE.t-data-table TD {
   border: 1px solid silver;
   margin: 0px;
 }
-
-DIV.t-beaneditor
-{
+DIV.t-beaneditor {
   display: block;
   background: #ffc;
   border: 2px solid silver;
   padding: 2px;
-  font-family: "Trebuchet MS", Arial, sans-serif; 
+  font-family: "Trebuchet MS", Arial, sans-serif;
 }
-
-FORM.t-beaneditor LABEL:after
-{
+FORM.t-beaneditor LABEL:after {
   content: ":";
 }
-
-DIV.t-beaneditor-row
-{
+DIV.t-beaneditor-row {
   padding: 4px 0px 2px 0px;
 }
-
-DIV.t-beaneditor LABEL:after
-{
+DIV.t-beaneditor LABEL:after {
   vertical-align: middle;
   content: ":";
 }
-
-DIV.t-beaneditor LABEL
-{
+DIV.t-beaneditor LABEL {
   width: 10%;
   display: block;
   float: left;
@@ -163,47 +118,33 @@
   clear: left;
   padding-right: 3px;
 }
-
-TABLE.t-data-grid THEAD TR
-{
+TABLE.t-data-grid THEAD TR {
   color: white;
   background-color: #809FFF;
 }
-
-TABLE.t-data-grid THEAD TR TH
-{
+TABLE.t-data-grid THEAD TR TH {
   text-align: left;
   padding: 3px;
   white-space: nowrap;
   border-right: 1px solid silver;
   border-bottom: 1px solid silver;
 }
-
-TABLE.t-data-grid
-{
+TABLE.t-data-grid {
   border-collapse: collapse;
   border-left: 1px solid silver;
 }
-
-TABLE.t-data-grid TBODY TR TD
-{
+TABLE.t-data-grid TBODY TR TD {
   border-right: 1px solid silver;
   border-bottom: 1px solid silver;
   padding: 2px;
 }
-
-DIV.t-data-grid
-{
-  font-family: "Trebuchet MS", Arial, sans-serif; 
-}
-
-DIV.t-data-grid-pager
-{
+DIV.t-data-grid {
+  font-family: "Trebuchet MS", Arial, sans-serif;
+}
+DIV.t-data-grid-pager {
   margin: 8px 0px;
 }
-
-DIV.t-data-grid-pager A, DIV.t-data-grid-pager SPAN.current
-{
+DIV.t-data-grid-pager A, DIV.t-data-grid-pager SPAN.current {
   text-decoration: none;
   color: black;
   padding: 2px 5px;
@@ -211,97 +152,67 @@
   border: 1px solid silver;
   margin-right: 5px;
 }
-
-DIV.t-data-grid-pager A:hover
-{
+DIV.t-data-grid-pager A:hover {
   border: 1px solid black;
 }
-
-DIV.t-data-grid-pager SPAN.current
-{
+DIV.t-data-grid-pager SPAN.current {
   color: white;
   background-color: #809FFF;
 }
-
-TABLE.t-data-grid TR TH A
-{
+TABLE.t-data-grid TR TH A {
   color: white;
 }
-
-IMG
-{
+IMG {
   border: none;
 }
-
-
-DIV.t-env-data-section
-{
+DIV.t-env-data-section {
   padding-left: 5px;
 }
-
-DIV.t-env-data DD, DIV.t-exception-report DD
-{
+DIV.t-env-data DD, DIV.t-exception-report DD {
   margin-left: 25px;
   margin-bottom: 10px;
 }
-
-DIV.t-env-data LI
-{
+DIV.t-env-data LI {
   margin-left: -25px;
 }
-
-DIV.t-env-data-section
-{
+DIV.t-env-data-section {
   font-size: 12pt;
   background-color: #E1E1E1;
   color: blue;
   padding: 2px 3px;
   font-weight: bold;
 }
-
-TABLE.t-location-outer
-{
+TABLE.t-location-outer {
   padding: 5px;
   border-collapse: collapse;
   border: 1px solid black;
   width: 100%;
-} 
-
-TD.t-location-line
-{
+}
+TD.t-location-line {
   width: 40px;
   text-align: right;
   padding: 0px;
   background-color: #E1E1E1;
-  padding-right: 3px; 
+  padding-right: 3px;
   border-right: 1px solid black;
 }
-
-TD.t-location-content
-{
+TD.t-location-content {
   border-top: 1px solid silver;
   border-right: 1px solid black;
   white-space: pre;
 }
-
-TD.t-location-current
-{
+TD.t-location-current {
   background-color: #FFFFCF;
 }
-
-TD.t-location-content-first
-{
+TD.t-location-content-first {
   border-top: 1px solid black;
 }
-
 DIV.t-palette {
   display: inline;
 }
-
 DIV.t-palette SELECT {
   margin-bottom: 2px;
 }
-
 DIV.t-palette-title {
   color: white;
   background-color: #809FFF;
@@ -310,33 +221,26 @@
   margin-bottom: 3px;
   display: block;
 }
-
-
 DIV.t-palette-available {
   float: left;
 }
-
-DIV.t-palette-controls { 
-    margin: 0px 5px;
-	width: 64px;
-	float: left;
-	text-align: center;
-}
-
-DIV.t-palette-controls BUTTON { 
-  width: 64px;
+DIV.t-palette-controls {
+  margin: 5px 5px; 
+  float: left;
+  text-align: center;
 }
-
-DIV.t-palette-controls BUTTON[disabled] IMG  {
+DIV.t-palette-controls BUTTON {
+  display:block;
+  margin-bottom: 3px;
+}
+DIV.t-palette-controls BUTTON[disabled] IMG {
   filter: alpha(opacity=25);
   -moz-opacity: .25;
 }
-
 DIV.t-palette-selected {
   float: left;
   clear: right;
 }
-
 DIV.t-palette-spacer {
   clear: left;
-}
\ No newline at end of file
+}

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/deselect.png
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/deselect.png?view=auto&rev=541497
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/deselect.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js?view=diff&rev=541497&r1=541496&r2=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js Thu May 24 18:02:02 2007
@@ -48,8 +48,6 @@
         }     
       });
 
-// window.alert("result = " + event.result);
-
 	  // On a failure result, display the error div.
 	  
 	  if (form.errorDiv) {
@@ -184,7 +182,6 @@
 Tapestry.FieldEventManager.prototype = {
 
   initialize : function(field) {
-  
     $(field).fieldEventManager = this;
   
     this.validators = [ ];
@@ -204,7 +201,6 @@
   // any subsequent validators for that field are skipped.
   
   addValidator : function(acceptBlank, validator) {
-  
     this.validators.push([ acceptBlank, validator]);
   },
 
@@ -249,15 +245,12 @@
   	    this.label.addClassName("t-error");
   	}
   	
-  	if (this.icon) {
-  	  if (event.error && ! this.icon.visible()) {
-  	    new Effect.Appear(this.icon);
-	  }
-	  else if (! event.error && this.icon.visible()) {
-		this.icon.hide();
-      }
-  	}
-  	
+  	if (! this.icon) return;
+  
+   	if (event.error && ! this.icon.visible()) { new Effect.Appear(this.icon); }
+   	else if (! event.error && this.icon.visible()) { this.icon.hide(); }
   }
 };
+
+
  

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/parameters.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/parameters.apt?view=diff&rev=541497&r1=541496&r2=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/parameters.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/parameters.apt Thu May 24 18:02:02 2007
@@ -115,6 +115,8 @@
 *------------+----------------------------------------------------------------------------------+
 | <<Prefix>> | <<Description>>                                                                  |
 *------------+----------------------------------------------------------------------------------+
+| asset      | The relative path to an asset file (which must exist). |
+*------------+----------------------------------------------------------------------------------+
 | block      | The id of a block within the template. |
 *------------+----------------------------------------------------------------------------------+
 | component  | The id of another component within the same template.                            |

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt?view=diff&rev=541497&r1=541496&r2=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt Thu May 24 18:02:02 2007
@@ -13,6 +13,10 @@
   Progress on Tapestry 5 is really taking off. This space lists some cool new features that have been added
   recently.
   
+  * Palette component for sophisticated multiple-property selection and ordering.
+  
+  * New "asset:" binding prefix to allow asset files to be bound to parameters.
+  
   * Template expansions are now allowed inside attributes.
   
   * Applications may optionally provide a global message catalog (which is searched when a page or component message catalog

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/PaletteDemo.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/PaletteDemo.html?view=auto&rev=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/PaletteDemo.html (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/PaletteDemo.html Thu May 24 18:02:02 2007
@@ -0,0 +1,21 @@
+<html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+
+  <style>
+    DIV.t-palette SELECT { width: 300px; }
+  </style>
+
+  <h1>Palette Demo</h1>
+
+
+  <t:form>
+    <div class="t-beaneditor">
+      <t:palette t:id="languages" model="languageModel" encoder="languageEncoder"/>
+      <br/>
+      <input type="submit"/>
+    </div>
+  </t:form>
+  
+  <p>
+    Selected Languages: ${languages}
+  </p>
+</html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/Start.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/Start.html?view=diff&rev=541497&r1=541496&r2=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/Start.html (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/Start.html Thu May 24 18:02:02 2007
@@ -62,11 +62,6 @@
           <li>
             <a t:type="PageLink" page="PasswordFieldDemo">PasswordFieldDemo</a> -- test for the
             PasswordField component </li>
-        </ul>
-      </td>
-      <td>
-        <ul>
-
           <li>
             <a t:type="PageLink" page="RenderComponentDemo">RenderComponentDemo</a> -- components
             that "nominate" other components to render </li>
@@ -76,7 +71,12 @@
           <li>
             <a t:type="PageLink" page="ToDoListVolatile">ToDo List (Volatile)</a> -- Loops and
             Submit inside Form, volatile mode </li>
-          <li>
+        </ul>
+      </td>
+      <td>
+        <ul>
+
+         <li>
             <a t:type="PageLink" page="ToDoList">ToDo List</a> -- Loops and Submit inside Form using
             a primary key encoder </li>
           <li>
@@ -136,6 +136,9 @@
           </li>
           <li>
             <t:pagelink page="attributeExpansionsDemo">Attribute Expansions Demo</t:pagelink> -- use expansions inside attributes of ordinary elements
+          </li>
+          <li>
+            <t:pagelink page="PaletteDemo">Palette Demo</t:pagelink> -- multiple selection component
           </li>
         </ul>
       </td>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?view=diff&rev=541497&r1=541496&r2=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java Thu May 24 18:02:02 2007
@@ -31,7 +31,7 @@
  * my system, Skype is listening on localhost:80.
  */
 @Test(timeOut = 50000, sequential = true, groups =
-{ "integration" }, enabled = true)
+{ "integration" })
 public class IntegrationTests extends AbstractIntegrationTestSuite
 {
     @Test
@@ -944,5 +944,47 @@
         // An unrelated test, but fills in a bunch of minor gaps.
 
         assertSourcePresent("<!-- A comment! -->");
+    }
+
+    @Test
+    public void palette_component()
+    {
+        open(BASE_URL);
+        clickAndWait("link=Palette Demo");
+
+        addSelection("languages:avail", "label=Haskell");
+        addSelection("languages:avail", "label=Javascript");
+        click("languages:select");
+
+        clickAndWait("//input[@type='submit']");
+        assertTextPresent("Selected Languages: [HASKELL, JAVASCRIPT]");
+
+        addSelection("languages", "label=Javascript");
+        click("languages:deselect");
+
+        addSelection("languages:avail", "label=Perl");
+        removeSelection("languages:avail", "label=Javascript");
+        addSelection("languages:avail", "label=Erlang");
+        addSelection("languages:avail", "label=Java");
+        addSelection("languages:avail", "label=Lisp");
+        addSelection("languages:avail", "label=Ml");
+        addSelection("languages:avail", "label=Python");
+        addSelection("languages:avail", "label=Ruby");
+
+        click("languages:select");
+
+        removeSelection("languages", "label=Perl");
+        removeSelection("languages", "label=Erlang");
+        removeSelection("languages", "label=Java");
+        removeSelection("languages", "label=Lisp");
+        removeSelection("languages", "label=Ml");
+        removeSelection("languages", "label=Python");
+
+        for (int i = 0; i < 7; i++)
+            click("languages:up");
+
+        clickAndWait("//input[@type='submit']");
+
+        assertTextPresent("Selected Languages: [RUBY, HASKELL, PERL, ERLANG, JAVA, LISP, ML, PYTHON]");
     }
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/data/ProgrammingLanguage.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/data/ProgrammingLanguage.java?view=auto&rev=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/data/ProgrammingLanguage.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/data/ProgrammingLanguage.java Thu May 24 18:02:02 2007
@@ -0,0 +1,20 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed 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.
+
+package org.apache.tapestry.integration.app1.data;
+
+public enum ProgrammingLanguage
+{
+    ADA, ASSEMBLY, C, PERL, ERLANG, HASKELL, JAVA, JAVASCRIPT, LISP, ML, PYTHON, RUBY, SCALA, SCHEME
+}

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PaletteDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PaletteDemo.java?view=auto&rev=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PaletteDemo.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PaletteDemo.java Thu May 24 18:02:02 2007
@@ -0,0 +1,56 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed 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.
+
+package org.apache.tapestry.integration.app1.pages;
+
+import java.util.List;
+
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.SelectModel;
+import org.apache.tapestry.ValueEncoder;
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.annotations.Persist;
+import org.apache.tapestry.integration.app1.data.ProgrammingLanguage;
+import org.apache.tapestry.util.EnumSelectModel;
+import org.apache.tapestry.util.EnumValueEncoder;
+
+public class PaletteDemo
+{
+    @Inject
+    private ComponentResources _resources;
+
+    @Persist
+    private List<ProgrammingLanguage> _languages;
+
+    public List<ProgrammingLanguage> getLanguages()
+    {
+        return _languages;
+    }
+
+    public void setLanguages(List<ProgrammingLanguage> selected)
+    {
+        _languages = selected;
+    }
+
+    public SelectModel getLanguageModel()
+    {
+        return new EnumSelectModel(ProgrammingLanguage.class, _resources.getMessages());
+    }
+
+    @SuppressWarnings("unchecked")
+    public ValueEncoder getLanguageEncoder()
+    {
+        return new EnumValueEncoder(ProgrammingLanguage.class);
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/add_script.txt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/add_script.txt?view=diff&rev=541497&r1=541496&r2=541497
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/add_script.txt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/add_script.txt Thu May 24 18:02:02 2007
@@ -1,6 +1,8 @@
 <html><body><p>Ready to be updated with scripts.</p><script language="javascript" type="text/javascript">
 <!--
+Event.observe(window, "load", function() {
 doSomething();
 doSomethingElse();
+});
 // -->
 </script></body></html>