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/05/30 20:44:14 UTC

svn commit: r410343 - 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/ fram...

Author: jkuhnert
Date: Tue May 30 11:44:13 2006
New Revision: 410343

URL: http://svn.apache.org/viewvc?rev=410343&view=rev
Log:
More tests, start of log control system in browser

Added:
    tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/TDebugConsole.js   (with props)
    tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/templates/TDebugConsole.html   (with props)
    tapestry/tapestry4/trunk/framework/src/js/tests/test_debug.js   (with props)
    tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_TDebugConsole.html   (with props)
    tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/engine/DirectEventServiceTest.java
Modified:
    tapestry/tapestry4/trunk/build.xml
    tapestry/tapestry4/trunk/examples/TimeTracker/src/context/Home.html
    tapestry/tapestry4/trunk/examples/TimeTracker/src/context/WEB-INF/Border.html
    tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/dojo.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/build.xml
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/AjaxShellDelegate.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/html/WidgetEvent.script
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/DirectEventService.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/EngineMessages.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/EngineStrings.properties
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/event/BrowserEvent.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.jwc
    tapestry/tapestry4/trunk/framework/src/js/build.xml
    tapestry/tapestry4/trunk/framework/src/js/tapestry/test.js
    tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/DropDownDatePicker.js
    tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/TDatePicker.js
    tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/__package__.js
    tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_DropDownDatePicker.html

Modified: tapestry/tapestry4/trunk/build.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/build.xml?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/build.xml (original)
+++ tapestry/tapestry4/trunk/build.xml Tue May 30 11:44:13 2006
@@ -23,6 +23,7 @@
 
 	<filelist id="project.modules" dir="." files="
 			framework/build.xml 
+			framework/src/js/build.xml 
 			portlet/build.xml 
 			contrib/build.xml 
 			annotations/build.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=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/examples/TimeTracker/src/context/Home.html (original)
+++ tapestry/tapestry4/trunk/examples/TimeTracker/src/context/Home.html Tue May 30 11:44:13 2006
@@ -1,6 +1,7 @@
 <span jwcid="@Border">
 
-<p>This is the Tapestry TimeTracker application. It is a demonstration of some of the new
+<p>
+This is the Tapestry TimeTracker application. It is a demonstration of some of the new
 core features available in tapestry, as well as how a sample application might be built
 using them.
 </p>

Modified: tapestry/tapestry4/trunk/examples/TimeTracker/src/context/WEB-INF/Border.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/examples/TimeTracker/src/context/WEB-INF/Border.html?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/examples/TimeTracker/src/context/WEB-INF/Border.html (original)
+++ tapestry/tapestry4/trunk/examples/TimeTracker/src/context/WEB-INF/Border.html Tue May 30 11:44:13 2006
@@ -1,4 +1,7 @@
-<html jwcid="@Shell" title="message:window.title" ajaxEnabled="true" >
+<html jwcid="@Shell" 
+	  title="message:window.title" 
+	  ajaxEnabled="true" 
+	  browserLogLevel="DEBUG" >
 
 <link rel="shortcut icon" href="favicon.ico" type="image/gif" />
 <link href="css/timetracker.css" rel="stylesheet" type="text/css" media="all" />

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=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/dojo.css (original)
+++ tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/dojo.css Tue May 30 11:44:13 2006
@@ -11,7 +11,7 @@
     width: 50%;
     border-top: 1px solid #ddd;
     border-right: 1px solid #ddd;
-    position: fixed;
+    position: absolute;
     overflow: auto;
     left: 0px;
     bottom: 0px;
@@ -22,6 +22,6 @@
     font: 9px lucida grande, Arial, Verdana;
     z-index: 2000;
     opacity: 0.8;
-    filter: alpha(opacity :   80);
+    filter: alpha(opacity : 80);
     background: #eef1f8;
 }

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=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/timetracker.css (original)
+++ tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/timetracker.css Tue May 30 11:44:13 2006
@@ -84,4 +84,5 @@
     padding-right: 6px;
     float:left;
     clear:both;
+    width:95%;
 }

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=410343&r1=410342&r2=410343&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 Tue May 30 11:44:13 2006
@@ -75,8 +75,7 @@
      * Invoked when an item is selected from the project
      * selection list.
      */
-    @EventListener(events = {"selectOption", "onChange"}, 
-            targets = { "projectChoose" }, elements = { "startPicker" })
+    @EventListener(events = "selectOption", targets = "projectChoose")
     public void projectSelected()
     {
         _log.debug("projectSelected()");

Modified: tapestry/tapestry4/trunk/framework/build.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/build.xml?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/build.xml (original)
+++ tapestry/tapestry4/trunk/framework/build.xml Tue May 30 11:44:13 2006
@@ -77,7 +77,7 @@
 	<property name="dojo.js.dir" value="${js.dir}/dojo" />
 	<property name="tapestry.js.dir" value="${js.dir}/tapestry" />
 	
- <target name="compile" depends="compile-dependencies,create-version-file">
+  <target name="compile" depends="compile-dependencies,create-version-file">
  	<copy todir="${java.classes.dir}/dojo" overwrite="true" preservelastmodified="true">
  		<fileset dir="${dojo.js.dir}" />
  	</copy>

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/AjaxShellDelegate.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/AjaxShellDelegate.java?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/AjaxShellDelegate.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/AjaxShellDelegate.java Tue May 30 11:44:13 2006
@@ -13,6 +13,7 @@
 // limitations under the License.
 package org.apache.tapestry.dojo;
 
+import org.apache.hivemind.util.Defense;
 import org.apache.tapestry.IAsset;
 import org.apache.tapestry.IMarkupWriter;
 import org.apache.tapestry.IRender;
@@ -27,6 +28,17 @@
  */
 public class AjaxShellDelegate implements IRender
 {
+    /** Client side debug log level. */
+    public static final String BROWSER_LOG_DEBUG="DEBUG";
+    /** Client side info log level. */
+    public static final String BROWSER_LOG_INFO="INFO";
+    /** Client side warning log level. */
+    public static final String BROWSER_LOG_WARNING="WARNING";
+    /** Client side error log level. */
+    public static final String BROWSER_LOG_ERROR="ERROR";
+    /** Client side critical log level. */
+    public static final String BROWSER_LOG_CRITICAL="CRITICAL";
+    
     private IAsset _dojoSource;
     
     private IAsset _dojoPath;
@@ -35,6 +47,8 @@
     
     private IEngineService _assetService;
     
+    private String _browserLogLevel = BROWSER_LOG_WARNING;
+    
     /**
      * {@inheritDoc}
      */
@@ -64,7 +78,35 @@
                 _tapestrySource.getResourceLocation()
                 .getPath()).getAbsoluteURL()).append("\"></script>");
         
