diff dwtx/jface/text/source/CompositeRuler.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/CompositeRuler.d	Sat Aug 23 19:10:48 2008 +0200
@@ -0,0 +1,881 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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.CompositeRuler;
+
+import dwt.dwthelper.utils;
+
+
+import java.util.ArrayList;
+import java.util.EventListener;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import dwt.DWT;
+import dwt.custom.StyledText;
+import dwt.events.ControlListener;
+import dwt.events.DisposeEvent;
+import dwt.events.DisposeListener;
+import dwt.events.FocusListener;
+import dwt.events.HelpListener;
+import dwt.events.KeyListener;
+import dwt.events.MouseListener;
+import dwt.events.MouseMoveListener;
+import dwt.events.MouseTrackListener;
+import dwt.events.PaintListener;
+import dwt.events.TraverseListener;
+import dwt.graphics.Font;
+import dwt.graphics.Point;
+import dwt.graphics.Rectangle;
+import dwt.widgets.Canvas;
+import dwt.widgets.Composite;
+import dwt.widgets.Control;
+import dwt.widgets.Display;
+import dwt.widgets.Event;
+import dwt.widgets.Layout;
+import dwt.widgets.Listener;
+import dwt.widgets.Menu;
+import dwtx.core.runtime.Assert;
+import dwtx.jface.text.BadLocationException;
+import dwtx.jface.text.IDocument;
+import dwtx.jface.text.IRegion;
+import dwtx.jface.text.ITextViewer;
+import dwtx.jface.text.ITextViewerExtension;
+import dwtx.jface.text.ITextViewerExtension5;
+
+
+/**
+ * Standard implementation of
+ * {@link dwtx.jface.text.source.IVerticalRuler}.
+ * <p>
+ * This ruler does not have a a visual representation of its own. The
+ * presentation comes from the configurable list of vertical ruler columns. Such
+ * columns must implement the
+ * {@link dwtx.jface.text.source.IVerticalRulerColumn}. interface.</p>
+ * <p>
+ * Clients may instantiate and configure this class.</p>
+ *
+ * @see dwtx.jface.text.source.IVerticalRulerColumn
+ * @see dwtx.jface.text.ITextViewer
+ * @since 2.0
+ */
+public class CompositeRuler : IVerticalRuler, IVerticalRulerExtension, IVerticalRulerInfoExtension {
+
+
+    /**
+     * Layout of the composite vertical ruler. Arranges the list of columns.
+     */
+    class RulerLayout : Layout {
+
+        /**
+         * Creates the new ruler layout.
+         */
+        protected RulerLayout() {
+        }
+
+        /*
+         * @see Layout#computeSize(Composite, int, int, bool)
+         */
+        protected Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) {
+            Control[] children= composite.getChildren();
+            Point size= new Point(0, 0);
+            for (int i= 0; i < children.length; i++) {
+                Point s= children[i].computeSize(DWT.DEFAULT, DWT.DEFAULT, flushCache);
+                size.x += s.x;
+                size.y= Math.max(size.y, s.y);
+            }
+            size.x += (Math.max(0, children.length -1) * fGap);
+            return size;
+        }
+
+        /*
+         * @see Layout#layout(Composite, bool)
+         */
+        protected void layout(Composite composite, bool flushCache) {
+            Rectangle clArea= composite.getClientArea();
+            int rulerHeight= clArea.height;
+
+            int x= 0;
+            Iterator e= fDecorators.iterator();
+            while (e.hasNext()) {
+                IVerticalRulerColumn column= (IVerticalRulerColumn) e.next();
+                int columnWidth= column.getWidth();
+                column.getControl().setBounds(x, 0, columnWidth, rulerHeight);
+                x += (columnWidth + fGap);
+            }
+        }
+    }
+
+    /**
+     * A canvas that adds listeners to all its children. Used by the implementation of the
+     * vertical ruler to propagate listener additions and removals to the ruler's columns.
+     */
+    static class CompositeRulerCanvas : Canvas {
+
+        /**
+         * Keeps the information for which event type a listener object has been added.
+         */
+        static class ListenerInfo {
+            Class fClass;
+            EventListener fListener;
+        }
+
+        /** The list of listeners added to this canvas. */
+        private List fCachedListeners= new ArrayList();
+        /**
+         * Internal listener for opening the context menu.
+         * @since 3.0
+         */
+        private Listener fMenuDetectListener;
+
+        /**
+         * Creates a new composite ruler canvas.
+         *
+         * @param parent the parent composite
+         * @param style the DWT styles
+         */
+        public CompositeRulerCanvas(Composite parent, int style) {
+            super(parent, style);
+            fMenuDetectListener= new Listener() {
+                public void handleEvent(Event event) {
+                    if (event.type is DWT.MenuDetect) {
+                        Menu menu= getMenu();
+                        if (menu !is null) {
+                            menu.setLocation(event.x, event.y);
+                            menu.setVisible(true);
+                        }
+                    }
+                }
+            };
+            super.addDisposeListener(new DisposeListener() {
+                public void widgetDisposed(DisposeEvent e) {
+                    if (fCachedListeners !is null) {
+                        fCachedListeners.clear();
+                        fCachedListeners= null;
+                    }
+                }
+            });
+        }
+
+        /**
+         * Adds the given listener object as listener of the given type (<code>clazz</code>) to
+         * the given control.
+         *
+         * @param clazz the listener type
+         * @param control the control to add the listener to
+         * @param listener the listener to be added
+         */
+        private void addListener(Class clazz, Control control, EventListener listener) {
+            if (ControlListener.class.equals(clazz)) {
+                control. addControlListener((ControlListener) listener);
+                return;
+            }
+            if (FocusListener.class.equals(clazz)) {
+                control. addFocusListener((FocusListener) listener);
+                return;
+            }
+            if (HelpListener.class.equals(clazz)) {
+                control. addHelpListener((HelpListener) listener);
+                return;
+            }
+            if (KeyListener.class.equals(clazz)) {
+                control. addKeyListener((KeyListener) listener);
+                return;
+            }
+            if (MouseListener.class.equals(clazz)) {
+                control. addMouseListener((MouseListener) listener);
+                return;
+            }
+            if (MouseMoveListener.class.equals(clazz)) {
+                control. addMouseMoveListener((MouseMoveListener) listener);
+                return;
+            }
+            if (MouseTrackListener.class.equals(clazz)) {
+                control. addMouseTrackListener((MouseTrackListener) listener);
+                return;
+            }
+            if (PaintListener.class.equals(clazz)) {
+                control. addPaintListener((PaintListener) listener);
+                return;
+            }
+            if (TraverseListener.class.equals(clazz)) {
+                control. addTraverseListener((TraverseListener) listener);
+                return;
+            }
+            if (DisposeListener.class.equals(clazz)) {
+                control. addDisposeListener((DisposeListener) listener);
+                return;
+            }
+        }
+
+        /**
+         * Removes the given listener object as listener of the given type (<code>clazz</code>) from
+         * the given control.
+         *
+         * @param clazz the listener type
+         * @param control the control to remove the listener from
+         * @param listener the listener to be removed
+         */
+        private void removeListener(Class clazz, Control control, EventListener listener) {
+            if (ControlListener.class.equals(clazz)) {
+                control. removeControlListener((ControlListener) listener);
+                return;
+            }
+            if (FocusListener.class.equals(clazz)) {
+                control. removeFocusListener((FocusListener) listener);
+                return;
+            }
+            if (HelpListener.class.equals(clazz)) {
+                control. removeHelpListener((HelpListener) listener);
+                return;
+            }
+            if (KeyListener.class.equals(clazz)) {
+                control. removeKeyListener((KeyListener) listener);
+                return;
+            }
+            if (MouseListener.class.equals(clazz)) {
+                control. removeMouseListener((MouseListener) listener);
+                return;
+            }
+            if (MouseMoveListener.class.equals(clazz)) {
+                control. removeMouseMoveListener((MouseMoveListener) listener);
+                return;
+            }
+            if (MouseTrackListener.class.equals(clazz)) {
+                control. removeMouseTrackListener((MouseTrackListener) listener);
+                return;
+            }
+            if (PaintListener.class.equals(clazz)) {
+                control. removePaintListener((PaintListener) listener);
+                return;
+            }
+            if (TraverseListener.class.equals(clazz)) {
+                control. removeTraverseListener((TraverseListener) listener);
+                return;
+            }
+            if (DisposeListener.class.equals(clazz)) {
+                control. removeDisposeListener((DisposeListener) listener);
+                return;
+            }
+        }
+
+        /**
+         * Adds the given listener object to the internal book keeping under
+         * the given listener type (<code>clazz</code>).
+         *
+         * @param clazz the listener type
+         * @param listener the listener object
+         */
+        private void addListener(Class clazz, EventListener listener) {
+            Control[] children= getChildren();
+            for (int i= 0; i < children.length; i++) {
+                if (children[i] !is null && !children[i].isDisposed())
+                    addListener(clazz, children[i], listener);
+            }
+
+            ListenerInfo info= new ListenerInfo();
+            info.fClass= clazz;
+            info.fListener= listener;
+            fCachedListeners.add(info);
+        }
+
+        /**
+         * Removes the given listener object from the internal book keeping under
+         * the given listener type (<code>clazz</code>).
+         *
+         * @param clazz the listener type
+         * @param listener the listener object
+         */
+        private void removeListener(Class clazz, EventListener listener) {
+            int length= fCachedListeners.size();
+            for (int i= 0; i < length; i++) {
+                ListenerInfo info= (ListenerInfo) fCachedListeners.get(i);
+                if (listener is info.fListener && clazz.equals(info.fClass)) {
+                    fCachedListeners.remove(i);
+                    break;
+                }
+            }
+
+            Control[] children= getChildren();
+            for (int i= 0; i < children.length; i++) {
+                if (children[i] !is null && !children[i].isDisposed())
+                    removeListener(clazz, children[i], listener);
+            }
+        }
+
+        /**
+         * Tells this canvas that a child has been added.
+         *
+         * @param child the child
+         */
+        public void childAdded(Control child) {
+            if (child !is null && !child.isDisposed()) {
+                int length= fCachedListeners.size();
+                for (int i= 0; i < length; i++) {
+                    ListenerInfo info= (ListenerInfo) fCachedListeners.get(i);
+                    addListener(info.fClass, child, info.fListener);
+                }
+                child.addListener(DWT.MenuDetect, fMenuDetectListener);
+            }
+        }
+
+        /**
+         * Tells this canvas that a child has been removed.
+         *
+         * @param child the child
+         */
+        public void childRemoved(Control child) {
+            if (child !is null && !child.isDisposed()) {
+                int length= fCachedListeners.size();
+                for (int i= 0; i < length; i++) {
+                    ListenerInfo info= (ListenerInfo) fCachedListeners.get(i);
+                    removeListener(info.fClass, child, info.fListener);
+                }
+                child.removeListener(DWT.MenuDetect, fMenuDetectListener);
+            }
+        }
+
+        /*
+         * @see Control#removeControlListener(ControlListener)
+         */
+        public void removeControlListener(ControlListener listener) {
+            removeListener(ControlListener.class, listener);
+            super.removeControlListener(listener);
+        }
+
+        /*
+         * @see Control#removeFocusListener(FocusListener)
+         */
+        public void removeFocusListener(FocusListener listener) {
+            removeListener(FocusListener.class, listener);
+            super.removeFocusListener(listener);
+        }
+
+        /*
+         * @see Control#removeHelpListener(HelpListener)
+         */
+        public void removeHelpListener(HelpListener listener) {
+            removeListener(HelpListener.class, listener);
+            super.removeHelpListener(listener);
+        }
+
+        /*
+         * @see Control#removeKeyListener(KeyListener)
+         */
+        public void removeKeyListener(KeyListener listener) {
+            removeListener(KeyListener.class, listener);
+            super.removeKeyListener(listener);
+        }
+
+        /*
+         * @see Control#removeMouseListener(MouseListener)
+         */
+        public void removeMouseListener(MouseListener listener) {
+            removeListener(MouseListener.class, listener);
+            super.removeMouseListener(listener);
+        }
+
+        /*
+         * @see Control#removeMouseMoveListener(MouseMoveListener)
+         */
+        public void removeMouseMoveListener(MouseMoveListener listener) {
+            removeListener(MouseMoveListener.class, listener);
+            super.removeMouseMoveListener(listener);
+        }
+
+        /*
+         * @see Control#removeMouseTrackListener(MouseTrackListener)
+         */
+        public void removeMouseTrackListener(MouseTrackListener listener) {
+            removeListener(MouseTrackListener.class, listener);
+            super.removeMouseTrackListener(listener);
+        }
+
+        /*
+         * @see Control#removePaintListener(PaintListener)
+         */
+        public void removePaintListener(PaintListener listener) {
+            removeListener(PaintListener.class, listener);
+            super.removePaintListener(listener);
+        }
+
+        /*
+         * @see Control#removeTraverseListener(TraverseListener)
+         */
+        public void removeTraverseListener(TraverseListener listener) {
+            removeListener(TraverseListener.class, listener);
+            super.removeTraverseListener(listener);
+        }
+
+        /*
+         * @see Widget#removeDisposeListener(DisposeListener)
+         */
+        public void removeDisposeListener(DisposeListener listener) {
+            removeListener(DisposeListener.class, listener);
+            super.removeDisposeListener(listener);
+        }
+
+        /*
+         * @seeControl#addControlListener(ControlListener)
+         */
+        public void addControlListener(ControlListener listener) {
+            super.addControlListener(listener);
+            addListener(ControlListener.class, listener);
+        }
+
+        /*
+         * @see Control#addFocusListener(FocusListener)
+         */
+        public void addFocusListener(FocusListener listener) {
+            super.addFocusListener(listener);
+            addListener(FocusListener.class, listener);
+        }
+
+        /*
+         * @see Control#addHelpListener(HelpListener)
+         */
+        public void addHelpListener(HelpListener listener) {
+            super.addHelpListener(listener);
+            addListener(HelpListener.class, listener);
+        }
+
+        /*
+         * @see Control#addKeyListener(KeyListener)
+         */
+        public void addKeyListener(KeyListener listener) {
+            super.addKeyListener(listener);
+            addListener(KeyListener.class, listener);
+        }
+
+        /*
+         * @see Control#addMouseListener(MouseListener)
+         */
+        public void addMouseListener(MouseListener listener) {
+            super.addMouseListener(listener);
+            addListener(MouseListener.class, listener);
+        }
+
+        /*
+         * @see Control#addMouseMoveListener(MouseMoveListener)
+         */
+        public void addMouseMoveListener(MouseMoveListener listener) {
+            super.addMouseMoveListener(listener);
+            addListener(MouseMoveListener.class, listener);
+        }
+
+        /*
+         * @see Control#addMouseTrackListener(MouseTrackListener)
+         */
+        public void addMouseTrackListener(MouseTrackListener listener) {
+            super.addMouseTrackListener(listener);
+            addListener(MouseTrackListener.class, listener);
+        }
+
+        /*
+         * @seeControl#addPaintListener(PaintListener)
+         */
+        public void addPaintListener(PaintListener listener) {
+            super.addPaintListener(listener);
+            addListener(PaintListener.class, listener);
+        }
+
+        /*
+         * @see Control#addTraverseListener(TraverseListener)
+         */
+        public void addTraverseListener(TraverseListener listener) {
+            super.addTraverseListener(listener);
+            addListener(TraverseListener.class, listener);
+        }
+
+        /*
+         * @see Widget#addDisposeListener(DisposeListener)
+         */
+        public void addDisposeListener(DisposeListener listener) {
+            super.addDisposeListener(listener);
+            addListener(DisposeListener.class, listener);
+        }
+    }
+
+    /** The ruler's viewer */
+    private ITextViewer fTextViewer;
+    /** The ruler's canvas to which to add the ruler columns */
+    private CompositeRulerCanvas fComposite;
+    /** The ruler's annotation model */
+    private IAnnotationModel fModel;
+    /** The list of columns */
+    private List fDecorators= new ArrayList(2);
+    /** The cached location of the last mouse button activity */
+    private Point fLocation= new Point(-1, -1);
+    /** The cached line of the list mouse button activity */
+    private int fLastMouseButtonActivityLine= -1;
+    /** The gap between the individual columns of this composite ruler */
+    private int fGap;
+    /**
+     * The set of annotation listeners.
+     * @since 3.0
+     */
+    private Set fAnnotationListeners= new HashSet();
+
+
+    /**
+     * Constructs a new composite vertical ruler.
+     */
+    public CompositeRuler() {
+        this(0);
+    }
+
+    /**
+     * Constructs a new composite ruler with the given gap between its columns.
+     *
+     * @param gap
+     */
+    public CompositeRuler(int gap) {
+        fGap= gap;
+    }
+
+    /**
+     * Inserts the given column at the specified slot to this composite ruler.
+     * Columns are counted from left to right.
+     *
+     * @param index the index
+     * @param rulerColumn the decorator to be inserted
+     */
+    public void addDecorator(int index, IVerticalRulerColumn rulerColumn) {
+        rulerColumn.setModel(getModel());
+
+        if (index > fDecorators.size())
+            fDecorators.add(rulerColumn);
+        else
+            fDecorators.add(index, rulerColumn);
+
+        if (fComposite !is null && !fComposite.isDisposed()) {
+            rulerColumn.createControl(this, fComposite);
+            fComposite.childAdded(rulerColumn.getControl());
+            layoutTextViewer();
+        }
+    }
+
+    /**
+     * Removes the decorator in the specified slot from this composite ruler.
+     *
+     * @param index the index
+     */
+    public void removeDecorator(int index) {
+        IVerticalRulerColumn rulerColumn= (IVerticalRulerColumn) fDecorators.get(index);
+        removeDecorator(rulerColumn);
+    }
+
+    /**
+     * Removes the given decorator from the composite ruler.
+     *
+     * @param rulerColumn the ruler column to be removed
+     * @since 3.0
+     */
+    public void removeDecorator(IVerticalRulerColumn rulerColumn) {
+        fDecorators.remove(rulerColumn);
+        if (rulerColumn !is null) {
+            Control cc= rulerColumn.getControl();
+            if (cc !is null && !cc.isDisposed()) {
+                fComposite.childRemoved(cc);
+                cc.dispose();
+            }
+        }
+        layoutTextViewer();
+    }
+
+    /**
+     * Layouts the text viewer. This also causes this ruler to get
+     * be layouted.
+     */
+    private void layoutTextViewer() {
+
+        Control parent= fTextViewer.getTextWidget();
+
+        if (fTextViewer instanceof ITextViewerExtension) {
+            ITextViewerExtension extension= (ITextViewerExtension) fTextViewer;
+            parent= extension.getControl();
+        }
+
+        if (parent instanceof Composite && !parent.isDisposed())
+            ((Composite) parent).layout(true);
+    }
+
+    /*
+     * @see IVerticalRuler#getControl()
+     */
+    public Control getControl() {
+        return fComposite;
+    }
+
+    /*
+     * @see IVerticalRuler#createControl(Composite, ITextViewer)
+     */
+    public Control createControl(Composite parent, ITextViewer textViewer) {
+
+        fTextViewer= textViewer;
+
+        fComposite= new CompositeRulerCanvas(parent, DWT.NONE);
+        fComposite.setLayout(new RulerLayout());
+
+        Iterator iter= fDecorators.iterator();
+        while (iter.hasNext()) {
+            IVerticalRulerColumn column= (IVerticalRulerColumn) iter.next();
+            column.createControl(this, fComposite);
+            fComposite.childAdded(column.getControl());
+        }
+
+        return fComposite;
+    }
+
+    /*
+     * @see IVerticalRuler#setModel(IAnnotationModel)
+     */
+    public void setModel(IAnnotationModel model) {
+
+        fModel= model;
+
+        Iterator e= fDecorators.iterator();
+        while (e.hasNext()) {
+            IVerticalRulerColumn column= (IVerticalRulerColumn) e.next();
+            column.setModel(model);
+        }
+    }
+
+    /*
+     * @see IVerticalRuler#getModel()
+     */
+    public IAnnotationModel getModel() {
+        return fModel;
+    }
+
+    /*
+     * @see IVerticalRuler#update()
+     */
+    public void update() {
+        if (fComposite !is null && !fComposite.isDisposed()) {
+            Display d= fComposite.getDisplay();
+            if (d !is null) {
+                d.asyncExec(new Runnable() {
+                    public void run() {
+                        immediateUpdate();
+                    }
+                });
+            }
+        }
+    }
+    
+    /**
+     * Immediately redraws the entire ruler (without asynchronous posting).
+     * 
+     * @since 3.2
+     */
+    public void immediateUpdate() {
+        Iterator e= fDecorators.iterator();
+        while (e.hasNext()) {
+            IVerticalRulerColumn column= (IVerticalRulerColumn) e.next();
+            column.redraw();
+        }
+    }
+
+    /*
+     * @see IVerticalRulerExtension#setFont(Font)
+     */
+    public void setFont(Font font) {
+        Iterator e= fDecorators.iterator();
+        while (e.hasNext()) {
+            IVerticalRulerColumn column= (IVerticalRulerColumn) e.next();
+            column.setFont(font);
+        }
+    }
+
+    /*
+     * @see IVerticalRulerInfo#getWidth()
+     */
+    public int getWidth() {
+        int width= 0;
+        Iterator e= fDecorators.iterator();
+        while (e.hasNext()) {
+            IVerticalRulerColumn column= (IVerticalRulerColumn) e.next();
+            width += (column.getWidth() + fGap);
+        }
+        return Math.max(0, width - fGap);
+    }
+
+    /*
+     * @see IVerticalRulerInfo#getLineOfLastMouseButtonActivity()
+     */
+    public int getLineOfLastMouseButtonActivity() {
+        if (fLastMouseButtonActivityLine is -1)
+            fLastMouseButtonActivityLine= toDocumentLineNumber(fLocation.y);
+        else if (fTextViewer.getDocument() is null || fLastMouseButtonActivityLine >= fTextViewer.getDocument().getNumberOfLines())
+            fLastMouseButtonActivityLine= -1;
+        return fLastMouseButtonActivityLine;
+    }
+
+    /*
+     * @see IVerticalRulerInfo#toDocumentLineNumber(int)
+     */
+    public int toDocumentLineNumber(int y_coordinate) {
+        if (fTextViewer is null || y_coordinate is -1)
+            return -1;
+
+        StyledText text= fTextViewer.getTextWidget();
+        int line= text.getLineIndex(y_coordinate);
+        
+        if (line is text.getLineCount() - 1) {
+            // check whether y_coordinate exceeds last line
+            if (y_coordinate > text.getLinePixel(line + 1))
+                return -1;
+        }
+        
+        return widgetLine2ModelLine(fTextViewer, line);
+    }
+
+    /**
+     * Returns the line in the given viewer's document that correspond to the given
+     * line of the viewer's widget.
+     *
+     * @param viewer the viewer
+     * @param widgetLine the widget line
+     * @return the corresponding line the viewer's document
+     * @since 2.1
+     */
+    protected final static int widgetLine2ModelLine(ITextViewer viewer, int widgetLine) {
+
+        if (viewer instanceof ITextViewerExtension5) {
+            ITextViewerExtension5 extension= (ITextViewerExtension5) viewer;
+            return extension.widgetLine2ModelLine(widgetLine);
+        }
+
+        try {
+            IRegion r= viewer.getVisibleRegion();
+            IDocument d= viewer.getDocument();
+            return widgetLine += d.getLineOfOffset(r.getOffset());
+        } catch (BadLocationException x) {
+        }
+        return widgetLine;
+    }
+
+    /**
+     * Returns this ruler's text viewer.
+     *
+     * @return this ruler's text viewer
+     */
+    public ITextViewer getTextViewer() {
+        return fTextViewer;
+    }
+
+    /*
+     * @see IVerticalRulerExtension#setLocationOfLastMouseButtonActivity(int, int)
+     */
+    public void setLocationOfLastMouseButtonActivity(int x, int y) {
+        fLocation.x= x;
+        fLocation.y= y;
+        fLastMouseButtonActivityLine= -1;
+    }
+
+    /**
+     * Returns an iterator over the <code>IVerticalRulerColumns</code> that make up this
+     * composite column.
+     *
+     * @return an iterator over the contained columns.
+     * @since 3.0
+     */
+    public Iterator getDecoratorIterator() {
+        Assert.isNotNull(fDecorators, "fDecorators must be initialized"); //$NON-NLS-1$
+        return fDecorators.iterator();
+    }
+
+    /*
+     * @see dwtx.jface.text.source.IVerticalRulerInfoExtension#getHover()
+     * @since 3.0
+     */
+    public IAnnotationHover getHover() {
+        return null;
+    }
+
+    /*
+     * @see dwtx.jface.text.source.IVerticalRulerInfoExtension#addVerticalRulerListener(dwtx.jface.text.source.IVerticalRulerListener)
+     * @since 3.0
+     */
+    public void addVerticalRulerListener(IVerticalRulerListener listener) {
+        fAnnotationListeners.add(listener);
+    }
+
+    /*
+     * @see dwtx.jface.text.source.IVerticalRulerInfoExtension#removeVerticalRulerListener(dwtx.jface.text.source.IVerticalRulerListener)
+     * @since 3.0
+     */
+    public void removeVerticalRulerListener(IVerticalRulerListener listener) {
+        fAnnotationListeners.remove(listener);
+    }
+
+    /**
+     * Fires the annotation selected event to all registered vertical ruler
+     * listeners.
+     * TODO use robust iterators
+     *
+     * @param event the event to fire
+     * @since 3.0
+     */
+    public void fireAnnotationSelected(VerticalRulerEvent event) {
+        // forward to listeners
+        for (Iterator it= fAnnotationListeners.iterator(); it.hasNext();) {
+            IVerticalRulerListener listener= (IVerticalRulerListener) it.next();
+            listener.annotationSelected(event);
+        }
+    }
+
+    /**
+     * Fires the annotation default selected event to all registered vertical
+     * ruler listeners.
+     * TODO use robust iterators
+     *
+     * @param event the event to fire
+     * @since 3.0
+     */
+    public void fireAnnotationDefaultSelected(VerticalRulerEvent event) {
+        // forward to listeners
+        for (Iterator it= fAnnotationListeners.iterator(); it.hasNext();) {
+            IVerticalRulerListener listener= (IVerticalRulerListener) it.next();
+            listener.annotationDefaultSelected(event);
+        }
+    }
+
+    /**
+     * Informs all registered vertical ruler listeners that the content menu on a selected annotation\
+     * is about to be shown.
+     * TODO use robust iterators
+     *
+     * @param event the event to fire
+     * @param menu the menu that is about to be shown
+     * @since 3.0
+     */
+    public void fireAnnotationContextMenuAboutToShow(VerticalRulerEvent event, Menu menu) {
+        // forward to listeners
+        for (Iterator it= fAnnotationListeners.iterator(); it.hasNext();) {
+            IVerticalRulerListener listener= (IVerticalRulerListener) it.next();
+            listener.annotationContextMenuAboutToShow(event, menu);
+        }
+    }
+
+    /**
+     * Relayouts the receiver.
+     *
+     * @since 3.3
+     */
+    public void relayout() {
+        layoutTextViewer();
+    }
+}