}
+ /**
+ * 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;
+ }
+
}
super();
this.client = client;
owner = component;
+
+ setOwnerPid(getElement(), client.getPid(owner));
+
setStyleName(CLASSNAME);
sinkEvents(VTooltip.TOOLTIP_EVENTS);
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;
+ }-*/;
+
}
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 {
}
}
- 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);
}
}
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;
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;
if (client.updateComponent(this, uidl, true)) {
return;
}
+ clickEventHandler.handleEventHandlerRegistration(client);
final VMarginInfo margins = new VMarginInfo(uidl
.getIntAttribute("margins"));
widgetToCaption.remove(component);
}
}
+
+ private Paintable getComponent(Element element) {
+ return Util.getChildPaintableForElement(client, VCssLayout.this,
+ element);
+ }
+
}
private RenderSpace space;
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;
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);
}
}
}\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
* 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}.
* 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}.
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;
/**
private static final long serialVersionUID = -6408703812053460073L;
+ private static final String CLICK_EVENT = VCssLayout.CLICK_EVENT_IDENTIFIER;
+
/**
* Custom layout slots containing the components.
*/
}
}
+ @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);
+ }
+
}
* 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}.
<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 <none></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 <none></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>
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;
layoutsLayout.addComponent(createClickableGridLayout());
layoutsLayout.addComponent(createClickableVerticalLayout());
layoutsLayout.addComponent(createClickableAbsoluteLayout());
+ layoutsLayout.addComponent(createClickableCSSLayout());
VerticalLayout mainLayout = new VerticalLayout();
mainLayout.setMargin(true);
}
+ 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);