org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationBlock.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationBlock.java

Source

/*******************************************************************************
 * Copyright (c) 2009 QNX Software Systems 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:
 *     QNX Software Systems - initial API and implementation
 *******************************************************************************/

package org.eclipse.cdt.internal.ui.workingsets;

import java.util.Collection;

import org.eclipse.core.resources.IProject;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.FontDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.IFilter;
import org.eclipse.jface.viewers.IFontProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.model.WorkbenchLabelProvider;

import org.eclipse.cdt.ui.CDTSharedImages;

import org.eclipse.cdt.internal.ui.dialogs.OptionalMessageDialog;

/**
 * A block of UI controls for management of working set configurations. These collect the selection of project
 * configurations for the member projects of the working sets into named presets.
 * 
 * @author Christian W. Damus (cdamus)
 * 
 * @since 6.0
 */
public class WorkingSetConfigurationBlock {

    private static final String BUILD_PROMPT_DIALOG_ID = "workingsets.build.prompt"; //$NON-NLS-1$
    private static final int BUILD_PROMPT_DIALOG_NO = 0;
    private static final int BUILD_PROMPT_DIALOG_CANCEL = 1;
    private static final int BUILD_PROMPT_DIALOG_YES = 2;

    private WorkspaceSnapshot workspace;
    private WorkingSetConfigsController controller;

    private IWorkingSetProxy.ISnapshot initialSelection;
    private IFilter workingSetFilter;

    private Control contents;

    /**
     * Initializes me. I take the most recently used working set as my initial selection.
     * 
     * @param workspace
     *            the workspace snapshot to edit
     */
    public WorkingSetConfigurationBlock(WorkspaceSnapshot workspace) {
        this(workspace, null);
    }

    /**
     * Initializes me with my initial selection.
     * 
     * @param workspace
     *            the workspace snapshot to edit
     * @param initialSelection
     *            my initial selection
     */
    public WorkingSetConfigurationBlock(WorkspaceSnapshot workspace, IWorkingSetProxy.ISnapshot initialSelection) {

        this.workspace = workspace;
        this.initialSelection = initialSelection;
    }

    /**
     * Queries the working set filter, if any, that restricts the display of working sets.
     * 
     * @return my working-set filter
     */
    public IFilter getWorkingSetFilter() {
        return workingSetFilter;
    }

    /**
     * Assigns a filter to restrict the working sets that are shown.
     * 
     * @param filter
     *            a working-set filter
     */
    public void setWorkingSetFilter(IFilter filter) {
        this.workingSetFilter = filter;
    }

    /**
     * Creates the contents of the working set configuration management control block.
     * 
     * @param parent
     *            the parent composite in which to create my controls
     * 
     * @return my controls
     */
    public Control createContents(Composite parent) {
        SashForm sashForm = new SashForm(parent, SWT.VERTICAL | SWT.SMOOTH);

        GridLayoutFactory layoutFactory = GridLayoutFactory.fillDefaults();
        createWorkingSetConfigsArea(sashForm, layoutFactory.extendedMargins(0, 0, 0, 15));
        createProjectConfigsArea(sashForm, layoutFactory.extendedMargins(0, 0, 15, 0));

        sashForm.setWeights(new int[] { 1, 1 });

        contents = sashForm;

        return sashForm;
    }

