You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by jk...@apache.org on 2006/06/11 04:30:29 UTC

svn commit: r413401 - in /tapestry/tapestry4/trunk: ./ examples/TimeTracker/src/context/ examples/TimeTracker/src/context/WEB-INF/ examples/TimeTracker/src/context/css/ examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/ framework/src/j...

Author: jkuhnert
Date: Sat Jun 10 19:30:27 2006
New Revision: 413401

URL: http://svn.apache.org/viewvc?rev=413401&view=rev
Log:
I hate posix..... 

Added:
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.jwc
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.script
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.jwc
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.script
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/util/Strftime.java
    tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/DropdownTimePicker.js   (with props)
    tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/templates/images/timeIcon.gif   (with props)
    tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_datetime.js   (with props)
    tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/util/StrftimeTest.java
Removed:
    tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/DropDownDatePicker.js
    tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/TDatePicker.js
Modified:
    tapestry/tapestry4/trunk/examples/TimeTracker/src/context/Home.html
    tapestry/tapestry4/trunk/examples/TimeTracker/src/context/WEB-INF/Home.properties
    tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/dojo.css
    tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/forms.css
    tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/timetracker.css
    tapestry/tapestry4/trunk/examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/Framework.library
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/asset/AssetService.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/parse/Tapestry_4_1.dtd
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java
    tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/asset/TestUnprotectedAsset.java
    tapestry/tapestry4/trunk/status.xml

Modified: tapestry/tapestry4/trunk/examples/TimeTracker/src/context/Home.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/examples/TimeTracker/src/context/Home.html?rev=413401&r1=413400&r2=413401&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/examples/TimeTracker/src/context/Home.html (original)
+++ tapestry/tapestry4/trunk/examples/TimeTracker/src/context/Home.html Sat Jun 10 19:30:27 2006
@@ -6,36 +6,55 @@
 using them.
 </p>
 
+<form jwcid="taskForm@Form" class="container">
+<h3><span jwcid="@Insert" value="message:new.task"/></h3>
+	<fieldset>
+    <table width="90%" class="form" cellpadding="2" cellspacing="0" >
+    <tr>
+      <td><label jwcid="@FieldLabel" field="component:projectChoose" /></td>
+      <td><label>Description</label></td>
+      <td><label>Duration</label></td>
+      <td>&nbsp;</td>
+    </tr>
+    <tr>
+      <td><div class="field required"><span jwcid="projectChoose" /></div></td>
+      <td><div class="field"><input name="fm-lastname" id="fm-lastname" type="text" /></div></td>
+      <td><div jwcid="duration@Any">18 minutes</div></td>
+      <td>&nbsp;</td>
+    </tr>
+    
+    <tr>
+      <td><label jwcid="@FieldLabel" field="component:datePicker" /></td>
+      <td><label jwcid="@FieldLabel" field="component:startPicker" /></td>
+      <td><label jwcid="@FieldLabel" field="component:endPicker" /></td>
+      <td>&nbsp;</td>
+    </tr>
+    
+    <tr>
+	  <td><div class="field required"><input jwcid="datePicker" /></div></td>
+      <td>
+      	<div class="field required">
+      		<input jwcid="startPicker" />
+      	</div>
+      </td>
+      <td>
+      	<div class="field required">
+      		<input jwcid="endPicker" />
+      	</div>
+      </td>
+      <td>
+      	<input jwcid="@Submit" value="message:button.add" class="submitButton" />
+      </td>
+    </tr>
+    
+    </table>
+    </fieldset>
+</form>
+
 <div jwcid="projectDescription@Any" >
 	<span jwcid="@If" condition="ognl:selectedProject">
-		<span jwcid="@Insert" value="ognl:selectedProject.name" />
+		<h2 style="clear:left" ><span jwcid="@Insert" value="ognl:selectedProject.name" /></h2>
 	</span>
 </div>
 
-<form jwcid="taskForm@Form" >
-    <fieldset>
-    <legend><span jwcid="@Insert" value="message:new.task"/></legend>
-    
-    <div class="fm-hopt">
-      <span jwcid="@FieldLabel" field="component:projectChoose" />
-      <span jwcid="projectChoose" />
-    </div>
-    
-    <div class="fm-hopt">
-      <label for="startPicker">Start</label>
-      <input jwcid="startPicker" style="width:auto" size="10"  />
-    </div>
-    <div class="fm-hopt">
-      <label for="fm-middlename">End</label>
-      <input style="width:auto" size="10" id="fm-middlename" name="fm-middlename" type="text" />
-    </div>
-    <div class="fm-hreq">
-      <label for="fm-lastname">Description</label>
-      <input name="fm-lastname" id="fm-lastname" type="text" />
-    </div>
-    <div id="fm-hsubmit" class="fm-req">
-      <input jwcid="@Submit" value="message:button.add" />
-    </div>
-    </fieldset>
-</form>
 </span>

Modified: tapestry/tapestry4/trunk/examples/TimeTracker/src/context/WEB-INF/Home.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/examples/TimeTracker/src/context/WEB-INF/Home.properties?rev=413401&r1=413400&r2=413401&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/examples/TimeTracker/src/context/WEB-INF/Home.properties (original)
+++ tapestry/tapestry4/trunk/examples/TimeTracker/src/context/WEB-INF/Home.properties Sat Jun 10 19:30:27 2006
@@ -1,4 +1,9 @@
 new.task=Task Entry
 
 choose.project=Project
-button.add=add
\ No newline at end of file
+button.add=add
+
+task.start.date=Date
+task.start.time=Start
+task.end.time=End
+task.duration=Duration

Modified: tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/dojo.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/dojo.css?rev=413401&r1=413400&r2=413401&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/dojo.css (original)
+++ tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/dojo.css Sat Jun 10 19:30:27 2006
@@ -24,4 +24,17 @@
     opacity: 0.8;
     filter: alpha(opacity : 80);
     background: #eef1f8;
-}
\ No newline at end of file
+}
+
+.timePickerContainer {
+	background: #7591bc url("images/dpBg.gif") top left repeat-x;
+}
+
+.timeContainer thead tr td {
+	border-bottom:1px solid #e6e6e6;
+	margin:0;
+	padding:0.45em 0 0.45em 0;
+	color:#fff;
+	font:bold 0.75em Helvetica, Arial, Verdana, sans-serif;
+	text-align:center;
+}

