/*******************************************************************************
* Copyright (c) 2013 Zend Techologies Ltd.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Zend Technologies Ltd. - initial API and implementation
*******************************************************************************/
package org.eclipse.php.formatter.ui.preferences;
import java.util.*;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.php.formatter.core.CodeFormatterConstants;
import org.eclipse.php.formatter.core.profiles.CodeFormatterPreferences;
import org.eclipse.php.formatter.ui.FormatterMessages;
import org.eclipse.php.formatter.ui.FormatterUIPlugin;
import org.eclipse.php.internal.ui.util.Messages;
import org.eclipse.php.internal.ui.util.PixelConverter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
public abstract class ModifyDialogTabPage {
/**
* This is the default listener for any of the Preference classes. It is
* added by the respective factory methods and updates the page's preview on
* each change.
*/
protected final Observer fUpdater = (o, arg) -> {
updatePreferences();
doUpdatePreview();
notifyValuesModified();
};
/**
* The base class of all Preference classes. A preference class provides a
* wrapper around one or more SWT widgets and handles the input of values
* for some key. On each change, the new value is written to the map and the
* listeners are notified.
*/
protected abstract class Preference extends Observable {
/**
* Returns the main control of a preference, which is mainly used to
* manage the focus. This may be <code>null</code> if the preference
* doesn't have a control which is able to have the focus.
*
* @return The main control
*/
public abstract Control getControl();
@Override
protected void setChanged() {
super.setChanged();
notifyObservers();
}
}
/**
* Wrapper around a checkbox and a label.
*/
protected final class CheckboxPreference extends Preference {
private final Button fCheckbox;
public CheckboxPreference(Composite composite, int numColumns, String text) {
if (text == null) {
throw new IllegalArgumentException(
FormatterMessages.ModifyDialogTabPage_error_msg_values_text_unassigned);
}
fCheckbox = new Button(composite, SWT.CHECK);
fCheckbox.setText(text);
fCheckbox.setLayoutData(createGridData(numColumns, GridData.FILL_HORIZONTAL, SWT.DEFAULT));
fCheckbox.setFont(composite.getFont());
fCheckbox.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
setChanged();
}
});
}
public void setIsChecked(boolean isChecked) {
fCheckbox.setSelection(isChecked);
}
public boolean isChecked() {
return fCheckbox.getSelection();
}
public void setEnabled(boolean isEnabled) {
fCheckbox.setEnabled(isEnabled);
}
public boolean isEnabled() {
return fCheckbox.isEnabled();
}
@Override
public Control getControl() {
return fCheckbox;
}
}
/**
* Wrapper around a Combo box.
*/
protected final class ComboPreference extends Preference {
private final String[] fItems;
private final Combo fCombo;
public ComboPreference(Composite composite, int numColumns, String text, String[] items) {
if (items == null || text == null)
throw new IllegalArgumentException(
FormatterMessages.ModifyDialogTabPage_error_msg_values_items_text_unassigned);
fItems = items;
createLabel(numColumns - 1, composite, text);
fCombo = new Combo(composite, SWT.SINGLE | SWT.READ_ONLY);
fCombo.setFont(composite.getFont());
fCombo.setItems(items);
fCombo.setLayoutData(
createGridData(1, GridData.HORIZONTAL_ALIGN_FILL, fCombo.computeSize(SWT.DEFAULT, SWT.DEFAULT).x));
fCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
setChanged();
}
});
}
public void setSelectedItem(String item) {
int index = 0;
boolean found = false;
for (; index < fItems.length; index++) {
if (fItems[index].equals(item)) {
found = true;
break;
}
}
if (found) {
fCombo.select(index);
}
}
public String getSelectedItem() {
int index = fCombo.getSelectionIndex();
return fItems[index];
}
public int getSelectionIndex() {
return fCombo.getSelectionIndex();
}
@Override
public Control getControl() {
return fCombo;
}
}
/**
* Wrapper around a textfied which requests an integer input of a given
* range.
*/
protected final class NumberPreference extends Preference {
private final int fMinValue, fMaxValue;
private final Text fNumberText;
protected int fSelected;
protected int fOldSelected;
public NumberPreference(Composite composite, int numColumns, String text, int minValue, int maxValue) {
createLabel(numColumns - 1, composite, text, GridData.FILL_HORIZONTAL);
fNumberText = new Text(composite, SWT.SINGLE | SWT.BORDER | SWT.RIGHT);
fNumberText.setFont(composite.getFont());
final int length = Integer.toString(maxValue).length() + 3;
fNumberText.setLayoutData(createGridData(1, GridData.HORIZONTAL_ALIGN_END,
fPixelConverter.convertWidthInCharsToPixels(length)));
fMinValue = minValue;
fMaxValue = maxValue;
fNumberText.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
NumberPreference.this.focusGained();
}
@Override
public void focusLost(FocusEvent e) {
NumberPreference.this.focusLost();
}
});
fNumberText.addModifyListener(e -> fieldModified());
}
private IStatus createErrorStatus() {
return new Status(IStatus.ERROR, FormatterUIPlugin.PLUGIN_ID, 0,
Messages.format(FormatterMessages.ModifyDialogTabPage_NumberPreference_error_invalid_value,
new String[] { Integer.toString(fMinValue), Integer.toString(fMaxValue) }),
null);
}
protected void focusGained() {
fOldSelected = fSelected;
fNumberText.setSelection(0, fNumberText.getCharCount());
}
protected void focusLost() {
updateStatus(null);
final String input = fNumberText.getText();
if (!validInput(input)) {
fSelected = fOldSelected;
} else {
fSelected = Integer.parseInt(input);
}
if (fSelected != fOldSelected) {
setChanged();
fNumberText.setText(Integer.toString(fSelected));
}
}
protected void fieldModified() {
final String trimInput = fNumberText.getText().trim();
final boolean valid = validInput(trimInput);
updateStatus(valid ? null : createErrorStatus());
if (valid) {
final int number = Integer.parseInt(trimInput);
if (fSelected != number) {
fSelected = number;
setChanged();
}
}
}
private boolean validInput(String trimInput) {
boolean isValid = true;
try {
int number = Integer.parseInt(trimInput);
if (number < fMinValue || number > fMaxValue) {
isValid = false;
}
} catch (NumberFormatException x) {
isValid = false;
}
return isValid;
}
public void setValue(int value) {
fNumberText.setText(String.valueOf(value));
}
public int getValue() {
return fSelected;
}
@Override
public Control getControl() {
return fNumberText;
}
}
/**
* Wrapper around a textfied which requests an integer input of a given
* range.
*/
protected final class StringPreference extends Preference {
private final Label fLabel;
private IInputValidator fInputValidator;
private final Text fNumberText;
protected String fSelected;
protected String fOldSelected;
public StringPreference(Composite composite, int numColumns, String text, IInputValidator inputValidator) {
fInputValidator = inputValidator;
fLabel = new Label(composite, SWT.NONE);
fLabel.setFont(composite.getFont());
fLabel.setText(text);
fLabel.setLayoutData(createGridData(numColumns - 1, GridData.HORIZONTAL_ALIGN_BEGINNING, SWT.DEFAULT));
fNumberText = new Text(composite, SWT.SINGLE | SWT.BORDER);
fNumberText.setFont(composite.getFont());
final int length = 30;
fNumberText.setLayoutData(createGridData(1, GridData.HORIZONTAL_ALIGN_BEGINNING,
fPixelConverter.convertWidthInCharsToPixels(length)));
fNumberText.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
StringPreference.this.focusGained();
}
@Override
public void focusLost(FocusEvent e) {
StringPreference.this.focusLost();
}
});
fNumberText.addModifyListener(e -> fieldModified());
}
public void setEnabled(boolean isEnabled) {
fNumberText.setEnabled(isEnabled);
}
public boolean isEnabled() {
return fNumberText.isEnabled();
}
protected void focusGained() {
fOldSelected = fSelected;
fNumberText.setSelection(0, fNumberText.getCharCount());
}
public void setValue(String value) {
fNumberText.setText(value);
}
private IStatus createErrorStatus(String errorText) {
return new Status(IStatus.ERROR, FormatterUIPlugin.PLUGIN_ID, 0, errorText, null);
}
protected void focusLost() {
updateStatus(null);
final String input = fNumberText.getText();
if (fInputValidator != null && fInputValidator.isValid(input) != null) {
fSelected = fOldSelected;
} else {
fSelected = input;
}
if (fSelected != fOldSelected) {
setChanged();
fNumberText.setText(fSelected);
}
}
protected void fieldModified() {
final String text = fNumberText.getText();
final String errorText = fInputValidator != null ? fInputValidator.isValid(text) : null;
if (errorText == null) {
updateStatus(null);
if (fSelected != text) {
fSelected = text;
setChanged();
}
} else {
updateStatus(createErrorStatus(errorText));
}
}
public String getValue() {
return fSelected;
}
@Override
public Control getControl() {
return fNumberText;
}
}
/**
* This class provides the default way to preserve and re-establish the
* focus over multiple modify sessions. Each ModifyDialogTabPage has its own
* instance, and it should add all relevant controls upon creation, always
* in the same sequence. This established a mapping of controls to indexes,
* which allows to restore the focus in a later session. The index is saved
* in the dialog settings, and there is only one common preference for all
* tab pages. It is always the currently active tab page which stores its
* focus index.
*/
protected final static class DefaultFocusManager extends FocusAdapter {
private final static String PREF_LAST_FOCUS_INDEX = FormatterUIPlugin.PLUGIN_ID
+ "formatter_page.modify_dialog_tab_page.last_focus_index"; //$NON-NLS-1$
private final IDialogSettings fDialogSettings;
private final Map<Control, Integer> fItemMap;
private final List<Control> fItemList;
private int fIndex;
public DefaultFocusManager() {
fDialogSettings = FormatterUIPlugin.getDefault().getDialogSettings();
fItemMap = new HashMap<>();
fItemList = new ArrayList<>();
fIndex = 0;
}
@Override
public void focusGained(FocusEvent e) {
fDialogSettings.put(PREF_LAST_FOCUS_INDEX, fItemMap.get(e.widget).intValue());
}
public void add(Control control) {
control.addFocusListener(this);
fItemList.add(fIndex, control);
fItemMap.put(control, Integer.valueOf(fIndex++));
}
public void add(Preference preference) {
final Control control = preference.getControl();
if (control != null)
add(control);
}
public boolean isUsed() {
return fIndex != 0;
}
public void restoreFocus() {
int index = 0;
try {
index = fDialogSettings.getInt(PREF_LAST_FOCUS_INDEX);
// make sure the value is within the range
if ((index >= 0) && (index <= fItemList.size() - 1)) {
fItemList.get(index).setFocus();
}
} catch (NumberFormatException ex) {
// this is the first time
}
}
public void resetFocus() {
fDialogSettings.put(PREF_LAST_FOCUS_INDEX, -1);
}
}
/**
* The default focus manager. This widget knows all widgets which can have
* the focus and listens for focusGained events, on which it stores the
* index of the current focus holder. When the dialog is restarted,
* <code>restoreFocus()</code> sets the focus to the last control which had
* it.
*
* The standard Preference object are managed by this focus manager if they
* are created using the respective factory methods. Other SWT widgets can
* be added in subclasses when they are created.
*/
protected final DefaultFocusManager fDefaultFocusManager;
/**
* Constant array for boolean selection
*/
protected static final String[] FALSE_TRUE = { CodeFormatterConstants.FALSE, CodeFormatterConstants.TRUE };
/**
* A pixel converter for layout calculations
*/
protected PixelConverter fPixelConverter;
/**
* The map where the current settings are stored.
*/
protected final CodeFormatterPreferences codeFormatterPreferences;
/**
* The modify dialog where we can display status messages.
*/
private final ModifyDialog fModifyDialog;
/*
* Create a new <code>ModifyDialogTabPage</code>
*/
public ModifyDialogTabPage(ModifyDialog modifyDialog, CodeFormatterPreferences preferences) {
this.codeFormatterPreferences = preferences;
fModifyDialog = modifyDialog;
fDefaultFocusManager = new DefaultFocusManager();
}
/**
* Create the contents of this tab page.
* <p>
* Subclasses should implement <code>doCreatePreferences</code> and
* <code>doCreatePreview</code> may also be overridden as necessary.
* </p>
*
* @param parent
* The parent composite
* @return Created content control
*/
public Composite createContents(Composite parent) {
final int numColumns = 4;
if (fPixelConverter == null) {
fPixelConverter = new PixelConverter(parent);
}
final SashForm sashForm = new SashForm(parent, SWT.HORIZONTAL);
sashForm.setFont(parent.getFont());
Composite scrollContainer = new Composite(sashForm, SWT.NONE);
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
scrollContainer.setLayoutData(gridData);
GridLayout layout = new GridLayout(2, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
scrollContainer.setLayout(layout);
ScrolledComposite scroll = new ScrolledComposite(scrollContainer, SWT.V_SCROLL | SWT.H_SCROLL);
scroll.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
scroll.setExpandHorizontal(true);
scroll.setExpandVertical(true);
final Composite settingsContainer = new Composite(scroll, SWT.NONE);
settingsContainer.setFont(sashForm.getFont());
scroll.setContent(settingsContainer);
settingsContainer.setLayout(new PageLayout(scroll, 400, 400));
settingsContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Composite settingsPane = new Composite(settingsContainer, SWT.NONE);
settingsPane.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
layout = new GridLayout(numColumns, false);
layout.verticalSpacing = (int) (1.5
* fPixelConverter.convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING));
layout.horizontalSpacing = fPixelConverter.convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
layout.marginHeight = fPixelConverter.convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
layout.marginWidth = fPixelConverter.convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
settingsPane.setLayout(layout);
doCreatePreferences(settingsPane, numColumns);
settingsContainer.setSize(settingsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT));
scroll.addControlListener(new ControlListener() {
@Override
public void controlMoved(ControlEvent e) {
}
@Override
public void controlResized(ControlEvent e) {
settingsContainer.setSize(settingsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT));
}
});
Label sashHandle = new Label(scrollContainer, SWT.SEPARATOR | SWT.VERTICAL);
gridData = new GridData(SWT.RIGHT, SWT.FILL, false, true);
sashHandle.setLayoutData(gridData);
final Composite previewPane = new Composite(sashForm, SWT.NONE);
previewPane.setLayout(createGridLayout(numColumns, true));
previewPane.setFont(sashForm.getFont());
doCreatePreviewPane(previewPane, numColumns);
initializePage();
sashForm.setWeights(new int[] { 3, 3 });
return sashForm;
}
/**
* This method is called after all controls have been alloated, including
* the preview. It can be used to set the preview text and to create
* listeners.
*
*/
protected abstract void initializePage();
/**
* Create the left side of the modify dialog. This is meant to be
* implemented by subclasses.
*
* @param composite
* Composite to create in
* @param numColumns
* Number of columns to use
*/
protected abstract void doCreatePreferences(Composite composite, int numColumns);
/**
* Create the right side of the modify dialog. By default, the preview is
* displayed there. Subclasses can override this method in order to
* customize the right-hand side of the dialog.
*
* @param composite
* Composite to create in
* @param numColumns
* Number of columns to use
* @return Created composite
*/
protected Composite doCreatePreviewPane(Composite composite, int numColumns) {
createLabel(numColumns, composite, FormatterMessages.ModifyDialogTabPage_preview_label_text);
final PHPPreview preview = doCreatePhpPreview(composite);
fDefaultFocusManager.add(preview.getControl());
final GridData gd = createGridData(numColumns, GridData.FILL_BOTH, 0);
gd.widthHint = 0;
gd.heightHint = 0;
preview.getControl().setLayoutData(gd);
return composite;
}
/**
* To be implemented by subclasses. This method should return an instance of
* JavaPreview. Currently, the choice is between CompilationUnitPreview
* which contains a valid compilation unit, or a SnippetPreview which
* formats several independent code snippets and displays them in the same
* window.
*
* @param parent
* Parent composite
* @return Created preview
*/
protected abstract PHPPreview doCreatePhpPreview(Composite parent);
/**
* This is called when the page becomes visible. Common tasks to do include:
* <ul>
* <li>Updating the preview.</li>
* <li>Setting the focus</li>
* </ul>
*/
final public void makeVisible() {
fDefaultFocusManager.resetFocus();
doUpdatePreview();
}
/**
* Update the preview. To be implemented by subclasses.
*/
protected abstract void doUpdatePreview();
/**
*
*/
protected abstract void updatePreferences();
protected void notifyValuesModified() {
fModifyDialog.valuesModified();
}
/**
* Each tab page should remember where its last focus was, and reset it
* correctly within this method. This method is only called after
* initialization on the first tab page to be displayed in order to restore
* the focus of the last session.
*/
public void setInitialFocus() {
if (fDefaultFocusManager.isUsed()) {
fDefaultFocusManager.restoreFocus();
}
}
/**
* Set the status field on the dialog. This can be used by tab pages to
* report inconsistent input. The OK button is disabled if the kind is
* IStatus.ERROR.
*
* @param status
* Status describing the current page error state
*/
protected void updateStatus(IStatus status) {
fModifyDialog.updateStatus(status);
}
/*
* Create a GridLayout with the default margin and spacing settings, as well
* as the specified number of columns.
*/
protected GridLayout createGridLayout(int numColumns, boolean margins) {
final GridLayout layout = new GridLayout(numColumns, false);
layout.verticalSpacing = fPixelConverter.convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing = fPixelConverter.convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
if (margins) {
layout.marginHeight = fPixelConverter.convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
layout.marginWidth = fPixelConverter.convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
} else {
layout.marginHeight = 0;
layout.marginWidth = 0;
}
return layout;
}
/*
* Convenience method to create a GridData.
*/
protected static GridData createGridData(int numColumns, int style, int widthHint) {
final GridData gd = new GridData(style);
gd.horizontalSpan = numColumns;
gd.widthHint = widthHint;
return gd;
}
/*
* Convenience method to create a label.
*/
protected static Label createLabel(int numColumns, Composite parent, String text) {
return createLabel(numColumns, parent, text, GridData.FILL_HORIZONTAL);
}
/*
* Convenience method to create a label
*/
protected static Label createLabel(int numColumns, Composite parent, String text, int gridDataStyle) {
final Label label = new Label(parent, SWT.WRAP);
label.setFont(parent.getFont());
label.setText(text);
label.setLayoutData(createGridData(numColumns, gridDataStyle, SWT.DEFAULT));
return label;
}
/*
* Convenience method to create a group
*/
protected Group createGroup(int numColumns, Composite parent, String text) {
final Group group = new Group(parent, SWT.NONE);
group.setFont(parent.getFont());
group.setLayoutData(createGridData(numColumns, GridData.FILL_HORIZONTAL, SWT.DEFAULT));
final GridLayout layout = new GridLayout(numColumns, false);
layout.verticalSpacing = fPixelConverter.convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing = fPixelConverter.convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
layout.marginHeight = fPixelConverter.convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
group.setLayout(layout);
group.setText(text);
return group;
}
/*
* Convenience method to create a NumberPreference. The widget is registered
* as a potential focus holder, and the default updater is added.
*/
protected NumberPreference createNumberPref(Composite composite, int numColumns, String name, int minValue,
int maxValue) {
final NumberPreference pref = new NumberPreference(composite, numColumns, name, minValue, maxValue);
fDefaultFocusManager.add(pref);
pref.addObserver(fUpdater);
return pref;
}
/*
* Convenience method to create a ComboPreference. The widget is registered
* as a potential focus holder, and the default updater is added.
*/
protected ComboPreference createComboPref(Composite composite, int numColumns, String name, String[] items) {
final ComboPreference pref = new ComboPreference(composite, numColumns, name, items);
fDefaultFocusManager.add(pref);
pref.addObserver(fUpdater);
return pref;
}
/*
* Convenience method to create a CheckboxPreference. The widget is
* registered as a potential focus holder, and the default updater is added.
*/
protected CheckboxPreference createCheckboxPref(Composite composite, int numColumns, String name) {
final CheckboxPreference pref = new CheckboxPreference(composite, numColumns, name);
fDefaultFocusManager.add(pref);
pref.addObserver(fUpdater);
return pref;
}
/*
* Convenience method to create a StringPreference. The widget is registered
* as a potential focus holder, and the default updater is added.
*
* @since 3.6
*/
protected StringPreference createStringPref(Composite composite, int numColumns, String name, String key,
IInputValidator inputValidator) {
StringPreference pref = new StringPreference(composite, numColumns, name, inputValidator);
fDefaultFocusManager.add(pref);
pref.addObserver(fUpdater);
return pref;
}
/*
* Create a nice phpdoc comment for some string.
*/
protected static String createPreviewHeader(String title) {
return "/**\n* " + title + "\n*/\n"; //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Layout used for the settings part. Makes sure to show scrollbars if
* necessary. The settings part needs to be layouted on resize.
*/
private static class PageLayout extends Layout {
private final ScrolledComposite fContainer;
private final int fMinimalWidth;
private final int fMinimalHight;
private PageLayout(ScrolledComposite container, int minimalWidth, int minimalHight) {
fContainer = container;
fMinimalWidth = minimalWidth;
fMinimalHight = minimalHight;
}
@Override
public Point computeSize(Composite composite, int wHint, int hHint, boolean force) {
if (wHint != SWT.DEFAULT && hHint != SWT.DEFAULT) {
return new Point(wHint, hHint);
}
int x = fMinimalWidth;
int y = fMinimalHight;
Control[] children = composite.getChildren();
for (int i = 0; i < children.length; i++) {
Point size = children[i].computeSize(SWT.DEFAULT, SWT.DEFAULT, force);
x = Math.max(x, size.x);
y = Math.max(y, size.y);
}
Rectangle area = fContainer.getClientArea();
if (area.width > x) {
fContainer.setExpandHorizontal(true);
} else {
fContainer.setExpandHorizontal(false);
}
if (area.height > y) {
fContainer.setExpandVertical(true);
} else {
fContainer.setExpandVertical(false);
}
if (wHint != SWT.DEFAULT) {
x = wHint;
}
if (hHint != SWT.DEFAULT) {
y = hHint;
}
return new Point(x, y);
}
@Override
public void layout(Composite composite, boolean force) {
Rectangle rect = composite.getClientArea();
Control[] children = composite.getChildren();
for (int i = 0; i < children.length; i++) {
children[i].setSize(rect.width, rect.height);
}
}
}
}