    /**
     * Creates the "working set configurations" pane in the upper part of the sash form.
     * 
     * @param parent
     *            the parent composite
     * @param layoutFactory
     *            a layout-factory to use to lay out the composite in a grid, possibly pre-configured. Its use
     *            is optional
     * 
     * @return the working set configurations pane
     */
    protected Composite createWorkingSetConfigsArea(Composite parent, GridLayoutFactory layoutFactory) {
        Composite result = new Composite(parent, SWT.NONE);
        layoutFactory.numColumns(2).applyTo(result);

        GridDataFactory layoutDataFactory = GridDataFactory.fillDefaults();

        Label label = new Label(result, SWT.NONE);
        label.setText(WorkingSetMessages.WSConfigDialog_wsTree_label);
        layoutDataFactory.span(2, 1).applyTo(label);

        controller = new WorkingSetConfigsController(workspace, initialSelection);

        TreeViewer tree = new TreeViewer(result);
        layoutDataFactory.span(1, 1).align(SWT.FILL, SWT.FILL).grab(true, true).hint(250, SWT.DEFAULT)
                .applyTo(tree.getControl());

        tree.setContentProvider(new WSConfigsContentProvider());
        tree.setLabelProvider(new WSConfigsLabelProvider(tree));
        controller.setTreeViewer(tree);

        tree.setComparator(new ViewerComparator() {
            @Override
            public int category(Object element) {
                if (element instanceof IWorkingSetConfiguration.ISnapshot) {
                    IWorkingSetConfiguration.ISnapshot config = (IWorkingSetConfiguration.ISnapshot) element;
                    if (config.isReadOnly()) {
                        return 0;
                    }
                }
                return 1;
            }
        });

        tree.getTree().getAccessible().addAccessibleListener(new AccessibleAdapter() {
            @Override
            public void getName(AccessibleEvent e) {
                e.result = WorkingSetMessages.WSConfigDialog_wsTree_accessible_name;
            }
        });

        Composite buttons = new Composite(result, SWT.NONE);
        layoutDataFactory.grab(false, false).hint(SWT.DEFAULT, SWT.DEFAULT).applyTo(buttons);
        layoutFactory.numColumns(1).extendedMargins(0, 0, 0, 0).applyTo(buttons);

        Button button = new Button(buttons, SWT.PUSH);
        layoutDataFactory.align(SWT.FILL, SWT.BEGINNING).applyTo(button);
        button.setText(WorkingSetMessages.WSConfigDialog_add_label);
        controller.setAddButton(button);

        button = new Button(buttons, SWT.PUSH);
        layoutDataFactory.applyTo(button);
        button.setText(WorkingSetMessages.WSConfigDialog_remove_label);
        controller.setRemoveButton(button);

        button = new Button(buttons, SWT.PUSH);
        layoutDataFactory.applyTo(button);
        button.setText(WorkingSetMessages.WSConfigDialog_rename_label);
        controller.setRenameButton(button);

        button = new Button(buttons, SWT.PUSH);
        layoutDataFactory.applyTo(button);
        button.setText(WorkingSetMessages.WSConfigDialog_activate_label);
        controller.setActivateButton(button);

        button = new Button(buttons, SWT.PUSH);
        layoutDataFactory.applyTo(button);
        button.setText(WorkingSetMessages.WSConfigDialog_build_label);
        controller.setBuildButton(button);

        return result;
    }

    /**
     * Creates the "project configurations" pane in the lower part of the sash form.
     * 
     * @param parent
     *            the parent composite
     * @param layoutFactory
     *            a layout-factory to use to lay out the composite in a grid, possibly pre-configured. Its use
     *            is optional
     * 
     * @return the project configurations pane
     */
    protected Composite createProjectConfigsArea(Composite parent, GridLayoutFactory layoutFactory) {
        Composite result = new Composite(parent, SWT.NONE);
        layoutFactory.numColumns(1).applyTo(result);

        GridDataFactory layoutDataFactory = GridDataFactory.fillDefaults();

        Label label = new Label(result, SWT.NONE);
        label.setText(WorkingSetMessages.WSConfigDialog_projTree_label);
        layoutDataFactory.applyTo(label);

        ProjectConfigsController projectsController = new ProjectConfigsController();
        CheckboxTreeViewer tree = new CheckboxTreeViewer(result);
        layoutDataFactory.span(1, 1).align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(tree.getControl());

        controller.setProjectConfigsController(projectsController);
        projectsController.setWorkingSetConfigurationsController(controller);

        projectsController.setTreeViewer(tree);

        tree.setComparator(new ViewerComparator());

        tree.getTree().getAccessible().addAccessibleListener(new AccessibleAdapter() {
            @Override
            public void getName(AccessibleEvent e) {
                e.result = WorkingSetMessages.WSConfigDialog_projTree_accessible_name;
            }
        });

        return result;
    }

    /**
     * Saves the working set configurations to storage.
     */
    public void save() {
        workspace.save();
    }

    /**
     * Builds the projects that were reconfigured by the dialog, if any. The user is prompted (if prompting is
     * not disabled via the preference) before building. The user has the options to build, not build, or
     * cancel. The result indicates cancellation.
     * 
     * @return <code>true</code> if the user opted to save changes and exit the dialog (with or without
     *         build); <code>false</code> if the user cancelled and the dialog should remain open and unsaved
     */
    public boolean build() {
        boolean result = true;
        Collection<IProject> projects = workspace.getProjectsToBuild();

        if (!projects.isEmpty()) {
            int defaultButton = OptionalMessageDialog.getDialogDetail(BUILD_PROMPT_DIALOG_ID);
            if (defaultButton == OptionalMessageDialog.NO_DETAIL) {
                defaultButton = BUILD_PROMPT_DIALOG_YES; // yes button is the default-default
            }

            int button = OptionalMessageDialog.open(BUILD_PROMPT_DIALOG_ID, contents.getShell(),
                    WorkingSetMessages.WSConfigDialog_buildPrompt_title, null,
                    WorkingSetMessages.WSConfigDialog_buildPrompt_message, MessageDialog.QUESTION, new String[] {
                            IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL, IDialogConstants.YES_LABEL },
                    defaultButton);

            if (button == OptionalMessageDialog.NOT_SHOWN) {
                // handle the case where the dialog was suppressed. Get the current default
                button = defaultButton;
            } else if (button != BUILD_PROMPT_DIALOG_CANCEL) {
                // store non-cancel selection as the new default answer
                OptionalMessageDialog.setDialogDetail(BUILD_PROMPT_DIALOG_ID, button);
            }

            switch (button) {
            case BUILD_PROMPT_DIALOG_YES:
                // do the build
                new BuildJob(projects).schedule();
                break;
            case BUILD_PROMPT_DIALOG_NO:
                // just don't build
                break;
            default: // BUILD_PROMPT_DIALOG_CANCEL
                result = false;
                break;
            }
        }

        return result;
    }

