blob: 632fb952b310e8ddc4b4ad2066f1eadc4d6d2e29 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2016 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.jdt.internal.ui.preferences.formatter;
import java.util.Objects;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Text;
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.jface.layout.PixelConverter;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.util.SWTUtil;
public abstract class ModifyDialogTabPage implements IModifyDialogTabPage {
/**
* 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) -> {
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 {
private final Map<String, String> fPreferences;
private boolean fEnabled;
private String fKey;
/**
* Create a new Preference.
* @param preferences The map where the value is written.
* @param key The key for which a value is managed.
*/
public Preference(Map<String, String> preferences, String key) {
fPreferences= preferences;
fEnabled= true;
fKey= key;
}
/**
* @return Gets the map of this Preference.
*/
protected final Map<String, String> getPreferences() {
return fPreferences;
}
/**
* Set the enabled state of all SWT widgets of this preference.
* @param enabled new value
*/
public final void setEnabled(boolean enabled) {
fEnabled= enabled;
updateWidget();
}
/**
* @return Gets the enabled state of all SWT widgets of this Preference.
*/
public final boolean getEnabled() {
return fEnabled;
}
/**
* Set the key which is used to store the value.
* @param key New value
*/
public final void setKey(String key) {
if (key == null || !fKey.equals(key)) {
fKey= key;
updateWidget();
}
}
/**
* @return Gets the currently used key which is used to store the value.
*/
public final String getKey() {
return fKey;
}
/**
* 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();
/**
* To be implemented in subclasses. Update the SWT widgets when the state
* of this object has changed (enabled, key, ...).
*/
protected abstract void updateWidget();
}
/**
* Wrapper around a checkbox and a label.
*/
protected class ButtonPreference extends Preference {
private final String[] fValues;
private final Button fCheckbox;
/**
* Create a new CheckboxPreference.
* @param composite The composite on which the SWT widgets are added.
* @param numColumns The number of columns in the composite's GridLayout.
* @param preferences The map to store the values.
* @param key The key to store the values.
* @param values An array of two elements indicating the values to store on unchecked/checked.
* @param text The label text for this Preference.
* @param style SWT style flag for the button
*/
public ButtonPreference(Composite composite, int numColumns,
Map<String, String> preferences, String key,
String [] values, String text, int style) {
super(preferences, key);
if (values == null || text == null)
throw new IllegalArgumentException(FormatterMessages.ModifyDialogTabPage_error_msg_values_text_unassigned);
fValues= values;
fCheckbox= new Button(composite, style);
fCheckbox.setText(text);
fCheckbox.setLayoutData(createGridData(numColumns, GridData.FILL_HORIZONTAL, SWT.DEFAULT));
fCheckbox.setFont(composite.getFont());
updateWidget();
fCheckbox.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
checkboxChecked(((Button)e.widget).getSelection());
}
});
}
protected void checkboxChecked(boolean state) {
getPreferences().put(getKey(), state ? fValues[1] : fValues[0]);
setChanged();
notifyObservers();
}
@Override
protected void updateWidget() {
if (getKey() != null) {
fCheckbox.setEnabled(getEnabled());
fCheckbox.setSelection(getChecked());
} else {
fCheckbox.setSelection(false);
fCheckbox.setEnabled(false);
}
}
public boolean getChecked() {
return fValues[1].equals(getPreferences().get(getKey()));
}
public void setChecked(boolean checked) {
getPreferences().put(getKey(), checked ? fValues[1] : fValues[0]);
updateWidget();
checkboxChecked(checked);
}
@Override
public Control getControl() {
return fCheckbox;
}
}
protected final class CheckboxPreference extends ButtonPreference {
public CheckboxPreference(Composite composite, int numColumns, Map<String, String> preferences, String key, String[] values, String text) {
super(composite, numColumns, preferences, key, values, text, SWT.CHECK);
}
}
protected final class RadioPreference extends ButtonPreference {
public RadioPreference(Composite composite, int numColumns, Map<String, String> preferences, String key, String[] values, String text) {
super(composite, numColumns, preferences, key, values, text, SWT.RADIO);
}
}
/**
* Wrapper around a Combo box.
*/
protected final class ComboPreference extends Preference {
private final String [] fItems;
private final String[] fValues;
private final Combo fCombo;
/**
* Create a new ComboPreference.
* @param composite The composite on which the SWT widgets are added.
* @param numColumns The number of columns in the composite's GridLayout.
* @param preferences The map to store the values.
* @param key The key to store the values.
* @param values An array of n elements indicating the values to store for each selection.
* @param text The label text for this Preference.
* @param items An array of n elements indicating the text to be written in the combo box.
*/
public ComboPreference(Composite composite, int numColumns,
Map<String, String> preferences, String key,
String [] values, String text, String [] items) {
super(preferences, key);
if (values == null || items == null || text == null)
throw new IllegalArgumentException(FormatterMessages.ModifyDialogTabPage_error_msg_values_items_text_unassigned);
fValues= values;
fItems= items;
createLabel(numColumns - 1, composite, text);
fCombo= new Combo(composite, SWT.SINGLE | SWT.READ_ONLY);
fCombo.setFont(composite.getFont());
SWTUtil.setDefaultVisibleItemCount(fCombo);
fCombo.setItems(items);
int max= 0;
for (String item : items) {
if (item.length() > max) {
max= item.length();
}
}
fCombo.setLayoutData(createGridData(1, GridData.HORIZONTAL_ALIGN_FILL, fCombo.computeSize(SWT.DEFAULT, SWT.DEFAULT).x));
updateWidget();
fCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
comboSelected(((Combo)e.widget).getSelectionIndex());
}
});
}
protected void comboSelected(int index) {
getPreferences().put(getKey(), fValues[index]);
setChanged();
notifyObservers(fValues[index]);
}
@Override
protected void updateWidget() {
if (getKey() != null) {
fCombo.setEnabled(getEnabled());
fCombo.setText(getSelectedItem());
} else {
fCombo.setText(""); //$NON-NLS-1$
fCombo.setEnabled(false);
}
}
public String getSelectedItem() {
final String selected= getPreferences().get(getKey());
for (int i= 0; i < fValues.length; i++) {
if (fValues[i].equals(selected)) {
return fItems[i];
}
}
return ""; //$NON-NLS-1$
}
public boolean hasValue(String value) {
return value.equals(getPreferences().get(getKey()));
}
@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 Label fNumberLabel;
private final Text fNumberText;
protected int fSelected;
protected int fOldSelected;
/**
* Create a new NumberPreference.
* @param composite The composite on which the SWT widgets are added.
* @param numColumns The number of columns in the composite's GridLayout.
* @param preferences The map to store the values.
* @param key The key to store the values.
* @param minValue The minimum value which is valid input.
* @param maxValue The maximum value which is valid input.
* @param text The label text for this Preference or {@code null} if none.
*/
public NumberPreference(Composite composite, int numColumns,
Map<String, String> preferences, String key,
int minValue, int maxValue, String text) {
super(preferences, key);
fNumberLabel= text == null ? null : 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;
updateWidget();
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, JavaPlugin.getPluginId(), 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) {
saveSelected();
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;
saveSelected();
}
}
}
private boolean validInput(String trimInput) {
int number;
try {
number= Integer.parseInt(trimInput);
} catch (NumberFormatException x) {
return false;
}
if (number < fMinValue) return false;
if (number > fMaxValue) return false;
return true;
}
private void saveSelected() {
getPreferences().put(getKey(), Integer.toString(fSelected));
setChanged();
notifyObservers();
}
@Override
protected void updateWidget() {
final boolean hasKey= getKey() != null;
if (fNumberLabel != null)
fNumberLabel.setEnabled(hasKey && getEnabled());
fNumberText.setEnabled(hasKey && getEnabled());
if (hasKey) {
String s= getPreferences().get(getKey());
try {
fSelected= Integer.parseInt(s);
} catch (NumberFormatException e) {
final String message= Messages.format(FormatterMessages.ModifyDialogTabPage_NumberPreference_error_invalid_key, getKey());
JavaPlugin.log(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.OK, message, e));
s= ""; //$NON-NLS-1$
}
fNumberText.setText(s);
} else {
fNumberText.setText(""); //$NON-NLS-1$
}
}
@Override
public Control getControl() {
return fNumberText;
}
}
/**
* Wrapper around a text field which requests a string input.
*
* @since 3.6
*/
protected final class StringPreference extends Preference {
/**
* Validates the input.
* <p>
* The default implementation declares all non-<code>null</code> values as valid.
* </p>
*
* @since 3.6
*/
protected class Validator {
boolean isValid(String input) {
return input != null;
}
}
private final Label fLabel;
private final Text fText;
private IInputValidator fInputValidator;
protected String fSelected;
protected String fOldSelected;
/**
* Creates a new <code>StringPreference</code>.
*
* @param composite the composite on which the SWT widgets are added.
* @param numColumns the number of columns in the composite's {@link GridLayout}
* @param preferences the map to store the values.
* @param key the key to store the values.
* @param text the label text for this Preference.
* @param inputValidator the input validator or <code>null</code> if none
*/
public StringPreference(Composite composite, int numColumns, Map<String, String> preferences, String key, String text, IInputValidator inputValidator) {
super(preferences, key);
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));
fText= new Text(composite, SWT.SINGLE | SWT.BORDER);
fText.setFont(composite.getFont());
final int length= 30;
fText.setLayoutData(createGridData(1, GridData.HORIZONTAL_ALIGN_BEGINNING, fPixelConverter.convertWidthInCharsToPixels(length)));
updateWidget();
fText.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
StringPreference.this.focusGained();
}
@Override
public void focusLost(FocusEvent e) {
StringPreference.this.focusLost();
}
});
fText.addModifyListener(e -> fieldModified());
}
private IStatus createErrorStatus(String errorText) {
return new Status(IStatus.ERROR, JavaPlugin.getPluginId(), 0, errorText, null);
}
protected void focusGained() {
fOldSelected= fSelected;
fText.setSelection(0, fText.getCharCount());
}
protected void focusLost() {
updateStatus(null);
final String input= fText.getText();
if (fInputValidator != null && fInputValidator.isValid(input) != null)
fSelected= fOldSelected;
else
fSelected= input;
if (!Objects.equals(fSelected, fOldSelected)) {
saveSelected();
fText.setText(fSelected);
}
}
protected void fieldModified() {
final String text= fText.getText();
final String errorText= fInputValidator != null ? fInputValidator.isValid(text) : null;
if (errorText == null) {
updateStatus(null);
if (!Objects.equals(fSelected, text)) {
fSelected= text;
saveSelected();
}
} else
updateStatus(createErrorStatus(errorText));
}
private void saveSelected() {
getPreferences().put(getKey(), fSelected);
setChanged();
notifyObservers();
}
@Override
protected void updateWidget() {
final boolean hasKey= getKey() != null;
fLabel.setEnabled(hasKey && getEnabled());
fText.setEnabled(hasKey && getEnabled());
if (hasKey) {
fSelected= getPreferences().get(getKey());
fText.setText(fSelected);
} else {
fText.setText(""); //$NON-NLS-1$
}
}
@Override
public Control getControl() {
return fText;
}
}
/**
* 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= JavaUI.ID_PLUGIN + "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= JavaPlugin.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);
}
}
/**
* 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 (Control c : children) {
Point size= c.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();
for (Control c : composite.getChildren()) {
c.setSize(rect.width, rect.height);
}
}
}
/**
* 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;
/**
* A pixel converter for layout calculations
*/
protected PixelConverter fPixelConverter;
/**
* The map where the current settings are stored.
*/
protected Map<String, String> fWorkingValues;
/**
* The modify dialog where we can display status messages.
*/
private IModifyDialogTabPage.IModificationListener fModifyListener;
/*
* Create a new <code>ModifyDialogTabPage</code>
*/
public ModifyDialogTabPage(IModifyDialogTabPage.IModificationListener modifyListener, Map<String, String> workingValues) {
fWorkingValues= workingValues;
fModifyListener= modifyListener;
fDefaultFocusManager= new DefaultFocusManager();
}
public ModifyDialogTabPage() {
fDefaultFocusManager= new DefaultFocusManager();
}
@Override
public void setWorkingValues(Map<String, String> workingValues) {
fWorkingValues= workingValues;
}
@Override
public void setModifyListener(IModifyDialogTabPage.IModificationListener modifyListener) {
fModifyListener= modifyListener;
}
/**
* 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
*/
@Override
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 allocated, 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 JavaPreview preview= doCreateJavaPreview(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 JavaPreview doCreateJavaPreview(Composite parent);
@Override
public final void makeVisible() {
fDefaultFocusManager.resetFocus();
doUpdatePreview();
}
/**
* Update the preview. To be implemented by subclasses.
*/
protected abstract void doUpdatePreview();
protected void notifyValuesModified() {
fModifyListener.valuesModified();
}
@Override
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) {
fModifyListener.updateStatus(status);
}
/*
* Factory methods to make GUI construction easier
*/
/*
* 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);
PixelConverter pixelConverter= new PixelConverter(parent);
label.setLayoutData(createGridData(numColumns, gridDataStyle, pixelConverter.convertHorizontalDLUsToPixels(150)));
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);
//layout.marginHeight= fPixelConverter.convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
//layout.marginWidth= fPixelConverter.convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
group.setLayout(layout);//createGridLayout(numColumns, true));
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, String key,
int minValue, int maxValue) {
final NumberPreference pref= new NumberPreference(composite, numColumns, fWorkingValues,
key, minValue, maxValue, 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, fWorkingValues, key, name, inputValidator);
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 key, String [] values, String [] items) {
final ComboPreference pref= new ComboPreference(composite, numColumns,
fWorkingValues, key, values, 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, String key,
String [] values) {
final CheckboxPreference pref= new CheckboxPreference(composite, numColumns,
fWorkingValues, key, values, name);
fDefaultFocusManager.add(pref);
pref.addObserver(fUpdater);
return pref;
}
protected RadioPreference createRadioPref(Composite composite, int numColumns, String name, String key,
String [] values) {
final RadioPreference pref= new RadioPreference(composite, numColumns,
fWorkingValues, key, values, name);
fDefaultFocusManager.add(pref);
pref.addObserver(fUpdater);
return pref;
}
/*
* Create a nice javadoc comment for some string.
*/
protected static String createPreviewHeader(String title) {
return "/**\n* " + title + "\n*/\n"; //$NON-NLS-1$ //$NON-NLS-2$
}
}