+        // logging configuration
+        str.append("\n<script type=\"text/javascript\">")
+        .append("dojo.require(\"dojo.logging.Logger\");\n")
+        .append("dojo.log.setLevel(dojo.log.getLevel(\"").append(_browserLogLevel)
+        .append("\"));</script>");
+        
         writer.printRaw(str.toString());
+    }
+    
+    /**
+     * Sets the dojo logging level. Similar to log4j style
+     * log levels. 
+     * @param level The string constant for the level, valid values
+     *              are:
+     *              <p>
+     *              <ul>
+     *              <li>{@link #BROWSER_LOG_DEBUG}</li>
+     *              <li>{@link #BROWSER_LOG_INFO}</li>
+     *              <li>{@link #BROWSER_LOG_WARNING}</li>
+     *              <li>{@link #BROWSER_LOG_ERROR}</li>
+     *              <li>{@link #BROWSER_LOG_CRITICAL}</li>
+     *              </ul>
+     *              </p>
+     */
+    public void setLogLevel(String level)
+    {
+        Defense.notNull("level", level);
+        
+        _browserLogLevel = level;
     }
     
     /**

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/html/WidgetEvent.script
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/html/WidgetEvent.script?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/html/WidgetEvent.script (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/html/WidgetEvent.script Tue May 30 11:44:13 2006
@@ -21,7 +21,7 @@
             var content={beventname:"${event}"};
             tapestry.event.buildEventProperties(e, content);
             if (!content["beventtarget.id"]) content["beventtarget.id"]="${component.id}";
-            
+            dojo.debug("Selected value " + dojo.widget.byId("${component.id}").comboBoxSelectionValue.value);
             dojo.io.bind({
                 url:"${url}",
                 content:content,

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/DirectEventService.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/DirectEventService.java?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/DirectEventService.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/DirectEventService.java Tue May 30 11:44:13 2006
@@ -146,17 +146,16 @@
 
     protected void triggerComponent(IRequestCycle cycle, IDirectEvent direct, Object[] parameters)
     {
-        BrowserEvent event = null;
-        if (BrowserEvent.hasBrowserEvent(cycle)) {
-            event = new BrowserEvent(cycle);
-            
-            Object[] parms = new Object[parameters.length + 1];
-            System.arraycopy(parameters, 0, parms, 0, parameters.length);
-            parms[parms.length - 1] = event;
-            
-            cycle.setListenerParameters(parms);
-        } else
-            throw new ApplicationRuntimeException("No browser event found in request.");
+        if (!BrowserEvent.hasBrowserEvent(cycle))
+            throw new ApplicationRuntimeException(EngineMessages.noBrowserEvent());
+        
+        BrowserEvent event = new BrowserEvent(cycle);
+        
+        Object[] parms = new Object[parameters.length + 1];
+        System.arraycopy(parameters, 0, parms, 0, parameters.length);
+        parms[parms.length - 1] = event;
+        
+        cycle.setListenerParameters(parms);
         
         direct.triggerEvent(cycle, event);
     }

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/EngineMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/EngineMessages.java?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/EngineMessages.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/EngineMessages.java Tue May 30 11:44:13 2006
@@ -52,6 +52,11 @@
         return _formatter.format("page-not-compatible", page.getPageName(), expectedType.getName());
     }
 
+    public static String noBrowserEvent()
+    {
+        return _formatter.format("missing-browser-event", new Object[]{});
+    }
+    
     static String exceptionDuringCleanup(Throwable cause)
     {
         return _formatter.format("exception-during-cleanup", cause);

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/EngineStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/EngineStrings.properties?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/EngineStrings.properties (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/engine/EngineStrings.properties Tue May 30 11:44:13 2006
@@ -23,3 +23,5 @@
 exception-during-cleanup=Exception during post-request cleanup: {0}
 
 validate-cycle=A validate cycle during page activation was detected: {0}.
+
+missing-browser-event=A direct event call was made but no browser event was found in the request.

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/event/BrowserEvent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/event/BrowserEvent.java?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/event/BrowserEvent.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/event/BrowserEvent.java Tue May 30 11:44:13 2006
@@ -27,17 +27,17 @@
  */
 public class BrowserEvent
 {
-    static final String NAME="beventname";
-    static final String TYPE="beventtype";
-    static final String KEYS="beventkeys";
-    static final String CHAR_CODE="beventcharCode";
-    static final String PAGE_X="beventpageX";
-    static final String PAGE_Y="beventpageY";
-    static final String LAYER_X="beventlayerX";
-    static final String LAYER_Y="beventlayerY";
+    public static final String NAME="beventname";
+    public static final String TYPE="beventtype";
+    public static final String KEYS="beventkeys";
+    public static final String CHAR_CODE="beventcharCode";
+    public static final String PAGE_X="beventpageX";
+    public static final String PAGE_Y="beventpageY";
+    public static final String LAYER_X="beventlayerX";
+    public static final String LAYER_Y="beventlayerY";
     
-    static final String TARGET="beventtarget";
-    static final String TARGET_ATTR_ID="id";
+    public static final String TARGET="beventtarget";
+    public static final String TARGET_ATTR_ID="id";
     
     private String _name;
     private String _type;

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.java?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.java Tue May 30 11:44:13 2006
@@ -71,12 +71,12 @@
             writer.println();
 
             writeMetaTag(writer, "name", "generator", GENERATOR_CONTENT);
-
+            
             if (getRenderContentType())
                 writeMetaTag(writer, "http-equiv", "Content-Type", writer.getContentType());
             
             if (getRenderBaseTag())
-            getBaseTagWriter().render(writer, cycle);
+                getBaseTagWriter().render(writer, cycle);
             
             writer.begin("title");
             

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.jwc
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.jwc?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.jwc (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/Shell.jwc Tue May 30 11:44:13 2006
@@ -107,6 +107,13 @@
      </description>
   </parameter>
   
+  <parameter name="browserLogLevel" default-value="literal:WARNING">
+    <description>
+    Sets the default browser based log level. Default value is WARNING. Uses
+    the dojo.log API.
+    </description>
+  </parameter>
+  
   <parameter name="ajaxEnabled" 
              default-value="false" >
      <description>
@@ -148,6 +155,7 @@
    <set name="assetService" value="assetService" />
    <set name="dojoPath" value="dojoPath" />
    <set name="tapestrySource" value="tapestrySource" />
+   <set name="logLevel" value="browserLogLevel" />
   </bean>
   
   <asset name="defaultDojoSource" path="classpath:/dojo/dojo.js" />

Modified: tapestry/tapestry4/trunk/framework/src/js/build.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/build.xml?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/build.xml (original)
+++ tapestry/tapestry4/trunk/framework/src/js/build.xml Tue May 30 11:44:13 2006
@@ -39,7 +39,7 @@
 	<taskdef name="dojo-test" classname="org.dojotoolkit.ant.DojoTestTask" 
 			classpath="lib/ant-dojotest.jar" />
 	
-	<import file="${hivebuild.dir}/jar-module.xml" />
+	<import file="${hivebuild.dir}/module.xml" />
 	
 	<target name="check-dependencies" description="Ensures that dojo.dir is set.">
 
@@ -61,29 +61,25 @@
 			<property name="docless" value="true" />
 			<property name="profile" value="tapestry" />
 		</ant>
-
-		<copy todir="${root.dir}/bin/org/apache/tapestry/html" overwrite="true">
+		
+		<copy todir="${java.classes.dir}/dojo" overwrite="true">
 			<fileset dir="${release.dir}">
 				<exclude name="dojo/demos/**" />
+				<exclude name="dojo/tests/**" />
 			</fileset>
 		</copy>
 	</target>
 	
-	<target name="copy-libs">
-		<copy todir="${root.dir}/bin/org/apache/tapestry/html" overwrite="true">
-			<fileset dir="${release.dir}">
-				<exclude name="dojo/demos/**" />
-			</fileset>
-		</copy>
+	<target name="install" >
+	
 	</target>
 	
 	<!-- ====================================================== -->
 	<!-- Testing												-->
 	<!-- ====================================================== -->
 	
-	<target name="test-js" description="Tests tapestry js package with dojo test utils." >
+	<target name="run-tests" description="Tests tapestry js package with dojo test utils." >
 		 <dojo-test dojosrc="./dojo/" testsrc="tests"/>
-		<!-- <dojo-test dojosrc="${dojo.dir}/../" testsrc="tests"/> -->
 	</target>
 	
 </project>

Modified: tapestry/tapestry4/trunk/framework/src/js/tapestry/test.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/test.js?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tapestry/test.js (original)
+++ tapestry/tapestry4/trunk/framework/src/js/tapestry/test.js Tue May 30 11:44:13 2006
@@ -1,5 +1,7 @@
 dojo.provide("tapestry.test");
 
+if (dj_undef("byId", dj_global)) {
 dojo.byId=function(id) {
 	return document.getElementById(id);
-};
\ No newline at end of file
+}
+}
\ No newline at end of file

Modified: tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/DropDownDatePicker.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/DropDownDatePicker.js?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/DropDownDatePicker.js (original)
+++ tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/DropDownDatePicker.js Tue May 30 11:44:13 2006
@@ -1,5 +1,4 @@
 dojo.provide("tapestry.widget.DropDownDatePicker");
-dojo.widget.manager.registerWidgetPackage("tapestry.widget");
 
 dojo.require("dojo.widget");
 dojo.require("dojo.widget.HtmlWidget");
@@ -8,11 +7,13 @@
 dojo.require("dojo.html");
 dojo.require("dojo.date");
 
+dojo.widget.tags.addParseTreeHandler("dojo:dropdowndatepicker");
+
 tapestry.widget.DropDownDatePicker = function(){
 	
 	dojo.widget.HtmlWidget.call(this);
 	this.widgetType = "DropDownDatePicker";
-	
+	this.subWidgetType="";
 	this.templateString = '<div><input type="text" value="" style="vertical-align:middle;" dojoAttachPoint="valueInputNode" /> <img src="" alt="" dojoAttachPoint="containerDropdownNode" dojoAttachEvent="onclick: onDropdown;" style="vertical-align:middle; cursor:pointer; cursor:hand;" /><div dojoAttachPoint="subWidgetContainerNode" class="dropDownContainer"><div dojoAttachPoint="subWidgetNode" class="subWidgetContainer"></div></div></div>';
 	this.templateCssPath = "";
 	
@@ -67,12 +68,8 @@
 dojo.inherits(tapestry.widget.DropDownDatePicker, dojo.widget.HtmlWidget);
 
 dojo.lang.extend(tapestry.widget.DropDownDatePicker, {
-	
 	//	default attributes
 	dateFormat:"%m/%d/%Y", //see <http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html>
-	dateIconPath:"../../tapestry/widget/templates/images/dateIcon.gif",
+	dateIconPath:"templates/images/dateIcon.gif",
 	inputWidth:"6em"
-	
 });
-
-dojo.widget.tags.addParseTreeHandler("dojo:dropdowndatepicker");
\ No newline at end of file

Modified: tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/TDatePicker.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/TDatePicker.js?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/TDatePicker.js (original)
+++ tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/TDatePicker.js Tue May 30 11:44:13 2006
@@ -1,4 +1,5 @@
 dojo.provide("tapestry.widget.TDatePicker");
+
 dojo.require("dojo.widget.DatePicker");
 dojo.require("dojo.widget.html.DatePicker");
 

Added: tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/TDebugConsole.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/TDebugConsole.js?rev=410343&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/TDebugConsole.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/TDebugConsole.js Tue May 30 11:44:13 2006
@@ -0,0 +1,50 @@
+dojo.provide("tapestry.widget.TDebugConsole");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.Menu2");
+dojo.require("dojo.lang");
+dojo.require("dojo.html");
+dojo.require("dojo.event.*");
+dojo.widget.tags.addParseTreeHandler("dojo:tdebugConsole");
+
+tapestry.widget.TDebugConsole=function(){
+	dojo.widget.HtmlWidget.call(this);
+	this.widgetType="TDebugConsole";
+	this.isContainer=false;
+};
+
+dojo.inherits(tapestry.widget.TDebugConsole, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(tapestry.widget.TDebugConsole, {
+	templatePath:dojo.uri.dojoUri("../tapestry/widget/templates/TDebugConsole.html"),
+	templateCssPath:null,
+	
+	fillInTemplate:function(){
+		document.getElementById("debug").appendChild(this.domNode);
+		
+		var mbar = dojo.widget.createWidget("MenuBar2", 
+											{widgetId:"mbar"}, 
+											this.menuBar);
+		var mbaritem1 = dojo.widget.createWidget("MenuBarItem2", 
+												{submenuId:"submenu1",
+												caption:"View",widgetId:"mainFile"}, 
+												this.menuBarItem1);
+		mbar.addChild(mbaritem1);
+		
+		var popup = dojo.widget.createWidget("PopupMenu2", 
+											{widgetId:"submenu1"}, 
+											this.popupMenu2);
+		var mitem = dojo.widget.createWidget("MenuItem2", 
+											{widgetId:"mitem1",
+											caption:"INFO"}, 
+											this.popupMenuItem1);
+		popup.addChild(mitem);
+		
+		dojo.event.connect(mitem, "onClick", function(e){alert('hello world');});
+	},
+	
+	postCreate:function(){
+	}
+	
+});
\ No newline at end of file

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

Modified: tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/__package__.js?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/__package__.js (original)
+++ tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/__package__.js Tue May 30 11:44:13 2006
@@ -4,3 +4,4 @@
 	]
 });
 dojo.provide("tapestry.widget.*");
