You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2013/06/11 02:38:33 UTC
git commit: Add events to Palette component so that client-side can
choose to accept or veto a change to the selection
Updated Branches:
refs/heads/master f02a205eb -> 53e056052
Add events to Palette component so that client-side can choose to accept or veto a change to the selection
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/53e05605
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/53e05605
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/53e05605
Branch: refs/heads/master
Commit: 53e056052e17d6e719b40815e5fd0be3a394ef0a
Parents: f02a205
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Mon Jun 10 17:38:29 2013 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Mon Jun 10 17:38:29 2013 -0700
----------------------------------------------------------------------
54_RELEASE_NOTES.txt | 7 +
.../META-INF/modules/t5/core/events.coffee | 11 ++
.../META-INF/modules/t5/core/palette.coffee | 181 +++++++++++++------
.../tapestry5/corelib/components/Palette.java | 8 +-
.../resources/META-INF/assets/core/Palette.css | 18 +-
.../tapestry5/corelib/components/Palette.tml | 14 +-
tapestry-core/src/test/app1/PaletteDemo.tml | 7 +-
.../META-INF/modules/palette-demo.coffee | 5 +
.../tapestry5/integration/app1/FormTests.java | 8 +-
.../integration/app1/PaletteTests.java | 28 +--
.../integration/app1/pages/PaletteDemo.java | 4 +-
11 files changed, 197 insertions(+), 94 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/53e05605/54_RELEASE_NOTES.txt
----------------------------------------------------------------------
diff --git a/54_RELEASE_NOTES.txt b/54_RELEASE_NOTES.txt
index f05b58c..28f7e40 100644
--- a/54_RELEASE_NOTES.txt
+++ b/54_RELEASE_NOTES.txt
@@ -268,3 +268,10 @@ org.apache.tapestry5.test.TapestryRunnerConstants in the new tapestry-runner mod
## AbstractValidator base class
The constructor for AbstractValidator has changed to include an instance of JavaScriptSupport.
+
+## CSS Changes
+
+Where Tapestry-specific CSS still exists (in support of the Palette component and the Tree component), the "t-" prefix
+has been removed. This may affect applications that overrode the Tapestry CSS rules to adapt Tapestry to the application
+look and feel.
+
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/53e05605/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/events.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/events.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/events.coffee
index bc9ca33..4054520 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/events.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/events.coffee
@@ -124,6 +124,17 @@ define
# * If the field's container has class "input-append" or "input-prepend", then the block is inserted after the container
showValidationError: "t5:field:show-validation-error"
+ # Events triggered by the Palette component.
+ palette:
+ # Event triggered when the selection is about to change. The memo object has these properties:
+ # * selectedValues - list of selected values (if change is allowed)
+ # * reorder - if true, then the event represents changing the ordrer of the selections only
+ # * cancel - function to invoke to prevent the change to the Palette from occurring
+ willChange: "t5:palette:willChange"
+ # Event triggered after the selection has changed. The memo object has one property:
+ # * selectedValues - list of selected values
+ didChange: "t5:palette:didChange"
+
# Defines a number of event names specific to Tapestry Zones. Zones are Tapestry components that are structured
# to correctly support dynamic updates from the server via an Ajax request, and a standard response
# (the partial page render reponse). More details are available in the `t5/core/zone` module.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/53e05605/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/palette.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/palette.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/palette.coffee
index b03163e..9f8cc4c 100644
--- a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/palette.coffee
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/palette.coffee
@@ -1,4 +1,4 @@
-# Copyright 2012 The Apache Software Foundation
+# Copyright 2012-2013 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.
@@ -15,14 +15,17 @@
# ## t5/core/palette
#
# Support for the `core/Palette` component.
-define ["./dom", "underscore"],
- (dom, _) ->
+define ["./dom", "underscore", "./events"],
+ (dom, _, events) ->
+
+ isSelected = (option) -> option.selected
+
class PaletteController
constructor: (id) ->
@selected = (dom id)
- @container = @selected.findParent ".t-palette"
- @available = @container.findFirst ".t-palette-available select"
+ @container = @selected.findParent ".palette"
+ @available = @container.findFirst ".palette-available select"
@hidden = @container.findFirst "input[type=hidden]"
@select = @container.findFirst "[data-action=select]"
@@ -69,6 +72,8 @@ define ["./dom", "underscore"],
for option in movers
@selected.element.add option
+ # Invoked after any change to the selections list to update the hidden field as well as the
+ # buttons' state.
updateAfterChange: ->
@updateHidden()
@updateButtons()
@@ -107,6 +112,8 @@ define ["./dom", "underscore"],
@doMoveDown()
return false
+ # Invoked whenever the selections in either list changes or after an updates; figures out which buttons
+ # should be enabled and which disabled.
updateButtons: ->
@select.element.disabled = @available.element.selectedIndex < 0
@@ -123,78 +130,139 @@ define ["./dom", "underscore"],
doDeselect: -> @transferOptions @selected, @available, false
doMoveUp: ->
- e = @selected.element
- pos = e.selectedIndex - 1
- movers = @removeSelectedOptions @selected
- before = e.options[if pos < 0 then 0 else pos]
+ options = _.toArray @selected.element.options
+
+ movers = _.filter options, isSelected
+
+ # The element before the first selected element is the pivot; all the selected elements will
+ # move before the pivot. If there is no pivot, the elements are shifted to the front of the list.
+ firstMoverIndex= _.first(movers).index
+ pivot = options[firstMoverIndex - 1]
+
+ options = _.reject options, isSelected
+
+ splicePos = if pivot then _.indexOf options, pivot else 0
+
+ movers.reverse()
+
+ for o in movers
+ options.splice splicePos, 0, o
+
+ @reorderSelected options
- @reorderOptions movers, before
doMoveDown: ->
- e = @selected.element
- lastSelected = _.chain(e.options).toArray().reverse().find((o) -> o.selected).value()
+ options = _.toArray @selected.element.options
- lastPos = lastSelected.index
- before = e.options[lastPos + 2]
+ movers = _.filter options, isSelected
- movers = @removeSelectedOptions @selected
+ # The element after the last selected element is the pivot; all the selected elements will
+ # move after the pivot. If there is no pivot, the elements are shifted to the end of the list.
+ lastMoverIndex = _.last(movers).index
+ pivot = options[lastMoverIndex + 1]
- @reorderOptions movers, before
+ options = _.reject options, isSelected
- reorderOptions: (movers, before) ->
- for mover in movers
- @addOption @selected, mover, before
- @updateAfterChange()
+ splicePos = if pivot then _.indexOf(options, pivot) + 1 else options.length
+
+ movers.reverse()
+
+ for o in movers
+ options.splice splicePos, 0, o
+
+ @reorderSelected options
+
+ # Reorders the selected options to the provided list of options; handles triggering the willUpdate and
+ # didUpdate events.
+ reorderSelected: (options) ->
+
+ canceled = false
+
+ memo =
+ selectedValues: _.pluck options, "value"
+ reorder: true
+ cancel: -> canceled = true
+
+ @selected.trigger events.palette.willChange, memo
+
+ unless canceled
+ @deleteOptions @selected
+
+ for o in options
+ @selected.element.add o, null
+
+ @selected.trigger events.palette.didChange, memo
+
+ @updateAfterChange()
+
+ # Deletes all options from a select (an ElementWrapper), prior to new options being populated in.
+ deleteOptions: (select) ->
+
+ e = select.element
+
+ for i in [(e.length - 1)..0] by -1
+ e.remove i
+
+ # Moves options between the available and selected lists, including event notifiations before and after.
transferOptions: (from, to, atEnd) ->
+
if from.element.selectedIndex is -1
return
- _(to.element.options).each (o) -> o.selected = false
+ # This could be done in a single pass, but:
+ movers = _.filter from.element.options, isSelected
+ fromOptions = _.reject from.element.options, isSelected
- movers = @removeSelectedOptions from
+ toOptions = _.toArray to.element.options
- @moveOptions movers, to, atEnd
+ for o in movers
+ @insertOption toOptions, o, atEnd
- removeSelectedOptions: (select) ->
- movers = []
- e = select.element
- options = e.options
+ selectedOptions = if to is @selected then toOptions else fromOptions
- for i in [(e.length - 1)..(e.selectedIndex)] by -1
- o = options[i]
- if o.selected
- e.remove i
- movers.unshift o
+ canceled = false
+
+ memo =
+ selectedValues: _.pluck selectedOptions, "value"
+ reorder: false
+ cancel: -> canceled = true
+
+ @selected.trigger events.palette.willChange, memo
+
+ return if canceled
+
+ # Remove the movers (the selected from elements):
+ for i in [(from.element.length - 1)..0] by -1
+ if from.element.options[i].selected
+ from.element.remove i
+
+ # A bit ugly: update the to select by removing all, then adding back in.
- return movers
+ for i in [(to.element.length - 1)..0] by -1
+ to.element.options[i].selected = false
+ to.element.remove i
- moveOptions: (movers, to, atEnd) ->
- _.each movers, (o) =>
- @moveOption o, to, atEnd
+ for o in toOptions
+ to.element.add o, null
+
+ @selected.trigger events.palette.didChange, memo
@updateAfterChange()
- moveOption: (option, to, atEnd) ->
- before = null
+
+ insertOption: (options, option, atEnd) ->
unless atEnd
optionOrder = @valueToOrderIndex[option.value]
- candidate = _.find to.element.options, (o) => @valueToOrderIndex[o.value] > optionOrder
- if candidate
- before = candidate
-
- @addOption to, option, before
-
- addOption: (to, option, before) ->
- try
- to.element.add option, before
- catch ex
- if before is null
- # IE throws an exception about type mismatch; here's the fix:
- to.add option
- else
- to.add option, before.index
+ before = _.find options, (o) => @valueToOrderIndex[o.value] > optionOrder
+
+ if before
+ i = _.indexOf options, before
+ options.splice i, 0, option
+ else
+ options.push option
+
indexOfLastSelection: (select) ->
e = select.element
@@ -221,8 +289,5 @@ define ["./dom", "underscore"],
_(options[last..]).all (o) -> o.selected
- initialize = (id) ->
- new PaletteController(id)
-
- # Export just the initialize function
- return initialize
\ No newline at end of file
+ # Export just the initializer function
+ (id) -> new PaletteController(id)
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/53e05605/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Palette.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Palette.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Palette.java
index d82dcad..5ea4fba 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Palette.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Palette.java
@@ -1,4 +1,4 @@
-// Copyright 2007, 2008, 2009, 2010, 2011, 2012 The Apache Software Foundation
+// Copyright 2007-2013 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.
@@ -47,7 +47,7 @@ import java.util.Collection;
* <p/>
* <pre>
* <style>
- * DIV.t-palette SELECT { width: 300px; }
+ * DIV.palette SELECT { width: 300px; }
* </style>
* </pre>
* <p/>
@@ -59,6 +59,10 @@ import java.util.Collection;
* <p/>
* For an alternative component that can be used for similar purposes, see
* {@link Checklist}.
+ * <p>Starting in 5.4, the selected parameter may be any kind of collection, but is typically a List if the Palette is configured for re-ordering,
+ * and a Set if order does not matter (though it is common to use a List in the latter case as well). Also, starting in 5.4,
+ * the Palette is compatible with the {@link org.apache.tapestry5.validator.Required} validator (on both client and server-side), and
+ * triggers new events that allows the application to veto a proposed changed to the selection (see the {@code t5/core/events} module).
*
* @tapestrydoc
* @see Form
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/53e05605/tapestry-core/src/main/resources/META-INF/assets/core/Palette.css
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/resources/META-INF/assets/core/Palette.css b/tapestry-core/src/main/resources/META-INF/assets/core/Palette.css
index b2aa921..fe8b62f 100644
--- a/tapestry-core/src/main/resources/META-INF/assets/core/Palette.css
+++ b/tapestry-core/src/main/resources/META-INF/assets/core/Palette.css
@@ -1,13 +1,13 @@
-DIV.t-palette {
+DIV.palette {
display: inline;
}
-DIV.t-palette SELECT {
+DIV.palette SELECT {
margin-bottom: 2px;
width: 200px;
}
-DIV.t-palette-title {
+DIV.palette-title {
color: white;
background-color: black;
text-align: center;
@@ -17,28 +17,28 @@ DIV.t-palette-title {
width: 200px;
}
-DIV.t-palette-available {
+DIV.palette-available {
float: left;
}
-DIV.t-palette-controls {
+DIV.palette-controls {
margin: 5px 5px;
float: left;
}
-DIV.t-palette-controls > DIV {
+DIV.palette-controls > DIV {
margin-top: 5px;
}
-DIV.t-palette-controls > DIV:first-child {
+DIV.palette-controls > DIV:first-child {
margin-top: 0;
}
-DIV.t-palette-selected {
+DIV.palette-selected {
float: left;
clear: right;
}
-DIV.t-palette-spacer {
+DIV.palette-spacer {
clear: left;
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/53e05605/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Palette.tml
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Palette.tml b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Palette.tml
index 7512185..8b3b196 100644
--- a/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Palette.tml
+++ b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Palette.tml
@@ -1,9 +1,9 @@
-<div class="t-palette" xml:space="default" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
+<div class="palette" xml:space="default" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
<t:remove>Contains the array of option ids for selected elements:</t:remove>
<input type="hidden" name="${controlName}" value="${initialJSON}" disabled="${disabledValue}"/>
- <div class="t-palette-available">
- <div class="t-palette-title">
+ <div class="palette-available">
+ <div class="palette-title">
<t:delegate to="availableLabel"/>
</div>
<select multiple="multiple" size="${size}" disabled="${disabledValue}">
@@ -15,7 +15,7 @@
</select>
</div>
- <div class="t-palette-controls">
+ <div class="palette-controls">
<div>
<button data-action="select" class="btn" disabled="${disabledValue}">
<img src="${select}" alt="${message:core-palette-select-label}"/>
@@ -39,12 +39,12 @@
</div>
</t:if>
</div>
- <div class="t-palette-selected">
- <div class="t-palette-title">
+ <div class="palette-selected">
+ <div class="palette-title">
<t:delegate to="selectedLabel"/>
</div>
<t:remove>
- data-value=mode="options" is a bit of hack to inform the client side that the value for the field is all options, selected or not.
+ data-value=mode="options" is a bit of hack to inform the client side that the value for the field is all options, selected or not. This is used by validation logic.
</t:remove>
<select t:type="any" t:id="selected" id="${clientId}" multiple="multiple" size="${size}" disabled="${disabledValue}" data-value-mode="options" t:mixins="rendernotification">
<t:remove>Starts empty, populated on the client side.</t:remove>
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/53e05605/tapestry-core/src/test/app1/PaletteDemo.tml
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/app1/PaletteDemo.tml b/tapestry-core/src/test/app1/PaletteDemo.tml
index 3023c3a..7e516ce 100644
--- a/tapestry-core/src/test/app1/PaletteDemo.tml
+++ b/tapestry-core/src/test/app1/PaletteDemo.tml
@@ -39,6 +39,11 @@
</t:form>
-<p>Selected Languages: ${languages}</p>
+<dl class="dl-horizontal">
+ <dt>Languages:</dt>
+ <dd id="selected-languages">${languages}</dd>
+ <dt>Selected Values</dt>
+ <dd id="event-selection"/>
+</dl>
</html>
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/53e05605/tapestry-core/src/test/coffeescript/META-INF/modules/palette-demo.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/coffeescript/META-INF/modules/palette-demo.coffee b/tapestry-core/src/test/coffeescript/META-INF/modules/palette-demo.coffee
new file mode 100644
index 0000000..226e062
--- /dev/null
+++ b/tapestry-core/src/test/coffeescript/META-INF/modules/palette-demo.coffee
@@ -0,0 +1,5 @@
+define ["t5/core/dom", "t5/core/events"],
+ (dom, events) ->
+
+ dom.onDocument events.palette.willChange, (event, memo) ->
+ (dom "event-selection").update JSON.stringify memo.selectedValues
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/53e05605/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FormTests.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FormTests.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FormTests.java
index e8cf44d..24558d2 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FormTests.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FormTests.java
@@ -471,13 +471,13 @@ public class FormTests extends TapestryCoreTestCase
"//input[@id='datefield']",
- "//div[@class='t-palette']//input[@type='hidden']",
+ "//div[@class='palette']//input[@type='hidden']",
- "//div[@class='t-palette-available']//select",
+ "//div[@class='palette-available']//select",
- "//div[@class='t-palette-selected']//select",
+ "//div[@class='palette-selected']//select",
- "//div[@class='t-palette-controls']//button",
+ "//div[@class='palette-controls']//button",
"//input[@id='submit_0']"};
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/53e05605/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/PaletteTests.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/PaletteTests.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/PaletteTests.java
index e9b0889..03d87fc 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/PaletteTests.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/PaletteTests.java
@@ -1,4 +1,4 @@
-// Copyright 2009, 2011 The Apache Software Foundation
+// Copyright 2009-2013 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.
@@ -24,17 +24,17 @@ import org.testng.annotations.Test;
public class PaletteTests extends TapestryCoreTestCase
{
- public static final String AVAILABLE_OPTIONS = "css=.t-palette-available select";
+ public static final String AVAILABLE_OPTIONS = "css=.palette-available select";
- public static final String SELECTED_OPTIONS = "css=.t-palette-selected select";
+ public static final String SELECTED_OPTIONS = "css=.palette-selected select";
- public static final String SELECT_BUTTON = "css=.t-palette [data-action=select]";
+ public static final String SELECT_BUTTON = "css=.palette [data-action=select]";
- public static final String DESELECT_BUTTON = "css=.t-palette [data-action=deselect]";
+ public static final String DESELECT_BUTTON = "css=.palette [data-action=deselect]";
- public static final String MOVE_UP_BUTTON = "css=.t-palette [data-action=move-up]";
+ public static final String MOVE_UP_BUTTON = "css=.palette [data-action=move-up]";
- public static final String MOVE_DOWN_BUTTON = "css=.t-palette [data-action=move-down]";
+ public static final String MOVE_DOWN_BUTTON = "css=.palette [data-action=move-down]";
@Test
public void palette_component()
@@ -43,18 +43,22 @@ public class PaletteTests extends TapestryCoreTestCase
waitForPageInitialized();
- assertText("css=.t-palette-available .t-palette-title",
+ assertText("css=.palette-available .palette-title",
"Languages Offered");
- assertText("css=.t-palette-selected .t-palette-title",
+ assertText("css=.palette-selected .palette-title",
"Selected Languages");
addSelection(AVAILABLE_OPTIONS, "label=Haskell");
addSelection(AVAILABLE_OPTIONS, "label=Javascript");
click(SELECT_BUTTON);
+ // What a listener on the events.palette.willChange event would see in memo.selectdValues:
+ assertText("id=event-selection", "[\"HASKELL\",\"JAVASCRIPT\"]");
+
+
clickAndWait(SUBMIT);
- assertTextPresent("Selected Languages: [HASKELL, JAVASCRIPT]");
+ assertText("id=selected-languages", "[HASKELL, JAVASCRIPT]");
waitForPageInitialized();
@@ -75,7 +79,7 @@ public class PaletteTests extends TapestryCoreTestCase
clickAndWait(SUBMIT);
- assertTextPresent("[ERLANG, HASKELL, JAVA, LISP, ML, PERL, PYTHON, RUBY]");
+ assertText("id=selected-languages", "[ERLANG, HASKELL, JAVA, LISP, ML, PERL, PYTHON, RUBY]");
check("reorder");
@@ -97,7 +101,7 @@ public class PaletteTests extends TapestryCoreTestCase
clickAndWait(SUBMIT);
- assertTextPresent("[ERLANG, RUBY, HASKELL, JAVA, LISP, ML, PYTHON, PERL]");
+ assertText("id=selected-languages", "[ERLANG, RUBY, HASKELL, JAVA, LISP, ML, PYTHON, PERL]");
}
/**
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/53e05605/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteDemo.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteDemo.java
index 8ed2e3f..2f92fc6 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteDemo.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteDemo.java
@@ -1,4 +1,4 @@
-// Copyright 2007, 2012 The Apache Software Foundation
+// Copyright 2007-2013 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.
@@ -17,6 +17,7 @@ package org.apache.tapestry5.integration.app1.pages;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.SelectModel;
import org.apache.tapestry5.ValueEncoder;
+import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.integration.app1.data.ProgrammingLanguage;
@@ -28,6 +29,7 @@ import org.apache.tapestry5.util.EnumValueEncoder;
import java.util.ArrayList;
import java.util.List;
+@Import(module="palette-demo")
public class PaletteDemo
{
@Inject