]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fixed remaining issues for #3541 - VerticalLayout/GridLayout/AbsoluteLayout/CSSLayout...
authorArtur Signell <artur.signell@itmill.com>
Thu, 26 Nov 2009 12:54:11 +0000 (12:54 +0000)
committerArtur Signell <artur.signell@itmill.com>
Thu, 26 Nov 2009 12:54:11 +0000 (12:54 +0000)
svn changeset:10072/svn branch:6.2

12 files changed:
src/com/vaadin/terminal/gwt/client/Util.java
src/com/vaadin/terminal/gwt/client/VCaption.java
src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayout.java
src/com/vaadin/terminal/gwt/client/ui/VCssLayout.java
src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java
src/com/vaadin/terminal/gwt/client/ui/VOrderedLayout.java
src/com/vaadin/ui/AbsoluteLayout.java
src/com/vaadin/ui/AbstractOrderedLayout.java
src/com/vaadin/ui/CssLayout.java
src/com/vaadin/ui/GridLayout.java
tests/src/com/vaadin/tests/layouts/TestLayoutClickListeners.html
tests/src/com/vaadin/tests/layouts/TestLayoutClickListeners.java

index 9824b31e47a984ae04d6ac03d68df318dc7ec21b..9ae18cc01d7f1bc723fa2980d3c21bfded0966f0 100644 (file)
@@ -755,4 +755,49 @@ public class Util {
 
     }
 
+    /**
+     * Locates the child component of <literal>parent</literal> which contains
+     * the element <literal>element</literal>. The child component is also
+     * returned if "element" is part of its caption. If
+     * <literal>element</literal> is not part of any child component, null is
+     * returned.
+     * 
+     * @param client
+     *            A reference to ApplicationConnection
+     * @param parent
+     *            The widget that contains <literal>element</literal>.
+     * @param element
+     *            An element that is a sub element of the parent
+     * @return The Paintable which the element is a part of. Null if the element
+     *         does not belong to a child.
+     */
+    public static Paintable getChildPaintableForElement(
+            ApplicationConnection client, Container parent, Element element) {
+        Element rootElement = ((Widget) parent).getElement();
+        while (element != null && element != rootElement) {
+            Paintable paintable = client.getPaintable(element);
+            if (paintable == null) {
+                String ownerPid = VCaption.getCaptionOwnerPid(element);
+                if (ownerPid != null) {
+                    paintable = client.getPaintable(ownerPid);
+                }
+            }
+
+            if (paintable != null) {
+                try {
+                    if (parent.hasChildComponent((Widget) paintable)) {
+                        return paintable;
+                    }
+                } catch (ClassCastException e) {
+                    // We assume everything is a widget however there is no need
+                    // to crash everything if there is a paintable that is not.
+                }
+            }
+
+            element = (Element) element.getParentElement();
+        }
+
+        return null;
+    }
+
 }
index 5a6306b79b0ad89ca45a43a1f1a0f68cd838dc34..ba57956c27ad97545b106c76607815e08a3982b6 100644 (file)
@@ -51,6 +51,9 @@ public class VCaption extends HTML {
         super();
         this.client = client;
         owner = component;
+
+        setOwnerPid(getElement(), client.getPid(owner));
+
         setStyleName(CLASSNAME);
         sinkEvents(VTooltip.TOOLTIP_EVENTS);
 
@@ -440,4 +443,18 @@ public class VCaption extends HTML {
         return captionText;
     }
 
+    public static String getCaptionOwnerPid(Element e) {
+        return getOwnerPid(e);
+    }
+
+    private native static void setOwnerPid(Element el, String pid)
+    /*-{
+        el.vOwnerPid = pid;
+    }-*/;
+
+    public native static String getOwnerPid(Element el)
+    /*-{
+        return el.vOwnerPid;
+    }-*/;
+
 }
