]> source.dussan.org Git - vaadin-framework.git/commitdiff
"Sizeable" Grid and OrderedLayout
authorMatti Tahvonen <matti.tahvonen@itmill.com>
Wed, 6 Feb 2008 07:58:22 +0000 (07:58 +0000)
committerMatti Tahvonen <matti.tahvonen@itmill.com>
Wed, 6 Feb 2008 07:58:22 +0000 (07:58 +0000)
svn changeset:3714/svn branch:trunk

src/com/itmill/toolkit/terminal/gwt/client/DefaultWidgetSet.java
src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/AbsoluteGrid.java [new file with mode: 0644]
src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableGridLayout.java [new file with mode: 0644]
src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableOrderedLayout.java [new file with mode: 0644]

index b3ee13f7a34e145cdbf9a392b9508ec92ec741ec..edf4bf3d81fa271ac0024a9b69ad0f15a42cd045 100644 (file)
@@ -43,6 +43,8 @@ import com.itmill.toolkit.terminal.gwt.client.ui.ITwinColSelect;
 import com.itmill.toolkit.terminal.gwt.client.ui.IUnknownComponent;
 import com.itmill.toolkit.terminal.gwt.client.ui.IUpload;
 import com.itmill.toolkit.terminal.gwt.client.ui.IWindow;
