org.eclipse.swt.examples.layoutexample.FormLayoutTab.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.swt.examples.layoutexample.FormLayoutTab.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.examples.layoutexample;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;

class FormLayoutTab extends Tab {
    /* Controls for setting layout parameters */
    Spinner marginWidth, marginHeight, marginLeft, marginRight, marginTop, marginBottom, spacing;
    /* The example layout instance */
    FormLayout formLayout;
    /* TableEditors and related controls*/
    TableEditor nameEditor, comboEditor, widthEditor, heightEditor;
    TableEditor leftEditor, rightEditor, topEditor, bottomEditor;
    CCombo combo;
    Text nameText, widthText, heightText;
    Button leftAttach, rightAttach, topAttach, bottomAttach;

    /* Constants */
    final int NAME_COL = 0;
    final int COMBO_COL = 1;
    final int WIDTH_COL = 2;
    final int HEIGHT_COL = 3;
    final int LEFT_COL = 4;
    final int RIGHT_COL = 5;
    final int TOP_COL = 6;
    final int BOTTOM_COL = 7;

    final int MODIFY_COLS = 4; // The number of columns with combo or text editors
    final int TOTAL_COLS = 8;

    /**
     * Creates the Tab within a given instance of LayoutExample.
     */
    FormLayoutTab(LayoutExample instance) {
        super(instance);
    }

    /**
     * Returns the constant for the alignment for an
     * attachment given a string.
     */
    int alignmentConstant(String align) {
        if (align.equals("LEFT"))
            return SWT.LEFT;
        if (align.equals("RIGHT"))
            return SWT.RIGHT;
        if (align.equals("TOP"))
            return SWT.TOP;
        if (align.equals("BOTTOM"))
            return SWT.BOTTOM;
        if (align.equals("CENTER"))
            return SWT.CENTER;
        return SWT.DEFAULT;
    }

    /**
     * Returns a string representing the alignment for an
     * attachment given a constant.
     */
    String alignmentString(int align) {
        switch (align) {
        case SWT.LEFT:
            return "LEFT";
        case SWT.RIGHT:
            return "RIGHT";
        case SWT.TOP:
            return "TOP";
        case SWT.BOTTOM:
            return "BOTTOM";
        case SWT.CENTER:
            return "CENTER";
        }
        return "DEFAULT";
    }

    /**
     * Update the attachment field in case the type of control
     * has changed.
     */
    String checkAttachment(String oldAttach, FormAttachment newAttach) {
        String controlClass = newAttach.control.getClass().toString();
        String controlType = controlClass.substring(controlClass.lastIndexOf('.') + 1);
        int i = 0;
        while (i < oldAttach.length() && !Character.isDigit(oldAttach.charAt(i))) {
            i++;
        }
        String index = oldAttach.substring(i, oldAttach.indexOf(','));
        return controlType + index + "," + newAttach.offset + ":" + alignmentString(newAttach.alignment);
    }

