package com.sksamuel.jqm4gwt.html; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Node; import com.google.gwt.user.client.ui.AttachDetachException; import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.IsWidget; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.WidgetCollection; /** * Flow panel based on the given HTML element sent as constructor argument. * <br> A panel that formats its child widgets using the default HTML layout behavior. */ public class CustomFlowPanel extends ComplexPanel { /** * Creates an empty flow panel based on the given element. */ public CustomFlowPanel(Element e) { setElement(e); // no excessive FlowPanel() -> DOM.createDiv() } // THE FOLLOWING CODE is exact copy from FlowPanel and ComplexPanel /** The command used to orphan children. */ private AttachDetachException.Command orphanCommand; private WidgetCollection children = null; @Override protected WidgetCollection getChildren() { return children != null ? children : super.getChildren(); } // ComplexPanel.doLogicalClear() is not available, that's why we need this stupid copy private void _doLogicalClear() { // Only use one orphan command per panel to avoid object creation. if (orphanCommand == null) { orphanCommand = new AttachDetachException.Command() { @Override public void execute(Widget w) { orphan(w); } }; } try { AttachDetachException.tryCommand(this, orphanCommand); } finally { children = new WidgetCollection(this); } } /** * Adds a new child widget to the panel. * * @param w the widget to be added */ @Override public void add(Widget w) { Element elt = getElement(); add(w, elt); } @Override public void clear() { try { _doLogicalClear(); } finally { // Remove all existing child nodes. Node child = getElement().getFirstChild(); while (child != null) { getElement().removeChild(child); child = getElement().getFirstChild(); } } } public void insert(IsWidget w, int beforeIndex) { insert(asWidgetOrNull(w), beforeIndex); } /** * Inserts a widget before the specified index. * * @param w the widget to be inserted * @param beforeIndex the index before which it will be inserted * @throws IndexOutOfBoundsException if <code>beforeIndex</code> is out of range */ public void insert(Widget w, int beforeIndex) { Element elt = getElement(); insert(w, elt, beforeIndex, true); } /** * The same as ComplexPanel.add(child, container), but without physical DOM.appendChild() attach. * * @param parentPanel - depends on externalChild placement in DOM, in most of the cases it should be RootPanel.get() **/ public static CustomFlowPanel adoptExternal(ComplexPanel parentPanel, Element externalChild) { if (parentPanel == null || externalChild == null) return null; CustomFlowPanel rslt = new CustomFlowPanel(externalChild); WidgetCollection children = getChildren(parentPanel); children.add(rslt); // Logical attach adoptChild(parentPanel, rslt); // Adopt return rslt; } private static native WidgetCollection getChildren(ComplexPanel panel) /*-{ return panel.@com.google.gwt.user.client.ui.ComplexPanel::children; }-*/; private static native void adoptChild(Panel parent, Widget child) /*-{ parent.@com.google.gwt.user.client.ui.Panel::adopt(Lcom/google/gwt/user/client/ui/Widget;)(child); }-*/; }