org.eclipse.ui.texteditor.templates.CTemplatePreferencePage.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ui.texteditor.templates.CTemplatePreferencePage.java

Source

/*
* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/

package org.eclipse.ui.texteditor.templates;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Assert;
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.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.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.TemplateStore;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnLayoutData;
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.IStructuredContentProvider;
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.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
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.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.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.ScrollBar;
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.ui.ActiveShellExpression;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.handlers.IHandlerService;
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.ITextEditorActionDefinitionIds;
import org.eclipse.ui.texteditor.IUpdate;
import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds;

import com.ibm.icu.text.Collator;

/**
 * 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 CTemplatePreferencePage extends PreferencePage implements IWorkbenchPreferencePage {

    final class ColumnLayout extends Layout {

        ColumnLayout() {
            columns = new ArrayList();
        }

        public void addColumnData(ColumnLayoutData data) {
            columns.add(data);
        }

        private Point computeTableSize(Table table, int wHint, int hHint) {
            Point result = table.computeSize(wHint, hHint);
            int width = 0;
            int size = columns.size();
            for (int i = 0; i < size; i++) {
                ColumnLayoutData layoutData = (ColumnLayoutData) columns.get(i);
                if (layoutData instanceof ColumnPixelData) {
                    ColumnPixelData col = (ColumnPixelData) layoutData;
                    width += col.width;
                    if (col.addTrim)
                        width += COLUMN_TRIM;
                } else if (layoutData instanceof ColumnWeightData) {
                    ColumnWeightData col = (ColumnWeightData) layoutData;
                    width += col.minimumWidth;
                } else {
                    Assert.isTrue(false, "Unknown column layout data");
                }
            }

            if (width > result.x)
                result.x = width;
            return result;
        }

        private void layoutTable(Table table, int width, Rectangle area, boolean increase) {
            TableColumn tableColumns[] = table.getColumns();
            int size = Math.min(columns.size(), tableColumns.length);
            int widths[] = new int[size];
            int weightIteration[] = new int[size];
            int numberOfWeightColumns = 0;
            int fixedWidth = 0;
            int minWeightWidth = 0;
            int totalWeight = 0;
            for (int i = 0; i < size; i++) {
                ColumnLayoutData col = (ColumnLayoutData) columns.get(i);
                if (col instanceof ColumnPixelData) {
                    ColumnPixelData cpd = (ColumnPixelData) col;
                    int pixels = cpd.width;
                    if (cpd.addTrim)
                        pixels += COLUMN_TRIM;
                    widths[i] = pixels;
                    fixedWidth += pixels;
                } else if (col instanceof ColumnWeightData) {
                    ColumnWeightData cw = (ColumnWeightData) col;
                    weightIteration[numberOfWeightColumns] = i;
                    numberOfWeightColumns++;
                    totalWeight += cw.weight;
                    minWeightWidth += cw.minimumWidth;
                    widths[i] = cw.minimumWidth;
                } else {
                    Assert.isTrue(false, "Unknown column layout data");
                }
            }

            int restIncludingMinWidths = width - fixedWidth;
            int rest = restIncludingMinWidths - minWeightWidth;
            if (numberOfWeightColumns > 0 && rest > 0) {
                int totalWantedPixels = 0;
                int wantedPixels[] = new int[numberOfWeightColumns];
                for (int i = 0; i < numberOfWeightColumns; i++) {
                    ColumnWeightData cw = (ColumnWeightData) columns.get(weightIteration[i]);
                    wantedPixels[i] = totalWeight != 0 ? (cw.weight * restIncludingMinWidths) / totalWeight : 0;
                    totalWantedPixels += wantedPixels[i];
                }

                int totalDistributed = 0;
                for (int i = 0; i < numberOfWeightColumns; i++) {
                    int pixels = totalWantedPixels != 0 ? (wantedPixels[i] * rest) / totalWantedPixels : 0;
                    totalDistributed += pixels;
                    widths[weightIteration[i]] += pixels;
                }

                int diff = rest - totalDistributed;
                for (int i = 0; diff > 0; i = (i + 1) % numberOfWeightColumns) {
                    widths[weightIteration[i]]++;
                    diff--;
                }

            }
            if (increase)
                table.setSize(area.width, area.height);
            for (int i = 0; i < size; i++)
                tableColumns[i].setWidth(widths[i]);

            if (!increase)
                table.setSize(area.width, area.height);
        }

        protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
            return computeTableSize(getTable(composite), wHint, hHint);
        }

        protected void layout(Composite composite, boolean flushCache) {
            Rectangle area = composite.getClientArea();
            Table table = getTable(composite);
            int tableWidth = table.getSize().x;
            int trim = computeTrim(area, table, tableWidth);
            int width = Math.max(0, area.width - trim);
            if (width > 1)
                layoutTable(table, width, area, tableWidth < area.width);
            if (composite.getData("recalculateKey") == null) {
                composite.setData("recalculateKey", Boolean.FALSE);
                composite.layout();
            }
        }

        private int computeTrim(Rectangle area, Table table, int tableWidth) {
            Point preferredSize = computeTableSize(table, area.width, area.height);
            int trim;
            if (tableWidth > 1)
                trim = tableWidth - table.getClientArea().width;
            else
                trim = 2 * table.getBorderWidth() + 1;
            if (preferredSize.y > area.height) {
                ScrollBar vBar = table.getVerticalBar();
                if (!vBar.isVisible()) {
                    Point vBarSize = vBar.getSize();
                    trim += vBarSize.x;
                }
            }
            return trim;
        }

        private Table getTable(Composite composite) {
            return (Table) composite.getChildren()[0];
        }

        private static final String RECALCULATE_LAYOUT = "recalculateKey";
        private int COLUMN_TRIM = "carbon".equals(SWT.getPlatform()) ? 24 : 3;
        private List columns;

    }

    /**
     * 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() {
                // XXX: workaround for
                // https://bugs.eclipse.org/bugs/show_bug.cgi?id=206111
                if (fOperationCode == ITextOperationTarget.REDO)
                    return;

                boolean wasEnabled = isEnabled();
                boolean isEnabled = (fOperationTarget != null && fOperationTarget.canDoOperation(fOperationCode));
                setEnabled(isEnabled);

                if (wasEnabled != isEnabled) {
                    firePropertyChange(ENABLED, wasEnabled ? Boolean.TRUE : Boolean.FALSE,
                            isEnabled ? Boolean.TRUE : Boolean.FALSE);
                }
            }

            /**
             * @see Action#run()
             */
            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 CStatusInfo 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 CTemplateVariableProcessor fTemplateProcessor = new CTemplateVariableProcessor();

        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 Template";
            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 CStatusInfo();

            fContextTypeRegistry = registry;

            TemplateContextType type = fContextTypeRegistry.getContextType(template.getContextTypeId());
            fTemplateProcessor.setContextType(type);
        }

        /*
         * @see org.eclipse.jface.dialogs.Dialog#isResizable()
         * @since 3.4
         */
        protected boolean isResizable() {
            return true;
        }

        /*
         * @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("Template name can't be empty. ");
                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;
            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 = new ModifyListener() {
                public void modifyText(ModifyEvent e) {
                    doTextWidgetChanged(e.widget);
                }
            };

            if (fIsNameModifiable) {
                createLabel(parent, "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();
                        }
                    }
                });
                fNameText.setEnabled(false);

                createLabel(composite, "Context: ");
                fContextCombo = new Combo(composite, SWT.READ_ONLY);

                for (int i = 0; i < fContextTypes.length; i++) {
                    fContextCombo.add(fContextTypes[i][1]);
                }

                fContextCombo.addModifyListener(listener);
                fContextCombo.setEnabled(false);

                fAutoInsertCheckbox = createCheckbox(composite, "Automatically insert");
                fAutoInsertCheckbox.setSelection(fOriginalTemplate.isAutoInsertable());
                fAutoInsertCheckbox.setEnabled(false);
            }

            createLabel(parent, "File Name: ");

            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, "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());

            final Composite composite = new Composite(parent, SWT.NONE);
            layout = new GridLayout();
            layout.marginWidth = 0;
            layout.marginHeight = 0;
            composite.setLayout(layout);
            composite.setLayoutData(new GridData());

            final Menu menu = new Menu(composite);

            createMenuItem(menu, "${author}");
            createMenuItem(menu, "${baseName}");
            createMenuItem(menu, "${baseNameUpper}");
            createMenuItem(menu, "${copyright}");
            new MenuItem(menu, SWT.SEPARATOR);
            createMenuItem(menu, "${controllerIncludes}");
            createMenuItem(menu, "${wrapperLIT}");
            createMenuItem(menu, "${wrapperCreating}");

            fInsertVariableButton = new Button(composite, SWT.NONE);
            fInsertVariableButton.setLayoutData(getButtonGridData(fInsertVariableButton));
            fInsertVariableButton.setText("Insert Variable...");
            fInsertVariableButton.addSelectionListener(new SelectionListener() {
                public void widgetSelected(SelectionEvent e) {
                    menu.setVisible(true);
                }

                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 createMenuItem(Menu menu, final String string) {
            MenuItem item = new MenuItem(menu, SWT.NONE);
            item.setText(string);
            item.addSelectionListener(new SelectionAdapter() {
                public void widgetSelected(SelectionEvent e) {
                    fPatternEditor.getTextWidget().insert(string);
                }
            });
        }

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

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

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

            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 initializeActions() {
            final ArrayList handlerActivations = new ArrayList(3);
            final IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench()
                    .getAdapter(IHandlerService.class);
            getShell().addDisposeListener(new DisposeListener() {

                public void widgetDisposed(DisposeEvent e) {
                    handlerService.deactivateHandlers(handlerActivations);
                }
            });

            ActiveShellExpression expression = new ActiveShellExpression(fPatternEditor.getControl().getShell());

            TextViewerAction action = new TextViewerAction(fPatternEditor, ITextOperationTarget.UNDO);
            action.setText("Undo");
            fGlobalActions.put(ITextEditorActionConstants.UNDO, action);
            handlerActivations.add(handlerService.activateHandler(IWorkbenchActionDefinitionIds.UNDO,
                    new ActionHandler(action), expression));

            action = new TextViewerAction(fPatternEditor, ITextOperationTarget.REDO);
            action.setText("Redo");
            fGlobalActions.put(ITextEditorActionConstants.REDO, action);
            handlerActivations.add(handlerService.activateHandler(IWorkbenchActionDefinitionIds.REDO,
                    new ActionHandler(action), expression));

            action = new TextViewerAction(fPatternEditor, ITextOperationTarget.CUT);
            action.setText("Cut");
            fGlobalActions.put(ITextEditorActionConstants.CUT, action);

            action = new TextViewerAction(fPatternEditor, ITextOperationTarget.COPY);
            action.setText("Copy");
            fGlobalActions.put(ITextEditorActionConstants.COPY, action);

            action = new TextViewerAction(fPatternEditor, ITextOperationTarget.PASTE);
            action.setText("Paste");
            fGlobalActions.put(ITextEditorActionConstants.PASTE, action);

            action = new TextViewerAction(fPatternEditor, ITextOperationTarget.SELECT_ALL);
            action.setText("Select All");
            fGlobalActions.put(ITextEditorActionConstants.SELECT_ALL, action);

            action = new TextViewerAction(fPatternEditor, ISourceViewer.CONTENTASSIST_PROPOSALS);
            action.setText("Content Assist");
            fGlobalActions.put("ContentAssistProposal", action); //$NON-NLS-1$
            handlerActivations
                    .add(handlerService.activateHandler(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS,
                            new ActionHandler(action), expression));

            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.appendToGroup(ITextEditorActionConstants.GROUP_UNDO,
                    (IAction) fGlobalActions.get(ITextEditorActionConstants.REDO));

            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 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() {
            CStatusInfo status;

            boolean valid = fNameText == null || fNameText.getText().trim().length() != 0;
            if (!valid) {
                status = new CStatusInfo();
                if (!fSuppressError) {
                    status.setError("Template name cannot be empty. ");
                }
            } 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;
        }

    }

    class TemplateContentProvider implements IStructuredContentProvider {

        TemplateContentProvider() {
        }

        public Object[] getElements(Object input) {
            return fStore.getTemplateData(false);
        }

        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            fStore = (TemplateStore) newInput;
        }

        public void dispose() {
            fStore = null;
        }

        private TemplateStore fStore;
    }

    /**
     * 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 1:
                return template.getDescription();
            // case 3:
            // return template.isAutoInsertable() ? "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 CTemplatePreferencePage() {
        super();

        setDescription("Edit templates: ");
    }

    /**
     * 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("Name");
        int minWidth = computeMinimumColumnWidth(gc, "Name");
        columnLayout.addColumnData(new ColumnWeightData(2, minWidth, true));

        //      TableColumn column2 = new TableColumn(table, SWT.NONE);
        //      column2.setText("Context");
        //      minWidth = computeMinimumContextColumnWidth(gc);
        //      columnLayout.addColumnData(new ColumnWeightData(1, minWidth, true));

        TableColumn column3 = new TableColumn(table, SWT.NONE);
        column3.setText("File Name");
        minWidth = computeMinimumColumnWidth(gc, "File Name");
        columnLayout.addColumnData(new ColumnWeightData(3, minWidth, true));

        // TableColumn column4 = new TableColumn(table, SWT.NONE);
        // column4.setAlignment(SWT.CENTER);
        // column4.setText("Auto Insert");
        // minWidth = computeMinimumColumnWidth(gc, "Auto Insert");
        // minWidth = Math.max(minWidth, computeMinimumColumnWidth(gc, "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 = Collator.getInstance().compare(left.getName(), right.getName());
                    if (result != 0)
                        return result;
                    return Collator.getInstance().compare(left.getDescription(), 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("New...");
        fAddButton.setLayoutData(getButtonGridData(fAddButton));
        fAddButton.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event e) {
                add();
            }
        });
        fAddButton.setEnabled(false);

        fEditButton = new Button(buttons, SWT.PUSH);
        fEditButton.setText("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("Remove");
        fRemoveButton.setLayoutData(getButtonGridData(fRemoveButton));
        fRemoveButton.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event e) {
                remove();
            }
        });
        fRemoveButton.setEnabled(false);

        createSeparator(buttons);

        fRestoreButton = new Button(buttons, SWT.PUSH);
        fRestoreButton.setText("Restore Removed");
        fRestoreButton.setLayoutData(getButtonGridData(fRestoreButton));
        fRestoreButton.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event e) {
                restoreDeleted();
            }
        });

        fRevertButton = new Button(buttons, SWT.PUSH);
        fRevertButton.setText("Revert to Default");
        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("Import...");
        fImportButton.setLayoutData(getButtonGridData(fImportButton));
        fImportButton.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event e) {
                import_();
            }
        });
        fImportButton.setEnabled(false);

        fExportButton = new Button(buttons, SWT.PUSH);
        fExportButton.setText("Export...");
        fExportButton.setLayoutData(getButtonGridData(fExportButton));
        fExportButton.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event e) {
                export();
            }
        });
        fExportButton.setEnabled(false);

        fPatternViewer = doCreateViewer(parent);

        if (isShowFormatterSetting()) {
            fFormatButton = new Button(parent, SWT.CHECK);
            fFormatButton.setText("Code Format");
            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("Context").x;
        Iterator iter = getContextTypeRegistry().contextTypes();
        while (iter.hasNext()) {
            TemplateContextType contextType = (TemplateContextType) 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 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("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);
        viewer.getTextWidget().setCaret(null);

        Control control = viewer.getControl();
        data = new GridData(GridData.FILL_BOTH);
        data.horizontalSpan = 2;
        data.heightHint = convertHeightInCharsToPixels(5);
        control.setLayoutData(data);

        return viewer;
    }

    /**
     * Creates, configures and returns a source viewer to present the template
     * pattern on the preference page. Clients may override to provide a custom
     * source viewer featuring e.g. syntax coloring.
     * 
     * @param parent
     *            the parent control
     * @return a configured source viewer
     */
    protected SourceViewer createViewer(Composite parent) {
        SourceViewer viewer = new SourceViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
        SourceViewerConfiguration configuration = new SourceViewerConfiguration();
        viewer.configure(configuration);
        IDocument document = new Document();
        viewer.setDocument(document);
        return viewer;
    }

    /**
     * Return the grid data for the button.
     * 
     * @param button
     *            the button
     * @return the grid data
     */
    private static GridData getButtonGridData(Button button) {
        GridData data = new GridData(GridData.FILL_HORIZONTAL);
        // 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(false);
        fRemoveButton.setEnabled(false);
        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(), "Create Template", "Create Template")) {
                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_() {
    }

    private void export() {
    }

    private void export(TemplatePersistenceData[] templates) {
    }

    private boolean confirmOverwrite(File file) {
        return MessageDialog.openQuestion(getShell(), "Overwrite? ",
                NLSUtility.format("Do you want to overwrite? ", file.getAbsolutePath()));
    }

    private void remove() {
    }

    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.setChecked(data, data.isEnabled());
        }

        selectionChanged1();
        fTableViewer.refresh();
    }

    /*
     * @see Control#setVisible(boolean)
     */
    public void setVisible(boolean visible) {
        super.setVisible(visible);
        if (visible)
            setTitle("Templates");
    }

    /*
     * @see PreferencePage#performDefaults()
     */
    protected void performDefaults() {
        if (isShowFormatterSetting()) {
            IPreferenceStore prefs = getPreferenceStore();
            fFormatButton.setSelection(prefs.getDefaultBoolean(getFormatterPreferenceKey()));
        }

        // fTemplateStore.restoreDefaults(false);
        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 = "Read error. ";
        String message = "Read error";
        MessageDialog.openError(getShell(), title, message);
    }

    /*
     * @since 3.2
     */
    private void openWriteErrorDialog() {
        String title = "Write error";
        String message = "Write error";
        MessageDialog.openError(getShell(), title, message);
    }

    protected SourceViewer getViewer() {
        return fPatternViewer;
    }

    protected TableViewer getTableViewer() {
        return fTableViewer;
    }
}