com.nokia.carbide.cdt.internal.api.builder.ui.MMPSelectionUI.java Source code

Java tutorial

Introduction

Here is the source code for com.nokia.carbide.cdt.internal.api.builder.ui.MMPSelectionUI.java

Source

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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 com.nokia.carbide.cdt.internal.api.builder.ui;

import com.nokia.carbide.cdt.builder.EpocEngineHelper;
import com.nokia.carbide.cdt.builder.project.ICarbideBuildConfiguration;
import com.nokia.carbide.cdt.builder.project.ICarbideProjectInfo;
import com.nokia.carbide.cpp.epoc.engine.model.bldinf.IExtension;
import com.nokia.carbide.cpp.sdk.core.ISymbianBuildContext;
import com.nokia.cpp.internal.api.utils.core.Check;
import com.nokia.cpp.internal.api.utils.core.ListenerList;

import org.eclipse.core.runtime.*;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.List;

/*
 * UIDs:
 * table
 * buildOrderColumn
 * fileNameColumn
 * locationColumn
 * selectAllButton
 * deselectAllButton
 * excludeExtensionMakefilesCheckbox
 * excludeTestComponentsCheckbox
 */
/**
 *
 */
public class MMPSelectionUI extends Composite implements ISelectionProvider {

    private static final String AUTOTEST_UID = ".uid"; //$NON-NLS-1$
    private static int MMP_SELECTION_THRESHOLD = 3;

    public final class FileInfo {
        private int ordinal;
        private boolean isTest;
        private boolean isMMP;
        private String fileName;
        private String location;
        private boolean checked;
        private IPath path;

        private FileInfo() {
        }

        private FileInfo(IPath path, int ordinal, boolean isTest) {
            this.path = path;
            this.ordinal = ordinal;
            this.isTest = isTest;
            fileName = path.lastSegment();
            isMMP = "mmp".equalsIgnoreCase(new Path(fileName).getFileExtension()); //$NON-NLS-1$
            String pathString = path.toString();
            location = pathString.substring(0, pathString.length() - fileName.length());
        }

        public int getOrdinal() {
            return ordinal;
        }

        public boolean isTest() {
            return isTest;
        }

        public boolean isMMP() {
            return isMMP;
        }

        public String getFileName() {
            return fileName;
        }

        public String getLocation() {
            return location;
        }

        public boolean isChecked() {
            return checked;
        }

        public void setChecked(boolean checked) {
            this.checked = checked;
        }

        /**
         * Returns whether this info corresponds to path
         * @param path IPath
         * @return boolean
         */
        public boolean hasPath(IPath path) {
            // since this path is absolute, all relative paths should end with the same segments
            IPath testPath = this.path.removeFirstSegments(this.path.segmentCount() - path.segmentCount());
            return Arrays.asList(testPath.segments()).equals(Arrays.asList(path.segments()));
        }

        @Override
        public String toString() {
            return getFileName();
        }

    }

    private final class LabelProvider implements ITableLabelProvider {
        public Image getColumnImage(Object element, int columnIndex) {
            return null;
        }

        public String getColumnText(Object element, int columnIndex) {
            FileInfo info = (FileInfo) element;
            switch (columnIndex) {
            case BUILD_ORDER_COLUMN:
                String suffix = info.isTest() ? " " + ICarbideProjectInfo.TEST_COMPONENT_LABEL : "";
                return Integer.toString(info.getOrdinal()) + suffix;
            case FILENAME_COLUMN:
                return info.getFileName();
            case LOCATION_COLUMN:
                return info.getLocation();
            }
            return null;
        }

        public void addListener(ILabelProviderListener listener) {
        }

        public void dispose() {
        }

        public boolean isLabelProperty(Object element, String property) {
            return false;
        }

        public void removeListener(ILabelProviderListener listener) {
        }
    }

