org.eclipse.tcf.internal.debug.ui.launch.TCFPathMapTab.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.tcf.internal.debug.ui.launch.TCFPathMapTab.java

Source

/*******************************************************************************
 * Copyright (c) 2009, 2015 Wind River Systems, Inc. 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:
 *     Wind River Systems - initial API and implementation
 *******************************************************************************/
package org.eclipse.tcf.internal.debug.ui.launch;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;

import org.eclipse.core.runtime.Assert;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnPixelData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ICheckStateProvider;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
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.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.tcf.internal.debug.launch.TCFLaunchDelegate;
import org.eclipse.tcf.internal.debug.launch.TCFLaunchDelegate.PathMapRule;
import org.eclipse.tcf.internal.debug.ui.Activator;
import org.eclipse.tcf.internal.debug.ui.ImageCache;
import org.eclipse.tcf.services.IPathMap;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;

// TODO: add source lookup container that represents ATTR_PATH_MAP
public class TCFPathMapTab extends AbstractLaunchConfigurationTab {

    private CheckboxTableViewer viewer;
    private Button button_add;
    private Button button_edit;
    private Button button_remove;
    private Button button_up;
    private Button button_down;
    private MenuItem item_add;
    private MenuItem item_edit;
    private MenuItem item_remove;
    private MenuItem item_up;
    private MenuItem item_down;

    protected static final int SIZING_TABLE_WIDTH = 500;
    protected static final int SIZING_TABLE_HEIGHT = 300;

    private static final String[] column_ids = { "", //$NON-NLS-1$
            IPathMap.PROP_SOURCE, IPathMap.PROP_DESTINATION, IPathMap.PROP_CONTEXT_QUERY, };

    private static final String[] column_names = { "", //$NON-NLS-1$
            "Source", //$NON-NLS-1$
            "Destination", //$NON-NLS-1$
            "Context query", //$NON-NLS-1$
    };

    protected final static String PROP_ENABLED = "Enabled"; //$NON-NLS-1$
    protected final static String PROP_GENERATED = "Generated"; //$NON-NLS-1$

    private final static String ATTR_PATH_MAP_V1 = TCFLaunchDelegate.ATTR_PATH_MAP + "V1"; //$NON-NLS-1$

    private static final String TAB_ID = "org.eclipse.tcf.launch.pathMapTab"; //$NON-NLS-1$

    private List<IPathMap.PathMapRule> map;

    private class FileMapContentProvider implements IStructuredContentProvider {

        public Object[] getElements(Object input) {
            return map.toArray(new IPathMap.PathMapRule[map.size()]);
        }

        public void inputChanged(Viewer viewer, Object old_input, Object new_input) {
        }

        public void dispose() {
        }
    }

    private class FileCheckStateProvider implements ICheckStateProvider {

        @Override
        public boolean isChecked(Object element) {
            IPathMap.PathMapRule e = (IPathMap.PathMapRule) element;
            if (e.getProperties().containsKey(PROP_ENABLED)) {
                return Boolean.parseBoolean(e.getProperties().get(PROP_ENABLED).toString());
            }
            return true;
        }

        @Override
        public boolean isGrayed(Object element) {
            return false;
        }
    }

    private class FileCheckStateListener implements ICheckStateListener {

        @Override
        public void checkStateChanged(CheckStateChangedEvent event) {
            IPathMap.PathMapRule rule = (IPathMap.PathMapRule) event.getElement();
            if (rule.getProperties().containsKey(PROP_GENERATED)
                    && Boolean.parseBoolean(rule.getProperties().get(PROP_GENERATED).toString())) {
                viewer.refresh();
                return;
            }
            if (event.getChecked())
                rule.getProperties().remove(PROP_ENABLED);
            else
                rule.getProperties().put(PROP_ENABLED, Boolean.FALSE);
            viewer.refresh();
            updateLaunchConfigurationDialog();
        }
    }

    private class FileMapLabelProvider extends LabelProvider implements ITableLabelProvider, IColorProvider {

        public Image getColumnImage(Object element, int column) {
            return null;
        }

        public String getColumnText(Object element, int column) {
            IPathMap.PathMapRule e = (IPathMap.PathMapRule) element;
            Object o = e.getProperties().get(column_ids[column]);
            if (o == null)
                return ""; //$NON-NLS-1$
            return o.toString();
        }

        @Override
        public Color getForeground(Object element) {
            if (element instanceof IPathMap.PathMapRule) {
                IPathMap.PathMapRule rule = (IPathMap.PathMapRule) element;
                if (rule.getProperties().containsKey(PROP_GENERATED)
                        && Boolean.parseBoolean(rule.getProperties().get(PROP_GENERATED).toString())) {
                    return PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_GRAY);
                }
            }
            return null;
        }

