de.walware.statet.base.internal.ui.preferences.CodeGenerationTemplatesConfigurationBlock.java Source code

Java tutorial

Introduction

Here is the source code for de.walware.statet.base.internal.ui.preferences.CodeGenerationTemplatesConfigurationBlock.java

Source

/*=============================================================================#
 # Copyright (c) 2005-2015 Stephan Wahlbrink (WalWare.de) and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
 # http://www.eclipse.org/legal/epl-v10.html
 # 
 # Contributors:
 #     Stephan Wahlbrink - initial API and implementation
 #=============================================================================*/

package de.walware.statet.base.internal.ui.preferences;

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.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateContextType;
import org.eclipse.jface.text.templates.persistence.TemplatePersistenceData;
import org.eclipse.jface.text.templates.persistence.TemplateReaderWriter;
import org.eclipse.jface.text.templates.persistence.TemplateStore;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.statushandlers.StatusManager;

import de.walware.ecommons.ltk.ui.sourceediting.ISourceEditor;
import de.walware.ecommons.ltk.ui.sourceediting.SourceEditorViewerConfigurator;
import de.walware.ecommons.ltk.ui.sourceediting.ViewerSourceEditorAdapter;
import de.walware.ecommons.ltk.ui.templates.EditTemplateDialog;
import de.walware.ecommons.preferences.ui.ConfigurationBlock;
import de.walware.ecommons.preferences.ui.SettingsUpdater;
import de.walware.ecommons.templates.TemplateVariableProcessor;
import de.walware.ecommons.text.ui.TextViewerEditorColorUpdater;
import de.walware.ecommons.text.ui.TextViewerJFaceUpdater;
import de.walware.ecommons.ui.ISettingsChangedHandler;
import de.walware.ecommons.ui.dialogs.groups.CategorizedOptionButtonsGroup;
import de.walware.ecommons.ui.dialogs.groups.CategorizedOptionsGroup.CategorizedItem;
import de.walware.ecommons.ui.util.UIAccess;

import de.walware.statet.ext.templates.ICodeGenerationTemplatesCategory;

import de.walware.statet.base.internal.ui.StatetUIPlugin;

/**
 * The page to configure the codegenerator templates.
 */
public class CodeGenerationTemplatesConfigurationBlock extends ConfigurationBlock {

    public static final String EXTENSION_POINT = "codeGenerationTemplatesCategory"; //$NON-NLS-1$
    public static final String ATT_ID = "id"; //$NON-NLS-1$
    public static final String ATT_NAME = "name"; //$NON-NLS-1$
    public static final String ATT_CLASS = "providerClass"; //$NON-NLS-1$

    private final static int IDX_EDIT = 0;
    private final static int IDX_IMPORT = 2;
    private final static int IDX_EXPORT = 3;
    private final static int IDX_EXPORTALL = 4;

    public class TemplateItem extends CategorizedItem {

        protected TemplatePersistenceData fData;

        public TemplateItem(final TemplatePersistenceData data) {
            super(data.getTemplate().getDescription());
            fData = data;
        }
    }

    private class Group extends CategorizedOptionButtonsGroup<TemplateItem> {

        public Group() {
            super(new String[] { Messages.CodeTemplates_EditButton_label, null,
                    Messages.CodeTemplates_ImportButton_label, Messages.CodeTemplates_ExportButton_label,
                    Messages.CodeTemplates_ExportAllButton_label, });
        }

        @Override
        protected void handleDoubleClick(final TemplateItem item, final IStructuredSelection rawSelection) {
            doEdit(item);
        }

        @Override
        public void handleSelection(final TemplateItem item, final IStructuredSelection rawSelection) {
            fButtonGroup.enableButton(IDX_EDIT, (item != null));
            fButtonGroup.enableButton(IDX_EXPORT, rawSelection.size() > 0);

            updateSourceViewerInput(item);
        }

        @Override
        public void handleButtonPressed(final int buttonIdx, final TemplateItem item,
                final IStructuredSelection rawSelection) {
            switch (buttonIdx) {
            case IDX_EDIT:
                if (item != null) {
                    doEdit(item);
                }
                break;

            case IDX_EXPORT:
                final List<TemplatePersistenceData> datas = new ArrayList<TemplatePersistenceData>();
                for (final Iterator<?> iter = rawSelection.iterator(); iter.hasNext();) {
                    final Object curr = iter.next();
                    if (curr instanceof TemplateItem) {
                        datas.add(((TemplateItem) curr).fData);
                    } else {
                        final int catIndex = getIndexOfCategory(curr);
                        for (int j = 0; j < fCategoryChilds[catIndex].length; j++) {
                            datas.add(fCategoryChilds[catIndex][j].fData);
                        }
                    }
                }
                doExport(datas.toArray(new TemplatePersistenceData[datas.size()]));
                break;

            case IDX_EXPORTALL:
                doExport(fTemplatesStore.getAllTemplateData());
                break;

            case IDX_IMPORT:
                doImport();
                break;
            }
        }

    }

