Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKai Maetzel2004-04-07 19:57:45 +0000
committerKai Maetzel2004-04-07 19:57:45 +0000
commit7640754a617d2a64db39f8261affb55b6b41df1c (patch)
treee23414e69fccaa188dce2579874d8ad3e9523b4a
parent1db8e410e0cb2badefadfc3af625c2dce2d004e2 (diff)
downloadeclipse.platform.text-7640754a617d2a64db39f8261affb55b6b41df1c.tar.gz
eclipse.platform.text-7640754a617d2a64db39f8261affb55b6b41df1c.tar.xz
eclipse.platform.text-7640754a617d2a64db39f8261affb55b6b41df1c.zip
projection summaries
-rw-r--r--org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/AnnotationBag.java50
-rw-r--r--org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionAnnotationModel.java102
-rw-r--r--org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionSummary.java189
-rw-r--r--org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionSupport.java47
4 files changed, 380 insertions, 8 deletions
diff --git a/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/AnnotationBag.java b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/AnnotationBag.java
new file mode 100644
index 000000000..830c9fed4
--- /dev/null
+++ b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/AnnotationBag.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jface.text.source.projection;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.jface.text.source.Annotation;
+
+/**
+ * A bag of annotations.
+ */
+public class AnnotationBag extends Annotation {
+
+ private Set fAnnotations;
+
+ /** Creates a new annotation bag.
+ *
+ * @param type the annotation type
+ */
+ public AnnotationBag(String type) {
+ super(type, false, null);
+ }
+
+ public void add(Annotation annotation) {
+ if (fAnnotations == null)
+ fAnnotations= new HashSet(2);
+ fAnnotations.add(annotation);
+ }
+
+ public void remove(Annotation annotation) {
+ if (fAnnotations != null) {
+ fAnnotations.remove(annotation);
+ if (fAnnotations.isEmpty())
+ fAnnotations= null;
+ }
+ }
+
+ public boolean isEmpty() {
+ return fAnnotations == null;
+ }
+}
diff --git a/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionAnnotationModel.java b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionAnnotationModel.java
index aac5b2736..72c9779eb 100644
--- a/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionAnnotationModel.java
+++ b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionAnnotationModel.java
@@ -11,7 +11,11 @@
package org.eclipse.jface.text.source.projection;
import java.util.Iterator;
+import java.util.Map;
+import org.eclipse.core.runtime.NullProgressMonitor;
+
+import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.AnnotationModel;
@@ -25,6 +29,61 @@ import org.eclipse.jface.text.source.AnnotationModel;
* @since 3.0
*/
public class ProjectionAnnotationModel extends AnnotationModel {
+
+
+ private class Summarizer extends Thread {
+
+ public Summarizer() {
+ setDaemon(true);
+ start();
+ synchronized (fLock) {
+ fHasStarted= false;
+ }
+ }
+
+ /*
+ * @see java.lang.Thread#run()
+ */
+ public void run() {
+
+ synchronized (fLock) {
+ fHasStarted= true;
+ }
+
+ fProjectionSummary.updateSummaries(new NullProgressMonitor());
+
+ synchronized (fLock) {
+ if (fSummarizer == this)
+ fSummarizer= null;
+ }
+ }
+ }
+
+
+ private ProjectionSummary fProjectionSummary;
+
+ private Object fLock= new Object();
+ private volatile Summarizer fSummarizer;
+ private volatile boolean fHasStarted= false;
+
+
+ public ProjectionAnnotationModel(ProjectionSummary summary) {
+ fProjectionSummary= summary;
+ }
+
+ public void setProjectionSummary(ProjectionSummary summary) {
+ fProjectionSummary= summary;
+ }
+
+ private void updateSummaries() {
+ if (fProjectionSummary == null)
+ return;
+
+ synchronized (fLock) {
+ if (fSummarizer == null || fHasStarted)
+ fSummarizer= new Summarizer();
+ }
+ }
/**
* Changes the state of the given annotation to collapsed. An appropriate
@@ -38,6 +97,7 @@ public class ProjectionAnnotationModel extends AnnotationModel {
if (!projection.isCollapsed()) {
projection.markCollapsed();
modifyAnnotation(projection, true);
+ updateSummaries();
}
}
}
@@ -54,6 +114,7 @@ public class ProjectionAnnotationModel extends AnnotationModel {
if (projection.isCollapsed()) {
projection.markExpanded();
modifyAnnotation(projection, true);
+ updateSummaries();
}
}
}
@@ -74,6 +135,7 @@ public class ProjectionAnnotationModel extends AnnotationModel {
projection.markCollapsed();
modifyAnnotation(projection, true);
+ updateSummaries();
}
}
@@ -85,6 +147,20 @@ public class ProjectionAnnotationModel extends AnnotationModel {
* @return <code>true</code> if any annotation has been expanded, <code>false</code> otherwise
*/
public boolean expandAll(int offset, int length) {
+ return expandAll(offset, length, true);
+ }
+
+ /**
+ * Expands all annotations that overlap with the given range and are collapsed. Fires a model change event if
+ * requested.
+ *
+ * @param offset the offset of the range
+ * @param length the length of the range
+ * @param fireModelChanged <code>true</code> if a model change event
+ * should be fired, <code>false</code> otherwise
+ * @return <code>true</code> if any annotation has been expanded, <code>false</code> otherwise
+ */
+ protected boolean expandAll(int offset, int length, boolean fireModelChanged) {
boolean expanding= false;
@@ -101,9 +177,31 @@ public class ProjectionAnnotationModel extends AnnotationModel {
}
}
- if (expanding)
- fireModelChanged();
+ if (expanding) {
+ if (fireModelChanged)
+ fireModelChanged();
+ updateSummaries();
+ }
return expanding;
}
+
+ /**
+ * Modifies the annotation model.
+ *
+ * @param deletions the list of deleted annotations
+ * @param additions the set of annotations to add together with their associated position
+ * @param modifications the list of modified annotations
+ */
+ public void modifyAnnotations(Annotation[] deletions, Map additions, Annotation[] modifications) {
+ try {
+ replaceAnnotations(deletions, additions, false);
+ if (modifications != null) {
+ for (int i= 0; i < modifications.length; i++)
+ modifyAnnotation(modifications[i], false);
+ }
+ } catch (BadLocationException x) {
+ }
+ fireModelChanged();
+ }
} \ No newline at end of file
diff --git a/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionSummary.java b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionSummary.java
new file mode 100644
index 000000000..814325b73
--- /dev/null
+++ b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionSummary.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jface.text.source.projection;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationAccess;
+import org.eclipse.jface.text.source.IAnnotationAccessExtension;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.IAnnotationModelExtension;
+
+/**
+ * Strategy for managing annotation summaries for collapsed ranges.
+ *
+ * @since 3.0
+ */
+public class ProjectionSummary {
+
+ private ProjectionViewer fProjectionViewer;
+ private IAnnotationModel fAnnotationModel;
+ private IAnnotationAccess fAnnotationAccess;
+ private List fConfiguredAnnotationTypes;
+
+ public ProjectionSummary(ProjectionViewer projectionViewer, IAnnotationAccess annotationAccess) {
+ super();
+ fProjectionViewer= projectionViewer;
+ fAnnotationAccess= annotationAccess;
+ }
+
+ public void addAnnotationType(String annotationType) {
+ if (fConfiguredAnnotationTypes == null) {
+ fConfiguredAnnotationTypes= new ArrayList();
+ fConfiguredAnnotationTypes.add(annotationType);
+ } else if (!fConfiguredAnnotationTypes.contains(annotationType))
+ fConfiguredAnnotationTypes.add(annotationType);
+ }
+
+ public void removeAnnotationType(String annotationType) {
+ if (fConfiguredAnnotationTypes != null) {
+ fConfiguredAnnotationTypes.remove(annotationType);
+ if (fConfiguredAnnotationTypes.size() == 0)
+ fConfiguredAnnotationTypes= null;
+ }
+ }
+
+ public void updateSummaries(IProgressMonitor monitor) {
+ fAnnotationModel= fProjectionViewer.getVisualAnnotationModel();
+ removeSummaries(monitor);
+ createSummaries(monitor);
+ }
+
+ private boolean isCanceled(IProgressMonitor monitor) {
+ return monitor != null && monitor.isCanceled();
+ }
+
+ public void removeSummaries(IProgressMonitor monitor) {
+ IAnnotationModelExtension extension= null;
+ List bags= null;
+
+ if (fAnnotationModel instanceof IAnnotationModelExtension) {
+ extension= (IAnnotationModelExtension) fAnnotationModel;
+ bags= new ArrayList();
+ }
+
+ Iterator e= fAnnotationModel.getAnnotationIterator();
+ while (e.hasNext()) {
+ Annotation annotation= (Annotation) e.next();
+ if (annotation instanceof AnnotationBag) {
+ if (bags == null)
+ fAnnotationModel.removeAnnotation(annotation);
+ else
+ bags.add(annotation);
+ }
+
+ if (isCanceled(monitor))
+ return;
+ }
+
+ if (bags != null && bags.size() > 0) {
+ Annotation[] deletions= new Annotation[bags.size()];
+ bags.toArray(deletions);
+ if (!isCanceled(monitor))
+ extension.replaceAnnotations(deletions, null);
+ }
+ }
+
+ public void createSummaries(IProgressMonitor monitor) {
+ Map additions= new HashMap();
+
+ ProjectionAnnotationModel model= fProjectionViewer.getProjectionAnnotationModel();
+ Iterator e= model.getAnnotationIterator();
+ while (e.hasNext()) {
+ ProjectionAnnotation projection= (ProjectionAnnotation) e.next();
+ if (projection.isCollapsed()) {
+ Position position= model.getPosition(projection);
+ IRegion summaryRegion= fProjectionViewer.computeCollapsedRegion(position);
+ if (summaryRegion != null) {
+ Position summaryAnchor= fProjectionViewer.computeCollapsedRegionAnchor(position);
+ if (summaryAnchor != null)
+ createSummary(additions, summaryRegion, summaryAnchor);
+ }
+ }
+
+ if (isCanceled(monitor))
+ return;
+ }
+
+ if (additions.size() > 0) {
+ if (fAnnotationModel instanceof IAnnotationModelExtension) {
+ IAnnotationModelExtension extension= (IAnnotationModelExtension) fAnnotationModel;
+ if (!isCanceled(monitor))
+ extension.replaceAnnotations(null, additions);
+ } else {
+ Iterator e1= additions.keySet().iterator();
+ while (e1.hasNext()) {
+ AnnotationBag bag= (AnnotationBag) e1.next();
+ Position position= (Position) additions.get(bag);
+ if (isCanceled(monitor))
+ return;
+ fAnnotationModel.addAnnotation(bag, position);
+ }
+ }
+ }
+ }
+
+ private void createSummary(Map additions, IRegion summaryRange, Position summaryAnchor) {
+ Map map= new HashMap();
+
+ int size= fConfiguredAnnotationTypes.size();
+ for (int i= 0; i < size; i++) {
+ String type= (String) fConfiguredAnnotationTypes.get(i);
+ map.put(type, new AnnotationBag(type));
+ }
+
+ IAnnotationModel model= fProjectionViewer.getAnnotationModel();
+ Iterator e= model.getAnnotationIterator();
+ while (e.hasNext()) {
+ Annotation annotation= (Annotation) e.next();
+ AnnotationBag bag= findBagForType(map, annotation.getType());
+ if (bag != null) {
+ Position position= model.getPosition(annotation);
+ if (includes(summaryRange, position))
+ bag.add(annotation);
+ }
+ }
+
+ for (int i= 0; i < size; i++) {
+ AnnotationBag bag= (AnnotationBag) map.get(fConfiguredAnnotationTypes.get(i));
+ if (!bag.isEmpty())
+ additions.put(bag, new Position(summaryAnchor.getOffset(), summaryAnchor.getLength()));
+ }
+ }
+
+ private AnnotationBag findBagForType(Map bagMap, String annotationType) {
+ if (fAnnotationAccess instanceof IAnnotationAccessExtension) {
+ IAnnotationAccessExtension extension= (IAnnotationAccessExtension) fAnnotationAccess;
+ Object[] superTypes= extension.getSupertypes(annotationType);
+ for (int i= 0; i < superTypes.length; i++) {
+ AnnotationBag bag= (AnnotationBag) bagMap.get(superTypes[i]);
+ if (bag != null)
+ return bag;
+ }
+ }
+ return null;
+ }
+
+ private boolean includes(IRegion range, Position position) {
+ if (!position.isDeleted())
+ return range.getOffset() <= position.getOffset() && position.getOffset() + position.getLength() <= range.getOffset() + range.getLength();
+ return false;
+ }
+}
diff --git a/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionSupport.java b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionSupport.java
index d86034995..13a5ef92f 100644
--- a/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionSupport.java
+++ b/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionSupport.java
@@ -10,6 +10,9 @@
*******************************************************************************/
package org.eclipse.jface.text.source.projection;
+import java.util.ArrayList;
+import java.util.List;
+
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.StyledTextContent;
@@ -99,13 +102,26 @@ public class ProjectionSupport {
}
private final static Object PROJECTION= new Object();
+ private List fSummarizableTypes;
- private static RGB getColor() {
- // TODO read out preference settings
- Color c= Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY);
- return c.getRGB();
+ public ProjectionSupport() {
}
+ public void addSummarizableAnnotationType(String annotationType) {
+ if (fSummarizableTypes == null) {
+ fSummarizableTypes= new ArrayList();
+ fSummarizableTypes.add(annotationType);
+ } else if (!fSummarizableTypes.contains(annotationType))
+ fSummarizableTypes.add(annotationType);
+ }
+
+ public void removeSummarizableAnnotationType(String annotationType) {
+ if (fSummarizableTypes != null)
+ fSummarizableTypes.remove(annotationType);
+ if (fSummarizableTypes.size() == 0)
+ fSummarizableTypes= null;
+ }
+
/**
* Enable projection for the given viewer
*
@@ -113,11 +129,13 @@ public class ProjectionSupport {
* @param annotationAccess the annotation access
* @param sharedTextColors the shared text colors
*/
- public static void enableProjection(ISourceViewer viewer, IAnnotationAccess annotationAccess, ISharedTextColors sharedTextColors) {
+ public void enableProjection(ISourceViewer viewer, IAnnotationAccess annotationAccess, ISharedTextColors sharedTextColors) {
if (viewer instanceof ProjectionViewer) {
ProjectionViewer projectionViewer= (ProjectionViewer) viewer;
+ projectionViewer.setProjectionSummary(createProjectionSummary(projectionViewer, annotationAccess));
+
AnnotationPainter painter= new ProjectionAnnotationsPainter(projectionViewer, annotationAccess);
painter.addDrawingStrategy(PROJECTION, new ProjectionDrawingStrategy());
painter.addAnnotationType(ProjectionAnnotation.TYPE, PROJECTION);
@@ -126,15 +144,26 @@ public class ProjectionSupport {
ProjectionRulerColumn column= new ProjectionRulerColumn(projectionViewer.getProjectionAnnotationModel(), 9, annotationAccess);
column.addAnnotationType(ProjectionAnnotation.TYPE);
+ // TODO make hover configurable from outside
column.setHover(new ProjectionAnnotationHover());
projectionViewer.addVerticalRulerColumn(column);
}
}
+
+ private ProjectionSummary createProjectionSummary(ProjectionViewer projectionViewer, IAnnotationAccess annotationAccess) {
+ ProjectionSummary summary= new ProjectionSummary(projectionViewer, annotationAccess);
+ if (fSummarizableTypes != null) {
+ int size= fSummarizableTypes.size();
+ for (int i= 0; i < size; i++)
+ summary.addAnnotationType((String) fSummarizableTypes.get(i));
+ }
+ return summary;
+ }
/**
* @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
*/
- public static Object getAdapter(ISourceViewer viewer, Class required) {
+ public Object getAdapter(ISourceViewer viewer, Class required) {
if (ProjectionAnnotationModel.class.equals(required)) {
if (viewer instanceof ProjectionViewer) {
ProjectionViewer projectionViewer= (ProjectionViewer) viewer;
@@ -143,4 +172,10 @@ public class ProjectionSupport {
}
return null;
}
+
+ private RGB getColor() {
+ // TODO read out preference settings
+ Color c= Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY);
+ return c.getRGB();
+ }
}

Back to the top