org.eclipse.handly.ui.workingset.AbstractWorkingSetPage.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.handly.ui.workingset.AbstractWorkingSetPage.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Vladimir Piskarev (1C) - adaptation
 *******************************************************************************/
package org.eclipse.handly.ui.workingset;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.handly.ui.viewer.LabelComparator;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.wizard.WizardPage;
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.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.IWorkingSetPage;

/**
 * A partial implementation of {@link IWorkingSetPage}. A tree viewer on the
 * left is used to show the workspace content, a table viewer on the right
 * is used to show the working set content. Buttons to move content from right
 * to left and vice versa are available between the two viewers. A text field
 * allows to set/change the working set name.
 * <p>
 * Adapted from <code>org.eclipse.jdt.internal.ui.workingsets.AbstractWorkingSetWizardPage</code>.
 * </p>
 * @see #getPageId()
 * @see #configureTree(TreeViewer)
 * @see #configureTable(TableViewer)
 */
public abstract class AbstractWorkingSetPage extends WizardPage implements IWorkingSetPage {
    protected static final IAdaptable[] NO_ELEMENTS = new IAdaptable[0];

    private Text workingSetName;
    private TreeViewer tree;
    private TableViewer table;
    private ITreeContentProvider treeContentProvider;
    private IWorkingSet workingSet;
    private boolean firstCheck = true;
    private HashSet<IAdaptable> selectedElements = new HashSet<IAdaptable>();
    private IStructuredSelection initialSelection;

    /**
     * Creates a new wizard page with the given name, title, and image.
     *
     * @param pageName the name of the page
     * @param title the title for this wizard page,
     *  or <code>null</code> if none
     * @param titleImage the image descriptor for the title of this wizard page,
     *  or <code>null</code> if none
     */
    public AbstractWorkingSetPage(String pageName, String title, ImageDescriptor titleImage) {
        super(pageName, title, titleImage);
        setDescription(Messages.AbstractWorkingSetPage_workingSet_description);
        IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
        if (activeWorkbenchWindow != null) {
            ISelection selection = activeWorkbenchWindow.getSelectionService().getSelection();
            if (selection instanceof IStructuredSelection)
                initialSelection = (IStructuredSelection) selection;
        }
    }

    public void setInitialSelection(IStructuredSelection selection) {
        this.initialSelection = selection;
    }