    /**
     * Creates the widgets in the "child" group.
     */
    @Override
    void createChildWidgets() {
        /* Add common controls */
        super.createChildWidgets();

        /* Resize the columns */
        table.getColumn(LEFT_COL).setWidth(90);
        table.getColumn(RIGHT_COL).setWidth(90);
        table.getColumn(TOP_COL).setWidth(90);
        table.getColumn(BOTTOM_COL).setWidth(90);

        /* Add TableEditors */
        nameEditor = new TableEditor(table);
        comboEditor = new TableEditor(table);
        widthEditor = new TableEditor(table);
        heightEditor = new TableEditor(table);
        leftEditor = new TableEditor(table);
        rightEditor = new TableEditor(table);
        topEditor = new TableEditor(table);
        bottomEditor = new TableEditor(table);
        table.addMouseListener(MouseListener.mouseDownAdapter(e -> {
            resetEditors();
            index = table.getSelectionIndex();
            Point pt = new Point(e.x, e.y);
            newItem = table.getItem(pt);
            if (newItem == null)
                return;
            TableItem oldItem = comboEditor.getItem();
            if (newItem == oldItem || newItem != lastSelected) {
                lastSelected = newItem;
                return;
            }
            table.showSelection();

            combo = new CCombo(table, SWT.READ_ONLY);
            createComboEditor(combo, comboEditor);

            nameText = new Text(table, SWT.SINGLE);
            nameText.setText(data.get(index)[NAME_COL]);
            createTextEditor(nameText, nameEditor, NAME_COL);

            widthText = new Text(table, SWT.SINGLE);
            widthText.setText(data.get(index)[WIDTH_COL]);
            createTextEditor(widthText, widthEditor, WIDTH_COL);

            heightText = new Text(table, SWT.SINGLE);
            heightText.setText(data.get(index)[HEIGHT_COL]);
            createTextEditor(heightText, heightEditor, HEIGHT_COL);

            leftAttach = new Button(table, SWT.PUSH);
            leftAttach.setText(LayoutExample.getResourceString("Attach_Edit"));
            leftEditor.horizontalAlignment = SWT.LEFT;
            leftEditor.grabHorizontal = true;
            leftEditor.minimumWidth = leftAttach.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
            leftEditor.setEditor(leftAttach, newItem, LEFT_COL);
            leftAttach.addSelectionListener(SelectionListener.widgetSelectedAdapter(e1 -> {
                Shell shell = tabFolderPage.getShell();
                AttachDialog dialog = new AttachDialog(shell);
                dialog.setText(LayoutExample.getResourceString("Left_Attachment"));
                dialog.setColumn(LEFT_COL);
                String attach = dialog.open();
                newItem.setText(LEFT_COL, attach);
                resetEditors();
            }));

            rightAttach = new Button(table, SWT.PUSH);
            rightAttach.setText(LayoutExample.getResourceString("Attach_Edit"));
            rightEditor.horizontalAlignment = SWT.LEFT;
            rightEditor.grabHorizontal = true;
            rightEditor.minimumWidth = rightAttach.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
            rightEditor.setEditor(rightAttach, newItem, RIGHT_COL);
            rightAttach.addSelectionListener(SelectionListener.widgetSelectedAdapter(e1 -> {
                Shell shell = tabFolderPage.getShell();
                AttachDialog dialog = new AttachDialog(shell);
                dialog.setText(LayoutExample.getResourceString("Right_Attachment"));
                dialog.setColumn(RIGHT_COL);
                String attach = dialog.open();
                newItem.setText(RIGHT_COL, attach);
                if (newItem.getText(LEFT_COL).endsWith(")"))
                    newItem.setText(LEFT_COL, "");
                resetEditors();
            }));

            topAttach = new Button(table, SWT.PUSH);
            topAttach.setText(LayoutExample.getResourceString("Attach_Edit"));
            topEditor.horizontalAlignment = SWT.LEFT;
            topEditor.grabHorizontal = true;
            topEditor.minimumWidth = topAttach.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
            topEditor.setEditor(topAttach, newItem, TOP_COL);
            topAttach.addSelectionListener(SelectionListener.widgetSelectedAdapter(e1 -> {
                Shell shell = tabFolderPage.getShell();
                AttachDialog dialog = new AttachDialog(shell);
                dialog.setText(LayoutExample.getResourceString("Top_Attachment"));
                dialog.setColumn(TOP_COL);
                String attach = dialog.open();
                newItem.setText(TOP_COL, attach);
                resetEditors();
            }));
            bottomAttach = new Button(table, SWT.PUSH);
            bottomAttach.setText(LayoutExample.getResourceString("Attach_Edit"));
            bottomEditor.horizontalAlignment = SWT.LEFT;
            bottomEditor.grabHorizontal = true;
            bottomEditor.minimumWidth = bottomAttach.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
            bottomEditor.setEditor(bottomAttach, newItem, BOTTOM_COL);
            bottomAttach.addSelectionListener(SelectionListener.widgetSelectedAdapter(e1 -> {
                Shell shell = tabFolderPage.getShell();
                AttachDialog dialog = new AttachDialog(shell);
                dialog.setText(LayoutExample.getResourceString("Bottom_Attachment"));
                dialog.setColumn(BOTTOM_COL);
                String attach = dialog.open();
                newItem.setText(BOTTOM_COL, attach);
                if (newItem.getText(TOP_COL).endsWith(")"))
                    newItem.setText(TOP_COL, "");
                resetEditors();
            }));

            for (int i = 0; i < table.getColumnCount(); i++) {
                Rectangle rect = newItem.getBounds(i);
                if (rect.contains(pt)) {
                    switch (i) {
                    case 0:
                        resetEditors();
                        break;
                    case COMBO_COL:
                        combo.setFocus();
                        break;
                    case WIDTH_COL:
                        widthText.setFocus();
                        break;
                    case HEIGHT_COL:
                        heightText.setFocus();
                        break;
                    default:
                        break;
                    }
                }
            }
        }));
    }