index 63f865082b673de3b0f0bbfece29d9a470064b34..2a7ee079a9c60c09d757aab9ca597837005a3e49 100644 (file)
@@ -24,6 +24,7 @@ import com.vaadin.terminal.gwt.client.Container;
 import com.vaadin.terminal.gwt.client.Paintable;
 import com.vaadin.terminal.gwt.client.RenderSpace;
 import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.Util;
 import com.vaadin.terminal.gwt.client.VCaption;
 
 public class VAbsoluteLayout extends ComplexPanel implements Container {
@@ -412,20 +413,18 @@ public class VAbsoluteLayout extends ComplexPanel implements Container {
         }
     }
 
-    private Paintable getComponent(Element target) {
-        while (target != null && target != canvas) {
-            Paintable paintable = client.getPaintable(target);
-            if (paintable != null) {
-                String pid = client.getPid(paintable);
-                AbsoluteWrapper wrapper = pidToComponentWrappper.get(pid);
-                if (wrapper != null) {
-                    return paintable;
-                }
-            }
-            target = DOM.getParent(target);
-        }
-
-        return null;
+    /**
+     * Returns the child component which contains "element". The child component
+     * is also returned if "element" is part of its caption.
+     * 
+     * @param element
+     *            An element that is a sub element of the root element in this
+     *            layout
+     * @return The Paintable which the element is a part of. Null if the element
+     *         belongs to the layout and not to a child.
+     */
+    private Paintable getComponent(Element element) {
+        return Util.getChildPaintableForElement(client, this, element);
     }
 
 }
index ebd201724b0386582a6fac254158327c875b405f..bf13530d7f6566bf9d491ecca12a4783d3c92754 100644 (file)
@@ -10,6 +10,9 @@ import java.util.Iterator;
 import java.util.Set;
 
 import com.google.gwt.dom.client.Style;
+import com.google.gwt.event.dom.client.DomEvent.Type;
+import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.ui.FlowPanel;
@@ -22,17 +25,34 @@ import com.vaadin.terminal.gwt.client.Paintable;
 import com.vaadin.terminal.gwt.client.RenderSpace;
 import com.vaadin.terminal.gwt.client.StyleConstants;
 import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.Util;
 import com.vaadin.terminal.gwt.client.VCaption;
 import com.vaadin.terminal.gwt.client.ValueMap;
 
 public class VCssLayout extends SimplePanel implements Paintable, Container {
     public static final String TAGNAME = "csslayout";
     public static final String CLASSNAME = "v-" + TAGNAME;
+    public static final String CLICK_EVENT_IDENTIFIER = "click";
 
     private FlowPane panel = new FlowPane();
 
     private Element margin = DOM.createDiv();
 
+    private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler(
+            this, CLICK_EVENT_IDENTIFIER) {
+
+        @Override
+        protected Paintable getChildComponent(Element element) {
+            return panel.getComponent(element);
+        }
+
+        @Override
+        protected <H extends EventHandler> HandlerRegistration registerHandler(
+                H handler, Type<H> type) {
+            return addDomHandler(handler, type);
+        }
+    };
+
     private boolean hasHeight;
     private boolean hasWidth;
 
@@ -68,6 +88,7 @@ public class VCssLayout extends SimplePanel implements Paintable, Container {
         if (client.updateComponent(this, uidl, true)) {
             return;
         }
+        clickEventHandler.handleEventHandlerRegistration(client);
 
         final VMarginInfo margins = new VMarginInfo(uidl
                 .getIntAttribute("margins"));
@@ -206,6 +227,12 @@ public class VCssLayout extends SimplePanel implements Paintable, Container {
                 widgetToCaption.remove(component);
             }
         }
+
+        private Paintable getComponent(Element element) {
+            return Util.getChildPaintableForElement(client, VCssLayout.this,
+                    element);
+        }
+
     }
 
     private RenderSpace space;
index 2dae5626d6e14ddefd25e1aeeb79a4be288d7c8f..1c2fcf5b6ffb0c022a4ca93568a82f317212bf1e 100644 (file)
@@ -17,7 +17,6 @@ import com.google.gwt.dom.client.Document;
 import com.google.gwt.event.dom.client.DomEvent.Type;
 import com.google.gwt.event.shared.EventHandler;
 import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.ui.AbsolutePanel;
 import com.google.gwt.user.client.ui.SimplePanel;
