de.xirp.ui.util.SWTUtil.java Source code

Java tutorial

Introduction

Here is the source code for de.xirp.ui.util.SWTUtil.java

Source

/** 
 * ============================================================================
 * Xirp 2: eXtendable interface for robotic purposes.
 * ============================================================================
 * 
 * Copyright (C) 2005-2007, by Authors and Contributors listed in CREDITS.txt
 * 
 * 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.opensource.org/licenses/cpl1.0.php
 *
 * ----------------------------
 * SWTUtil.java
 * ----------------------------
 *
 * Original Author:  Matthias Gernand [matthias.gernand AT gmx.de]
 * Contributor(s):   Rabea Gransberger [rgransberger AT web.de]
 *
 * Changes
 * -------
 * 23.01.2006:      Created by Matthias Gernand.
 */
package de.xirp.ui.util;

import java.io.File;
import java.io.IOException;

import javolution.lang.MathLib;

import org.apache.commons.io.FilenameUtils;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Resource;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Widget;

import de.xirp.ui.Application;
import de.xirp.util.DoublePoint;
import de.xirp.util.I18n;

/**
 * Contains frequently used UI-methods, all accessed statically.<br>
 * 
 * @author Matthias Gernand
 * @author Rabea Gransberger
 */
public final class SWTUtil {

    /**
     * SWT allows the GUI thread to access SWT widgets only.<br>
     * If another thread tries to access a widget an "invalid thread
     * access exception" is thrown.<br>
     * <br>
     * In order to allow access to SWT widgets from other threads to
     * the GUI thread this method may be used.<br>
     * <br>
     * The {@link Runnable} contains the code to execute in his
     * <code>run</code>-Method.<br>
     * <br>
     * There is only <b>ONE</b> GUI thread, so remember to put only
     * minimized code and no expensive calculations into the
     * {@link Runnable} because otherwise the GUI will be blocked to
     * long.<br>
     * <br>
     * This method returns immediately not waiting for the given
     * {@link Runnable} to be executed.
     * 
     * @param runnable
     *            Runnable containing the Code to execute in the GUI
     *            thread
     * @see Display#asyncExec(Runnable)
     */
    public static final void asyncExec(final Runnable runnable) {
        Display display = Application.getApplication().getDisplay();
        if (SWTUtil.swtAssert(display)) {
            display.asyncExec(runnable);
        }
    }

    /**
     * SWT allows the GUI thread to access SWT widgets only.<br>
     * If another thread tries to access a widget an "invalid thread
     * access exception" is thrown.<br>
     * <br>
     * In order to allow access to SWT widgets from other threads to
     * the GUI thread this method may be used.<br>
     * <br>
     * The {@link Runnable} contains the code to execute in his
     * <code>run</code>-Method.<br>
     * <br>
     * There is only <b>ONE</b> GUI thread, so remember to put only
     * minimized code and no expensive calculations into the
     * {@link Runnable} because otherwise the GUI will be blocked to
     * long.<br>
     * <br>
     * This method returns when the given {@link Runnable} was
     * executed.
     * 
     * @param runnable
     *            Runnable containing the code to execute in the GUI
     *            thread
     * @see Display#syncExec(Runnable)
     */
    public static final void syncExec(final Runnable runnable) {
        Display display = Application.getApplication().getDisplay();
        if (SWTUtil.swtAssert(display)) {
            display.syncExec(runnable);
        }
    }

    /**
     * Centers the given dialog shell on the screen.
     * 
     * @param dialogShell
     *            Shell of the dialog to center
     */
    public static final void centerDialog(final Shell dialogShell) {

        Rectangle shellBounds = dialogShell.getParent().getBounds();
        Point dialogSize = dialogShell.getSize();

        dialogShell.setLocation((shellBounds.x + (shellBounds.width - dialogSize.x) / 2),
                (shellBounds.y + (shellBounds.height - dialogSize.y) / 2));
    }

    /**
     * Convenience method for adding a grid layout to a component.<br>
     * 
     * @param toLayout
     *            the Composite to add the layout to
     * @param numColumns
     *            number of columns for the grid layout
     * @param makeColumnsEqualWidth
     *            <code>true</code> if all the columns of the layout
     *            should have equal width (use <code>true</code> if
     *            there is only one column)
     * @return The layout which was added to the component
     * @see org.eclipse.swt.layout.GridLayout
     */
    public static final GridLayout setGridLayout(final Composite toLayout, final int numColumns,
            final boolean makeColumnsEqualWidth) {

        GridLayout gl = new GridLayout();
        gl.numColumns = numColumns;
        gl.makeColumnsEqualWidth = makeColumnsEqualWidth;
        toLayout.setLayout(gl);

        return gl;
    }

    /**
     * Sets the margins of the given layout to <code>0</code>.
     * 
     * @param layout
     *            the layout
     */
    public static final void resetMargins(GridLayout layout) {
        layout.marginHeight = 0;
        layout.marginWidth = 0;
    }

