org.openxdata.designer.client.view.DesignGroupView.java Source code

Java tutorial

Introduction

Here is the source code for org.openxdata.designer.client.view.DesignGroupView.java

Source

package org.openxdata.designer.client.view;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.openxdata.designer.client.Context;
import org.openxdata.designer.client.controller.DragDropListener;
import org.openxdata.designer.client.controller.FormDesignerDragController;
import org.openxdata.designer.client.controller.FormDesignerDropController;
import org.openxdata.designer.client.controller.IWidgetPopupMenuListener;
import org.openxdata.designer.client.controller.WidgetPropertyChangeListener;
import org.openxdata.designer.client.controller.WidgetPropertySetter;
import org.openxdata.designer.client.controller.WidgetSelectionListener;
import org.openxdata.designer.client.util.FormDesignerUtil;
import org.openxdata.designer.client.util.StyleUtil;
import org.openxdata.designer.client.vew.widget.images.FormDesignerImages;
import org.openxdata.designer.client.widget.DesignGroupWidget;
import org.openxdata.designer.client.widget.DesignWidgetWrapper;
import org.openxdata.designer.client.widget.PaletteWidget;
import org.openxdata.sharedlib.client.OpenXdataConstants;
import org.openxdata.sharedlib.client.model.OptionDef;
import org.openxdata.sharedlib.client.model.QuestionDef;
import org.openxdata.sharedlib.client.util.FormUtil;
import org.openxdata.sharedlib.client.widget.DatePickerEx;
import org.openxdata.sharedlib.client.widget.DatePickerWidget;
import org.openxdata.sharedlib.client.widget.DateTimeWidget;
import org.openxdata.sharedlib.client.widget.RadioButtonWidget;
import org.openxdata.sharedlib.client.widget.TextBoxWidget;
import org.openxdata.sharedlib.client.widget.TimeWidget;

import com.allen_sauer.gwt.dnd.client.drop.DropController;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DecoratedTabPanel;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.MenuItemSeparator;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import org.openxdata.designer.client.DesignerMessages;
import org.openxdata.sharedlib.client.locale.FormsConstants;
import org.openxdata.sharedlib.client.model.QuestionType;

/**
 * 
 *  www.openxdata.org - Licensed as written in license.txt and original sources of this file and its authors are found in sources.txt.
 *
 */
