blob: 43dbe2c6d0d206402979fee0337496a2d7435ed1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2018 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Nicolaj Hoess <nicohoess@gmail.com> - Editor templates pref page: Allow to sort by column - https://bugs.eclipse.org/203722
*******************************************************************************/
package org.eclipse.ui.texteditor.templates;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.osgi.framework.FrameworkUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Cursor;
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.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.text.templates.TemplatePersistenceData;
import org.eclipse.text.templates.TemplateReaderWriter;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.commands.ActionHandler;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.StatusDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.BidiUtils;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnPixelData;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.jface.text.templates.ContextTypeRegistry;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateContextType;
import org.eclipse.jface.text.templates.TemplateException;
import org.eclipse.jface.text.templates.persistence.TemplateStore;
import org.eclipse.ui.ActiveShellExpression;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.internal.texteditor.NLSUtility;
import org.eclipse.ui.internal.texteditor.SWTUtil;
import org.eclipse.ui.internal.texteditor.TextEditorPlugin;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.ui.texteditor.IUpdate;
/**
* A template preference page allows configuration of the templates for an
* editor. It provides controls for adding, removing and changing templates as
* well as enablement, default management and an optional formatter preference.
* <p>
* Subclasses need to provide a {@link TemplateStore} and a
* {@link ContextTypeRegistry} and should set the preference store. They may
* optionally override {@link #isShowFormatterSetting()}.
* </p>
*
* @since 3.0
*/
public abstract class TemplatePreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
/**
* Dialog to edit a template. Clients will usually instantiate, but
* may also extend.
*
* @since 3.3
*/
protected static class EditTemplateDialog extends StatusDialog {
private class TextViewerAction extends Action implements IUpdate {
private int fOperationCode= -1;
private ITextOperationTarget fOperationTarget;
/**
* Creates a new action.
*
* @param viewer the viewer
* @param operationCode the opcode
*/
public TextViewerAction(ITextViewer viewer, int operationCode) {
fOperationCode= operationCode;
fOperationTarget= viewer.getTextOperationTarget();
update();
}
/**
* Updates the enabled state of the action.
* Fires a property change if the enabled state changes.
*
* @see Action#firePropertyChange(String, Object, Object)
*/
@Override
public void update() {
// XXX: workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=206111
if (fOperationCode == ITextOperationTarget.REDO || fOperationCode == ITextOperationTarget.REDO)
return;
boolean wasEnabled= isEnabled();
boolean isEnabled= (fOperationTarget != null && fOperationTarget.canDoOperation(fOperationCode));
setEnabled(isEnabled);
if (wasEnabled != isEnabled) {
firePropertyChange(ENABLED, wasEnabled ? Boolean.TRUE : Boolean.FALSE, isEnabled ? Boolean.TRUE : Boolean.FALSE);
}
}
/**
* @see Action#run()
*/
@Override
public void run() {
if (fOperationCode != -1 && fOperationTarget != null) {
fOperationTarget.doOperation(fOperationCode);
}
}
}
private final Template fOriginalTemplate;
private Text fNameText;
private Text fDescriptionText;
private Combo fContextCombo;
private SourceViewer fPatternEditor;
private Button fInsertVariableButton;
private Button fAutoInsertCheckbox;
private boolean fIsNameModifiable;
private StatusInfo fValidationStatus;
private boolean fSuppressError= true; // #4354
private Map<String, TextViewerAction> fGlobalActions= new HashMap<>(10);
private List<String> fSelectionActions = new ArrayList<>(3);
private String[][] fContextTypes;
private ContextTypeRegistry fContextTypeRegistry;
private final TemplateVariableProcessor fTemplateProcessor= new TemplateVariableProcessor();
private Template fNewTemplate;
/**
* Creates a new dialog.
*
* @param parent the shell parent of the dialog
* @param template the template to edit
* @param edit whether this is a new template or an existing being edited
* @param isNameModifiable whether the name of the template may be modified
* @param registry the context type registry to use
*/
public EditTemplateDialog(Shell parent, Template template, boolean edit, boolean isNameModifiable, ContextTypeRegistry registry) {
super(parent);
String title= edit
? TemplatesMessages.EditTemplateDialog_title_edit
: TemplatesMessages.EditTemplateDialog_title_new;
setTitle(title);
fOriginalTemplate= template;
fIsNameModifiable= isNameModifiable;
List<String[]> contexts= new ArrayList<>();
for (Iterator<TemplateContextType> it= registry.contextTypes(); it.hasNext();) {
TemplateContextType type= it.next();
contexts.add(new String[] { type.getId(), type.getName() });
}
Collections.sort(contexts, new Comparator<String[]>() {
Collator fCollator= Collator.getInstance();
@Override
public int compare(String[] o1, String[] o2) {
return fCollator.compare(o1[1], o2[1]);
}
});
fContextTypes= contexts.toArray(new String[contexts.size()][]);
fValidationStatus= new StatusInfo();
fContextTypeRegistry= registry;
TemplateContextType type= fContextTypeRegistry.getContextType(template.getContextTypeId());
fTemplateProcessor.setContextType(type);
}
@Override
protected boolean isResizable() {
return true;
}
@Override
public void create() {
super.create();
// update initial OK button to be disabled for new templates
boolean valid= fNameText == null || !fNameText.getText().trim().isEmpty();
if (!valid) {
StatusInfo status = new StatusInfo();
status.setError(TemplatesMessages.EditTemplateDialog_error_noname);
updateButtonsEnableState(status);
}
}
@Override
protected Control createDialogArea(Composite ancestor) {
Composite parent= new Composite(ancestor, SWT.NONE);
GridLayout layout= new GridLayout();
layout.numColumns= 2;
layout.marginHeight= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
layout.verticalSpacing= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
parent.setLayout(layout);
parent.setLayoutData(new GridData(GridData.FILL_BOTH));
ModifyListener listener = e -> doTextWidgetChanged(e.widget);
if (fIsNameModifiable) {
createLabel(parent, TemplatesMessages.EditTemplateDialog_name);
Composite composite= new Composite(parent, SWT.NONE);
composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
layout= new GridLayout();
layout.numColumns= 4;
layout.marginWidth= 0;
layout.marginHeight= 0;
composite.setLayout(layout);
fNameText= createText(composite);
fNameText.addModifyListener(listener);
fNameText.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
}
@Override
public void focusLost(FocusEvent e) {
if (fSuppressError) {
fSuppressError= false;
updateButtons();
}
}
});
BidiUtils.applyBidiProcessing(fNameText, BidiUtils.BTD_DEFAULT);
createLabel(composite, TemplatesMessages.EditTemplateDialog_context);
fContextCombo= new Combo(composite, SWT.READ_ONLY);
for (String[] fContextType : fContextTypes) {
fContextCombo.add(fContextType[1]);
}
fContextCombo.addModifyListener(listener);
SWTUtil.setDefaultVisibleItemCount(fContextCombo);
fAutoInsertCheckbox= createCheckbox(composite, TemplatesMessages.EditTemplateDialog_autoinsert);
fAutoInsertCheckbox.setSelection(fOriginalTemplate.isAutoInsertable());
}
createLabel(parent, TemplatesMessages.EditTemplateDialog_description);
int descFlags= fIsNameModifiable ? SWT.BORDER : SWT.BORDER | SWT.READ_ONLY;
fDescriptionText= new Text(parent, descFlags );
fDescriptionText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fDescriptionText.addModifyListener(listener);
BidiUtils.applyBidiProcessing(fDescriptionText, BidiUtils.BTD_DEFAULT);
Label patternLabel= createLabel(parent, TemplatesMessages.EditTemplateDialog_pattern);
patternLabel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
fPatternEditor= createEditor(parent, fOriginalTemplate.getPattern());
Label filler= new Label(parent, SWT.NONE);
filler.setLayoutData(new GridData());
Composite composite= new Composite(parent, SWT.NONE);
layout= new GridLayout();
layout.marginWidth= 0;
layout.marginHeight= 0;
composite.setLayout(layout);
composite.setLayoutData(new GridData());
fInsertVariableButton= new Button(composite, SWT.NONE);
fInsertVariableButton.setLayoutData(getButtonGridData(fInsertVariableButton));
fInsertVariableButton.setText(TemplatesMessages.EditTemplateDialog_insert_variable);
fInsertVariableButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
fPatternEditor.getTextWidget().setFocus();
fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {}
});
fDescriptionText.setText(fOriginalTemplate.getDescription());
if (fIsNameModifiable) {
fNameText.setText(fOriginalTemplate.getName());
fNameText.addModifyListener(listener);
fContextCombo.select(getIndex(fOriginalTemplate.getContextTypeId()));
} else {
fPatternEditor.getControl().setFocus();
}
initializeActions();
applyDialogFont(parent);
return composite;
}
private void doTextWidgetChanged(Widget w) {
if (w == fNameText) {
fSuppressError= false;
updateButtons();
} else if (w == fContextCombo) {
String contextId= getContextId();
fTemplateProcessor.setContextType(fContextTypeRegistry.getContextType(contextId));
} else if (w == fDescriptionText) {
// oh, nothing
}
}
private String getContextId() {
if (fContextCombo != null && !fContextCombo.isDisposed()) {
String name= fContextCombo.getText();
for (String[] fContextType : fContextTypes) {
if (name.equals(fContextType[1])) {
return fContextType[0];
}
}
}
return fOriginalTemplate.getContextTypeId();
}
private void doSourceChanged(IDocument document) {
String text= document.get();
fValidationStatus.setOK();
TemplateContextType contextType= fContextTypeRegistry.getContextType(getContextId());
if (contextType != null) {
try {
contextType.validate(text);
} catch (TemplateException e) {
fValidationStatus.setError(e.getLocalizedMessage());
}
}
updateAction(ITextEditorActionConstants.UNDO);
updateButtons();
}
/**
* Return the grid data for the button.
*
* @param button the button
* @return the grid data
*/
private static GridData getButtonGridData(Button button) {
GridData data= new GridData(GridData.FILL_HORIZONTAL);
// TODO get some button hints.
// data.heightHint= SWTUtil.getButtonHeightHint(button);
return data;
}
private static Label createLabel(Composite parent, String name) {
Label label= new Label(parent, SWT.NULL);
label.setText(name);
label.setLayoutData(new GridData());
return label;
}
private static Text createText(Composite parent) {
Text text= new Text(parent, SWT.BORDER);
text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
return text;
}
private static Button createCheckbox(Composite parent, String name) {
Button button= new Button(parent, SWT.CHECK);
button.setText(name);
button.setLayoutData(new GridData());
return button;
}
private SourceViewer createEditor(Composite parent, String pattern) {
SourceViewer viewer= createViewer(parent);
viewer.setEditable(true);
IDocument document= viewer.getDocument();
if (document != null)
document.set(pattern);
else {
document= new Document(pattern);
viewer.setDocument(document);
}
int nLines= document.getNumberOfLines();
if (nLines < 5) {
nLines= 5;
} else if (nLines > 12) {
nLines= 12;
}
Control control= viewer.getControl();
GridData data= new GridData(GridData.FILL_BOTH);
data.widthHint= convertWidthInCharsToPixels(80);
data.heightHint= convertHeightInCharsToPixels(nLines);
control.setLayoutData(data);
viewer.addTextListener(event -> {
if (event.getDocumentEvent() != null)
doSourceChanged(event.getDocumentEvent().getDocument());
});
viewer.addSelectionChangedListener(event -> updateSelectionDependentActions());
return viewer;
}
/**
* Creates the viewer to be used to display the pattern. Subclasses may override.
*
* @param parent the parent composite of the viewer
* @return a configured <code>SourceViewer</code>
*/
protected SourceViewer createViewer(Composite parent) {
SourceViewer viewer= new SourceViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
SourceViewerConfiguration configuration= new SourceViewerConfiguration() {
@Override
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
ContentAssistant assistant= new ContentAssistant();
assistant.enableAutoActivation(true);
assistant.enableAutoInsert(true);
assistant.setContentAssistProcessor(fTemplateProcessor, IDocument.DEFAULT_CONTENT_TYPE);
return assistant;
}
};
viewer.configure(configuration);
return viewer;
}
private void initializeActions() {
final ArrayList<IHandlerActivation> handlerActivations= new ArrayList<>(3);
final IHandlerService handlerService= PlatformUI.getWorkbench().getAdapter(IHandlerService.class);
final Expression expression= new ActiveShellExpression(fPatternEditor.getControl().getShell());
getShell().addDisposeListener(e -> handlerService.deactivateHandlers(handlerActivations));
fPatternEditor.getTextWidget().addFocusListener(new FocusListener() {
@Override
public void focusLost(FocusEvent e) {
handlerService.deactivateHandlers(handlerActivations);
}
@Override
public void focusGained(FocusEvent e) {
IAction action= fGlobalActions.get(ITextEditorActionConstants.REDO);
handlerActivations.add(handlerService.activateHandler(IWorkbenchCommandConstants.EDIT_REDO, new ActionHandler(action), expression));
action= fGlobalActions.get(ITextEditorActionConstants.UNDO);
handlerActivations.add(handlerService.activateHandler(IWorkbenchCommandConstants.EDIT_UNDO, new ActionHandler(action), expression));
action= fGlobalActions.get(ITextEditorActionConstants.CONTENT_ASSIST);
handlerActivations.add(handlerService.activateHandler(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS, new ActionHandler(action), expression));
}
});
TextViewerAction action= new TextViewerAction(fPatternEditor, ITextOperationTarget.UNDO);
action.setText(TemplatesMessages.EditTemplateDialog_undo);
fGlobalActions.put(ITextEditorActionConstants.UNDO, action);
action= new TextViewerAction(fPatternEditor, ITextOperationTarget.REDO);
action.setText(TemplatesMessages.EditTemplateDialog_redo);
fGlobalActions.put(ITextEditorActionConstants.REDO, action);
action= new TextViewerAction(fPatternEditor, ITextOperationTarget.CUT);
action.setText(TemplatesMessages.EditTemplateDialog_cut);
fGlobalActions.put(ITextEditorActionConstants.CUT, action);
action= new TextViewerAction(fPatternEditor, ITextOperationTarget.COPY);
action.setText(TemplatesMessages.EditTemplateDialog_copy);
fGlobalActions.put(ITextEditorActionConstants.COPY, action);
action= new TextViewerAction(fPatternEditor, ITextOperationTarget.PASTE);
action.setText(TemplatesMessages.EditTemplateDialog_paste);
fGlobalActions.put(ITextEditorActionConstants.PASTE, action);
action= new TextViewerAction(fPatternEditor, ITextOperationTarget.SELECT_ALL);
action.setText(TemplatesMessages.EditTemplateDialog_select_all);
fGlobalActions.put(ITextEditorActionConstants.SELECT_ALL, action);
action= new TextViewerAction(fPatternEditor, ISourceViewer.CONTENTASSIST_PROPOSALS);
action.setText(TemplatesMessages.EditTemplateDialog_content_assist);
fGlobalActions.put(ITextEditorActionConstants.CONTENT_ASSIST, action);
fSelectionActions.add(ITextEditorActionConstants.CUT);
fSelectionActions.add(ITextEditorActionConstants.COPY);
fSelectionActions.add(ITextEditorActionConstants.PASTE);
// create context menu
MenuManager manager= new MenuManager(null, null);
manager.setRemoveAllWhenShown(true);
manager.addMenuListener(this::fillContextMenu);
StyledText text= fPatternEditor.getTextWidget();
Menu menu= manager.createContextMenu(text);
text.setMenu(menu);
}
private void fillContextMenu(IMenuManager menu) {
menu.add(new GroupMarker(ITextEditorActionConstants.GROUP_UNDO));
menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, fGlobalActions.get(ITextEditorActionConstants.UNDO));
menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, fGlobalActions.get(ITextEditorActionConstants.REDO));
menu.add(new Separator(ITextEditorActionConstants.GROUP_EDIT));
menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, fGlobalActions.get(ITextEditorActionConstants.CUT));
menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, fGlobalActions.get(ITextEditorActionConstants.COPY));
menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, fGlobalActions.get(ITextEditorActionConstants.PASTE));
menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, fGlobalActions.get(ITextEditorActionConstants.SELECT_ALL));
menu.add(new Separator("templates")); //$NON-NLS-1$
menu.appendToGroup("templates", fGlobalActions.get("ContentAssistProposal")); //$NON-NLS-1$ //$NON-NLS-2$
}
private void updateSelectionDependentActions() {
Iterator<String> iterator= fSelectionActions.iterator();
while (iterator.hasNext())
updateAction(iterator.next());
}
private void updateAction(String actionId) {
IAction action= fGlobalActions.get(actionId);
if (action instanceof IUpdate)
((IUpdate) action).update();
}
private int getIndex(String contextid) {
if (contextid == null)
return -1;
for (int i= 0; i < fContextTypes.length; i++) {
if (contextid.equals(fContextTypes[i][0])) {
return i;
}
}
return -1;
}
private void updateButtons() {
StatusInfo status;
boolean valid= fNameText == null || !fNameText.getText().trim().isEmpty();
if (!valid) {
status = new StatusInfo();
if (!fSuppressError)
status.setError(TemplatesMessages.EditTemplateDialog_error_noname);
} else if (!isValidPattern(fPatternEditor.getDocument().get())) {
status = new StatusInfo();
if (!fSuppressError)
status.setError(TemplatesMessages.EditTemplateDialog_error_invalidPattern);
} else {
status= fValidationStatus;
}
updateStatus(status);
}
/**
* Validates the pattern.
* <p>
* The default implementation rejects invalid XML characters.
* </p>
*
* @param pattern the pattern to verify
* @return <code>true</code> if the pattern is valid
* @since 3.7 protected, before it was private
*/
protected boolean isValidPattern(String pattern) {
for (int i= 0; i < pattern.length(); i++) {
char ch= pattern.charAt(i);
if (!(ch == 9 || ch == 10 || ch == 13 || ch >= 32))
return false;
}
return true;
}
/*
* @since 3.1
*/
@Override
protected void okPressed() {
String name= fNameText == null ? fOriginalTemplate.getName() : fNameText.getText();
boolean isAutoInsertable= fAutoInsertCheckbox != null && fAutoInsertCheckbox.getSelection();
fNewTemplate= new Template(name, fDescriptionText.getText(), getContextId(), fPatternEditor.getDocument().get(), isAutoInsertable);
super.okPressed();
}
/**
* Returns the created template.
*
* @return the created template
* @since 3.1
*/
public Template getTemplate() {
return fNewTemplate;
}
/**
* Returns the content assist processor that
* suggests template variables.
*
* @return the processor to suggest variables
* @since 3.3
*/
protected IContentAssistProcessor getTemplateProcessor() {
return fTemplateProcessor;
}
@Override
protected IDialogSettings getDialogBoundsSettings() {
String sectionName= getClass().getName() + "_dialogBounds"; //$NON-NLS-1$
IDialogSettings settings = PlatformUI
.getDialogSettingsProvider(FrameworkUtil.getBundle(TemplatePreferencePage.class))
.getDialogSettings();
IDialogSettings section= settings.getSection(sectionName);
if (section == null)
section= settings.addNewSection(sectionName);
return section;
}
}
/**
* Label provider for templates.
*/
private class TemplateLabelProvider extends LabelProvider implements ITableLabelProvider {
@Override
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
@Override
public String getColumnText(Object element, int columnIndex) {
TemplatePersistenceData data = (TemplatePersistenceData) element;
Template template= data.getTemplate();
switch (columnIndex) {
case 0:
return template.getName();
case 1:
TemplateContextType type= fContextTypeRegistry.getContextType(template.getContextTypeId());
if (type != null)
return type.getName();
return template.getContextTypeId();
case 2:
return template.getDescription();
case 3:
return template.isAutoInsertable() ? TemplatesMessages.TemplatePreferencePage_on : ""; //$NON-NLS-1$
default:
return ""; //$NON-NLS-1$
}
}
}
/** Qualified key for formatter preference. */
private static final String DEFAULT_FORMATTER_PREFERENCE_KEY= "org.eclipse.ui.texteditor.templates.preferences.format_templates"; //$NON-NLS-1$
/** The table presenting the templates. */
private CheckboxTableViewer fTableViewer;
/* buttons */
private Button fAddButton;
private Button fEditButton;
private Button fImportButton;
private Button fExportButton;
private Button fRemoveButton;
private Button fRestoreButton;
private Button fRevertButton;
/** The viewer displays the pattern of selected template. */
private SourceViewer fPatternViewer;
/** Format checkbox. This gets conditionally added. */
private Button fFormatButton;
/** The store for our templates. */
private TemplateStore fTemplateStore;
/** The context type registry. */
private ContextTypeRegistry fContextTypeRegistry;
/**
* Creates a new template preference page.
*/
protected TemplatePreferencePage() {
super();
setDescription(TemplatesMessages.TemplatePreferencePage_message);
}
/**
* Returns the template store.
*
* @return the template store
*/
public TemplateStore getTemplateStore() {
return fTemplateStore;
}
/**
* Returns the context type registry.
*
* @return the context type registry
*/
public ContextTypeRegistry getContextTypeRegistry() {
return fContextTypeRegistry;
}
/**
* Sets the template store.
*
* @param store the new template store
*/
public void setTemplateStore(TemplateStore store) {
fTemplateStore= store;
}
/**
* Sets the context type registry.
*
* @param registry the new context type registry
*/
public void setContextTypeRegistry(ContextTypeRegistry registry) {
fContextTypeRegistry= registry;
}
@Override
public void init(IWorkbench workbench) {
}
@Override
protected Control createContents(Composite ancestor) {
Composite parent= new Composite(ancestor, SWT.NONE);
GridLayout layout= new GridLayout();
layout.numColumns= 2;
layout.marginHeight= 0;
layout.marginWidth= 0;
parent.setLayout(layout);
Composite innerParent= new Composite(parent, SWT.NONE);
GridLayout innerLayout= new GridLayout();
innerLayout.numColumns= 2;
innerLayout.marginHeight= 0;
innerLayout.marginWidth= 0;
innerParent.setLayout(innerLayout);
GridData gd= new GridData(GridData.FILL_BOTH);
gd.horizontalSpan= 2;
innerParent.setLayoutData(gd);
Composite tableComposite= new Composite(innerParent, SWT.NONE);
GridData data= new GridData(GridData.FILL_BOTH);
data.widthHint= 360;
data.heightHint= convertHeightInCharsToPixels(10);
tableComposite.setLayoutData(data);
ColumnLayout columnLayout= new ColumnLayout();
tableComposite.setLayout(columnLayout);
Table table= new Table(tableComposite, SWT.CHECK | SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL);
table.setHeaderVisible(true);
table.setLinesVisible(true);
GC gc= new GC(getShell());
gc.setFont(JFaceResources.getDialogFont());
TemplateViewerComparator viewerComparator= new TemplateViewerComparator();
TableColumn column1= new TableColumn(table, SWT.NONE);
column1.setText(TemplatesMessages.TemplatePreferencePage_column_name);
int minWidth= computeMinimumColumnWidth(gc, TemplatesMessages.TemplatePreferencePage_column_name);
columnLayout.addColumnData(new ColumnWeightData(2, minWidth, true));
column1.addSelectionListener(new TemplateColumnSelectionAdapter(column1, 0, viewerComparator));
TableColumn column2= new TableColumn(table, SWT.NONE);
column2.setText(TemplatesMessages.TemplatePreferencePage_column_context);
minWidth= computeMinimumContextColumnWidth(gc);
columnLayout.addColumnData(new ColumnWeightData(1, minWidth, true));
column2.addSelectionListener(new TemplateColumnSelectionAdapter(column2, 1, viewerComparator));
TableColumn column3= new TableColumn(table, SWT.NONE);
column3.setText(TemplatesMessages.TemplatePreferencePage_column_description);
minWidth= computeMinimumColumnWidth(gc, TemplatesMessages.TemplatePreferencePage_column_description);
columnLayout.addColumnData(new ColumnWeightData(3, minWidth, true));
column3.addSelectionListener(new TemplateColumnSelectionAdapter(column3, 2, viewerComparator));
TableColumn column4= new TableColumn(table, SWT.NONE);
column4.setAlignment(SWT.CENTER);
column4.setText(TemplatesMessages.TemplatePreferencePage_column_autoinsert);
minWidth= computeMinimumColumnWidth(gc, TemplatesMessages.TemplatePreferencePage_column_autoinsert);
minWidth= Math.max(minWidth, computeMinimumColumnWidth(gc, TemplatesMessages.TemplatePreferencePage_on));
columnLayout.addColumnData(new ColumnPixelData(minWidth, false, false));
column4.addSelectionListener(new TemplateColumnSelectionAdapter(column4, 3, viewerComparator));
gc.dispose();
fTableViewer= new CheckboxTableViewer(table);
fTableViewer.setLabelProvider(new TemplateLabelProvider());
fTableViewer.setContentProvider(new TemplateContentProvider());
fTableViewer.setComparator(viewerComparator);
// Specify default sorting
table.setSortColumn(column1);
table.setSortDirection(viewerComparator.getDirection());
fTableViewer.addDoubleClickListener(e -> edit());
fTableViewer.addSelectionChangedListener(e -> selectionChanged1());
fTableViewer.addCheckStateListener(event -> {
TemplatePersistenceData d = (TemplatePersistenceData) event.getElement();
d.setEnabled(event.getChecked());
});
BidiUtils.applyTextDirection(fTableViewer.getControl(), BidiUtils.BTD_DEFAULT);
Composite buttons= new Composite(innerParent, SWT.NONE);
buttons.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
layout= new GridLayout();
layout.marginHeight= 0;
layout.marginWidth= 0;
buttons.setLayout(layout);
fAddButton= new Button(buttons, SWT.PUSH);
fAddButton.setText(TemplatesMessages.TemplatePreferencePage_new);
fAddButton.setLayoutData(getButtonGridData(fAddButton));
fAddButton.addListener(SWT.Selection, e -> add());
fEditButton= new Button(buttons, SWT.PUSH);
fEditButton.setText(TemplatesMessages.TemplatePreferencePage_edit);
fEditButton.setLayoutData(getButtonGridData(fEditButton));
fEditButton.addListener(SWT.Selection, e -> edit());
fRemoveButton= new Button(buttons, SWT.PUSH);
fRemoveButton.setText(TemplatesMessages.TemplatePreferencePage_remove);
fRemoveButton.setLayoutData(getButtonGridData(fRemoveButton));
fRemoveButton.addListener(SWT.Selection, e -> remove());
createSeparator(buttons);
fRestoreButton= new Button(buttons, SWT.PUSH);
fRestoreButton.setText(TemplatesMessages.TemplatePreferencePage_restore);
fRestoreButton.setLayoutData(getButtonGridData(fRestoreButton));
fRestoreButton.addListener(SWT.Selection, e -> restoreDeleted());
fRevertButton= new Button(buttons, SWT.PUSH);
fRevertButton.setText(TemplatesMessages.TemplatePreferencePage_revert);
fRevertButton.setLayoutData(getButtonGridData(fRevertButton));
fRevertButton.addListener(SWT.Selection, e -> revert());
createSeparator(buttons);
fImportButton= new Button(buttons, SWT.PUSH);
fImportButton.setText(TemplatesMessages.TemplatePreferencePage_import);
fImportButton.setLayoutData(getButtonGridData(fImportButton));
fImportButton.addListener(SWT.Selection, e -> import_());
fExportButton= new Button(buttons, SWT.PUSH);
fExportButton.setText(TemplatesMessages.TemplatePreferencePage_export);
fExportButton.setLayoutData(getButtonGridData(fExportButton));
fExportButton.addListener(SWT.Selection, e -> export());
fPatternViewer= doCreateViewer(parent);
if (isShowFormatterSetting()) {
fFormatButton= new Button(parent, SWT.CHECK);
fFormatButton.setText(TemplatesMessages.TemplatePreferencePage_use_code_formatter);
GridData gd1= new GridData();
gd1.horizontalSpan= 2;
fFormatButton.setLayoutData(gd1);
fFormatButton.setSelection(getPreferenceStore().getBoolean(getFormatterPreferenceKey()));
}
fTableViewer.setInput(fTemplateStore);
fTableViewer.setAllChecked(false);
fTableViewer.setCheckedElements(getEnabledTemplates());
updateButtons();
Dialog.applyDialogFont(parent);
innerParent.layout();
return parent;
}
/*
* @since 3.2
*/
private int computeMinimumColumnWidth(GC gc, String string) {
return gc.stringExtent(string).x + 10; // pad 10 to accommodate table header trimmings
}
/*
* @since 3.4
*/
private int computeMinimumContextColumnWidth(GC gc) {
int width= gc.stringExtent(TemplatesMessages.TemplatePreferencePage_column_context).x;
Iterator<TemplateContextType> iter= getContextTypeRegistry().contextTypes();
while (iter.hasNext()) {
TemplateContextType contextType= iter.next();
width= Math.max(width, gc.stringExtent(contextType.getName()).x);
}
return width;
}
/**
* Creates a separator between buttons.
*
* @param parent the parent composite
* @return a separator
*/
private Label createSeparator(Composite parent) {
Label separator= new Label(parent, SWT.NONE);
separator.setVisible(false);
GridData gd= new GridData();
gd.horizontalAlignment= GridData.FILL;
gd.verticalAlignment= GridData.BEGINNING;
gd.heightHint= 4;
separator.setLayoutData(gd);
return separator;
}
/**
* Returns whether the formatter preference checkbox should be shown.
*
* @return <code>true</code> if the formatter preference checkbox should
* be shown, <code>false</code> otherwise
*/
protected boolean isShowFormatterSetting() {
return true;
}
private TemplatePersistenceData[] getEnabledTemplates() {
List<TemplatePersistenceData> enabled= new ArrayList<>();
TemplatePersistenceData[] datas= fTemplateStore.getTemplateData(false);
for (TemplatePersistenceData data : datas) {
if (data.isEnabled()) {
enabled.add(data);
}
}
return enabled.toArray(new TemplatePersistenceData[enabled.size()]);
}
private SourceViewer doCreateViewer(Composite parent) {
Label label= new Label(parent, SWT.NONE);
label.setText(TemplatesMessages.TemplatePreferencePage_preview);
GridData data= new GridData();
data.horizontalSpan= 2;
label.setLayoutData(data);
SourceViewer viewer= createViewer(parent);
viewer.setEditable(false);
Cursor arrowCursor= viewer.getTextWidget().getDisplay().getSystemCursor(SWT.CURSOR_ARROW);
viewer.getTextWidget().setCursor(arrowCursor);
// Don't set caret to 'null' as this causes https://bugs.eclipse.org/293263
// viewer.getTextWidget().setCaret(null);
Control control= viewer.getControl();
data= new GridData(GridData.FILL_BOTH);
data.horizontalSpan= 2;
data.heightHint= convertHeightInCharsToPixels(5);
control.setLayoutData(data);
return viewer;
}
/**
* Creates, configures and returns a source viewer to present the template
* pattern on the preference page. Clients may override to provide a custom
* source viewer featuring e.g. syntax coloring.
*
* @param parent the parent control
* @return a configured source viewer
*/
protected SourceViewer createViewer(Composite parent) {
SourceViewer viewer= new SourceViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
SourceViewerConfiguration configuration= new SourceViewerConfiguration();
viewer.configure(configuration);
IDocument document= new Document();
viewer.setDocument(document);
return viewer;
}
/**
* Return the grid data for the button.
*
* @param button the button
* @return the grid data
*/
private static GridData getButtonGridData(Button button) {
GridData data= new GridData(GridData.FILL_HORIZONTAL);
// TODO replace SWTUtil
// data.widthHint= SWTUtil.getButtonWidthHint(button);
// data.heightHint= SWTUtil.getButtonHeightHint(button);
return data;
}
private void selectionChanged1() {
updateViewerInput();
updateButtons();
}
/**
* Updates the pattern viewer.
*/
protected void updateViewerInput() {
IStructuredSelection selection = fTableViewer.getStructuredSelection();
if (selection.size() == 1) {
TemplatePersistenceData data= (TemplatePersistenceData) selection.getFirstElement();
Template template= data.getTemplate();
fPatternViewer.getDocument().set(template.getPattern());
} else {
fPatternViewer.getDocument().set(""); //$NON-NLS-1$
}
}
/**
* Updates the buttons.
*/
protected void updateButtons() {
IStructuredSelection selection = fTableViewer.getStructuredSelection();
int selectionCount= selection.size();
int itemCount= fTableViewer.getTable().getItemCount();
boolean canRestore= fTemplateStore.getTemplateData(true).length != fTemplateStore.getTemplateData(false).length;
boolean canRevert= false;
for (Iterator<?> it= selection.iterator(); it.hasNext();) {
TemplatePersistenceData data= (TemplatePersistenceData) it.next();
if (data.isModified()) {
canRevert= true;
break;
}
}
fEditButton.setEnabled(selectionCount == 1);
fExportButton.setEnabled(selectionCount > 0);
fRemoveButton.setEnabled(selectionCount > 0 && selectionCount <= itemCount);
fRestoreButton.setEnabled(canRestore);
fRevertButton.setEnabled(canRevert);
}
private void add() {
Iterator<TemplateContextType> it= fContextTypeRegistry.contextTypes();
if (it.hasNext()) {
Template template= new Template("", "", it.next().getId(), "", true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Template newTemplate= editTemplate(template, false, true);
if (newTemplate != null) {
TemplatePersistenceData data= new TemplatePersistenceData(newTemplate, true);
fTemplateStore.add(data);
fTableViewer.refresh();
fTableViewer.setChecked(data, true);
fTableViewer.setSelection(new StructuredSelection(data));
}
}
}
/**
* Creates the edit dialog. Subclasses may override this method to provide a
* custom dialog.
*
* @param template the template being edited
* @param edit whether the dialog should be editable
* @param isNameModifiable whether the template name may be modified
* @return an <code>EditTemplateDialog</code> which will be opened.
* @deprecated not called any longer as of 3.1 - use {@link #editTemplate(Template, boolean, boolean)}
*/
@Deprecated
protected Dialog createTemplateEditDialog(Template template, boolean edit, boolean isNameModifiable) {
return new EditTemplateDialog(getShell(), template, edit, isNameModifiable, fContextTypeRegistry);
}
/**
* Creates the edit dialog. Subclasses may override this method to provide a
* custom dialog.
*
* @param template the template being edited
* @param edit whether the dialog should be editable
* @param isNameModifiable whether the template name may be modified
* @return the created or modified template, or <code>null</code> if the edition failed
* @since 3.1
*/
protected Template editTemplate(Template template, boolean edit, boolean isNameModifiable) {
EditTemplateDialog dialog= new EditTemplateDialog(getShell(), template, edit, isNameModifiable, fContextTypeRegistry);
if (dialog.open() == Window.OK) {
return dialog.getTemplate();
}
return null;
}
private void edit() {
IStructuredSelection selection = fTableViewer.getStructuredSelection();
Object[] objects= selection.toArray();
if ((objects == null) || (objects.length != 1))
return;
TemplatePersistenceData data= (TemplatePersistenceData) selection.getFirstElement();
edit(data);
}
private void edit(TemplatePersistenceData data) {
Template oldTemplate= data.getTemplate();
Template newTemplate= editTemplate(new Template(oldTemplate), true, true);
if (newTemplate != null) {
if (!newTemplate.getName().equals(oldTemplate.getName()) &&
openCreateNewOrRenameDialog())
{
data= new TemplatePersistenceData(newTemplate, true);
fTemplateStore.add(data);
fTableViewer.refresh();
} else {
data.setTemplate(newTemplate);
fTableViewer.refresh(data);
}
selectionChanged1();
fTableViewer.setChecked(data, data.isEnabled());
fTableViewer.setSelection(new StructuredSelection(data));
}
}
private void import_() {
FileDialog dialog= new FileDialog(getShell());
dialog.setText(TemplatesMessages.TemplatePreferencePage_import_title);
dialog.setFilterExtensions(new String[] {TemplatesMessages.TemplatePreferencePage_import_extension});
String path= dialog.open();
if (path == null)
return;
try {
ArrayList<TemplatePersistenceData> selection= new ArrayList<>();
TemplateReaderWriter reader= new TemplateReaderWriter();
File file= new File(path);
if (file.exists()) {
try (InputStream input = new BufferedInputStream(new FileInputStream(file))) {
TemplatePersistenceData[] datas= reader.read(input, null);
for (TemplatePersistenceData data : datas) {
fTemplateStore.add(data);
String id= data.getId();
if (id == null) {
selection.add(data);
} else {
data= fTemplateStore.getTemplateData(id);
if (data != null) {
selection.add(data);
}
}
}
}
}
fTableViewer.refresh();
fTableViewer.setAllChecked(false);
fTableViewer.setCheckedElements(getEnabledTemplates());
fTableViewer.setSelection(new StructuredSelection(selection), true);
selectionChanged1();
} catch (FileNotFoundException e) {
openReadErrorDialog(e);
} catch (IOException e) {
openReadErrorDialog(e);
}
}
private void export() {
IStructuredSelection selection = fTableViewer.getStructuredSelection();
Object[] templates= selection.toArray();
TemplatePersistenceData[] datas= new TemplatePersistenceData[templates.length];
for (int i= 0; i != templates.length; i++)
datas[i]= (TemplatePersistenceData) templates[i];
export(datas);
}
private void export(TemplatePersistenceData[] templates) {
FileDialog dialog= new FileDialog(getShell(), SWT.SAVE);
dialog.setText(TemplatesMessages.TemplatePreferencePage_export_title);
dialog.setFilterExtensions(new String[] {TemplatesMessages.TemplatePreferencePage_export_extension});
dialog.setFileName(TemplatesMessages.TemplatePreferencePage_export_filename);
String path= dialog.open();
if (path == null)
return;
File file= new File(path);
if (file.isHidden()) {
String title= TemplatesMessages.TemplatePreferencePage_export_error_title;
String message= NLSUtility.format(TemplatesMessages.TemplatePreferencePage_export_error_hidden, file.getAbsolutePath());
MessageDialog.openError(getShell(), title, message);
return;
}
if (file.exists() && !file.canWrite()) {
String title= TemplatesMessages.TemplatePreferencePage_export_error_title;
String message= NLSUtility.format(TemplatesMessages.TemplatePreferencePage_export_error_canNotWrite, file.getAbsolutePath());
MessageDialog.openError(getShell(), title, message);
return;
}
if (!file.exists() || confirmOverwrite(file)) {
try (OutputStream output = new BufferedOutputStream(new FileOutputStream(file))) {
TemplateReaderWriter writer= new TemplateReaderWriter();
writer.save(templates, output);
} catch (IOException e) {
openWriteErrorDialog(e);
}
}
}
private boolean confirmOverwrite(File file) {
return MessageDialog.openQuestion(getShell(),
TemplatesMessages.TemplatePreferencePage_export_exists_title,
NLSUtility.format(TemplatesMessages.TemplatePreferencePage_export_exists_message, file.getAbsolutePath()));
}
private void remove() {
IStructuredSelection selection = fTableViewer.getStructuredSelection();
Iterator<?> elements= selection.iterator();
while (elements.hasNext()) {
TemplatePersistenceData data= (TemplatePersistenceData) elements.next();
fTemplateStore.delete(data);
}
fTableViewer.refresh();
}
private void restoreDeleted() {
TemplatePersistenceData[] oldTemplates= fTemplateStore.getTemplateData(false);
fTemplateStore.restoreDeleted();
TemplatePersistenceData[] newTemplates= fTemplateStore.getTemplateData(false);
fTableViewer.refresh();
fTableViewer.setCheckedElements(getEnabledTemplates());
ArrayList<TemplatePersistenceData> selection= new ArrayList<>();
selection.addAll(Arrays.asList(newTemplates));
selection.removeAll(Arrays.asList(oldTemplates));
fTableViewer.setSelection(new StructuredSelection(selection), true);
selectionChanged1();
}
private void revert() {
IStructuredSelection selection = fTableViewer.getStructuredSelection();
Iterator<?> elements= selection.iterator();
while (elements.hasNext()) {
TemplatePersistenceData data= (TemplatePersistenceData) elements.next();
data.revert();
fTableViewer.setChecked(data, data.isEnabled());
}
selectionChanged1();
fTableViewer.refresh();
}
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible)
setTitle(TemplatesMessages.TemplatePreferencePage_title);
}
@Override
protected void performDefaults() {
if (isShowFormatterSetting()) {
IPreferenceStore prefs= getPreferenceStore();
fFormatButton.setSelection(prefs.getDefaultBoolean(getFormatterPreferenceKey()));
}
fTemplateStore.restoreDefaults(false);
// refresh
fTableViewer.refresh();
fTableViewer.setAllChecked(false);
fTableViewer.setCheckedElements(getEnabledTemplates());
}
@Override
public boolean performOk() {
if (isShowFormatterSetting()) {
IPreferenceStore prefs= getPreferenceStore();
prefs.setValue(getFormatterPreferenceKey(), fFormatButton.getSelection());
}
try {
fTemplateStore.save();
} catch (IOException e) {
openWriteErrorDialog(e);
}
return super.performOk();
}
/**
* Returns the key to use for the formatter preference.
*
* @return the formatter preference key
*/
protected String getFormatterPreferenceKey() {
return DEFAULT_FORMATTER_PREFERENCE_KEY;
}
@Override
public boolean performCancel() {
try {
fTemplateStore.load();
} catch (IOException e) {
openReadErrorDialog(e);
return false;
}
return super.performCancel();
}
/*
* @since 3.2
*/
private void openReadErrorDialog(IOException ex) {
IStatus status= new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, IStatus.OK, "Failed to read templates.", ex); //$NON-NLS-1$
TextEditorPlugin.getDefault().getLog().log(status);
String title= TemplatesMessages.TemplatePreferencePage_error_read_title;
String message= TemplatesMessages.TemplatePreferencePage_error_read_message;
MessageDialog.openError(getShell(), title, message);
}
/*
* @since 3.2
*/
private void openWriteErrorDialog(IOException ex) {
IStatus status= new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, IStatus.OK, "Failed to write templates.", ex); //$NON-NLS-1$
TextEditorPlugin.getDefault().getLog().log(status);
String title= TemplatesMessages.TemplatePreferencePage_error_write_title;
String message= TemplatesMessages.TemplatePreferencePage_error_write_message;
MessageDialog.openError(getShell(), title, message);
}
private boolean openCreateNewOrRenameDialog() {
MessageDialog dialog = new MessageDialog(getShell(),
TemplatesMessages.TemplatePreferencePage_question_create_new_title, null,
TemplatesMessages.TemplatePreferencePage_question_create_new_message, MessageDialog.QUESTION, 0,
TemplatesMessages.TemplatePreferencePage_question_create_new_button_create,
TemplatesMessages.TemplatePreferencePage_question_create_new_button_rename);
return dialog.open() == 0;
}
protected SourceViewer getViewer() {
return fPatternViewer;
}
protected TableViewer getTableViewer() {
return fTableViewer;
}
private final class TemplateViewerComparator extends ViewerComparator {
private int fSortColumn;
private int fSortOrder; // 1 = asc, -1 = desc
public TemplateViewerComparator() {
fSortColumn= 0;
fSortOrder= 1;
}
/**
* Returns the {@linkplain SWT} style constant for the sort direction.
*
* @return {@link SWT#DOWN} for asc sorting, {@link SWT#UP} otherwise
*/
public int getDirection() {
return fSortOrder == 1 ? SWT.DOWN : SWT.UP;
}
/**
* Sets the sort column. If the newly set sort column equals the previous set sort column,
* the sort direction changes.
*
* @param column New sort column
*/
public void setColumn(int column) {
if (column == fSortColumn) {
fSortOrder*= -1;
} else {
fSortColumn= column;
fSortOrder= 1;
}
}
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
if (viewer instanceof TableViewer) {
IBaseLabelProvider baseLabel= ((TableViewer)viewer).getLabelProvider();
String left= ((TemplateLabelProvider)baseLabel).getColumnText(e1, fSortColumn);
String right= ((TemplateLabelProvider)baseLabel).getColumnText(e2, fSortColumn);
int sortResult= getComparator().compare(left, right);
return sortResult * fSortOrder;
}
return super.compare(viewer, e1, e2);
}
}
private final class TemplateColumnSelectionAdapter extends SelectionAdapter {
private final TableColumn fTableColumn;
private final int fColumnIndex;
private final TemplateViewerComparator fViewerComparator;
public TemplateColumnSelectionAdapter(TableColumn column, int index, TemplateViewerComparator vc) {
fTableColumn= column;
fColumnIndex= index;
fViewerComparator= vc;
}
@Override
public void widgetSelected(SelectionEvent e) {
fViewerComparator.setColumn(fColumnIndex);
int dir= fViewerComparator.getDirection();
fTableViewer.getTable().setSortDirection(dir);
fTableViewer.getTable().setSortColumn(fTableColumn);
fTableViewer.refresh();
}
}
}