/******************************************************************************* * Copyright (c) 2009, 2015 ARM Limited 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: * ARM Limited - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.debug.internal.ui.sourcelookup; import java.util.ArrayList; import java.util.List; import org.eclipse.cdt.debug.core.sourcelookup.MappingSourceContainer; import org.eclipse.cdt.debug.internal.core.sourcelookup.MapEntrySourceContainer; import org.eclipse.cdt.debug.internal.ui.CDebugImages; import org.eclipse.cdt.debug.internal.ui.ICDebugHelpContextIds; import org.eclipse.cdt.debug.internal.ui.SWTUtil; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.sourcelookup.ISourceContainer; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.DialogCellEditor; import org.eclipse.jface.viewers.ICellModifier; 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.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; 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.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.Control; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Item; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.PlatformUI; public class MappingSourceContainerDialog extends TitleAreaDialog { class EntryCellModifier implements ICellModifier { /* (non-Javadoc) * @see org.eclipse.jface.viewers.ICellModifier#canModify(java.lang.Object, java.lang.String) */ @Override public boolean canModify(Object element, String property) { return (CP_COMPILATION_PATH.equals(property) || CP_FILE_SYSTEM_PATH.equals(property)); } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ICellModifier#getValue(java.lang.Object, java.lang.String) */ @Override public Object getValue(Object element, String property) { if (element instanceof MapEntrySourceContainer) { MapEntrySourceContainer entry = (MapEntrySourceContainer)element; if (CP_COMPILATION_PATH.equals(property)) return entry.getBackendPathStr(); if (CP_FILE_SYSTEM_PATH.equals(property)) return entry.getLocalPath().toOSString(); } return null; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ICellModifier#modify(java.lang.Object, java.lang.String, java.lang.Object) */ @Override public void modify(Object element, String property, Object value) { MapEntrySourceContainer entry = (element instanceof Item) ? (MapEntrySourceContainer)((Item)element).getData() : (MapEntrySourceContainer)element; boolean isDirty = false; if (CP_COMPILATION_PATH.equals(property)) { entry.setBackendPathStr((String)value); isDirty = true; } else if (CP_FILE_SYSTEM_PATH.equals(property)) { entry.setLocalPath(new Path((String)value)); isDirty = true; } if (isDirty) refresh(); } } class DirectoryCellEditor extends DialogCellEditor { DirectoryCellEditor(Composite parent) { super(parent); } /* (non-Javadoc) * @see org.eclipse.jface.viewers.DialogCellEditor#openDialogBox(org.eclipse.swt.widgets.Control) */ @Override protected Object openDialogBox(Control cellEditorWindow) { TableItem[] selection = ((Table)cellEditorWindow.getParent()).getSelection(); DirectoryDialog dialog = new DirectoryDialog(cellEditorWindow.getShell()); dialog.setFilterPath(selection[0].getText(1)); return dialog.open(); } } class EntryLabelProvider extends LabelProvider implements ITableLabelProvider { /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int) */ @Override public Image getColumnImage(Object element, int columnIndex) { if (element instanceof MapEntrySourceContainer && columnIndex == 0) { return CDebugImages.get(CDebugImages.IMG_OBJS_PATH_MAP_ENTRY); } return null; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int) */ @Override public String getColumnText(Object element, int columnIndex) { if (element instanceof MapEntrySourceContainer) { MapEntrySourceContainer entry = (MapEntrySourceContainer)element; if (columnIndex == 0) return entry.getBackendPathStr(); if (columnIndex == 1) return entry.getLocalPath().toOSString(); } return null; } } // Column properties private static final String CP_COMPILATION_PATH = "compilationPath"; //$NON-NLS-1$ private static final String CP_FILE_SYSTEM_PATH = "fileSystemPath"; //$NON-NLS-1$ private MappingSourceContainer fOriginalContainer; private MappingSourceContainer fContainer; private Text fNameText; private Button fMappingWithBackendEnabledCheck; private TableViewer fViewer; private Button fAddButton; private Button fRemoveButton; private Button fUpButton; private Button fDownButton; private ControlListener fTableListener; private boolean fIsValid = true; public MappingSourceContainerDialog(Shell shell, MappingSourceContainer container) { super(shell); fOriginalContainer = container; fContainer = container.copy(); fTableListener = new ControlListener() { /* (non-Javadoc) * @see org.eclipse.swt.events.ControlListener#controlMoved(org.eclipse.swt.events.ControlEvent) */ @Override public void controlMoved(ControlEvent e) { MappingSourceContainerDialog.this.controlMoved(e); } /* (non-Javadoc) * @see org.eclipse.swt.events.ControlListener#controlResized(org.eclipse.swt.events.ControlEvent) */ @Override public void controlResized(ControlEvent e) { MappingSourceContainerDialog.this.controlResized(e); } }; } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.TrayDialog#close() */ @Override public boolean close() { fViewer.getTable().removeControlListener(fTableListener); fContainer.dispose(); return super.close(); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.Dialog#isResizable() */ @Override protected boolean isResizable() { return true; } /* (non-Javadoc) * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell) */ @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(SourceLookupUIMessages.PathMappingDialog_16); newShell.setToolTipText(SourceLookupUIMessages.MappingSourceContainerDialog_0); newShell.setImage(CDebugImages.get( CDebugImages.IMG_OBJS_PATH_MAPPING)); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.Dialog#createContents(org.eclipse.swt.widgets.Composite) */ @Override protected Control createContents(Composite parent) { Control control = super.createContents(parent); initialize(); return control; } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) */ @Override protected Control createDialogArea(Composite parent) { Composite control = (Composite)super.createDialogArea(parent); setTitle(SourceLookupUIMessages.PathMappingDialog_0); setTitleImage(CDebugImages.get(CDebugImages.IMG_WIZBAN_PATH_MAPPING)); Composite composite = new Composite(control, SWT.None); composite.setLayout(new GridLayout(2, false)); composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); createNameArea(composite); createViewer(composite); createViewerButtonBar(composite); createMappingWithBackendEnabledArea(composite); PlatformUI.getWorkbench().getHelpSystem().setHelp(getShell(), ICDebugHelpContextIds.SOURCE_PATH_MAP_ENTRY_DIALOG); return control; } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.Dialog#okPressed() */ @Override protected void okPressed() { fOriginalContainer.clear(); fOriginalContainer.setName(fNameText.getText().trim()); fOriginalContainer.setIsMappingWithBackendEnabled(fMappingWithBackendEnabledCheck.getSelection()); try { fOriginalContainer.addMapEntries((MapEntrySourceContainer[])fContainer.getSourceContainers()); } catch (CoreException e) { } super.okPressed(); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.TitleAreaDialog#setErrorMessage(java.lang.String) */ @Override public void setErrorMessage(String newErrorMessage) { fIsValid = (newErrorMessage == null); super.setErrorMessage(newErrorMessage); } public MappingSourceContainer getContainer() { return fOriginalContainer; } private void createNameArea(Composite parent) { Composite composite = new Composite(parent, SWT.None); composite.setLayout(new GridLayout(2, false)); composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1)); Label label = new Label(composite, SWT.NONE); label.setText(SourceLookupUIMessages.PathMappingDialog_12); fNameText = new Text(composite, SWT.BORDER | SWT.SINGLE); GridData data = new GridData(SWT.FILL, SWT.CENTER, false, false); data.widthHint = 200; fNameText.setLayoutData(data); fNameText.addModifyListener(new ModifyListener() { /* (non-Javadoc) * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent) */ @Override public void modifyText(ModifyEvent e) { } }); } private void createMappingWithBackendEnabledArea(Composite parent) { Composite composite = new Composite(parent, SWT.None); composite.setLayout(new GridLayout(1, false)); composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1)); fMappingWithBackendEnabledCheck = new Button(composite, SWT.CHECK); fMappingWithBackendEnabledCheck.setText(SourceLookupUIMessages.PathMappingDialog_MappingWithBackendEnabled); fMappingWithBackendEnabledCheck.setToolTipText(SourceLookupUIMessages.PathMappingDialog_MappingWithBackendEnabledTooltip); GridData data = new GridData(SWT.FILL, SWT.CENTER, false, false); fMappingWithBackendEnabledCheck.setLayoutData(data); } private void createViewer(Composite parent) { Composite tableComp = new Composite(parent, SWT.NONE); tableComp.setLayout(new GridLayout()); tableComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); fViewer = new TableViewer(tableComp, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION); Table table = fViewer.getTable(); table.setLinesVisible(true); table.setHeaderVisible(true); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.widthHint = 500; data.heightHint = 200; table.setLayoutData(data); table.addControlListener(fTableListener); TableColumn nameColumn = new TableColumn(table, SWT.NULL); nameColumn.setResizable(true); nameColumn.setText(SourceLookupUIMessages.PathMappingDialog_1); nameColumn.setToolTipText(SourceLookupUIMessages.MappingSourceContainerDialog_1); TableColumn valueColumn = new TableColumn(table, SWT.NULL); valueColumn.setResizable(true); valueColumn.setText(SourceLookupUIMessages.PathMappingDialog_2); valueColumn.setToolTipText(SourceLookupUIMessages.MappingSourceContainerDialog_2); fViewer.setColumnProperties( new String[] { CP_COMPILATION_PATH, CP_FILE_SYSTEM_PATH, }); fViewer.setContentProvider(new IStructuredContentProvider() { /* (non-Javadoc) * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) */ @Override public Object[] getElements(Object inputElement) { if (inputElement instanceof MappingSourceContainer) { try { return ((MappingSourceContainer)inputElement).getSourceContainers(); } catch (CoreException e) { } } return new Object[0]; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ @Override public void dispose() { } /* (non-Javadoc) * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) */ @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } }); fViewer.setCellEditors(new CellEditor[] { new TextCellEditor(table), new DirectoryCellEditor(table), }); fViewer.setCellModifier(new EntryCellModifier()); fViewer.setLabelProvider(new EntryLabelProvider()); fViewer.addSelectionChangedListener(new ISelectionChangedListener() { /* (non-Javadoc) * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */ @Override public void selectionChanged(SelectionChangedEvent event) { updateViewerButtons(); } }); } private void createViewerButtonBar(Composite parent) { Composite buttonComp = new Composite(parent, SWT.NONE); buttonComp.setLayout(new GridLayout()); buttonComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, false, false)); fAddButton = createPushButton(buttonComp, SourceLookupUIMessages.MappingSourceContainerDialog_3); fAddButton.addSelectionListener(new SelectionAdapter() { /* (non-Javadoc) * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected(SelectionEvent event) { addPathEntry(); } }); fRemoveButton = createPushButton(buttonComp, SourceLookupUIMessages.PathMappingDialog_15); fRemoveButton.addSelectionListener(new SelectionAdapter() { /* (non-Javadoc) * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected(SelectionEvent event) { removePathEntries(); } }); fUpButton = createPushButton(buttonComp, SourceLookupUIMessages.MappingSourceContainerDialog_4); fUpButton.addSelectionListener(new SelectionAdapter() { /* (non-Javadoc) * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected(SelectionEvent event) { move(true); } }); fDownButton = createPushButton(buttonComp, SourceLookupUIMessages.MappingSourceContainerDialog_5); fDownButton.addSelectionListener(new SelectionAdapter() { /* (non-Javadoc) * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected(SelectionEvent event) { move(false); } }); } private void initialize() { fNameText.setText(fContainer.getName()); fNameText.selectAll(); fMappingWithBackendEnabledCheck.setSelection(fContainer.isMappingWithBackendEnabled()); fViewer.setInput(fContainer); updateViewerButtons(); } private Button createPushButton(Composite parent, String label) { Button button = new Button(parent, SWT.PUSH); button.setText(label); GridData gd = new GridData(SWT.FILL, SWT.BEGINNING, true, false); gd.widthHint = SWTUtil.getButtonWidthHint(button); button.setLayoutData(gd); return button; } private MapEntrySourceContainer[] getSelectedEntries() { List<?> list = ((IStructuredSelection)fViewer.getSelection()).toList(); return list.toArray(new MapEntrySourceContainer[list.size()]); } private void updateErrorMessage() { setErrorMessage(null); try { ISourceContainer[] containers = fContainer.getSourceContainers(); if (containers.length == 0) return; for (ISourceContainer c : containers) { MapEntrySourceContainer entry = (MapEntrySourceContainer)c; String backendPath = entry.getBackendPathStr(); if (backendPath.isEmpty()) { setErrorMessage(SourceLookupUIMessages.PathMappingDialog_5); break; } IPath localPath = entry.getLocalPath(); if (localPath.isEmpty()) { setErrorMessage(SourceLookupUIMessages.PathMappingDialog_7); break; } if (!localPath.toFile().exists()) { setErrorMessage(SourceLookupUIMessages.PathMappingDialog_8); break; } if (!localPath.toFile().isDirectory()) { setErrorMessage(SourceLookupUIMessages.PathMappingDialog_9); break; } if (!localPath.toFile().isAbsolute()) { setErrorMessage(SourceLookupUIMessages.PathMappingDialog_10); break; } } } catch (CoreException e) { // ignore } } private void updateViewerButtons() { boolean ok = true; boolean remove = true; boolean up = true; boolean down = true; try { ISourceContainer[] allEntries = fContainer.getSourceContainers(); MapEntrySourceContainer[] entries = getSelectedEntries(); if (entries.length == 0) { remove = false; } if (entries.length != 1) { up = false; down = false; } else { up = (!entries[0].equals(allEntries[0])); down = (!entries[0].equals(allEntries[allEntries.length - 1])); } ok = (allEntries.length != 0 && fIsValid); } catch (CoreException e) { // ignore, shouldn't happen } getButton(IDialogConstants.OK_ID).setEnabled(ok); fRemoveButton.setEnabled(remove); fUpButton.setEnabled(up); fDownButton.setEnabled(down); } private void refresh() { ISelection s = fViewer.getSelection(); fViewer.refresh(); fViewer.setSelection(s); updateErrorMessage(); updateViewerButtons(); } void controlMoved(ControlEvent e) { } void controlResized(ControlEvent e) { // resize columns Table table = fViewer.getTable(); int width = table.getSize().x; if (width > 0) { TableColumn[] columns = table.getColumns(); int colWidth = width / columns.length; for (TableColumn col : columns) { if (col.getWidth() == 0) { col.setWidth(colWidth); } } } } void addPathEntry() { MapEntrySourceContainer entry = new MapEntrySourceContainer(); fContainer.addMapEntry(entry); fViewer.refresh(); fViewer.setSelection(new StructuredSelection(entry), true); updateViewerButtons(); fViewer.editElement(entry, 0); } void removePathEntries() { MapEntrySourceContainer[] entries = getSelectedEntries(); fContainer.removeMapEntries(entries); refresh(); } void move(boolean up) { MapEntrySourceContainer[] selEntries = getSelectedEntries(); if (selEntries.length != 1) return; MapEntrySourceContainer entry = selEntries[0]; try { ISourceContainer[] containers = fContainer.getSourceContainers(); List<MapEntrySourceContainer> list = new ArrayList<MapEntrySourceContainer>(containers.length); for (ISourceContainer container : containers) { list.add(((MapEntrySourceContainer)container).copy()); } int index = list.indexOf(entry); list.remove(index); index = (up) ? index - 1 : index + 1; list.add(index, entry); fContainer.clear(); fContainer.addMapEntries(list.toArray(new MapEntrySourceContainer[list.size()])); refresh(); } catch (CoreException e) { } catch (IndexOutOfBoundsException e) { } } }