+dojo.widget.manager.registerWidgetPackage("tapestry.widget");
\ No newline at end of file

Added: tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/templates/TDebugConsole.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/templates/TDebugConsole.html?rev=410343&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/templates/TDebugConsole.html (added)
+++ tapestry/tapestry4/trunk/framework/src/js/tapestry/widget/templates/TDebugConsole.html Tue May 30 11:44:13 2006
@@ -0,0 +1,9 @@
+<div dojoAttachPoint="menuBar" >
+	<div dojoAttachPoint="menuBarItem1" ></div>
+	<div dojoAttachPoint="menuBarItem2" ></div>
+	<div dojoAttachPoint="menuBarItem3" ></div>
+</div>
+
+<div dojoAttachPoint="popupMenu2" >
+	<div dojoAttachPoint="popupMenuItem1" ></div>
+</div>

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

Added: tapestry/tapestry4/trunk/framework/src/js/tests/test_debug.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tests/test_debug.js?rev=410343&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tests/test_debug.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/tests/test_debug.js Tue May 30 11:44:13 2006
@@ -0,0 +1,27 @@
+dojo.require("dojo.logging.Logger");
+
+function test_debug_log(){
+	dojo.log.debug("Debug message.");
+	dojo.log.info("Info message");
+	dojo.log.err("Error message.");
+	dojo.log.warn("Warning message");
+	dojo.log.crit("Critical message");
+}
+
+function test_debug_logLevel(){
+	dojo.log.info("info msg");
+	
+	dojo.log.setLevel(dojo.log.getLevel("WARNING"));
+	dojo.log.info("SHOULD NOT SEE THIS");
+	var last = dojo.logging.logQueueHandler.data.pop();
+	jum.assertEquals("filterwarn", "info msg", last.message);
+	
+	var currLength = dojo.logging.logQueueHandler.data.length;
+	dojo.log.debug("DEFINITELY SHOULDNT see this");
+	jum.assertEquals("logmsglength", currLength, dojo.logging.logQueueHandler.data.length);
+	
+	currLength = dojo.logging.logQueueHandler.data.length;
+	dojo.log.warn("Filtered warning");
+	dojo.log.err("Filtered error");
+	jum.assertEquals("logmsgfilteredlength", currLength + 2, dojo.logging.logQueueHandler.data.length);
+}
\ No newline at end of file

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

