blob: 53aabafb686e93479db7bd963569cfd7cc770408 [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.editor.ruler;
import com.atlassian.connector.eclipse.internal.crucible.ui.ActiveReviewManager.IReviewActivationListener;
import com.atlassian.connector.eclipse.internal.crucible.ui.CrucibleUiPlugin;
import com.atlassian.connector.eclipse.internal.crucible.ui.CrucibleUiUtil;
import com.atlassian.connector.eclipse.internal.crucible.ui.ICrucibleFileProvider;
import com.atlassian.connector.eclipse.internal.crucible.ui.annotations.CrucibleAnnotationModel;
import com.atlassian.connector.eclipse.internal.crucible.ui.annotations.CrucibleCommentAnnotation;
import com.atlassian.connector.eclipse.team.ui.CrucibleFile;
import com.atlassian.theplugin.commons.crucible.api.model.CrucibleFileInfo;
import com.atlassian.theplugin.commons.crucible.api.model.Review;
import com.atlassian.theplugin.commons.crucible.api.model.notification.CrucibleNotification;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.source.AbstractRulerColumn;
import org.eclipse.jface.text.source.AnnotationModel;
import org.eclipse.jface.text.source.CompositeRuler;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.IAnnotationModelListener;
import org.eclipse.jface.text.source.ISharedTextColors;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.mylyn.tasks.core.ITask;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.internal.texteditor.PropertyEventDispatcher;
import org.eclipse.ui.texteditor.AnnotationPreference;
import org.eclipse.ui.texteditor.AnnotationPreferenceLookup;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.rulers.IContributedRulerColumn;
import org.eclipse.ui.texteditor.rulers.RulerColumnDescriptor;
import java.util.Collection;
import java.util.List;
public class CommentAnnotationRulerColumn extends AbstractRulerColumn implements IContributedRulerColumn,
IReviewActivationListener {
/** The contribution descriptor. */
private RulerColumnDescriptor fDescriptor;
private CrucibleAnnotationModel annotationModel;
private ITextEditor fEditor;
private Color colorCommented;
private ISourceViewer fViewer;
private PropertyEventDispatcher fDispatcher;
private IDocumentProvider fDocumentProvider;
public CommentAnnotationRulerColumn() {
setTextInset(10);
setHover(new CommentAnnotationRulerHover(this));
}
@Override
public void dispose() {
colorCommented.dispose();
super.dispose();
}
public RulerColumnDescriptor getDescriptor() {
return fDescriptor;
}
public void setDescriptor(RulerColumnDescriptor descriptor) {
fDescriptor = descriptor;
}
public void setEditor(ITextEditor editor) {
fEditor = editor;
fDocumentProvider = fEditor.getDocumentProvider();
}
public ITextEditor getEditor() {
return fEditor;
}
public void columnCreated() {
}
public void columnRemoved() {
}
protected Color computeLeftBackground(int line) {
List<CrucibleCommentAnnotation> annotations = getAnnotations(line);
if (annotations == null || annotations.size() == 0) {
return super.computeBackground(line);
} else {
return colorCommented;
}
}
@Override
protected Color computeForeground(int line) {
return Display.getDefault().getSystemColor(SWT.COLOR_BLACK);
}
@Override
protected void paintLine(GC gc, int modelLine, int widgetLine, int linePixel, int lineHeight) {
gc.setBackground(computeLeftBackground(modelLine));
gc.fillRectangle(0, linePixel, getWidth(), lineHeight);
}
public List<CrucibleCommentAnnotation> getAnnotations(int startLine) {
try {
int offset = fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput()).getLineOffset(startLine);
return annotationModel == null ? null : annotationModel.getAnnotationsForOffset(offset);
} catch (BadLocationException e) {
}
return null;
}
private ISharedTextColors getSharedColors() {
return EditorsUI.getSharedTextColors();
}
public static RGB getColorFromAnnotationPreference(IPreferenceStore store, AnnotationPreference pref) {
String key = pref.getColorPreferenceKey();
RGB rgb = null;
if (store.contains(key)) {
if (store.isDefault(key)) {
rgb = pref.getColorPreferenceValue();
} else {
rgb = PreferenceConverter.getColor(store, key);
}
}
if (rgb == null) {
rgb = pref.getColorPreferenceValue();
}
return rgb;
}
private void updateCommentedColor(AnnotationPreference pref, IPreferenceStore store) {
if (pref != null) {
RGB rgb = getColorFromAnnotationPreference(store, pref);
colorCommented = getSharedColors().getColor(rgb);
}
}
/**
* Initializes the given line number ruler column from the preference store.
*/
private void initialize() {
final IPreferenceStore store = EditorsUI.getPreferenceStore();
if (store == null) {
return;
}
AnnotationPreferenceLookup lookup = EditorsUI.getAnnotationPreferenceLookup();
final AnnotationPreference commentedPref = lookup.getAnnotationPreference(CrucibleCommentAnnotation.COMMENT_ANNOTATION_ID);
updateCommentedColor(commentedPref, store);
redraw();
// listen to changes
fDispatcher = new PropertyEventDispatcher(store);
if (commentedPref != null) {
fDispatcher.addPropertyChangeListener(commentedPref.getColorPreferenceKey(), new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
updateCommentedColor(commentedPref, store);
redraw();
}
});
}
}
@Override
public Control createControl(CompositeRuler parentRuler, Composite parentControl) {
ITextViewer viewer = parentRuler.getTextViewer();
Assert.isLegal(viewer instanceof ISourceViewer);
fViewer = (ISourceViewer) viewer;
fViewer.showAnnotations(true);
IAnnotationModel model = fViewer.getAnnotationModel();
if (model == null) {
fViewer.setDocument(fViewer.getDocument(), new AnnotationModel());
}
fViewer.getAnnotationModel().addAnnotationModelListener(new IAnnotationModelListener() {
public void modelChanged(IAnnotationModel model) {
if (CrucibleUiPlugin.getDefault().getActiveReviewManager().isReviewActive()) {
reviewActivated(CrucibleUiPlugin.getDefault().getActiveReviewManager().getActiveTask(),
CrucibleUiPlugin.getDefault().getActiveReviewManager().getActiveReview());
} else {
reviewDeactivated(null, null);
}
}
});
initialize();
CrucibleUiPlugin.getDefault().getActiveReviewManager().addReviewActivationListener(this);
return super.createControl(parentRuler, parentControl);
}
public void reviewActivated(ITask task, Review review) {
annotationModel = null;
CrucibleFileInfo currentFileInfo = null;
CrucibleFile file = null;
if (fEditor.getEditorInput() instanceof ICrucibleFileProvider) {
ICrucibleFileProvider fileProvider = (ICrucibleFileProvider) fEditor.getEditorInput();
file = fileProvider.getCrucibleFile();
}
if (fEditor.getEditorInput() instanceof IFileEditorInput) {
IFileEditorInput input = (IFileEditorInput) fEditor.getEditorInput();
file = CrucibleUiUtil.getCruciblePostCommitFile(input.getFile(), review);
}
if (file != null) {
currentFileInfo = review.getFileByPermId(file.getCrucibleFileInfo().getPermId());
if (currentFileInfo != null) {
annotationModel = new CrucibleAnnotationModel(fEditor, fEditor.getEditorInput(),
fDocumentProvider.getDocument(fEditor.getEditorInput()), new CrucibleFile(currentFileInfo,
file.isOldFile()), review);
}
}
Display.getDefault().asyncExec(new Runnable() {
public void run() {
redraw();
}
});
}
/**
* task and review might be null when called internally
*/
public void reviewDeactivated(ITask task, Review review) {
annotationModel = null;
Display.getDefault().asyncExec(new Runnable() {
public void run() {
redraw();
}
});
}
public void reviewUpdated(ITask task, Review review, Collection<CrucibleNotification> differences) {
reviewActivated(task, review);
}
}