/*
* Copyright 2013 Hewlett-Packard Development Company, L.P
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hp.alm.ali.idea.content.devmotive;
import com.hp.alm.ali.idea.content.AliContentFactory;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorGutter;
import com.intellij.openapi.editor.colors.ColorKey;
import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.actions.ActiveAnnotationGutter;
import com.intellij.openapi.vcs.annotate.FileAnnotation;
import com.intellij.openapi.vcs.history.VcsFileRevision;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.ui.content.ContentManagerEvent;
import com.intellij.ui.content.ContentManagerListener;
import org.jetbrains.annotations.Nullable;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.Color;
import java.awt.Cursor;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class DevMotiveAnnotationGutter implements ActiveAnnotationGutter, ChangeListener, ContentManagerListener {
private FileAnnotation annotation;
private DevMotivePanel devMotivePanel;
private EditorGutterComponentEx editorGutterComponentEx;
private String unknownLine;
public DevMotiveAnnotationGutter(Project project, FileAnnotation annotation, List<VcsFileRevision> revisions, EditorGutter editorGutter) {
this.annotation = annotation;
devMotivePanel = AliContentFactory.addDevMotiveContent(project, annotation.getFile(), revisions, annotation.getVcsKey().getName(), this, true);
devMotivePanel.addChangeListener(this);
if (editorGutter instanceof EditorGutterComponentEx) {
editorGutterComponentEx = (EditorGutterComponentEx) editorGutter;
unknownLine = "???";
} else {
// unable to resize, make sure to reserve enough room
unknownLine = "??????????";
}
}
@Override
public void stateChanged(ChangeEvent e) {
updateAnnotations();
}
private void updateAnnotations() {
if (editorGutterComponentEx != null) {
editorGutterComponentEx.revalidateMarkup();
}
}
@Override
public void doAction(int line) {
if (devMotivePanel == null) {
return;
}
VcsRevisionNumber revisionNumber = annotation.getLineRevisionNumber(line);
if (revisionNumber != null) {
devMotivePanel.selectRevision(revisionNumber);
}
}
@Override
public Cursor getCursor(int line) {
if (devMotivePanel == null) {
return Cursor.getDefaultCursor();
}
VcsRevisionNumber revisionNumber = annotation.getLineRevisionNumber(line);
if (revisionNumber != null) {
Collection<WorkItem> workItems = devMotivePanel.getWorkItemsByRevisionNumber(revisionNumber, true);
if (workItems != null && !workItems.isEmpty() ) {
return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
}
}
return Cursor.getDefaultCursor();
}
@Nullable
@Override
public String getLineText(int line, Editor editor) {
VcsRevisionNumber revisionNumber = annotation.getLineRevisionNumber(line);
if (revisionNumber == null) {
return null;
}
if (devMotivePanel == null) {
return "---";
}
Collection<WorkItem> workItems = devMotivePanel.getWorkItemsByRevisionNumber(revisionNumber, false);
if (workItems == null) {
return unknownLine;
}
StringBuffer buf = new StringBuffer();
for (WorkItem workItem: workItems) {
if (buf.length() > 0) {
buf.append(", ");
}
switch (workItem.getType()) {
case DEFECT:
buf.append("D: ");
break;
case USER_STORY:
buf.append("U: ");
break;
}
buf.append(workItem.getId());
}
return buf.toString();
}
@Nullable
@Override
public String getToolTip(int line, Editor editor) {
VcsRevisionNumber revisionNumber = annotation.getLineRevisionNumber(line);
if (revisionNumber == null) {
return null;
}
if (devMotivePanel == null) {
return "Dev Motive closed";
}
Collection<WorkItem> workItems = devMotivePanel.getWorkItemsByRevisionNumber(revisionNumber, true);
if (workItems == null) {
if (loadRevisionNumber(revisionNumber)) {
return "Loading association information...";
} else {
return "Revision not found";
}
} else if (!workItems.isEmpty()) {
StringBuffer buf = new StringBuffer();
for (WorkItem workItem: workItems) {
if (buf.length() > 0) {
buf.append("\n\n");
}
buf.append(getWorkItemToolTip(workItem));
}
return buf.toString();
} else {
return null;
}
}
private boolean loadRevisionNumber(VcsRevisionNumber revisionNumber) {
List<VcsFileRevision> revisions = annotation.getRevisions();
if (revisions != null) {
for (VcsFileRevision revision: revisions) {
if (revisionNumber.equals(revision.getRevisionNumber())) {
devMotivePanel.load(Arrays.asList(revision));
return true;
}
}
}
return false;
}
@Override
public EditorFontType getStyle(int line, Editor editor) {
VcsRevisionNumber revisionNumber = annotation.getLineRevisionNumber(line);
if (revisionNumber != null && revisionNumber.equals(annotation.getCurrentRevision())) {
return EditorFontType.BOLD_ITALIC;
} else {
return EditorFontType.ITALIC;
}
}
@Nullable
@Override
public ColorKey getColor(int line, Editor editor) {
return null;
}
@Nullable
@Override
public Color getBgColor(int line, Editor editor) {
return null;
}
@Override
public List<AnAction> getPopupActions(int line, Editor editor) {
return Collections.emptyList();
}
@Override
public void gutterClosed() {
releasePanel();
}
private void releasePanel() {
if (devMotivePanel != null) {
devMotivePanel.removeChangeListener(this);
devMotivePanel = null;
}
}
private String getWorkItemToolTip(WorkItem workItem) {
if (WorkItem.Type.NONE.equals(workItem.getType())) {
return workItem.getName();
} else {
return workItem.getType() + " #" + workItem.getId() + ": " + workItem.getName();
}
}
@Override
public void contentAdded(ContentManagerEvent event) {
if (devMotivePanel == null && event.getContent().getComponent() instanceof DevMotivePanel) {
DevMotivePanel panel = (DevMotivePanel) event.getContent().getComponent();
if (annotation.getFile().equals(panel.getFile())) {
devMotivePanel = panel;
devMotivePanel.addChangeListener(this);
}
}
}
@Override
public void contentRemoved(ContentManagerEvent event) {
if (devMotivePanel != null && devMotivePanel.equals(event.getContent().getComponent())) {
releasePanel();
updateAnnotations();
}
}
@Override
public void contentRemoveQuery(ContentManagerEvent event) {
}
@Override
public void selectionChanged(ContentManagerEvent event) {
}
}