diff dwtx/ui/forms/widgets/AbstractHyperlink.d @ 75:5d489b9f966c

Fix continue porting
author Frank Benoit <benoit@tionex.de>
date Sat, 24 May 2008 05:11:16 +0200
parents
children c3583c6ec027
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/ui/forms/widgets/AbstractHyperlink.d	Sat May 24 05:11:16 2008 +0200
@@ -0,0 +1,341 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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.ui.forms.widgets.AbstractHyperlink;
+
+
+import dwt.DWT;
+import dwt.accessibility.ACC;
+import dwt.events.PaintEvent;
+import dwt.events.PaintListener;
+import dwt.graphics.GC;
+import dwt.graphics.Point;
+import dwt.graphics.Rectangle;
+import dwt.widgets.Canvas;
+import dwt.widgets.Composite;
+import dwt.widgets.Event;
+import dwt.widgets.Listener;
+import dwtx.core.runtime.ListenerList;
+import dwtx.ui.forms.events.HyperlinkEvent;
+import dwtx.ui.forms.events.IHyperlinkListener;
+import dwtx.ui.internal.forms.widgets.FormsResources;
+
+import dwt.dwthelper.utils;
+
+/**
+ * This is the base class for custom hyperlink widget. It is responsible for
+ * processing mouse and keyboard events, and converting them into unified
+ * hyperlink events. Subclasses are responsible for rendering the hyperlink in
+ * the client area.
+ *
+ * @since 3.0
+ */
+public abstract class AbstractHyperlink : Canvas {
+    private bool hasFocus;
+    bool paintFocus=true;
+
+    /*
+     * Armed link is one that will activate on a mouse up event, i.e.
+     * it has received a mouse down and mouse still on top of it.
+     */
+    private bool armed;
+
+    private ListenerList listeners;
+
+    /**
+     * Amount of the margin width around the hyperlink (default is 1).
+     */
+    protected int marginWidth = 1;
+
+    /**
+     * Amount of the margin height around the hyperlink (default is 1).
+     */
+    protected int marginHeight = 1;
+
+    /**
+     * Creates a new hyperlink in the provided parent.
+     *
+     * @param parent
+     *            the control parent
+     * @param style
+     *            the widget style
+     */
+    public this(Composite parent, int style) {
+        super(parent, style);
+        addListener(DWT.KeyDown, new class Listener {
+            public void handleEvent(Event e) {
+                if (e.character is '\r') {
+                    handleActivate(e);
+                }
+            }
+        });
+        addPaintListener(new class PaintListener {
+            public void paintControl(PaintEvent e) {
+                paint(e);
+            }
+        });
+        addListener(DWT.Traverse, new class Listener {
+            public void handleEvent(Event e) {
+                switch (e.detail) {
+                case DWT.TRAVERSE_PAGE_NEXT:
+                case DWT.TRAVERSE_PAGE_PREVIOUS:
+                case DWT.TRAVERSE_ARROW_NEXT:
+                case DWT.TRAVERSE_ARROW_PREVIOUS:
+                case DWT.TRAVERSE_RETURN:
+                    e.doit = false;
+                    return;
+                }
+                e.doit = true;
+            }
+        });
+        Listener listener = new class Listener {
+            public void handleEvent(Event e) {
+                switch (e.type) {
+                case DWT.FocusIn:
+                    hasFocus = true;
+                    handleEnter(e);
+                    break;
+                case DWT.FocusOut:
+                    hasFocus = false;
+                    handleExit(e);
+                    break;
+                case DWT.DefaultSelection:
+                    handleActivate(e);
+                    break;
+                case DWT.MouseEnter:
+                    handleEnter(e);
+                    break;
+                case DWT.MouseExit:
+                    handleExit(e);
+                    break;
+                case DWT.MouseDown:
+                    handleMouseDown(e);
+                    break;
+                case DWT.MouseUp:
+                    handleMouseUp(e);
+                    break;
+                case DWT.MouseMove:
+                    handleMouseMove(e);
+                    break;
+                }
+            }
+        };
+        addListener(DWT.MouseEnter, listener);
+        addListener(DWT.MouseExit, listener);
+        addListener(DWT.MouseDown, listener);
+        addListener(DWT.MouseUp, listener);
+        addListener(DWT.MouseMove, listener);
+        addListener(DWT.FocusIn, listener);
+        addListener(DWT.FocusOut, listener);
+        setCursor(FormsResources.getHandCursor());
+    }
+
+    /**
+     * Adds the event listener to this hyperlink.
+     *
+     * @param listener
+     *            the event listener to add
+     */
+    public void addHyperlinkListener(IHyperlinkListener listener) {
+        if (listeners is null)
+            listeners = new ListenerList();
+        listeners.add(cast(Object)listener);
+    }
+
+    /**
+     * Removes the event listener from this hyperlink.
+     *
+     * @param listener
+     *            the event listener to remove
+     */
+    public void removeHyperlinkListener(IHyperlinkListener listener) {
+        if (listeners is null)
+            return;
+        listeners.remove(cast(Object)listener);
+    }
+
+    /**
+     * Returns the selection state of the control. When focus is gained, the
+     * state will be <samp>true </samp>; it will switch to <samp>false </samp>
+     * when the control looses focus.
+     *
+     * @return <code>true</code> if the widget has focus, <code>false</code>
+     *         otherwise.
+     */
+    public bool getSelection() {
+        return hasFocus;
+    }
+
+    /**
+     * Called when hyperlink is entered. Subclasses that override this method
+     * must call 'super'.
+     */
+    protected void handleEnter(Event e) {
+        redraw();
+        if (listeners is null)
+            return;
+        int size = listeners.size();
+        HyperlinkEvent he = new HyperlinkEvent(this, getHref(), getText(),
+                e.stateMask);
+        Object[] listenerList = listeners.getListeners();
+        for (int i = 0; i < size; i++) {
+            IHyperlinkListener listener = cast(IHyperlinkListener) listenerList[i];
+            listener.linkEntered(he);
+        }
+    }
+
+    /**
+     * Called when hyperlink is exited. Subclasses that override this method
+     * must call 'super'.
+     */
+    protected void handleExit(Event e) {
+        // disarm the link; won't activate on mouseup
+        armed = false;
+        redraw();
+        if (listeners is null)
+            return;
+        int size = listeners.size();
+        HyperlinkEvent he = new HyperlinkEvent(this, getHref(), getText(),
+                e.stateMask);
+        Object[] listenerList = listeners.getListeners();
+        for (int i = 0; i < size; i++) {
+            IHyperlinkListener listener = cast(IHyperlinkListener) listenerList[i];
+            listener.linkExited(he);
+        }
+    }
+
+    /**
+     * Called when hyperlink has been activated. Subclasses that override this
+     * method must call 'super'.
+     */
+    protected void handleActivate(Event e) {
+        // disarm link, back to normal state
+        armed = false;
+        getAccessible().setFocus(ACC.CHILDID_SELF);
+        if (listeners is null)
+            return;
+        int size = listeners.size();
+        setCursor(FormsResources.getBusyCursor());
+        HyperlinkEvent he = new HyperlinkEvent(this, getHref(), getText(),
+                e.stateMask);
+        Object[] listenerList = listeners.getListeners();
+        for (int i = 0; i < size; i++) {
+            IHyperlinkListener listener = cast(IHyperlinkListener) listenerList[i];
+            listener.linkActivated(he);
+        }
+        if (!isDisposed())
+            setCursor(FormsResources.getHandCursor());
+    }
+
+    /**
+     * Sets the object associated with this hyperlink. Concrete implementation
+     * of this class can use if to store text, URLs or model objects that need
+     * to be processed on hyperlink events.
+     *
+     * @param href
+     *            the hyperlink object reference
+     */
+    public void setHref(Object href) {
+        setData("href", href); //$NON-NLS-1$
+    }
+
+    /**
+     * Returns the object associated with this hyperlink.
+     *
+     * @see #setHref
+     * @return the hyperlink object reference
+     */
+    public Object getHref() {
+        return getData("href"); //$NON-NLS-1$
+    }
+
+    /**
+     * Returns the textual representation of this hyperlink suitable for showing
+     * in tool tips or on the status line.
+     *
+     * @return the hyperlink text
+     */
+    public String getText() {
+        return getToolTipText();
+    }
+
+    /**
+     * Paints the hyperlink as a reaction to the provided paint event.
+     *
+     * @param gc
+     *            graphic context
+     */
+    protected abstract void paintHyperlink(GC gc);
+
+    /**
+     * Paints the control as a reaction to the provided paint event.
+     *
+     * @param e
+     *            the paint event
+     */
+    protected void paint(PaintEvent e) {
+        GC gc = e.gc;
+        Rectangle clientArea = getClientArea();
+        if (clientArea.width is 0 || clientArea.height is 0)
+            return;
+        paintHyperlink(gc);
+        if (paintFocus && hasFocus) {
+            Rectangle carea = getClientArea();
+            gc.setForeground(getForeground());
+            gc.drawFocus(0, 0, carea.width, carea.height);
+        }
+    }
+
+    private void handleMouseDown(Event e) {
+        if (e.button !is 1)
+            return;
+        // armed and ready to activate on mouseup
+        armed = true;
+    }
+
+    private void handleMouseUp(Event e) {
+        if (!armed || e.button !is 1)
+            return;
+        Point size = getSize();
+        // Filter out mouse up events outside
+        // the link. This can happen when mouse is
+        // clicked, dragged outside the link, then
+        // released.
+        if (e.x < 0)
+            return;
+        if (e.y < 0)
+            return;
+        if (e.x >= size.x)
+            return;
+        if (e.y >= size.y)
+            return;
+        handleActivate(e);
+    }
+
+    private void handleMouseMove(Event e) {
+        // disarm link if we move out of bounds
+        if (armed) {
+            Point size = getSize();
+            armed = (e.x >= 0 && e.y >= 0 && e.x < size.x && e.y < size.y);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see dwt.widgets.Control#setEnabled(bool)
+     */
+
+    public void setEnabled (bool enabled) {
+        super.setEnabled(enabled);
+        redraw();
+    }
+}