public class DesignGroupView extends Composite implements WidgetSelectionListener, IWidgetPopupMenuListener,
        DragDropListener, WidgetPropertyChangeListener {

    private final FormsConstants i18n = GWT.create(FormsConstants.class);
    private final DesignerMessages messages = GWT.create(DesignerMessages.class);

    protected static final int MOVE_LEFT = 1;
    protected static final int MOVE_RIGHT = 2;
    protected static final int MOVE_UP = 3;
    protected static final int MOVE_DOWN = 4;

    /** The popup panel for the design surface context menu. */
    protected PopupPanel popup;

    /** The popup panel for the widget context menu. */
    protected PopupPanel widgetPopup;

    /** The cursor position x cordinate. */
    protected int x;

    /** The cursor position y cordinate. */
    protected int y;

    protected int clipboardLeftMostPos;
    protected int clipboardTopMostPos;

    /** The copy menu item for the design surface context menu. */
    protected MenuItem copyMenu;

    /** The cut menu item. */
    protected MenuItem cutMenu;
    protected MenuItem pasteMenu;
    protected MenuItem deleteWidgetsMenu;
    protected MenuItem groupWidgetsMenu;
    protected MenuItem lockWidgetsMenu;
    protected MenuItemSeparator cutCopySeparator;
    protected MenuItemSeparator pasteSeparator;
    protected MenuItemSeparator deleteWidgetsSeparator;
    protected MenuItemSeparator groupWidgetsSeparator;

    protected int selectionXPos;
    protected int selectionYPos;
    protected boolean mouseMoved = false;

    protected AbsolutePanel selectedPanel = new AbsolutePanel();
    protected FormDesignerDragController selectedDragController;
    protected WidgetSelectionListener widgetSelectionListener;

    /** The rubber band widget for multiple widget selection. */
    protected Label rubberBand = new Label("");

    protected final FormDesignerImages images;

    /** Tabs for displaying pages. */
    protected DecoratedTabPanel tabs = new DecoratedTabPanel();
    protected HashMap<Integer, DesignWidgetWrapper> pageWidgets = new HashMap<Integer, DesignWidgetWrapper>();

    /** The index of the selected page tab. */
    protected int selectedTabIndex = 0;

    protected WidgetSelectionListener currentWidgetSelectionListener;

    /** The text box widget for inline label editing. */
    protected TextBox txtEdit = new TextBox();
    protected DesignWidgetWrapper editWidget;

    /** The selection rubber band height in pixels. */
    protected String rubberBandHeight;

    /** The selection rubber band width in pixels. */
    protected String rubberBandWidth;

    /**
     * Creates a new instance of the design surface.
     * 
     * @param images
     */
    public DesignGroupView(FormDesignerImages images) {
        this.images = images;
    }

    public void onDragEnd(Widget widget) {
        onWidgetSelected(getSelectedWidget((DesignWidgetWrapper) widget), true);

        ((DesignWidgetWrapper) widget).refreshSize();
        if (((DesignWidgetWrapper) widget).getWrappedWidget() instanceof DesignGroupWidget)
            DOM.setStyleAttribute(((DesignWidgetWrapper) widget).getWrappedWidget().getElement(), "cursor",
                    "default");
    }

    public void onDragStart(Widget widget) {
        onWidgetSelected(getSelectedWidget((DesignWidgetWrapper) widget), true);
    }

    private DesignWidgetWrapper getSelectedWidget(DesignWidgetWrapper widget) {
        if (widget.getWrappedWidget() instanceof DesignGroupWidget && !widget.isRepeated()) {
            String cursor = DOM.getStyleAttribute(widget.getWrappedWidget().getElement(), "cursor");
            if ("move".equals(cursor) || "default".equals(cursor))
                return ((DesignGroupWidget) widget.getWrappedWidget()).getHeaderLabel();
        }
        return widget;
    }

    public void onWidgetSelected(Widget widget, boolean multipleSel) {

        //Some widgets like check boxes and buttons may not have sizes set yet
        //and so when in edit mode, they fire onmousedown events.
        if (widget != null && widget == editWidget)
            return;

        if (widget == null)
            selectedDragController.clearSelection();
        else if (widget instanceof DesignWidgetWrapper
                && !(((DesignWidgetWrapper) widget).getWrappedWidget() instanceof DesignGroupWidget)) {
            String s = ((DesignWidgetWrapper) widget).getWidth();
            if (!"100%".equals(s)) {
                if (widgetSelectionListener instanceof DesignSurfaceView) {
                    ((DesignSurfaceView) widgetSelectionListener).clearSelection();
                    if (selectedDragController.getSelectedWidgetCount() == 1)
                        ((DesignSurfaceView) widgetSelectionListener).clearGroupBoxSelection();
                }

                if (!multipleSel && !selectedDragController.isWidgetSelected(widget))
                    selectedDragController.clearSelection();

                //Deselect and stop editing of any widget in group boxes
                //TODO Doesnt this slow us a bit?
                if (widget instanceof DesignWidgetWrapper
                        && ((DesignWidgetWrapper) widget).getWidgetSelectionListener() instanceof DesignSurfaceView)
                    clearGroupBoxSelection();

                //Deselect any previously selected widgets in groupbox
                selectedDragController.selectWidget(widget);
            }

            stopLabelEdit(false);
        }

        widgetSelectionListener.onWidgetSelected(widget, multipleSel);
    }

    protected void cutWidgets() {
        copyWidgets(true);
    }

    /**
     * Adds the selected widgets to a group box.
     */
    protected void groupWidgets() {
        cutWidgets();

        x = clipboardLeftMostPos + selectedPanel.getAbsoluteLeft();
        y = clipboardTopMostPos + selectedPanel.getAbsoluteTop();

        DesignWidgetWrapper widget = addNewGroupBox(false);
        DesignGroupView designGroupView = (DesignGroupView) widget.getWrappedWidget();
        designGroupView.updateCursorPos(x + 20, y + 45);
        designGroupView.pasteWidgets(true);
        selectedDragController.clearSelection();
        designGroupView.clearSelection();
        widget.setHeightInt(FormUtil.convertDimensionToInt(rubberBandHeight) + 35);
        widget.setWidth(rubberBandWidth);

        selectedDragController.selectWidget(widget);
        widgetSelectionListener.onWidgetSelected(((DesignGroupWidget) designGroupView).getHeaderLabel(), false);
    }

    protected void copyWidgets(boolean remove) {
        Context.clipBoardWidgets.clear();

        for (int i = 0; i < selectedDragController.getSelectedWidgetCount(); i++) {
            DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedDragController.getSelectedWidgetAt(i);
            widget.storePosition();
            if (i == 0) {
                clipboardLeftMostPos = FormUtil.convertDimensionToInt(widget.getLeft());
                clipboardTopMostPos = FormUtil.convertDimensionToInt(widget.getTop());
            } else {
                int dimension = FormUtil.convertDimensionToInt(widget.getLeft());
                if (clipboardLeftMostPos > dimension)
                    clipboardLeftMostPos = dimension;
                dimension = FormUtil.convertDimensionToInt(widget.getTop());
                if (clipboardTopMostPos > dimension)
                    clipboardTopMostPos = dimension;
            }

            if (remove) { //cut{
                tryUnregisterDropController(widget);
                selectedPanel.remove(widget);
            } else { //copy
                widget = new DesignWidgetWrapper(widget, images);
                tryUnregisterDropController(widget);
            }

            Context.clipBoardWidgets.add(widget);
        }
    }

    private void tryUnregisterDropController(DesignWidgetWrapper widget) {
        if (widget.getWrappedWidget() instanceof DesignGroupWidget)
            PaletteView.unRegisterDropController(((DesignGroupWidget) widget.getWrappedWidget()).getDragController()
                    .getFormDesignerDropController());
    }

    private void updateClipboardLeftMostPos() {
        for (int i = 0; i < Context.clipBoardWidgets.size(); i++) {
            DesignWidgetWrapper widget = Context.clipBoardWidgets.get(i);
            widget.storePosition();
            if (i == 0) {
                clipboardLeftMostPos = FormUtil.convertDimensionToInt(widget.getLeft());
                clipboardTopMostPos = FormUtil.convertDimensionToInt(widget.getTop());
            } else {
                int dimension = FormUtil.convertDimensionToInt(widget.getLeft());
                if (clipboardLeftMostPos > dimension)
                    clipboardLeftMostPos = dimension;
                dimension = FormUtil.convertDimensionToInt(widget.getTop());
                if (clipboardTopMostPos > dimension)
                    clipboardTopMostPos = dimension;
            }
        }
    }

    protected void updateCursorPos(int x, int y) {
        this.x = x;
        this.y = y;
    }

    protected void pasteWidgets(boolean afterContextMenu) {
        int xOffset = x - clipboardLeftMostPos;
        int yOffset = y - clipboardTopMostPos;

        selectedDragController.clearSelection();

        for (int i = 0; i < Context.clipBoardWidgets.size(); i++) {
            DesignWidgetWrapper widget = new DesignWidgetWrapper(Context.clipBoardWidgets.get(i), images);
            widget.setWidgetSelectionListener(this);

            if (i == 0) {
                if (widget.getPopupPanel() != widgetPopup)
                    updateClipboardLeftMostPos();
            }

            selectedDragController.makeDraggable(widget);
            selectedPanel.add(widget);

            if (widget.getWrappedWidget() instanceof DesignGroupWidget && !widget.isRepeated())
                selectedDragController.makeDraggable(widget,
                        ((DesignGroupWidget) widget.getWrappedWidget()).getHeaderLabel());

            if (widget.getPopupPanel() != widgetPopup) {
                if (afterContextMenu)
                    selectedPanel.setWidgetPosition(widget,
                            (x - getAbsoluteLeft()) + (widget.getLeftInt() - clipboardLeftMostPos - 10),
                            (y - getAbsoluteTop()) + (widget.getTopInt() - clipboardTopMostPos - 10));
                else
                    selectedPanel.setWidgetPosition(widget, x - 10, y - 10);
            } else {
                String s = widget.getLeft();
                int xPos = Integer.parseInt(s.substring(0, s.length() - 2)) + xOffset;
                s = widget.getTop();
                int yPos = Integer.parseInt(s.substring(0, s.length() - 2)) + yOffset;

                if (yPos - widget.getAbsoluteTop() >= 0 && xPos - widget.getAbsoluteLeft() >= 0) {
                    xPos = xPos - widget.getAbsoluteLeft();
                    yPos = yPos - widget.getAbsoluteTop();
                }

                selectedPanel.setWidgetPosition(widget, xPos, yPos);
            }

            widget.setWidth(widget.getWidth());
            widget.setHeight(widget.getHeight());
            widget.setPopupPanel(widgetPopup);
            selectedDragController.toggleSelection(widget);
            if (widget.getWrappedWidget() instanceof DesignGroupWidget)
                ((DesignGroupWidget) widget.getWrappedWidget()).setWidgetPosition();

            if (i == 0 && Context.clipBoardWidgets.size() == 1)
                widgetSelectionListener.onWidgetSelected(widget, true);
        }

        if (Context.clipBoardWidgets.size() > 1)
            widgetSelectionListener.onWidgetSelected(null, true);
    }

    protected boolean deleteWidgets() {
        if (!Window.confirm(i18n.deleteWidgetPrompt()))
            return true;

        for (int i = 0; i < selectedDragController.getSelectedWidgetCount(); i++) {
            DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedDragController.getSelectedWidgetAt(i);
            if (widget.getLayoutNode() != null)
                widget.getLayoutNode().getParentNode().removeChild(widget.getLayoutNode());
            tryUnregisterDropController(widget);
            selectedPanel.remove(widget);
        }

        selectedDragController.clearSelection();

        return false;
    }

    public void copyItem() {
        if (selectedDragController.isAnyWidgetSelected())
            copyWidgets(false);
        else
            copyChildWidgets(false);
    }

    public void cutItem() {
        if (selectedDragController.isAnyWidgetSelected())
            cutWidgets();
        else
            copyChildWidgets(true);
    }

    private void copyChildWidgets(boolean remove) {
        if (selectedPanel.getWidgetIndex(rubberBand) > -1)
            selectedPanel.remove(rubberBand);
        for (int index = 0; index < selectedPanel.getWidgetCount(); index++) {
            DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedPanel.getWidget(index);
            if (widget.getWrappedWidget() instanceof DesignGroupWidget) {
                DesignGroupWidget designGroupWidget = (DesignGroupWidget) widget.getWrappedWidget();
                if (designGroupWidget.isAnyWidgetSelected()) {
                    designGroupWidget.copyWidgets(remove);
                    return;
                }
            }
        }
    }

    public void pasteItem() {
        pasteItem(false);
    }

    public void pasteItem(boolean increment) {
        if (Context.clipBoardWidgets.size() > 0) {
            if (!selectedDragController.isAnyWidgetSelected()) {
                if (this instanceof DesignGroupWidget) {
                } else if (increment) {
                    x += selectedPanel.getAbsoluteLeft();
                    y += selectedPanel.getAbsoluteTop();
                } else {
                    x += 10;
                    y += 10;
                }

                pasteWidgets(false);
            } else if (selectedDragController.getSelectedWidgetCount() == 1) {
                DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedDragController.getSelectedWidgetAt(0);
                if (widget.getWrappedWidget() instanceof DesignGroupWidget)
                    ((DesignGroupWidget) widget.getWrappedWidget()).pasteItem();
            }
        }
    }

    /**
     * Deletes the selected widgets.
     */
    public void deleteSelectedItem() {
        if (selectedDragController.isAnyWidgetSelected())
            deleteWidgets();
    }

    /**
     * Aligns all labels to the right and all non labels to their left.
     * This is excecuted after pressing Ctrl + F
     * 
     * @param panel the panel holding the widgets.
     */
    private void rightAlignLabels(AbsolutePanel panel) {
        List<DesignWidgetWrapper> labels = new ArrayList<DesignWidgetWrapper>();
        List<DesignWidgetWrapper> inputs = new ArrayList<DesignWidgetWrapper>();
        int longestLabelWidth = 0, longestLabelLeft = 20;

        boolean usingSelection = false;
        int count = selectedDragController.getSelectedWidgetCount();
        if (count < 2)
            count = panel.getWidgetCount();
        else
            usingSelection = true;

        List<String> tops = getInputWidgetTops(panel, usingSelection, count);

        DesignWidgetWrapper widget = null;
        for (int index = 0; index < count; index++) {
            if (usingSelection)
                widget = (DesignWidgetWrapper) selectedDragController.getSelectedWidgetAt(index);
            else
                widget = (DesignWidgetWrapper) panel.getWidget(index);

            //We do not format buttons and group boxes
            if (widget.getWrappedWidget() instanceof Button
                    || widget.getWrappedWidget() instanceof DesignGroupWidget)
                continue;

            if (widget.getWrappedWidget() instanceof Label) {
                //We do not align labels which are not on the same y pos as at least one input widget.
                if (!tops.contains(widget.getTop()))
                    continue;

                if (widget.getElement().getScrollWidth() > longestLabelWidth) {
                    longestLabelWidth = widget.getElement().getScrollWidth();
                    longestLabelLeft = FormUtil.convertDimensionToInt(widget.getLeft());
                }

                labels.add(widget);
            } else
                inputs.add(widget);
        }

        int relativeWidth = longestLabelWidth + longestLabelLeft;
        String left = (relativeWidth + 5) + OpenXdataConstants.UNITS;
        for (int index = 0; index < inputs.size(); index++)
            inputs.get(index).setLeft(left);

        for (int index = 0; index < labels.size(); index++) {
            widget = labels.get(index);
            widget.setLeft((relativeWidth - widget.getElement().getScrollWidth() + OpenXdataConstants.UNITS));
        }
    }

    /**
     * Gets a list of widget top values, in the selected page, which capture user data. 
     * These are neither labels, buttons, nor group boxes.
     * 
     * @param panel the absolute panel for the current page.
     * @param usingSelection set to true if you want only selected widgets.
     * @param count the number of widgets to traverse.
     * @return the widget top value list.
     */
    private List<String> getInputWidgetTops(AbsolutePanel panel, boolean usingSelection, int count) {
        List<String> inputWidgetTops = new ArrayList<String>();

        DesignWidgetWrapper widget = null;
        for (int index = 0; index < count; index++) {
            if (usingSelection)
                widget = (DesignWidgetWrapper) selectedDragController.getSelectedWidgetAt(index);
            else
                widget = (DesignWidgetWrapper) panel.getWidget(index);

            if (widget.getWrappedWidget() instanceof Button
                    || widget.getWrappedWidget() instanceof DesignGroupWidget
                    || widget.getWrappedWidget() instanceof Label)
                continue;

            inputWidgetTops.add(widget.getTop());
        }

        return inputWidgetTops;
    }

    /**
     * @see org.openxdata.formtools.client.controller.IFormDesignerController#alignLeft()
     */
    public boolean alignLeft() {
        List<Widget> widgets = selectedDragController.getSelectedWidgets();
        if (widgets == null || widgets.size() < 2) {
            for (int index = 0; index < selectedPanel.getWidgetCount(); index++) {
                DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedPanel.getWidget(index);
                if (widget.getWrappedWidget() instanceof DesignGroupWidget) {
                    if (((DesignGroupWidget) widget.getWrappedWidget()).alignLeft())
                        return true;
                }
            }
            return false;
        }

        //align according to the last selected item.
        String left = ((DesignWidgetWrapper) widgets.get(widgets.size() - 1)).getLeft();
        for (int index = 0; index < widgets.size(); index++)
            ((DesignWidgetWrapper) widgets.get(index)).setLeft(left);

        return true;
    }

    /**
     * @see org.openxdata.formtools.client.controller.IFormDesignerController#alignRight()
     */
    public boolean alignRight() {
        List<Widget> widgets = selectedDragController.getSelectedWidgets();
        if (widgets == null || widgets.size() < 2) {
            for (int index = 0; index < selectedPanel.getWidgetCount(); index++) {
                DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedPanel.getWidget(index);
                if (widget.getWrappedWidget() instanceof DesignGroupWidget) {
                    if (((DesignGroupWidget) widget.getWrappedWidget()).alignRight())
                        return true;
                }
            }
            return false;
        }

        //align according to the last selected item.
        DesignWidgetWrapper widget = (DesignWidgetWrapper) widgets.get(widgets.size() - 1);
        int total = widget.getElement().getScrollWidth() + FormUtil.convertDimensionToInt(widget.getLeft());
        for (int index = 0; index < widgets.size(); index++) {
            widget = (DesignWidgetWrapper) widgets.get(index);
            widget.setLeft((total - widget.getElement().getScrollWidth() + OpenXdataConstants.UNITS));
        }

        return true;
    }

    /**
     * @see org.openxdata.formtools.client.controller.IFormDesignerController#alignLeft()
     */
    public boolean alignTop() {
        List<Widget> widgets = selectedDragController.getSelectedWidgets();
        if (widgets == null || widgets.size() < 2) {
            for (int index = 0; index < selectedPanel.getWidgetCount(); index++) {
                DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedPanel.getWidget(index);
                if (widget.getWrappedWidget() instanceof DesignGroupWidget) {
                    if (((DesignGroupWidget) widget.getWrappedWidget()).alignTop())
                        return true;
                }
            }
            return false;
        }

        //align according to the last selected item.
        String top = ((DesignWidgetWrapper) widgets.get(widgets.size() - 1)).getTop();
        for (int index = 0; index < widgets.size(); index++)
            ((DesignWidgetWrapper) widgets.get(index)).setTop(top);

        return true;
    }

    /**
     * @see org.openxdata.formtools.client.controller.IFormDesignerController#alignRight()
     */
    public boolean alignBottom() {
        List<Widget> widgets = selectedDragController.getSelectedWidgets();
        if (widgets == null || widgets.size() < 2) {
            for (int index = 0; index < selectedPanel.getWidgetCount(); index++) {
                DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedPanel.getWidget(index);
                if (widget.getWrappedWidget() instanceof DesignGroupWidget) {
                    if (((DesignGroupWidget) widget.getWrappedWidget()).alignBottom())
                        return true;
                }
            }
            return false;
        }

        //align according to the last selected item.
        DesignWidgetWrapper widget = (DesignWidgetWrapper) widgets.get(widgets.size() - 1);
        int total = widget.getElement().getScrollHeight() + FormUtil.convertDimensionToInt(widget.getTop());
        for (int index = 0; index < widgets.size(); index++) {
            widget = (DesignWidgetWrapper) widgets.get(index);
            widget.setTop((total - widget.getElement().getScrollHeight() + OpenXdataConstants.UNITS));
        }

        return true;
    }

    /**
     * @see org.openxdata.formtools.client.controller.IFormDesignerController#makeSameHeight()
     */
    public boolean makeSameHeight() {
        List<Widget> widgets = selectedDragController.getSelectedWidgets();
        if (widgets == null || widgets.size() < 2) {
            for (int index = 0; index < selectedPanel.getWidgetCount(); index++) {
                DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedPanel.getWidget(index);
                if (widget.getWrappedWidget() instanceof DesignGroupWidget) {
                    if (((DesignGroupWidget) widget.getWrappedWidget()).makeSameHeight())
                        return true;
                }
            }
            return false;
        }

        //align according to the last selected item.
        String height = ((DesignWidgetWrapper) widgets.get(widgets.size() - 1)).getHeight();
        for (int index = 0; index < widgets.size(); index++)
            ((DesignWidgetWrapper) widgets.get(index)).setHeight(height);

        return true;
    }

    /**
     * @see org.openxdata.formtools.client.controller.IFormDesignerController#makeSameWidth()
     */
    public boolean makeSameWidth() {
        List<Widget> widgets = selectedDragController.getSelectedWidgets();
        if (widgets == null || widgets.size() < 2) {
            for (int index = 0; index < selectedPanel.getWidgetCount(); index++) {
                DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedPanel.getWidget(index);
                if (widget.getWrappedWidget() instanceof DesignGroupWidget) {
                    if (((DesignGroupWidget) widget.getWrappedWidget()).makeSameWidth())
                        return true;
                }
            }
            return false;
        }

        //align according to the last selected item.
        String width = ((DesignWidgetWrapper) widgets.get(widgets.size() - 1)).getWidth();
        for (int index = 0; index < widgets.size(); index++)
            ((DesignWidgetWrapper) widgets.get(index)).setWidth(width);

        return true;
    }

    /**
     * @see org.openxdata.formtools.client.controller.IFormDesignerController#makeSameSize()
     */
    public boolean makeSameSize() {
        List<Widget> widgets = selectedDragController.getSelectedWidgets();
        if (widgets == null || widgets.size() < 2) {
            for (int index = 0; index < selectedPanel.getWidgetCount(); index++) {
                DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedPanel.getWidget(index);
                if (widget.getWrappedWidget() instanceof DesignGroupWidget) {
                    if (((DesignGroupWidget) widget.getWrappedWidget()).makeSameSize())
                        return true;
                }
            }
            return false;
        }

        //align according to the last selected item.
        String width = ((DesignWidgetWrapper) widgets.get(widgets.size() - 1)).getWidth();
        String height = ((DesignWidgetWrapper) widgets.get(widgets.size() - 1)).getHeight();
        for (int index = 0; index < widgets.size(); index++) {
            ((DesignWidgetWrapper) widgets.get(index)).setWidth(width);
            ((DesignWidgetWrapper) widgets.get(index)).setHeight(height);
        }

        return true;
    }

    /**
     * @see org.openxdata.formtools.client.controller.IFormDesignerController#format()
     */
    public boolean format() {
        if (selectedDragController.getSelectedWidgetCount() < 2) {
            for (int index = 0; index < selectedPanel.getWidgetCount(); index++) {
                DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedPanel.getWidget(index);
                if (widget.getWrappedWidget() instanceof DesignGroupWidget) {
                    if (((DesignGroupWidget) widget.getWrappedWidget()).format())
                        return true;
                }
            }
            return false;
        }

        rightAlignLabels(selectedPanel);
        return true;
    }

    /**
     * Selects all widgets on the selected page.
     */
    protected void selectAll() {
        if (editWidget != null) {
            txtEdit.selectAll();
            return; //let label editor do select all
        }

        selectedDragController.clearSelection();
        for (int i = 0; i < selectedPanel.getWidgetCount(); i++) {
            if (selectedPanel.getWidget(i) instanceof DesignWidgetWrapper) {
                DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedPanel.getWidget(i);
                if ("100%".equalsIgnoreCase(widget.getWidth()))
                    continue; //This could be a group header label and hence we are not selecting it via all
                selectedDragController.selectWidget(widget);
            }
        }
    }

    public FormDesignerDragController getDragController() {
        return this.selectedDragController;
    }

    public AbsolutePanel getPanel() {
        return this.selectedPanel;
    }

    public PopupPanel getWidgetPopup() {
        return widgetPopup;
    }

    protected boolean handleStartLabelEditing(Event event) {
        String s = event.getTarget().getClassName();
        s.toString();
        if (!event.getCtrlKey() && !isTextBoxFocus(event)) {
            if (selectedDragController.getSelectedWidgetCount() == 1) {
                stopLabelEdit(false);

                if (selectedDragController.getSelectedWidgetCount() == 0 && this instanceof DesignGroupWidget)
                    editWidget = ((DesignGroupWidget) this).getHeaderLabel();
                else
                    editWidget = (DesignWidgetWrapper) selectedDragController.getSelectedWidgetAt(0);

                if (editWidget != null) {
                    if (editWidget.getWidgetSelectionListener() instanceof DesignGroupWidget
                            & !(this instanceof DesignGroupWidget)) {
                        boolean ret = ((DesignGroupWidget) editWidget.getWidgetSelectionListener())
                                .handleStartLabelEditing(event);
                        editWidget = null;
                        return ret;
                    } else if (editWidget.hasLabelEdidting()) {
                        selectedDragController.makeNotDraggable(editWidget);

                        if (this instanceof DesignGroupWidget) {
                            ((DesignGroupWidget) this).clearSelection();
                        }

                        selectedDragController.clearSelection();
                        editWidget.startEditMode(txtEdit);
                        return true;
                    } else if (editWidget.getWrappedWidget() instanceof DesignGroupWidget) {
                        //Handle label editing
                        DesignWidgetWrapper headerLabel = ((DesignGroupWidget) editWidget.getWrappedWidget())
                                .getHeaderLabel();
                        if (headerLabel == null)
                            return false;

                        //Without these two lines, the edit text is not selected, not even with Ctrl + A
                        selectedDragController.makeNotDraggable(editWidget);
                        editWidget.removeStyleName("dragdrop-handle");

                        ((DesignGroupWidget) editWidget.getWrappedWidget()).clearSelection();
                        selectedDragController.clearSelection();
                        headerLabel.startEditMode(txtEdit);
                        return true;
                    } else
                        editWidget = null;
                }
            }
        }
        return false;
    }

    protected void handleStopLabelEditing(boolean select) {
        if (editWidget == null && selectedDragController.isAnyWidgetSelected()) {
            editWidget = (DesignWidgetWrapper) selectedDragController.getSelectedWidgetAt(0);
            if (editWidget.getWidgetSelectionListener() instanceof DesignGroupWidget
                    & !(this instanceof DesignGroupWidget)) {
                ((DesignGroupWidget) editWidget.getWidgetSelectionListener()).handleStopLabelEditing(select);
                editWidget = null;
                return;
            } else if (editWidget.hasLabelEdidting())
                stopLabelEdit(select);
        } else
            stopLabelEdit(select);
    }

    protected boolean isTextBoxFocus(Event event) {
        return event.getTarget().getClassName().equalsIgnoreCase("gwt-TextBox")
                || event.getTarget().getClassName().equalsIgnoreCase("gwt-SuggestBox");
    }

    protected boolean isTextAreaFocus(Event event) {
        return event.getTarget().getClassName().equalsIgnoreCase("gwt-TextArea");
    }

    public int getRubberLeft() {
        return FormUtil.convertDimensionToInt(DOM.getStyleAttribute(rubberBand.getElement(), "left"));
    }

    public int getRubberTop() {
        return FormUtil.convertDimensionToInt(DOM.getStyleAttribute(rubberBand.getElement(), "top"));
    }

    public void startRubberBand(Event event) {
        //Prevent the browser from selecting text.
        DOM.eventPreventDefault(event);

        selectedPanel.add(rubberBand);

        x = event.getClientX() - selectedPanel.getAbsoluteLeft();
        y = event.getClientY() - selectedPanel.getAbsoluteTop();

        DOM.setStyleAttribute(rubberBand.getElement(), "width", 0 + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(rubberBand.getElement(), "height", 0 + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(rubberBand.getElement(), "left", x + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(rubberBand.getElement(), "top", y + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(rubberBand.getElement(), "visibility", "visible");

        DOM.setCapture(getElement());
    }

    public void stopRubberBand(Event event) {
        selectedPanel.remove(rubberBand);
    }

    public void moveRubberBand(Event event) {
        try {
            int width = (event.getClientX() - selectedPanel.getAbsoluteLeft()) - x;
            int height = (event.getClientY() - selectedPanel.getAbsoluteTop()) - y;

            if (width < 0) {
                DOM.setStyleAttribute(rubberBand.getElement(), "left",
                        event.getClientX() - selectedPanel.getAbsoluteLeft() + OpenXdataConstants.UNITS);
                DOM.setStyleAttribute(rubberBand.getElement(), "width", width * -1 + OpenXdataConstants.UNITS);
            } else
                DOM.setStyleAttribute(rubberBand.getElement(), "width",
                        (event.getClientX() - selectedPanel.getAbsoluteLeft()) - getRubberLeft()
                                + OpenXdataConstants.UNITS);

            if (height < 0) {
                DOM.setStyleAttribute(rubberBand.getElement(), "top",
                        event.getClientY() - selectedPanel.getAbsoluteTop() + OpenXdataConstants.UNITS);
                DOM.setStyleAttribute(rubberBand.getElement(), "height", height * -1 + OpenXdataConstants.UNITS);
            } else
                DOM.setStyleAttribute(rubberBand.getElement(), "height",
                        (event.getClientY() - selectedPanel.getAbsoluteTop()) - getRubberTop()
                                + OpenXdataConstants.UNITS);
        } catch (Exception ex) {
            //This exception is intentionally ignored as a rubber band is no big deal
        }
    }

    /**
     * Moves widgets in a given direction due to movement of the keyboard arrow keys.
     * 
     * @param dirrection the move dirrection.
     * @return true if any widget was moved, else false.
     */
    protected boolean moveWidgets(int dirrection) {
        List<Widget> widgets = selectedDragController.getSelectedWidgets();
        if (widgets == null)
            return false;

        int pos;
        for (int index = 0; index < widgets.size(); index++) {
            DesignWidgetWrapper widget = (DesignWidgetWrapper) widgets.get(index);

            if (dirrection == MOVE_LEFT) {
                pos = FormUtil.convertDimensionToInt(widget.getLeft());
                widget.setLeft(pos - 1 + OpenXdataConstants.UNITS);
            } else if (dirrection == MOVE_RIGHT) {
                pos = FormUtil.convertDimensionToInt(widget.getLeft());
                widget.setLeft(pos + 1 + OpenXdataConstants.UNITS);
            } else if (dirrection == MOVE_UP) {
                pos = FormUtil.convertDimensionToInt(widget.getTop());
                widget.setTop(pos - 1 + OpenXdataConstants.UNITS);
            } else if (dirrection == MOVE_DOWN) {
                pos = FormUtil.convertDimensionToInt(widget.getTop());
                widget.setTop(pos + 1 + OpenXdataConstants.UNITS);
            }
        }

        return widgets.size() > 0;
    }

    /**
     * Resizes widgets in a given direction due to movement of the keyboard arrow keys.
     * 
     * @param Event the current event object.
     * @return true if any widget was resized, else false.
     */
    protected boolean resizeWidgets(Event event) {
        List<Widget> widgets = selectedDragController.getSelectedWidgets();
        if (widgets == null)
            return false;

        int resizedCount = 0;

        int keycode = event.getKeyCode();
        for (int index = 0; index < widgets.size(); index++) {
            DesignWidgetWrapper widget = (DesignWidgetWrapper) widgets.get(index);
            if (!widget.isResizable())
                continue;

            resizedCount++;

            if (keycode == KeyCodes.KEY_LEFT)
                widget.setWidthInt(widget.getWidthInt() - 1);
            else if (keycode == KeyCodes.KEY_RIGHT)
                widget.setWidthInt(widget.getWidthInt() + 1);
            else if (keycode == KeyCodes.KEY_UP)
                widget.setHeightInt(widget.getHeightInt() - 1);
            else if (keycode == KeyCodes.KEY_DOWN)
                widget.setHeightInt(widget.getHeightInt() + 1);
            else
                return false; //Shift press when not in combination with arrow keys is ignored.
        }

        return resizedCount > 0;
    }

    /**
     * Selects widgets wrapped by the rubber band.
     * 
     * @param event the event object.
     */
    protected void selectWidgets(Event event) {
        int endX = event.getClientX() - selectedPanel.getAbsoluteLeft();
        int endY = event.getClientY() - selectedPanel.getAbsoluteTop();

        //Store this for Group Widgets
        rubberBandHeight = DOM.getStyleAttribute(rubberBand.getElement(), "height");
        rubberBandWidth = DOM.getStyleAttribute(rubberBand.getElement(), "width");

        for (int i = 0; i < selectedPanel.getWidgetCount(); i++) {
            if (selectedPanel.getWidget(i) instanceof DesignWidgetWrapper) {
                DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedPanel.getWidget(i);
                if (widget.isWidgetInRect(selectionXPos, selectionYPos, endX, endY))
                    selectedDragController.selectWidget(widget);
            }
        }

        if ((event.getCtrlKey() || event.getShiftKey() || event.getAltKey())
                && selectedDragController.getSelectedWidgetCount() == 1) {
            DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedDragController.getSelectedWidgetAt(0);
            widget.setWidthInt(endX - widget.getLeftInt());
            widget.setHeightInt(endY - widget.getTopInt());
        }

        if (event.getKeyCode() == KeyCodes.KEY_UP || event.getKeyCode() == KeyCodes.KEY_DOWN) {
            for (int index = 0; index < selectedDragController.getSelectedWidgetCount(); index++) {
                DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedDragController
                        .getSelectedWidgetAt(index);
                widget.setHeightInt(endY - widget.getTopInt());
            }
        }

        if (event.getKeyCode() == KeyCodes.KEY_RIGHT || event.getKeyCode() == KeyCodes.KEY_LEFT) {
            for (int index = 0; index < selectedDragController.getSelectedWidgetCount(); index++) {
                DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedDragController
                        .getSelectedWidgetAt(index);
                widget.setWidthInt(endX - widget.getLeftInt());
            }
        }

        if (selectedDragController.getSelectedWidgetCount() > 0)
            widgetSelectionListener.onWidgetSelected(null, false);
    }

    /**
     * Updates the design surface context menu basing on the selected widgets.
     */
    protected void updatePopup() {
        boolean visible = false;
        if (selectedDragController.isAnyWidgetSelected())
            visible = true;
        deleteWidgetsSeparator.setVisible(visible);
        deleteWidgetsMenu.setVisible(visible);

        //For now this is only used by the DesignSurfaceView
        if (groupWidgetsSeparator != null) {
            groupWidgetsSeparator.setVisible(visible);
            groupWidgetsMenu.setVisible(visible);
        }

        cutCopySeparator.setVisible(visible);
        cutMenu.setVisible(visible);
        copyMenu.setVisible(visible);

        visible = false;
        if (Context.clipBoardWidgets.size() > 0)
            visible = true;
        pasteSeparator.setVisible(visible);
        pasteMenu.setVisible(visible);

        lockWidgetsMenu.setHTML(FormDesignerUtil.createHeaderHTML(images.add(),
                Context.getLockWidgets() ? messages.unLockWidgets() : messages.lockWidgets()));
    }

    /**
     * Gets the design widget wrapper representing the selected page.
     * 
     * @return the design widget wrapper for the selected page.
     */
    protected DesignWidgetWrapper getSelPageDesignWidget() {
        return pageWidgets.get(selectedTabIndex);
    }

    /**
     * Adds a new widget with a widget selection listener to the selected page.
     * 
     * @param widget the widget.
     * @param select set to true to automatically select the new widget.
     * @param widgetSelectionListener the widget selection listener.
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewWidget(Widget widget, boolean select,
            WidgetSelectionListener widgetSelectionListener) {
        currentWidgetSelectionListener = widgetSelectionListener;
        return addNewWidget(widget, select);
    }

    /**
     * Adds a new widget to the currently selected page.
     * 
     * @param widget the widget to add.
     * @param select set to true to automatically select the widget.
     * @return the new widget.
     */
    protected DesignWidgetWrapper addNewWidget(Widget widget, boolean select) {
        stopLabelEdit(false);

        DesignWidgetWrapper wrapper = new DesignWidgetWrapper(widget, widgetPopup, currentWidgetSelectionListener);

        if (widget instanceof Label || widget instanceof TextBox || widget instanceof ListBox
                || widget instanceof TextArea || widget instanceof Hyperlink || widget instanceof CheckBox
                || widget instanceof RadioButton || widget instanceof DateTimeWidget || widget instanceof Button) {

            wrapper.setFontFamily(FormUtil.getDefaultFontFamily());
            wrapper.setFontSize(FormUtil.getDefaultFontSize());

            if (widget instanceof DateTimeWidget) {
                ((DateTimeWidget) widget).setFontFamily(FormUtil.getDefaultFontFamily());
                ((DateTimeWidget) widget).setFontSize(FormUtil.getDefaultFontSize());
            }
        }

        selectedDragController.makeDraggable(wrapper);

        selectedPanel.add(wrapper);
        selectedPanel.setWidgetPosition(wrapper, x - wrapper.getParent().getAbsoluteLeft(),
                y - wrapper.getParent().getAbsoluteTop());
        if (select) {
            selectedDragController.clearSelection();
            selectedDragController.toggleSelection(wrapper);
            onWidgetSelected(wrapper, false);
        }
        return wrapper;
    }

    /**
     * Adds a new label widget to the selected page.
     * 
     * @param text the label text.
     * @param select set to true if you want to automatically select the widget.
     * @return the new label widget.
     */
    protected DesignWidgetWrapper addNewLabel(String text, boolean select) {
        if (text == null)
            text = i18n.label();
        Label label = new Label(text);

        DesignWidgetWrapper wrapper = addNewWidget(label, select);
        wrapper.setFontFamily(FormUtil.getDefaultFontFamily());
        wrapper.setFontSize(FormUtil.getDefaultFontSize());
        return wrapper;
    }

    /**
     * Adds a new audio or video widget.
     * 
     * @param text the display text for the widget.
     * @param select set to true to automatically select the new widget.
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewVideoAudio(String text, boolean select) {
        if (text == null)
            text = i18n.clickToPlay();
        Hyperlink link = new Hyperlink(text, "");

        DesignWidgetWrapper wrapper = addNewWidget(link, select);
        wrapper.setFontFamily(FormUtil.getDefaultFontFamily());
        wrapper.setFontSize(FormUtil.getDefaultFontSize());
        return wrapper;
    }

    /**
     * Adds a new server search widget to the selected page.
     * 
     * @param text the display text for the widget.
     * @param select set to true to automatically select the new widget.
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewServerSearch(String text, boolean select) {
        if (text == null)
            text = i18n.noSelection();
        Label label = new Label(text);

        DesignWidgetWrapper wrapper = addNewWidget(label, select);
        wrapper.setFontFamily(FormUtil.getDefaultFontFamily());
        wrapper.setFontSize(FormUtil.getDefaultFontSize());
        return wrapper;
    }

    /**
     * Adds a new picture widget to the selected page.
     * 
     * @param select set to true to automatically select the new widget.s
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewPicture(boolean select) {
        Image image = FormUtil.createImage(images.picture());
        DOM.setStyleAttribute(image.getElement(), "height", "155" + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(image.getElement(), "width", "185" + OpenXdataConstants.UNITS);
        return addNewWidget(image, select);
    }

    /**
     * Adds a new TextBox to the selected page.
     * 
     * @param select set to true to automatically select the new widget.
     * @return the newly added widget.s
     */
    protected DesignWidgetWrapper addNewTextBox(boolean select) {
        TextBoxWidget tb = new TextBoxWidget();
        DOM.setStyleAttribute(tb.getElement(), "height", "25" + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(tb.getElement(), "width", "200" + OpenXdataConstants.UNITS);
        return addNewWidget(tb, select);
    }

    /**
     * Adds a new date picker to the selected page.
     * 
     * @param select set to true to automatically select the new widget.
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewDatePicker(boolean select) {
        DatePickerEx tb = new DatePickerWidget();
        DOM.setStyleAttribute(tb.getElement(), "height", "25" + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(tb.getElement(), "width", "200" + OpenXdataConstants.UNITS);
        return addNewWidget(tb, select);
    }

    /**
     * Adds a new date time widget to the selected page.
     * 
     * @param select set to true to automatically select the new widget.
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewDateTimeWidget(boolean select) {
        DateTimeWidget tb = new DateTimeWidget();
        DOM.setStyleAttribute(tb.getElement(), "height", "25" + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(tb.getElement(), "width", "200" + OpenXdataConstants.UNITS);
        return addNewWidget(tb, select);
    }

    /**
     * Adds a new time widget to the selected page.
     * 
     * @param select set to true to automatically select the new widget.
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewTimeWidget(boolean select) {
        TimeWidget tb = new TimeWidget();
        DOM.setStyleAttribute(tb.getElement(), "height", "25" + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(tb.getElement(), "width", "200" + OpenXdataConstants.UNITS);
        return addNewWidget(tb, select);
    }

    /**
     * Adds a new CheckBox to the selected page.
     * 
     * @param select set to true to automatically select the new widget.
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewCheckBox(boolean select) {
        DesignWidgetWrapper wrapper = addNewWidget(new CheckBox(i18n.checkBox()), select);
        wrapper.setFontFamily(FormUtil.getDefaultFontFamily());
        wrapper.setFontSize(FormUtil.getDefaultFontSize());
        return wrapper;
    }

    /**
     * Adds a new radio button to the selected page.
     * 
     * @param select set to true to automatically select the new widget.
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewRadioButton(boolean select) {
        DesignWidgetWrapper wrapper = addNewWidget(new RadioButtonWidget("RadioButton", i18n.radioButton()),
                select);
        wrapper.setFontFamily(FormUtil.getDefaultFontFamily());
        wrapper.setFontSize(FormUtil.getDefaultFontSize());
        return wrapper;
    }

    /**
     * Adds a new drop downlist box to the selected page.
     * 
     * @param select set to true to automatically select the new widget.
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewDropdownList(boolean select) {
        ListBox lb = new ListBox(false);
        DOM.setStyleAttribute(lb.getElement(), "height", "25" + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(lb.getElement(), "width", "200" + OpenXdataConstants.UNITS);
        DesignWidgetWrapper wrapper = addNewWidget(lb, select);
        return wrapper;
    }

    /**
     * Adds a new text area to the selected page.
     * 
     * @param select set to true to automatically select the new widget.
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewTextArea(boolean select) {
        TextArea ta = new TextArea();
        DOM.setStyleAttribute(ta.getElement(), "height", "60" + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(ta.getElement(), "width", "200" + OpenXdataConstants.UNITS);
        return addNewWidget(ta, select);
    }

    /**
     * Adds a new button.
     * 
     * @param label the button label or text.
     * @param binding the widget binding.
     * @param select set to true to automatically select the new widget.
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewButton(String label, String binding, boolean select) {
        DesignWidgetWrapper wrapper = addNewWidget(new Button(label), select);
        wrapper.setFontFamily(FormUtil.getDefaultFontFamily());
        wrapper.setFontSize(FormUtil.getDefaultFontSize());
        wrapper.setWidthInt(70);
        wrapper.setHeightInt(30);
        wrapper.setBinding(binding);
        wrapper.setTitle(binding);
        return wrapper;
    }

    /**
     * Adds a new submit button.
     * 
     * @param select set to true to automatically select the new button.s
     * @return the new button widget.
     */
    protected DesignWidgetWrapper addSubmitButton(boolean select) {
        return addNewButton(i18n.submit(), "submit", select);
    }

    /**
     * Adds a new cancel button.
     * 
     * @param select set to true to automatically select the new widget.
     * @return the new button.
     */
    protected DesignWidgetWrapper addCancelButton(boolean select) {
        return addNewButton(i18n.cancel(), "cancel", select);
    }

    public void onCopy(Widget sender) {
        selectedDragController.clearSelection();
        selectedDragController.selectWidget(sender.getParent().getParent());
        copyWidgets(false);
    }

    public void onCut(Widget sender) {
        selectedDragController.clearSelection();
        selectedDragController.selectWidget(sender.getParent().getParent());
        cutWidgets();
    }

    public void onDelete(Widget sender) {
        selectedDragController.clearSelection();
        selectedDragController.selectWidget(sender.getParent().getParent());
        deleteWidgets();
    }

    public DesignWidgetWrapper onDrop(Widget widget, int x, int y) {
        if (!(widget instanceof PaletteWidget))
            return null;

        this.x = x;
        this.y = y;

        String text = ((PaletteWidget) widget).getName();

        DesignWidgetWrapper retWidget = null;

        if (text.equals(i18n.label()))
            retWidget = addNewLabel(i18n.label(), true);
        else if (text.equals(i18n.textBox()))
            retWidget = addNewTextBox(true);
        else if (text.equals(i18n.checkBox()))
            retWidget = addNewCheckBox(true);
        else if (text.equals(i18n.radioButton()))
            retWidget = addNewRadioButton(true);
        else if (text.equals(i18n.listBox()))
            retWidget = addNewDropdownList(true);
        else if (text.equals(i18n.textArea()))
            retWidget = addNewTextArea(true);
        else if (text.equals(i18n.button()))
            retWidget = addNewButton(i18n.button(), null, true);
        else if (text.equals(i18n.datePicker()))
            retWidget = addNewDatePicker(true);
        else if (text.equals(messages.dateTimeWidget()))
            retWidget = addNewDateTimeWidget(true);
        else if (text.equals(messages.timeWidget()))
            retWidget = addNewTimeWidget(true);
        else if (text.equals(i18n.groupBox()))
            retWidget = addNewGroupBox(true);
        else if (text.equals(i18n.repeatSection()))
            retWidget = addNewRepeatSection(true);
        else if (text.equals(i18n.picture()))
            retWidget = addNewPictureSection(null, null, true);
        else if (text.equals(i18n.videoAudio()))
            retWidget = addNewVideoAudioSection(null, null, true);

        if (retWidget != null) {
            int height = FormUtil.convertDimensionToInt(getHeight());
            int h = retWidget.getTopInt() + retWidget.getHeightInt();
            if (height < h)
                setHeight(height + (h - height) + 10 + OpenXdataConstants.UNITS);

            int width = FormUtil.convertDimensionToInt(getWidth());
            int w = retWidget.getLeftInt() + retWidget.getWidthInt();
            if (width < w)
                setWidth(width + (w - width) + 10 + OpenXdataConstants.UNITS);
        }

        return retWidget;
    }

    /**
     * Sets up the current page.
     */
    protected void initPanel() {

        //Create a DragController for each logical area where a set of draggable
        // widgets and drop targets will be allowed to interact with one another.
        selectedDragController = new FormDesignerDragController(selectedPanel, false, this);

        // Allow multiple widgets to be selected at once using CTRL-click
        selectedDragController.setBehaviorMultipleSelection(true);

        // create a DropController for each drop target on which draggable widgets
        // can be dropped
        DropController dropController = new FormDesignerDropController(selectedPanel, this);

        // Don't forget to register each DropController with a DragController
        selectedDragController.registerDropController(dropController);
        PaletteView.registerDropController(dropController);

        initEditWidget();
    }

    /**
     * Sets up the inline label editing widget.
     */
    private void initEditWidget() {
        DOM.setStyleAttribute(txtEdit.getElement(), "borderStyle", "none");
        DOM.setStyleAttribute(txtEdit.getElement(), "fontFamily", FormUtil.getDefaultFontFamily());
        DOM.setStyleAttribute(txtEdit.getElement(), "fontSize", FormUtil.getDefaultFontSize());
        txtEdit.setWidth("400" + OpenXdataConstants.UNITS);
    }

    /**
     * Stops inplace editing of widget text.
     * 
     * @param select a flag to determine whether to select the stoped edit widget.
     */
    protected void stopLabelEdit(boolean select) {
        if (editWidget != null) {
            if (selectedPanel.getWidgetIndex(editWidget) < 0) {
                editWidget = null;
                return;
            }

            DesignWidgetWrapper designGroupWidgetWrapper = null;
            if (editWidget.getWrappedWidget() instanceof DesignGroupWidget) {
                //Stop header label editing
                DesignWidgetWrapper headerLabel = ((DesignGroupWidget) editWidget.getWrappedWidget())
                        .getHeaderLabel();
                if (headerLabel != null) {
                    designGroupWidgetWrapper = editWidget;
                    editWidget = headerLabel;
                }
            }

            editWidget.stopEditMode();

            String text = txtEdit.getText();
            if (text.trim().length() > 0)
                editWidget.setText(text);

            if (designGroupWidgetWrapper == null) {
                selectedPanel.setWidgetPosition(editWidget, editWidget.getLeftInt(), editWidget.getTopInt());
                selectedDragController.makeDraggable(editWidget);
            } else
                selectedDragController.makeDraggable(designGroupWidgetWrapper, editWidget);

            if (designGroupWidgetWrapper != null)
                editWidget = designGroupWidgetWrapper;

            if (select) {
                selectedDragController.selectWidget(editWidget);
                widgetSelectionListener.onWidgetSelected(editWidget, false);
            }

            editWidget = null;
        }
    }

    @Override
    public void onBrowserEvent(Event event) {

        switch (DOM.eventGetType(event)) {
        case Event.ONMOUSEDOWN:

            FormDesignerUtil.enableContextMenu(getElement());

            mouseMoved = false;
            x = event.getClientX();
            y = event.getClientY();

            if (editWidget != null) {
                if (editWidget.getWrappedWidgetEx().getElement() == event.getTarget())
                    return;
                handleStopLabelEditing(false);
            }

            if ((event.getButton() & Event.BUTTON_RIGHT) != 0) {
                updatePopup();

                int ypos = event.getClientY();
                if (Window.getClientHeight() - ypos < 220)
                    ypos = event.getClientY() - 220;

                int xpos = event.getClientX();
                if (Window.getClientWidth() - xpos < 170)
                    xpos = event.getClientX() - 170;

                FormDesignerUtil.disableContextMenu(popup.getElement());
                FormDesignerUtil.disableContextMenu(getElement());
                popup.setPopupPosition(xpos, ypos);
                popup.show();
            } else {
                selectionXPos = selectionYPos = -1;
                selectionXPos = x - selectedPanel.getAbsoluteLeft();
                selectionYPos = y - selectedPanel.getAbsoluteTop();

                if (!(event.getShiftKey() || event.getCtrlKey())) {
                    selectedDragController.clearSelection();
                    if (event.getTarget() != this.selectedPanel.getElement()) {
                        try {
                            if (event.getTarget().getInnerText().equals(DesignWidgetWrapper.getTabDisplayText(
                                    tabs.getTabBar().getTabHTML(tabs.getTabBar().getSelectedTab())))) {
                                widgetSelectionListener.onWidgetSelected(getSelPageDesignWidget(),
                                        event.getCtrlKey());
                                return;
                            }
                        } catch (Exception ex) {
                        }
                    }
                }

                if (widgetSelectionListener != null) {
                    if (this instanceof DesignGroupWidget)
                        widgetSelectionListener.onWidgetSelected((DesignWidgetWrapper) this.getParent().getParent(),
                                event.getCtrlKey());

                    widgetSelectionListener.onWidgetSelected(this, event.getCtrlKey());
                }

                clearGroupBoxSelection();

                if (!(this instanceof DesignGroupWidget
                        && !"default".equals(DOM.getStyleAttribute(getElement(), "cursor"))))
                    startRubberBand(event);
            }

            break;
        case Event.ONMOUSEMOVE:
            mouseMoved = true;
            if (event.getButton() == Event.BUTTON_LEFT)
                moveRubberBand(event);
            break;
        case Event.ONMOUSEUP:
            stopRubberBand(event);
            if (selectionXPos > 0 && mouseMoved)
                selectWidgets(event);
            mouseMoved = false;
            DOM.releaseCapture(getElement()); //Mouse could have been captured in startRubberBand and so release it.
            break;
        }
    }

    /**
     * Un selects all selected widgets, if any, in all group boxes on the current page.
     */
    protected void clearGroupBoxSelection() {
        for (int index = 0; index < selectedPanel.getWidgetCount(); index++) {
            Widget wid = selectedPanel.getWidget(index);
            if (!(wid instanceof DesignWidgetWrapper))
                continue;
            if (!(((DesignWidgetWrapper) wid).getWrappedWidget() instanceof DesignGroupWidget))
                continue;
            ((DesignGroupWidget) ((DesignWidgetWrapper) wid).getWrappedWidget()).clearGroupBoxSelection();

            if (selectedDragController.isWidgetSelected(wid))
                selectedDragController.toggleSelection(wid);
        }
    }

    /**
     * Un selects all selected widgets, if any, on the current page.
     */
    protected void clearSelection() {
        selectedDragController.clearSelection();
    }

    /**
     * Processes key down events for the selected page.
     * 
     * @param event the event object.
     * @return true if the event has been handled, else false.
     */
    protected boolean handleKeyDownEvent(Event event) {
        boolean ret = false;

        if (isTextBoxFocus(event) && editWidget == null)
            return false; //could be on widget properties pane.

        if (this.isVisible()) {
            int keyCode = event.getKeyCode();
            if (event.getShiftKey() || event.getCtrlKey())
                ret = resizeWidgets(event);
            else if (keyCode == KeyCodes.KEY_LEFT)
                ret = moveWidgets(MOVE_LEFT);
            else if (keyCode == KeyCodes.KEY_RIGHT)
                ret = moveWidgets(MOVE_RIGHT);
            else if (keyCode == KeyCodes.KEY_UP)
                ret = moveWidgets(MOVE_UP);
            else if (keyCode == KeyCodes.KEY_DOWN)
                ret = moveWidgets(MOVE_DOWN);

            if (event.getCtrlKey() && (keyCode == 'A' || keyCode == 'a')) {
                if (!isTextAreaFocus(event)) {

                    //This works only when the textarea is clicked to get focus. Need to make it work even before clicking the text area (as long as it is visible)
                    //As for now, Ctrl+A selects all widgets on the design surface's current tab
                    //If one wants to select all widgets within a DesignGroupWidget, they should
                    //right click and select all
                    if (isTextBoxFocus(event)) {
                        if (this instanceof DesignGroupWidget && ((DesignGroupWidget) this).editWidget != null)
                            ((DesignGroupWidget) this).txtEdit.selectAll();

                        DOM.eventPreventDefault(event);
                    } else {
                        if (this instanceof DesignSurfaceView)
                            ((DesignSurfaceView) this).selectAll();
                        else if (widgetSelectionListener instanceof DesignSurfaceView)
                            ((DesignSurfaceView) widgetSelectionListener).selectAll();

                        DOM.eventPreventDefault(event);
                    }
                }
                ret = true;
            } else if (event.getCtrlKey() && (keyCode == 'C' || keyCode == 'c')) {
                if (selectedDragController.isAnyWidgetSelected()) {
                    copyWidgets(false);
                    ret = true;
                }
            } else if (event.getCtrlKey() && (keyCode == 'X' || keyCode == 'x')) {
                if (selectedDragController.isAnyWidgetSelected()) {
                    cutWidgets();
                    ret = true;
                }
            } else if (event.getCtrlKey() && (keyCode == 'V' || keyCode == 'v')) {
                if (Context.clipBoardWidgets.size() > 0 && x >= 0) {
                    if (event.getTarget() == selectedPanel.getElement()) {
                        pasteItem(false);
                        x = -1; //TODO prevent pasting twice as this is fired twice. Needs smarter solution
                    }
                    ret = true;
                }
            } else if (keyCode == KeyCodes.KEY_DELETE && !isTextBoxFocus(event)) {
                if (selectedDragController.isAnyWidgetSelected()) {
                    deleteWidgets();
                    ret = true;
                }
            } else if (event.getCtrlKey() && (keyCode == 'F' || keyCode == 'f')) {
                format();
                DOM.eventPreventDefault(event);
                ret = false; //For now this is reserved for only designsurfaceview
            }

            if (!ret) {
                if (!isTextBoxFocus(event) || (editWidget != null)) {
                    boolean ret1 = false;
                    if (keyCode != KeyCodes.KEY_DELETE && editWidget == null)
                        ret1 = handleStartLabelEditing(event);
                    else if (keyCode == KeyCodes.KEY_ENTER && editWidget != null)
                        handleStopLabelEditing(true);
                    else if (keyCode == KeyCodes.KEY_ESCAPE && editWidget != null) {
                        txtEdit.setText(editWidget.getText());
                        handleStopLabelEditing(true);
                    }

                    if (ret1) //If handle start label edit is handled, need to signal such that others are not called for the same.
                        ret = true;
                }
            }
        }

        return ret;
    }

    /**
     * Gets the background color for the selected page.
     * 
     * @return the html color value.
     */
    public String getBackgroundColor() {
        return DOM.getStyleAttribute(selectedPanel.getElement(), "backgroundColor");
    }

    /**
     * Gets the widgth for the selected page.
     * 
     * @return the widget in pixels.
     */
    public String getWidth() {
        return DOM.getStyleAttribute(selectedPanel.getElement(), "width");
    }

    /**
     * Gets the height for the selected page.
     * 
     * @return the height in pixels.
     */
    public String getHeight() {
        return DOM.getStyleAttribute(selectedPanel.getElement(), "height");
    }

    /**
     * Sets the background color of the selected page.
     * 
     * @param backgroundColor the background color. This can be any valid html color value.
     */
    public void setBackgroundColor(String backgroundColor) {
        try {
            DOM.setStyleAttribute(selectedPanel.getElement(), "backgroundColor", backgroundColor);
        } catch (Exception ex) {
        }
    }

    /**
     * Sets the width in pixels of the selected page.
     */
    public void setWidth(String width) {
        try {
            DOM.setStyleAttribute(selectedPanel.getElement(), "width", width);
        } catch (Exception ex) {
        }
    }

    /**
     * Sets the height in pixels of the selected page.
     */
    public void setHeight(String height) {
        try {
            DOM.setStyleAttribute(selectedPanel.getElement(), "height", height);
        } catch (Exception ex) {
        }
    }

    /**
     * Adds a new set of radio buttons.
     * 
     * @param questionDef the question that we are to add the radio buttons for.
     * @param vertically set to true to add the radio buttons slopping vertically downwards instead of horizontally.
     * @return this will always be null.
     */
    protected DesignWidgetWrapper addNewRadioButtonSet(QuestionDef questionDef, boolean vertically) {
        List<OptionDef> options = questionDef.getOptions();

        if (questionDef.getDataType() == QuestionType.BOOLEAN) {
            options = new ArrayList<OptionDef>();
            options.add(new OptionDef(1, i18n.displayValueTrue(), QuestionDef.TRUE_VALUE, questionDef));
            options.add(new OptionDef(1, i18n.displayValueFalse(), QuestionDef.FALSE_VALUE, questionDef));
        }

        for (int i = 0; i < options.size(); i++) {
            OptionDef optionDef = (OptionDef) options.get(i);
            DesignWidgetWrapper wrapper = addNewWidget(new RadioButtonWidget(optionDef.getText()), false);
            wrapper.setFontFamily(FormUtil.getDefaultFontFamily());
            wrapper.setFontSize(FormUtil.getDefaultFontSize());
            wrapper.setBinding(optionDef.getVariableName());
            wrapper.setParentBinding(questionDef.getBinding());
            wrapper.setText(optionDef.getText());
            wrapper.setTitle(optionDef.getText());

            if (vertically)
                y += 40;
            else
                x += (optionDef.getText().length() * 14);
        }

        return null;
    }

    /**
     * Changes a widget to a different type. For instance single select question types
     * can have their drop down widget changed to radio buttons.
     * 
     * @param vertically set to true to have the widgets vertically, else false to have them horizontally.
     */
    protected void changeWidget(boolean vertically) {
        if (selectedDragController.getSelectedWidgetCount() != 1)
            return;

        DesignWidgetWrapper widget = (DesignWidgetWrapper) selectedDragController.getSelectedWidgetAt(0);
        if (!(widget.getWrappedWidget() instanceof ListBox))
            return;

        QuestionDef questionDef = widget.getQuestionDef();
        if (questionDef == null)
            return;

        x = widget.getLeftInt() + selectedPanel.getAbsoluteLeft();
        y = widget.getTopInt() + selectedPanel.getAbsoluteTop();

        if (widget.getLayoutNode() != null)
            widget.getLayoutNode().getParentNode().removeChild(widget.getLayoutNode());
        selectedPanel.remove(widget);
        selectedDragController.clearSelection();

        if (widget.getWrappedWidget() instanceof ListBox)
            addNewRadioButtonSet(questionDef, vertically);

        //increase height if the last widget is beyond our current y coordinate.
        int height = FormUtil.convertDimensionToInt(getHeight());
        if ((height + getAbsoluteTop()) < y)
            setHeight(y + OpenXdataConstants.UNITS);
    }

    /**
     * Adds a new group box widget.
     * 
     * @param select set to true to automatically selecte the newly added widget.
     * @return the new widget.
     */
    protected DesignWidgetWrapper addNewGroupBox(boolean select) {
        DesignGroupWidget group = new DesignGroupWidget(images, this);
        group.addStyleName("getting-started-label2");
        DOM.setStyleAttribute(group.getElement(), "height", "200" + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(group.getElement(), "width", "500" + OpenXdataConstants.UNITS);
        group.setWidgetSelectionListener(currentWidgetSelectionListener);

        DesignWidgetWrapper widget = addNewWidget(group, select);

        //Header label stuff
        widget.setBorderStyle("dashed");
        AbsolutePanel panel = selectedPanel;
        FormDesignerDragController dragController = selectedDragController;

        selectedDragController = widget.getDragController();
        selectedPanel = widget.getPanel();

        DesignWidgetWrapper headerLabel = addNewLabel("Header Label", false);
        headerLabel.setBackgroundColor(StyleUtil.COLOR_GROUP_HEADER);
        DOM.setStyleAttribute(headerLabel.getElement(), "width", "100%");
        headerLabel.setTextAlign("center");
        selectedDragController.makeNotDraggable(headerLabel);
        headerLabel.setWidth("100%");
        headerLabel.setHeightInt(20);
        headerLabel.setForeColor("white");
        headerLabel.setFontWeight("bold");

        selectedPanel = panel;
        selectedDragController = dragController;

        selectedDragController.makeDraggable(widget, headerLabel);
        group.setHeaderLabel(headerLabel);
        //End header label stuff

        //Without this, widgets in this box cant use Ctrl + A in edit mode and also
        //edited text is not automatically selected.
        widget.removeStyleName("dragdrop-handle");

        return widget;
    }

    /**
     * Adds a new repeat section widget.
     * 
     * @param select set to true to automatically select the newly added widget.
     * @return the new widget.
     */
    protected DesignWidgetWrapper addNewRepeatSection(boolean select) {
        DesignGroupWidget repeat = new DesignGroupWidget(images, this);
        repeat.addStyleName("getting-started-label2");
        DOM.setStyleAttribute(repeat.getElement(), "height", "100" + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(repeat.getElement(), "width", "500" + OpenXdataConstants.UNITS);
        repeat.setWidgetSelectionListener(currentWidgetSelectionListener);

        DesignWidgetWrapper widget = addNewWidget(repeat, select);
        widget.setRepeated(true);

        FormDesignerDragController selDragController = selectedDragController;
        AbsolutePanel absPanel = selectedPanel;
        PopupPanel wdpopup = widgetPopup;
        WidgetSelectionListener wgSelectionListener = currentWidgetSelectionListener;

        selectedDragController = widget.getDragController();
        selectedPanel = widget.getPanel();
        widgetPopup = repeat.getWidgetPopup();
        currentWidgetSelectionListener = repeat;

        int oldY = y;
        y = 55;
        x = 10;
        if (selectedPanel.getAbsoluteLeft() > 0)
            x += selectedPanel.getAbsoluteLeft();
        if (selectedPanel.getAbsoluteTop() > 0)
            y += selectedPanel.getAbsoluteTop();

        addNewButton(i18n.addNew(), "addnew", false);

        selectedDragController.clearSelection();

        selectedDragController = selDragController;
        selectedPanel = absPanel;
        widgetPopup = wdpopup;
        currentWidgetSelectionListener = wgSelectionListener;

        y = oldY;
        widget.removeStyleName("dragdrop-handle");

        return widget;
    }

    /**
     * Adds a new picture section widget.
     * 
     * @param parentBinding the binding of the question for this widget.
     * @param text the display text for the widget.
     * @param select set to true if you want to automatically select the new widget.
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewPictureSection(String parentBinding, String text, boolean select) {
        DesignGroupWidget repeat = new DesignGroupWidget(images, this);
        repeat.addStyleName("getting-started-label2");
        DOM.setStyleAttribute(repeat.getElement(), "height", "245" + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(repeat.getElement(), "width", "200" + OpenXdataConstants.UNITS);
        repeat.setWidgetSelectionListener(currentWidgetSelectionListener);

        DesignWidgetWrapper widget = addNewWidget(repeat, select);
        widget.setRepeated(false);

        FormDesignerDragController selDragController = selectedDragController;
        AbsolutePanel absPanel = selectedPanel;
        PopupPanel wdpopup = widgetPopup;
        WidgetSelectionListener wgSelectionListener = currentWidgetSelectionListener;

        selectedDragController = widget.getDragController();
        selectedPanel = widget.getPanel();
        widgetPopup = repeat.getWidgetPopup();
        currentWidgetSelectionListener = repeat;

        int oldY = y;

        y = 35;
        x = 10;
        if (selectedPanel.getAbsoluteLeft() > 0)
            x += selectedPanel.getAbsoluteLeft();
        if (selectedPanel.getAbsoluteTop() > 0)
            y += selectedPanel.getAbsoluteTop();
        addNewPicture(false).setBinding(parentBinding);

        y = 55 + 120 + 25;
        x = 10;
        if (selectedPanel.getAbsoluteLeft() > 0)
            x += selectedPanel.getAbsoluteLeft();
        if (selectedPanel.getAbsoluteTop() > 0)
            y += selectedPanel.getAbsoluteTop();

        addNewButton(i18n.browse(), "browse", false).setParentBinding(parentBinding);
        x = 120;
        if (selectedPanel.getAbsoluteLeft() > 0)
            x += selectedPanel.getAbsoluteLeft();
        addNewButton(i18n.clear(), "clear", false).setParentBinding(parentBinding);

        selectedDragController.clearSelection();

        selectedDragController = selDragController;
        selectedPanel = absPanel;
        widgetPopup = wdpopup;
        currentWidgetSelectionListener = wgSelectionListener;

        y = oldY;

        //Header label stuff
        widget.setBorderStyle("dashed");
        AbsolutePanel panel = selectedPanel;
        FormDesignerDragController dragController = selectedDragController;

        selectedDragController = widget.getDragController();
        selectedPanel = widget.getPanel();

        y = selectedPanel.getAbsoluteTop();
        x = selectedPanel.getAbsoluteLeft();
        DesignWidgetWrapper headerLabel = addNewLabel(text != null ? text : "Picture", false);
        headerLabel.setBackgroundColor(StyleUtil.COLOR_GROUP_HEADER);
        DOM.setStyleAttribute(headerLabel.getElement(), "width", "100%");
        headerLabel.setTextAlign("center");
        selectedDragController.makeNotDraggable(headerLabel);
        headerLabel.setWidth("100%");
        headerLabel.setHeightInt(20);
        headerLabel.setForeColor("white");
        headerLabel.setFontWeight("bold");

        selectedPanel = panel;
        selectedDragController = dragController;

        selectedDragController.makeDraggable(widget, headerLabel);
        repeat.setHeaderLabel(headerLabel);
        //End header label stuff

        y = oldY;

        //Without this, widgets in this box cant use Ctrl + A in edit mode and also
        //edited text is not automatically selected.
        widget.removeStyleName("dragdrop-handle");

        return widget;
    }

    /**
     * Adds a new Audio or Video section widget.
     * 
     * @param parentBinding the binding of the question for this widget.
     * @param text the widget text.
     * @param select set to true if you want the widget to be automatically selected.
     * @return the newly added widget.
     */
    protected DesignWidgetWrapper addNewVideoAudioSection(String parentBinding, String text, boolean select) {
        DesignGroupWidget repeat = new DesignGroupWidget(images, this);
        repeat.addStyleName("getting-started-label2");
        DOM.setStyleAttribute(repeat.getElement(), "height", "125" + OpenXdataConstants.UNITS);
        DOM.setStyleAttribute(repeat.getElement(), "width", "200" + OpenXdataConstants.UNITS);
        repeat.setWidgetSelectionListener(currentWidgetSelectionListener);

        DesignWidgetWrapper widget = addNewWidget(repeat, select);
        widget.setRepeated(false);

        FormDesignerDragController selDragController = selectedDragController;
        AbsolutePanel absPanel = selectedPanel;
        PopupPanel wdpopup = widgetPopup;
        WidgetSelectionListener wgSelectionListener = currentWidgetSelectionListener;

        selectedDragController = widget.getDragController();
        selectedPanel = widget.getPanel();
        widgetPopup = repeat.getWidgetPopup();
        currentWidgetSelectionListener = repeat;

        int oldY = y;

        y = 20 + 25;
        x = 45;
        if (selectedPanel.getAbsoluteLeft() > 0)
            x += selectedPanel.getAbsoluteLeft();
        if (selectedPanel.getAbsoluteTop() > 0)
            y += selectedPanel.getAbsoluteTop();
        addNewVideoAudio(null, false).setBinding(parentBinding);

        y = 60 + 25;
        x = 10;
        if (selectedPanel.getAbsoluteLeft() > 0)
            x += selectedPanel.getAbsoluteLeft();
        if (selectedPanel.getAbsoluteTop() > 0)
            y += selectedPanel.getAbsoluteTop();

        addNewButton(i18n.browse(), "browse", false).setParentBinding(parentBinding);
        x = 120;
        if (selectedPanel.getAbsoluteLeft() > 0)
            x += selectedPanel.getAbsoluteLeft();
        addNewButton(i18n.clear(), "clear", false).setParentBinding(parentBinding);

        selectedDragController.clearSelection();

        selectedDragController = selDragController;
        selectedPanel = absPanel;
        widgetPopup = wdpopup;
        currentWidgetSelectionListener = wgSelectionListener;

        y = oldY;

        //Header label stuff
        widget.setBorderStyle("dashed");
        AbsolutePanel panel = selectedPanel;
        FormDesignerDragController dragController = selectedDragController;

        selectedDragController = widget.getDragController();
        selectedPanel = widget.getPanel();

        y = selectedPanel.getAbsoluteTop();
        x = selectedPanel.getAbsoluteLeft();
        DesignWidgetWrapper headerLabel = addNewLabel(text != null ? text : i18n.recording(), false);
        headerLabel.setBackgroundColor(StyleUtil.COLOR_GROUP_HEADER);
        DOM.setStyleAttribute(headerLabel.getElement(), "width", "100%");
        headerLabel.setTextAlign("center");
        selectedDragController.makeNotDraggable(headerLabel);
        headerLabel.setWidth("100%");
        headerLabel.setHeightInt(20);
        headerLabel.setForeColor("white");
        headerLabel.setFontWeight("bold");

        selectedPanel = panel;
        selectedDragController = dragController;

        selectedDragController.makeDraggable(widget, headerLabel);
        repeat.setHeaderLabel(headerLabel);
        //End header label stuff

        y = oldY;

        //Without this, widgets in this box cant use Ctrl + A in edit mode and also
        //edited text is not automatically selected.
        widget.removeStyleName("dragdrop-handle");

        return widget;
    }

    protected void lockWidgets() {
        Context.setLockWidgets(!Context.getLockWidgets());
    }

    public boolean onWidgetPropertyChanged(byte property, String value) {
        if (WidgetPropertySetter.setProperty(property, selectedDragController, value))
            return true;

        int count = selectedPanel.getWidgetCount();
        for (int index = 0; index < count; index++) {
            Widget widget = selectedPanel.getWidget(index);
            if (!(widget instanceof DesignWidgetWrapper))
                continue;

            DesignWidgetWrapper wrapper = (DesignWidgetWrapper) widget;
            if (!(wrapper.getWrappedWidget() instanceof DesignGroupWidget))
                continue;

            if (((DesignGroupWidget) wrapper.getWrappedWidget()).onWidgetPropertyChanged(property, value))
                return true;
        }

        return false;
    }
}