    /**
     * Sets the spacings of the given layout to <code>0</code>.
     * 
     * @param layout
     *            the layout
     */
    public static final void resetSpacings(GridLayout layout) {
        layout.horizontalSpacing = 0;
        layout.verticalSpacing = 0;
    }

    /**
     * Sets the grid data for a component which parent has a grid
     * layout.<br>
     * 
     * @param addLayoutDataTo
     *            the control to add the data to
     * @param grabExcessHorizontalSpace
     *            grabExcessHorizontalSpace specifies whether the
     *            width of the cell changes depending on the size of
     *            the parent Composite
     * @param grabExcessVerticalSpace
     *            grabExcessVerticalSpace specifies whether the height
     *            of the cell changes depending on the size of the
     *            parent Composite
     * @param horizontalAlignment
     *            horizontalAlignment specifies how controls will be
     *            positioned horizontally within a cell.
     * @param verticalAlignment
     *            verticalAlignment specifies how controls will be
     *            positioned vertically within a cell.
     * @param horizontalSpan
     *            horizontalSpan specifies the number of column cells
     *            that the control will take up.
     * @param verticalSpan
     *            verticalSpan specifies the number of row cells that
     *            the control will take up.
     * @return GirdData<br>
     *         The grid data which was added to the control
     * @see org.eclipse.swt.layout.GridData
     */
    public static final GridData setGridData(final Control addLayoutDataTo, final boolean grabExcessHorizontalSpace,
            final boolean grabExcessVerticalSpace, final int horizontalAlignment, final int verticalAlignment,
            final int horizontalSpan, final int verticalSpan) {

        GridData gd = new GridData();
        gd.grabExcessHorizontalSpace = grabExcessHorizontalSpace;
        gd.grabExcessVerticalSpace = grabExcessVerticalSpace;
        gd.horizontalAlignment = horizontalAlignment;
        gd.verticalAlignment = verticalAlignment;
        gd.horizontalSpan = horizontalSpan;
        gd.verticalSpan = verticalSpan;
        addLayoutDataTo.setLayoutData(gd);

        return gd;
    }

    /**
     * Converts the given Point which is relative to the first Control
     * to a Point relative to the second control.<br>
     * 
     * @param x
     *            X Coordinate of the Point to convert
     * @param y
     *            Y Coordinate of the Point to convert
     * @param from
     *            Control to which the Point coordinates are relative
     * @param to
     *            Control to which the Point coordinates should be
     *            relative after conversion
     * @return Point<br>
     *         Relative point to the second control
     */
    public static final Point convertPoint(final int x, final int y, final Control from, final Control to) {
        Point point = new Point(x, y);
        return convertPoint(point, from, to);
    }

    /**
     * Converts the given Point which is relative to the first Control
     * to a Point relative to the second control.<br>
     * 
     * @param point
     *            The Point to Convert
     * @param from
     *            Control to which the Point coordinates are relative
     * @param to
     *            Control to which the Point coordinates should be
     *            relative after conversion
     * @return Point<br>
     *         relative point to the second control
     */
    public static final Point convertPoint(final Point point, final Control from, final Control to) {
        Point displayMouse = from.toDisplay(point);
        Point convert = to.toControl(displayMouse);

        return convert;
    }