    //
    // Nested classes
    //

    /**
     * Simple content provider for the working set configurations tree.
     * 
     * @author Christian W. Damus (cdamus)
     */
    private class WSConfigsContentProvider implements ITreeContentProvider {
        private Collection<IWorkingSetProxy> workingSets;

        @Override
        public Object[] getChildren(Object parentElement) {
            if (parentElement == workingSets) {
                Collection<IWorkingSetProxy> filtered = filterWorkingSets(workingSets);
                return filtered.toArray();
            } else if (parentElement instanceof IWorkingSetProxy) {
                return ((IWorkingSetProxy) parentElement).getConfigurations().toArray();
            } else {
                return new Object[0];
            }
        }

        private Collection<IWorkingSetProxy> filterWorkingSets(Collection<IWorkingSetProxy> workingSets) {
            if (workingSetFilter == null) {
                return workingSets;
            }

            Collection<IWorkingSetProxy> result = new java.util.ArrayList<IWorkingSetProxy>();

            for (IWorkingSetProxy next : workingSets) {
                if (workingSetFilter.select(next)) {
                    result.add(next);
                }
            }

            return result;
        }

        @Override
        public Object getParent(Object element) {
            return (element instanceof IWorkingSetConfiguration)
                    ? ((IWorkingSetConfiguration) element).getWorkingSet()
                    : null;
        }

        @Override
        public boolean hasChildren(Object element) {
            return (element != null) && !(element instanceof IWorkingSetConfiguration);
        }

        @Override
        public Object[] getElements(Object inputElement) {
            return getChildren(inputElement);
        }

        @Override
        public void dispose() {
            // nothing to dispose
        }

        @Override
        @SuppressWarnings("unchecked")
        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            workingSets = (Collection<IWorkingSetProxy>) newInput;
        }

    }

    /**
     * Label provider for working sets and their configurations. The active configuration is highlighted in
     * bold and affixed with an "(active)" decoration. The special read-only configuration is further
     * differentiated with an italic font.
     * 
     * @author Christian W. Damus (cdamus)
     */
    private class WSConfigsLabelProvider extends LabelProvider implements IFontProvider {
        private WorkbenchLabelProvider wbLabels = new WorkbenchLabelProvider();
        private Image configImage = CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_CONFIG);
        private Font defaultFont;
        private ResourceManager fonts = new LocalResourceManager(JFaceResources.getResources());

        WSConfigsLabelProvider(Viewer viewer) {
            defaultFont = viewer.getControl().getFont();
        }

        @Override
        public String getText(Object element) {
            if (element instanceof IWorkingSetConfiguration) {
                IWorkingSetConfiguration config = (IWorkingSetConfiguration) element;

                if (config.isActive()) {
                    return WorkingSetConfiguration.isReadOnly(config)
                            ? WorkingSetMessages.WSConfigDialog_implicit_config
                            : NLS.bind(WorkingSetMessages.WSConfigDialog_active_config, config.getName());
                }
                return config.getName();
            } else if (element instanceof IWorkingSetProxy) {
                return ((IWorkingSetProxy) element).resolve().getLabel();
            }

            return wbLabels.getText(element);
        }

        @Override
        public Image getImage(Object element) {
            if (element instanceof IWorkingSetConfiguration) {
                return configImage;
            } else if (element instanceof IWorkingSetProxy) {
                return wbLabels.getImage(((IWorkingSetProxy) element).resolve());
            }

            return wbLabels.getImage(element);
        }

        @Override
        public void dispose() {
            wbLabels.dispose();
            fonts.dispose();
            super.dispose();
        }

        @Override
        public Font getFont(Object element) {
            if (element instanceof IWorkingSetConfiguration) {
                IWorkingSetConfiguration config = (IWorkingSetConfiguration) element;
                if (config.isActive()) {
                    FontDescriptor desc = FontDescriptor.createFrom(defaultFont);

                    desc = WorkingSetConfiguration.isReadOnly(config) ? desc.withStyle(SWT.BOLD | SWT.ITALIC)
                            : desc.withStyle(SWT.BOLD);
                    return (Font) fonts.get(desc);
                }
            }

            return wbLabels.getFont(element);
        }
    }
}