diff org.eclipse.ui.forms/src/org/eclipse/ui/internal/forms/widgets/FormUtil.d @ 12:bc29606a740c

Added dwt-addons in original directory structure of eclipse.org
author Frank Benoit <benoit@tionex.de>
date Sat, 14 Mar 2009 18:23:29 +0100
parents
children dbfb303e8fb0
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.ui.forms/src/org/eclipse/ui/internal/forms/widgets/FormUtil.d	Sat Mar 14 18:23:29 2009 +0100
@@ -0,0 +1,532 @@
+/*******************************************************************************
+ * 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
+ *     Chriss Gross (schtoo@schtoo.com) - fix for 61670
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.ui.internal.forms.widgets.FormUtil;
+
+
+// import com.ibm.icu.text.BreakIterator;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.widgets.ColumnLayout;
+import org.eclipse.ui.forms.widgets.Form;
+import org.eclipse.ui.forms.widgets.FormText;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.ILayoutExtension;
+
+import java.lang.all;
+import java.util.Set;
+
+import  org.eclipse.dwtxhelper.mangoicu.UBreakIterator;
+
+public class FormUtil {
+
+    public static const String PLUGIN_ID = "org.eclipse.ui.forms"; //$NON-NLS-1$
+
+    static const int H_SCROLL_INCREMENT = 5;
+
+    static const int V_SCROLL_INCREMENT = 64;
+
+    public static const String DEBUG = PLUGIN_ID ~ "/debug"; //$NON-NLS-1$
+
+    public static const String DEBUG_TEXT = DEBUG ~ "/text"; //$NON-NLS-1$
+    public static const String DEBUG_TEXTSIZE = DEBUG ~ "/textsize"; //$NON-NLS-1$
+
+    public static const String DEBUG_FOCUS = DEBUG ~ "/focus"; //$NON-NLS-1$
+
+    public static const String FOCUS_SCROLLING = "focusScrolling"; //$NON-NLS-1$
+
+    public static const String IGNORE_BODY = "__ignore_body__"; //$NON-NLS-1$
+
+    public static Text createText(Composite parent, String label,
+            FormToolkit factory) {
+        return createText(parent, label, factory, 1);
+    }
+
+    public static Text createText(Composite parent, String label,
+            FormToolkit factory, int span) {
+        factory.createLabel(parent, label);
+        Text text = factory.createText(parent, ""); //$NON-NLS-1$
+        int hfill = span is 1 ? GridData.FILL_HORIZONTAL
+                : GridData.HORIZONTAL_ALIGN_FILL;
+        GridData gd = new GridData(hfill | GridData.VERTICAL_ALIGN_CENTER);
+        gd.horizontalSpan = span;
+        text.setLayoutData(gd);
+        return text;
+    }
+
+    public static Text createText(Composite parent, String label,
+            FormToolkit factory, int span, int style) {
+        Label l = factory.createLabel(parent, label);
+        if ((style & SWT.MULTI) !is 0) {
+            GridData gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
+            l.setLayoutData(gd);
+        }
+        Text text = factory.createText(parent, "", style); //$NON-NLS-1$
+        int hfill = span is 1 ? GridData.FILL_HORIZONTAL
+                : GridData.HORIZONTAL_ALIGN_FILL;
+        GridData gd = new GridData(hfill | GridData.VERTICAL_ALIGN_CENTER);
+        gd.horizontalSpan = span;
+        text.setLayoutData(gd);
+        return text;
+    }
+
+    public static Text createText(Composite parent, FormToolkit factory,
+            int span) {
+        Text text = factory.createText(parent, ""); //$NON-NLS-1$
+        int hfill = span is 1 ? GridData.FILL_HORIZONTAL
+                : GridData.HORIZONTAL_ALIGN_FILL;
+        GridData gd = new GridData(hfill | GridData.VERTICAL_ALIGN_CENTER);
+        gd.horizontalSpan = span;
+        text.setLayoutData(gd);
+        return text;
+    }
+
+    public static int computeMinimumWidth(GC gc, String text) {
+        auto wb =  UBreakIterator.openWordIterator( ULocale.Default, text );
+        scope(exit) wb.close();
+        int last = 0;
+        int width = 0;
+
+        for (int loc = wb.first(); loc !is UBreakIterator.Done; loc = wb.next()) {
+            String word = text.substring(last, loc);
+            Point extent = gc.textExtent(word);
+            width = Math.max(width, extent.x);
+            last = loc;
+        }
+        String lastWord = text.substring(last);
+        Point extent = gc.textExtent(lastWord);
+        width = Math.max(width, extent.x);
+        return width;
+    }
+
+    public static Point computeWrapSize(GC gc, String text, int wHint) {
+        auto wb =  UBreakIterator.openWordIterator( ULocale.Default, text );
+        scope(exit) wb.close();
+        FontMetrics fm = gc.getFontMetrics();
+        int lineHeight = fm.getHeight();
+
+        int saved = 0;
+        int last = 0;
+        int height = lineHeight;
+        int maxWidth = 0;
+        for (int loc = wb.first(); loc !is UBreakIterator.Done; loc = wb.next()) {
+            String word = text.substring(saved, loc);
+            Point extent = gc.textExtent(word);
+            if (extent.x > wHint) {
+                // overflow
+                saved = last;
+                height += extent.y;
+                // switch to current word so maxWidth will accommodate very long single words
+                word = text.substring(last, loc);
+                extent = gc.textExtent(word);
+            }
+            maxWidth = Math.max(maxWidth, extent.x);
+            last = loc;
+        }
+        /*
+         * Correct the height attribute in case it was calculated wrong due to wHint being less than maxWidth.
+         * The recursive call proved to be the only thing that worked in all cases. Some attempts can be made
+         * to estimate the height, but the algorithm needs to be run again to be sure.
+         */
+        if (maxWidth > wHint)
+            return computeWrapSize(gc, text, maxWidth);
+        return new Point(maxWidth, height);
+    }
+
+    public static void paintWrapText(GC gc, String text, Rectangle bounds) {
+        paintWrapText(gc, text, bounds, false);
+    }
+
+    public static void paintWrapText(GC gc, String text, Rectangle bounds,
+            bool underline) {
+        auto wb =  UBreakIterator.openWordIterator( ULocale.Default, text );
+        scope(exit) wb.close();
+        FontMetrics fm = gc.getFontMetrics();
+        int lineHeight = fm.getHeight();
+        int descent = fm.getDescent();
+
+        int saved = 0;
+        int last = 0;
+        int y = bounds.y;
+        int width = bounds.width;
+
+        for (int loc = wb.first(); loc !is UBreakIterator.Done; loc = wb.next()) {
+            String line = text.substring(saved, loc);
+            Point extent = gc.textExtent(line);
+
+            if (extent.x > width) {
+                // overflow
+                String prevLine = text.substring(saved, last);
+                gc.drawText(prevLine, bounds.x, y, true);
+                if (underline) {
+                    Point prevExtent = gc.textExtent(prevLine);
+                    int lineY = y + lineHeight - descent + 1;
+                    gc
+                            .drawLine(bounds.x, lineY, bounds.x + prevExtent.x,
+                                    lineY);
+                }
+
+                saved = last;
+                y += lineHeight;
+            }
+            last = loc;
+        }
+        // paint the last line
+        String lastLine = text.substring(saved, last);
+        gc.drawText(lastLine, bounds.x, y, true);
+        if (underline) {
+            int lineY = y + lineHeight - descent + 1;
+            Point lastExtent = gc.textExtent(lastLine);
+            gc.drawLine(bounds.x, lineY, bounds.x + lastExtent.x, lineY);
+        }
+    }
+
+    public static ScrolledComposite getScrolledComposite(Control c) {
+        Composite parent = c.getParent();
+
+        while (parent !is null) {
+            if ( auto sc = cast(ScrolledComposite)parent ) {
+                return sc;
+            }
+            parent = parent.getParent();
+        }
+        return null;
+    }
+
+    public static void ensureVisible(Control c) {
+        ScrolledComposite scomp = getScrolledComposite(c);
+        if (scomp !is null) {
+            Object data = scomp.getData(FOCUS_SCROLLING);
+            if (data is null || !data.opEquals(Boolean.FALSE))
+                FormUtil.ensureVisible(scomp, c);
+        }
+    }
+
+    public static void ensureVisible(ScrolledComposite scomp, Control control) {
+        // if the control is a FormText we do not need to scroll since it will
+        // ensure visibility of its segments as necessary
+        if ( auto ft = cast(FormText)control )
+            return;
+        Point controlSize = control.getSize();
+        Point controlOrigin = getControlLocation(scomp, control);
+        ensureVisible(scomp, controlOrigin, controlSize);
+    }
+
+    public static void ensureVisible(ScrolledComposite scomp,
+            Point controlOrigin, Point controlSize) {
+        Rectangle area = scomp.getClientArea();
+        Point scompOrigin = scomp.getOrigin();
+
+        int x = scompOrigin.x;
+        int y = scompOrigin.y;
+
+        // horizontal right, but only if the control is smaller
+        // than the client area
+        if (controlSize.x < area.width
+                && (controlOrigin.x + controlSize.x > scompOrigin.x
+                        + area.width)) {
+            x = controlOrigin.x + controlSize.x - area.width;
+        }
+        // horizontal left - make sure the left edge of
+        // the control is showing
+        if (controlOrigin.x < x) {
+            if (controlSize.x < area.width)
+                x = controlOrigin.x + controlSize.x - area.width;
+            else
+                x = controlOrigin.x;
+        }
+        // vertical bottom
+        if (controlSize.y < area.height
+                && (controlOrigin.y + controlSize.y > scompOrigin.y
+                        + area.height)) {
+            y = controlOrigin.y + controlSize.y - area.height;
+        }
+        // vertical top - make sure the top of
+        // the control is showing
+        if (controlOrigin.y < y) {
+            if (controlSize.y < area.height)
+                y = controlOrigin.y + controlSize.y - area.height;
+            else
+                y = controlOrigin.y;
+        }
+
+        if (scompOrigin.x !is x || scompOrigin.y !is y) {
+            // scroll to reveal
+            scomp.setOrigin(x, y);
+        }
+    }
+
+    public static void ensureVisible(ScrolledComposite scomp, Control control,
+            MouseEvent e) {
+        Point controlOrigin = getControlLocation(scomp, control);
+        int rX = controlOrigin.x + e.x;
+        int rY = controlOrigin.y + e.y;
+        Rectangle area = scomp.getClientArea();
+        Point scompOrigin = scomp.getOrigin();
+
+        int x = scompOrigin.x;
+        int y = scompOrigin.y;
+        // System.out.println("Ensure: area="+area+", origin="+scompOrigin+",
+        // cloc="+controlOrigin+", csize="+controlSize+", x="+x+", y="+y);
+
+        // horizontal right
+        if (rX > scompOrigin.x + area.width) {
+            x = rX - area.width;
+        }
+        // horizontal left
+        else if (rX < x) {
+            x = rX;
+        }
+        // vertical bottom
+        if (rY > scompOrigin.y + area.height) {
+            y = rY - area.height;
+        }
+        // vertical top
+        else if (rY < y) {
+            y = rY;
+        }
+
+        if (scompOrigin.x !is x || scompOrigin.y !is y) {
+            // scroll to reveal
+            scomp.setOrigin(x, y);
+        }
+    }
+
+    public static Point getControlLocation(ScrolledComposite scomp,
+            Control control) {
+        int x = 0;
+        int y = 0;
+        Control content = scomp.getContent();
+        Control currentControl = control;
+        for (;;) {
+            if (currentControl is content)
+                break;
+            Point location = currentControl.getLocation();
+            // if (location.x > 0)
+            // x += location.x;
+            // if (location.y > 0)
+            // y += location.y;
+            x += location.x;
+            y += location.y;
+            currentControl = currentControl.getParent();
+        }
+        return new Point(x, y);
+    }
+
+    static void scrollVertical(ScrolledComposite scomp, bool up) {
+        scroll(scomp, 0, up ? -V_SCROLL_INCREMENT : V_SCROLL_INCREMENT);
+    }
+
+    static void scrollHorizontal(ScrolledComposite scomp, bool left) {
+        scroll(scomp, left ? -H_SCROLL_INCREMENT : H_SCROLL_INCREMENT, 0);
+    }
+
+    static void scrollPage(ScrolledComposite scomp, bool up) {
+        Rectangle clientArea = scomp.getClientArea();
+        int increment = up ? -clientArea.height : clientArea.height;
+        scroll(scomp, 0, increment);
+    }
+
+    static void scroll(ScrolledComposite scomp, int xoffset, int yoffset) {
+        Point origin = scomp.getOrigin();
+        Point contentSize = scomp.getContent().getSize();
+        int xorigin = origin.x + xoffset;
+        int yorigin = origin.y + yoffset;
+        xorigin = Math.max(xorigin, 0);
+        xorigin = Math.min(xorigin, contentSize.x - 1);
+        yorigin = Math.max(yorigin, 0);
+        yorigin = Math.min(yorigin, contentSize.y - 1);
+        scomp.setOrigin(xorigin, yorigin);
+    }
+
+    public static void updatePageIncrement(ScrolledComposite scomp) {
+        ScrollBar vbar = scomp.getVerticalBar();
+        if (vbar !is null) {
+            Rectangle clientArea = scomp.getClientArea();
+            int increment = clientArea.height - 5;
+            vbar.setPageIncrement(increment);
+        }
+        ScrollBar hbar = scomp.getHorizontalBar();
+        if (hbar !is null) {
+            Rectangle clientArea = scomp.getClientArea();
+            int increment = clientArea.width - 5;
+            hbar.setPageIncrement(increment);
+        }
+    }
+
+    public static void processKey(int keyCode, Control c) {
+        ScrolledComposite scomp = FormUtil.getScrolledComposite(c);
+        if (scomp !is null) {
+            if (null !is cast(Combo)c )
+                return;
+            switch (keyCode) {
+            case SWT.ARROW_DOWN:
+                if (scomp.getData("novarrows") is null) //$NON-NLS-1$
+                    FormUtil.scrollVertical(scomp, false);
+                break;
+            case SWT.ARROW_UP:
+                if (scomp.getData("novarrows") is null) //$NON-NLS-1$
+                    FormUtil.scrollVertical(scomp, true);
+                break;
+            case SWT.ARROW_LEFT:
+                FormUtil.scrollHorizontal(scomp, true);
+                break;
+            case SWT.ARROW_RIGHT:
+                FormUtil.scrollHorizontal(scomp, false);
+                break;
+            case SWT.PAGE_UP:
+                FormUtil.scrollPage(scomp, true);
+                break;
+            case SWT.PAGE_DOWN:
+                FormUtil.scrollPage(scomp, false);
+                break;
+            default:
+            }
+        }
+    }
+
+    public static bool isWrapControl(Control c) {
+        if ((c.getStyle() & SWT.WRAP) !is 0)
+            return true;
+        if (auto comp = cast(Composite)c ) {
+            return ( null !is cast(ILayoutExtension)( comp.getLayout() ));
+        }
+        return false;
+    }
+
+    public static int getWidthHint(int wHint, Control c) {
+        bool wrap = isWrapControl(c);
+        return wrap ? wHint : SWT.DEFAULT;
+    }
+
+    public static int getHeightHint(int hHint, Control c) {
+        if ( auto comp = cast(Composite)c ) {
+            Layout layout = comp.getLayout();
+            if (null !is cast(ColumnLayout)layout )
+                return hHint;
+        }
+        return SWT.DEFAULT;
+    }
+
+    public static int computeMinimumWidth(Control c, bool changed) {
+        if ( auto comp = cast(Composite)c ) {
+            Layout layout = comp.getLayout();
+            if ( auto le = cast(ILayoutExtension)layout )
+                return le.computeMinimumWidth(
+                        comp, changed);
+        }
+        return c.computeSize(FormUtil.getWidthHint(5, c), SWT.DEFAULT, changed).x;
+    }
+
+    public static int computeMaximumWidth(Control c, bool changed) {
+        if ( auto comp = cast(Composite)c ) {
+            Layout layout = comp.getLayout();
+            if ( auto le = cast(ILayoutExtension)layout )
+                return le.computeMaximumWidth(
+                        comp, changed);
+        }
+        return c.computeSize(SWT.DEFAULT, SWT.DEFAULT, changed).x;
+    }
+
+    public static Form getForm(Control c) {
+        Composite parent = c.getParent();
+        while (parent !is null) {
+            if ( auto frm = cast(Form)parent ) {
+                return frm;
+            }
+            parent = parent.getParent();
+        }
+        return null;
+    }
+
+    public static Image createAlphaMashImage(Device device, Image srcImage) {
+        Rectangle bounds = srcImage.getBounds();
+        int alpha = 0;
+        int calpha = 0;
+        ImageData data = srcImage.getImageData();
+        // Create a new image with alpha values alternating
+        // between fully transparent (0) and fully opaque (255).
+        // This image will show the background through the
+        // transparent pixels.
+        for (int i = 0; i < bounds.height; i++) {
+            // scan line
+            alpha = calpha;
+            for (int j = 0; j < bounds.width; j++) {
+                // column
+                data.setAlpha(j, i, alpha);
+                alpha = alpha is 255 ? 0 : 255;
+            }
+            calpha = calpha is 255 ? 0 : 255;
+        }
+        return new Image(device, data);
+    }
+
+    public static bool mnemonicMatch(String text, dchar key) {
+        char mnemonic = findMnemonic(text);
+        if (mnemonic is '\0')
+            return false;
+        return CharacterToUpper(key) is CharacterToUpper(mnemonic);
+    }
+
+    private static char findMnemonic(String string) {
+        int index = 0;
+        int length = string.length;
+        do {
+            while (index < length && string.charAt(index) !is '&')
+                index++;
+            if (++index >= length)
+                return '\0';
+            if (string.charAt(index) !is '&')
+                return string.charAt(index);
+            index++;
+        } while (index < length);
+        return '\0';
+    }
+
+    public static void setFocusScrollingEnabled(Control c, bool enabled) {
+        ScrolledComposite scomp = null;
+
+        if ( auto sc = cast(ScrolledComposite)c )
+            scomp = sc;
+        else
+            scomp = getScrolledComposite(c);
+        if (scomp !is null)
+            scomp.setData(FormUtil.FOCUS_SCROLLING, enabled ? null : Boolean.FALSE);
+    }
+
+    public static void setAntialias(GC gc, int style) {
+        if (!gc.getAdvanced()) {
+            gc.setAdvanced(true);
+            if (!gc.getAdvanced())
+                return;
+        }
+        gc.setAntialias(style);
+    }
+}