    @Override
    public void createControl(Composite parent) {
        initializeDialogUnits(parent);

        Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayout(new GridLayout());
        composite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
        setControl(composite);

        Label label = new Label(composite, SWT.WRAP);
        label.setText(Messages.AbstractWorkingSetPage_workingSet_name);
        GridData gd = new GridData(
                GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER);
        label.setLayoutData(gd);

        workingSetName = new Text(composite, SWT.SINGLE | SWT.BORDER);
        workingSetName.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
        workingSetName.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                validateInput();
            }
        });

        Composite leftCenterRightComposite = new Composite(composite, SWT.NONE);
        GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
        gridData.heightHint = convertHeightInCharsToPixels(20);
        leftCenterRightComposite.setLayoutData(gridData);
        GridLayout gridLayout = new GridLayout(3, false);
        gridLayout.marginHeight = 0;
        gridLayout.marginWidth = 0;
        leftCenterRightComposite.setLayout(gridLayout);

        Composite leftComposite = new Composite(leftCenterRightComposite, SWT.NONE);
        gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
        gridData.widthHint = convertWidthInCharsToPixels(40);
        leftComposite.setLayoutData(gridData);
        gridLayout = new GridLayout(1, false);
        gridLayout.marginHeight = 0;
        gridLayout.marginWidth = 0;
        leftComposite.setLayout(gridLayout);

        Composite centerComposite = new Composite(leftCenterRightComposite, SWT.NONE);
        gridLayout = new GridLayout(1, false);
        gridLayout.marginHeight = 0;
        gridLayout.marginWidth = 0;
        centerComposite.setLayout(gridLayout);
        centerComposite.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, false, false));

        Composite rightComposite = new Composite(leftCenterRightComposite, SWT.NONE);
        gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
        gridData.widthHint = convertWidthInCharsToPixels(40);
        rightComposite.setLayoutData(gridData);
        gridLayout = new GridLayout(1, false);
        gridLayout.marginHeight = 0;
        gridLayout.marginWidth = 0;
        rightComposite.setLayout(gridLayout);

        createTree(leftComposite);
        createTable(rightComposite);

        if (workingSet != null)
            workingSetName.setText(workingSet.getName());

        initializeSelectedElements();
        validateInput();

        table.setInput(selectedElements);
        table.refresh(true);
        tree.refresh(true);

        createButtonBar(centerComposite);

        workingSetName.setFocus();
        workingSetName.setSelection(0, workingSetName.getText().length());

        Dialog.applyDialogFont(composite);
    }

    @Override
    public void finish() {
        String name = workingSetName.getText();
        IAdaptable[] elements = getFinalWorkingSetElements(workingSet,
                selectedElements.toArray(new IAdaptable[selectedElements.size()]));

        if (workingSet == null) {
            IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager();
            workingSet = workingSetManager.createWorkingSet(name, elements);
            workingSet.setId(getPageId());
        } else {
            workingSet.setName(name);
            workingSet.setElements(elements);
        }
    }

    @Override
    public IWorkingSet getSelection() {
        return workingSet;
    }

    @Override
    public void setSelection(IWorkingSet workingSet) {
        if (workingSet == null)
            throw new IllegalArgumentException();

        this.workingSet = workingSet;
        if (getContainer() != null && getShell() != null && workingSetName != null) {
            firstCheck = false;
            workingSetName.setText(workingSet.getName());
            initializeSelectedElements();
            validateInput();
        }
    }

    /**
     * Returns the page id as specified in the extension point
     * <code>org.eclipse.ui.workingSets</code>.
     * 
     * @return the page id
     */
    protected abstract String getPageId();

    /**
     * Configures the tree viewer used on the left side of the dialog.
     *
     * Implementors must set:
     * <ul>
     *  <li>The content provider</li>
     *  <li>The label provider</li>
     *  <li>The viewers input</li>
     * </ul>
     * They may also set:
     * <ul>
     *   <li>The viewer comparator</li>
     *   <li>Any viewer filter</li>
     * </ul>
     * 
     * @param tree the tree viewer to configure
     * @see #initializeTreeSelection(TreeViewer)
     */
    protected abstract void configureTree(TreeViewer tree);

    /**
     * Configures the table viewer used on the right side of the dialog.
     *
     * Implementors must set:
     * <ul>
     *  <li>The label provider</li>
     * </ul>
     * They may also set:
     * <ul>
     *   <li>The viewer comparator</li>
     * </ul>
     * They must not set:
     * <ul>
     *  <li>The viewers content provider</li>
     *  <li>The viewers input</li>
     *  <li>Any viewer filter</li>
     * </ul>
     *
     * @param table the table viewer to configure
     */
    protected abstract void configureTable(TableViewer table);

    protected final IStructuredSelection getInitialSelection() {
        return initialSelection;
    }

    /**
     * Sets initial selection for the tree viewer of the dialog.
     *
     * @param tree the tree viewer
     */
    protected void initializeTreeSelection(TreeViewer tree) {
        if (workingSet == null)
            return;

        IStructuredSelection selection = getInitialSelection();
        if (selection != null && !selection.isEmpty()) {
            IAdaptable[] elements = adaptElements(getAdaptables(selection.toArray()));
            if (elements.length > 0) {
                tree.setSelection(new StructuredSelection(elements));
            }
        }
    }

    /**
     * Transforms the supplied elements into elements that are suitable for
     * containment in the working set.
     * 
     * @param objects the objects to transform
     * @return an array of transformed elements that may be empty if no elements
     *  from the original array are suitable
     */
    @SuppressWarnings("restriction")
    protected IAdaptable[] adaptElements(IAdaptable[] objects) {
        IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager();
        IWorkingSet workingSet = workingSetManager.createWorkingSet("", NO_ELEMENTS); //$NON-NLS-1$
        workingSet.setId(getPageId());
        ((org.eclipse.ui.internal.AbstractWorkingSet) workingSet).connect(workingSetManager);
        try {
            return workingSet.adaptElements(objects);
        } finally {
            ((org.eclipse.ui.internal.AbstractWorkingSet) workingSet).disconnect();
        }

        // Unfortunately, this "clean" implementation doesn't work,
        // as WorkingSet#adaptElements expects a WorkingSetManager
        // rather than AbstractWorkingSetManager:

        //        ILocalWorkingSetManager workingSetManager =
        //            PlatformUI.getWorkbench().createLocalWorkingSetManager();
        //        try
        //        {
        //            IWorkingSet workingSet =
        //                workingSetManager.createWorkingSet("", NO_ELEMENTS);
        //            workingSet.setId(getPageId());
        //            workingSetManager.addWorkingSet(workingSet);
        //            return workingSet.adaptElements(objects);
        //        }
        //        finally
        //        {
        //            workingSetManager.dispose();
        //        }
    }

    protected static IAdaptable[] getAdaptables(Object[] elements) {
        ArrayList<IAdaptable> result = new ArrayList<IAdaptable>(elements.length);
        for (Object element : elements) {
            if (element instanceof IAdaptable)
                result.add((IAdaptable) element);
        }
        return result.toArray(new IAdaptable[result.size()]);
    }

    /**
     * Returns the elements that are to be shown in the table initially.
     * Returns an empty array if the table should be initially empty.
     * The given working set is the working set that will be configured
     * by this dialog, or <code>null</code> if it does not yet exist.
     *
     * @param workingSet the working set to configure,
     *  or <code>null</code> if it does not yet exist
     * @return the elements to show in the table (not <code>null</code>)
     */
    protected IAdaptable[] getInitialWorkingSetElements(IWorkingSet workingSet) {
        if (workingSet != null)
            return workingSet.getElements();
        else {
            IStructuredSelection selection = getInitialSelection();
            if (selection != null && !selection.isEmpty())
                return adaptElements(getAdaptables(selection.toArray()));
        }
        return NO_ELEMENTS;
    }

    /**
     * Returns the elements that are to be set into the working set
     * configured by this dialog.
     *
     * @param workingSet the working set to configure,
     *  or <code>null</code> if it does not yet exist
     * @param elements the elements explicitly selected by the user
     *  (never <code>null</code>) 
     * @return the elements to ultimately set into the working set
     *  (not <code>null</code>)
     */
    protected IAdaptable[] getFinalWorkingSetElements(IWorkingSet workingSet, IAdaptable[] elements) {
        return elements;
    }

    private void createTree(Composite parent) {
        Label label = new Label(parent, SWT.NONE);
        label.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false));
        label.setText(Messages.AbstractWorkingSetPage_workspace_content);

        tree = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI);
        tree.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        tree.setComparator(new LabelComparator());
        tree.addFilter(new AddedElementsFilter());
        tree.setUseHashlookup(true);

        configureTree(tree);
        initializeTreeSelection(tree);

        treeContentProvider = (ITreeContentProvider) tree.getContentProvider();
    }

    private void createButtonBar(Composite parent) {
        Label spacer = new Label(parent, SWT.NONE);
        spacer.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));

        final Button addButton = new Button(parent, SWT.PUSH);
        addButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
        addButton.setText(Messages.AbstractWorkingSetPage_add_button);
        addButton.setEnabled(!tree.getSelection().isEmpty());

        final Button addAllButton = new Button(parent, SWT.PUSH);
        addAllButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
        addAllButton.setText(Messages.AbstractWorkingSetPage_addAll_button);
        addAllButton.setEnabled(tree.getTree().getItems().length > 0);

        final Button removeButton = new Button(parent, SWT.PUSH);
        removeButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
        removeButton.setText(Messages.AbstractWorkingSetPage_remove_button);
        removeButton.setEnabled(!table.getSelection().isEmpty());

        final Button removeAllButton = new Button(parent, SWT.PUSH);
        removeAllButton.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, false, false));
        removeAllButton.setText(Messages.AbstractWorkingSetPage_removeAll_button);
        removeAllButton.setEnabled(!selectedElements.isEmpty());

        tree.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                addButton.setEnabled(!event.getSelection().isEmpty());
            }
        });

        addButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                addTreeSelection();

                removeAllButton.setEnabled(true);
                addAllButton.setEnabled(tree.getTree().getItems().length > 0);
            }
        });

        tree.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                addTreeSelection();

                removeAllButton.setEnabled(true);
                addAllButton.setEnabled(tree.getTree().getItems().length > 0);
            }
        });

        table.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                removeButton.setEnabled(!event.getSelection().isEmpty());
            }
        });

        removeButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                removeTableSelection();

                addAllButton.setEnabled(true);
                removeAllButton.setEnabled(!selectedElements.isEmpty());
            }
        });

        table.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                removeTableSelection();

                addAllButton.setEnabled(true);
                removeAllButton.setEnabled(!selectedElements.isEmpty());
            }
        });

        addAllButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                TreeItem[] items = tree.getTree().getItems();
                for (TreeItem item : items) {
                    Object element = item.getData();
                    if (element instanceof IAdaptable)
                        selectedElements.add((IAdaptable) element);
                }
                table.refresh();
                tree.refresh();

                addAllButton.setEnabled(false);
                removeAllButton.setEnabled(true);
            }
        });

        removeAllButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                selectedElements.clear();

                table.refresh();
                tree.refresh();

                removeAllButton.setEnabled(false);
                addAllButton.setEnabled(true);
            }
        });
    }

    /*
     * Moves selected elements in the tree into the table
     */
    private void addTreeSelection() {
        IStructuredSelection selection = (IStructuredSelection) tree.getSelection();
        IAdaptable[] elements = getAdaptables(selection.toArray());
        selectedElements.addAll(Arrays.asList(elements));
        table.add(elements);
        tree.remove(elements);
        table.setSelection(selection);
        table.getControl().setFocus();
        validateInput();
    }

    /*
     * Moves the selected elements in the table into the tree
     */
    private void removeTableSelection() {
        IStructuredSelection selection = (IStructuredSelection) table.getSelection();
        selectedElements.removeAll(selection.toList());
        Object[] selectedElements = selection.toArray();
        table.remove(selectedElements);
        try {
            tree.getTree().setRedraw(false);
            for (Object selectedElement : selectedElements) {
                tree.refresh(treeContentProvider.getParent(selectedElement), true);
            }
        } finally {
            tree.getTree().setRedraw(true);
        }
        tree.setSelection(selection);
        tree.getControl().setFocus();
        validateInput();
    }

    private void createTable(Composite parent) {
        Label label = new Label(parent, SWT.WRAP);
        label.setText(Messages.AbstractWorkingSetPage_workingSet_content);
        label.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));

        table = new TableViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI);

        GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        table.getControl().setLayoutData(gd);

        table.setComparator(new LabelComparator());
        table.setUseHashlookup(true);

        configureTable(table);

        table.setContentProvider(new IStructuredContentProvider() {
            public Object[] getElements(Object inputElement) {
                return selectedElements.toArray();
            }

            public void dispose() {
            }

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

    private void validateInput() {
        String errorMessage = null;
        String infoMessage = null;
        String newText = workingSetName.getText();

        if (!newText.equals(newText.trim())) {
            errorMessage = Messages.AbstractWorkingSetPage_warning_nameWhitespace;
        }

        if (newText.isEmpty()) {
            if (firstCheck) {
                setPageComplete(false);
                firstCheck = false;
                return;
            } else {
                errorMessage = Messages.AbstractWorkingSetPage_warning_nameMustNotBeEmpty;
            }
        }

        firstCheck = false;

        if (errorMessage == null && workingSet != null && !newText.equals(workingSet.getName())) {
            IWorkingSet[] workingSets = PlatformUI.getWorkbench().getWorkingSetManager().getWorkingSets();
            for (IWorkingSet workingSet : workingSets) {
                if (newText.equals(workingSet.getName())) {
                    errorMessage = Messages.AbstractWorkingSetPage_warning_workingSetExists;
                }
            }
        }

        if (!hasSelectedElement()) {
            infoMessage = Messages.AbstractWorkingSetPage_warning_resourceMustBeChecked;
        }

        setMessage(infoMessage, INFORMATION);
        setErrorMessage(errorMessage);
        setPageComplete(errorMessage == null);
    }

    private boolean hasSelectedElement() {
        return !selectedElements.isEmpty();
    }

    private void initializeSelectedElements() {
        selectedElements.clear();
        selectedElements.addAll(Arrays.asList(getInitialWorkingSetElements(workingSet)));
    }

    private class AddedElementsFilter extends ViewerFilter {
        @Override
        public boolean select(Viewer viewer, Object parentElement, Object element) {
            return !selectedElements.contains(element);
        }
    }
}