/*******************************************************************************
 * 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.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.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.ITextOperationTarget;
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.actions.ActionFactory;
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.internal.texteditor.templates.TextViewerAction;

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 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.setActionDefinitionId(ActionFactory.UNDO.getCommandId());
			action.setText(TemplatesMessages.EditTemplateDialog_undo);
			fGlobalActions.put(ITextEditorActionConstants.UNDO, action);

			action= new TextViewerAction(fPatternEditor, ITextOperationTarget.REDO);
			action.setActionDefinitionId(ActionFactory.REDO.getCommandId());
			action.setText(TemplatesMessages.EditTemplateDialog_redo);
			fGlobalActions.put(ITextEditorActionConstants.REDO, action);

			action = new TextViewerAction(fPatternEditor, ITextOperationTarget.CUT);
			action.setActionDefinitionId(ActionFactory.CUT.getCommandId());
			action.setText(TemplatesMessages.EditTemplateDialog_cut);
			fGlobalActions.put(ITextEditorActionConstants.CUT, action);

			action = new TextViewerAction(fPatternEditor, ITextOperationTarget.COPY);
			action.setActionDefinitionId(ActionFactory.COPY.getCommandId());
			action.setText(TemplatesMessages.EditTemplateDialog_copy);
			fGlobalActions.put(ITextEditorActionConstants.COPY, action);

			action= new TextViewerAction(fPatternEditor, ITextOperationTarget.PASTE);
			action.setActionDefinitionId(ActionFactory.PASTE.getCommandId());
			action.setText(TemplatesMessages.EditTemplateDialog_paste);
			fGlobalActions.put(ITextEditorActionConstants.PASTE, action);

			action= new TextViewerAction(fPatternEditor, ITextOperationTarget.SELECT_ALL);
			action.setActionDefinitionId(ActionFactory.SELECT_ALL.getCommandId());
			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;

	private TextViewerAction fPatternViewerCopyAction;

	private TextViewerAction fPatternViewerSelectAllAction;

	/**
	 * 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);

		addActionsToPatternViewer(viewer);

		return viewer;
	}

	private void addActionsToPatternViewer(SourceViewer viewer) {
		// create actions
		fPatternViewerCopyAction = new TextViewerAction(viewer, ITextOperationTarget.COPY);
		fPatternViewerCopyAction.setActionDefinitionId(ActionFactory.COPY.getCommandId());
		fPatternViewerCopyAction.setText(TemplatesMessages.EditTemplateDialog_copy);

		fPatternViewerSelectAllAction = new TextViewerAction(viewer, ITextOperationTarget.SELECT_ALL);
		fPatternViewerSelectAllAction.setActionDefinitionId(ActionFactory.SELECT_ALL.getCommandId());
		fPatternViewerSelectAllAction.setText(TemplatesMessages.EditTemplateDialog_select_all);

		viewer.addSelectionChangedListener(this::updateCopyAction);
		// create context menu
		MenuManager manager = new MenuManager(null, null);
		manager.setRemoveAllWhenShown(true);
		manager.addMenuListener(this::fillPatternViewerContextMenu);

		StyledText text = viewer.getTextWidget();
		Menu menu = manager.createContextMenu(text);
		text.setMenu(menu);
	}

	private void fillPatternViewerContextMenu(IMenuManager menu) {
		menu.add(new Separator(ITextEditorActionConstants.GROUP_EDIT));
		menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, fPatternViewerCopyAction);
		menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, fPatternViewerSelectAllAction);
	}

	/**
	 * @param event The event
	 */
	private void updateCopyAction(SelectionChangedEvent event) {
		if (fPatternViewerCopyAction != null)
			fPatternViewerCopyAction.update();
	}

	/**
	 * 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();
		}
	}
}