    /**
     * Creates the control widgets.
     */
    @Override
    void createControlWidgets() {
        /* Controls the margins and spacing of the FormLayout */
        Group marginGroup = new Group(controlGroup, SWT.NONE);
        marginGroup.setText(LayoutExample.getResourceString("Margins_Spacing"));
        marginGroup.setLayout(new GridLayout(2, false));
        marginGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
        new Label(marginGroup, SWT.NONE).setText("marginWidth");
        marginWidth = new Spinner(marginGroup, SWT.BORDER);
        marginWidth.setSelection(0);
        marginWidth.addSelectionListener(selectionListener);
        new Label(marginGroup, SWT.NONE).setText("marginHeight");
        marginHeight = new Spinner(marginGroup, SWT.BORDER);
        marginHeight.setSelection(0);
        marginHeight.addSelectionListener(selectionListener);
        new Label(marginGroup, SWT.NONE).setText("marginLeft");
        marginLeft = new Spinner(marginGroup, SWT.BORDER);
        marginLeft.setSelection(0);
        marginLeft.addSelectionListener(selectionListener);
        new Label(marginGroup, SWT.NONE).setText("marginRight");
        marginRight = new Spinner(marginGroup, SWT.BORDER);
        marginRight.setSelection(0);
        marginRight.addSelectionListener(selectionListener);
        new Label(marginGroup, SWT.NONE).setText("marginTop");
        marginTop = new Spinner(marginGroup, SWT.BORDER);
        marginTop.setSelection(0);
        marginTop.addSelectionListener(selectionListener);
        new Label(marginGroup, SWT.NONE).setText("marginBottom");
        marginBottom = new Spinner(marginGroup, SWT.BORDER);
        marginBottom.setSelection(0);
        marginBottom.addSelectionListener(selectionListener);
        new Label(marginGroup, SWT.NONE).setText("spacing");
        spacing = new Spinner(marginGroup, SWT.BORDER);
        spacing.setSelection(0);
        spacing.addSelectionListener(selectionListener);

        /* Add common controls */
        super.createControlWidgets();
    }

    /**
     * Creates the example layout.
     */
    @Override
    void createLayout() {
        formLayout = new FormLayout();
        layoutComposite.setLayout(formLayout);
    }

    /**
     * Disposes the editors without placing their contents
     * into the table.
     */
    @Override
    void disposeEditors() {
        comboEditor.setEditor(null, null, -1);
        combo.dispose();
        nameText.dispose();
        widthText.dispose();
        heightText.dispose();
        leftAttach.dispose();
        rightAttach.dispose();
        topAttach.dispose();
        bottomAttach.dispose();
    }

