diff dwtx/jface/text/source/projection/ProjectionRulerColumn.d @ 129:eb30df5ca28b

Added JFace Text sources
author Frank Benoit <benoit@tionex.de>
date Sat, 23 Aug 2008 19:10:48 +0200
parents
children c4fb132a086c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/text/source/projection/ProjectionRulerColumn.d	Sat Aug 23 19:10:48 2008 +0200
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module dwtx.jface.text.source.projection.ProjectionRulerColumn;
+
+import dwt.dwthelper.utils;
+
+
+import java.util.Iterator;
+
+import dwt.DWT;
+import dwt.events.MouseEvent;
+import dwt.events.MouseMoveListener;
+import dwt.events.MouseTrackAdapter;
+import dwt.graphics.Color;
+import dwt.widgets.Composite;
+import dwt.widgets.Control;
+import dwt.widgets.Display;
+import dwtx.jface.text.BadLocationException;
+import dwtx.jface.text.IDocument;
+import dwtx.jface.text.Position;
+import dwtx.jface.text.source.AnnotationRulerColumn;
+import dwtx.jface.text.source.CompositeRuler;
+import dwtx.jface.text.source.IAnnotationAccess;
+import dwtx.jface.text.source.IAnnotationModel;
+import dwtx.jface.text.source.IAnnotationModelExtension;
+
+
+/**
+ * A ruler column for controlling the behavior of a
+ * {@link dwtx.jface.text.source.projection.ProjectionViewer}.
+ *
+ * @since 3.0
+ */
+class ProjectionRulerColumn : AnnotationRulerColumn {
+
+    private ProjectionAnnotation fCurrentAnnotation;
+
+    /**
+     * Creates a new projection ruler column.
+     *
+     * @param model the column's annotation model
+     * @param width the width in pixels
+     * @param annotationAccess the annotation access
+     */
+    public ProjectionRulerColumn(IAnnotationModel model, int width, IAnnotationAccess annotationAccess) {
+        super(model, width, annotationAccess);
+    }
+
+    /**
+     * Creates a new projection ruler column.
+     *
+     * @param width the width in pixels
+     * @param annotationAccess the annotation access
+     */
+    public ProjectionRulerColumn(int width, IAnnotationAccess annotationAccess) {
+        super(width, annotationAccess);
+    }
+
+    /*
+     * @see dwtx.jface.text.source.AnnotationRulerColumn#mouseClicked(int)
+     */
+    protected void mouseClicked(int line) {
+        clearCurrentAnnotation();
+        ProjectionAnnotation annotation= findAnnotation(line, true);
+        if (annotation !is null) {
+            ProjectionAnnotationModel model= (ProjectionAnnotationModel) getModel();
+            model.toggleExpansionState(annotation);
+        }
+    }
+
+    /**
+     * Returns the projection annotation of the column's annotation
+     * model that contains the given line.
+     *
+     * @param line the line
+     * @param exact <code>true</code> if the annotation range must match exactly
+     * @return the projection annotation containing the given line
+     */
+    private ProjectionAnnotation findAnnotation(int line, bool exact) {
+
+        ProjectionAnnotation previousAnnotation= null;
+
+        IAnnotationModel model= getModel();
+        if (model !is null) {
+            IDocument document= getCachedTextViewer().getDocument();
+
+            int previousDistance= Integer.MAX_VALUE;
+
+            Iterator e= model.getAnnotationIterator();
+            while (e.hasNext()) {
+                Object next= e.next();
+                if (next instanceof ProjectionAnnotation) {
+                    ProjectionAnnotation annotation= (ProjectionAnnotation) next;
+                    Position p= model.getPosition(annotation);
+                    if (p is null)
+                        continue;
+
+                    int distance= getDistance(annotation, p, document, line);
+                    if (distance is -1)
+                        continue;
+
+                    if (!exact) {
+                        if (distance < previousDistance) {
+                            previousAnnotation= annotation;
+                            previousDistance= distance;
+                        }
+                    } else if (distance is 0) {
+                        previousAnnotation= annotation;
+                    }
+                }
+            }
+        }
+
+        return previousAnnotation;
+    }
+
+    /**
+     * Returns the distance of the given line to the start line of the given position in the given document. The distance is
+     * <code>-1</code> when the line is not included in the given position.
+     *
+     * @param annotation the annotation
+     * @param position the position
+     * @param document the document
+     * @param line the line
+     * @return <code>-1</code> if line is not contained, a position number otherwise
+     */
+    private int getDistance(ProjectionAnnotation annotation, Position position, IDocument document, int line) {
+        if (position.getOffset() > -1 && position.getLength() > -1) {
+            try {
+                int startLine= document.getLineOfOffset(position.getOffset());
+                int endLine= document.getLineOfOffset(position.getOffset() + position.getLength());
+                if (startLine <= line && line < endLine) {
+                    if (annotation.isCollapsed()) {
+                        int captionOffset;
+                        if (position instanceof IProjectionPosition)
+                            captionOffset= ((IProjectionPosition) position).computeCaptionOffset(document);
+                        else
+                            captionOffset= 0;
+
+                        int captionLine= document.getLineOfOffset(position.getOffset() + captionOffset);
+                        if (startLine <= captionLine && captionLine < endLine)
+                            return Math.abs(line - captionLine);
+                    }
+                    return line - startLine;
+                }
+            } catch (BadLocationException x) {
+            }
+        }
+        return -1;
+    }
+
+    private bool clearCurrentAnnotation() {
+        if (fCurrentAnnotation !is null) {
+            fCurrentAnnotation.setRangeIndication(false);
+            fCurrentAnnotation= null;
+            return true;
+        }
+        return false;
+    }
+
+    /*
+     * @see dwtx.jface.text.source.IVerticalRulerColumn#createControl(dwtx.jface.text.source.CompositeRuler, dwt.widgets.Composite)
+     */
+    public Control createControl(CompositeRuler parentRuler, Composite parentControl) {
+        Control control= super.createControl(parentRuler, parentControl);
+
+        // set background
+        Display display= parentControl.getDisplay();
+        Color background= display.getSystemColor(DWT.COLOR_LIST_BACKGROUND);
+        control.setBackground(background);
+
+        // install hover listener
+        control.addMouseTrackListener(new MouseTrackAdapter() {
+            public void mouseExit(MouseEvent e) {
+                if (clearCurrentAnnotation())
+                    redraw();
+            }
+        });
+
+        // install mouse move listener
+        control.addMouseMoveListener(new MouseMoveListener() {
+            public void mouseMove(MouseEvent e) {
+                bool redraw= false;
+                ProjectionAnnotation annotation= findAnnotation(toDocumentLineNumber(e.y), false);
+                if (annotation !is fCurrentAnnotation) {
+                    if (fCurrentAnnotation !is null) {
+                        fCurrentAnnotation.setRangeIndication(false);
+                        redraw= true;
+                    }
+                    fCurrentAnnotation= annotation;
+                    if (fCurrentAnnotation !is null && !fCurrentAnnotation.isCollapsed()) {
+                        fCurrentAnnotation.setRangeIndication(true);
+                        redraw= true;
+                    }
+                }
+                if (redraw)
+                    redraw();
+            }
+        });
+        return control;
+    }
+
+    /*
+     * @see dwtx.jface.text.source.AnnotationRulerColumn#setModel(dwtx.jface.text.source.IAnnotationModel)
+     */
+    public void setModel(IAnnotationModel model) {
+        if (model instanceof IAnnotationModelExtension) {
+            IAnnotationModelExtension extension= (IAnnotationModelExtension) model;
+            model= extension.getAnnotationModel(ProjectionSupport.PROJECTION);
+        }
+        super.setModel(model);
+    }
+
+    /*
+     * @see dwtx.jface.text.source.AnnotationRulerColumn#isPropagatingMouseListener()
+     */
+    protected bool isPropagatingMouseListener() {
+        return false;
+    }
+
+    /*
+     * @see dwtx.jface.text.source.AnnotationRulerColumn#hasAnnotation(int)
+     */
+    protected bool hasAnnotation(int lineNumber) {
+        return findAnnotation(lineNumber, true) !is null;
+    }
+}