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/09 23:10:19 UTC

svn commit: r413168 - in /tapestry/tapestry4/trunk/framework/src: java/org/apache/tapestry/ java/org/apache/tapestry/dojo/html/ java/org/apache/tapestry/form/ java/org/apache/tapestry/internal/event/ java/org/apache/tapestry/services/impl/ test/org/apa...

Author: jkuhnert
Date: Fri Jun  9 14:10:18 2006
New Revision: 413168

URL: http://svn.apache.org/viewvc?rev=413168&view=rev
Log:
Finished connecting EventListener form based events, fixed Any component ID rendering. Still need to re-do
client side validation.

Modified:
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/AbstractComponent.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/html/WidgetEvent.script
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupport.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupportImpl.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/internal/event/ComponentEventProperty.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/ComponentEventInvoker.java
    tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/internal/event/ComponentEventPropertyTest.java
    tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/services/impl/ComponentEventInvokerTest.java

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/AbstractComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/AbstractComponent.java?rev=413168&r1=413167&r2=413168&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/AbstractComponent.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/AbstractComponent.java Fri Jun  9 14:10:18 2006
@@ -54,6 +54,9 @@
 
     private static final Map EMPTY_MAP = Collections.unmodifiableMap(new HashMap(1));
 
+    /** @since 4.1 */
+    protected String _clientId;
+    
     /**
      * The page that contains the component, possibly itself (if the component is in fact, a page).
      */
@@ -300,6 +303,16 @@
      */
     protected void renderIdAttribute(IMarkupWriter writer, IRequestCycle cycle)
     {
+        // try to generate a client id if needed/possible
+        if (_clientId == null) {
+            String id = getBoundId();
+            if (id == null) id = getId();
+            
+            _clientId = 
+                cycle.getUniqueId(TapestryUtils
+                        .convertTapestryIdToNMToken(id));
+        }
+        
         String id = getClientId();
         if (id != null)
             writer.attribute("id", id);
@@ -432,12 +445,24 @@
      */
     public String getClientId()
     {
-        if (_bindings == null)
+        if (_clientId != null)
+            return _clientId;
+        
+        String boundId = getBoundId();
+        if (boundId == null)
             return getId();
         
+        return boundId;
+    }
+    
+    String getBoundId()
+    {
+        if (_bindings == null)
+            return null;
+        
         IBinding id = (IBinding)_bindings.get("id");
         if (id == null)
-            return getId();
+            return null;
         
         return id.getObject().toString();
     }

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=413168&r1=413167&r2=413168&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 Fri Jun  9 14:10:18 2006
@@ -37,7 +37,6 @@
                     
                     <foreach expression="formEvent[1]" key="formName">
                     tapestry.form.submitAsync("${formName}", "test", content);
-                    dojo.log.debug("Need to submit to form ${formName}");
                     </foreach>
                 });
             </foreach>

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupport.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupport.java?rev=413168&r1=413167&r2=413168&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupport.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupport.java Fri Jun  9 14:10:18 2006
@@ -15,6 +15,7 @@
 package org.apache.tapestry.form;
 
 import org.apache.tapestry.FormBehavior;
+import org.apache.tapestry.IForm;
 import org.apache.tapestry.IRender;
 import org.apache.tapestry.engine.ILink;
 
@@ -59,4 +60,11 @@
      *         {@link FormConstants#SUBMIT_CANCEL} or {@link FormConstants#SUBMIT_REFRESH}.
      */
     String rewind();
+    
+    /**
+     * Gets a reference to the previously stored {@link IForm}.
+     * @return The form this object is managing/supporting.
+     * @since 4.1
+     */
+    IForm getForm();
 }

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupportImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupportImpl.java?rev=413168&r1=413167&r2=413168&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupportImpl.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupportImpl.java Fri Jun  9 14:10:18 2006
@@ -190,6 +190,14 @@
     }
 
     /**
+     * {@inheritDoc}
+     */
+    public IForm getForm()
+    {
+        return _form;
+    }
+    
+    /**
      * Adds an event handler for the form, of the given type.
      */
 
@@ -559,7 +567,7 @@
         // New, handles cases where an eventlistener
         // causes a form submission.
         BrowserEvent event = new BrowserEvent(_cycle);