Modified: tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_DropDownDatePicker.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_DropDownDatePicker.html?rev=410343&r1=410342&r2=410343&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_DropDownDatePicker.html (original)
+++ tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_DropDownDatePicker.html Tue May 30 11:44:13 2006
@@ -10,11 +10,11 @@
 
 <script type="text/javascript">
 var djConfig = {
-    isDebug: true,
-    debugAtAllCosts: true
+    isDebug: true
 };
 </script>
-<script type="text/javascript" src="../../../java/org/apache/tapestry/html/dojo/dojo.js"></script>
+<script type="text/javascript" src="../../dojo/dojo.js"></script>
+<script type="text/javascript" src="../../tapestry/core.js"></script>
 <style type="text/css">
 body { font-family : sans-serif; }
 
@@ -112,15 +112,12 @@
 
 </head>
 <script type="text/javascript">
-    dojo.setModulePrefix("tapestry", "../../../../../../js/tapestry"); 
-    dojo.setModulePrefix("tapestry.widget", "../../../../../../js/tapestry/widget"); 
-    
     dojo.require("tapestry.widget.DropDownDatePicker");
 </script>
 <body>
 
 <p>
-<div dojoType="DropDownDatePicker" subWidgetType="DatePicker" widgetId="date1" />
+<div dojoType="DropDownDatePicker" subWidgetType="TDatePicker" widgetId="date1" ></div>
 </p>
 
 </body>