    /**
     * Generates code for the example layout.
     */
    @Override
    StringBuilder generateLayoutCode() {
        StringBuilder code = new StringBuilder();
        code.append("\t\tFormLayout formLayout = new FormLayout ();\n");
        if (formLayout.marginWidth != 0) {
            code.append("\t\tformLayout.marginWidth = " + formLayout.marginWidth + ";\n");
        }
        if (formLayout.marginHeight != 0) {
            code.append("\t\tformLayout.marginHeight = " + formLayout.marginHeight + ";\n");
        }
        if (formLayout.marginLeft != 0) {
            code.append("\t\tformLayout.marginLeft = " + formLayout.marginLeft + ";\n");
        }
        if (formLayout.marginRight != 0) {
            code.append("\t\tformLayout.marginRight = " + formLayout.marginRight + ";\n");
        }
        if (formLayout.marginTop != 0) {
            code.append("\t\tformLayout.marginTop = " + formLayout.marginTop + ";\n");
        }
        if (formLayout.marginBottom != 0) {
            code.append("\t\tformLayout.marginBottom = " + formLayout.marginBottom + ";\n");
        }
        if (formLayout.spacing != 0) {
            code.append("\t\tformLayout.spacing = " + formLayout.spacing + ";\n");
        }
        code.append("\t\tshell.setLayout (formLayout);\n");

        boolean first = true;
        for (int i = 0; i < children.length; i++) {
            Control control = children[i];
            code.append(getChildCode(control, i));
            FormData data = (FormData) control.getLayoutData();
            if (data != null) {
                code.append("\t\t");
                if (first) {
                    code.append("FormData ");
                    first = false;
                }
                code.append("data = new FormData ();\n");
                if (data.width != SWT.DEFAULT) {
                    code.append("\t\tdata.width = " + data.width + ";\n");
                }
                if (data.height != SWT.DEFAULT) {
                    code.append("\t\tdata.height = " + data.height + ";\n");
                }
                if (data.left != null) {
                    if (data.left.control != null) {
                        TableItem item = table.getItem(i);
                        String controlString = item.getText(LEFT_COL);
                        int index = Integer.valueOf(
                                controlString.substring(controlString.indexOf(',') - 1, controlString.indexOf(',')))
                                .intValue();
                        code.append("\t\tdata.left = new FormAttachment (" + names[index] + ", " + data.left.offset
                                + ", SWT." + alignmentString(data.left.alignment) + ");\n");
                    } else {
                        if (data.right != null || (data.left.numerator != 0 || data.left.offset != 0)) {
                            code.append("\t\tdata.left = new FormAttachment (" + data.left.numerator + ", "
                                    + data.left.offset + ");\n");
                        }
                    }
                }
                if (data.right != null) {
                    if (data.right.control != null) {
                        TableItem item = table.getItem(i);
                        String controlString = item.getText(RIGHT_COL);
                        int index = Integer.valueOf(controlString.substring(controlString.indexOf(',') - 1,
                                controlString.indexOf(',')));
                        code.append("\t\tdata.right = new FormAttachment (" + names[index] + ", "
                                + data.right.offset + ", SWT." + alignmentString(data.right.alignment) + ");\n");
                    } else {
                        code.append("\t\tdata.right = new FormAttachment (" + data.right.numerator + ", "
                                + data.right.offset + ");\n");
                    }
                }
                if (data.top != null) {
                    if (data.top.control != null) {
                        TableItem item = table.getItem(i);
                        String controlString = item.getText(TOP_COL);
                        int index = Integer.valueOf(controlString.substring(controlString.indexOf(',') - 1,
                                controlString.indexOf(',')));
                        code.append("\t\tdata.top = new FormAttachment (" + names[index] + ", " + data.top.offset
                                + ", SWT." + alignmentString(data.top.alignment) + ");\n");
                    } else {
                        if (data.bottom != null || (data.top.numerator != 0 || data.top.offset != 0)) {
                            code.append("\t\tdata.top = new FormAttachment (" + data.top.numerator + ", "
                                    + data.top.offset + ");\n");
                        }
                    }
                }
                if (data.bottom != null) {
                    if (data.bottom.control != null) {
                        TableItem item = table.getItem(i);
                        String controlString = item.getText(BOTTOM_COL);
                        int index = Integer.valueOf(controlString.substring(controlString.indexOf(',') - 1,
                                controlString.indexOf(',')));
                        code.append("\t\tdata.bottom = new FormAttachment (" + names[index] + ", "
                                + data.bottom.offset + ", SWT." + alignmentString(data.bottom.alignment) + ");\n");
                    } else {
                        code.append("\t\tdata.bottom = new FormAttachment (" + data.bottom.numerator + ", "
                                + data.bottom.offset + ");\n");
                    }
                }
                code.append("\t\t" + names[i] + ".setLayoutData (data);\n");
            }
        }
        return code;
    }