-        _form.getEventInvoker().invokeListeners(_form, _cycle, event);
+        _form.getEventInvoker().invokeFormListeners(this, _cycle, event);
         
         int expected = _allocatedIds.size();
         

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/internal/event/ComponentEventProperty.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/internal/event/ComponentEventProperty.java?rev=413168&r1=413167&r2=413168&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/internal/event/ComponentEventProperty.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/internal/event/ComponentEventProperty.java Fri Jun  9 14:10:18 2006
@@ -19,6 +19,8 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.tapestry.event.BrowserEvent;
+
 
 /**
  * Represents a configured listener/event(s) binding for a 
@@ -156,5 +158,33 @@
         return _formEventMap.keySet();
     }
     
-    
+    /**
+     * Creates a list of listeners bound to a particular form
+     * and client side browser event. 
+     * 
+     * @param formId
+     *          The form to find listeners for.
+     * @param event
+     *          The browser event that generated the request.
+     * @param append 
+     *          The optional list to add the listeners to.
+     * @return The list of listeners to invoke for the form and event passed in,
+     *          will be empty if none found.
+     */
+    public List getFormEventListeners(String formId, BrowserEvent event, List append)
+    {   
+        List ret = (append == null) ? new ArrayList() : append;
+        
+        List listeners = (List)_formEventMap.get(event.getName());
+        if (listeners == null) 
+            return ret;
+        
+        for (int i=0; i < listeners.size(); i++) {
+            EventBoundListener listener = (EventBoundListener)listeners.get(i);
+            if (listener.getFormId().equals(formId))
+                ret.add(listener);
+        }
+        
+        return ret;
+    }
 }

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/ComponentEventInvoker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/ComponentEventInvoker.java?rev=413168&r1=413167&r2=413168&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/ComponentEventInvoker.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/ComponentEventInvoker.java Fri Jun  9 14:10:18 2006
@@ -13,16 +13,20 @@
 // limitations under the License.
 package org.apache.tapestry.services.impl;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.hivemind.util.Defense;
 import org.apache.tapestry.IActionListener;
 import org.apache.tapestry.IComponent;
+import org.apache.tapestry.IForm;
 import org.apache.tapestry.IRequestCycle;
 import org.apache.tapestry.event.BrowserEvent;
 import org.apache.tapestry.event.ResetEventListener;
+import org.apache.tapestry.form.FormSupport;
 import org.apache.tapestry.internal.event.ComponentEventProperty;
 import org.apache.tapestry.internal.event.EventBoundListener;
 import org.apache.tapestry.listener.ListenerInvoker;
