| /******************************************************************************* |
| * Copyright (c) 2000, 2006 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 |
| * Sebastian Davids <sdavids@gmx.de> - bug 77332 - [Markers] Add task dialog improvements |
| *******************************************************************************/ |
| |
| package org.eclipse.ui.views.markers.internal; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspaceRunnable; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.dialogs.ErrorDialog; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.dialogs.TrayDialog; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.ModifyEvent; |
| import org.eclipse.swt.events.ModifyListener; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Text; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; |
| import org.eclipse.ui.internal.ide.StatusUtil; |
| |
| /** |
| * Shows the properties of a new or existing marker |
| */ |
| class DialogMarkerProperties extends TrayDialog { |
| |
| private static final String DIALOG_SETTINGS_SECTION = "DialogMarkerPropertiesDialogSettings"; //$NON-NLS-1$ |
| |
| /** |
| * The marker being shown, or <code>null</code> for a new marker |
| */ |
| private IMarker marker = null; |
| |
| /** |
| * The resource on which to create a new marker |
| */ |
| private IResource resource = null; |
| |
| /** |
| * The type of marker to be created |
| */ |
| private String type = IMarker.MARKER; |
| |
| /** |
| * The initial attributes to use when creating a new marker |
| */ |
| private Map initialAttributes = null; |
| |
| /** |
| * The text control for the Description field. |
| */ |
| private Text descriptionText; |
| |
| /** |
| * The control for the Creation Time field. |
| */ |
| private Label creationTime; |
| |
| /** |
| * The text control for the Resource field. |
| */ |
| private Text resourceText; |
| |
| /** |
| * The text control for the Folder field. |
| */ |
| private Text folderText; |
| |
| /** |
| * The text control for the Location field. |
| */ |
| private Text locationText; |
| |
| /** |
| * Dirty flag. True if any changes have been made. |
| */ |
| private boolean dirty; |
| |
| private String title; |
| |
| /** |
| * Creates the dialog. By default this dialog creates a new marker. |
| * To set the resource and initial attributes for the new marker, |
| * use <code>setResource</code> and <code>setInitialAttributes</code>. |
| * To show or modify an existing marker, use <code>setMarker</code>. |
| * |
| * @param shell the parent shell |
| */ |
| DialogMarkerProperties(Shell parentShell) { |
| super(parentShell); |
| setShellStyle(getShellStyle() | SWT.RESIZE); |
| } |
| |
| /** |
| * Creates the dialog. By default this dialog creates a new marker. |
| * To set the resource and initial attributes for the new marker, |
| * use <code>setResource</code> and <code>setInitialAttributes</code>. |
| * To show or modify an existing marker, use <code>setMarker</code>. |
| * |
| * @param shell the parent shell |
| * @param title the title of the dialog |
| */ |
| DialogMarkerProperties(Shell parentShell, String title) { |
| super(parentShell); |
| setShellStyle(getShellStyle() | SWT.RESIZE); |
| this.title = title; |
| } |
| |
| /** |
| * Sets the marker to show or modify. |
| * |
| * @param marker the marker, or <code>null</code> to create a new marker |
| */ |
| void setMarker(IMarker marker) { |
| this.marker = marker; |
| if (marker != null) { |
| try { |
| type = marker.getType(); |
| } catch (CoreException e) { |
| } |
| } |
| } |
| |
| /** |
| * Returns the marker being created or modified. |
| * For a new marker, this returns <code>null</code> until |
| * the dialog returns, but is non-null after. |
| */ |
| IMarker getMarker() { |
| return marker; |
| } |
| |
| /** |
| * Sets the resource to use when creating a new marker. |
| * If not set, the new marker is created on the workspace root. |
| * |
| * @param resource the marker's resource |
| */ |
| public void setResource(IResource resource) { |
| this.resource = resource; |
| } |
| |
| /** |
| * Returns the resource to use when creating a new marker, |
| * or <code>null</code> if none has been set. |
| * If not set, the new marker is created on the workspace root. |
| */ |
| IResource getResource() { |
| return resource; |
| } |
| |
| /** |
| * Sets initial attributes to use when creating a new marker. |
| * If not set, the new marker is created with default attributes. |
| */ |
| void setInitialAttributes(Map initialAttributes) { |
| this.initialAttributes = initialAttributes; |
| } |
| |
| /** |
| * Returns the initial attributes to use when creating a new marker, |
| * or <code>null</code> if not set. |
| * If not set, the new marker is created with default attributes. |
| */ |
| Map getInitialAttributes() { |
| if (initialAttributes == null) { |
| initialAttributes = new HashMap(); |
| } |
| return initialAttributes; |
| } |
| |
| /** |
| * Method declared on Window. |
| */ |
| protected void configureShell(Shell newShell) { |
| super.configureShell(newShell); |
| if (title == null) { |
| newShell.setText(MarkerMessages.propertiesDialog_title); |
| } else { |
| newShell.setText(title); |
| } |
| } |
| |
| /** |
| * Method declared on Dialog. |
| */ |
| protected Control createDialogArea(Composite parent) { |
| //initialize resources/properties |
| if (marker != null) { |
| resource = marker.getResource(); |
| try { |
| initialAttributes = marker.getAttributes(); |
| } catch (CoreException e) { |
| } |
| } else if (resource == null) { |
| resource = ResourcesPlugin.getWorkspace().getRoot(); |
| } |
| |
| Composite comp = (Composite) super.createDialogArea(parent); |
| Composite composite = new Composite(comp, SWT.NULL); |
| GridLayout layout = new GridLayout(2, false); |
| layout.marginWidth = 0; |
| layout.marginHeight = 0; |
| composite.setLayout(layout); |
| GridData gridData = new GridData(GridData.FILL_HORIZONTAL); |
| composite.setLayoutData(gridData); |
| |
| initializeDialogUnits(composite); |
| |
| createDescriptionArea(composite); |
| if (marker != null) { |
| createSeperator(composite); |
| createCreationTimeArea(composite); |
| } |
| createAttributesArea(composite); |
| if (resource != null) { |
| createSeperator(composite); |
| createResourceArea(composite); |
| } |
| |
| updateDialogFromMarker(); |
| updateEnablement(); |
| |
| Dialog.applyDialogFont(composite); |
| |
| return composite; |
| } |
| |
| /** |
| * Creates a seperator. |
| */ |
| protected void createSeperator(Composite parent) { |
| Label seperator = new Label(parent, SWT.NULL); |
| GridData gridData = new GridData(GridData.FILL_HORIZONTAL); |
| gridData.horizontalSpan = 2; |
| seperator.setLayoutData(gridData); |
| } |
| |
| /** |
| * Method createCreationTimeArea. |
| * @param parent |
| */ |
| private void createCreationTimeArea(Composite parent) { |
| Label label = new Label(parent, SWT.NONE); |
| label.setText(MarkerMessages |
| .propertiesDialog_creationTime_text); |
| |
| creationTime = new Label(parent, SWT.NONE); |
| } |
| |
| /** |
| * Creates the OK and Cancel buttons. |
| */ |
| protected void createButtonsForButtonBar(Composite parent) { |
| createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, |
| true); |
| createButton(parent, IDialogConstants.CANCEL_ID, |
| IDialogConstants.CANCEL_LABEL, false); |
| } |
| |
| /** |
| * Creates the area for the Description field. |
| */ |
| private void createDescriptionArea(Composite parent) { |
| Label label = new Label(parent, SWT.NONE); |
| label.setText(MarkerMessages.propertiesDialog_description_text); |
| descriptionText = new Text(parent, (SWT.SINGLE | SWT.BORDER)); |
| GridData gridData = new GridData(GridData.FILL_HORIZONTAL); |
| gridData.widthHint = convertHorizontalDLUsToPixels(400); |
| descriptionText.setLayoutData(gridData); |
| |
| descriptionText.addModifyListener(new ModifyListener() { |
| public void modifyText(ModifyEvent e) { |
| markDirty(); |
| } |
| }); |
| } |
| |
| /** |
| * This method is intended to be overridden by subclasses. The attributes area is created between |
| * the creation time area and the resource area. |
| * |
| * @param parent the parent composite |
| */ |
| protected void createAttributesArea(Composite parent) { |
| } |
| |
| /** |
| * Creates the area for the Resource field. |
| */ |
| private void createResourceArea(Composite parent) { |
| Label resourceLabel = new Label(parent, SWT.NONE); |
| resourceLabel.setText(MarkerMessages.propertiesDialog_resource_text); |
| resourceText = new Text(parent, SWT.SINGLE | SWT.WRAP |
| | SWT.READ_ONLY | SWT.BORDER); |
| GridData gridData = new GridData(GridData.FILL_HORIZONTAL); |
| resourceText.setLayoutData(gridData); |
| |
| Label folderLabel = new Label(parent, SWT.NONE); |
| folderLabel.setText(MarkerMessages.propertiesDialog_folder_text); |
| folderText = new Text(parent, SWT.SINGLE | SWT.WRAP | SWT.READ_ONLY |
| | SWT.BORDER); |
| gridData = new GridData(GridData.FILL_HORIZONTAL); |
| folderText.setLayoutData(gridData); |
| |
| Label locationLabel = new Label(parent, SWT.NONE); |
| locationLabel.setText(MarkerMessages.propertiesDialog_location_text); |
| locationText = new Text(parent, SWT.SINGLE | SWT.WRAP |
| | SWT.READ_ONLY | SWT.BORDER); |
| gridData = new GridData(GridData.FILL_HORIZONTAL); |
| locationText.setLayoutData(gridData); |
| } |
| |
| /** |
| * Updates the dialog from the marker state. |
| */ |
| protected void updateDialogFromMarker() { |
| if (marker == null) { |
| updateDialogForNewMarker(); |
| return; |
| } |
| descriptionText.setText(Util.getProperty(IMarker.MESSAGE, marker)); |
| if (creationTime != null) { |
| creationTime.setText(Util.getCreationTime(marker)); |
| } |
| if (resourceText != null) { |
| resourceText.setText(Util.getResourceName(marker)); |
| } |
| if (folderText != null) { |
| folderText.setText(Util.getContainerName(marker)); |
| } |
| if (locationText != null) { |
| String line = Util.getProperty(IMarker.LINE_NUMBER, marker); |
| if (line.equals("")) { //$NON-NLS-1$ |
| locationText.setText(""); //$NON-NLS-1$ |
| } else { |
| locationText.setText(NLS.bind(MarkerMessages.label_lineNumber, line)); |
| } |
| } |
| |
| descriptionText.selectAll(); |
| } |
| |
| /** |
| * Updates the dialog from the predefined attributes. |
| */ |
| protected void updateDialogForNewMarker() { |
| if (resource != null && resourceText != null && folderText != null) { |
| resourceText.setText(resource.getName()); |
| |
| IPath path = resource.getFullPath(); |
| int n = path.segmentCount() - 1; // n is the number of segments in container, not path |
| if (n > 0) { |
| int len = 0; |
| for (int i = 0; i < n; ++i) { |
| len += path.segment(i).length(); |
| } |
| // account for /'s |
| if (n > 1) { |
| len += n - 1; |
| } |
| StringBuffer sb = new StringBuffer(len); |
| for (int i = 0; i < n; ++i) { |
| if (i != 0) { |
| sb.append('/'); |
| } |
| sb.append(path.segment(i)); |
| } |
| folderText.setText(sb.toString()); |
| } |
| } |
| |
| if (initialAttributes != null) { |
| Object description = initialAttributes.get(IMarker.MESSAGE); |
| if (description != null && description instanceof String) { |
| descriptionText.setText((String) description); |
| } |
| descriptionText.selectAll(); |
| |
| Object line = initialAttributes.get(IMarker.LINE_NUMBER); |
| if (line != null && line instanceof Integer && locationText != null) { |
| locationText.setText( |
| NLS.bind(MarkerMessages.label_lineNumber, line)); |
| } |
| } |
| } |
| |
| /** |
| * Method declared on Dialog |
| */ |
| protected void okPressed() { |
| if (marker == null || Util.isEditable(marker)) { |
| saveChanges(); |
| } |
| super.okPressed(); |
| } |
| |
| /** |
| * Sets the dialog's dirty flag to <code>true</code> |
| */ |
| protected void markDirty() { |
| dirty = true; |
| } |
| |
| /** |
| * @return |
| * <ul> |
| * <li><code>true</code> if the dirty flag has been set to true.</li> |
| * <li><code>false</code> otherwise.</li> |
| * </ul> |
| */ |
| protected boolean isDirty() { |
| return dirty; |
| } |
| |
| /** |
| * Saves the changes made in the dialog if needed. |
| * Creates a new marker if needed. |
| * Updates the existing marker only if there have been changes. |
| */ |
| private void saveChanges() { |
| |
| final CoreException[] coreExceptions = new CoreException[1]; |
| |
| try { |
| final Map attrs = getMarkerAttributes(); |
| |
| PlatformUI.getWorkbench().getProgressService().busyCursorWhile( |
| new IRunnableWithProgress() { |
| /* (non-Javadoc) |
| * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| public void run(IProgressMonitor monitor) { |
| try { |
| |
| monitor.beginTask("", 100);//$NON-NLS-1$ |
| ResourcesPlugin.getWorkspace().run( |
| new IWorkspaceRunnable() { |
| public void run( |
| IProgressMonitor monitor) |
| throws CoreException { |
| if (marker == null) { |
| createMarker(monitor); |
| } |
| if (isDirty()) { |
| updateMarker(monitor, attrs); |
| } |
| } |
| }, monitor); |
| monitor.done(); |
| } catch (CoreException e) { |
| coreExceptions[0] = e; |
| } |
| } |
| |
| }); |
| } catch (InvocationTargetException e) { |
| IDEWorkbenchPlugin.log(e.getMessage(), StatusUtil.newStatus( |
| IStatus.ERROR, e.getMessage(), e)); |
| return; |
| } |
| |
| catch (InterruptedException e) { |
| } |
| |
| if (coreExceptions[0] != null) { |
| ErrorDialog |
| .openError( |
| getShell(), |
| MarkerMessages.Error, null, coreExceptions[0].getStatus()); |
| } |
| |
| } |
| |
| /** |
| * Creates or updates the marker. Must be called within a workspace runnable. |
| * @param monitor the monitor we report to. |
| * @param attrs the attributes from the dialog |
| */ |
| private void updateMarker(IProgressMonitor monitor, Map attrs) |
| throws CoreException { |
| // Set the marker attributes from the current dialog field values. |
| // Do not use setAttributes(Map) as that overwrites any attributes |
| // not covered by the dialog. |
| |
| int increment = 50 / attrs.size(); |
| |
| for (Iterator i = attrs.keySet().iterator(); i.hasNext();) { |
| monitor.worked(increment); |
| String key = (String) i.next(); |
| Object val = attrs.get(key); |
| marker.setAttribute(key, val); |
| } |
| } |
| |
| /** |
| * Returns the marker attributes to save back to the marker, |
| * based on the current dialog fields. |
| */ |
| protected Map getMarkerAttributes() { |
| Map attrs; |
| if (initialAttributes == null) { |
| attrs = initialAttributes; |
| } else { |
| attrs = new HashMap(); |
| } |
| attrs.put(IMarker.MESSAGE, descriptionText.getText()); |
| return attrs; |
| } |
| |
| /** |
| * Create the marker and report progress |
| * to the monitor. |
| * @param monitor |
| * @throws CoreException |
| */ |
| private void createMarker(IProgressMonitor monitor) throws CoreException { |
| if (resource == null) { |
| return; |
| } |
| |
| monitor.worked(10); |
| marker = resource.createMarker(type); |
| monitor.worked(40); |
| } |
| |
| /** |
| * Updates widget enablement for the dialog. Should be overridden by subclasses. |
| */ |
| protected void updateEnablement() { |
| descriptionText.setEditable(isEditable()); |
| } |
| |
| /** |
| * @return |
| * <ul> |
| * <li><code>true</code> if the marker is editable or the dialog is creating a new marker.</li> |
| * <li><code>false</code> if the marker is not editable.</li> |
| * </ul> |
| */ |
| protected boolean isEditable() { |
| if (marker == null) { |
| return true; |
| } |
| return Util.isEditable(marker); |
| } |
| |
| /** |
| * Sets the marker type when creating a new marker. |
| * |
| * @param type the marker type |
| */ |
| void setType(String type) { |
| this.type = type; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jface.window.Dialog#getDialogBoundsSettings() |
| * |
| * @since 3.2 |
| */ |
| protected IDialogSettings getDialogBoundsSettings() { |
| IDialogSettings settings = IDEWorkbenchPlugin.getDefault().getDialogSettings(); |
| IDialogSettings section = settings.getSection(DIALOG_SETTINGS_SECTION); |
| if (section == null) { |
| section = settings.addNewSection(DIALOG_SETTINGS_SECTION); |
| } |
| return section; |
| } |
| } |