    protected IProject fProject;
    private String[] fCategoryIds;
    private ICodeGenerationTemplatesCategory[] fCategoryProvider;

    protected CodeGenerationTemplatesStore fTemplatesStore;

    protected Group fGroup;
    private SourceViewer fPatternViewer;
    private int fPatternViewerConfiguredCategory = -1;
    private TextViewerJFaceUpdater fPatternViewerUpdater = null;
    private SourceEditorViewerConfigurator fPatternConfigurator;
    private ISourceEditor fPatternEditor;

    private final TemplateVariableProcessor fPatternTemplateProcessor;
    private final TemplateVariableProcessor fEditTemplateProcessor;

    public CodeGenerationTemplatesConfigurationBlock(final IProject project) throws CoreException {
        fProject = project;
        fGroup = new Group();
        loadRegisteredTemplates();
        fGroup.generateListModel();

        fPatternTemplateProcessor = new TemplateVariableProcessor();
        fEditTemplateProcessor = new TemplateVariableProcessor();
    }

    private void loadRegisteredTemplates() {
        final IExtensionRegistry registry = Platform.getExtensionRegistry();
        final IConfigurationElement[] elements = registry.getConfigurationElementsFor(StatetUIPlugin.PLUGIN_ID,
                EXTENSION_POINT);

        fCategoryIds = new String[elements.length];
        fCategoryProvider = new ICodeGenerationTemplatesCategory[elements.length];
        fGroup.fCategorys = new String[elements.length];
        fGroup.fCategoryChilds = new TemplateItem[elements.length][];
        final TemplateStore[] templates = new TemplateStore[elements.length];

        for (int i = 0; i < elements.length; i++) {
            fCategoryIds[i] = elements[i].getAttribute(ATT_ID);
            Assert.isLegal(fCategoryIds[i] != null);

            fGroup.fCategorys[i] = elements[i].getAttribute(ATT_NAME);
            if (fGroup.fCategorys[i] == null) {
                fGroup.fCategorys[i] = fCategoryIds[i];
            }

            try {
                fCategoryProvider[i] = (ICodeGenerationTemplatesCategory) elements[i]
                        .createExecutableExtension(ATT_CLASS);
            } catch (final CoreException e) {
                throw new IllegalArgumentException(
                        "Error occured when loading templateprovider of category with id " + fCategoryIds[i], e); //$NON-NLS-1$
            }

            templates[i] = fCategoryProvider[i].getTemplateStore();
        }

        fTemplatesStore = new CodeGenerationTemplatesStore(fProject, templates);
        try {
            fTemplatesStore.load();
        } catch (final IOException e) {
            StatetUIPlugin.logUnexpectedError(e);
        }
        for (int i = 0; i < fCategoryIds.length; i++) {
            final TemplatePersistenceData[] datas = fTemplatesStore.getTemplateData(i);

            fGroup.fCategoryChilds[i] = new TemplateItem[datas.length];
            for (int j = 0; j < fGroup.fCategoryChilds[i].length; j++) {
                fGroup.fCategoryChilds[i][j] = new TemplateItem(datas[j]);
            }
        }
    }

    private void reloadTemplateData() {
        for (int i = 0; i < fCategoryIds.length; i++) {
            for (int j = 0; j < fGroup.fCategoryChilds[i].length; j++) {
                fGroup.fCategoryChilds[i][j].fData = fTemplatesStore.getTemplateData(i,
                        fGroup.fCategoryChilds[i][j].fData.getId());
            }
        }
    }

    private void updateTemplate(final TemplatePersistenceData data) {
        final TemplatePersistenceData[] datas = fTemplatesStore.getAllTemplateData();
        for (int i = 0; i < datas.length; i++) {
            final String id = datas[i].getId();
            if (id != null && id.equals(data.getId())) {
                datas[i].setTemplate(data.getTemplate());
                break;
            }
        }
    }

    @Override
    public void setUseProjectSpecificSettings(final boolean enable) {
        super.setUseProjectSpecificSettings(enable);

        if (enable) {
            UIAccess.getDisplay(getShell()).asyncExec(new Runnable() {
                @Override
                public void run() {
                    fGroup.reselect();
                }
            });
        }
    }