    /**
     * Returns the string to insert when a new child control is added to the table.
     */
    @Override
    String[] getInsertString(String name, String controlType) {
        return new String[] { name, controlType, "-1", "-1",
                "0,0 (" + LayoutExample.getResourceString("Default") + ")", "",
                "0,0 (" + LayoutExample.getResourceString("Default") + ")", "" };
    }

    /**
     * Returns the layout data field names.
     */
    @Override
    String[] getLayoutDataFieldNames() {
        return new String[] { "Control Name", "Control Type", "width", "height", "left", "right", "top", "bottom" };
    }

    /**
     * Gets the text for the tab folder item.
     */
    @Override
    String getTabText() {
        return "FormLayout";
    }

    /**
     * Takes information from TableEditors and stores it.
     */
    @Override
    void resetEditors(boolean tab) {
        TableItem oldItem = comboEditor.getItem();
        if (oldItem != null) {
            int row = table.indexOf(oldItem);
            try {
                new String(nameText.getText());
            } catch (NumberFormatException e) {
                nameText.setText(oldItem.getText(NAME_COL));
            }
            try {
                Integer.parseInt(widthText.getText());
            } catch (NumberFormatException e) {
                widthText.setText(oldItem.getText(WIDTH_COL));
            }
            try {
                Integer.parseInt(heightText.getText());
            } catch (NumberFormatException e) {
                heightText.setText(oldItem.getText(HEIGHT_COL));
            }
            String[] insert = new String[] { nameText.getText(), combo.getText(), widthText.getText(),
                    heightText.getText() };
            data.set(row, insert);
            for (int i = 0; i < MODIFY_COLS; i++) {
                oldItem.setText(i, data.get(row)[i]);
            }
            if (!tab)
                disposeEditors();
        }
        setLayoutState();
        refreshLayoutComposite();
        setLayoutData();
        layoutComposite.layout(true);
        layoutGroup.layout(true);
    }

    /**
     * Return the initial weight of the layout and control groups within the SashForm.
     * @return the desired sash weights for the tab page
     */
    @Override
    int[] sashWeights() {
        return new int[] { 40, 60 };
    }

    /**
     * Sets an attachment to the edge of a widget using the
     * information in the table.
     */
    FormAttachment setAttachment(String attachment) {
        String control, align;
        int position, offset;
        int comma = attachment.indexOf(',');
        char first = attachment.charAt(0);
        if (Character.isLetter(first)) {
            /* Case where there is a control */
            control = attachment.substring(0, comma);
            int i = 0;
            while (i < control.length() && !Character.isDigit(control.charAt(i))) {
                i++;
            }
            String end = control.substring(i);
            int index = Integer.valueOf(end).intValue();
            Control attachControl = children[index];
            int colon = attachment.indexOf(':');
            try {
                offset = Integer.valueOf(attachment.substring(comma + 1, colon)).intValue();
            } catch (NumberFormatException e) {
                offset = 0;
            }
            align = attachment.substring(colon + 1);
            return new FormAttachment(attachControl, offset, alignmentConstant(align));
        } else {
            /* Case where there is a position */
            try {
                position = Integer.valueOf(attachment.substring(0, comma));
            } catch (NumberFormatException e) {
                position = 0;
            }
            try {
                offset = Integer.valueOf(attachment.substring(comma + 1));
            } catch (NumberFormatException e) {
                offset = 0;
            }
            return new FormAttachment(position, offset);
        }
    }

