// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.dataprofiler.core.ui.dialog;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
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.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.ide.undo.CreateMarkersOperation;
import org.eclipse.ui.ide.undo.UpdateMarkersOperation;
import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.views.markers.internal.MarkerMessages;
import org.eclipse.ui.views.markers.internal.Util;
/**
*
* DOC mzhao class global comment. Detailled comment
*/
@SuppressWarnings("restriction")
public class TdDialogMarkerProperties 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.
*/
@SuppressWarnings("unchecked")
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;
/**
* The name used to describe the specific kind of marker. Used when creating an undo command for the dialog, so that
* a specific name such as "Undo Create Task" or "Undo Modify Bookmark" can be used.
*/
private String markerName;
/**
* 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 parentShell the parent shell
*/
public TdDialogMarkerProperties(Shell parentShell) {
super(parentShell);
}
/**
* 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 parentShell the parent shell
* @param title the title of the dialog
*/
public TdDialogMarkerProperties(Shell parentShell, String title) {
super(parentShell);
this.title = 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 parentShell the parent shell
* @param title the title of the dialog
* @param markerName the name used to describe the specific kind of marker shown
*
* @since 3.3
*/
public TdDialogMarkerProperties(Shell parentShell, String title, String markerName) {
super(parentShell);
this.title = title;
this.markerName = markerName;
}
/**
* Sets the marker to show or modify.
* <p>
* IMPORTANT: Although this class is internal, there are public subclasses that expose this method as API. Changes
* in this implementation should be treated as API changes.
*
* @param marker the marker, or <code>null</code> to create a new marker
*
* @since 3.3
*/
public void setMarker(IMarker marker) {
this.marker = marker;
if (marker != null) {
try {
type = marker.getType();
} catch (CoreException e) {
e.printStackTrace();
}
}
}
/**
* 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.
* <p>
* IMPORTANT: Although this method is protected and the class is internal, there are public subclasses that expose
* this method as API. Changes in this implementation should be treated as API changes.
*
* @return the marker
*
* @since 3.3
*/
protected IMarker getMarker() {
return marker;
}
/**
* Sets the resource to use when creating a new task. If not set, the new task is created on the workspace root.
* <p>
* IMPORTANT: Although this class is internal, there are public subclasses that expose this method as API. Changes
* in this implementation should be treated as API changes.
*
* @param resource the resource
*/
public void setResource(IResource resource) {
this.resource = resource;
}
/**
* Returns the resource to use when creating a new task, or <code>null</code> if none has been set. If not set, the
* new task is created on the workspace root.
* <p>
* IMPORTANT: Although this method is protected and the class is internal, there are public subclasses that expose
* this method as API. Changes in this implementation should be treated as API changes.
*
* @return the resource
*
* @since 3.3
*/
protected IResource getResource() {
return resource;
}
/**
* Sets initial attributes to use when creating a new task. If not set, the new task is created with default
* attributes.
* <p>
* IMPORTANT: Although this method is protected and the class is internal, there are public subclasses that expose
* this method as API. Changes in this implementation should be treated as API changes.
*
* @param initialAttributes the initial attributes
*
* @since 3.3
*/
@SuppressWarnings("unchecked")
public void setInitialAttributes(Map initialAttributes) {
this.initialAttributes = initialAttributes;
}
/**
* Returns the initial attributes to use when creating a new task, or <code>null</code> if not set. If not set, the
* new task is created with default attributes.
* <p>
* IMPORTANT: Although this method is protected and the class is internal, there are public subclasses that expose
* this method as API. Changes in this implementation should be treated as API changes.
*
* @return the initial attributes
*
* @since 3.3
*/
@SuppressWarnings("unchecked")
protected 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);//$NON-NLS-1$
} 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) {
e.printStackTrace();
}
} 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);//$NON-NLS-1$
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);//$NON-NLS-1$
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);//$NON-NLS-1$
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 && locationText != null) {
locationText.setText(line.toString());
}
}
}
/**
* 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.
*/
@SuppressWarnings("unchecked")
private void saveChanges() {
Map attrs = getMarkerAttributes();
IUndoableOperation op = null;
if (marker == null) {
if (resource == null)
return;
op = new CreateMarkersOperation(type, attrs, resource, getCreateOperationTitle());
} else {
if (isDirty()) {
op = new UpdateMarkersOperation(marker, attrs, getModifyOperationTitle(), true);
}
}
if (op != null) {
try {
PlatformUI.getWorkbench().getOperationSupport().getOperationHistory().execute(op, null,
WorkspaceUndoUtil.getUIInfoAdapter(getShell()));
} catch (ExecutionException e) {
if (e.getCause() instanceof CoreException) {
ErrorDialog.openError(getShell(), MarkerMessages.Error, null, ((CoreException) e.getCause()).getStatus());
} else {
IDEWorkbenchPlugin.log(e.getMessage(), e);
}
}
}
}
/**
* Returns the marker attributes to save back to the marker, based on the current dialog fields.
*/
@SuppressWarnings("unchecked")
protected Map getMarkerAttributes() {
Map attrs = getInitialAttributes();
attrs.put(IMarker.MESSAGE, descriptionText.getText());
return attrs;
}
/**
* 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
*
* @since 3.3 this method is protected.
*/
protected 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;
}
/**
* Return the string that describes a modify marker operation. Subclasses may override to more specifically describe
* the marker.
*
* @since 3.3
*/
protected String getModifyOperationTitle() {
if (markerName == null) {
// we don't know what kind of marker is being modified
return MarkerMessages.DialogMarkerProperties_ModifyMarker;
}
return NLS.bind(MarkerMessages.qualifiedMarkerCommand_title, MarkerMessages.DialogMarkerProperties_Modify, markerName);//$NON-NLS-2$
}
/**
* Return the string that describes a create marker operation. Subclasses may override to more specifically describe
* the marker.
*
* @since 3.3
*/
protected String getCreateOperationTitle() {
if (markerName == null) {
// we don't know what kind of marker is being created
return MarkerMessages.DialogMarkerProperties_CreateMarker;//$NON-NLS-1$
}
return NLS.bind(MarkerMessages.qualifiedMarkerCommand_title, MarkerMessages.DialogMarkerProperties_Create, markerName);//$NON-NLS-2$
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.dialogs.Dialog#isResizable()
*/
protected boolean isResizable() {
return true;
}
}