| /******************************************************************************* |
| * 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$ |
| } |
| } |