@@ -1044,20 +1043,18 @@ public class VGridLayout extends SimplePanel implements Paintable, Container {
         return cell;
     }
 
+    /**
+     * Returns the child component which contains "element". The child component
+     * is also returned if "element" is part of its caption.
+     * 
+     * @param element
+     *            An element that is a sub element of the root element in this
+     *            layout
+     * @return The Paintable which the element is a part of. Null if the element
+     *         belongs to the layout and not to a child.
+     */
     private Paintable getComponent(Element element) {
-        Element rootElement = getElement();
-        while (element != null && element != rootElement) {
-            Paintable paintable = client.getPaintable(element);
-            if (paintable != null) {
-                Cell cell = paintableToCell.get(paintable);
-                if (cell != null) {
-                    return paintable;
-                }
-            }
-            element = DOM.getParent(element);
-        }
-
-        return null;
+        return Util.getChildPaintableForElement(client, this, element);
     }
 
 }
index cb5624142fdc00c68becffd6b6d8399ebd236949..8848681753f7ddfd329e16228001e73d1aebc1cf 100644 (file)
@@ -938,24 +938,17 @@ public class VOrderedLayout extends CellBasedLayout {
     }\r
 \r
     /**\r
-     * Returns the child component which contains "element".\r
+     * Returns the child component which contains "element". The child component\r
+     * is also returned if "element" is part of its caption.\r
      * \r
      * @param element\r
-     * @return\r
+     *            An element that is a sub element of the root element in this\r
+     *            layout\r
+     * @return The Paintable which the element is a part of. Null if the element\r
+     *         belongs to the layout and not to a child.\r
      */\r
     private Paintable getComponent(Element element) {\r
-        Element rootElement = getElement();\r
-        while (element != null && element != rootElement) {\r
-            Paintable paintable = client.getPaintable(element);\r
-            if (paintable != null\r
-                    && widgetToComponentContainer.containsKey(paintable)) {\r
-                return paintable;\r
-            } else {\r
-                element = (Element) element.getParentElement();\r
-            }\r
-        }\r
-\r
-        return null;\r
+        return Util.getChildPaintableForElement(client, this, element);\r
     }\r
 \r
 }\r
index d32ba913b1c5f3f360c03c05a57a10a5ec5b88e1..406ee9072df60e1c139d3f760d245c3d79ab70cb 100644 (file)
@@ -379,8 +379,7 @@ public class AbsoluteLayout extends AbstractLayout {
      * Add a click listener to the layout. The listener is called whenever the
      * user clicks inside the layout. Also when the click targets a component
      * inside the Panel, provided the targeted component does not prevent the
-     * click event from propagating. A caption is not considered part of a
-     * component.
+     * click event from propagating.
      * 
      * The child component that was clicked is included in the
      * {@link LayoutClickEvent}.
index dc722bbd126c94e632bef2b3eb684f203d7d7732..04449bd7b8d958d73b9b50a3644b425d2c6ae63e 100644 (file)
@@ -334,8 +334,7 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements
      * Add a click listener to the layout. The listener is called whenever the
      * user clicks inside the layout. Also when the click targets a component
      * inside the Panel, provided the targeted component does not prevent the
-     * click event from propagating. A caption is not considered part of a
-     * component.
+     * click event from propagating.
      * 
      * The child component that was clicked is included in the
      * {@link LayoutClickEvent}.
index 0b98ac7975237e9134b55f055780c3fd8759df53..e0276369566004b1517c712d6f93270f79227a09 100644 (file)
@@ -3,10 +3,14 @@ package com.vaadin.ui;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.Map;
 
+import com.vaadin.event.LayoutEvents.LayoutClickEvent;
+import com.vaadin.event.LayoutEvents.LayoutClickListener;
 import com.vaadin.terminal.PaintException;
 import com.vaadin.terminal.PaintTarget;
 import com.vaadin.terminal.Paintable;
+import com.vaadin.terminal.gwt.client.MouseEventDetails;
 import com.vaadin.terminal.gwt.client.ui.VCssLayout;
 
 /**
@@ -55,6 +59,8 @@ public class CssLayout extends AbstractLayout {
 
     private static final long serialVersionUID = -6408703812053460073L;
 
+    private static final String CLICK_EVENT = VCssLayout.CLICK_EVENT_IDENTIFIER;
+
     /**
      * Custom layout slots containing the components.
      */
@@ -218,4 +224,53 @@ public class CssLayout extends AbstractLayout {
         }
     }
 