Added: tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_TDebugConsole.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_TDebugConsole.html?rev=410343&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_TDebugConsole.html (added)
+++ tapestry/tapestry4/trunk/framework/src/js/tests/widget/test_TDebugConsole.html Tue May 30 11:44:13 2006
@@ -0,0 +1,81 @@
+<!--
+<!DOCTYPE html
+    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<title>DebugConsole Test</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+
+<script type="text/javascript">
+var djConfig = {
+    isDebug: true
+};
+</script>
+<script type="text/javascript" src="../../dojo/dojo.js"></script>
+<script type="text/javascript" src="../../tapestry/core.js"></script>
+</head>
+
+<body>
+<style>
+:link,:visited { text-decoration:none }
+
+/* no list-markers by default, since lists are used more often for semantics */
+ul,ol { list-style:none }
+
+/* avoid browser default inconsistent heading font-sizes */
+/* and pre/code too */
+h1,h2,h3,h4,h5,h6,pre,code { font-size:1em; }
+
+/* remove the inconsistent (among browsers) default ul,ol padding or margin  */
+/* the default spacing on headings does not match nor align with 
+   normal interline spacing at all, so let's get rid of it. */
+/* zero out the spacing around pre, form, body, html, p, blockquote as well */
+/* form elements are oddly inconsistent, and not quite CSS emulatable. */
+/*  nonetheless strip their margin and padding as well */
+ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,body,html,p,blockquote,fieldset,input
+{ margin:0; padding:0 }
+
+/* whoever thought blue linked image borders were a good idea? */
+a img,:link img,:visited img { border:none }
+
+/* de-italicize address */
+address { font-style:normal }
+
+body { margin:0; padding:0; }
+
+fieldset { border:0; }
+
+#debug {
+    display: block;
+    height: 80px;
+    width: 50%;
+    border-top: 1px solid #ddd;
+    border-right: 1px solid #ddd;
+    position: absolute;
+    overflow: auto;
+    left: 0px;
+    bottom: 0px;
+    text-align: left;
+    padding: 0px;
+    margin-top:0px;
+    padding-right: 0;
+    color: #000;
+    font: 9px lucida grande, Arial, Verdana;
+    opacity: 0.8;
+    filter: alpha(opacity : 80);
+    background: #eef1f8;
+}
+</style>
+
+<script type="text/javascript">
+	dojo.require("tapestry.widget.*");
+    dojo.require("tapestry.widget.TDebugConsole");
+</script>
+
+<div id="debug">
+<div dojoType="TDebugConsole" ></div>
+</div>
+</body>
+</html>
\ No newline at end of file

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