    /**
     * Blocks a dialog from returning a value to soon. A event loop is
     * installed. When the dialog shell disposes the code after this
     * method call will be executed. Like: returning <code>true</code>
     * or something else.<br>
     * 
     * @param dialogShell
     *            The dialogs shell
     */
    public static final void blockDialogFromReturning(final Shell dialogShell) {
        Display display = dialogShell.getParent().getDisplay();
        while (!dialogShell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    /**
     * Shows a busy cursor while the given Runnable is running.<br>
     * 
     * @param parent
     *            The parent shell
     * @param runnable
     *            The runnable to execute
     * @see java.lang.Runnable
     */
    public static final void showBusyWhile(final Shell parent, final Runnable runnable) {
        BusyIndicator.showWhile(parent.getDisplay(), runnable);
    }

    /**
     * Packs the columns of the given table.
     * 
     * @param table
     *            The table to pack.
     */
    public static final void packTable(final Table table) {
        for (TableColumn c : table.getColumns()) {
            c.pack();
        }
    }

    /**
     * Checks if, the given constant is set in the given style.
     * 
     * @param style
     *            The style
     * @param constant
     *            The constant to check
     * @return <code>true</code> if the constant is set.<br>
     *         <code>false</code> if the constant is not set.<br>
     */
    public static final boolean checkStyle(final int style, final int constant) {
        return ((style & constant) != 0);
    }

    /**
     * Disposes the given widget only if it is not <code>null</code>
     * or not disposed.
     * 
     * @param widget
     *            The widget to dispose.
     * @return <code>true</code> if dispose was successful<br>
     *         <code>false</coed> if dispose was not successful<br>
     */
    public static final boolean secureDispose(Widget widget) {
        if (SWTUtil.swtAssert(widget)) {
            widget.dispose();
            return true;
        }
        return false;
    }

    /**
     * Disposes the given device only if it is not <code>null</code>
     * or not disposed.
     * 
     * @param device
     *            The device to dispose.
     * @return <code>true</code> if dispose was successful<br>
     *         <code>false</coed> if dispose was not successful<br>
     */
    public static final boolean secureDispose(Device device) {
        if (SWTUtil.swtAssert(device)) {
            device.dispose();
            return true;
        }
        return false;
    }

    /**
     * Disposes the given resource only if it is not <code>null</code>
     * or not disposed.
     * 
     * @param resource
     *            The widget to dispose.
     * @return <code>true</code> if dispose was successful<br>
     *         <code>false</coed> if dispose was not successful<br>
     */
    public static final boolean secureDispose(Resource resource) {
        if (SWTUtil.swtAssert(resource)) {
            resource.dispose();
            return true;
        }
        return false;
    }

    /**
     * Tests if a widget is not <code>null</code> and not disposed.
     * 
     * @param widget
     *            The widget to test.
     * @return <code>true</code> if widget is not <code>null</code>
     *         and not disposed.<br>
     *         <code>false</code> if widget is either
     *         <code>null</code> or disposed.<br>
     */
    public static final boolean swtAssert(Widget widget) {
        return (widget != null && !widget.isDisposed());
    }

    /**
     * Tests if a device is not <code>null</code> and not disposed.
     * 
     * @param device
     *            The device to test.
     * @return <code>true</code> if device is not <code>null</code>
     *         and not disposed.<br>
     *         <code>false</code> if device is either
     *         <code>null</code> or disposed.<br>
     */
    public static final boolean swtAssert(Device device) {
        return (device != null && !device.isDisposed());
    }

    /**
     * Tests if a resource is not <code>null</code> and not
     * disposed.
     * 
     * @param resource
     *            The resource to test.
     * @return <code>true</code> if resource is not
     *         <code>null</code> and not disposed.<br>
     *         <code>false</code> if resource is either
     *         <code>null</code> or disposed.<br>
     */
    public static final boolean swtAssert(Resource resource) {
        return (resource != null && !resource.isDisposed());
    }

    /**
     * Rotates the given point around the given center.
     * 
     * @param p
     *            the point to rotate
     * @param center
     *            the center of rotation
     * @param phi
     *            the angle for rotation in radian.
     * @return the rotated point
     */
    public static final Point rotate(Point p, Point center, double phi) {
        double cosPhi = MathLib.cos(phi);
        double sinPhi = MathLib.sin(phi);

        Point newPoint = new Point(p.x, p.y);

        newPoint.x = newPoint.x - center.x;
        newPoint.y = newPoint.y - center.y;

        double newX = sinPhi * newPoint.x + cosPhi * newPoint.y + center.x;
        double newY = -cosPhi * newPoint.x + sinPhi * newPoint.y + center.y;

        newPoint.x = (int) Math.rint(newX);
        newPoint.y = (int) Math.rint(newY);
        return newPoint;
    }

    /**
     * Rotates the given point around the given center.
     * 
     * @param p
     *            the point to rotate
     * @param center
     *            the center of rotation
     * @param phi
     *            the angle for rotation in radian.
     * @return the rotated point
     */
    public static final DoublePoint rotate(DoublePoint p, DoublePoint center, double phi) {
        double cosPhi = MathLib.cos(phi);
        double sinPhi = MathLib.sin(phi);

        DoublePoint newPoint = new DoublePoint(p.x, p.y);

        newPoint.x = newPoint.x - center.x;
        newPoint.y = newPoint.y - center.y;

        double newX = sinPhi * newPoint.x + cosPhi * newPoint.y + center.x;
        double newY = -cosPhi * newPoint.x + sinPhi * newPoint.y + center.y;

        newPoint.x = (int) Math.rint(newX);
        newPoint.y = (int) Math.rint(newY);
        return newPoint;
    }

    /**
     * Opens the given file with the default program for the files
     * extension as registered at the OS.
     * 
     * @param path
     *            the absolute path to the file.
     * @throws IOException
     *             thrown if no registered program for the given file
     *             extension was found
     */
    public static final void openFile(String path) throws IOException {
        Program p = Program.findProgram(FilenameUtils.getExtension(path));
        if (p != null) {
            p.execute(path);
        } else {
            throw new IOException(I18n.getString("SWTUtil.exception.noSuitableProgramFound")); //$NON-NLS-1$
        }
    }

    /**
     * Opens the given file with the default program for the files
     * extension as registered at the OS.
     * 
     * @param file
     *            the file
     * @throws IOException
     *             thrown if no registered program for the given file
     *             extension was found
     */
    public static final void openFile(File file) throws IOException {
        openFile(file.getAbsolutePath());
    }
}