org.eclipse.draw2d.FigureCanvas.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.draw2d.FigureCanvas.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2010, 2012 IBM Corporation, Gerhardt Informatics Kft. 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
 *     Gerhardt Informatics Kft. - GEFGWT port
 *******************************************************************************/
package org.eclipse.draw2d;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;

import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * A scrolling Canvas that contains {@link Figure Figures} viewed through a
 * {@link Viewport}. Call {@link #setContents(IFigure)} to specify the root of
 * the tree of <tt>Figures</tt> to be viewed through the <tt>Viewport</tt>.
 * <p>
 * Normal procedure for using a FigureCanvas:
 * <ol>
 * <li>Create a FigureCanvas.
 * <li>Create a Draw2d Figure and call {@link #setContents(IFigure)}. This
 * Figure will be the top-level Figure of the Draw2d application.
 * </ol>
 * <dl>
 * <dt><b>Required Styles (when using certain constructors):</b></dt>
 * <dd>V_SCROLL, H_SCROLL, NO_REDRAW_RESIZE</dd>
 * <dt><b>Optional Styles:</b></dt>
 * <dd>DOUBLE_BUFFERED, RIGHT_TO_LEFT, LEFT_TO_RIGHT, NO_BACKGROUND, BORDER</dd>
 * </dl>
 * <p>
 * Note: Only one of the styles RIGHT_TO_LEFT, LEFT_TO_RIGHT may be specified.
 * </p>
 */
public class FigureCanvas extends Canvas {

    private static final int ACCEPTED_STYLES = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT | SWT.V_SCROLL | SWT.H_SCROLL
            | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED | SWT.BORDER;

    /**
     * The default styles are mixed in when certain constructors are used. This
     * constant is a bitwise OR of the following SWT style constants:
     * <UL>
     * <LI>{@link SWT#NO_REDRAW_RESIZE}</LI>
     * <LI>{@link SWT#NO_BACKGROUND}</LI>
     * <LI>{@link SWT#V_SCROLL}</LI>
     * <LI>{@link SWT#H_SCROLL}</LI>
     * </UL>
     */
    static final int DEFAULT_STYLES = SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND | SWT.V_SCROLL | SWT.H_SCROLL;

    private static final int REQUIRED_STYLES = SWT.NO_REDRAW_RESIZE | SWT.V_SCROLL | SWT.H_SCROLL;

    /** Never show scrollbar */
    public static int NEVER = 0;
    /** Automatically show scrollbar when needed */
    public static int AUTOMATIC = 1;
    /** Always show scrollbar */
    public static int ALWAYS = 2;

    private int vBarVisibility = AUTOMATIC;
    private int hBarVisibility = AUTOMATIC;
    private Viewport viewport;
    private Font font;
    private int hBarOffset;
    private int vBarOffset;

    private PropertyChangeListener horizontalChangeListener = new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent event) {
            RangeModel model = getViewport().getHorizontalRangeModel();
            hBarOffset = Math.max(0, -model.getMinimum());
            getHorizontalBar().setValues(model.getValue() + hBarOffset, model.getMinimum() + hBarOffset,
                    model.getMaximum() + hBarOffset, model.getExtent(), Math.max(1, model.getExtent() / 20),
                    Math.max(1, model.getExtent() * 3 / 4));
        }
    };

    private PropertyChangeListener verticalChangeListener = new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent event) {
            RangeModel model = getViewport().getVerticalRangeModel();
            vBarOffset = Math.max(0, -model.getMinimum());
            getVerticalBar().setValues(model.getValue() + vBarOffset, model.getMinimum() + vBarOffset,
                    model.getMaximum() + vBarOffset, model.getExtent(), Math.max(1, model.getExtent() / 20),
                    Math.max(1, model.getExtent() * 3 / 4));
        }
    };

    public final int SCROLL_SIZE;

    private PropertyChangeListener horizontalChangeListenerGWT = new PropertyChangeListener() {

        private boolean scrollbarsVisible = false;

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            com.google.gwt.canvas.client.Canvas canvas = (com.google.gwt.canvas.client.Canvas) getNativeWidget();
            LayoutPanel canvasParent = (LayoutPanel) canvas.getParent();
            if (isInPalette(canvas)) {
                return;
            }
            int defWidth = canvasParent.getOffsetWidth();
            RangeModel model = (RangeModel) evt.getSource();
            int maxVal = model.getMaximum();
            int minVal = model.getMinimum();
            int value = model.getValue();
            int size = maxVal - minVal;
            LayoutPanel simplePanel = getSimplePanel();
            simplePanel.setWidth(size + "px");
            ScrollPanel parent = (ScrollPanel) simplePanel.getParent();
            Element canvasContainerElement = canvasParent.getWidgetContainerElement(canvas);
            if ((minVal < 0 || maxVal > defWidth) && defWidth > 0 && scrollbarsVisible == false) {
                canvasContainerElement.getStyle().setBottom(SCROLL_SIZE, Unit.PX);
                onResize();
                scrollbarsVisible = true;
            } else if (minVal >= 0 && maxVal <= defWidth && scrollbarsVisible == true) {
                canvasContainerElement.getStyle().setBottom(0, Unit.PX);
                onResize();
                scrollbarsVisible = false;
            }
            parent.setHorizontalScrollPosition(value - minVal);
            // There is a missing event that isn't sent:
            scroll(parent);
            getLightweightSystem().getRootFigure().repaint();
        }

    };

    private PropertyChangeListener verticalChangeListenerGWT = new PropertyChangeListener() {

        private boolean scrollbarsVisible = false;

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            com.google.gwt.canvas.client.Canvas canvas = (com.google.gwt.canvas.client.Canvas) getNativeWidget();
            LayoutPanel canvasParent = (LayoutPanel) canvas.getParent();
            if (isInPalette(canvas)) {
                return;
            }
            int defHeight = canvasParent.getOffsetHeight();
            RangeModel model = (RangeModel) evt.getSource();
            int maxVal = model.getMaximum();
            int minVal = model.getMinimum();
            int size = maxVal - minVal;
            LayoutPanel simplePanel = getSimplePanel();
            simplePanel.setHeight(size + "px");
            ScrollPanel parent = (ScrollPanel) simplePanel.getParent();
            parent.setVerticalScrollPosition(model.getValue() - minVal);
            Element canvasContainerElement = canvasParent.getWidgetContainerElement(canvas);
            if ((minVal < 0 || maxVal > defHeight && defHeight > 0) && scrollbarsVisible == false) {
                canvasContainerElement.getStyle().setRight(SCROLL_SIZE, Unit.PX);
                onResize();
                scrollbarsVisible = true;
            } else if (minVal >= 0 && maxVal <= defHeight && scrollbarsVisible == true) {
                canvasContainerElement.getStyle().setRight(0, Unit.PX);
                onResize();
                scrollbarsVisible = false;
            }
            // There is a missing event that isn't sent:
            scroll(parent);
            getLightweightSystem().getRootFigure().repaint();
        }
    };

    private boolean isInPalette(Widget widget) {
        Widget parent = widget.getParent();
        if (parent == null) {
            return false;
        } else {
            if (parent.getElement().getId().equals("PALETTE_PANEL")) {
                return true;
            } else {
                return isInPalette(parent);
            }
        }
    }

    private final LightweightSystem lws;

    /**
     * Creates a new FigureCanvas with the given parent and the
     * {@link #DEFAULT_STYLES}.
     * 
     * @param parent
     *            the parent
     */
    public FigureCanvas(Composite parent) {
        this(parent, SWT.DOUBLE_BUFFERED, new LightweightSystem());
    }

    public FigureCanvas(com.google.gwt.canvas.client.Canvas canvas) {
        super(canvas);
        SCROLL_SIZE = 17;
        this.lws = new LightweightSystem();
        this.lws.setControl(this);
        getHorizontalBar().setVisible(false);
        getVerticalBar().setVisible(false);
        hook();
    }

    public FigureCanvas(com.google.gwt.canvas.client.Canvas canvas, LightweightSystem system) {
        super(canvas);
        SCROLL_SIZE = 17;
        this.lws = system;
        this.lws.setControl(this);
        getHorizontalBar().setVisible(false);
        getVerticalBar().setVisible(false);
        hook();
    }

    /**
     * Constructor which applies the default styles plus any optional styles
     * indicated.
     * 
     * @param parent
     *            the parent composite
     * @param style
     *            see the class javadoc for optional styles
     * @since 3.1
     */
    public FigureCanvas(Composite parent, int style) {
        this(new ScrolledComposite(parent, style), style, new LightweightSystem());
    }

    /**
     * Constructor which uses the given styles verbatim. Certain styles must be
     * used with this class. Refer to the class javadoc for more details.
     * 
     * @param style
     *            see the class javadoc for <b>required</b> and optional styles
     * @param parent
     *            the parent composite
     * @since 3.4
     */
    public FigureCanvas(int style, Composite parent) {
        this(style, parent, new LightweightSystem());
    }

    /**
     * Constructs a new FigureCanvas with the given parent and
     * LightweightSystem, using the {@link #DEFAULT_STYLES}.
     * 
     * @param parent
     *            the parent
     * @param lws
     *            the LightweightSystem
     */
    public FigureCanvas(Composite parent, LightweightSystem lws) {
        this(DEFAULT_STYLES, parent, lws);
    }

    /**
     * Constructor taking a lightweight system and SWT style, which is used
     * verbatim. Certain styles must be used with this class. Refer to the class
     * javadoc for more details.
     * 
     * @param style
     *            see the class javadoc for <b>required</b> and optional styles
     * @param parent
     *            the parent composite
     * @param lws
     *            the LightweightSystem
     * @since 3.4
     */
    public FigureCanvas(int style, Composite parent, LightweightSystem lws) {
        super(parent, checkStyle(style));
        SCROLL_SIZE = 17;
        getHorizontalBar().setVisible(false);
        getVerticalBar().setVisible(false);
        this.lws = lws;
        lws.setControl(this);
        hook();
    }

    private void hookGWTScrolling() {
        Viewport vp = getViewport();

        vp.getHorizontalRangeModel().addPropertyChangeListener(horizontalChangeListenerGWT);
        vp.getVerticalRangeModel().addPropertyChangeListener(verticalChangeListenerGWT);
    }

    private void unhookGWTScrolling() {
        Viewport vp = getViewport();

        vp.getHorizontalRangeModel().removePropertyChangeListener(horizontalChangeListenerGWT);
        vp.getVerticalRangeModel().removePropertyChangeListener(verticalChangeListenerGWT);
    }

    /**
     * Constructor
     * 
     * @param parent
     *            the parent composite
     * @param style
     *            look at class javadoc for valid styles
     * @param lws
     *            the lightweight system
     * @since 3.1
     */
    public FigureCanvas(Composite parent, int style, LightweightSystem lws) {
        this(style | DEFAULT_STYLES, parent, lws);
    }

    private static int checkStyle(int style) {
        if ((style & REQUIRED_STYLES) != REQUIRED_STYLES)
            throw new IllegalArgumentException("Required style missing on FigureCanvas"); //$NON-NLS-1$
        if ((style & ~ACCEPTED_STYLES) != 0)
            throw new IllegalArgumentException("Invalid style being set on FigureCanvas"); //$NON-NLS-1$
        return style;
    }

    /**
     * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
     */
    public org.eclipse.swt.graphics.Point computeSize(int wHint, int hHint, boolean changed) {
        // TODO Still doesn't handle scrollbar cases, such as when a constrained
        // width
        // would require a horizontal scrollbar, and therefore additional
        // height.
        int borderSize = computeTrim(0, 0, 0, 0).x * -2;
        if (wHint >= 0)
            wHint = Math.max(0, wHint - borderSize);
        if (hHint >= 0)
            hHint = Math.max(0, hHint - borderSize);
        Dimension size = getLightweightSystem().getRootFigure().getPreferredSize(wHint, hHint)
                .getExpanded(borderSize, borderSize);
        size.union(new Dimension(wHint, hHint));
        return new org.eclipse.swt.graphics.Point(size.width, size.height);
    }

    /**
     * @return the contents of the {@link Viewport}.
     */
    public IFigure getContents() {
        return getViewport().getContents();
    }

    /**
     * @see org.eclipse.swt.widgets.Control#getFont()
     */
    public Font getFont() {
        if (font == null)
            font = super.getFont();
        return font;
    }

    /**
     * @return the horizontal scrollbar visibility.
     */
    public int getHorizontalScrollBarVisibility() {
        return hBarVisibility;
    }

    /**
     * @return the LightweightSystem
     */
    public LightweightSystem getLightweightSystem() {
        return lws;
    }

    /**
     * @return the vertical scrollbar visibility.
     */
    public int getVerticalScrollBarVisibility() {
        return vBarVisibility;
    }

    /**
     * Returns the Viewport. If it's <code>null</code>, a new one is created.
     * 
     * @return the viewport
     */
    public Viewport getViewport() {
        if (viewport == null)
            setViewport(new Viewport(true));
        return viewport;
    }

    /**
     * Adds listeners for scrolling.
     */
    private void hook() {
        getLightweightSystem().getUpdateManager().addUpdateListener(new UpdateListener() {
            public void notifyPainting(Rectangle damage, java.util.Map dirtyRegions) {
            }

            public void notifyValidating() {
                if (!isDisposed())
                    layoutViewport();
            }
        });

        getHorizontalBar().addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                scrollToX(getHorizontalBar().getSelection() - hBarOffset);
            }
        });

        getVerticalBar().addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                scrollToY(getVerticalBar().getSelection() - vBarOffset);
            }
        });

        if (getSimplePanel() != null) {
            final ScrollPanel sp = (ScrollPanel) getSimplePanel().getParent();

            if (sp != null) {
                sp.addScrollHandler(new ScrollHandler() {
                    @Override
                    public void onScroll(ScrollEvent event) {
                        scroll(sp);
                    }
                });
            }
        }
    }

    private void scroll(ScrollPanel sp) {
        int hsp = sp.getHorizontalScrollPosition();
        int vsp = sp.getVerticalScrollPosition();

        int hminimum = getViewport().getHorizontalRangeModel().getMinimum();
        int vminimum = getViewport().getVerticalRangeModel().getMinimum();

        scrollTo(hminimum + hsp, vminimum + vsp);
    }

    private void hookViewport() {
        getViewport().getHorizontalRangeModel().addPropertyChangeListener(horizontalChangeListener);
        getViewport().getVerticalRangeModel().addPropertyChangeListener(verticalChangeListener);
        hookGWTScrolling();
    }

    private void unhookViewport() {
        getViewport().getHorizontalRangeModel().removePropertyChangeListener(horizontalChangeListener);
        getViewport().getVerticalRangeModel().removePropertyChangeListener(verticalChangeListener);
        unhookGWTScrolling();
    }

    private void layoutViewport() {
        ScrollPaneSolver.Result result;
        result = ScrollPaneSolver.solve(new Rectangle(getBounds()).setLocation(0, 0), getViewport(),
                getHorizontalScrollBarVisibility(), getVerticalScrollBarVisibility(), computeTrim(0, 0, 0, 0).width,
                computeTrim(0, 0, 0, 0).height);
        getLightweightSystem().setIgnoreResize(true);
        try {
            if (getHorizontalBar().getVisible() != result.showH)
                getHorizontalBar().setVisible(result.showH);
            if (getVerticalBar().getVisible() != result.showV)
                getVerticalBar().setVisible(result.showV);
            Rectangle r = new Rectangle(getBounds());
            r.setLocation(0, 0);
            getLightweightSystem().getRootFigure().setBounds(r);
        } finally {
            getLightweightSystem().setIgnoreResize(false);
        }
    }

    /**
     * Scrolls in an animated way to the new x and y location.
     * 
     * @param x
     *            the x coordinate to scroll to
     * @param y
     *            the y coordinate to scroll to
     */
    public void scrollSmoothTo(int x, int y) {
        // Ensure newHOffset and newVOffset are within the appropriate ranges
        x = verifyScrollBarOffset(getViewport().getHorizontalRangeModel(), x);
        y = verifyScrollBarOffset(getViewport().getVerticalRangeModel(), y);

        int oldX = getViewport().getViewLocation().x;
        int oldY = getViewport().getViewLocation().y;
        int dx = x - oldX;
        int dy = y - oldY;

        if (dx == 0 && dy == 0)
            return; // Nothing to do.

        Dimension viewingArea = getViewport().getClientArea().getSize();

        int minFrames = 3;
        int maxFrames = 6;
        if (dx == 0 || dy == 0) {
            minFrames = 6;
            maxFrames = 13;
        }
        int frames = (Math.abs(dx) + Math.abs(dy)) / 15;
        frames = Math.max(frames, minFrames);
        frames = Math.min(frames, maxFrames);

        int stepX = Math.min((dx / frames), (viewingArea.width / 3));
        int stepY = Math.min((dy / frames), (viewingArea.height / 3));

        for (int i = 1; i < frames; i++) {
            scrollTo(oldX + i * stepX, oldY + i * stepY);
            getViewport().getUpdateManager().performUpdate();
        }
        scrollTo(x, y);
    }

    /**
     * Scrolls the contents to the new x and y location. If this scroll
     * operation only consists of a vertical or horizontal scroll, a call will
     * be made to {@link #scrollToY(int)} or {@link #scrollToX(int)},
     * respectively, to increase performance.
     * 
     * @param x
     *            the x coordinate to scroll to
     * @param y
     *            the y coordinate to scroll to
     */
    public void scrollTo(int x, int y) {
        x = verifyScrollBarOffset(getViewport().getHorizontalRangeModel(), x);
        y = verifyScrollBarOffset(getViewport().getVerticalRangeModel(), y);
        if (x == getViewport().getViewLocation().x)
            scrollToY(y);
        else if (y == getViewport().getViewLocation().y)
            scrollToX(x);
        else
            getViewport().setViewLocation(x, y);
    }

    /**
     * Scrolls the contents horizontally so that they are offset by
     * <code>hOffset</code>.
     * 
     * @param hOffset
     *            the new horizontal offset
     */
    public void scrollToX(int hOffset) {
        hOffset = verifyScrollBarOffset(getViewport().getHorizontalRangeModel(), hOffset);
        int hOffsetOld = getViewport().getViewLocation().x;
        if (hOffset == hOffsetOld)
            return;
        int dx = -hOffset + hOffsetOld;

        Rectangle clientArea = getViewport().getBounds().getCropped(getViewport().getInsets());
        Rectangle blit = clientArea.getResized(-Math.abs(dx), 0);
        Rectangle expose = clientArea.getCopy();
        Point dest = clientArea.getTopLeft();
        expose.width = Math.abs(dx);
        if (dx < 0) { // Moving left?
            blit.translate(-dx, 0); // Move blit area to the right
            expose.x = dest.x + blit.width;
        } else
            // Moving right
            dest.x += dx; // Move expose area to the right

        // fix for bug 41111
        Control[] children = getChildren();

        boolean[] manualMove = new boolean[children.length];
        for (int i = 0; i < children.length; i++) {
            org.eclipse.swt.graphics.Rectangle bounds = children[i].getBounds();
            manualMove[i] = blit.width <= 0 || bounds.x > blit.x + blit.width || bounds.y > blit.y + blit.height
                    || bounds.x + bounds.width < blit.x || bounds.y + bounds.height < blit.y;
        }
        scroll(dest.x, dest.y, blit.x, blit.y, blit.width, blit.height, true);
        for (int i = 0; i < children.length; i++) {
            if (children[i].isDisposed())
                continue;
            org.eclipse.swt.graphics.Rectangle bounds = children[i].getBounds();
            if (manualMove[i])
                children[i].setBounds(bounds.x + dx, bounds.y, bounds.width, bounds.height);
        }

        getViewport().setIgnoreScroll(true);
        getViewport().setHorizontalLocation(hOffset);
        getViewport().setIgnoreScroll(false);
        redraw(expose.x, expose.y, expose.width, expose.height, true);
    }

    /**
     * Scrolls the contents vertically so that they are offset by
     * <code>vOffset</code>.
     * 
     * @param vOffset
     *            the new vertical offset
     */
    public void scrollToY(int vOffset) {
        vOffset = verifyScrollBarOffset(getViewport().getVerticalRangeModel(), vOffset);
        int vOffsetOld = getViewport().getViewLocation().y;
        if (vOffset == vOffsetOld)
            return;
        int dy = -vOffset + vOffsetOld;

        Rectangle clientArea = getViewport().getBounds().getCropped(getViewport().getInsets());
        Rectangle blit = clientArea.getResized(0, -Math.abs(dy));
        Rectangle expose = clientArea.getCopy();
        Point dest = clientArea.getTopLeft();
        expose.height = Math.abs(dy);
        if (dy < 0) { // Moving up?
            blit.translate(0, -dy); // Move blit area down
            expose.y = dest.y + blit.height; // Move expose area down
        } else
            // Moving down
            dest.y += dy;

        // fix for bug 41111
        Control[] children = getChildren();
        boolean[] manualMove = new boolean[children.length];
        for (int i = 0; i < children.length; i++) {
            org.eclipse.swt.graphics.Rectangle bounds = children[i].getBounds();
            manualMove[i] = blit.height <= 0 || bounds.x > blit.x + blit.width || bounds.y > blit.y + blit.height
                    || bounds.x + bounds.width < blit.x || bounds.y + bounds.height < blit.y;
        }
        scroll(dest.x, dest.y, blit.x, blit.y, blit.width, blit.height, true);
        for (int i = 0; i < children.length; i++) {
            if (children[i].isDisposed())
                continue;
            org.eclipse.swt.graphics.Rectangle bounds = children[i].getBounds();
            if (manualMove[i])
                children[i].setBounds(bounds.x, bounds.y + dy, bounds.width, bounds.height);
        }

        getViewport().setIgnoreScroll(true);
        getViewport().setVerticalLocation(vOffset);
        getViewport().setIgnoreScroll(false);
        redraw(expose.x, expose.y, expose.width, expose.height, true);
    }

    /**
     * Sets the given border on the LightweightSystem's root figure.
     * 
     * @param border
     *            The new border
     */
    public void setBorder(Border border) {
        getLightweightSystem().getRootFigure().setBorder(border);
    }

    /**
     * Sets the contents of the {@link Viewport}.
     * 
     * @param figure
     *            the new contents
     */
    public void setContents(IFigure figure) {
        getViewport().setContents(figure);
    }

    /**
     * @see org.eclipse.swt.widgets.Control#setFont(org.eclipse.swt.graphics.Font)
     */
    public void setFont(Font font) {
        this.font = font;
        super.setFont(font);
    }

    /**
     * Sets the horizontal scrollbar visibility. Possible values are
     * {@link #AUTOMATIC}, {@link #ALWAYS}, and {@link #NEVER}.
     * 
     * @param v
     *            the new visibility
     */
    public void setHorizontalScrollBarVisibility(int v) {
        hBarVisibility = v;
    }

    /**
     * Sets both the horizontal and vertical scrollbar visibility to the given
     * value. Possible values are {@link #AUTOMATIC}, {@link #ALWAYS}, and
     * {@link #NEVER}.
     * 
     * @param both
     *            the new visibility
     */
    public void setScrollBarVisibility(int both) {
        setHorizontalScrollBarVisibility(both);
        setVerticalScrollBarVisibility(both);
    }

    /**
     * Sets the vertical scrollbar visibility. Possible values are
     * {@link #AUTOMATIC}, {@link #ALWAYS}, and {@link #NEVER}.
     * 
     * @param v
     *            the new visibility
     */
    public void setVerticalScrollBarVisibility(int v) {
        vBarVisibility = v;
    }

    /**
     * Sets the Viewport. The given Viewport must use "fake" scrolling. That is,
     * it must be constructed using <code>new Viewport(true)</code>.
     * 
     * @param vp
     *            the new viewport
     */
    public void setViewport(Viewport vp) {
        if (viewport != null)
            unhookViewport();
        viewport = vp;
        lws.setContents(viewport);
        hookViewport();
    }

    private int verifyScrollBarOffset(RangeModel model, int value) {
        /**
         * FIXME: The maximum - extent value is too small and cuts of 17px of
         * the diagram if both scrollbars are visible.
         * 
         * @author Szenko
         */
        // value = Math.max(model.getMinimum(), value);
        // return Math.min(model.getMaximum() - model.getExtent(), value);
        return value;
    }

    @Override
    public void onResize() {
        final Element realParent = (Element) ((LayoutPanel) canvas.getParent()).getWidgetContainerElement(canvas);

        int pw = realParent.getClientWidth();
        int ph = realParent.getClientHeight();

        // in case of trouble :)
        // canvas.setPixelSize(pw, ph);

        canvas.setCoordinateSpaceWidth(pw);
        canvas.setCoordinateSpaceHeight(ph);

        canvas.getElement().getStyle().setProperty("DIRTY", "dirty");

        IFigure rootFigure = getLightweightSystem().getRootFigure();
        rootFigure.revalidate();
        rootFigure.repaint();
    }

    @Override
    public void redraw() {
        super.redraw();
        getLightweightSystem().getRootFigure().repaint();
    }

}