+import com.itmill.toolkit.terminal.gwt.client.ui.absolutegrid.ISizeableGridLayout;
+import com.itmill.toolkit.terminal.gwt.client.ui.absolutegrid.ISizeableOrderedLayout;
 import com.itmill.toolkit.terminal.gwt.client.ui.richtextarea.IRichTextArea;
 
 public class DefaultWidgetSet implements WidgetSet {
@@ -68,6 +70,9 @@ public class DefaultWidgetSet implements WidgetSet {
         } else if ("com.itmill.toolkit.terminal.gwt.client.ui.IWindow"
                 .equals(className)) {
             return new IWindow();
+        } else if ("com.itmill.toolkit.terminal.gwt.client.ui.absolutegrid.ISizeableOrderedLayout"
+                .equals(className)) {
+            return new ISizeableOrderedLayout();
         } else if ("com.itmill.toolkit.terminal.gwt.client.ui.IOrderedLayoutVertical"
                 .equals(className)) {
             return new IOrderedLayoutVertical();
@@ -80,6 +85,9 @@ public class DefaultWidgetSet implements WidgetSet {
         } else if ("com.itmill.toolkit.terminal.gwt.client.ui.ILink"
                 .equals(className)) {
             return new ILink();
+        } else if ("com.itmill.toolkit.terminal.gwt.client.ui.absolutegrid.ISizeableGridLayout"
+                .equals(className)) {
+            return new ISizeableGridLayout();
         } else if ("com.itmill.toolkit.terminal.gwt.client.ui.IGridLayout"
                 .equals(className)) {
             return new IGridLayout();
@@ -192,7 +200,10 @@ public class DefaultWidgetSet implements WidgetSet {
         } else if ("window".equals(tag)) {
             return "com.itmill.toolkit.terminal.gwt.client.ui.IWindow";
         } else if ("orderedlayout".equals(tag)) {
-            if ("horizontal".equals(uidl.getStringAttribute("orientation"))) {
+            if (uidl.hasAttribute("height")) {
+                return "com.itmill.toolkit.terminal.gwt.client.ui.absolutegrid.ISizeableOrderedLayout";
+            } else if ("horizontal".equals(uidl
+                    .getStringAttribute("orientation"))) {
                 return "com.itmill.toolkit.terminal.gwt.client.ui.IOrderedLayoutHorizontal";
             } else {
                 return "com.itmill.toolkit.terminal.gwt.client.ui.IOrderedLayoutVertical";
@@ -202,7 +213,14 @@ public class DefaultWidgetSet implements WidgetSet {
         } else if ("link".equals(tag)) {
             return "com.itmill.toolkit.terminal.gwt.client.ui.ILink";
         } else if ("gridlayout".equals(tag)) {
-            return "com.itmill.toolkit.terminal.gwt.client.ui.IGridLayout";
+            if (uidl.hasAttribute("height")) {
+                // height needs to be set to use sizeable grid layout, with
+                // width only or no size at all it fails to render properly.
+                return "com.itmill.toolkit.terminal.gwt.client.ui.absolutegrid.ISizeableGridLayout";
+            } else {
+                // Fall back to GWT FlexTable based implementation.
+                return "com.itmill.toolkit.terminal.gwt.client.ui.IGridLayout";
+            }
         } else if ("tree".equals(tag)) {
             return "com.itmill.toolkit.terminal.gwt.client.ui.ITree";
         } else if ("select".equals(tag)) {
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/AbsoluteGrid.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/AbsoluteGrid.java
new file mode 100644 (file)
index 0000000..e2fb89f
--- /dev/null
@@ -0,0 +1,297 @@
+package com.itmill.toolkit.terminal.gwt.client.ui.absolutegrid;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+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.Composite;
+import com.google.gwt.user.client.ui.SimplePanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
+import com.itmill.toolkit.terminal.gwt.client.Caption;
+import com.itmill.toolkit.terminal.gwt.client.ContainerResizedListener;
+import com.itmill.toolkit.terminal.gwt.client.Util;
+import com.itmill.toolkit.terminal.gwt.client.ui.AlignmentInfo;
+
+/**
+ * Prototype helper widget to implement complex sized Toolkit layouts like
+ * GridLayout and OrderedLayout. Supports size, margins, spacing, but has bit
+ * expensive layout function.
+ */
+public class AbsoluteGrid extends Composite implements ContainerResizedListener {
+
+    protected HashMap cells = new HashMap();
+
+    private int cols = 1;
+    private int rows = 1;
+
+    private AbsolutePanel ap;
+
+    protected int marginTop;
+    protected int marginBottom;
+    protected int marginLeft;
+    protected int marginRight;
+
+    private int offsetWidth;
+
+    private int offsetHeight;
+
+    public AbsoluteGrid() {
+        ap = new AbsolutePanel();
+        initWidget(ap);
+    }
+
+    public AbsoluteGridCell getCell(int col, int row) {
+        AbsoluteGridCell p = (AbsoluteGridCell) cells.get(col + "." + row);
+        if (p == null) {
+            p = new AbsoluteGridCell(col, row);
+            cells.put(col + "." + row, p);
+            ap.add(p);
+        }
+        return p;
+    }
+
+    public void clear() {
+        ap.clear();
+        cells.clear();
+    }
+
+    public Iterator getCellIterator() {
+        return cells.values().iterator();
+    }
+
+    private float getCellWidth(int colspan) {
+        int total = ap.getOffsetWidth();
+        total -= getMarginWidth();
+        total -= getSpacingSize() * (cols - colspan);
+        if (total < 0) {
+            return 0;
+        }
+        return total * colspan / (float) cols;
+    }
+
+    /**
+     * 
+     * @return space used by left and right margin
+     */
+    private int getMarginWidth() {
+        return marginLeft + marginRight;
+    }
+
+    /**
+     * @return pixels reserved for space between components
+     */
+    protected int getSpacingSize() {
+        return 0;
+    }
+
+    private float getCellHeight(int rowspan) {
+        int total = ap.getOffsetHeight();
+        total -= getMarginHeight();
+        total -= getSpacingSize() * (rows - rowspan);
+        if (total < 0) {
+            return 0;
+        }
+        return total * rowspan / (float) rows;
+    }
+
+    /**
+     * 
+     * @return space used by top and bottom margin
+     */
+    private int getMarginHeight() {
+        return marginBottom + marginTop;
+    }
+
+    /**
+     * TODO contains Caption (which is a widget) in a very bad way, cannot be
+     * simple panel
+     */
+    public class AbsoluteGridCell extends SimplePanel {
+
+        int rowIndex;
+        int colIndex;
+        int colSpan = 1;
+        int rowSpan = 1;
+        private Element container = DOM.createDiv();
+
+        private Caption caption;
+        private AlignmentInfo alignmentInfo = new AlignmentInfo(
+                AlignmentInfo.ALIGNMENT_TOP + AlignmentInfo.ALIGNMENT_LEFT);
+
+        AbsoluteGridCell(int colIndex, int rowIndex) {
+            super();
+            DOM.appendChild(getElement(), container);
+            this.rowIndex = rowIndex;
+            this.colIndex = colIndex;
+        }
+
+        public void clear() {
+            super.clear();
+            if (caption != null) {
+                DOM.removeChild(getElement(), caption.getElement());
+                caption = null;
+            }
+        }
+
+        protected Element getContainerElement() {
+            return container;
+        }
+
+        void setColSpan(int s) {
+            // TODO Should remove possibly collapsing cells
+            colSpan = s;
+        }
+
+        void setRowSpan(int s) {
+            // TODO Should remove possibly collapsing cells
+            rowSpan = s;
+        }
+
+        private int getLeft() {
+            int left = marginLeft;
+            left += colIndex * getCellWidth(1);
+            left += getSpacingSize() * colIndex;
+            return left;
+        }
+
+        private int getTop() {
+            int top = marginTop;
+            top += rowIndex * getCellHeight(1);
+            top += getSpacingSize() * rowIndex;
+            return top;
+        }
+
+        public void render() {
+            setPixelSize((int) getCellWidth(colSpan),
+                    (int) getCellHeight(rowSpan));
+            ap.setWidgetPosition(this, getLeft(), getTop());
+        }
+
+        /**
+         * Does vertical positioning based on DOM values
+         */
+        public void vAling() {
+            DOM.setStyleAttribute(getElement(), "paddingTop", "0");
+            if (!alignmentInfo.isTop()) {
+                Widget c = getWidget();
+                if (c != null) {
+
+                    int oh = getOffsetHeight();
+                    int wt = DOM.getElementPropertyInt(container, "offsetTop");
+                    int wh = c.getOffsetHeight();
+
+                    int freeSpace = getOffsetHeight()
+                            - (DOM
+                                    .getElementPropertyInt(container,
+                                            "offsetTop") + c.getOffsetHeight());
+                    if (Util.isIE()) {
+                        freeSpace -= DOM.getElementPropertyInt(c.getElement(),
+                                "offsetTop");
+                    }
+                    if (freeSpace < 0) {
+                        freeSpace = 0; // clipping rest of contents when object
+                        // larger than reserved area
+                    }
+                    if (alignmentInfo.isVerticalCenter()) {
+                        ApplicationConnection.getConsole().log("oh" + oh);
+                        ApplicationConnection.getConsole().log("wt" + wt);
+                        ApplicationConnection.getConsole().log("wh" + wh);
+                        ApplicationConnection.getConsole().log(
+                                "freespace" + freeSpace);
+
+                        DOM.setStyleAttribute(getElement(), "paddingTop",
+                                (freeSpace / 2) + "px");
+                    } else {
+                        DOM.setStyleAttribute(getElement(), "paddingTop",
+                                (freeSpace) + "px");
+                    }
+                }
+            }
+        }
+
+        public void setPixelSize(int width, int height) {
+            super.setPixelSize(width, height);
+            DOM.setStyleAttribute(container, "width", width + "px");
+            int contHeight = height - getCaptionHeight();
+            if (contHeight < 0) {
+                contHeight = 0;
+            }
+            DOM.setStyleAttribute(container, "height", contHeight + "px");
+        }
+
+        private int getCaptionHeight() {
+            // remove hard coded caption height
+            return (caption == null) ? 0 : caption.getOffsetHeight();
+        }
+
+        public Caption getCaption() {
+            return caption;
+        }
+
+        public void setCaption(Caption newCaption) {
+            // TODO check for existing, shouldn't happen though
+            caption = newCaption;
+            DOM.insertChild(getElement(), caption.getElement(), 0);
+        }
+
+        public void setAlignment(int bitmask) {
+            if (alignmentInfo.getBitMask() != bitmask) {
+                alignmentInfo = new AlignmentInfo(bitmask);
+                setHorizontalAling();
+                // vertical align is set in render() method
+            }
+        }
+
+        private void setHorizontalAling() {
+            DOM.setStyleAttribute(getElement(), "textAlign", alignmentInfo
+                    .getHorizontalAlignment());
+        }
+    }
+
+    public void iLayout() {
+        boolean sizeChanged = false;
+        int newWidth = getOffsetWidth();
+        if (offsetWidth != newWidth) {
+            offsetWidth = newWidth;
+            sizeChanged = true;
+        }
+        int newHeight = getOffsetHeight();
+        if (offsetHeight != newHeight) {
+            offsetHeight = newHeight;
+            sizeChanged = true;
+        }
+        if (sizeChanged) {
+            for (Iterator it = cells.values().iterator(); it.hasNext();) {
+                AbsoluteGridCell cell = (AbsoluteGridCell) it.next();
+                cell.render();
+                cell.vAling();
+            }
+            Util.runDescendentsLayout(ap);
+        }
+    }
+
+    public int getCols() {
+        return cols;
+    }
+
+    public void setCols(int cols) {
+        this.cols = cols;
+        // force relayout
+        offsetHeight = 0;
+        offsetWidth = 0;
+    }
+
+    public int getRows() {
+        return rows;
+    }
+
+    public void setRows(int rows) {
+        this.rows = rows;
+        // force relayout
+        offsetHeight = 0;
+        offsetWidth = 0;
+    }
+}
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableGridLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableGridLayout.java
new file mode 100644 (file)
index 0000000..f149fea
--- /dev/null
@@ -0,0 +1,166 @@
+package com.itmill.toolkit.terminal.gwt.client.ui.absolutegrid;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import com.google.gwt.user.client.ui.Widget;
+import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
+import com.itmill.toolkit.terminal.gwt.client.Caption;
+import com.itmill.toolkit.terminal.gwt.client.Container;
+import com.itmill.toolkit.terminal.gwt.client.Paintable;
+import com.itmill.toolkit.terminal.gwt.client.UIDL;
+import com.itmill.toolkit.terminal.gwt.client.ui.MarginInfo;
+
+/**
+ * Proto level implementation of GridLayout.
+ * 
+ * All cell's will be equally sized.
+ * 
+ */
+public class ISizeableGridLayout extends AbsoluteGrid implements Paintable,
+        Container {
+    public static final String CLASSNAME = "i-gridlayout";
+    private int spacing;
+    private HashMap paintableToCellMap = new HashMap();
+    private ApplicationConnection client;
+
+    public ISizeableGridLayout() {
+        super();
+        setStyleName(CLASSNAME);
+    }
+
+    protected int getSpacingSize() {
+        return spacing;
+    }
+
+    public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+        this.client = client;
+
+        if (client.updateComponent(this, uidl, false)) {
+            return;
+        }
+
+        if (uidl.hasAttribute("caption")) {
+            setTitle(uidl.getStringAttribute("caption"));
+        }
+        int row = 0, column = 0;
+
+        final ArrayList oldCells = new ArrayList();
+        for (final Iterator iterator = getCellIterator(); iterator.hasNext();) {
+            oldCells.add(iterator.next());
+        }
+        clear();
+
+        setCols(uidl.getIntAttribute("w"));
+        setRows(uidl.getIntAttribute("h"));
+
+        handleMargins(uidl);
+        spacing = uidl.getBooleanAttribute("spacing") ? detectSpacingSize() : 0;
+
+        final int[] alignments = uidl.getIntArrayAttribute("alignments");
+        int alignmentIndex = 0;
+
+        for (final Iterator i = uidl.getChildIterator(); i.hasNext();) {
+            final UIDL r = (UIDL) i.next();
+            if ("gr".equals(r.getTag())) {
+                column = 0;
+                for (final Iterator j = r.getChildIterator(); j.hasNext();) {
+                    final UIDL c = (UIDL) j.next();
+                    if ("gc".equals(c.getTag())) {
+
+                        // Set cell width
+                        int colSpan;
+                        if (c.hasAttribute("w")) {
+                            colSpan = c.getIntAttribute("w");
+                        } else {
+                            colSpan = 1;
+                        }
+
+                        // Set cell height
+                        int rowSpan;
+                        if (c.hasAttribute("h")) {
+                            rowSpan = c.getIntAttribute("h");
+                        } else {
+                            rowSpan = 1;
+                        }
+
+                        final UIDL u = c.getChildUIDL(0);
+                        if (u != null) {
+                            final Paintable child = client.getPaintable(u);
+                            AbsoluteGridCell cell = getCell(column, row);
+                            paintableToCellMap.put(child, cell);
+                            cell.rowSpan = rowSpan;
+                            cell.colSpan = colSpan;
+
+                            oldCells.remove(cell);
+
+                            cell.setAlignment(alignments[alignmentIndex++]);
+
+                            cell.render();
+
+                            cell.setWidget((Widget) child);
+
+                            if (!u.getBooleanAttribute("cached")) {
+                                child.updateFromUIDL(u, client);
+                            }
+
+                            cell.vAling();
+                        }
+                        column += colSpan;
+                    }
+                }
+                row++;
+            }
+        }
+
+        // loop oldWidgetWrappers that where not re-attached and unregister them
+        for (final Iterator it = oldCells.iterator(); it.hasNext();) {
+            final AbsoluteGridCell w = (AbsoluteGridCell) it.next();
+            client.unregisterPaintable((Paintable) w.getWidget());
+            w.removeFromParent();
+            paintableToCellMap.remove(w.getWidget());
+        }
+
+    }
+
+    protected void handleMargins(UIDL uidl) {
+        final MarginInfo margins = new MarginInfo(uidl
+                .getIntAttribute("margins"));
+        // TODO build CSS detector to make margins configurable through css
+        marginTop = margins.hasTop() ? 15 : 0;
+        marginRight = margins.hasRight() ? 15 : 0;
+        marginBottom = margins.hasBottom() ? 15 : 0;
+        marginLeft = margins.hasLeft() ? 15 : 0;
+    }
+
+    private int detectSpacingSize() {
+        // TODO Auto-generated method stub
+        return 15;
+    }
+
+    public boolean hasChildComponent(Widget component) {
+        if (paintableToCellMap.containsKey(component)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public void replaceChildComponent(Widget oldComponent, Widget newComponent) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void updateCaption(Paintable component, UIDL uidl) {
+        AbsoluteGridCell cell = (AbsoluteGridCell) paintableToCellMap
+                .get(component);
+        Caption c = cell.getCaption();
+        if (c == null) {
+            c = new Caption(component, client);
+            cell.setCaption(c);
+        }
+        c.updateCaption(uidl);
+    }
+
+}
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableOrderedLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableOrderedLayout.java
new file mode 100644 (file)
index 0000000..a1e7cd8
--- /dev/null
@@ -0,0 +1,191 @@
+package com.itmill.toolkit.terminal.gwt.client.ui.absolutegrid;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import com.google.gwt.user.client.ui.Widget;
+import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
+import com.itmill.toolkit.terminal.gwt.client.Caption;
+import com.itmill.toolkit.terminal.gwt.client.Container;
+import com.itmill.toolkit.terminal.gwt.client.Paintable;
+import com.itmill.toolkit.terminal.gwt.client.UIDL;
+import com.itmill.toolkit.terminal.gwt.client.ui.MarginInfo;
+
+/**
+ * Proto level implementation of GridLayout.
+ * 
+ * All cell's will be equally sized.
+ * 
+ */
+public class ISizeableOrderedLayout extends AbsoluteGrid implements Paintable,
+        Container {
+    public static final String CLASSNAME = "i-orderedlayout";
+    private static final int ORIENTETION_HORIZONTAL = 1;
+    private int spacing;
+    private HashMap paintableToCellMap = new HashMap();
+    private ApplicationConnection client;
+    private int orientation;
+
+    public ISizeableOrderedLayout() {
+        super();
+        setStyleName(CLASSNAME);
+    }
+
+    protected int getSpacingSize() {
+        return spacing;
+    }
+
+    public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+        this.client = client;
+
+        if (client.updateComponent(this, uidl, false)) {
+            return;
+        }
+
+        orientation = uidl.getIntAttribute("orientation");
+
+        if (uidl.hasAttribute("caption")) {
+            setTitle(uidl.getStringAttribute("caption"));
+        }
+
+        handleMargins(uidl);
+        spacing = uidl.getBooleanAttribute("spacing") ? detectSpacingSize() : 0;
+
+        final int[] alignments = uidl.getIntArrayAttribute("alignments");
+        int alignmentIndex = 0;
+
+        // Update contained components
+
+        final ArrayList uidlWidgets = new ArrayList();
+        for (final Iterator it = uidl.getChildIterator(); it.hasNext();) {
+            final UIDL uidlForChild = (UIDL) it.next();
+            final Paintable child = client.getPaintable(uidlForChild);
+            uidlWidgets.add(child);
+        }
+
+        if (orientation == ORIENTETION_HORIZONTAL) {
+            setCols(uidlWidgets.size());
+            setRows(1);
+        } else {
+            setCols(1);
+            setRows(uidlWidgets.size());
+        }
+
+        final ArrayList oldWidgets = getPaintables();
+
+        final HashMap oldCaptions = new HashMap();
+
+        final Iterator newIt = uidlWidgets.iterator();
+        final Iterator newUidl = uidl.getChildIterator();
+
+        int row = 0, column = 0;
+        while (newIt.hasNext()) {
+            final Widget child = (Widget) newIt.next();
+            final UIDL childUidl = (UIDL) newUidl.next();
+
+            AbsoluteGridCell cell = getCell(column, row);
+
+            Widget oldChild = cell.getWidget();
+            if (oldChild != null) {
+                if (oldChild != child) {
+                    oldCaptions.put(oldChild, cell.getCaption());
+                    cell.clear();
+                    cell.setWidget(child);
+                    paintableToCellMap.remove(oldChild);
+                    Caption newCaption = (Caption) oldCaptions.get(child);
+                    if (newCaption == null) {
+                        newCaption = new Caption((Paintable) child, client);
+                    }
+                    cell.setCaption(newCaption);
+                }
+            } else {
+                cell.setWidget(child);
+            }
+
+            paintableToCellMap.put(child, cell);
+
+            cell.setAlignment(alignments[alignmentIndex++]);
+
+            cell.render();
+
+            ((Paintable) child).updateFromUIDL(childUidl, client);
+
+            cell.vAling();
+
+            if (orientation == ORIENTETION_HORIZONTAL) {
+                column++;
+            } else {
+                row++;
+            }
+            oldWidgets.remove(child);
+        }
+        // remove possibly remaining old Paintable object which were not updated
+        Iterator oldIt = oldWidgets.iterator();
+        while (oldIt.hasNext()) {
+            final Paintable p = (Paintable) oldIt.next();
+            if (!uidlWidgets.contains(p)) {
+                removePaintable(p);
+            }
+        }
+    }
+
+    private void removePaintable(Paintable oldChild) {
+        AbsoluteGridCell cell = (AbsoluteGridCell) paintableToCellMap
+                .get(oldChild);
+        if (cell != null) {
+            cell.clear();
+        }
+        client.unregisterPaintable(oldChild);
+    }
+
+    private ArrayList getPaintables() {
+        ArrayList paintables = new ArrayList();
+        Iterator it = paintableToCellMap.keySet().iterator();
+        while (it.hasNext()) {
+            Paintable p = (Paintable) it.next();
+            paintables.add(p);
+        }
+        return paintables;
+    }
+
+    protected void handleMargins(UIDL uidl) {
+        final MarginInfo margins = new MarginInfo(uidl
+                .getIntAttribute("margins"));
+        // TODO build CSS detector to make margins configurable through css
+        marginTop = margins.hasTop() ? 15 : 0;
+        marginRight = margins.hasRight() ? 15 : 0;
+        marginBottom = margins.hasBottom() ? 15 : 0;
+        marginLeft = margins.hasLeft() ? 15 : 0;
+    }
+
+    private int detectSpacingSize() {
+        // TODO Auto-generated method stub
+        return 15;
+    }
+
+    public boolean hasChildComponent(Widget component) {
+        if (paintableToCellMap.containsKey(component)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public void replaceChildComponent(Widget oldComponent, Widget newComponent) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void updateCaption(Paintable component, UIDL uidl) {
+        AbsoluteGridCell cell = (AbsoluteGridCell) paintableToCellMap
+                .get(component);
+        Caption c = cell.getCaption();
+        if (c == null) {
+            c = new Caption(component, client);
+            cell.setCaption(c);
+        }
+        c.updateCaption(uidl);
+    }
+
+}