Modified: tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/forms.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/forms.css?rev=413401&r1=413400&r2=413401&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/forms.css (original)
+++ tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/forms.css Sat Jun 10 19:30:27 2006
@@ -1,165 +1,55 @@
-/* Styles */
-form {
-    margin: 0;
-    padding: 0;
+div.requiredClause{
+	width:auto;
+	float:right;
+	padding-left:2px;
+	border-left:3px solid #ff660a;
+	margin-top:1.5em;
+	font-size: 0.7em;
+	font-weight:bold;
+}
+
+form { clear:both; border:1px solid #d0d8e2; margin:0; margin-bottom:1.5em; }
+form.container { padding:2em 1.5em; }
+* html form.container { width:100%; }
+
+/* field wrappers */
+form div.field{ margin-right:1.5em; padding-left:5px; }
+* html form div.field { margin-right:0.5em; }
+
+/* use in conjunction with div.field: <div class="field required"></div> */
+form div.required{ border-left:3px solid #ff660a; padding-left:2px; }
+form label{ display:block; margin-top:1em; font-size:0.65em; }
+form .ex-container label{ margin-top:0.75em; }
+
+/* input elements */
+form div.dropdown,
+form input.text,
+form input.numeric,
+form select,
+form textarea { border: 1px solid #a2da87; padding: 0.15em; width:100%; }
+form div.dropdown{ padding:0; height:22px; background-color:#fff;}
+form textarea { font-family:sans-serif; font-size:0.8em; margin: 0.55em 0; }
+* html form textarea { width:auto; }
+* html form select{ width:90%; }
+
+/*form textarea:focus { background-color: #F1F6FC; }*/
+form input.numeric { text-align:right; }
+
+form p { font-size:0.75em; }
+form h2 { font: 1.2em Tahoma, Myriad, sans-serif; background: #eef0f7 top left repeat-y; color: #4a7db5; padding: 1em 0.35em; }
+form h3 { font: 0.8em Tahoma, Myriad, sans-serif; font-weight:bold; color: #296cb5; margin:1.5em -1em 0 -1em; border-bottom: 1px solid #d0d8e2; padding-bottom:0; }
+form h4 { font: 0.8em Tahoma, Myriad, sans-serif; font-weight:bold; margin:0; margin-top:1em; border-bottom: 1px solid #ddd; }
+
+.submitButton,.submitButton:focus {
+	width: auto;
+	border: none;
+	background-color: #699ED9;
+	color: #fff;
+	padding: 0.1em;
+	border-bottom: 1px solid #5885b6 !important;
+	border-right: 1px solid #5885b6 !important;
+	border-top: 1px solid #92b8e2 !important;
+	border-left: 1px solid #92b8e2 !important;
+	cursor: hand;
+	cursor: pointer;
 }
-
-fieldset {
-    margin: 1em 0;
-    float: left;
-}
-
-legend {
-    margin-bottom: 0.7em;
-    padding: 0 .5em;
-    color: #036;
-    background: transparent;
-    font-size: 1.3em;
-    font-weight: bold;
-    float: left;
-    border-bottom: 1px solid #ccc;;
-    padding: 0 .5em;
-}
-
-label {
-    float: left;
-    width: 100px;
-    padding: 0 1em;
-    text-align: right;
-}
-
-fieldset div {
-    margin-bottom: .5em;
-    padding: 0;
-    display: block;
-}
-
-fieldset div input,fieldset div textarea {
-    width: 150px;
-    border-top: 1px solid #555;
-    border-left: 1px solid #555;
-    border-bottom: 1px solid #ccc;
-    border-right: 1px solid #ccc;
-    padding: 1px;
-    color: #333;
-}
-
-fieldset div select {
-    padding: 1px;
-}
-
-div.fm-multi div {
-    margin: 5px 0;
-}
-
-div.fm-multi input {
-    width: 1em;
-}
-
-div.fm-multi label {
-    display: block;
-    width: 200px;
-    padding-left: 5em;
-    text-align: left;
-}
-
-#fm-submit {
-    clear: both;
-    padding-top: 1em;
-    text-align: center;
-}
-
-#fm-submit input {
-    border: 1px solid #333;
-    padding: 2px 1em;
-    background: #555;
-    color: #fff;
-    font-size: 100%;
-}
-
-input:focus,textarea:focus {
-    background: #D6AE33;
-    color: #000;
-}
-
-fieldset div input:focus,fieldset div textarea:focus {
-    border-top: 1px solid #292929;
-    border-left: 1px solid #292929; 
-}
-
-/* required fields - does not work in IE */
-fieldset div.fm-req,fieldset div.fm-hreq {
-    font-weight: bold;
-}
-
-fieldset div.fm-req label:before,fieldset div.fm-hreq label:before {
-    content: "* "; /* does not work in IE */
-}
-
-div.fm-hopt,div.fm-hreq {
-    clear: none;
-    float: left;
-    margin-right: 1em;
-    margin-bottom: 1em;
-}
-
-div.fm-hopt label,div.fm-hreq label {
-    width: auto;
-    padding-left: 0px;
-    padding-bottom: 0.2em;
-}
-
-div.fm-hopt input,div.fm-hreq input {
-    clear: left;
-    float: left;
-}
-
-div.fm-hopt select,div.fm-hreq select {
-    clear: left;
-    float: left;
-}
-
-div.fm-hopt a {
-    clear: left;
-    float: left;
-}
-
-#fm-hsubmit {
-    text-align: center;
-    padding-top: 14px;
-    margin-right: 0.5em;
-    float: left;
-    width:auto;
-}
-
-#fm-hsubmitsec {
-    text-align: center;
-    padding-top: 14px;
-    margin-right: 0.5em;
-    float: left;
-}
-
-#fm-hsubmit input {
-    border: 1px solid #292929;
-    padding: 2px 1em;
-    background: #2A78B0;
-    color: #fff;
-    font-size: 100%;
-    float: left;
-    clear: left;
-    width:auto;
-}
-
-#fm-hsubmitsec input {
-    border: 1px solid #aaaaaa;
-    padding: 2px 1em;
-    background: #D4D4D4;
-    color: #555555;
-    font-size: 100%;
-    float: left;
-    clear: left;
-}
-
-#fm-hsubmit .dialog,#fm-hsubmitsec .dialog {
-    float: right;
-}
\ No newline at end of file

Modified: tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/timetracker.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/timetracker.css?rev=413401&r1=413400&r2=413401&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/timetracker.css (original)
+++ tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/timetracker.css Sat Jun 10 19:30:27 2006
@@ -15,6 +15,9 @@
     margin-left: 3%;
 }
 