    /* GUI ************************************************************************/

    @Override
    protected void createBlockArea(final Composite pageComposite) {
        final Label label = new Label(pageComposite, SWT.LEFT);
        label.setText(Messages.CodeTemplates_label);
        label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        fGroup.createGroup(pageComposite, 1);
        fGroup.initFields();

        fPatternViewer = createViewer(pageComposite);
    }

    private SourceViewer createViewer(final Composite parent) {
        final Label label = new Label(parent, SWT.LEFT);
        label.setText(Messages.CodeTemplates_Preview_label);
        label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        final SourceViewer viewer = new SourceViewer(parent, null, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
        viewer.setEditable(false);
        viewer.getTextWidget().setFont(JFaceResources.getFont(JFaceResources.TEXT_FONT));
        new TextViewerEditorColorUpdater(viewer, EditorsUI.getPreferenceStore());

        final IDocument document = new Document();
        viewer.setDocument(document);

        final GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
        data.heightHint = new PixelConverter(viewer.getControl()).convertHeightInCharsToPixels(5);
        viewer.getControl().setLayoutData(data);

        fPatternEditor = new ViewerSourceEditorAdapter(viewer, null);
        new SettingsUpdater(new ISettingsChangedHandler() {
            @Override
            public void handleSettingsChanged(final Set<String> groupIds, final Map<String, Object> options) {
                if (fPatternConfigurator != null) {
                    fPatternConfigurator.handleSettingsChanged(groupIds, options);
                }
            }
        }, viewer.getControl());

        return viewer;
    }

    protected void updateSourceViewerInput(final TemplateItem item) {
        if (fPatternViewer == null || !(UIAccess.isOkToUse(fPatternViewer.getControl()))) {
            return;
        }

        if (item != null) {
            final TemplatePersistenceData data = item.fData;
            final ICodeGenerationTemplatesCategory category = fCategoryProvider[item.getCategoryIndex()];
            final Template template = data.getTemplate();

            final TemplateContextType type = category.getContextTypeRegistry()
                    .getContextType(template.getContextTypeId());
            fPatternTemplateProcessor.setContextType(type);

            if (item.getCategoryIndex() != fPatternViewerConfiguredCategory) {
                fPatternViewerConfiguredCategory = item.getCategoryIndex();

                if (fPatternViewerUpdater != null) {
                    fPatternViewerUpdater.dispose();
                    fPatternViewerUpdater = null;
                }
                if (fPatternConfigurator != null) {
                    fPatternConfigurator.unconfigureTarget();
                    fPatternConfigurator = null;
                }

                fPatternConfigurator = category.getEditTemplateDialogConfiguator(fPatternTemplateProcessor,
                        fProject);
                fPatternConfigurator.setTarget(fPatternEditor);
                fPatternViewerUpdater = new TextViewerJFaceUpdater(fPatternViewer,
                        fPatternConfigurator.getSourceViewerConfiguration().getPreferences());

                final IDocument document = new Document(template.getPattern());
                fPatternConfigurator.getDocumentSetupParticipant().setup(document);
                fPatternViewer.setDocument(document);
            } else {
                fPatternViewer.getDocument().set(template.getPattern());
            }

        } else {
            fPatternViewer.getDocument().set(""); //$NON-NLS-1$
        }
    }

    /* Execute Actions ************************************************************/

    public void doEdit(final TemplateItem item) {
        final EditTemplateDialog dialog = new EditTemplateDialog(getShell(), item.fData.getTemplate(), true,
                EditTemplateDialog.FIX_TEMPLATE,
                fCategoryProvider[item.getCategoryIndex()].getEditTemplateDialogConfiguator(fEditTemplateProcessor,
                        fProject),
                fEditTemplateProcessor, fCategoryProvider[item.getCategoryIndex()].getContextTypeRegistry());
        if (dialog.open() == Window.OK) {
            // changed
            item.fData.setTemplate(dialog.getTemplate());
            fGroup.getStructuredViewer().refresh(item);
            fGroup.getStructuredViewer().setSelection(new StructuredSelection(item));
        }
    }

    public void doImport() {
        final FileDialog dialog = new FileDialog(getShell(), SWT.OPEN);
        dialog.setText(Messages.CodeTemplates_Import_title);
        dialog.setFilterExtensions(new String[] { Messages.CodeTemplates_Import_extension });
        final String path = dialog.open();

        if (path == null) {
            return;
        }

        try {
            final TemplateReaderWriter reader = new TemplateReaderWriter();
            final File file = new File(path);
            if (file.exists()) {
                final InputStream input = new BufferedInputStream(new FileInputStream(file));
                try {
                    final TemplatePersistenceData[] datas = reader.read(input, null);
                    for (int i = 0; i < datas.length; i++) {
                        updateTemplate(datas[i]);
                    }
                } finally {
                    try {
                        input.close();
                    } catch (final IOException x) {
                    }
                }
            }

            fGroup.getStructuredViewer().refresh();
            updateSourceViewerInput(fGroup.getSingleItem(fGroup.getSelectedItems()));

        } catch (final FileNotFoundException e) {
            openReadErrorDialog(e);
        } catch (final IOException e) {
            openReadErrorDialog(e);
        }
    }

    public void doExport(final TemplatePersistenceData[] templates) {
        final FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);
        dialog.setText(NLS.bind(Messages.CodeTemplates_Export_title, String.valueOf(templates.length)));
        dialog.setFilterExtensions(new String[] { Messages.CodeTemplates_Export_extension });
        dialog.setFileName(Messages.CodeTemplates_Export_filename);
        final String path = dialog.open();

        if (path == null) {
            return;
        }

        final File file = new File(path);

        if (file.isHidden()) {
            MessageDialog.openError(getShell(), Messages.CodeTemplates_Export_Error_title,
                    NLS.bind(Messages.CodeTemplates_Export_Error_Hidden_message, file.getAbsolutePath()));
            return;
        }

        if (file.exists() && !file.canWrite()) {
            MessageDialog.openError(getShell(), Messages.CodeTemplates_Export_Error_title,
                    NLS.bind(Messages.CodeTemplates_Export_Error_CanNotWrite_message, file.getAbsolutePath()));
            return;
        }

        if (!file.exists() || confirmOverwrite(file)) {
            OutputStream output = null;
            try {
                output = new BufferedOutputStream(new FileOutputStream(file));
                final TemplateReaderWriter writer = new TemplateReaderWriter();
                writer.save(templates, output);
                output.close();
            } catch (final IOException e) {
                if (output != null) {
                    try {
                        output.close();
                    } catch (final IOException e2) {
                        // ignore
                    }
                }
                openWriteErrorDialog(e);
            }
        }
    }

