org.eclipse.oomph.setup.presentation.PreferenceCaptureDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.oomph.setup.presentation.PreferenceCaptureDialog.java

Source

/*
 * Copyright (c) 2015 Ed Merks (Berlin, Germany) 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:
 *    Ed Merks - initial API and implementation
 */
package org.eclipse.oomph.setup.presentation;

import org.eclipse.oomph.internal.ui.UIPlugin;
import org.eclipse.oomph.preferences.PreferenceNode;
import org.eclipse.oomph.preferences.PreferencesFactory;
import org.eclipse.oomph.preferences.Property;
import org.eclipse.oomph.preferences.util.PreferencesUtil;
import org.eclipse.oomph.setup.CompoundTask;
import org.eclipse.oomph.setup.PreferenceTask;
import org.eclipse.oomph.setup.SetupTask;
import org.eclipse.oomph.setup.ui.recorder.RecorderTransaction;
import org.eclipse.oomph.util.IORuntimeException;
import org.eclipse.oomph.util.Pair;
import org.eclipse.oomph.util.PropertiesUtil;

import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.AbstractTreeIterator;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.edit.provider.ItemProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
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.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Ed Merks
 */
public class PreferenceCaptureDialog extends Dialog {
    private static final URI INSTANCE_URI = URI.createURI("//" + PreferencesUtil.INSTANCE_NODE);

    protected ILabelProvider labelProvider;

    protected FilteringAdapterFactoryContentProvider availablePreferencesContentProvider;

    protected FilteringAdapterFactoryContentProvider selectedPreferencesContentProvider;

    protected Set<Object> included = new HashSet<Object>();

    protected boolean fromEclipsePreferenceFile;

    /**
     * @since 2.6
     */
    public PreferenceCaptureDialog(Shell parent, AdapterFactory adapterFactory, boolean fromEclipsePreferenceFile) {
        super(parent);

        setShellStyle(getShellStyle() | SWT.RESIZE | SWT.MAX);

        this.fromEclipsePreferenceFile = fromEclipsePreferenceFile;

        labelProvider = new AdapterFactoryLabelProvider(adapterFactory);
        availablePreferencesContentProvider = new FilteringAdapterFactoryContentProvider(adapterFactory, false);
        selectedPreferencesContentProvider = new FilteringAdapterFactoryContentProvider(adapterFactory, true);
    }

    @Override
    protected void configureShell(Shell shell) {
        super.configureShell(shell);
        shell.setText(fromEclipsePreferenceFile ? "Import Preferences" : "Capture Preferences");
        shell.setImage(SetupEditorPlugin.INSTANCE
                .getSWTImage(fromEclipsePreferenceFile ? "preference_importer" : "preference_picker"));
    }

    protected List<?> getAvailablePreferences() {
        PreferenceNode rootPreferenceNode = PreferencesUtil.getRootPreferenceNode(Collections.unmodifiableSet(
                new LinkedHashSet<String>(Arrays.asList(new String[] { PreferencesUtil.BUNDLE_DEFAULTS_NODE,
                        PreferencesUtil.DEFAULT_NODE, PreferencesUtil.INSTANCE_NODE }))),
                false);

        Map<URI, Pair<String, String>> preferences = new HashMap<URI, Pair<String, String>>();
        for (PreferenceNode preferenceNode : rootPreferenceNode.getChildren()) {
            traverse(preferences, preferenceNode);
        }

        return RecorderTransaction.record(preferences);
    }

    protected void traverse(Map<URI, Pair<String, String>> preferences, PreferenceNode preferenceNode) {
        for (PreferenceNode childPreferenceNode : preferenceNode.getChildren()) {
            traverse(preferences, childPreferenceNode);
        }

        for (Property property : preferenceNode.getProperties()) {
            preferences.put(INSTANCE_URI.appendSegments(property.getRelativePath().segments()),
                    new Pair<String, String>(null, property.getValue()));
        }
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        final ItemProvider input = new ItemProvider();

        Composite contents = (Composite) super.createDialogArea(parent);

        GridLayout contentsGridLayout = (GridLayout) contents.getLayout();
        contentsGridLayout.numColumns = 3;

        GridData contentsGridData = (GridData) contents.getLayoutData();
        contentsGridData.horizontalAlignment = SWT.FILL;
        contentsGridData.verticalAlignment = SWT.FILL;

        Text preferenceFileText = null;

        if (fromEclipsePreferenceFile) {
            Group preferenceFileGroup = new Group(contents, SWT.NONE);
            preferenceFileGroup.setText("Eclipse Preference File");
            preferenceFileGroup.setLayout(new GridLayout(2, false));
            preferenceFileGroup.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 3, 1));

