blob: 988833e0b82f38ff79488bfb623c2d4df84b9e20 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 Atlassian 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:
* Atlassian - initial API and implementation
******************************************************************************/
package com.atlassian.connector.eclipse.internal.crucible.ui.dialogs;
import com.atlassian.connector.commons.misc.IntRange;
import com.atlassian.connector.commons.misc.IntRanges;
import com.atlassian.connector.eclipse.internal.crucible.core.client.CrucibleClient;
import com.atlassian.connector.eclipse.internal.crucible.ui.CrucibleUiPlugin;
import com.atlassian.connector.eclipse.internal.crucible.ui.CrucibleUiUtil;
import com.atlassian.connector.eclipse.team.ui.CrucibleFile;
import com.atlassian.theplugin.commons.crucible.api.model.Comment;
import com.atlassian.theplugin.commons.crucible.api.model.Comment.ReadState;
import com.atlassian.theplugin.commons.crucible.api.model.CrucibleFileInfo;
import com.atlassian.theplugin.commons.crucible.api.model.CustomFieldBean;
import com.atlassian.theplugin.commons.crucible.api.model.CustomFieldDef;
import com.atlassian.theplugin.commons.crucible.api.model.CustomFieldValue;
import com.atlassian.theplugin.commons.crucible.api.model.Review;
import com.atlassian.theplugin.commons.crucible.api.model.VersionedComment;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.ITextListener;
import org.eclipse.jface.text.TextEvent;
import org.eclipse.jface.text.source.LineRange;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.forms.widgets.FormToolkit;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
/**
* Dialog shown to the user when they add a comment to a review
*
* @author Thomas Ehrnhoefer
* @author Shawn Minto
*/
public class CrucibleAddCommentDialog extends AbstractCrucibleCommentDialog {
public class AddCommentRunnable implements IRunnableWithProgress {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
monitor.beginTask("Adding comment", IProgressMonitor.UNKNOWN);
if (newComment.length() > 0) {
CrucibleFileInfo crucibleFileInfo = crucibleFile.getCrucibleFileInfo();
VersionedComment comment = new VersionedComment(getReview(), crucibleFileInfo);
comment.setMessage(newComment);
comment.setAuthor(CrucibleUiUtil.getCachedUsers(getReview()).iterator().next());
comment.setReadState(ReadState.UNREAD);
Map<String, IntRanges> lineRanges = new HashMap<String, IntRanges>();
lineRanges.put("1.1",
new IntRanges(new IntRange(commentLines.getStartLine(), commentLines.getStartLine()
+ commentLines.getNumberOfLines())));
comment.setLineRanges(lineRanges);
crucibleFile.getCrucibleFileInfo().addComment(comment);
CrucibleUiPlugin.getDefault().getActiveReviewManager().activeReviewUpdated();
}
}
}
private final String shellTitle;
private final CrucibleClient client;
private LineRange commentLines;
private Comment parentComment;
private CrucibleFile crucibleFile;
private static final String SAVE_LABEL = "&Post";
private static final String DRAFT_LABEL = "Post as &Draft";
private static final String DEFECT_LABEL = "Defect";
private final boolean edit = false;
private FormToolkit toolkit;
private boolean draft = false;
private boolean defect = false;
private String newComment;
private Button saveButton;
private Button saveDraftButton;
public CrucibleAddCommentDialog(Shell parentShell, String shellTitle, Review review, String taskKey, String taskId,
TaskRepository taskRepository, CrucibleClient client) {
super(parentShell, taskRepository, review, taskKey, taskId);
this.shellTitle = shellTitle;
this.client = client;
}
@Override
protected Control createPageControls(Composite parent) {
// CHECKSTYLE:MAGIC:OFF
getShell().setText(shellTitle);
setTitle(shellTitle);
if (parentComment == null) {
setMessage("Create a new comment");
} else {
setMessage("Reply to a comment from: " + parentComment.getAuthor().getDisplayName());
}
// CHECKSTYLE:MAGIC:OFF
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new GridLayout(1, false));
if (toolkit == null) {
toolkit = new FormToolkit(getShell().getDisplay());
}
parent.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (toolkit != null) {
toolkit.dispose();
}
}
});
createAdditionalControl(composite);
createWikiTextControl(composite, toolkit);
commentText.getViewer().addTextListener(new ITextListener() {
public void textChanged(TextEvent event) {
boolean enabled = false;
if (commentText != null && commentText.getText().trim().length() > 0) {
enabled = true;
}
if (saveButton != null && !saveButton.isDisposed()
&& (parentComment == null || !parentComment.isDraft())) {
saveButton.setEnabled(enabled);
}
if (saveDraftButton != null && !saveDraftButton.isDisposed()) {
saveDraftButton.setEnabled(enabled);
}
}
});
((GridLayout) parent.getLayout()).makeColumnsEqualWidth = false;
// create buttons according to (implicit) reply type
int nrOfCustomFields = 0;
if (parentComment == null) { // "defect button" needed if new comment
Composite compositeCustomFields = new Composite(composite, SWT.NONE);
compositeCustomFields.setLayout(new GridLayout(1, false));
createDefectButton(compositeCustomFields);
GridDataFactory.fillDefaults()
.grab(true, false)
.span(nrOfCustomFields + 1, 1)
.applyTo(compositeCustomFields);
}
GridDataFactory.fillDefaults().grab(true, true).hint(SWT.DEFAULT, SWT.DEFAULT).applyTo(composite);
applyDialogFont(composite);
return composite;
}
protected void createAdditionalControl(Composite composite) {
}
protected void processFields() {
newComment = commentText.getText();
if (defect) { // process custom field selection only when defect is selected
for (CustomFieldDef field : customCombos.keySet()) {
CustomFieldValue customValue = (CustomFieldValue) customCombos.get(field).getElementAt(
customCombos.get(field).getCombo().getSelectionIndex());
if (customValue != null) {
CustomFieldBean bean = new CustomFieldBean();
bean.setConfigVersion(field.getConfigVersion());
bean.setValue(customValue.getName());
customFieldSelections.put(field.getName(), bean);
}
}
}
}
protected Button createDefectButton(Composite parent) {
// increment the number of columns in the button bar
((GridLayout) parent.getLayout()).numColumns++;
defectButton = new Button(parent, SWT.CHECK);
defectButton.setText(DEFECT_LABEL);
defectButton.setFont(JFaceResources.getDialogFont());
defectButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
defect = !defect;
// toggle combos
for (CustomFieldDef field : customCombos.keySet()) {
customCombos.get(field).getCombo().setEnabled(defect);
}
}
});
return defectButton;
}
protected void createCombo(Composite parent, final CustomFieldDef customField, int selection) {
((GridLayout) parent.getLayout()).numColumns++;
Label label = new Label(parent, SWT.NONE);
label.setText("Select " + customField.getName());
((GridLayout) parent.getLayout()).numColumns++;
ComboViewer comboViewer = new ComboViewer(parent);
comboViewer.setContentProvider(new ArrayContentProvider());
comboViewer.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element) {
CustomFieldValue fieldValue = (CustomFieldValue) element;
return fieldValue.getName();
}
});
comboViewer.setInput(customField.getValues());
comboViewer.getCombo().setEnabled(false);
customCombos.put(customField, comboViewer);
}
public boolean addComment() {
try {
newComment = commentText.getText();
processFields();
setMessage("");
run(true, false, new AddCommentRunnable());
} catch (InvocationTargetException e) {
StatusHandler.log(new Status(IStatus.ERROR, CrucibleUiPlugin.PLUGIN_ID, e.getMessage(), e));
setErrorMessage("Unable to add the comment to the review");
return false;
} catch (InterruptedException e) {
StatusHandler.log(new Status(IStatus.ERROR, CrucibleUiPlugin.PLUGIN_ID, e.getMessage(), e));
setErrorMessage("Unable to add the comment to the review");
return false;
}
setReturnCode(Window.OK);
close();
return true;
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
saveButton = createButton(parent, IDialogConstants.CLIENT_ID + 2, SAVE_LABEL, false);
saveButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
addComment();
}
});
saveButton.setEnabled(false);
if (!edit) { // if it is a new reply, saving as draft is possible
saveDraftButton = createButton(parent, IDialogConstants.CLIENT_ID + 2, DRAFT_LABEL, false);
saveDraftButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
draft = true;
addComment();
}
});
saveDraftButton.setEnabled(false);
}
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false).addSelectionListener(
new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
cancelPressed();
}
});
}
public void setReviewItem(CrucibleFile reviewItem) {
this.crucibleFile = reviewItem;
}
public void setParentComment(Comment comment) {
this.parentComment = comment;
}
public void setCommentLines(LineRange commentLines2) {
this.commentLines = commentLines2;
}
}