    /**
     * Sets the layout data for the children of the layout.
     */
    @Override
    void setLayoutData() {
        Control[] children = layoutComposite.getChildren();
        TableItem[] items = table.getItems();
        FormData data;
        int width, height;
        String left, right, top, bottom;
        for (int i = 0; i < children.length; i++) {
            width = Integer.valueOf(items[i].getText(WIDTH_COL)).intValue();
            height = Integer.valueOf(items[i].getText(HEIGHT_COL)).intValue();
            data = new FormData();
            if (width > 0)
                data.width = width;
            if (height > 0)
                data.height = height;

            left = items[i].getText(LEFT_COL);
            if (left.length() > 0) {
                data.left = setAttachment(left);
                if (data.left.control != null) {
                    String attachment = checkAttachment(left, data.left);
                    items[i].setText(LEFT_COL, attachment);
                }
            }
            right = items[i].getText(RIGHT_COL);
            if (right.length() > 0) {
                data.right = setAttachment(right);
                if (data.right.control != null) {
                    String attachment = checkAttachment(right, data.right);
                    items[i].setText(RIGHT_COL, attachment);
                }
            }
            top = items[i].getText(TOP_COL);
            if (top.length() > 0) {
                data.top = setAttachment(top);
                if (data.top.control != null) {
                    String attachment = checkAttachment(top, data.top);
                    items[i].setText(TOP_COL, attachment);
                }
            }
            bottom = items[i].getText(BOTTOM_COL);
            if (bottom.length() > 0) {
                data.bottom = setAttachment(bottom);
                if (data.bottom.control != null) {
                    String attachment = checkAttachment(bottom, data.bottom);
                    items[i].setText(BOTTOM_COL, attachment);
                }
            }
            children[i].setLayoutData(data);
        }
    }

    /**
     * Sets the state of the layout.
     */
    @Override
    void setLayoutState() {
        /* Set the margins and spacing */
        formLayout.marginWidth = marginWidth.getSelection();
        formLayout.marginHeight = marginHeight.getSelection();
        formLayout.marginLeft = marginLeft.getSelection();
        formLayout.marginRight = marginRight.getSelection();
        formLayout.marginTop = marginTop.getSelection();
        formLayout.marginBottom = marginBottom.getSelection();
        formLayout.spacing = spacing.getSelection();
    }

    /**
     * <code>AttachDialog</code> is the class that creates a
     * dialog specific for this example. It creates a dialog
     * with controls to set the values in a FormAttachment.
     */
    public class AttachDialog extends Dialog {
        String result = "";
        String controlInput, positionInput, alignmentInput, offsetInput;
        int col = 0;

        public AttachDialog(Shell parent, int style) {
            super(parent, style);
        }

        public AttachDialog(Shell parent) {
            this(parent, 0);
        }

        public void setColumn(int col) {
            this.col = col;
        }

        public String open() {
            Shell parent = getParent();
            final Shell shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
            shell.setText(getText());
            shell.setLayout(new GridLayout(3, true));

            /* Find out what was previously set as an attachment */
            TableItem newItem = leftEditor.getItem();
            result = newItem.getText(col);
            String oldAttach = result;
            String oldPos = "0", oldControl = "", oldAlign = "DEFAULT", oldOffset = "0";
            boolean isControl = false;
            if (oldAttach.length() != 0) {
                char first = oldAttach.charAt(0);
                if (Character.isLetter(first)) {
                    /* We have a control */
                    isControl = true;
                    oldControl = oldAttach.substring(0, oldAttach.indexOf(','));
                    oldAlign = oldAttach.substring(oldAttach.indexOf(':') + 1);
                    oldOffset = oldAttach.substring(oldAttach.indexOf(',') + 1, oldAttach.indexOf(':'));
                } else {
                    /* We have a position */
                    oldPos = oldAttach.substring(0, oldAttach.indexOf(','));
                    oldOffset = oldAttach.substring(oldAttach.indexOf(',') + 1);
                    if (oldOffset.endsWith(")")) { // i.e. (Default)
                        oldOffset = oldOffset.substring(0, oldOffset.indexOf(' '));
                    }
                }
            }

            /* Add position field */
            final Button posButton = new Button(shell, SWT.RADIO);
            posButton.setText(LayoutExample.getResourceString("Position"));
            posButton.setSelection(!isControl);
            final Combo position = new Combo(shell, SWT.NONE);
            position.setItems("0", "25", "33", "50", "67", "75", "100");
            position.setVisibleItemCount(7);
            position.setText(oldPos);
            position.setEnabled(!isControl);
            position.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));