@@ -95,6 +99,45 @@
     }
     
     /**
+     * Causes the configured listeners for the passed {@link FormSupport}'s {@link IForm) to
+     * be invoked, if mapped to this request/event.
+     * 
+     * @param formSupport
+     *          The form support object being rendered.
+     * @param cycle
+     *          The associated request.
+     * @param event
+     *          The event that started it all.
+     */
+    public void invokeFormListeners(FormSupport formSupport, final IRequestCycle cycle, 
+            BrowserEvent event)
+    {
+        IForm component = formSupport.getForm();
+        String id = component.getId();
+        
+        List listeners = getFormEvents(id, event);
+        
+        for (int i=0; i < listeners.size(); i++) {
+            EventBoundListener eventListener = (EventBoundListener)listeners.get(i);
+            
+            final IComponent container = 
+                (component.getContainer() == null) ? component : component.getContainer();
+            
+            final IActionListener listener = 
+                container.getListeners().getListener(eventListener.getMethodName());
+            
+            // defer execution until after form is done rewinding
+            component.addDeferredRunnable(new Runnable()
+            {
+                public void run()
+                {
+                    _invoker.invokeListener(listener, container, cycle);
+                }
+            });
+        }
+    }
+    
+    /**
      * Adds a deferred event listener binding for the specified component.
      * 
      * @param componentId 
@@ -176,6 +219,38 @@
         }
         
         return prop;
+    }
+    
+    /**
+     * Listeners mapped with a submitForm=formId binding are a special case for the
+     * invokers, as we can't just invoke them but must plug the EventListener in to
+     * the normal form rewind logic. This handles mapping an incoming form submission
+     * to our pre-mapped form event invokers.
+     * 
+     * @param id 
+     *          The component id of the form.
+     * @param event
+     *          The browser event based on.
+     * @return List of listeners on specified form/event combination, will be empty
+     *          list if none found.
+     */
+    List getFormEvents(String id, BrowserEvent event)
+    {
+        List ret = new ArrayList();
+        
+        Iterator it = _components.values().iterator();
+        while (it.hasNext()) {
+            ComponentEventProperty prop = (ComponentEventProperty)it.next();
+            prop.getFormEventListeners(id, event, ret);
+        }
+        
+        it = _elements.values().iterator();
+        while (it.hasNext()) {
+            ComponentEventProperty prop = (ComponentEventProperty)it.next();
+            prop.getFormEventListeners(id, event, ret);
+        }
+        
+        return ret;
     }
     
     /**

Modified: tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/internal/event/ComponentEventPropertyTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/internal/event/ComponentEventPropertyTest.java?rev=413168&r1=413167&r2=413168&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/internal/event/ComponentEventPropertyTest.java (original)
+++ tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/internal/event/ComponentEventPropertyTest.java Fri Jun  9 14:10:18 2006
@@ -16,6 +16,7 @@
 import java.util.List;
 
 import org.apache.hivemind.test.HiveMindTestCase;
+import org.apache.tapestry.event.BrowserEvent;
 
 
 /**
@@ -62,6 +63,25 @@
         assertNotNull(prop.getFormEventListeners("onFoo"));
         
         List listeners = prop.getFormEventListeners("onFoo");
+        assertEquals(1, listeners.size());
+        
+        EventBoundListener listener = (EventBoundListener)listeners.get(0);
+        assertEquals("compid", listener.getComponentId());
+        assertEquals("formid", listener.getFormId());
+        assertFalse(listener.isValidateForm());
+        
+        assertEquals("doFoo", listener.getMethodName());
+    }
+    
+    public void testGetFormEvents()
+    {
+        String[] events = {"onFoo"};
+        ComponentEventProperty prop = new ComponentEventProperty("compid");
+        BrowserEvent event = new BrowserEvent("onFoo", null);
+        
+        prop.addListener(events, "doFoo", "formid", false);
+        
+        List listeners = prop.getFormEventListeners("formid", event, null);
         assertEquals(1, listeners.size());
         
         EventBoundListener listener = (EventBoundListener)listeners.get(0);

Modified: tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/services/impl/ComponentEventInvokerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/services/impl/ComponentEventInvokerTest.java?rev=413168&r1=413167&r2=413168&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/services/impl/ComponentEventInvokerTest.java (original)
+++ tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/services/impl/ComponentEventInvokerTest.java Fri Jun  9 14:10:18 2006
@@ -17,12 +17,17 @@
 import java.util.List;
 import java.util.Map;
 
+import org.apache.hivemind.test.AggregateArgumentsMatcher;
+import org.apache.hivemind.test.ArgumentMatcher;
 import org.apache.tapestry.BaseComponentTestCase;
 import org.apache.tapestry.IActionListener;
 import org.apache.tapestry.IComponent;
+import org.apache.tapestry.IForm;
 import org.apache.tapestry.IRequestCycle;
+import org.apache.tapestry.IgnoreMatcher;
 import org.apache.tapestry.event.BrowserEvent;
 import org.apache.tapestry.event.EventTarget;
+import org.apache.tapestry.form.FormSupport;
 import org.apache.tapestry.internal.event.ComponentEventProperty;
 import org.apache.tapestry.listener.ListenerInvoker;
 import org.apache.tapestry.listener.ListenerMap;
@@ -126,6 +131,53 @@
         replayControls();
         
         invoker.invokeListeners(comp, cycle, event);
+        
+        verifyControls();
+    }
+    
+    public void testInvokeFormListener()
+    {
+        IRequestCycle cycle = newCycle();
+        IForm form = newForm();
+        FormSupport formSupport = (FormSupport) newMock(FormSupport.class);
+        Runnable runnable = (Runnable)newMock(Runnable.class);
+        
+        ListenerInvoker listenerInvoker = (ListenerInvoker)newMock(ListenerInvoker.class);
+        ListenerMap listenerMap = (ListenerMap)newMock(ListenerMap.class);
+        IActionListener listener = (IActionListener)newMock(IActionListener.class);
+        
+        Map tprops = new HashMap();
+        tprops.put("id", "testId");
+        BrowserEvent event = new BrowserEvent("onSelect", new EventTarget(tprops));
+        
+        ComponentEventInvoker invoker = new ComponentEventInvoker();
+        invoker.setListenerInvoker(listenerInvoker);
+        
+        invoker.addEventListener("testId", new String[] { "onSelect" }, "fooListener",
+                "form1", false);
+        
+        formSupport.getForm();
+        setReturnValue(formSupport, form);
+        form.getId();
+        setReturnValue(form, "form1");
+        
+        form.getContainer();
+        setReturnValue(form, form);
+        form.getContainer();
+        setReturnValue(form, form);
+        form.getListeners();
+        setReturnValue(form, listenerMap);
+        
+        listenerMap.getListener("fooListener");
+        setReturnValue(listenerMap, listener);
+        
+        form.addDeferredRunnable(runnable);
+        ArgumentMatcher ignore = new IgnoreMatcher();
+        getControl(form).setMatcher(new AggregateArgumentsMatcher(new ArgumentMatcher[] { ignore }));
+        
+        replayControls();
+        
+        invoker.invokeFormListeners(formSupport, cycle, event);
         
         verifyControls();
     }