/*
 *  Copyright (C) 2006-2019  Ronald Blankendaal
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
package org.dbgl.gui.abstractdialog;

import java.util.Comparator;
import java.util.Optional;
import java.util.stream.Stream;
import org.dbgl.service.ITextService;
import org.dbgl.service.ImageService;
import org.dbgl.service.SettingsService;
import org.dbgl.service.TextService;
import org.dbgl.util.SystemUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
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.Composite;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.ExpandBar;
import org.eclipse.swt.widgets.ExpandItem;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Scale;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;


public abstract class BaseDialog<T> extends Dialog {

	private final static int MIN_BUTTON_WIDTH = 80;
	private static Integer averageCharacterWidth_;

	protected final SelectionAdapter closeShellAdapter = new SelectionAdapter() {
		public void widgetSelected(SelectionEvent event) {
			shell_.close();
		}
	};

	protected final SelectionAdapter browseAdapter = new SelectionAdapter() {
		public void widgetSelected(SelectionEvent event) {
			SystemUtils.openForBrowsing(event.text);
		}
	};

	protected final Display display_;
	protected final int shellStyle_;
	protected Shell shell_;

	protected final ITextService text_;

	protected T result_;

	public BaseDialog(Shell parent, int shellStyle) {
		super(parent, SWT.NONE);
		display_ = parent.getDisplay();
		shellStyle_ = shellStyle;
		text_ = TextService.getInstance();
	}

	public BaseDialog(Shell parent) {
		this(parent, SWT.TITLE | SWT.CLOSE | SWT.BORDER | SWT.RESIZE | SWT.APPLICATION_MODAL);
	}

	public T open() {
		if (!prepare())
			return null;

		shell_ = shellStyle_ == SWT.PRIMARY_MODAL ? getParent(): new Shell(getParent(), shellStyle_);
		shell_.setText(getDialogTitle());

		onShellInit();

		onShellCreated();

		shell_.open();

		onShellOpened();

		while (!shell_.isDisposed()) {
			shellDispatchCallback();
			if (!display_.readAndDispatch()) {
				display_.sleep();
			}
		}

		onClose();

		return result_;
	}

	protected boolean prepare() {
		return true;
	}

	protected void onShellInit() {
	}

	protected abstract String getDialogTitle();

	protected abstract void onShellCreated();

	protected void onShellOpened() {
	}

	protected void shellDispatchCallback() {
	}

	protected void onClose() {
	}

	/* Font */
	protected static Font stringToFont(Device device, String[] font, Font defaultFont) {
		try {
			return new Font(device, font[0], Integer.parseInt(font[1]), Integer.parseInt(font[2]));
		} catch (Exception e) {
			e.printStackTrace();
			return defaultFont;
		}
	}

	protected static String fontToString(Device device, Font font) {
		FontData data = font.getFontData()[0];
		return data.getName() + '|' + data.getHeight() + '|' + data.getStyle();
	}

	protected static void setLayoutDataButtons(Button... buttons) {
		Optional<Integer> maxWidth = Stream.of(buttons).map(x -> x.computeSize(SWT.DEFAULT, SWT.DEFAULT).x).max(Comparator.naturalOrder());
		if (maxWidth.isPresent()) {
			if (averageCharacterWidth_ == null) {
				GC gc = new GC(buttons[0]);
				averageCharacterWidth_ = (int)gc.getFontMetrics().getAverageCharacterWidth();
				gc.dispose();
			}
			int width = (4 * averageCharacterWidth_) + Math.max(maxWidth.get(), MIN_BUTTON_WIDTH);

			for (Button button: buttons) {
				GridData gridData = new GridData(SWT.BEGINNING, SWT.FILL, true, false);
				gridData.widthHint = width;
				button.setLayoutData(gridData);
			}
		}
	}

	/* Composite */
	protected static Composite createComposite(Composite composite, Object layoutData, Layout layout) {
		Composite inner = new Composite(composite, SWT.NONE);
		if (layoutData != null)
			inner.setLayoutData(layoutData);
		if (layout != null)
			inner.setLayout(layout);
		return inner;
	}

	protected static Composite createComposite(Composite composite) {
		return createComposite(composite, null, null);
	}

	protected static Composite createComposite(Composite composite, Object layoutData) {
		return createComposite(composite, layoutData, null);
	}

	protected static Composite createComposite(Composite composite, int numColumns) {
		return createComposite(composite, null, new GridLayout(numColumns, false));
	}

	protected static Composite createInnerComposite(Composite composite, Object layoutData, int numColumns) {
		GridLayout layout = new GridLayout(numColumns, false);
		layout.horizontalSpacing = 4;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		return createComposite(composite, layoutData, layout);
	}

	protected static Composite createTabWithComposite(TabFolder tabFolder, String text, Layout layout) {
		Composite composite = createComposite(tabFolder, null, layout);
		TabItem tabItem = new TabItem(tabFolder, SWT.NONE);
		tabItem.setText(text);
		tabItem.setControl(composite);
		return composite;
	}

	protected static Composite createTabWithComposite(TabFolder tabFolder, String text, int numColumns) {
		return createTabWithComposite(tabFolder, text, new GridLayout(numColumns, false));
	}

	protected static Composite createTabWithInnerComposite(TabFolder tabFolder, String text, int numColumns) {
		Composite composite = createInnerComposite(tabFolder, null, numColumns);
		TabItem tabItem = new TabItem(tabFolder, SWT.NONE);
		tabItem.setText(text);
		tabItem.setControl(composite);
		return composite;
	}

	/* Group */
	protected static Group createGroup(Composite composite, Object layoutData, String text, Layout layout) {
		Group group = new Group(composite, SWT.NONE);
		if (layoutData != null)
			group.setLayoutData(layoutData);
		if (text != null)
			group.setText(text);
		if (layout != null)
			group.setLayout(layout);
		return group;
	}

	protected static Group createGroup(Composite composite, Object layoutData, String text, int numColumns) {
		return createGroup(composite, layoutData, text, new GridLayout(numColumns, false));
	}

	protected static Group createGroup(Composite composite, String text, Layout layout) {
		return createGroup(composite, null, text, layout);
	}

	protected static Group createGroup(Composite composite, String text, int numColumns) {
		return createGroup(composite, null, text, new GridLayout(numColumns, false));
	}

	protected static Group createGroup(Composite composite, Layout layout) {
		return createGroup(composite, null, null, layout);
	}

	/* ExpandItem */
	protected static ExpandItem createExpandItem(ExpandBar expandBar, String text, boolean expanded, Composite composite) {
		ExpandItem expandItem = new ExpandItem(expandBar, SWT.NONE);
		expandItem.setText(text);
		expandItem.setExpanded(expanded);
		expandItem.setControl(composite);
		expandItem.setHeight(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
		return expandItem;
	}

	/* Label */
	protected static Label createLabel(Composite composite, int style, Object layoutData, String text) {
		Label label = new Label(composite, style);
		if (layoutData != null)
			label.setLayoutData(layoutData);
		if (text != null)
			label.setText(text);
		return label;
	}

	protected static Label createLabel(Composite composite, int horizontalSpan, int verticalSpan, String text) {
		return createLabel(composite, SWT.NONE, new GridData(SWT.LEFT, SWT.CENTER, false, false, horizontalSpan, verticalSpan), text);
	}

	protected static Label createLabel(Composite composite, int horizontalSpan, int verticalSpan) {
		return createLabel(composite, SWT.NONE, new GridData(SWT.LEFT, SWT.CENTER, false, false, horizontalSpan, verticalSpan), null);
	}

	protected static Label createLabel(Composite composite, String text) {
		return createLabel(composite, SWT.NONE, null, text);
	}

	protected static Label createLabel(Composite composite) {
		return createLabel(composite, SWT.NONE, null, null);
	}

	/* Line Separator */
	protected static void createHorizontalSeparator(Composite composite, int horizontalSpan) {
		createLabel(composite, SWT.SEPARATOR | SWT.HORIZONTAL, new GridData(SWT.FILL, SWT.CENTER, true, false, horizontalSpan, 1), null);
	}

	protected static void createVerticalSeparator(Composite composite, int verticalSpan) {
		createLabel(composite, SWT.SEPARATOR | SWT.VERTICAL, new GridData(SWT.LEFT, SWT.FILL, false, true, 1, verticalSpan), null);
	}

	/* Text */
	protected static Text createText(Composite composite, int style, Object layoutData, String value, String tooltip) {
		Text text = new Text(composite, style);
		if (layoutData != null)
			text.setLayoutData(layoutData);
		if (value != null)
			text.setText(value);
		if (tooltip != null)
			text.setToolTipText(tooltip);
		return text;
	}

	protected static Text createText(Composite composite, int style, int horizontalSpan) {
		return createText(composite, style, new GridData(SWT.FILL, SWT.CENTER, true, false, horizontalSpan, 1), null, null);
	}

	protected static Text createText(Composite composite, Object layoutData) {
		return createText(composite, SWT.BORDER, layoutData, null, null);
	}

	protected static Text createText(Composite composite, int horizontalSpan) {
		return createText(composite, SWT.BORDER, new GridData(SWT.FILL, SWT.CENTER, true, false, horizontalSpan, 1), null, null);
	}

	protected static Text createText(Composite composite, String value) {
		return createText(composite, SWT.BORDER, null, value, null);
	}

	protected static Text createText(Composite composite) {
		return createText(composite, SWT.BORDER, new GridData(SWT.FILL, SWT.CENTER, true, false), null, null);
	}

	/* Textarea */
	protected static Text createTextarea(Composite composite, boolean readonly, boolean wrapping, int horizontalSpan, int verticalSpan, String value) {
		int style = SWT.BORDER | SWT.MULTI | SWT.V_SCROLL;
		if (readonly)
			style |= SWT.READ_ONLY;
		style |= wrapping ? SWT.WRAP: SWT.H_SCROLL;
		return createText(composite, style, new GridData(SWT.FILL, SWT.FILL, true, true, horizontalSpan, verticalSpan), value, null);
	}

	protected static Text createTextarea(Composite composite, boolean readonly) {
		int style = SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL;
		if (readonly)
			style |= SWT.READ_ONLY;
		return createText(composite, style, new GridData(SWT.FILL, SWT.FILL, true, true), null, null);
	}

	/* Button */
	protected static Button createButton(Composite composite, int style, Object layoutData, String text, String tooltip) {
		Button button = new Button(composite, style);
		if (layoutData != null)
			button.setLayoutData(layoutData);
		if (text != null)
			button.setText(text);
		if (tooltip != null)
			button.setToolTipText(tooltip);
		return button;
	}

	protected static Button createButton(Composite composite, Object layoutData, String text, String tooltip, SelectionListener listener) {
		Button button = createButton(composite, SWT.NONE, layoutData, text, tooltip);
		button.addSelectionListener(listener);
		return button;
	}

	protected static Button createButton(Composite composite, String text, SelectionListener listener) {
		Button button = createButton(composite, SWT.NONE, new GridData(SWT.FILL, SWT.CENTER, false, false), text, null);
		button.addSelectionListener(listener);
		return button;
	}

	/* CheckButton */
	protected static Button createCheckButton(Composite composite, Object layoutData, String text, String tooltip, boolean selected) {
		Button button = createButton(composite, SWT.CHECK, layoutData, text, tooltip);
		button.setSelection(selected);
		return button;
	}

	protected static Button createCheckButton(Composite composite, Object layoutData, String text, boolean selected) {
		return createCheckButton(composite, layoutData, text, null, selected);
	}

	protected static Button createCheckButton(Composite composite, Object layoutData, boolean selected) {
		return createCheckButton(composite, layoutData, null, null, selected);
	}

	protected static Button createCheckButton(Composite composite, int horizontalSpan, String text, String tooltip, boolean selected) {
		return createCheckButton(composite, new GridData(SWT.BEGINNING, SWT.CENTER, false, false, horizontalSpan, 1), text, tooltip, selected);
	}

	protected static Button createCheckButton(Composite composite, int horizontalSpan, String text, boolean selected) {
		return createCheckButton(composite, new GridData(SWT.BEGINNING, SWT.CENTER, false, false, horizontalSpan, 1), text, null, selected);
	}

	protected static Button createCheckButton(Composite composite, String tooltip) {
		return createCheckButton(composite, null, null, tooltip, false);
	}

	protected static Button createCheckButton(Composite composite, boolean selected) {
		return createCheckButton(composite, null, null, null, selected);
	}

	/* ToggleButton */
	protected static Button createToggleButton(Composite composite, String text, boolean selected, SelectionListener listener) {
		Button button = createButton(composite, SWT.TOGGLE, null, text, null);
		button.setSelection(selected);
		button.addSelectionListener(listener);
		return button;
	}

	/* ImageButton */
	protected static Button createImageButton(Composite composite, int style, Object layoutData, Image image, String text, String tooltip, SelectionListener listener, boolean enableDisposeListener) {
		Button button = createButton(composite, style, layoutData, text, tooltip);
		button.setImage(image);
		if (enableDisposeListener)
			button.addDisposeListener(new DisposeListener() {
				public void widgetDisposed(DisposeEvent e) {
					((Button)e.getSource()).getImage().dispose();
				}
			});
		if (listener != null)
			button.addSelectionListener(listener);
		return button;
	}

	protected static Button createImageButton(Composite composite, int style, Object layoutData, Image image, String tooltip) {
		return createImageButton(composite, style, layoutData, image, null, tooltip, null, true);
	}

	protected static Button createImageButton(Composite composite, int style, Image image, SelectionListener listener) {
		return createImageButton(composite, style, null, image, null, null, listener, true);
	}

	protected static Button createImageButton(Composite composite, Image image, String text, SelectionListener listener) {
		int display = SettingsService.getInstance().getIntValue("gui", "buttondisplay");
		return createImageButton(composite, SWT.NONE, new GridData(SWT.FILL, SWT.CENTER, false, false), display != 1 ? image: null, text, null, listener, display != 1);
	}

	public static Button createImageButton(Composite composite, String text, String image) {
		int display = SettingsService.getInstance().getIntValue("gui", "buttondisplay");
		return createImageButton(composite, SWT.NONE, null, display != 1 ? ImageService.getResourceImage(composite.getDisplay(), image): null, display == 2 ? null: text, display == 2 ? text: null,
			null, display != 1);
	}

	/* RadioButton */
	protected static Button createRadioButton(Composite composite, String text, int numColumns, boolean selected) {
		Button button = createButton(composite, SWT.RADIO, new GridData(SWT.BEGINNING, SWT.CENTER, false, false, numColumns, 1), text, null);
		button.setSelection(selected);
		return button;
	}

	protected static Button createRadioButton(Composite composite, String text) {
		return createRadioButton(composite, text, 1, false);
	}

	/* ArrowButton */
	protected static Button createArrowButton(Composite composite, int directionStyle, SelectionListener listener) {
		Button button = new Button(composite, SWT.ARROW | directionStyle);
		button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
		button.addSelectionListener(listener);
		return button;
	}

	protected static Button createUpButton(Composite composite, SelectionListener listener) {
		return createArrowButton(composite, SWT.UP, listener);
	}

	protected static Button createDownButton(Composite composite, SelectionListener listener) {
		return createArrowButton(composite, SWT.DOWN, listener);
	}

	/* ThreeDotButton */
	protected static Button createThreeDotButton(Composite composite, SelectionListener listener) {
		return createButton(composite, null, "...", null, listener);
	}

	/* Link */
	protected static Link createLink(Composite composite, String text, SelectionListener listener) {
		Link link = new Link(composite, SWT.NONE);
		link.setText(text);
		link.addSelectionListener(listener);
		return link;
	}

	/* ProgressBar */
	protected static ProgressBar createProgressBar(Composite composite) {
		ProgressBar progressBar = new ProgressBar(composite, SWT.NONE);
		progressBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		return progressBar;
	}

	/* Spinner */
	protected static Spinner createSpinner(Composite composite, int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) {
		Spinner spinner = new Spinner(composite, SWT.BORDER);
		spinner.setValues(selection, minimum, maximum, digits, increment, pageIncrement);
		return spinner;
	}

	protected static Spinner createSpinner(Composite composite, int minimum, int maximum) {
		Spinner spinner = new Spinner(composite, SWT.BORDER);
		spinner.setMinimum(minimum);
		spinner.setMaximum(maximum);
		return spinner;
	}

	/* Scale */
	protected static Scale createScale(Composite composite, boolean vertical, Object layoutData, int selection, int minimum, int maximum, int increment, int pageIncrement) {
		Scale scale = new Scale(composite, vertical ? SWT.VERTICAL: SWT.HORIZONTAL);
		if (layoutData != null)
			scale.setLayoutData(layoutData);
		scale.setMinimum(minimum);
		scale.setMaximum(maximum);
		scale.setIncrement(increment);
		scale.setPageIncrement(pageIncrement);
		scale.setSelection(selection);
		return scale;
	}

	protected static Scale createScale(Composite composite, boolean vertical, Object layoutData, int selection, int maximum, int pageIncrement) {
		Scale scale = new Scale(composite, vertical ? SWT.VERTICAL: SWT.HORIZONTAL);
		if (layoutData != null)
			scale.setLayoutData(layoutData);
		scale.setMaximum(maximum);
		scale.setPageIncrement(pageIncrement);
		scale.setSelection(selection);
		return scale;
	}

	protected static Scale createScale(Composite composite, boolean vertical, Object layoutData) {
		Scale scale = new Scale(composite, vertical ? SWT.VERTICAL: SWT.HORIZONTAL);
		if (layoutData != null)
			scale.setLayoutData(layoutData);
		return scale;
	}

	/* ToolItem */
	protected static ToolItem createImageToolItem(ToolBar toolBar, int style, Image image, String tooltip, SelectionListener listener) {
		ToolItem toolItem = new ToolItem(toolBar, style);
		toolItem.setImage(image);
		toolItem.setToolTipText(tooltip);
		if (listener != null)
			toolItem.addSelectionListener(listener);
		return toolItem;
	}

	protected static ToolItem createImageToolItem(ToolBar toolBar, String title, String img, SelectionListener listener) {
		ToolItem toolItem = new ToolItem(toolBar, SWT.PUSH | SWT.BORDER);
		int displaySelection = SettingsService.getInstance().getIntValue("gui", "buttondisplay");
		if (displaySelection != 1)
			toolItem.setImage(ImageService.getResourceImage(toolBar.getDisplay(), img));
		if (displaySelection == 2)
			toolItem.setToolTipText(title);
		else
			toolItem.setText(title);
		toolItem.addSelectionListener(listener);
		return toolItem;
	}

	protected static ToolItem createSeparatorToolItem(ToolBar toolBar, int width) {
		ToolItem toolItem = new ToolItem(toolBar, SWT.SEPARATOR | SWT.BORDER);
		toolItem.setWidth(width);
		return toolItem;
	}

	/* MenuItem */
	protected static MenuItem createMenuItem(Menu menu, int style, int pos, String title, String img, int accelerator, SelectionListener listener) {
		MenuItem menuItem = pos != -1 ? new MenuItem(menu, style, pos): new MenuItem(menu, style);
		menuItem.setText(title);
		if (accelerator != -1)
			menuItem.setAccelerator(accelerator);
		if ((img != null) && (SettingsService.getInstance().getIntValue("gui", "buttondisplay") != 1))
			menuItem.setImage(ImageService.getResourceImage(menu.getDisplay(), img));
		if (listener != null)
			menuItem.addSelectionListener(listener);
		return menuItem;
	}

	protected static MenuItem createMenuItem(Menu menu, int style, String title, String img, int accelerator, SelectionListener listener) {
		return createMenuItem(menu, style, -1, title, img, accelerator, listener);
	}

	protected static MenuItem createMenuItem(Menu menu, int pos, String title, SelectionListener listener) {
		return createMenuItem(menu, listener == null ? SWT.CASCADE: SWT.NONE, pos, title, null, -1, listener);
	}

	protected static MenuItem createMenuItem(Menu menu, String title, String img, SelectionListener listener) {
		return createMenuItem(menu, listener == null ? SWT.CASCADE: SWT.NONE, -1, title, img, -1, listener);
	}

	protected static MenuItem createTopMenuItem(Menu menu, String title, String img, SelectionListener listener) {
		return createMenuItem(menu, listener == null ? SWT.CASCADE: SWT.NONE, 0, title, img, -1, listener);
	}

	protected static MenuItem createSeparatorMenuItem(Menu menu) {
		return new MenuItem(menu, SWT.SEPARATOR);
	}

	/* Menu */
	protected static Menu createMenu(Menu parentMenu, String text, String img) {
		MenuItem menuItem = createMenuItem(parentMenu, text, img, null);
		Menu menu = new Menu(menuItem);
		menuItem.setMenu(menu);
		return menu;
	}

	protected static Menu createMenu(Menu parentMenu, String text) {
		return createMenu(parentMenu, text, null);
	}

	/* List */
	protected static List createList(Composite composite, int style, String[] items, int select) {
		List list = new List(composite, style);
		list.setItems(items);
		list.select(select);
		list.showSelection();
		return list;
	}

	protected static List createList(Composite composite, int style, int horizontalSpan, int verticalSpan) {
		List list = new List(composite, style);
		list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, horizontalSpan, verticalSpan));
		return list;
	}

	protected static List createList(Composite composite, int horizontalSpan, int verticalSpan) {
		return createList(composite, SWT.V_SCROLL | SWT.BORDER, horizontalSpan, verticalSpan);
	}

	/* TableColumn */
	protected static TableColumn createTableColumn(Table table, int width, String text) {
		TableColumn column = new TableColumn(table, SWT.NONE);
		column.setWidth(width);
		column.setText(text);
		return column;
	}

	/* Combo */
	protected static Combo createCombo(Composite composite, int style, Object layoutData, String[] items, int visibleItemCount, int select, String tooltip) {
		Combo combo = new Combo(composite, style);
		if (layoutData != null)
			combo.setLayoutData(layoutData);
		if (items != null)
			combo.setItems(items);
		combo.setVisibleItemCount(visibleItemCount);
		if (select >= 0)
			combo.select(select);
		if (tooltip != null)
			combo.setToolTipText(tooltip);
		return combo;
	}

	protected static Combo createCombo(Composite composite, int style, String[] items, String tooltip) {
		return createCombo(composite, style, null, items, 10, -1, tooltip);
	}

	protected static Combo createCombo(Composite composite, String[] items, int visibleItemCount, int select) {
		return createCombo(composite, SWT.READ_ONLY, null, items, visibleItemCount, select, null);
	}

	protected static Combo createCombo(Composite composite, String[] items, int visibleItemCount, String tooltip) {
		return createCombo(composite, SWT.READ_ONLY, null, items, visibleItemCount, -1, tooltip);
	}

	protected static Combo createCombo(Composite composite, String[] items, int visibleItemCount) {
		return createCombo(composite, SWT.READ_ONLY, null, items, visibleItemCount, -1, null);
	}

	protected static Combo createCombo(Composite composite, String[] items, String tooltip) {
		return createCombo(composite, SWT.READ_ONLY, null, items, 10, -1, tooltip);
	}

	protected static Combo createEditableCombo(Composite composite, String[] items, int visibleItemCount) {
		return createCombo(composite, SWT.NONE, null, items, visibleItemCount, -1, null);
	}

	protected static Combo createEditableCombo(Composite composite, String[] items, int visibleItemCount, String tooltip) {
		return createCombo(composite, SWT.NONE, null, items, visibleItemCount, -1, tooltip);
	}

	protected static Combo createWideEditableCombo(Composite composite, String[] items, int visibleItemCount, String tooltip) {
		return createCombo(composite, SWT.NONE, new GridData(SWT.FILL, SWT.CENTER, true, false), items, visibleItemCount, -1, tooltip);
	}

	/* Label + Text */
	protected static Text createLabelAndText(Composite composite, String labelText, int style, Object layoutData, String value, String tooltip) {
		createLabel(composite, labelText);
		return createText(composite, style, layoutData, value, tooltip);
	}

	protected static Text createLabelAndText(Composite composite, String labelText, int horizontalSpan, String value, String tooltip) {
		return createLabelAndText(composite, labelText, SWT.BORDER, new GridData(SWT.FILL, SWT.CENTER, true, false, horizontalSpan, 1), value, tooltip);
	}

	protected static Text createLabelAndText(Composite composite, String labelText, int horizontalSpan, String value) {
		return createLabelAndText(composite, labelText, SWT.BORDER, new GridData(SWT.FILL, SWT.CENTER, true, false, horizontalSpan, 1), value, null);
	}

	protected static Text createLabelAndText(Composite composite, String labelText, int horizontalSpan) {
		return createLabelAndText(composite, labelText, SWT.BORDER, new GridData(SWT.FILL, SWT.CENTER, true, false, horizontalSpan, 1), null, null);
	}

	protected static Text createLabelAndText(Composite composite, String labelText) {
		return createLabelAndText(composite, labelText, SWT.BORDER, new GridData(SWT.FILL, SWT.CENTER, true, false), null, null);
	}

	protected static Text createLabelAndText(Composite composite, String labelText, String value) {
		return createLabelAndText(composite, labelText, SWT.BORDER, new GridData(SWT.FILL, SWT.CENTER, true, false), value, null);
	}

	/* Label + Textarea */
	protected static Text createLabelAndTextarea(Composite composite, String labelText, boolean readonly, boolean wrapping, int horizontalSpan, int verticalSpan, String value) {
		createLabel(composite, labelText);
		return createTextarea(composite, readonly, wrapping, horizontalSpan, verticalSpan, value);
	}

	protected static Text createLabelAndTextarea(Composite composite, String labelText, boolean readonly, boolean wrapping, int horizontalSpan, int verticalSpan) {
		return createLabelAndTextarea(composite, labelText, readonly, wrapping, horizontalSpan, verticalSpan, null);
	}

	protected static Text createLabelAndTextarea(Composite composite, String labelText, boolean readonly, String value) {
		return createLabelAndTextarea(composite, labelText, readonly, false, 1, 1, value);
	}

	protected static Text createLabelAndTextarea(Composite composite, String labelText, boolean readonly) {
		return createLabelAndTextarea(composite, labelText, readonly, false, 1, 1, null);
	}

	/* Label + Scale */
	protected static Scale createLabelAndScale(Composite composite, String labelText, boolean vertical, Object layoutData, int selection, int minimum, int maximum, int increment, int pageIncrement) {
		createLabel(composite, labelText);
		return createScale(composite, vertical, layoutData, selection, minimum, maximum, increment, pageIncrement);
	}

	/* Label + Spinner */
	protected static Spinner createLabelAndSpinner(Composite composite, String labelText, int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) {
		createLabel(composite, labelText);
		return createSpinner(composite, selection, minimum, maximum, digits, increment, pageIncrement);
	}

	protected static Spinner createLabelAndSpinner(Composite composite, String labelText, int selection) {
		return createLabelAndSpinner(composite, labelText, selection, 0, Integer.MAX_VALUE, 0, 1, 10);
	}

	/* Label + Button */
	protected static Button createLabelAndButton(Composite composite, String labelText, String buttonText, SelectionListener listener) {
		createLabel(composite, labelText);
		return createButton(composite, buttonText, listener);
	}

	/* Label + RadioButton */
	protected static Button createLabelAndRadioButton(Composite composite, String labelText, String text, boolean selected) {
		createLabel(composite, labelText);
		return createRadioButton(composite, text, 1, selected);
	}

	/* Label + CheckButton */
	protected static Button createLabelAndCheckButton(Composite composite, String labelText, int horizontalSpan, String text, String tooltip, boolean selected) {
		createLabel(composite, labelText);
		return createCheckButton(composite, horizontalSpan, text, tooltip, selected);
	}

	protected static Button createLabelAndCheckButton(Composite composite, String labelText, int horizontalSpan, String text, boolean selected) {
		return createLabelAndCheckButton(composite, labelText, horizontalSpan, text, null, selected);
	}

	protected static Button createLabelAndCheckButton(Composite composite, String labelText, int horizontalSpan, String text) {
		return createLabelAndCheckButton(composite, labelText, horizontalSpan, text, false);
	}

	protected static Button createLabelAndCheckButton(Composite composite, String labelText, int horizontalSpan, boolean selected) {
		return createLabelAndCheckButton(composite, labelText, horizontalSpan, null, selected);
	}

	protected static Button createLabelAndCheckButton(Composite composite, String labelText, int horizontalSpan) {
		return createLabelAndCheckButton(composite, labelText, horizontalSpan, null, false);
	}

	protected static Button createLabelAndCheckButton(Composite composite, String labelText, String text, boolean selected) {
		return createLabelAndCheckButton(composite, labelText, 1, text, selected);
	}

	protected static Button createLabelAndCheckButton(Composite composite, String labelText, boolean selected) {
		return createLabelAndCheckButton(composite, labelText, 1, null, selected);
	}

	protected static Button createLabelAndTooltipCheckButton(Composite composite, String labelText, String tooltip, boolean selected) {
		return createLabelAndCheckButton(composite, labelText, 1, null, tooltip, selected);
	}

	/* Label + Combo */
	protected static Combo createLabelAndCombo(Composite composite, String labelText, int style, Object layoutData, String[] items, int visibleItemCount, int select, String tooltip) {
		createLabel(composite, labelText);
		return createCombo(composite, style, layoutData, items, visibleItemCount, select, tooltip);
	}

	protected static Combo createLabelAndCombo(Composite composite, String labelText, String[] items, int visibleItemCount, int select) {
		return createLabelAndCombo(composite, labelText, SWT.READ_ONLY, null, items, visibleItemCount, select, null);
	}

	protected static Combo createLabelAndCombo(Composite composite, String labelText, String[] items, int visibleItemCount) {
		return createLabelAndCombo(composite, labelText, SWT.READ_ONLY, null, items, visibleItemCount, -1, null);
	}

	protected static Combo createLabelAndCombo(Composite composite, String labelText, boolean wide, int horizontalSpan, String[] items, int visibleItemCount, int select, String tooltip) {
		GridData gd = wide ? new GridData(SWT.FILL, SWT.CENTER, true, false, horizontalSpan, 1): new GridData(SWT.BEGINNING, SWT.CENTER, false, false, horizontalSpan, 1);
		return createLabelAndCombo(composite, labelText, SWT.READ_ONLY, gd, items, visibleItemCount, select, tooltip);
	}

	protected static Combo createLabelAndCombo(Composite composite, String labelText, boolean wide, int horizontalSpan, String[] items, int visibleItemCount) {
		return createLabelAndCombo(composite, labelText, wide, horizontalSpan, items, visibleItemCount, -1, null);
	}

	protected static Combo createLabelAndCombo(Composite composite, String labelText, int horizontalSpan, String[] items, int visibleItemCount, String tooltip) {
		return createLabelAndCombo(composite, labelText, false, horizontalSpan, items, visibleItemCount, -1, tooltip);
	}

	protected static Combo createLabelAndWideCombo(Composite composite, String labelText) {
		return createLabelAndCombo(composite, labelText, true, 1, null, 20, -1, null);
	}

	/* Label + EditableCombo */
	protected static Combo createLabelAndEditableCombo(Composite composite, String labelText, int horizontalSpan, String[] items, int visibleItemCount, String tooltip) {
		return createLabelAndCombo(composite, labelText, SWT.NONE, new GridData(SWT.BEGINNING, SWT.CENTER, false, false, horizontalSpan, 1), items, visibleItemCount, -1, tooltip);
	}

	protected static Combo createLabelAndEditableCombo(Composite composite, String labelText, String[] items, int visibleItemCount) {
		return createLabelAndEditableCombo(composite, labelText, 1, items, visibleItemCount, null);
	}
}