+    @Override
+    public void changeVariables(Object source, Map variables) {
+        super.changeVariables(source, variables);
+
+        if (variables.containsKey(CLICK_EVENT)) {
+            fireClick((Map<String, Object>) variables.get(CLICK_EVENT));
+        }
+
+    }
+
+    private void fireClick(Map<String, Object> parameters) {
+        MouseEventDetails mouseDetails = MouseEventDetails
+                .deSerialize((String) parameters.get("mouseDetails"));
+        Component childComponent = (Component) parameters.get("component");
+
+        fireEvent(new LayoutClickEvent(this, mouseDetails, childComponent));
+    }
+
+    /**
+     * Add a click listener to the layout. The listener is called whenever the
+     * user clicks inside the layout. Also when the click targets a component
+     * inside the Panel, provided the targeted component does not prevent the
+     * click event from propagating. A caption is not considered part of a
+     * component.
+     * 
+     * The child component that was clicked is included in the
+     * {@link LayoutClickEvent}.
+     * 
+     * Use {@link #removeListener(LayoutClickListener)} to remove the listener.
+     * 
+     * @param listener
+     *            The listener to add
+     */
+    public void addListener(LayoutClickListener listener) {
+        addListener(CLICK_EVENT, LayoutClickEvent.class, listener,
+                LayoutClickListener.clickMethod);
+    }
+
+    /**
+     * Remove a click listener from the layout. The listener should earlier have
+     * been added using {@link #addListener(LayoutClickListener)}.
+     * 
+     * @param listener
+     *            The listener to remove
+     */
+    public void removeListener(LayoutClickListener listener) {
+        removeListener(CLICK_EVENT, LayoutClickEvent.class, listener);
+    }
+
 }
index 856565194cdd760ed25565804fb9daeddf7e60fe..778b9b42cab0048e8785856c5c4a6e29ee69a9c6 100644 (file)
@@ -1326,8 +1326,7 @@ public class GridLayout extends AbstractLayout implements
      * Add a click listener to the layout. The listener is called whenever the
      * user clicks inside the layout. Also when the click targets a component
      * inside the Panel, provided the targeted component does not prevent the
-     * click event from propagating. A caption is not considered part of a
-     * component.
+     * click event from propagating.
      * 
      * The child component that was clicked is included in the
      * {@link LayoutClickEvent}.
index aa2e923ffaaf87f1c484cf560861fbed59941c92..f488eb9a81d80913cea32f5b9951664050af24f8 100644 (file)
@@ -26,6 +26,7 @@
        <td></td>
        <td>initial</td>
 </tr>
+<!--GridLayout-->
 <tr>
        <td>mouseClick</td>
        <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[0]/VLabel[0]</td>
        <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td>
        <td>exact:GridLayout: Click on This is tf5</td>
 </tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/domChild[0]/domChild[0]/domChild[1]</td>
+       <td>87,42</td>
+</tr>
+<tr>
+       <td>waitForVaadin</td>
+       <td></td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td>
+       <td>exact:GridLayout: Click on &lt;none&gt;</td>
+</tr>
+<!--VerticalLayout-->
 <tr>
        <td>mouseClick</td>
        <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[5]/VTextField[0]</td>
        <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td>
        <td>exact:VerticalLayout: Click on This is label 3</td>
 </tr>