        @Override
        public Color getBackground(Object element) {
            return null;
        }
    }

    private Exception init_error;

    public String getName() {
        return "Path Map"; //$NON-NLS-1$
    }

    @Override
    public Image getImage() {
        return ImageCache.getImage(ImageCache.IMG_PATH);
    }

    @Override
    public String getId() {
        return TAB_ID;
    }

    public void createControl(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout(1, false);
        composite.setFont(parent.getFont());
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 1, 1));
        createTable(composite);
        createCustomControls(composite);
        setControl(composite);
    }

    /**
     * Hook to add custom controls below the path map rules table.
     *
     * @param parent The parent composite. Must not be <code>null</code>.
     */
    protected void createCustomControls(Composite parent) {
        // Nothing to do
    }

    private void createTable(Composite parent) {
        Font font = parent.getFont();
        Label map_label = new Label(parent, SWT.WRAP);
        map_label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        map_label.setFont(font);
        map_label.setText("File Path Map Rules:"); //$NON-NLS-1$

        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout(2, false);
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        composite.setFont(font);
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL_BOTH));

        Table table = new Table(composite,
                SWT.CHECK | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
        table.setFont(font);

        configureTable(table);

        viewer = new CheckboxTableViewer(table);
        viewer.setContentProvider(new FileMapContentProvider());
        viewer.setLabelProvider(new FileMapLabelProvider());
        viewer.setCheckStateProvider(new FileCheckStateProvider());
        viewer.addCheckStateListener(new FileCheckStateListener());
        viewer.setColumnProperties(column_ids);
        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                updateButtons();
            }
        });
        viewer.addDoubleClickListener(new IDoubleClickListener() {
            @Override
            public void doubleClick(DoubleClickEvent event) {
                if (button_edit.isEnabled()) {
                    onEdit((IStructuredSelection) viewer.getSelection());
                }
            }
        });

        configureTableViewer(viewer);

        table.pack(true);

        createTableButtons(composite);
    }

    /**
     * Hook to configure the checkbox table viewer.
     *
     * @param viewer The checkbox table viewer. Must not be <code>null</code>.
     */
    protected void configureTableViewer(CheckboxTableViewer viewer) {
        // Nothing to do
    }

    protected void configureTable(final Table table) {
        GridData data = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_BEGINNING);
        data.widthHint = SIZING_TABLE_WIDTH;
        data.heightHint = SIZING_TABLE_HEIGHT;
        table.setLayoutData(data);

        final TableColumn colEnable = new TableColumn(table, 0);
        colEnable.setResizable(false);
        colEnable.setAlignment(SWT.CENTER);
        colEnable.setText(getColumnText(0));

        final TableColumn colSource = new TableColumn(table, 1);
        colSource.setResizable(true);
        colSource.setAlignment(SWT.LEFT);
        colSource.setText(getColumnText(1));

        final TableColumn colDest = new TableColumn(table, 2);
        colDest.setResizable(true);
        colDest.setAlignment(SWT.LEFT);
        colDest.setText(getColumnText(2));

        TableColumn colQuery = null;
        if (showContextQuery()) {
            colQuery = new TableColumn(table, 3);
            colQuery.setResizable(true);
            colQuery.setAlignment(SWT.LEFT);
            colQuery.setText(getColumnText(3));
        }

        TableLayout layout = new TableLayout();
        layout.addColumnData(new ColumnPixelData(30));
        layout.addColumnData(new ColumnPixelData(300));
        layout.addColumnData(new ColumnPixelData(300));
        if (showContextQuery())
            layout.addColumnData(new ColumnPixelData(100));

        table.setLayout(layout);
        table.setHeaderVisible(true);
        table.setLinesVisible(true);
    }

    protected boolean showContextQuery() {
        return true;
    }

    protected String getColumnText(int c) {
        if (c < column_names.length && c >= 0)
            return column_names[c];
        return ""; //$NON-NLS-1$
    }

    private void createTableButtons(Composite parent) {
        Font font = parent.getFont();
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        composite.setFont(font);
        composite.setLayout(layout);
        GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
        composite.setLayoutData(gd);

        Menu menu = new Menu(viewer.getTable());
        SelectionAdapter sel_adapter = null;

        button_add = new Button(composite, SWT.PUSH);
        button_add.setText(" &Add... "); //$NON-NLS-1$
        gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        PixelConverter converter = new PixelConverter(button_add);
        gd.widthHint = converter.convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
        button_add.setLayoutData(gd);
        button_add.addSelectionListener(sel_adapter = new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                onAdd();
            }
        });
        item_add = new MenuItem(menu, SWT.PUSH);
        item_add.setText("&Add..."); //$NON-NLS-1$
        item_add.addSelectionListener(sel_adapter);
        item_add.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ADD));

        button_edit = new Button(composite, SWT.PUSH);
        button_edit.setText(" &Edit... "); //$NON-NLS-1$
        button_edit.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
        button_edit.addSelectionListener(sel_adapter = new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                onEdit((IStructuredSelection) viewer.getSelection());
            }
        });
        item_edit = new MenuItem(menu, SWT.PUSH);
        item_edit.setText("&Edit..."); //$NON-NLS-1$
        item_edit.addSelectionListener(sel_adapter);

        button_remove = new Button(composite, SWT.PUSH);
        button_remove.setText(" &Remove "); //$NON-NLS-1$
        button_remove.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
        button_remove.addSelectionListener(sel_adapter = new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                onRemove((IStructuredSelection) viewer.getSelection());
            }
        });
        item_remove = new MenuItem(menu, SWT.PUSH);
        item_remove.setText("&Remove"); //$NON-NLS-1$
        item_remove.addSelectionListener(sel_adapter);
        item_remove.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ETOOL_DELETE));

        new MenuItem(menu, SWT.SEPARATOR);

        button_up = new Button(composite, SWT.PUSH);
        button_up.setText(" &Up "); //$NON-NLS-1$
        button_up.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
        button_up.addSelectionListener(sel_adapter = new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                onUp();
            }
        });
        item_up = new MenuItem(menu, SWT.PUSH);
        item_up.setText("&Up"); //$NON-NLS-1$
        item_up.addSelectionListener(sel_adapter);

        button_down = new Button(composite, SWT.PUSH);
        button_down.setText(" &Down "); //$NON-NLS-1$
        button_down.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
        button_down.addSelectionListener(sel_adapter = new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                onDown();
            }
        });
        item_down = new MenuItem(menu, SWT.PUSH);
        item_down.setText("&Down"); //$NON-NLS-1$
        item_down.addSelectionListener(sel_adapter);

        viewer.getTable().setMenu(menu);
    }

    private void onAdd() {
        // To guarantee a predictable path map properties iteration order,
        // we have to use a LinkedHashMap.
        int index = viewer.getTable().getSelectionIndex();
        final PathMapRule rule = new PathMapRule(new LinkedHashMap<String, Object>());
        PathMapRuleDialog dialog = new PathMapRuleDialog(getShell(), null, rule, true, showContextQuery());
        if (dialog.open() == Window.OK) {
            if (index >= 0)
                map.add(index, rule);
            else
                map.add(0, rule);
            viewer.refresh(true);
            updateLaunchConfigurationDialog();
            viewer.setSelection(new StructuredSelection(rule), true);
        }
    }

    private void onEdit(IStructuredSelection selection) {
        IPathMap.PathMapRule rule = (IPathMap.PathMapRule) selection.getFirstElement();
        PathMapRuleDialog dialog = new PathMapRuleDialog(getShell(), null, rule, true, showContextQuery());
        dialog.open();
        viewer.refresh(true);
        updateLaunchConfigurationDialog();
    }

    private void onRemove(IStructuredSelection selection) {
        for (Iterator<?> i = ((IStructuredSelection) viewer.getSelection()).iterator(); i.hasNext();) {
            IPathMap.PathMapRule rule = (IPathMap.PathMapRule) i.next();
            map.remove(rule);
        }
        viewer.refresh(true);
        updateLaunchConfigurationDialog();
    }

    private void onUp() {
        int index = viewer.getTable().getSelectionIndex();
        IPathMap.PathMapRule rule = map.remove(index);
        map.add(index - 1, rule);
        viewer.refresh(true);
        updateLaunchConfigurationDialog();
        viewer.setSelection(new StructuredSelection(rule), true);
    }

    private void onDown() {
        int index = viewer.getTable().getSelectionIndex();
        IPathMap.PathMapRule rule = map.remove(index);
        map.add(index + 1, rule);
        viewer.refresh(true);
        updateLaunchConfigurationDialog();
        viewer.setSelection(new StructuredSelection(rule), true);
    }

    protected final TableViewer getViewer() {
        return viewer;
    }

    List<IPathMap.PathMapRule> getPathMap() {
        return Collections.unmodifiableList(map);
    }

    public void initializeFrom(ILaunchConfiguration config) {
        setErrorMessage(null);
        setMessage(null);

        map = new ArrayList<IPathMap.PathMapRule>();
        initializePathMap(map, config);

        viewer.setInput(config);
        updateLaunchConfigurationDialog();
    }

    /**
     * Initialize the given path map.
     *
     * @param map The path map to initialize. Must not be <code>null</code>.
     * @param config The launch configuration. Must not be <code>null</code>.
     */
    protected void initializePathMap(List<IPathMap.PathMapRule> map, ILaunchConfiguration config) {
        Assert.isNotNull(map);
        Assert.isNotNull(config);

        try {
            String s = config.getAttribute(TCFLaunchDelegate.ATTR_PATH_MAP, ""); //$NON-NLS-1$
            String s1 = config.getAttribute(ATTR_PATH_MAP_V1, ""); //$NON-NLS-1$
            List<PathMapRule> m = TCFLaunchDelegate.parsePathMapAttribute(s);
            List<PathMapRule> m1 = TCFLaunchDelegate.parsePathMapAttribute(s1);
            for (IPathMap.PathMapRule rule : m1) {
                map.add(rule);
            }
            int i = -1;
            for (IPathMap.PathMapRule rule : m) {
                if (map.contains(rule))
                    i = map.indexOf(rule);
                else
                    map.add(++i, rule);
            }
        } catch (Exception e) {
            init_error = e;
            setErrorMessage("Cannot read launch configuration: " + e); //$NON-NLS-1$
            Activator.log(e);
        }
    }

    public void performApply(ILaunchConfigurationWorkingCopy config) {
        for (IPathMap.PathMapRule m : map)
            m.getProperties().remove(IPathMap.PROP_ID);
        StringBuffer bf = new StringBuffer();
        StringBuffer bf1 = new StringBuffer();
        for (IPathMap.PathMapRule m : map) {
            if (m.getProperties().containsKey(PROP_GENERATED)) {
                if (Boolean.parseBoolean(m.getProperties().get(PROP_GENERATED).toString())) {
                    continue;
                }
            }

            boolean enabled = true;
            if (m.getProperties().containsKey(PROP_ENABLED)) {
                enabled = Boolean.parseBoolean(m.getProperties().get(PROP_ENABLED).toString());
            }
            if (enabled) {
                m.getProperties().remove(PROP_ENABLED);
                bf.append(m.toString());
            }
            bf1.append(m.toString());
        }
        if (bf.length() == 0)
            config.removeAttribute(TCFLaunchDelegate.ATTR_PATH_MAP);
        else
            config.setAttribute(TCFLaunchDelegate.ATTR_PATH_MAP, bf.toString());

        if (bf1.length() == 0)
            config.removeAttribute(ATTR_PATH_MAP_V1);
        else
            config.setAttribute(ATTR_PATH_MAP_V1, bf1.toString());
    }

    public void setDefaults(ILaunchConfigurationWorkingCopy config) {
        config.removeAttribute(TCFLaunchDelegate.ATTR_PATH_MAP);
        config.removeAttribute(ATTR_PATH_MAP_V1);
    }

    @Override
    protected void updateLaunchConfigurationDialog() {
        super.updateLaunchConfigurationDialog();
        updateButtons();
    }

    protected void updateButtons() {
        boolean singleSelection = ((IStructuredSelection) viewer.getSelection()).size() == 1;
        int index = viewer.getTable().getSelectionIndex();
        int count = viewer.getTable().getItemCount();

        IPathMap.PathMapRule selected = (IPathMap.PathMapRule) ((IStructuredSelection) viewer.getSelection())
                .getFirstElement();
        boolean isGenerated = selected != null && selected.getProperties().containsKey(PROP_GENERATED)
                ? Boolean.parseBoolean(selected.getProperties().get(PROP_GENERATED).toString())
                : false;

        button_remove.setEnabled(!viewer.getSelection().isEmpty() && !isGenerated);
        button_edit.setEnabled(singleSelection && !isGenerated);
        button_up.setEnabled(singleSelection && index > 0 && !isGenerated);
        button_down.setEnabled(singleSelection && index < count - 1 && !isGenerated);

        item_remove.setEnabled(!viewer.getSelection().isEmpty() && !isGenerated);
        item_edit.setEnabled(singleSelection && !isGenerated);
        item_up.setEnabled(singleSelection && index > 0 && !isGenerated);
        item_down.setEnabled(singleSelection && index < count - 1 && !isGenerated);
    }

    @Override
    public boolean isValid(ILaunchConfiguration config) {
        setMessage(null);

        if (init_error != null) {
            setErrorMessage("Cannot read launch configuration: " + init_error); //$NON-NLS-1$
            return false;
        }

        setErrorMessage(null);
        return true;
    }
}