            final Text finalPreferenceFileText = preferenceFileText = new Text(preferenceFileGroup, SWT.BORDER);
            preferenceFileText.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 1, 1));

            Button preferenceFileBrowseButton = new Button(preferenceFileGroup, SWT.PUSH);
            preferenceFileBrowseButton.setText("Browse...");
            preferenceFileBrowseButton.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(SelectionEvent e) {
                    FileDialog dialog = new FileDialog(getShell(), SWT.OPEN | SWT.MULTI);
                    dialog.setFilterExtensions(new String[] { "*.epf" });
                    String result = dialog.open();
                    if (result != null) {
                        finalPreferenceFileText.setText(result);
                    }
                }
            });
        }

        Group filterGroupComposite = new Group(contents, SWT.NONE);
        filterGroupComposite.setText("Filter Available Preferences");
        filterGroupComposite.setLayout(new GridLayout(1, false));
        filterGroupComposite.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 3, 1));

        Composite availablePreferencesComposite = new Composite(contents, SWT.NONE);
        {
            GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
            data.horizontalAlignment = SWT.END;
            availablePreferencesComposite.setLayoutData(data);

            GridLayout layout = new GridLayout();
            data.horizontalAlignment = SWT.FILL;
            layout.marginHeight = 0;
            layout.marginWidth = 0;
            layout.numColumns = 1;
            availablePreferencesComposite.setLayout(layout);
        }

        Label availablePreferencesLabel = new Label(availablePreferencesComposite, SWT.NONE);
        availablePreferencesLabel.setText("Available Preferences");
        GridData availablePreferencesLabelGridData = new GridData();
        availablePreferencesLabelGridData.verticalAlignment = SWT.FILL;
        availablePreferencesLabelGridData.horizontalAlignment = SWT.FILL;
        availablePreferencesLabel.setLayoutData(availablePreferencesLabelGridData);

        PatternFilter filter = new PatternFilter();
        filter.setIncludeLeadingWildcard(true);
        final FilteredTree availablePreferencesTree = new FilteredTree(availablePreferencesComposite,
                SWT.MULTI | SWT.BORDER, filter, true);
        GridData availablePreferencesTreeGridData = new GridData();
        availablePreferencesTreeGridData.widthHint = Display.getCurrent().getBounds().width / 5;
        availablePreferencesTreeGridData.heightHint = Display.getCurrent().getBounds().height / 3;
        availablePreferencesTreeGridData.verticalAlignment = SWT.FILL;
        availablePreferencesTreeGridData.horizontalAlignment = SWT.FILL;
        availablePreferencesTreeGridData.grabExcessHorizontalSpace = true;
        availablePreferencesTreeGridData.grabExcessVerticalSpace = true;
        availablePreferencesTree.setLayoutData(availablePreferencesTreeGridData);

        Control filterControl = availablePreferencesTree.getChildren()[0];
        filterControl.setParent(filterGroupComposite);
        filterControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        final TreeViewer availablePreferencesTreeViewer = availablePreferencesTree.getViewer();
        availablePreferencesTreeViewer.setContentProvider(availablePreferencesContentProvider);
        availablePreferencesTreeViewer.setLabelProvider(labelProvider);
        if (!fromEclipsePreferenceFile) {
            input.getChildren().addAll(getAvailablePreferences());
        }

        availablePreferencesTreeViewer.setInput(input);

        Composite controlButtons = new Composite(contents, SWT.NONE);
        GridData controlButtonsGridData = new GridData();
        controlButtonsGridData.verticalAlignment = SWT.FILL;
        controlButtonsGridData.horizontalAlignment = SWT.FILL;
        controlButtons.setLayoutData(controlButtonsGridData);

        GridLayout controlsButtonGridLayout = new GridLayout();
        controlButtons.setLayout(controlsButtonGridLayout);

        new Label(controlButtons, SWT.NONE);

        final Button addButton = new Button(controlButtons, SWT.PUSH);
        addButton.setText("Add");
        GridData addButtonGridData = new GridData();
        addButtonGridData.verticalAlignment = SWT.FILL;
        addButtonGridData.horizontalAlignment = SWT.FILL;
        addButton.setLayoutData(addButtonGridData);

        final Button removeButton = new Button(controlButtons, SWT.PUSH);
        removeButton.setText("Remove");
        GridData removeButtonGridData = new GridData();
        removeButtonGridData.verticalAlignment = SWT.FILL;
        removeButtonGridData.horizontalAlignment = SWT.FILL;
        removeButton.setLayoutData(removeButtonGridData);

        Label spaceLabel = new Label(controlButtons, SWT.NONE);
        GridData spaceLabelGridData = new GridData();
        spaceLabelGridData.verticalSpan = 2;
        spaceLabel.setLayoutData(spaceLabelGridData);

        Composite selectedPreferencesComposite = new Composite(contents, SWT.NONE);
        {
            GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
            data.horizontalAlignment = SWT.END;
            selectedPreferencesComposite.setLayoutData(data);

            GridLayout layout = new GridLayout();
            data.horizontalAlignment = SWT.FILL;
            layout.marginHeight = 0;
            layout.marginWidth = 0;
            layout.numColumns = 1;
            selectedPreferencesComposite.setLayout(layout);
        }

        Label selectedPreferencesLabel = new Label(selectedPreferencesComposite, SWT.NONE);
        selectedPreferencesLabel.setText("Selected Preferences");
        GridData selectedPreferencesLabelGridData = new GridData();
        selectedPreferencesLabelGridData.horizontalSpan = 2;
        selectedPreferencesLabelGridData.horizontalAlignment = SWT.FILL;
        selectedPreferencesLabelGridData.verticalAlignment = SWT.FILL;
        selectedPreferencesLabel.setLayoutData(selectedPreferencesLabelGridData);

        final Tree selectedPreferencesTree = new Tree(selectedPreferencesComposite, SWT.MULTI | SWT.BORDER);
        GridData selectedPreferencesTreeGridData = new GridData();
        selectedPreferencesTreeGridData.widthHint = Display.getCurrent().getBounds().width / 5;
        selectedPreferencesTreeGridData.heightHint = Display.getCurrent().getBounds().height / 3;
        selectedPreferencesTreeGridData.verticalAlignment = SWT.FILL;
        selectedPreferencesTreeGridData.horizontalAlignment = SWT.FILL;
        selectedPreferencesTreeGridData.grabExcessHorizontalSpace = true;
        selectedPreferencesTreeGridData.grabExcessVerticalSpace = true;
        selectedPreferencesTree.setLayoutData(selectedPreferencesTreeGridData);

        final TreeViewer selectedPreferencesTreeViewer = new TreeViewer(selectedPreferencesTree);
        selectedPreferencesTreeViewer.setContentProvider(selectedPreferencesContentProvider);
        selectedPreferencesTreeViewer.setLabelProvider(labelProvider);
        selectedPreferencesTreeViewer.setInput(input);

        availablePreferencesTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                if (addButton.isEnabled()) {
                    addButton.notifyListeners(SWT.Selection, null);
                }
            }
        });

        selectedPreferencesTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                if (removeButton.isEnabled()) {
                    removeButton.notifyListeners(SWT.Selection, null);
                }
            }
        });

        addButton.addSelectionListener(new FilteringSelectionAdapter(selectedPreferencesTreeViewer,
                availablePreferencesTreeViewer, input, true));
        removeButton.addSelectionListener(new FilteringSelectionAdapter(selectedPreferencesTreeViewer,
                availablePreferencesTreeViewer, input, false));

        if (preferenceFileText != null) {
            preferenceFileText.addModifyListener(new ModifyListener() {
                public void modifyText(ModifyEvent e) {
                    included.clear();
                    EList<Object> children = input.getChildren();
                    children.clear();

                    try {
                        Map<URI, Pair<String, String>> preferences = new HashMap<URI, Pair<String, String>>();
                        Map<String, String> loadProperties = PropertiesUtil
                                .loadProperties(new File(((Text) e.widget).getText()));
                        for (Map.Entry<String, String> entry : loadProperties.entrySet()) {
                            String key = entry.getKey();
                            if (key.startsWith("/")) {
                                preferences.put(PreferencesFactory.eINSTANCE.createURI(key),
                                        new Pair<String, String>(null, entry.getValue()));
                            }
                        }

                        List<SetupTask> availablePreferences = RecorderTransaction.record(preferences);
                        children.addAll(availablePreferences);
                    } catch (IORuntimeException ex) {
                        children.add(new ItemProvider(ex.getMessage(), UIPlugin.INSTANCE.getImage("error")));
                    }

                    availablePreferencesTreeViewer.refresh();
                    selectedPreferencesTreeViewer.refresh();
                }
            });
        }

        return contents;
    }

    @Override
    public boolean close() {
        availablePreferencesContentProvider.dispose();
        selectedPreferencesContentProvider.dispose();
        return super.close();
    }

    public Map<URI, Pair<String, String>> getResult() {
        Map<URI, Pair<String, String>> result = new HashMap<URI, Pair<String, String>>();
        for (Object object : included) {
            PreferenceTask preferenceTask = (PreferenceTask) object;
            result.put(PreferencesFactory.eINSTANCE.createURI(preferenceTask.getKey()),
                    new Pair<String, String>(null, preferenceTask.getValue()));
        }

        return result;
    }

    /**
     * @author Ed Merks
     */
    private class FilteringSelectionAdapter extends SelectionAdapter {
        private final TreeViewer selectedPreferencesTreeViewer;

        private final TreeViewer availablePreferencesTreeViewer;

        private final ItemProvider input;

        private boolean add;

        private FilteringSelectionAdapter(TreeViewer selectedPreferencesTreeViewer,
                TreeViewer availablePreferencesTreeViewer, ItemProvider input, boolean add) {
            this.selectedPreferencesTreeViewer = selectedPreferencesTreeViewer;
            this.availablePreferencesTreeViewer = availablePreferencesTreeViewer;
            this.input = input;
            this.add = add;
        }

        @Override
        public void widgetSelected(SelectionEvent event) {
            IStructuredSelection selection = (IStructuredSelection) (add ? availablePreferencesTreeViewer
                    : selectedPreferencesTreeViewer).getSelection();
            List<Object> newSelection = new ArrayList<Object>();

            for (Object object : selection.toArray()) {
                Object[] children = (add ? availablePreferencesContentProvider : selectedPreferencesContentProvider)
                        .getChildren(object);
                if (children.length != 0) {
                    List<Object> choices = Arrays.asList(children);
                    newSelection.addAll(choices);
                } else {
                    newSelection.add(object);
                }
            }

            Set<Object> nonCandidates = new HashSet<Object>(newSelection);
            Object candidate = null;
            Object bestCandidate = null;

            for (TreeIterator<Object> it = (add ? availablePreferencesContentProvider
                    : selectedPreferencesContentProvider).getAllContents(input, false); it.hasNext();) {
                candidate = it.next();
                if (nonCandidates.remove(candidate)) {
                    if (!(bestCandidate instanceof PreferenceTask)) {
                        bestCandidate = null;
                    }
                } else {
                    if (!(candidate instanceof CompoundTask)) {
                        bestCandidate = candidate;
                    }

                    if (nonCandidates.isEmpty()) {
                        break;
                    }
                }
            }

            if (add) {
                included.addAll(newSelection);
            } else {
                included.removeAll(newSelection);
            }

            for (Object object : input.getChildren()) {
                if (object instanceof CompoundTask) {
                    CompoundTask compoundTask = (CompoundTask) object;
                    EList<SetupTask> setupTasks = compoundTask.getSetupTasks();
                    if (newSelection.containsAll(setupTasks)) {
                        newSelection.removeAll(setupTasks);
                        newSelection.add(compoundTask);
                    }
                }
            }

            selectedPreferencesTreeViewer.refresh();
            availablePreferencesTreeViewer.refresh();

            (add ? selectedPreferencesTreeViewer : availablePreferencesTreeViewer)
                    .setSelection(new StructuredSelection(newSelection));

            if (bestCandidate == null && candidate != null) {
                bestCandidate = candidate;
            }

            if (bestCandidate != null) {
                (add ? availablePreferencesTreeViewer : selectedPreferencesTreeViewer)
                        .setSelection(new StructuredSelection(bestCandidate));
            }
        }
    }

    /**
     * @author Ed Merks
     */
    private final class FilteringAdapterFactoryContentProvider extends AdapterFactoryContentProvider {
        private boolean include;

        private FilteringAdapterFactoryContentProvider(AdapterFactory adapterFactory, boolean include) {
            super(adapterFactory);
            this.include = include;
        }

        public TreeIterator<Object> getAllContents(Object object, boolean includeRoot) {
            return new AbstractTreeIterator<Object>(object, includeRoot) {
                private static final long serialVersionUID = 1L;

                @Override
                protected Iterator<? extends Object> getChildren(Object object) {
                    return Arrays.asList(object instanceof ItemProvider
                            ? FilteringAdapterFactoryContentProvider.this.getElements(object)
                            : FilteringAdapterFactoryContentProvider.this.getChildren(object)).iterator();
                }
            };
        }

        @Override
        public Object[] getElements(Object object) {
            List<Object> elements = ((ItemProvider) object).getChildren();
            List<Object> result = new ArrayList<Object>();

            for (Object element : elements) {
                if (include) {
                    for (Object child : getChildren(element)) {
                        if (included.contains(child)) {
                            result.add(element);
                            break;
                        }
                    }
                } else if (element instanceof ItemProvider) {
                    result.add(element);
                } else if (!included.containsAll(Arrays.asList(getChildren(element)))) {
                    result.add(element);
                }
            }

            return result.toArray();
        }

        @Override
        public Object[] getChildren(Object object) {
            Object[] children = super.getChildren(object);
            List<Object> result = new ArrayList<Object>();

            for (Object child : children) {
                if (included.contains(child) == include) {
                    result.add(child);
                }
            }

            return result.toArray();
        }
    }
}