    private static final int BUILD_ORDER_COLUMN = 0;
    private static final int FILENAME_COLUMN = 1;
    private static final int LOCATION_COLUMN = 2;

    private CheckboxTableViewer viewer;
    private Button selectAllButton;
    private Button deselectAllButton;
    private Button excludeExtensionMakefilesCheckbox;
    private Button excludeTestComponentsCheckbox;
    private ListenerList<ISelectionChangedListener> listeners;
    private List<ISymbianBuildContext> buildConfigs;
    private IPath bldInfFile;
    private final IRunnableContext runnableContext;
    private List<FileInfo> data = Collections.emptyList();
    private boolean hasUnnamedProjectExtensions;
    private ViewerFilter testFileFilter;
    private ViewerFilter extMakFileFilter;
    private int lastSortColumn = BUILD_ORDER_COLUMN; // default
    private int sortDirection = 1; // default
    private boolean useSBSv2Builder;

    /**
     * Create the composite
     * @param parent
     * @param style
     */
    public MMPSelectionUI(Composite parent, int style, IRunnableContext runnableContext) {
        super(parent, style);
        this.runnableContext = runnableContext;

        // layout self
        final GridLayout gridLayout = new GridLayout();
        gridLayout.numColumns = 2;
        gridLayout.marginBottom = 5;
        gridLayout.marginRight = 10;
        gridLayout.marginLeft = 10;
        setLayout(gridLayout);

        // viewer
        viewer = CheckboxTableViewer.newCheckList(this, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);
        viewer.setContentProvider(new ArrayContentProvider());
        viewer.setLabelProvider(new LabelProvider());
        Table table = viewer.getTable();
        table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        table.setData(AUTOTEST_UID, "table"); //$NON-NLS-1$

        // build order column
        TableColumn buildOrderColumn = new TableColumn(table, SWT.NONE); // alignment ignored when checkboxes in column
        buildOrderColumn.setText(Messages.getString("MMPSelectionUI.BuildOrderColumnLabel")); //$NON-NLS-1$
        buildOrderColumn.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                updateSortDirection(BUILD_ORDER_COLUMN);
                ViewerComparator comparator = getViewerComparator(BUILD_ORDER_COLUMN);
                viewer.setComparator(comparator);
                setColumnSorting((TableColumn) e.getSource(), sortDirection);
            }
        });
        buildOrderColumn.setData(AUTOTEST_UID, "buildOrderColumn"); //$NON-NLS-1$

        // file name column
        TableColumn fileNameColumn = new TableColumn(table, SWT.LEFT);
        fileNameColumn.setText(Messages.getString("MMPSelectionUI.FileNameColumnLabel")); //$NON-NLS-1$
        fileNameColumn.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                updateSortDirection(FILENAME_COLUMN);
                ViewerComparator comparator = getViewerComparator(FILENAME_COLUMN);
                viewer.setComparator(comparator);
                setColumnSorting((TableColumn) e.getSource(), sortDirection);
            }
        });
        fileNameColumn.setData(AUTOTEST_UID, "fileNameColumn"); //$NON-NLS-1$

        // location column
        final TableColumn locationColumn = new TableColumn(table, SWT.LEFT);
        locationColumn.setText(Messages.getString("MMPSelectionUI.LocationColumnLabel")); //$NON-NLS-1$
        locationColumn.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                updateSortDirection(LOCATION_COLUMN);
                ViewerComparator comparator = getViewerComparator(LOCATION_COLUMN);
                viewer.setComparator(comparator);
                setColumnSorting((TableColumn) e.getSource(), sortDirection);
            }
        });
        locationColumn.setData(AUTOTEST_UID, "locationColumn"); //$NON-NLS-1$

        setColumnSorting(buildOrderColumn, sortDirection);
        table.setHeaderVisible(true);

        // listen to checks
        viewer.addCheckStateListener(new ICheckStateListener() {
            public void checkStateChanged(CheckStateChangedEvent event) {
                FileInfo info = (FileInfo) event.getElement();
                info.setChecked(event.getChecked());
                fireSelectionChanged();
            }
        });

        // listen to double clicks
        viewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                for (Iterator iterator = selection.iterator(); iterator.hasNext();) {
                    FileInfo info = (FileInfo) iterator.next();
                    info.setChecked(!info.isChecked());
                    viewer.setChecked(info, info.isChecked());
                    fireSelectionChanged();
                }
            }
        });

        // select all/deselect all buttons
        final Composite composite = new Composite(this, SWT.NONE);
        composite.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false));
        composite.setLayout(new GridLayout());

        selectAllButton = new Button(composite, SWT.NONE);
        selectAllButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
        selectAllButton.setText(Messages.getString("MMPSelectionUI.SelectAllLabel")); //$NON-NLS-1$
        selectAllButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                setAllChecked(true);
            }
        });
        selectAllButton.setData(AUTOTEST_UID, "selectAllButton"); //$NON-NLS-1$
        deselectAllButton = new Button(composite, SWT.NONE);
        deselectAllButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
        deselectAllButton.setText(Messages.getString("MMPSelectionUI.DeselectAllLabel")); //$NON-NLS-1$
        deselectAllButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                setAllChecked(false);
            }
        });
        deselectAllButton.setData(AUTOTEST_UID, "deselectAllButton"); //$NON-NLS-1$

        // exclude extension makefiles check box
        excludeExtensionMakefilesCheckbox = new Button(this, SWT.CHECK);
        excludeExtensionMakefilesCheckbox.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
        excludeExtensionMakefilesCheckbox.setText(Messages.getString("MMPSelectionUI.ExcludeExtMakefilesLabel")); //$NON-NLS-1$
        excludeExtensionMakefilesCheckbox.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                boolean exclude = ((Button) e.getSource()).getSelection();
                if (extMakFileFilter == null) {
                    extMakFileFilter = new ViewerFilter() {
                        @Override
                        public boolean select(Viewer viewer, Object parentElement, Object element) {
                            FileInfo info = (FileInfo) element;
                            boolean select = info.isMMP();
                            if (!select)
                                info.setChecked(false);
                            return select;
                        }
                    };
                }
                if (exclude) {
                    viewer.addFilter(extMakFileFilter);
                    fireSelectionChanged();
                } else {
                    viewer.removeFilter(extMakFileFilter);
                }
                updateCheckedStateFromViewer();
            }
        });
        excludeExtensionMakefilesCheckbox.setData(AUTOTEST_UID, "excludeExtensionMakefilesCheckbox"); //$NON-NLS-1$

        // exclude test components checkbox
        excludeTestComponentsCheckbox = new Button(this, SWT.CHECK);
        excludeTestComponentsCheckbox.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
        excludeTestComponentsCheckbox.setText(Messages.getString("MMPSelectionUI.ExcludeTestCompsLabel")); //$NON-NLS-1$
        excludeTestComponentsCheckbox.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                boolean exclude = ((Button) e.getSource()).getSelection();
                if (testFileFilter == null) {
                    testFileFilter = new ViewerFilter() {
                        @Override
                        public boolean select(Viewer viewer, Object parentElement, Object element) {
                            FileInfo info = (FileInfo) element;
                            boolean select = !info.isTest();
                            if (!select)
                                info.setChecked(false);
                            return select;
                        }
                    };
                }
                if (exclude) {
                    viewer.addFilter(testFileFilter);
                    fireSelectionChanged();
                } else {
                    viewer.removeFilter(testFileFilter);
                }
                updateCheckedStateFromViewer();
            }
        });
        excludeTestComponentsCheckbox.setData(AUTOTEST_UID, "excludeTestComponentsCheckbox"); //$NON-NLS-1$
    }

    private void updateCheckedStateFromViewer() {
        for (FileInfo info : data) {
            info.setChecked(viewer.getChecked(info));
        }
    }

    /**
     * Sets the data for this UI from bld.inf file and list of build configs
     * @param bldInfFile IPath
     * @param buildConfigs List<ISymbianBuildContext>
     */
    public void setBldInfFile(final IPath bldInfFile, final List<ISymbianBuildContext> buildContexts,
            final boolean useSBSv2Builder) {
        if (bldInfFile.equals(this.bldInfFile) && buildConfigs.equals(this.buildConfigs))
            return;

        this.bldInfFile = bldInfFile;
        this.buildConfigs = buildContexts;
        this.useSBSv2Builder = useSBSv2Builder;

        try {
            runnableContext.run(true, true, new IRunnableWithProgress() {
                public void run(IProgressMonitor monitor) {
                    data = new ArrayList<FileInfo>();
                    List<IPath> normalMakMakeList = new ArrayList<IPath>();
                    List<IPath> testMakMakeList = new ArrayList<IPath>();
                    EpocEngineHelper.getMakMakeFiles(bldInfFile, buildConfigs, normalMakMakeList, testMakMakeList,
                            monitor);
                    int i = 0;
                    for (IPath currPath : normalMakMakeList) {
                        data.add(new FileInfo(currPath, ++i, false));
                    }
                    for (IPath currPath : testMakMakeList) {
                        data.add(new FileInfo(currPath, ++i, true));
                    }

                    // named extensions are only supported in SBSv2
                    if (useSBSv2Builder) {
                        List<IExtension> normalNamedExtensionsList = new ArrayList<IExtension>();
                        List<IExtension> testNamedExtensionsList = new ArrayList<IExtension>();
                        EpocEngineHelper.getNamedExtensions(bldInfFile, buildConfigs, normalNamedExtensionsList,
                                testNamedExtensionsList, monitor);

                        for (IExtension extension : normalNamedExtensionsList) {
                            data.add(new FileInfo(new Path(extension.getName()), ++i, false));
                        }
                        for (IExtension extension : testNamedExtensionsList) {
                            data.add(new FileInfo(new Path(extension.getName()), ++i, true));
                        }
                    }

                    hasUnnamedProjectExtensions = EpocEngineHelper.hasUnnamedExtensions(bldInfFile, buildConfigs,
                            monitor);
                }
            });
        } catch (InvocationTargetException e) {
        } catch (InterruptedException e) {
            // Nothing to do if the user interrupts.
        }
        viewer.setInput(data);
        TableColumn[] columns = viewer.getTable().getColumns();
        for (TableColumn tableColumn : columns) {
            tableColumn.pack();
        }
        if (data.size() > MMP_SELECTION_THRESHOLD) {
            setAllChecked(false);
        } else {
            setAllChecked(true);
        }
    }

    /**
     * Sets checked state of all items
     * @param state boolean
     */
    public void setAllChecked(boolean state) {
        for (TableItem item : viewer.getTable().getItems()) { // only want filtered items
            item.setChecked(state);
            FileInfo info = (FileInfo) item.getData();
            info.setChecked(state);
        }
        fireSelectionChanged();
    }

    private ViewerComparator getViewerComparator(int column) {
        switch (column) {
        case BUILD_ORDER_COLUMN:
            return new ViewerComparator() {
                public int compare(Viewer viewer, Object e1, Object e2) {
                    FileInfo info1 = (FileInfo) e1;
                    FileInfo info2 = (FileInfo) e2;
                    return (info1.getOrdinal() - info2.getOrdinal()) * sortDirection;
                }
            };
        case FILENAME_COLUMN:
            return new ViewerComparator() {
                public int compare(Viewer viewer, Object e1, Object e2) {
                    FileInfo info1 = (FileInfo) e1;
                    FileInfo info2 = (FileInfo) e2;
                    return info1.getFileName().compareToIgnoreCase(info2.getFileName()) * sortDirection;
                }
            };
        case LOCATION_COLUMN:
            return new ViewerComparator() {
                public int compare(Viewer viewer, Object e1, Object e2) {
                    FileInfo info1 = (FileInfo) e1;
                    FileInfo info2 = (FileInfo) e2;
                    return info1.getLocation().compareToIgnoreCase(info2.getLocation()) * sortDirection;
                }
            };

        }
        return null;
    }

    private void updateSortDirection(int column) {
        if (lastSortColumn == column) {
            sortDirection *= -1;
        } else {
            sortDirection = 1;
            lastSortColumn = column;
        }
    }

    private void setColumnSorting(TableColumn column, int order) {
        Table table = viewer.getTable();
        table.setSortColumn(column);
        table.setSortDirection(order > 0 ? SWT.UP : SWT.DOWN);
        updateCheckedStateFromViewer();
    }

    @Override
    protected void checkSubclass() {
        // Disable the check that prevents subclassing of SWT components
    }

    /**
     * Returns structured selection of FileInfos that can be queried for isChecked()
     * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
     * @return ISelection
     */
    public ISelection getSelection() {
        return new StructuredSelection(data);
    }

    /**
     * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
     */
    public void addSelectionChangedListener(ISelectionChangedListener listener) {
        if (listeners == null)
            listeners = new ListenerList<ISelectionChangedListener>();
        listeners.add(listener);
    }

    /**
     * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
     */
    public void removeSelectionChangedListener(ISelectionChangedListener listener) {
        if (listeners != null)
            listeners.remove(listener);
    }

    private void fireSelectionChanged() {
        if (listeners != null) {
            for (ISelectionChangedListener listener : listeners) {
                SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection());
                listener.selectionChanged(event);
            }
        }
    }

    /**
     * Expects structured selection FileInfos from which will update checked state
     * FileInfos must be those received from getSelection()
     * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
     * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
     */
    public void setSelection(ISelection selection) {
        Check.checkState(selection instanceof IStructuredSelection);
        IStructuredSelection structuredSelection = (IStructuredSelection) selection;
        for (Iterator iterator = structuredSelection.iterator(); iterator.hasNext();) {
            Object element = iterator.next();
            Check.checkContract(element instanceof FileInfo);
            FileInfo info = (FileInfo) element;
            viewer.setChecked(info, info.isChecked());
        }
    }

    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        viewer.getTable().setEnabled(enabled);
        selectAllButton.setEnabled(enabled);
        deselectAllButton.setEnabled(enabled);
        excludeExtensionMakefilesCheckbox.setEnabled(enabled);
        excludeTestComponentsCheckbox.setEnabled(enabled);
    }

    /**
     * @return true if all items checked
     */
    public boolean isCheckedAll() {
        for (FileInfo info : data) {
            if (!info.isChecked())
                return false;
        }

        return true;
    }

    /**
     * @return true if all items unchecked
     */
    public boolean isUncheckedAll() {
        for (FileInfo info : data) {
            if (info.isChecked())
                return false;
        }

        return true;
    }

    public String getExtensionsWarningMessage() {
        if (hasUnnamedProjectExtensions && !isCheckedAll()) {
            if (useSBSv2Builder) {
                return Messages.getString("MMPSelectionUI.prjExtensionsWarningSBSv2"); //$NON-NLS-1$
            } else {
                return Messages.getString("MMPSelectionUI.prjExtensionsWarningSBSv1"); //$NON-NLS-1$
            }
        }
        return null;
    }

    /**
     * Set the MMP selection threshold. When number of MMPs <= threshold, all MMPs are selected by default.
     * When number of MMPs > threshold, no MMP is selected by default.
     * @param threshold - threshold for MMP selection
     */
    public static void setMMPSelectionThreshold(int threshold) {
        MMP_SELECTION_THRESHOLD = threshold;
    }

}