            /* Add control field */
            final Button contButton = new Button(shell, SWT.RADIO);
            contButton.setText(LayoutExample.getResourceString("Control"));
            contButton.setSelection(isControl);
            final Combo control = new Combo(shell, SWT.READ_ONLY);
            TableItem[] items = table.getItems();
            TableItem currentItem = leftEditor.getItem();
            for (int i = 0; i < table.getItemCount(); i++) {
                if (items[i].getText(0).length() > 0) {
                    if (items[i] != currentItem) {
                        control.add(items[i].getText(COMBO_COL) + i);
                    }
                }
            }
            if (oldControl.length() != 0)
                control.setText(oldControl);
            else
                control.select(0);
            control.setEnabled(isControl);
            control.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));

            /* Add alignment field */
            new Label(shell, SWT.NONE).setText(LayoutExample.getResourceString("Alignment"));
            final Combo alignment = new Combo(shell, SWT.NONE);
            String[] alignmentValues;
            if (col == LEFT_COL || col == RIGHT_COL) {
                alignmentValues = new String[] { "SWT.LEFT", "SWT.RIGHT", "SWT.CENTER", "SWT.DEFAULT" };
            } else {
                // col == TOP_COL || col == BOTTOM_COL
                alignmentValues = new String[] { "SWT.TOP", "SWT.BOTTOM", "SWT.CENTER", "SWT.DEFAULT" };
            }
            alignment.setItems(alignmentValues);
            alignment.setText("SWT." + oldAlign);
            alignment.setEnabled(isControl);
            alignment.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));

            /* Add offset field */
            new Label(shell, SWT.NONE).setText(LayoutExample.getResourceString("Offset"));
            final Text offset = new Text(shell, SWT.SINGLE | SWT.BORDER);
            offset.setText(oldOffset);
            offset.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));

            /* Add listeners for choosing between position and control */
            posButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
                position.setEnabled(true);
                control.setEnabled(false);
                alignment.setEnabled(false);
            }));
            contButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
                position.setEnabled(false);
                control.setEnabled(true);
                alignment.setEnabled(true);
            }));

            Button clear = new Button(shell, SWT.PUSH);
            clear.setText(LayoutExample.getResourceString("Clear"));
            clear.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false));
            clear.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
                result = "";
                shell.close();
            }));
            /* OK button sets data into table */
            Button ok = new Button(shell, SWT.PUSH);
            ok.setText(LayoutExample.getResourceString("OK"));
            ok.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
            ok.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
                controlInput = control.getText();
                alignmentInput = alignment.getText().substring(4);
                positionInput = position.getText();
                if (positionInput.length() == 0)
                    positionInput = "0";
                try {
                    Integer.parseInt(positionInput);
                } catch (NumberFormatException except) {
                    positionInput = "0";
                }
                offsetInput = offset.getText();
                if (offsetInput.length() == 0)
                    offsetInput = "0";
                try {
                    Integer.parseInt(offsetInput);
                } catch (NumberFormatException except) {
                    offsetInput = "0";
                }
                if (posButton.getSelection() || controlInput.length() == 0) {
                    result = positionInput + "," + offsetInput;
                } else {
                    result = controlInput + "," + offsetInput + ":" + alignmentInput;
                }
                shell.close();
            }));
            Button cancel = new Button(shell, SWT.PUSH);
            cancel.setText(LayoutExample.getResourceString("Cancel"));
            cancel.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> shell.close()));

            shell.setDefaultButton(ok);
            shell.pack();
            /* Center the dialog */
            Point center = parent.getLocation();
            center.x = center.x + (parent.getBounds().width / 2) - (shell.getBounds().width / 2);
            center.y = center.y + (parent.getBounds().height / 2) - (shell.getBounds().height / 2);
            shell.setLocation(center);
            shell.open();
            while (!shell.isDisposed()) {
                if (display.readAndDispatch())
                    display.sleep();
            }

            return result;
        }
    }
}