blob: 3c62ac795f2bfa4cba8592dbf957777253590447 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.texteditor.templates;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.VerifyEvent;
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.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
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.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.Dialog;
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.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnPixelData;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
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.ITextListener;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.TextEvent;
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.TemplatePersistenceData;
import org.eclipse.jface.text.templates.persistence.TemplateReaderWriter;
import org.eclipse.jface.text.templates.persistence.TemplateStore;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.internal.texteditor.NLSUtility;
import org.eclipse.ui.internal.texteditor.TextEditorPlugin;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
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)
*/
public void update() {
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()
*/
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 fGlobalActions= new HashMap(10);
private List 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);
setShellStyle(getShellStyle() | SWT.MAX | SWT.RESIZE);
String title= edit
? TextEditorTemplateMessages.EditTemplateDialog_title_edit
: TextEditorTemplateMessages.EditTemplateDialog_title_new;
setTitle(title);
fOriginalTemplate= template;
fIsNameModifiable= isNameModifiable;
List contexts= new ArrayList();
for (Iterator it= registry.contextTypes(); it.hasNext();) {
TemplateContextType type= (TemplateContextType) it.next();
contexts.add(new String[] { type.getId(), type.getName() });
}
fContextTypes= (String[][]) contexts.toArray(new String[contexts.size()][]);
fValidationStatus= new StatusInfo();
fContextTypeRegistry= registry;
TemplateContextType type= fContextTypeRegistry.getContextType(template.getContextTypeId());
fTemplateProcessor.setContextType(type);
}
/*
* @see org.eclipse.ui.texteditor.templates.StatusDialog#create()
*/
public void create() {
super.create();
// update initial OK button to be disabled for new templates
boolean valid= fNameText == null || fNameText.getText().trim().length() != 0;
if (!valid) {
StatusInfo status = new StatusInfo();
status.setError(TextEditorTemplateMessages.EditTemplateDialog_error_noname);
updateButtonsEnableState(status);
}
}
/*
* @see Dialog#createDialogArea(Composite)
*/
protected Control createDialogArea(Composite ancestor) {
Composite parent= new Composite(ancestor, SWT.NONE);
GridLayout layout= new GridLayout();
layout.numColumns= 2;
parent.setLayout(layout);
parent.setLayoutData(new GridData(GridData.FILL_BOTH));
ModifyListener listener= new ModifyListener() {
public void modifyText(ModifyEvent e) {
doTextWidgetChanged(e.widget);
}
};
if (fIsNameModifiable) {
createLabel(parent, TextEditorTemplateMessages.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() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
if (fSuppressError) {
fSuppressError= false;
updateButtons();
}
}
});
createLabel(composite, TextEditorTemplateMessages.EditTemplateDialog_context);
fContextCombo= new Combo(composite, SWT.READ_ONLY);
for (int i= 0; i < fContextTypes.length; i++) {
fContextCombo.add(fContextTypes[i][1]);
}
fContextCombo.addModifyListener(listener);
fAutoInsertCheckbox= createCheckbox(composite, TextEditorTemplateMessages.EditTemplateDialog_autoinsert);
fAutoInsertCheckbox.setSelection(fOriginalTemplate.isAutoInsertable());
}
createLabel(parent, TextEditorTemplateMessages.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);
Label patternLabel= createLabel(parent, TextEditorTemplateMessages.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(TextEditorTemplateMessages.EditTemplateDialog_insert_variable);
fInsertVariableButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
fPatternEditor.getTextWidget().setFocus();
fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
}
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 (int i= 0; i < fContextTypes.length; i++) {
if (name.equals(fContextTypes[i][1])) {
return fContextTypes[i][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());
}
}
updateUndoAction();
updateButtons();
}
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(new ITextListener() {
public void textChanged(TextEvent event) {
if (event .getDocumentEvent() != null)
doSourceChanged(event.getDocumentEvent().getDocument());
}
});
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
updateSelectionDependentActions();
}
});
viewer.prependVerifyKeyListener(new VerifyKeyListener() {
public void verifyKey(VerifyEvent event) {
handleVerifyKeyPressed(event);
}
});
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() {
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 handleVerifyKeyPressed(VerifyEvent event) {
if (!event.doit)
return;
if (event.stateMask != SWT.MOD1)
return;
switch (event.character) {
case ' ':
fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
event.doit= false;
break;
// CTRL-Z
case 'z' - 'a' + 1:
fPatternEditor.doOperation(ITextOperationTarget.UNDO);
event.doit= false;
break;
}
}
private void initializeActions() {
TextViewerAction action= new TextViewerAction(fPatternEditor, ITextOperationTarget.UNDO);
action.setText(TextEditorTemplateMessages.EditTemplateDialog_undo);
fGlobalActions.put(ITextEditorActionConstants.UNDO, action);
action= new TextViewerAction(fPatternEditor, ITextOperationTarget.CUT);
action.setText(TextEditorTemplateMessages.EditTemplateDialog_cut);
fGlobalActions.put(ITextEditorActionConstants.CUT, action);
action= new TextViewerAction(fPatternEditor, ITextOperationTarget.COPY);
action.setText(TextEditorTemplateMessages.EditTemplateDialog_copy);
fGlobalActions.put(ITextEditorActionConstants.COPY, action);
action= new TextViewerAction(fPatternEditor, ITextOperationTarget.PASTE);
action.setText(TextEditorTemplateMessages.EditTemplateDialog_paste);
fGlobalActions.put(ITextEditorActionConstants.PASTE, action);
action= new TextViewerAction(fPatternEditor, ITextOperationTarget.SELECT_ALL);
action.setText(TextEditorTemplateMessages.EditTemplateDialog_select_all);
fGlobalActions.put(ITextEditorActionConstants.SELECT_ALL, action);
action= new TextViewerAction(fPatternEditor, ISourceViewer.CONTENTASSIST_PROPOSALS);
action.setText(TextEditorTemplateMessages.EditTemplateDialog_content_assist);
fGlobalActions.put("ContentAssistProposal", action); //$NON-NLS-1$
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(new IMenuListener() {
public void menuAboutToShow(IMenuManager mgr) {
fillContextMenu(mgr);
}
});
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, (IAction) fGlobalActions.get(ITextEditorActionConstants.UNDO));
menu.add(new Separator(ITextEditorActionConstants.GROUP_EDIT));
menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.CUT));
menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.COPY));
menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.PASTE));
menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.SELECT_ALL));
menu.add(new Separator("templates")); //$NON-NLS-1$
menu.appendToGroup("templates", (IAction) fGlobalActions.get("ContentAssistProposal")); //$NON-NLS-1$ //$NON-NLS-2$
}
private void updateSelectionDependentActions() {
Iterator iterator= fSelectionActions.iterator();
while (iterator.hasNext())
updateAction((String)iterator.next());
}
private void updateUndoAction() {
IAction action= (IAction) fGlobalActions.get(ITextEditorActionConstants.UNDO);
if (action instanceof IUpdate)
((IUpdate) action).update();
}
private void updateAction(String actionId) {
IAction action= (IAction) 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().length() != 0;
if (!valid) {
status = new StatusInfo();
if (!fSuppressError) {
status.setError(TextEditorTemplateMessages.EditTemplateDialog_error_noname);
}
} else {
status= fValidationStatus;
}
updateStatus(status);
}
/*
* @since 3.1
*/
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;
}
/*
* @see org.eclipse.jface.dialogs.Dialog#getDialogBoundsSettings()
* @since 3.2
*/
protected IDialogSettings getDialogBoundsSettings() {
String sectionName= getClass().getName() + "_dialogBounds"; //$NON-NLS-1$
IDialogSettings settings= TextEditorPlugin.getDefault().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 {
/*
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
*/
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
/*
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
*/
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() ? TextEditorTemplateMessages.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(TextEditorTemplateMessages.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;
}
/*
* @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
*/
public void init(IWorkbench workbench) {
}
/*
* @see PreferencePage#createContents(Composite)
*/
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());
TableColumn column1= new TableColumn(table, SWT.NONE);
column1.setText(TextEditorTemplateMessages.TemplatePreferencePage_column_name);
int minWidth= computeMinimumColumnWidth(gc, TextEditorTemplateMessages.TemplatePreferencePage_column_name);
columnLayout.addColumnData(new ColumnWeightData(2, minWidth, true));
TableColumn column2= new TableColumn(table, SWT.NONE);
column2.setText(TextEditorTemplateMessages.TemplatePreferencePage_column_context);
minWidth= computeMinimumColumnWidth(gc, TextEditorTemplateMessages.TemplatePreferencePage_column_context);
columnLayout.addColumnData(new ColumnWeightData(1, minWidth, true));
TableColumn column3= new TableColumn(table, SWT.NONE);
column3.setText(TextEditorTemplateMessages.TemplatePreferencePage_column_description);
minWidth= computeMinimumColumnWidth(gc, TextEditorTemplateMessages.TemplatePreferencePage_column_description);
columnLayout.addColumnData(new ColumnWeightData(3, minWidth, true));
TableColumn column4= new TableColumn(table, SWT.NONE);
column4.setAlignment(SWT.CENTER);
column4.setText(TextEditorTemplateMessages.TemplatePreferencePage_column_autoinsert);
minWidth= computeMinimumColumnWidth(gc, TextEditorTemplateMessages.TemplatePreferencePage_column_autoinsert);
minWidth= Math.max(minWidth, computeMinimumColumnWidth(gc, TextEditorTemplateMessages.TemplatePreferencePage_on));
columnLayout.addColumnData(new ColumnPixelData(minWidth, false, false));
gc.dispose();
fTableViewer= new CheckboxTableViewer(table);
fTableViewer.setLabelProvider(new TemplateLabelProvider());
fTableViewer.setContentProvider(new TemplateContentProvider());
fTableViewer.setComparator(new ViewerComparator() {
public int compare(Viewer viewer, Object object1, Object object2) {
if ((object1 instanceof TemplatePersistenceData) && (object2 instanceof TemplatePersistenceData)) {
Template left= ((TemplatePersistenceData) object1).getTemplate();
Template right= ((TemplatePersistenceData) object2).getTemplate();
int result= left.getName().compareToIgnoreCase(right.getName());
if (result != 0)
return result;
return left.getDescription().compareToIgnoreCase(right.getDescription());
}
return super.compare(viewer, object1, object2);
}
public boolean isSorterProperty(Object element, String property) {
return true;
}
});
fTableViewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent e) {
edit();
}
});
fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent e) {
selectionChanged1();
}
});
fTableViewer.addCheckStateListener(new ICheckStateListener() {
public void checkStateChanged(CheckStateChangedEvent event) {
TemplatePersistenceData d= (TemplatePersistenceData) event.getElement();
d.setEnabled(event.getChecked());
}
});
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(TextEditorTemplateMessages.TemplatePreferencePage_new);
fAddButton.setLayoutData(getButtonGridData(fAddButton));
fAddButton.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
add();
}
});
fEditButton= new Button(buttons, SWT.PUSH);
fEditButton.setText(TextEditorTemplateMessages.TemplatePreferencePage_edit);
fEditButton.setLayoutData(getButtonGridData(fEditButton));
fEditButton.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
edit();
}
});
fRemoveButton= new Button(buttons, SWT.PUSH);
fRemoveButton.setText(TextEditorTemplateMessages.TemplatePreferencePage_remove);
fRemoveButton.setLayoutData(getButtonGridData(fRemoveButton));
fRemoveButton.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
remove();
}
});
createSeparator(buttons);
fRestoreButton= new Button(buttons, SWT.PUSH);
fRestoreButton.setText(TextEditorTemplateMessages.TemplatePreferencePage_restore);
fRestoreButton.setLayoutData(getButtonGridData(fRestoreButton));
fRestoreButton.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
restoreDeleted();
}
});
fRevertButton= new Button(buttons, SWT.PUSH);
fRevertButton.setText(TextEditorTemplateMessages.TemplatePreferencePage_revert);
fRevertButton.setLayoutData(getButtonGridData(fRevertButton));
fRevertButton.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
revert();
}
});
createSeparator(buttons);
fImportButton= new Button(buttons, SWT.PUSH);
fImportButton.setText(TextEditorTemplateMessages.TemplatePreferencePage_import);
fImportButton.setLayoutData(getButtonGridData(fImportButton));
fImportButton.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
import_();
}
});
fExportButton= new Button(buttons, SWT.PUSH);
fExportButton.setText(TextEditorTemplateMessages.TemplatePreferencePage_export);
fExportButton.setLayoutData(getButtonGridData(fExportButton));
fExportButton.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
export();
}
});
fPatternViewer= doCreateViewer(parent);
if (isShowFormatterSetting()) {
fFormatButton= new Button(parent, SWT.CHECK);
fFormatButton.setText(TextEditorTemplateMessages.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
}
/**
* Creates a separator between buttons
* @param parent
* @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 enabled= new ArrayList();
TemplatePersistenceData[] datas= fTemplateStore.getTemplateData(false);
for (int i= 0; i < datas.length; i++) {
if (datas[i].isEnabled())
enabled.add(datas[i]);
}
return (TemplatePersistenceData[]) enabled.toArray(new TemplatePersistenceData[enabled.size()]);
}
private SourceViewer doCreateViewer(Composite parent) {
Label label= new Label(parent, SWT.NONE);
label.setText(TextEditorTemplateMessages.TemplatePreferencePage_preview);
GridData data= new GridData();
data.horizontalSpan= 2;
label.setLayoutData(data);
SourceViewer viewer= createViewer(parent);
viewer.setEditable(false);
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;
}
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= (IStructuredSelection) fTableViewer.getSelection();
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= (IStructuredSelection) fTableViewer.getSelection();
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 it= fContextTypeRegistry.contextTypes();
if (it.hasNext()) {
Template template= new Template("", "", ((TemplateContextType) 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)}
*/
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= (IStructuredSelection) fTableViewer.getSelection();
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()) &&
MessageDialog.openQuestion(getShell(),
TextEditorTemplateMessages.TemplatePreferencePage_question_create_new_title,
TextEditorTemplateMessages.TemplatePreferencePage_question_create_new_message))
{
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(TextEditorTemplateMessages.TemplatePreferencePage_import_title);
dialog.setFilterExtensions(new String[] {TextEditorTemplateMessages.TemplatePreferencePage_import_extension});
String path= dialog.open();
if (path == null)
return;
IFileStore fileStore= EFS.getLocalFileSystem().getStore(new Path(path));
try {
TemplateReaderWriter reader= new TemplateReaderWriter();
if (fileStore.fetchInfo().exists()) {
InputStream input= new BufferedInputStream(fileStore.openInputStream(EFS.NONE, null));
try {
TemplatePersistenceData[] datas= reader.read(input, null);
for (int i= 0; i < datas.length; i++) {
TemplatePersistenceData data= datas[i];
fTemplateStore.add(data);
}
} finally {
try {
input.close();
} catch (IOException x) {
// ignore
}
}
}
fTableViewer.refresh();
fTableViewer.setAllChecked(false);
fTableViewer.setCheckedElements(getEnabledTemplates());
} catch (CoreException e) {
openReadErrorDialog();
} catch (IOException e) {
openReadErrorDialog();
}
}
private void export() {
IStructuredSelection selection= (IStructuredSelection) fTableViewer.getSelection();
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(TextEditorTemplateMessages.TemplatePreferencePage_export_title);
dialog.setFilterExtensions(new String[] {TextEditorTemplateMessages.TemplatePreferencePage_export_extension});
dialog.setFileName(TextEditorTemplateMessages.TemplatePreferencePage_export_filename);
String path= dialog.open();
if (path == null)
return;
IFileStore fileStore= EFS.getLocalFileSystem().getStore(new Path(path));
IFileInfo fileInfo= fileStore.fetchInfo();
if (fileInfo.getAttribute(EFS.ATTRIBUTE_HIDDEN)) {
String title= TextEditorTemplateMessages.TemplatePreferencePage_export_error_title;
String message= NLSUtility.format(TextEditorTemplateMessages.TemplatePreferencePage_export_error_hidden, fileStore.toString());
MessageDialog.openError(getShell(), title, message);
return;
}
if (fileInfo.exists() && fileInfo.getAttribute(EFS.ATTRIBUTE_READ_ONLY)) {
String title= TextEditorTemplateMessages.TemplatePreferencePage_export_error_title;
String message= NLSUtility.format(TextEditorTemplateMessages.TemplatePreferencePage_export_error_canNotWrite, fileStore.toString());
MessageDialog.openError(getShell(), title, message);
return;
}
if (!fileInfo.exists() || confirmOverwrite(fileStore)) {
OutputStream output= null;
try {
output= new BufferedOutputStream(fileStore.openOutputStream(EFS.NONE, null));
TemplateReaderWriter writer= new TemplateReaderWriter();
writer.save(templates, output);
} catch (CoreException e) {
openWriteErrorDialog();
} catch (IOException e) {
openWriteErrorDialog();
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
// ignore
}
}
}
}
}
private boolean confirmOverwrite(IFileStore fileStore) {
return MessageDialog.openQuestion(getShell(),
TextEditorTemplateMessages.TemplatePreferencePage_export_exists_title,
NLSUtility.format(TextEditorTemplateMessages.TemplatePreferencePage_export_exists_message, fileStore.toString()));
}
private void remove() {
IStructuredSelection selection= (IStructuredSelection) fTableViewer.getSelection();
Iterator elements= selection.iterator();
while (elements.hasNext()) {
TemplatePersistenceData data= (TemplatePersistenceData) elements.next();
fTemplateStore.delete(data);
}
fTableViewer.refresh();
}
private void restoreDeleted() {
fTemplateStore.restoreDeleted();
fTableViewer.refresh();
fTableViewer.setCheckedElements(getEnabledTemplates());
updateButtons();
}
private void revert() {
IStructuredSelection selection= (IStructuredSelection) fTableViewer.getSelection();
Iterator elements= selection.iterator();
while (elements.hasNext()) {
TemplatePersistenceData data= (TemplatePersistenceData) elements.next();
data.revert();
}
fTableViewer.refresh();
selectionChanged1();
fTableViewer.setChecked(getEnabledTemplates(), true);
}
/*
* @see Control#setVisible(boolean)
*/
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible)
setTitle(TextEditorTemplateMessages.TemplatePreferencePage_title);
}
/*
* @see PreferencePage#performDefaults()
*/
protected void performDefaults() {
if (isShowFormatterSetting()) {
IPreferenceStore prefs= getPreferenceStore();
fFormatButton.setSelection(prefs.getDefaultBoolean(getFormatterPreferenceKey()));
}
fTemplateStore.restoreDefaults();
// refresh
fTableViewer.refresh();
fTableViewer.setAllChecked(false);
fTableViewer.setCheckedElements(getEnabledTemplates());
}
/*
* @see PreferencePage#performOk()
*/
public boolean performOk() {
if (isShowFormatterSetting()) {
IPreferenceStore prefs= getPreferenceStore();
prefs.setValue(getFormatterPreferenceKey(), fFormatButton.getSelection());
}
try {
fTemplateStore.save();
} catch (IOException e) {
openWriteErrorDialog();
}
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;
}
/*
* @see PreferencePage#performCancel()
*/
public boolean performCancel() {
try {
fTemplateStore.load();
} catch (IOException e) {
openReadErrorDialog();
return false;
}
return super.performCancel();
}
/*
* @since 3.2
*/
private void openReadErrorDialog() {
String title= TextEditorTemplateMessages.TemplatePreferencePage_error_read_title;
String message= TextEditorTemplateMessages.TemplatePreferencePage_error_read_message;
MessageDialog.openError(getShell(), title, message);
}
/*
* @since 3.2
*/
private void openWriteErrorDialog() {
String title= TextEditorTemplateMessages.TemplatePreferencePage_error_write_title;
String message= TextEditorTemplateMessages.TemplatePreferencePage_error_write_message;
MessageDialog.openError(getShell(), title, message);
}
protected SourceViewer getViewer() {
return fPatternViewer;
}
protected TableViewer getTableViewer() {
return fTableViewer;
}
}