+h2 { font: 1.4em Tahoma, Myriad, sans-serif; font-weight:bold; color: #296cb5; padding-bottom:0; }
+h3 { font: 0.8em Tahoma, Myriad, sans-serif; font-weight:bold; color: #296cb5; padding-bottom:0; }
+
 p {
     margin-bottom: 8px;   
 }

Modified: tapestry/tapestry4/trunk/examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java?rev=413401&r1=413400&r2=413401&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java (original)
+++ tapestry/tapestry4/trunk/examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java Sat Jun 10 19:30:27 2006
@@ -23,8 +23,9 @@
 import org.apache.tapestry.annotations.InjectObject;
 import org.apache.tapestry.annotations.Persist;
 import org.apache.tapestry.dojo.form.Autocompleter;
+import org.apache.tapestry.dojo.form.DropdownDatePicker;
+import org.apache.tapestry.dojo.form.DropdownTimePicker;
 import org.apache.tapestry.form.BeanPropertySelectionModel;
-import org.apache.tapestry.form.DatePicker;
 import org.apache.tapestry.form.IPropertySelectionModel;
 import org.apache.tapestry.html.BasePage;
 import org.apache.tapestry.timetracker.dao.ProjectDao;
@@ -51,13 +52,22 @@
     @Persist("session")
     public abstract Project getSelectedProject();
     
-    @Component(type = "DatePicker", id = "startPicker",
-            bindings = {"value=startTime"})
-    public abstract DatePicker getStartPicker();
+    public abstract Project getCurrentProject();
     
+    @Component(type = "DropdownDatePicker", id = "datePicker",
+            bindings = {"value=date", "displayName=message:task.start.date"})
+    public abstract DropdownDatePicker getDatePicker();
+    public abstract Date getDate();
+    
+    @Component(type = "DropdownTimePicker", id = "startPicker",
+            bindings = {"value=startTime", "displayName=message:task.start.time"})
+    public abstract DropdownTimePicker getStartPicker();
     public abstract Date getStartTime();
     
-    public abstract Project getCurrentProject();
+    @Component(type = "DropdownTimePicker", id = "endPicker",
+            bindings = {"value=endTime", "displayName=message:task.end.time"})
+    public abstract DropdownTimePicker getEndPicker();
+    public abstract Date getEndTime();
     
     /**
      * Selection model for projects.

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/Framework.library
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/Framework.library?rev=413401&r1=413400&r2=413401&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/Framework.library (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/Framework.library Sat Jun 10 19:30:27 2006
@@ -42,6 +42,8 @@
     <component-type type="Delegator" specification-path="components/Delegator.jwc"/>
 	<component-type type="Describe" specification-path="html/Describe.jwc"/>
     <component-type type="DirectLink" specification-path="link/DirectLink.jwc"/>
+    <component-type type="DropdownDatePicker" specification-path="dojo/form/DropdownDatePicker.jwc"/>
+    <component-type type="DropdownTimePicker" specification-path="dojo/form/DropdownTimePicker.jwc"/>
     <component-type type="Else" specification-path="components/Else.jwc"/>
     <component-type type="ExceptionDisplay" specification-path="html/ExceptionDisplay.jwc"/>
     <component-type type="ExternalLink" specification-path="link/ExternalLink.jwc"/>

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/asset/AssetService.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/asset/AssetService.java?rev=413401&r1=413400&r2=413401&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/asset/AssetService.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/asset/AssetService.java Sat Jun 10 19:30:27 2006
@@ -222,7 +222,7 @@
                 return;
             }
             
-            URL resourceURL = _classResolver.getResource(path);
+            URL resourceURL = _classResolver.getResource(translateCssPath(path));
             
             if (resourceURL == null)
                 throw new ApplicationRuntimeException(AssetMessages.noSuchResource(path));
@@ -243,6 +243,32 @@
 
     }
 
+    /**
+     * Utility that helps to resolve css file relative resources included
+     * in a css temlpate via "url('../images/foo.gif')" style css.
+     * 
+     * @param path The incoming path to check for css resource relativity
+     * @return The path unchanged if not containing a css relative path, otherwise
+     *          returns the path without the css filename in it so the resource is resolvable
+     *          directly from the path.
+     */
+    String translateCssPath(String path)
+    {
+        if (path == null) return null;
+        
+        // don't parse out actual css files
+        if (path.endsWith(".css")) return path;
+        
+        int index = path.lastIndexOf(".css");
+        if (index <= -1) return path;
+        
+        // now need to parse out whatever css file was referenced to get the real path
+        int pathEnd = path.lastIndexOf("/", index);
+        if (pathEnd <= -1) return path;
+        
+        return path.substring(0, pathEnd + 1) + path.substring(index + 4, path.length());
+    }
+    
     /**
      * Checks if the resource contained within the specified URL 
      * has a modified time greater than the request header value

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.java?rev=413401&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.java (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.java Sat Jun 10 19:30:27 2006
@@ -0,0 +1,132 @@
+// Copyright Jun 10, 2006 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.dojo.form;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry.IMarkupWriter;
+import org.apache.tapestry.IRequestCycle;
+import org.apache.tapestry.IScript;
+import org.apache.tapestry.TapestryUtils;
+import org.apache.tapestry.form.TranslatedField;
+import org.apache.tapestry.form.TranslatedFieldSupport;
+import org.apache.tapestry.form.ValidatableFieldSupport;
+import org.apache.tapestry.form.translator.DateTranslator;
+import org.apache.tapestry.json.JSONObject;
+import org.apache.tapestry.util.Strftime;
+import org.apache.tapestry.valid.ValidatorException;
+
+/**
+ * Implementation of the dojo DropdownDatePicker widget as a tapestry
+ * component. Wraps a form input field with a date picker icon next to it
+ * that when clicked on reveals a calendar to choose date values from. 
+ * 
+ * @author jkuhnert
+ */
+public abstract class DropdownDatePicker extends AbstractFormWidget
+    implements TranslatedField
+{
+    
+    /** parameter. */
+    public abstract Date getValue();
+    
+    public abstract void setValue(Date value);
+    
+    public abstract boolean isDisabled();
+    
+    /** Alt html text for the date icon, what is displayed when mouse hovers over icon. */
+    public abstract String getIconAlt();
+    
+    /**
+     * {@inheritDoc}
+     */
+    protected void renderFormWidget(IMarkupWriter writer, IRequestCycle cycle)
+    {
+        // dojo dates are in POSIX style formats so we format the value manually
+        DateTranslator translator = (DateTranslator) getTranslator();
+        
+        renderDelegatePrefix(writer, cycle);
+        
+        // the html output doesn't matter very much as dojo
+        // will create an inline input field for us anyways, but we do need
+        // a node to reference
+        writer.begin("div");
+        renderIdAttribute(writer, cycle);
+        
+        renderDelegateAttributes(writer, cycle);
+        
+        getValidatableFieldSupport().renderContributions(this, writer, cycle);
+        
+        renderInformalParameters(writer, cycle);
+        
+        writer.end();
+        renderDelegateSuffix(writer, cycle);
+        
+        // now create widget parms
+        JSONObject json = new JSONObject();
+        json.put("inputId", getClientId());
+        json.put("inputName", getName());
+        json.put("iconAlt", getIconAlt());
+        json.put("dateFormat", Strftime.convertToPosixFormat(translator.getPattern()));
+        if (getValue() != null)
+            json.put("date", getTranslatedFieldSupport().format(this, getValue()));
+        
+        Map parms = new HashMap();
+        parms.put("clientId", getClientId());
+        parms.put("props", json.toString());
+        
+        getScript().execute(cycle, TapestryUtils.getPageRenderSupport(cycle, this), parms);
+    }
+    
+    /**
+     * @see org.apache.tapestry.form.AbstractFormComponent#rewindFormComponent(org.apache.tapestry.IMarkupWriter, org.apache.tapestry.IRequestCycle)
+     */
+    protected void rewindFormWidget(IMarkupWriter writer, IRequestCycle cycle)
+    {
+        String value = cycle.getParameter(getName());
+        
+        try
+        {
+            Date date = (Date) getTranslatedFieldSupport().parse(this, value);
+
+            getValidatableFieldSupport().validate(this, writer, cycle, date);
+
+            setValue(date);
+        }
+        catch (ValidatorException e)
+        {
+            getForm().getDelegate().record(e);
+        }
+    }
+    
+    /**
+     * @see org.apache.tapestry.form.AbstractFormComponent#isRequired()
+     */
+    public boolean isRequired()
+    {
+        return getValidatableFieldSupport().isRequired(this);
+    }
+    
+    /** Injected. */
+    public abstract IScript getScript();
+    
+    /** Injected. */
+    public abstract TranslatedFieldSupport getTranslatedFieldSupport();
+    
+    /** Injected. */
+    public abstract ValidatableFieldSupport getValidatableFieldSupport();
+    
+}

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.jwc
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.jwc?rev=413401&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.jwc (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.jwc Sat Jun 10 19:30:27 2006
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+   Copyright 2006 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.
+-->
+
+<!DOCTYPE component-specification PUBLIC 
+  "-//Apache Software Foundation//Tapestry Specification 4.0//EN" 
+  "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">
+
+<component-specification class="org.apache.tapestry.dojo.form.DropdownDatePicker" allow-body="no">
+  
+  <parameter name="value" required="yes"/>
+  <parameter name="disabled"/>
+  <parameter name="iconAlt" default-value="literal:Select a Date" />
+  
+  <parameter name="displayName"/>
+  <parameter name="translator" default-value="translator:date,pattern=dd MMM yyyy"/>
+  <parameter name="validators"/>
+  <parameter name="id" property="idParameter" default-value="id"/>
+  
+  <inject property="script" type="script" object="DropdownDatePicker.script"/>
+  <inject property="translatedFieldSupport" object="service:tapestry.form.TranslatedFieldSupport"/>
+  <inject property="validatableFieldSupport" object="service:tapestry.form.ValidatableFieldSupport"/>
+    
+</component-specification>

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.script
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.script?rev=413401&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.script (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownDatePicker.script Sat Jun 10 19:30:27 2006
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!DOCTYPE script PUBLIC
+  "-//Apache Software Foundation//Tapestry Script Specification 3.0//EN"
+  "http://jakarta.apache.org/tapestry/dtd/Script_3_0.dtd">
+<script>
+<input-symbol key="clientId" required="yes" />
+<input-symbol key="props" required="yes" />
+    <body>
+        <unique>
+            dojo.require("dojo.widget.Manager");
+            dojo.require("dojo.widget.DropdownDatePicker");
+            dojo.require("tapestry.widget.*");
+        </unique>
+    </body>
+    <initialization>
+        tapestry.widget.synchronizeWidgetState("${clientId}", "DropdownDatePicker", ${props});
+    </initialization>
+</script>
\ No newline at end of file

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.java?rev=413401&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.java (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.java Sat Jun 10 19:30:27 2006
@@ -0,0 +1,134 @@
+// Copyright Jun 10, 2006 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.dojo.form;
+
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry.IMarkupWriter;
+import org.apache.tapestry.IRequestCycle;
+import org.apache.tapestry.IScript;
+import org.apache.tapestry.TapestryUtils;
+import org.apache.tapestry.form.TranslatedField;
+import org.apache.tapestry.form.TranslatedFieldSupport;
+import org.apache.tapestry.form.ValidatableFieldSupport;
+import org.apache.tapestry.form.translator.DateTranslator;
+import org.apache.tapestry.json.JSONObject;
+import org.apache.tapestry.util.Strftime;
+import org.apache.tapestry.valid.ValidatorException;
+
+/**
+ * Implementation of the dojo DropdownTimePicker widget as a tapestry
+ * component. Wraps a form input field with a date picker icon next to it
+ * that when clicked on reveals a pane to choose time values from. 
+ * 
+ * @author jkuhnert
+ */
+public abstract class DropdownTimePicker extends AbstractFormWidget
+    implements TranslatedField
+{
+    
+    /** parameter. */
+    public abstract Date getValue();
+    
+    public abstract void setValue(Date value);
+    
+    public abstract boolean isDisabled();
+    
+    /** Alt html text for the date icon, what is displayed when mouse hovers over icon. */
+    public abstract String getIconAlt();
+    
+    /**
+     * {@inheritDoc}
+     */
+    protected void renderFormWidget(IMarkupWriter writer, IRequestCycle cycle)
+    {
+        // dojo dates are in POSIX style formats so we format the value manually
+        DateTranslator translator = (DateTranslator) getTranslator();
+        
+        renderDelegatePrefix(writer, cycle);
+        
+        // the html output doesn't matter very much as dojo
+        // will create an inline input field for us anyways, but we do need
+        // a node to reference
+        writer.begin("div");
+        renderIdAttribute(writer, cycle);
+        
+        renderDelegateAttributes(writer, cycle);
+        
+        getValidatableFieldSupport().renderContributions(this, writer, cycle);
+        
+        renderInformalParameters(writer, cycle);
+        
+        writer.end();
+        renderDelegateSuffix(writer, cycle);
+        
+        // now create widget parms
+        JSONObject json = new JSONObject();
+        json.put("inputId", getClientId());
+        json.put("inputName", getName());
+        json.put("iconAlt", getIconAlt());
+        json.put("dateFormat", Strftime.convertToPosixFormat(translator.getPattern()));
+        if (getValue() != null)
+            json.put("date", DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, 
+                    getPage().getLocale()).format(getValue()));
+        
+        Map parms = new HashMap();
+        parms.put("clientId", getClientId());
+        parms.put("props", json.toString());
+        
+        getScript().execute(cycle, TapestryUtils.getPageRenderSupport(cycle, this), parms);
+    }
+    
+    /**
+     * @see org.apache.tapestry.form.AbstractFormComponent#rewindFormComponent(org.apache.tapestry.IMarkupWriter, org.apache.tapestry.IRequestCycle)
+     */
+    protected void rewindFormWidget(IMarkupWriter writer, IRequestCycle cycle)
+    {
+        String value = cycle.getParameter(getName());
+        
+        try
+        {
+            Date date = (Date) getTranslatedFieldSupport().parse(this, value);
+
+            getValidatableFieldSupport().validate(this, writer, cycle, date);
+
+            setValue(date);
+        }
+        catch (ValidatorException e)
+        {
+            getForm().getDelegate().record(e);
+        }
+    }
+    
+    /**
+     * @see org.apache.tapestry.form.AbstractFormComponent#isRequired()
+     */
+    public boolean isRequired()
+    {
+        return getValidatableFieldSupport().isRequired(this);
+    }
+    
+    /** Injected. */
+    public abstract IScript getScript();
+    
+    /** Injected. */
+    public abstract TranslatedFieldSupport getTranslatedFieldSupport();
+    
+    /** Injected. */
+    public abstract ValidatableFieldSupport getValidatableFieldSupport();
+    
+}

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.jwc
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.jwc?rev=413401&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.jwc (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.jwc Sat Jun 10 19:30:27 2006
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+   Copyright 2006 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.
+-->
+
+<!DOCTYPE component-specification PUBLIC 
+  "-//Apache Software Foundation//Tapestry Specification 4.0//EN" 
+  "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">
+
+<component-specification class="org.apache.tapestry.dojo.form.DropdownTimePicker" allow-body="no">
+  
+  <parameter name="value" required="yes"/>
+  <parameter name="disabled"/>
+  <parameter name="iconAlt" default-value="literal:Select a Time" />
+  
+  <parameter name="displayName"/>
+  <parameter name="translator" default-value="translator:date,pattern=hh:mm a"/>
+  <parameter name="validators"/>
+  <parameter name="id" property="idParameter" default-value="id"/>
+  
+  <inject property="script" type="script" object="DropdownTimePicker.script"/>
+  <inject property="translatedFieldSupport" object="service:tapestry.form.TranslatedFieldSupport"/>
+  <inject property="validatableFieldSupport" object="service:tapestry.form.ValidatableFieldSupport"/>
+    
+</component-specification>

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.script
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.script?rev=413401&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.script (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/DropdownTimePicker.script Sat Jun 10 19:30:27 2006
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!DOCTYPE script PUBLIC
+  "-//Apache Software Foundation//Tapestry Script Specification 3.0//EN"
+  "http://jakarta.apache.org/tapestry/dtd/Script_3_0.dtd">
+<script>
+<input-symbol key="clientId" required="yes" />
+<input-symbol key="props" required="yes" />
+    <body>
+        <unique>
+            dojo.require("dojo.widget.Manager");
+            dojo.require("tapestry.widget.*");
+            dojo.require("tapestry.widget.DropdownTimePicker");
+        </unique>
+    </body>
+    <initialization>
+        tapestry.widget.synchronizeWidgetState("${clientId}", "DropdownTimePicker", ${props});
+    </initialization>
+</script>
\ No newline at end of file

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/parse/Tapestry_4_1.dtd
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/parse/Tapestry_4_1.dtd?rev=413401&r1=413400&r2=413401&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/parse/Tapestry_4_1.dtd (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/parse/Tapestry_4_1.dtd Sat Jun 10 19:30:27 2006
@@ -4,11 +4,11 @@
 The DTD for Tapestry application, library, page and component specifications.
 Associated with the public identifier:
 
-	-//Apache Software Foundation//Tapestry Specification 4.0//EN
+	-//Apache Software Foundation//Tapestry Specification 4.1//EN
 	
 The canonical location for the DTD is:
 
-	http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd
+	http://jakarta.apache.org/tapestry/dtd/Tapestry_4_1.dtd
 
 For application specifications, the root element is application.
 

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java?rev=413401&r1=413400&r2=413401&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java Sat Jun 10 19:30:27 2006
@@ -438,18 +438,5 @@
     String getComponentId(IComponent comp)
     {
         return comp.getClientId();
-        
-        /* String id = null;
-        //form components have id's generated to ensure uniqueness
-        if (comp instanceof IFormComponent)
-            return ((IFormComponent)comp).getClientId();
-        
-        id = comp.getId();
-        if (comp.getBinding("id") != null
-                && comp.getBinding("id").getObject() != null)
-            id = comp.getBinding("id").getObject().toString();
-        
-        return id;
-        */
     }
 }

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/util/Strftime.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/util/Strftime.java?rev=413401&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/util/Strftime.java (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/util/Strftime.java Sat Jun 10 19:30:27 2006
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2006 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.util;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.TimeZone;
+
+/**
+ * Converts dates to strings using the same format specifiers as strftime Note: This does not mimic
+ * strftime perfectly. Certain strftime commands, are not supported, and will convert as if they
+ * were literals. Certain complicated commands, like those dealing with the week of the year
+ * probably don't have exactly the same behavior as strftime. These limitations are due to use
+ * SimpleDateTime. If the conversion was done manually, all these limitations could be eliminated.
+ * The interface looks like a subset of DateFormat. Maybe someday someone will make this class
+ * extend DateFormat.
+ * 
+ * <p>
+ * Added to tapestry in order to help with dojo/javascript date/time conversions.
+ * </p>
+ * 
+ * @see {@linkplain http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html}
+ * @author Bip Thelin
+ * @author Dan Sandberg
+ */
+public class Strftime
+{
+
+    protected static Properties translate;
+    protected static Properties pTranslate;
+    protected SimpleDateFormat simpleDateFormat;
+
+    /**
+     * Initialize our pattern translation
+     */
+    static {
+        translate = new Properties();
+        translate.put("a", "EEE");
+        translate.put("A", "EEEE");
+        translate.put("b", "MMM");
+        translate.put("B", "MMMM");
+        translate.put("c", "EEE MMM d HH:mm:ss yyyy");
+
+        // There's no way to specify the century in SimpleDateFormat. We don't want to hard-code
+        // 20 since this could be wrong for the pre-2000 files.
+        // translate.put("C", "20");
+        translate.put("d", "dd");
+        translate.put("D", "MM/dd/yy");
+        translate.put("e", "dd"); // will show as '03' instead of ' 3'
+        translate.put("F", "yyyy-MM-dd");
+        translate.put("g", "yy");
+        translate.put("G", "yyyy");
+        translate.put("H", "HH");
+        translate.put("h", "MMM");
+        translate.put("I", "hh");
+        translate.put("j", "DDD");
+        translate.put("k", "HH"); // will show as '07' instead of ' 7'
+        translate.put("l", "hh"); // will show as '07' instead of ' 7'
+        translate.put("m", "MM");
+        translate.put("M", "mm");
+        translate.put("n", "\n");
+        translate.put("p", "a");
+        translate.put("P", "a"); // will show as pm instead of PM
+        translate.put("r", "hh:mm:ss a");
+        translate.put("R", "HH:mm");
+        // There's no way to specify this with SimpleDateFormat
+        // translate.put("s","seconds since ecpoch");
+        translate.put("S", "ss");
+        translate.put("t", "\t");
+        translate.put("T", "HH:mm:ss");
+        // There's no way to specify this with SimpleDateFormat
+        // translate.put("u","day of week ( 1-7 )");
+
+        // There's no way to specify this with SimpleDateFormat
+        // translate.put("U","week in year with first sunday as first day...");
+
+        translate.put("V", "ww"); // I'm not sure this is always exactly the same
+
+        // There's no way to specify this with SimpleDateFormat
+        // translate.put("W","week in year with first monday as first day...");
+
+        // There's no way to specify this with SimpleDateFormat
+        // translate.put("w","E");
+        translate.put("X", "HH:mm:ss");
+        translate.put("x", "MM/dd/yy");
+        translate.put("y", "yy");
+        translate.put("Y", "yyyy");
+        translate.put("Z", "z");
+        translate.put("z", "Z");
+        translate.put("%", "%");
+        
+        pTranslate = new Properties();
+        pTranslate.put("EEE", "%a");
+        pTranslate.put("EEEE", "%A");
+        pTranslate.put("MMM", "%b");
+        pTranslate.put("MMMM", "%B");
+        pTranslate.put("EEE MMM d HH:mm:ss yyyy", "%c");
+
+        // There's no way to specify the century in SimpleDateFormat. We don't want to hard-code
+        // 20 since this could be wrong for the pre-2000 files.
+        // translate.put("C", "20");
+        pTranslate.put("dd", "%d");
+        pTranslate.put("MM/dd/yy", "%D");
+        pTranslate.put("yyyy-MM-dd", "%F");
+        pTranslate.put("yy", "%g");
+        pTranslate.put("yyyy", "%G");
+        pTranslate.put("HH", "%H");
+        pTranslate.put("MMM", "%h");
+        pTranslate.put("hh", "%I");
+        pTranslate.put("DDD", "%j");
+        pTranslate.put("MM", "%m");
+        pTranslate.put("mm", "%M");
+        pTranslate.put("\n", "%n");
+        pTranslate.put("a", "%p"); // will show as pm instead of PM
+        pTranslate.put("hh:mm:ss a", "%r");
+        pTranslate.put("HH:mm", "%R");
+        // There's no way to specify this with SimpleDateFormat
+        // translate.put("s","seconds since ecpoch");
+        pTranslate.put("ss", "%S");
+        pTranslate.put("\t", "%t");
+        pTranslate.put("HH:mm:ss", "%T");
+        // There's no way to specify this with SimpleDateFormat
+        // translate.put("u","day of week ( 1-7 )");
+
+        // There's no way to specify this with SimpleDateFormat
+        // translate.put("U","week in year with first sunday as first day...");
+
+        pTranslate.put("ww", "%V"); // I'm not sure this is always exactly the same
+
+        // There's no way to specify this with SimpleDateFormat
+        // translate.put("W","week in year with first monday as first day...");
+
+        // There's no way to specify this with SimpleDateFormat
+        // translate.put("w","E");
+        pTranslate.put("HH:mm:ss", "%X");
+        pTranslate.put("MM/dd/yy", "%x");
+        pTranslate.put("yy", "%y");
+        pTranslate.put("yyyy", "%Y");
+        pTranslate.put("z", "%Z");
+        pTranslate.put("Z", "%z");
+        pTranslate.put("%", "%");
+    }
+
+    /**
+     * Create an instance of this date formatting class.
+     * 
+     * @see #Strftime( String, Locale )
+     */
+    public Strftime(String origFormat)
+    {
+        String convertedFormat = convertDateFormat(origFormat);
+        simpleDateFormat = new SimpleDateFormat(convertedFormat);
+    }
+
+    /**
+     * Create an instance of this date formatting class.
+     * 
+     * @param origFormat
+     *            the strftime-style formatting string
+     * @param locale
+     *            the locale to use for locale-specific conversions
+     */
+    public Strftime(String origFormat, Locale locale)
+    {
+        String convertedFormat = convertDateFormat(origFormat);
+        simpleDateFormat = new SimpleDateFormat(convertedFormat, locale);
+    }
+
+    /**
+     * Format the date according to the strftime-style string given in the constructor.
+     * 
+     * @param date
+     *            the date to format
+     * @return the formatted date
+     */
+    public String format(Date date)
+    {
+        return simpleDateFormat.format(date);
+    }
+
+    /**
+     * Parses the input. 
+     * 
+     * @see {@link java.text.SimpleDateFormat#parse(String)}
+     * @param input The string to parse.
+     * @return A parsed {@link Date}.
+     * @throws ParseException On input error.
+     */
+    public Date parse(String input)
+    throws ParseException
+    {
+        return simpleDateFormat.parse(input);
+    }
+    
+    /**
+     * Get the timezone used for formatting conversions.
+     * 
+     * @return the timezone
+     */
+    public TimeZone getTimeZone()
+    {
+        return simpleDateFormat.getTimeZone();
+    }
+
+    /**
+     * Change the timezone used to format dates.
+     * 
+     * @see SimpleDateFormat#setTimeZone
+     */
+    public void setTimeZone(TimeZone timeZone)
+    {
+        simpleDateFormat.setTimeZone(timeZone);
+    }
+    
+    /**
+     * Does the exact opposite of {{@link #convertDateFormat(String)} by converting
+     * the incoming java date format string into a POSIX compliant format string.
+     * @param pattern The java date format style format
+     * @return The converted format into something usable by POSIX strftime style parser/formatters.
+     */
+    public static String convertToPosixFormat(String pattern)
+    {
+        if (pattern == null) return null;
+        
+        StringBuffer buf = new StringBuffer();
+        int start=-1;
+        
+        for(int i = 0; i < pattern.length(); i++) {
+            char c = pattern.charAt(i);
+            
+            // if in a definition
+            if (Character.isLetter(c)) {
+                if (start <= -1) start = i;
+                continue;
+            } else if (start >= 0) {
+                // we've hit the end of a definition
+                String conv = pattern.substring(start, i);
+                String match = pTranslate.getProperty(conv);
+                
+                if (match == null)
+                    buf.append(conv); // just append it, this shouldn't happen we hope
+                else
+                    buf.append(match);
+                
+                // reset
+                start=-1;
+            }
+            
+            buf.append(c);
+        }
+        
+        // grab last one, if any
+        if (start > -1) {
+            String conv = pattern.substring(start, pattern.length());
+            String match = pTranslate.getProperty(conv);
+            if (match == null) buf.append(conv);
+            else buf.append(match);
+        }
+        
+        return buf.toString();
+    }
+    
+    /**
+     * Search the provided pattern and get the C standard Date/Time formatting rules and convert
+     * them to the Java equivalent.
+     * 
+     * @param pattern
+     *            The pattern to search
+     * @return The modified pattern
+     */
+    public static String convertDateFormat(String pattern)
+    {
+        boolean inside = false;
+        boolean mark = false;
+        boolean modifiedCommand = false;
+        
+        StringBuffer buf = new StringBuffer();
+        
+        for(int i = 0; i < pattern.length(); i++) {
+            char c = pattern.charAt(i);
+
+            if (c == '%' && !mark) {
+                mark = true;
+            } else {
+                if (mark) {
+                    if (modifiedCommand) {
+                        // don't do anything--we just wanted to skip a char
+                        modifiedCommand = false;
+                        mark = false;
+                    } else {
+                        inside = translateCommand(buf, pattern, i, inside);
+                        // It's a modifier code
+                        if (c == 'O' || c == 'E') {
+                            modifiedCommand = true;
+                        } else {
+                            mark = false;
+                        }
+                    }
+                } else {
+                    if (!inside && c != ' ') {
+                        // We start a literal, which we need to quote
+                        buf.append("'");
+                        inside = true;
+                    }
+
+                    buf.append(c);
+                }
+            }
+        }
+
+        if (buf.length() > 0) {
+            char lastChar = buf.charAt(buf.length() - 1);
+
+            if (lastChar != '\'' && inside) {
+                buf.append('\'');
+            }
+        }
+        return buf.toString();
+    }
+
+    private static String quote(String str, boolean insideQuotes)
+    {
+        String retVal = str;
+        if (!insideQuotes) {
+            retVal = '\'' + retVal + '\'';
+        }
+        return retVal;
+    }
+
+    /**
+     * try to get the Java Date/Time formating associated with the C standard provided.
+     * 
+     * @param c
+     *            The C equivalent to translate
+     * @return The Java formatting rule to use
+     */
+    private static boolean translateCommand(StringBuffer buf, String pattern, int index,
+            boolean oldInside)
+    {
+        char firstChar = pattern.charAt(index);
+        boolean newInside = oldInside;
+
+        // O and E are modifiers, they mean to present an alternative representation of the next
+        // char
+        // we just handle the next char as if the O or E wasn't there
+        if (firstChar == 'O' || firstChar == 'E') {
+            if (index + 1 < pattern.length()) {
+                newInside = translateCommand(buf, pattern, index + 1, oldInside);
+            } else {
+                buf.append(quote("%" + firstChar, oldInside));
+            }
+        } else {
+            String command = translate.getProperty(String.valueOf(firstChar));
+
+            // If we don't find a format, treat it as a literal--That's what apache does
+            if (command == null) {
+                buf.append(quote("%" + firstChar, oldInside));
+            } else {
+                // If we were inside quotes, close the quotes
+                if (oldInside) {
+                    buf.append('\'');
+                }
+                buf.append(command);
+                newInside = false;
+            }
+        }
+        return newInside;
+    }
+}

Added: tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/DropdownTimePicker.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/DropdownTimePicker.js?rev=413401&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/DropdownTimePicker.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/DropdownTimePicker.js Sat Jun 10 19:30:27 2006
@@ -0,0 +1,58 @@
+dojo.provide("tapestry.widget.DropdownTimePicker");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.DropdownContainer");
+dojo.require("dojo.widget.TimePicker");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html");
+
+dojo.widget.defineWidget(
+	"tapestry.widget.DropdownTimePicker",
+	dojo.widget.DropdownContainer,
+	{
+		iconURL: dojo.uri.dojoUri("../tapestry/widget/templates/images/timeIcon.gif"),
+		iconAlt: "Select a Time",
+		zIndex: "10",
+		timePicker: null,
+		
+		dateFormat: "%I:%M %p",
+		date: null,
+		
+		fillInTemplate: function(args, frag){
+			tapestry.widget.DropdownTimePicker.superclass.fillInTemplate.call(this, args, frag);
+			var source = this.getFragNodeRef(frag);
+			
+			if(args.date){ this.date = args.date; }
+			
+			var dpNode = document.createElement("div");
+			this.containerNode.appendChild(dpNode);
+			
+			var dateProps = { widgetContainerId: this.widgetId };
+			if(this.date){
+				dateProps["date"] = this.date;
+				dateProps["storedDate"] = dojo.widget.TimePicker.util.toRfcDateTime(this.date);
+				this.inputNode.value = dojo.date.format(this.date, this.dateFormat);
+			}
+			this.timePicker = dojo.widget.createWidget("TimePicker", dateProps, dpNode);
+			dojo.event.connect(this.timePicker, "onSetTime", this, "onSetTime");
+			this.containerNode.style.zIndex = this.zIndex;
+			this.containerNode.style.backgroundColor = "transparent";
+		},
+		
+		onSetTime: function(){
+			this.inputNode.value = dojo.date.format(this.timePicker.time, this.dateFormat);
+			this.hideContainer();
+		},
+		
+		onInputChange: function(){
+			var tmp = new Date(this.inputNode.value);
+			this.timePicker.time = tmp;
+			this.timePicker.setDateTime(dojo.widget.TimePikcer.util.toRfcDateTime(tmp));
+			this.timePicker.initData();
+			this.timePicker.initUI();
+		}
+	},
+	"html"
+);
+
+dojo.widget.tags.addParseTreeHandler("dojo:dropdowntimepicker");

Propchange: tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/DropdownTimePicker.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/templates/images/timeIcon.gif
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/templates/images/timeIcon.gif?rev=413401&view=auto
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/templates/images/timeIcon.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_datetime.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_datetime.js?rev=413401&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_datetime.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_datetime.js Sat Jun 10 19:30:27 2006
@@ -0,0 +1,16 @@
+dojo.require("dojo.date");
+
+dojo.setModulePrefix("tapestry", "../tapestry");
+
+dojo.require("tapestry.*");
+dojo.require("tapestry.test");
+
+function test_time_format(){
+	var dt = new Date();
+	var value = dojo.date.format(dt, "%I:%M %p");
+	jum.assertTrue(value, value.indexOf("NaN") < 0);
+	
+	dt = new Date("03:00 am");
+	value = dojo.date.format(dt, "%I:%M %p");
+	jum.assertTrue(value, value.indexOf("NaN") < 0);
+}

Propchange: tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_datetime.js
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/asset/TestUnprotectedAsset.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/asset/TestUnprotectedAsset.java?rev=413401&r1=413400&r2=413401&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/asset/TestUnprotectedAsset.java (original)
+++ tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/asset/TestUnprotectedAsset.java Sat Jun 10 19:30:27 2006
@@ -153,4 +153,18 @@
         assertTrue(rm.containsResource("/org/apache/tapestry/html/dojo/src/test.png"));
     }
     
+    public void testCssPaths()
+    {
+        AssetService service = new AssetService();
+        String path = "/dojo/src/widget/template/HtmlComboBox.cssimages/foo.gif";
+        
+        assertEquals("/dojo/src/widget/template/images/foo.gif", service.translateCssPath(path));
+        assertEquals("/boo/templates/things/", 
+                service.translateCssPath("/boo/templates/somethingdumb.cssthings/"));
+        assertEquals("/foo/path/css/images.png", 
+                service.translateCssPath("/foo/path/css/images.png"));
+        assertEquals("/things/mytemplate.css",
+                service.translateCssPath("/things/mytemplate.css"));
+        assertNull(service.translateCssPath(null));
+    }
 }

Added: tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/util/StrftimeTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/util/StrftimeTest.java?rev=413401&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/util/StrftimeTest.java (added)
+++ tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/util/StrftimeTest.java Sat Jun 10 19:30:27 2006
@@ -0,0 +1,33 @@
+// Copyright Jun 10, 2006 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.util;
+
+import org.apache.hivemind.test.HiveMindTestCase;
+
+
+/**
+ * Tests functionality of {@link Strftime}.
+ * 
+ * @see {@linkplain http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html} for list of assertions
+ * @author jkuhnert
+ */
+public class StrftimeTest extends HiveMindTestCase
+{
+
+    public void testPosixFormat()
+    {
+        assertEquals("%m/%d/%Y", Strftime.convertToPosixFormat("MM/dd/yyyy"));
+        assertEquals("%H:%M:%S at %p", Strftime.convertToPosixFormat("HH:mm:ss at a"));
+    }
+}

Modified: tapestry/tapestry4/trunk/status.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/status.xml?rev=413401&r1=413400&r2=413401&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/status.xml (original)
+++ tapestry/tapestry4/trunk/status.xml Sat Jun 10 19:30:27 2006
@@ -104,6 +104,9 @@
   	  <action type="fix" dev="AA" fixes-bug="TAPESTRY-829" due-to="Ido M. Tamir">
   		FormLinkRenderer throws NPE with DirectlLinks.
   	  </action>       
+      <action type="fix" dev="JK" fixes-bug="TAPESTRY-952" >
+        Added logic to asset service that checks for incoming css file relative paths.
+      </action>
     </release>
     <release version="4.0.1" date="unreleased" >
       <action type="fix" dev="JK" fixes-bug="TAPESTRY-863" due-to="unknown contributor">