+<!--AbsoluteLayout-->
 <tr>
        <td>click</td>
        <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VAbsoluteLayout[0]/VAbsoluteLayout$AbsoluteWrapper[2]/VButton[0]/domChild[0]/domChild[0]</td>
        <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td>
        <td>exact:AbsoluteLayout: Click on This is its caption</td>
 </tr>
+<!--CssLayout-->
+<tr>
+       <td>waitForVaadin</td>
+       <td></td>
+       <td></td>
+</tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/domChild[0]/domChild[0]/domChild[1]</td>
-       <td>87,42</td>
+       <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/VCssLayout$FlowPane[0]/VTextField[0]</td>
+       <td>108,13</td>
 </tr>
 <tr>
        <td>waitForVaadin</td>
        <td></td>
        <td></td>
 </tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+       <td>76,12</td>
+</tr>
+<tr>
+       <td>waitForVaadin</td>
+       <td></td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VLabel[0]</td>
+       <td>exact:CSSLayout: Click on This is its caption</td>
+</tr>
 <tr>
        <td>assertText</td>
        <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td>
-       <td>exact:GridLayout: Click on &lt;none&gt;</td>
+       <td>exact:CSSLayout: Click on This is its caption</td>
+</tr>
+<tr>
+       <td>click</td>
+       <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/VCssLayout$FlowPane[0]/VButton[0]/domChild[0]/domChild[0]</td>
+       <td></td>
+</tr>
+<tr>
+       <td>waitForVaadin</td>
+       <td></td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VLabel[0]</td>
+       <td>Button A button with its own click listener was clicked</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td>
+       <td>exact:CSSLayout: Click on A button with its own click listener</td>
 </tr>
-
 </tbody></table>
 </body>
 </html>
index a96404e4f61dd5770c809c59231d09b88792e492..ecda096690f6a497062720ca4fe4f4a48b1bb1c1 100644 (file)
@@ -9,6 +9,7 @@ import com.vaadin.tests.components.AbstractTestCase;
 import com.vaadin.ui.AbsoluteLayout;
 import com.vaadin.ui.Button;
 import com.vaadin.ui.Component;
+import com.vaadin.ui.CssLayout;
 import com.vaadin.ui.GridLayout;
 import com.vaadin.ui.HorizontalLayout;
 import com.vaadin.ui.Label;
@@ -69,6 +70,7 @@ public class TestLayoutClickListeners extends AbstractTestCase {
         layoutsLayout.addComponent(createClickableGridLayout());
         layoutsLayout.addComponent(createClickableVerticalLayout());
         layoutsLayout.addComponent(createClickableAbsoluteLayout());
+        layoutsLayout.addComponent(createClickableCSSLayout());
 
         VerticalLayout mainLayout = new VerticalLayout();
         mainLayout.setMargin(true);
@@ -111,6 +113,38 @@ public class TestLayoutClickListeners extends AbstractTestCase {
 
     }
 
+    private Component createClickableCSSLayout() {
+        final CssLayout cl = new CssLayout();
+        cl.setCaption("CSSLayout");
+        cl.setStyleName("borders");
+        cl.setWidth("300px");
+        cl.setHeight("500px");
+        cl.addComponent(new TextField("This is its caption",
+                "This is a textfield"));
+        cl.addComponent(new TextField("Another textfield caption",
+                "This is another textfield"));
+
+        cl.addComponent(new Button("A button with its own click listener",
+                new Button.ClickListener() {
+
+                    public void buttonClick(
+                            com.vaadin.ui.Button.ClickEvent event) {
+                        log.log("Button " + event.getButton().getCaption()
+                                + " was clicked");
+
+                    }
+                }));
+        cl.addListener(new LayoutClickListener() {
+
+            public void layoutClick(LayoutClickEvent event) {
+                logLayoutClick("CSSLayout", event.getChildComponent());
+            }
+        });
+
+        return cl;
+
+    }
+
     private Layout createClickableGridLayout() {
 
         GridLayout gl = new GridLayout(4, 4);