    private boolean confirmOverwrite(final File file) {
        return MessageDialog.openQuestion(getShell(), Messages.CodeTemplates_Export_Exists_title,
                NLS.bind(Messages.CodeTemplates_Export_Exists_message, file.getAbsolutePath()));
    }

    /* IConfigurationBlock ********************************************************/

    @Override
    public void performDefaults() {
        fTemplatesStore.restoreDefaults();
        reloadTemplateData();

        // refresh
        fGroup.getStructuredViewer().refresh();
        updateSourceViewerInput(fGroup.getSingleItem(fGroup.getSelectedItems()));
    }

    @Override
    public boolean performOk() {
        if (fProject != null) {
            final TemplatePersistenceData[] templateData = fTemplatesStore.getAllTemplateData();
            fTemplatesStore.setProjectSpecific(isUseProjectSpecificSettings());
            for (int i = 0; i < templateData.length; i++) {
                fTemplatesStore.setProjectSpecific(templateData[i].getId(), isUseProjectSpecificSettings());
            }
        }
        try {
            fTemplatesStore.save();
        } catch (final IOException e) {
            StatetUIPlugin.logUnexpectedError(e);
            openWriteErrorDialog(e);
        }
        return true;
    }

    @Override
    public void performCancel() {
        try {
            fTemplatesStore.revertChanges();
        } catch (final IOException e) {
            openReadErrorDialog(e);
        }
    }

    /* Error Dialogs **************************************************************/

    private void openReadErrorDialog(final Exception e) {
        StatusManager.getManager().handle(new Status(IStatus.ERROR, StatetUIPlugin.PLUGIN_ID, 0,
                Messages.CodeTemplates_error_Read_message, e));
        MessageDialog.openError(getShell(), Messages.CodeTemplates_error_title,
                Messages.CodeTemplates_error_Read_message);
    }

    private void openWriteErrorDialog(final Exception e) {
        StatusManager.getManager().handle(new Status(IStatus.ERROR, StatetUIPlugin.PLUGIN_ID, 0,
                Messages.CodeTemplates_error_Write_message, e));
        MessageDialog.openError(getShell(), Messages.CodeTemplates_error_title,
                Messages.CodeTemplates_error_Write_message);
    }

}