Added: tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/engine/DirectEventServiceTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/engine/DirectEventServiceTest.java?rev=410343&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/engine/DirectEventServiceTest.java (added)
+++ tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/engine/DirectEventServiceTest.java Tue May 30 11:44:13 2006
@@ -0,0 +1,517 @@
+// Copyright 2004, 2005 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.engine;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.hivemind.ApplicationRuntimeException;
+import org.apache.hivemind.Location;
+import org.apache.hivemind.test.AggregateArgumentsMatcher;
+import org.apache.hivemind.test.ArgumentMatcher;
+import org.apache.tapestry.IComponent;
+import org.apache.tapestry.IDirectEvent;
+import org.apache.tapestry.IPage;
+import org.apache.tapestry.IRequestCycle;
+import org.apache.tapestry.IgnoreMatcher;
+import org.apache.tapestry.StaleSessionException;
+import org.apache.tapestry.event.BrowserEvent;
+import org.apache.tapestry.services.LinkFactory;
+import org.apache.tapestry.services.ResponseRenderer;
+import org.apache.tapestry.services.ServiceConstants;
+import org.apache.tapestry.web.WebRequest;
+import org.apache.tapestry.web.WebSession;
+
+/**
+ * Tests for {@link org.apache.tapestry.engine.DirectService}.
+ * 
+ * @author Howard M. Lewis Ship
+ * @since 4.0
+ */
+public class DirectEventServiceTest extends ServiceTestCase
+{
+    protected IDirectEvent newDirect()
+    {
+        return (IDirectEvent) newMock(IDirectEvent.class);
+    }
+
+    public void testGetLinkOnSamePage()
+    {
+        IPage page = newPage("ThePage");
+        IDirectEvent c = newDirect();
+        IRequestCycle cycle = newCycle();
+        WebRequest request = newWebRequest(false, null);
+        LinkFactory lf = newLinkFactory();
+        ILink link = newLink();
+
+        trainGetPage(cycle, page);
+        trainGetPage(c, page);
+        trainGetIdPath(c, "fred.barney");
+
+        Object[] serviceParameters = new Object[0];
+
+        Map parameters = new HashMap();
+
+        parameters.put(ServiceConstants.PAGE, "ThePage");
+        parameters.put(ServiceConstants.COMPONENT, "fred.barney");
+        parameters.put(ServiceConstants.CONTAINER, null);
+        parameters.put(ServiceConstants.SESSION, null);
+        parameters.put(ServiceConstants.PARAMETER, serviceParameters);
+
+        DirectEventService ds = new DirectEventService();
+
+        ds.setLinkFactory(lf);
+        ds.setRequest(request);
+        ds.setRequestCycle(cycle);
+
+        trainConstructLink(lf, ds, false, parameters, true, link);
+
+        replayControls();
+
+        assertSame(link, ds.getLink(false, new DirectEventServiceParameter(c, serviceParameters)));
+
+        verifyControls();
+    }
+
+    public void testGetLinkOnSamePageForPost()
+    {
+        IPage page = newPage("ThePage");
+        IDirectEvent c = newDirect();
+        IRequestCycle cycle = newCycle();
+        WebRequest request = newWebRequest(false, null);
+        LinkFactory lf = newLinkFactory();
+        ILink link = newLink();
+
+        trainGetPage(cycle, page);
+        trainGetPage(c, page);
+        trainGetIdPath(c, "fred.barney");
+
+        Object[] serviceParameters = new Object[0];
+
+        Map parameters = new HashMap();
+
+        parameters.put(ServiceConstants.PAGE, "ThePage");
+        parameters.put(ServiceConstants.COMPONENT, "fred.barney");
+        parameters.put(ServiceConstants.CONTAINER, null);
+        parameters.put(ServiceConstants.SESSION, null);
+        parameters.put(ServiceConstants.PARAMETER, serviceParameters);
+
+        DirectEventService ds = new DirectEventService();
+
+        ds.setLinkFactory(lf);
+        ds.setRequest(request);
+        ds.setRequestCycle(cycle);
+
+        trainConstructLink(lf, ds, true, parameters, true, link);
+
+        replayControls();
+
+        assertSame(link, ds.getLink(true, new DirectEventServiceParameter(c, serviceParameters)));
+
+        verifyControls();
+    }
+
+    public void testGetLinkOnSamePageStateful()
+    {
+        IPage page = newPage("ThePage");
+        IDirectEvent c = newDirect();
+        IRequestCycle cycle = newCycle();
+        WebSession session = newWebSession();
+        WebRequest request = newWebRequest(false, session);
+        LinkFactory lf = newLinkFactory();
+        ILink link = newLink();
+
+        trainGetPage(cycle, page);
+        trainGetPage(c, page);
+        trainGetIdPath(c, "fred.barney");
+
+        Object[] serviceParameters = new Object[0];
+
+        Map parameters = new HashMap();
+
+        parameters.put(ServiceConstants.PAGE, "ThePage");
+        parameters.put(ServiceConstants.COMPONENT, "fred.barney");
+        parameters.put(ServiceConstants.CONTAINER, null);
+        parameters.put(ServiceConstants.SESSION, "T");
+        parameters.put(ServiceConstants.PARAMETER, serviceParameters);
+
+        DirectEventService ds = new DirectEventService();
+        ds.setLinkFactory(lf);
+        ds.setRequest(request);
+        ds.setRequestCycle(cycle);
+
+        trainConstructLink(lf, ds, false, parameters, true, link);
+
+        replayControls();
+
+        assertSame(link, ds.getLink(false, new DirectEventServiceParameter(c, serviceParameters)));
+
+        verifyControls();
+    }
+
+    public void testGetLinkOnDifferentPage()
+    {
+        IPage page = newPage("ActivePage");
+        IPage componentPage = newPage("ComponentPage");
+        IDirectEvent c = newDirect();
+        IRequestCycle cycle = newCycle();
+        WebRequest request = newWebRequest(false, null);
+        LinkFactory lf = newLinkFactory();
+        ILink link = newLink();
+
+        trainGetPage(cycle, page);
+        trainGetPage(c, componentPage);
+        trainGetIdPath(c, "fred.barney");
+
+        Object[] serviceParameters = new Object[0];
+
+        Map parameters = new HashMap();
+
+        parameters.put(ServiceConstants.PAGE, "ActivePage");
+        parameters.put(ServiceConstants.COMPONENT, "fred.barney");
+        parameters.put(ServiceConstants.CONTAINER, "ComponentPage");
+        parameters.put(ServiceConstants.SESSION, null);
+        parameters.put(ServiceConstants.PARAMETER, serviceParameters);
+
+        DirectEventService ds = new DirectEventService();
+        ds.setLinkFactory(lf);
+        ds.setRequest(request);
+        ds.setRequestCycle(cycle);
+
+        trainConstructLink(lf, ds, false, parameters, true, link);
+
+        replayControls();
+
+        assertSame(link, ds.getLink(false, new DirectEventServiceParameter(c, serviceParameters)));
+
+        verifyControls();
+    }
+
+    public void testServiceSimple() throws Exception
+    {
+        Object[] parameters = new Object[0];
+        IRequestCycle cycle = newCycle();
+        IPage page = newPage();
+        IDirectEvent d = newDirect();
+        LinkFactory lf = newLinkFactory();
+        ResponseRenderer rr = newResponseRenderer();
+
+        trainGetParameter(cycle, ServiceConstants.COMPONENT, "fred.barney");
+        trainGetParameter(cycle, ServiceConstants.CONTAINER, null);
+        trainGetParameter(cycle, ServiceConstants.PAGE, "ActivePage");
+        trainGetParameter(cycle, ServiceConstants.SESSION, null);
+
+        trainGetPage(cycle, "ActivePage", page);
+        cycle.activate(page);
+
+        trainGetNestedComponent(page, "fred.barney", d);
+
+        trainExtractListenerParameters(lf, cycle, parameters);
+
+        trainExtractBrowserEvent(cycle);
+        
+        cycle.setListenerParameters(parameters);
+        
+        ArgumentMatcher ignore = new IgnoreMatcher();
+        getControl(cycle).setMatcher(new AggregateArgumentsMatcher(new ArgumentMatcher[]
+        {ignore }));
+        
+        d.triggerEvent(cycle, new BrowserEvent(null, null));
+        
+        getControl(d).setMatcher(new AggregateArgumentsMatcher(new ArgumentMatcher[]
+        { null, ignore }));
+        
+        rr.renderResponse(cycle);
+        
+        replayControls();
+
+        DirectEventService ds = new DirectEventService();
+        ds.setLinkFactory(lf);
+        ds.setResponseRenderer(rr);
+
+        ds.service(cycle);
+
+        verifyControls();
+    }
+
+    /**
+     * The complex case is where the component is contained on a different page than the active (at
+     * the time of render) page.
+     */
+    public void testServiceComplex() throws Exception
+    {
+        Object[] parameters = new Object[0];
+        IRequestCycle cycle = newCycle();
+        IPage page = newPage();
+        IPage componentPage = newPage();
+        IDirectEvent d = newDirect();
+        LinkFactory lf = newLinkFactory();
+        ResponseRenderer rr = newResponseRenderer();
+
+        trainGetParameter(cycle, ServiceConstants.COMPONENT, "fred.barney");
+        trainGetParameter(cycle, ServiceConstants.CONTAINER, "ComponentPage");
+        trainGetParameter(cycle, ServiceConstants.PAGE, "ActivePage");
+        trainGetParameter(cycle, ServiceConstants.SESSION, null);
+
+        trainGetPage(cycle, "ActivePage", page);
+
+        cycle.activate(page);
+
+        trainGetPage(cycle, "ComponentPage", componentPage);
+
+        trainGetNestedComponent(componentPage, "fred.barney", d);
+
+        trainExtractListenerParameters(lf, cycle, parameters);
+
+        trainExtractBrowserEvent(cycle);
+        
+        cycle.setListenerParameters(parameters);
+        
+        ArgumentMatcher ignore = new IgnoreMatcher();
+        getControl(cycle).setMatcher(new AggregateArgumentsMatcher(new ArgumentMatcher[]
+        {ignore }));
+        
+        d.triggerEvent(cycle, new BrowserEvent(null, null));
+        
+        getControl(d).setMatcher(new AggregateArgumentsMatcher(new ArgumentMatcher[]
+        { null, ignore }));
+
+        rr.renderResponse(cycle);
+
+        replayControls();
+
+        DirectEventService ds = new DirectEventService();
+        ds.setLinkFactory(lf);
+        ds.setResponseRenderer(rr);
+
+        ds.service(cycle);
+
+        verifyControls();
+    }
+
+    public void testServiceNotDirect() throws Exception
+    {
+        IRequestCycle cycle = newCycle();
+        IPage page = newPage();
+        IComponent c = newComponent();
+        Location l = newLocation();
+
+        trainGetParameter(cycle, ServiceConstants.COMPONENT, "fred.barney");
+        trainGetParameter(cycle, ServiceConstants.CONTAINER, null);
+        trainGetParameter(cycle, ServiceConstants.PAGE, "ActivePage");
+        trainGetParameter(cycle, ServiceConstants.SESSION, null);
+
+        trainGetPage(cycle, "ActivePage", page);
+        cycle.activate(page);
+
+        trainGetNestedComponent(page, "fred.barney", c);
+
+        trainGetExtendedId(c, "ActivePage/fred.barney");
+        trainGetLocation(c, l);
+
+        replayControls();
+
+        DirectEventService ds = new DirectEventService();
+
+        try
+        {
+            ds.service(cycle);
+            unreachable();
+        }
+        catch (ApplicationRuntimeException ex)
+        {
+            assertEquals(
+                    "Component ActivePage/fred.barney does not implement the org.apache.tapestry.IDirectEvent interface.",
+                    ex.getMessage());
+            assertSame(c, ex.getComponent());
+            assertSame(l, ex.getLocation());
+        }
+
+        verifyControls();
+    }
+
+    public void testSessionActiveAndRequired() throws Exception
+    {
+        Object[] parameters = new Object[0];
+        IRequestCycle cycle = newCycle();
+        IPage page = newPage();
+        IDirectEvent d = newDirect();
+        WebSession session = newWebSession(false);
+        WebRequest request = newWebRequest(session);
+        LinkFactory lf = newLinkFactory();
+        ResponseRenderer rr = newResponseRenderer();
+
+        trainGetParameter(cycle, ServiceConstants.COMPONENT, "fred.barney");
+        trainGetParameter(cycle, ServiceConstants.CONTAINER, null);
+        trainGetParameter(cycle, ServiceConstants.PAGE, "ActivePage");
+        trainGetParameter(cycle, ServiceConstants.SESSION, "T");
+
+        trainGetPage(cycle, "ActivePage", page);
+        cycle.activate(page);
+
+        trainGetNestedComponent(page, "fred.barney", d);
+
+        trainIsStateful(d, true);
+
+        trainExtractListenerParameters(lf, cycle, parameters);
+
+        trainExtractBrowserEvent(cycle);
+        
+        cycle.setListenerParameters(parameters);
+        
+        ArgumentMatcher ignore = new IgnoreMatcher();
+        getControl(cycle).setMatcher(new AggregateArgumentsMatcher(new ArgumentMatcher[]
+        {ignore }));
+        
+        d.triggerEvent(cycle, new BrowserEvent(null, null));
+        
+        getControl(d).setMatcher(new AggregateArgumentsMatcher(new ArgumentMatcher[]
+        { null, ignore }));
+
+        rr.renderResponse(cycle);
+
+        replayControls();
+
+        DirectEventService ds = new DirectEventService();
+        ds.setLinkFactory(lf);
+        ds.setResponseRenderer(rr);
+        ds.setRequest(request);
+
+        ds.service(cycle);
+
+        verifyControls();
+    }
+    
+    public void testStaleSession() throws Exception
+    {
+        IRequestCycle cycle = newCycle();
+        IPage page = newPage();
+        IDirectEvent d = newDirect();
+        WebRequest request = newWebRequest(null);
+        Location l = newLocation();
+
+        trainGetParameter(cycle, ServiceConstants.COMPONENT, "fred.barney");
+        trainGetParameter(cycle, ServiceConstants.CONTAINER, null);
+        trainGetParameter(cycle, ServiceConstants.PAGE, "ActivePage");
+        trainGetParameter(cycle, ServiceConstants.SESSION, "T");
+
+        trainGetPage(cycle, "ActivePage", page);
+        cycle.activate(page);
+
+        trainGetNestedComponent(page, "fred.barney", d);
+
+        trainIsStateful(d, true);
+
+        trainGetExtendedId(d, "ActivePage/fred.barney");
+        trainGetLocation(page, l);
+        trainGetPageName(page, "ActivePage");
+
+        replayControls();
+
+        DirectEventService ds = new DirectEventService();
+        ds.setRequest(request);
+
+        try
+        {
+            ds.service(cycle);
+            unreachable();
+        }
+        catch (StaleSessionException ex)
+        {
+            assertEquals(
+                    "Component ActivePage/fred.barney is stateful, but the HttpSession has expired (or has not yet been created).",
+                    ex.getMessage());
+            assertSame(page, ex.getComponent());
+            assertSame(l, ex.getLocation());
+            assertEquals("ActivePage", ex.getPageName());
+            assertSame(page, ex.getPage());
+        }
+
+        verifyControls();
+    }
+    
+    public void testNoBrowserEvent() throws Exception
+    {
+        Object[] parameters = new Object[0];
+        IRequestCycle cycle = newCycle();
+        IPage page = newPage();
+        IDirectEvent d = newDirect();
+        LinkFactory lf = newLinkFactory();
+        ResponseRenderer rr = newResponseRenderer();
+
+        trainGetParameter(cycle, ServiceConstants.COMPONENT, "fred.barney");
+        trainGetParameter(cycle, ServiceConstants.CONTAINER, null);
+        trainGetParameter(cycle, ServiceConstants.PAGE, "ActivePage");
+        trainGetParameter(cycle, ServiceConstants.SESSION, null);
+
+        trainGetPage(cycle, "ActivePage", page);
+        cycle.activate(page);
+
+        trainGetNestedComponent(page, "fred.barney", d);
+
+        trainExtractListenerParameters(lf, cycle, parameters);
+
+        cycle.getParameter(BrowserEvent.NAME);
+        setReturnValue(cycle, null);
+        
+        replayControls();
+        
+        DirectEventService ds = new DirectEventService();
+        ds.setLinkFactory(lf);
+        ds.setResponseRenderer(rr);
+        
+        try {
+            ds.service(cycle);
+            unreachable();
+        } catch (ApplicationRuntimeException e) {
+            assertExceptionSubstring(e, "no browser event was found");
+        }
+        
+        verifyControls();
+    }
+    
+    protected void trainIsStateful(IDirectEvent direct, boolean isStateful)
+    {
+        direct.isStateful();
+        setReturnValue(direct, isStateful);
+    }
+    
+    protected void trainExtractBrowserEvent(IRequestCycle cycle)
+    {
+        cycle.getParameter(BrowserEvent.NAME);
+        setReturnValue(cycle, "onClick");
+        
+        cycle.getParameter(BrowserEvent.NAME);
+        setReturnValue(cycle, "onClick");
+        
+        cycle.getParameter(BrowserEvent.TYPE);
+        setReturnValue(cycle, "click");
+        cycle.getParameters(BrowserEvent.KEYS);
+        setReturnValue(cycle, null);
+        cycle.getParameter(BrowserEvent.CHAR_CODE);
+        setReturnValue(cycle, null);
+        cycle.getParameter(BrowserEvent.PAGE_X);
+        setReturnValue(cycle, "123");
+        cycle.getParameter(BrowserEvent.PAGE_Y);
+        setReturnValue(cycle, "1243");
+        cycle.getParameter(BrowserEvent.LAYER_X);
+        setReturnValue(cycle, null);
+        cycle.getParameter(BrowserEvent.LAYER_Y);
+        setReturnValue(cycle, null);
+        
+        cycle.getParameter(BrowserEvent.TARGET + "." + BrowserEvent.TARGET_ATTR_ID);
+        setReturnValue(cycle, "element1");
+    }
+}
\ No newline at end of file