/*******************************************************************************
* Copyright (c) 2010 EclipseSource 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:
* EclipseSource - initial API and implementation
******************************************************************************/
package org.eclipse.swt.graphics;
import org.eclipse.rwt.graphics.Graphics;
import org.eclipse.swt.*;
import org.eclipse.swt.internal.graphics.*;
import org.eclipse.swt.internal.graphics.GCOperation.*;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
/**
* Class <code>GC</code> is provided to ease single-sourcing SWT and RWT code.
* Its text measurement methods directly delegate to the respective
* <code>Graphics</code> methods.
* <!--
* Class <code>GC</code> is where all of the drawing capabilities that are
* supported by SWT are located. Instances are used to draw on either an
* <code>Image</code>, a <code>Control</code>, or directly on a <code>Display</code>.
* -->
* <dl>
* <dt><b>Styles:</b></dt>
* <dd>LEFT_TO_RIGHT <!--, RIGHT_TO_LEFT --></dd>
* </dl>
*
* <!--
* <p>
* The SWT drawing coordinate system is the two-dimensional space with the origin
* (0,0) at the top left corner of the drawing area and with (x,y) values increasing
* to the right and downward respectively.
* </p>
*
* <p>
* The result of drawing on an image that was created with an indexed
* palette using a color that is not in the palette is platform specific.
* Some platforms will match to the nearest color while other will draw
* the color itself. This happens because the allocated image might use
* a direct palette on platforms that do not support indexed palette.
* </p>
* -->
*
* <p>
* Application code must explicitly invoke the <code>GC.dispose()</code>
* method to release the operating system resources managed by each instance
* when those instances are no longer required. <!-- This is <em>particularly</em>
* important on Windows95 and Windows98 where the operating system has a limited
* number of device contexts available. -->
* </p>
*
* <!--
* <p>
* Note: Only one of LEFT_TO_RIGHT and RIGHT_TO_LEFT may be specified.
* </p>
*
* @see org.eclipse.swt.events.PaintEvent
* @see <a href="http://www.eclipse.org/swt/snippets/#gc">GC snippets</a>
* @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: GraphicsExample, PaintExample</a>
* @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
* -->
* @since 1.3
*/
public class GC extends Resource {
private final Control control;
private Font font;
private Color background;
private Color foreground;
private int alpha;
private int lineWidth;
private int lineCap;
private int lineJoin;
private int style;
/**
* Constructs a new instance of this class which has been
* configured to draw on the specified drawable. Sets the
* foreground color, background color and font in the GC
* to match those in the drawable.
* <p>
* You must dispose the graphics context when it is no longer required.
* </p>
* @param drawable the drawable to draw on
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the drawable is null</li>
* <li>ERROR_NULL_ARGUMENT - if there is no current device</li>
* <li>ERROR_INVALID_ARGUMENT
* - if the drawable is an image that is not a bitmap or an icon
* - if the drawable is an image or printer that is already selected
* into another graphics context</li>
* </ul>
* @exception SWTError <ul>
* <li>ERROR_NO_HANDLES if a handle could not be obtained for GC creation</li>
* <li>ERROR_THREAD_INVALID_ACCESS if not called from the thread that created the drawable</li>
* </ul>
*/
public GC( final Drawable drawable ) {
this( drawable, SWT.NONE );
}
/**
* Constructs a new instance of this class which has been
* configured to draw on the specified drawable. Sets the
* foreground color, background color and font in the GC
* to match those in the drawable.
* <p>
* You must dispose the graphics context when it is no longer required.
* </p>
*
* @param drawable the drawable to draw on
* @param style the style of GC to construct
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the drawable is null</li>
* <li>ERROR_NULL_ARGUMENT - if there is no current device</li>
* <li>ERROR_INVALID_ARGUMENT
* - if the drawable is an image that is not a bitmap or an icon
* - if the drawable is an image or printer that is already selected
* into another graphics context</li>
* </ul>
* @exception SWTError <ul>
* <li>ERROR_NO_HANDLES if a handle could not be obtained for GC creation</li>
* <li>ERROR_THREAD_INVALID_ACCESS if not called from the thread that created the drawable</li>
* </ul>
*/
public GC( final Drawable drawable, final int style ) {
super( determineDevice( drawable ) );
if( drawable == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
// Assume that Drawable is either a Control or a Device
if( drawable instanceof Control ) {
control = ( Control )drawable;
} else {
control = null;
}
this.style = checkStyle( style );
font = determineFont( drawable );
background = determineBackground( drawable );
foreground = determineForeground( drawable );
alpha = 255;
lineCap = SWT.CAP_FLAT;
lineJoin = SWT.JOIN_MITER;
}
/**
* Sets the font which will be used by the receiver
* to draw and measure text to the argument. If the
* argument is null, then a default font appropriate
* for the platform will be used instead.
*
* @param font the new font for the receiver, or null to indicate a default font
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setFont( final Font font ) {
checkDisposed();
if( font != null && font.isDisposed() ) {
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
Font newFont = font != null ? font : getDevice().getSystemFont();
if( !newFont.equals( this.font ) ) {
this.font = newFont;
SetFont operation = new SetFont( this.font );
addGCOperation( operation );
}
}
/**
* Returns the font currently being used by the receiver
* to draw and measure text.
*
* @return the receiver's font
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public Font getFont() {
checkDisposed();
return font;
}
/**
* Returns the width of the specified character in the font
* selected into the receiver.
* <p>
* The width is defined as the space taken up by the actual
* character, not including the leading and tailing whitespace
* or overhang.
* </p>
*
* @param ch the character to measure
* @return the width of the character
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public int getCharWidth( final char ch ) {
checkDisposed();
return Graphics.stringExtent( font, Character.toString( ch ) ).x;
}
/**
* Returns the extent of the given string. No tab
* expansion or carriage return processing will be performed.
* <p>
* The <em>extent</em> of a string is the width and height of
* the rectangular area it would cover if drawn in a particular
* font (in this case, the current font in the receiver).
* </p>
*
* @param string the string to measure
* @return a point containing the extent of the string
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public Point stringExtent( final String string ) {
if( string == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
checkDisposed();
return Graphics.stringExtent( font, string );
}
/**
* Returns the extent of the given string. Tab expansion and
* carriage return processing are performed.
* <p>
* The <em>extent</em> of a string is the width and height of
* the rectangular area it would cover if drawn in a particular
* font (in this case, the current font in the receiver).
* </p>
*
* @param string the string to measure
* @return a point containing the extent of the string
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public Point textExtent( final String string ) {
if( string == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
checkDisposed();
return Graphics.textExtent( font, string, 0 );
}
/**
* Returns a FontMetrics which contains information
* about the font currently being used by the receiver
* to draw and measure text.
*
* @return font metrics for the receiver's font
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public FontMetrics getFontMetrics() {
checkDisposed();
return new FontMetrics( font );
}
/**
* Sets the background color. The background color is used
* for fill operations and as the background color when text
* is drawn.
*
* @param color the new background color for the receiver
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the color is null</li>
* <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setBackground( final Color color ) {
checkDisposed();
if( color == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
if( color.isDisposed() ) {
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
if( !color.equals( background ) ) {
background = color;
SetProperty operation
= new SetProperty( SetProperty.BACKGROUND, background );
addGCOperation( operation );
}
}
/**
* Returns the background color.
*
* @return the receiver's background color
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public Color getBackground() {
checkDisposed();
return background;
}
/**
* Sets the foreground color. The foreground color is used
* for drawing operations including when text is drawn.
*
* @param color the new foreground color for the receiver
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the color is null</li>
* <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setForeground( final Color color ) {
checkDisposed();
if( color == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
if( color.isDisposed() ) {
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
if( !color.equals( foreground ) ) {
foreground = color;
SetProperty operation
= new SetProperty( SetProperty.FOREGROUND, foreground );
addGCOperation( operation );
}
}
/**
* Returns the receiver's foreground color.
*
* @return the color used for drawing foreground things
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public Color getForeground() {
checkDisposed();
return foreground;
}
/**
* Returns the bounding rectangle of the receiver's clipping
* region. If no clipping region is set, the return value
* will be a rectangle which covers the entire bounds of the
* object the receiver is drawing on.
*
* @return the bounding rectangle of the clipping region
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public Rectangle getClipping() {
checkDisposed();
Rectangle result;
if( control != null ) {
result = control.getBounds();
} else {
result = device.getBounds();
}
return result;
}
/**
* Sets the receiver's alpha value which must be
* between 0 (transparent) and 255 (opaque).
* <p>
* This operation requires the operating system's advanced
* graphics subsystem which may not be available on some
* platforms.
* </p>
* @param alpha the alpha value
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
* </ul>
*/
public void setAlpha( final int alpha ) {
checkDisposed();
if( alpha >= 0 && alpha <= 255 && this.alpha != alpha ) {
this.alpha = alpha;
SetProperty operation
= new SetProperty( SetProperty.ALPHA, new Integer( alpha ) );
addGCOperation( operation );
}
}
/**
* Returns the receiver's alpha value. The alpha value
* is between 0 (transparent) and 255 (opaque).
*
* @return the alpha value
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public int getAlpha() {
checkDisposed();
return alpha;
}
/**
* Sets the width that will be used when drawing lines
* for all of the figure drawing operations (that is,
* <code>drawLine</code>, <code>drawRectangle</code>,
* <code>drawPolyline</code>, and so forth.
*
* @param lineWidth the width of a line
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setLineWidth( final int lineWidth ) {
checkDisposed();
if( this.lineWidth != lineWidth ) {
this.lineWidth = lineWidth;
SetProperty operation
= new SetProperty( SetProperty.LINE_WIDTH, new Integer( lineWidth ) );
addGCOperation( operation );
}
}
/**
* Returns the width that will be used when drawing lines
* for all of the figure drawing operations (that is,
* <code>drawLine</code>, <code>drawRectangle</code>,
* <code>drawPolyline</code>, and so forth.
*
* @return the receiver's line width
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public int getLineWidth() {
checkDisposed();
return lineWidth;
}
/**
* Sets the receiver's line cap style to the argument, which must be one
* of the constants <code>SWT.CAP_FLAT</code>, <code>SWT.CAP_ROUND</code>,
* or <code>SWT.CAP_SQUARE</code>.
*
* @param lineCap the cap style to be used for drawing lines
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_INVALID_ARGUMENT - if the style is not valid</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setLineCap( final int lineCap ) {
checkDisposed();
if( this.lineCap != lineCap ) {
switch( lineCap ) {
case SWT.CAP_ROUND:
case SWT.CAP_FLAT:
case SWT.CAP_SQUARE:
break;
default:
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
this.lineCap = lineCap;
SetProperty operation
= new SetProperty( SetProperty.LINE_CAP, new Integer( lineCap ) );
addGCOperation( operation );
}
}
/**
* Returns the receiver's line cap style, which will be one
* of the constants <code>SWT.CAP_FLAT</code>, <code>SWT.CAP_ROUND</code>,
* or <code>SWT.CAP_SQUARE</code>.
*
* @return the cap style used for drawing lines
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public int getLineCap() {
checkDisposed();
return lineCap;
}
/**
* Sets the receiver's line join style to the argument, which must be one
* of the constants <code>SWT.JOIN_MITER</code>, <code>SWT.JOIN_ROUND</code>,
* or <code>SWT.JOIN_BEVEL</code>.
*
* @param lineJoin the join style to be used for drawing lines
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_INVALID_ARGUMENT - if the style is not valid</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setLineJoin( final int lineJoin ) {
checkDisposed();
if( this.lineJoin != lineJoin ) {
switch( lineJoin ) {
case SWT.JOIN_MITER:
case SWT.JOIN_ROUND:
case SWT.JOIN_BEVEL:
break;
default:
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
this.lineJoin = lineJoin;
SetProperty operation
= new SetProperty( SetProperty.LINE_JOIN, new Integer( lineJoin ) );
addGCOperation( operation );
}
}
/**
* Returns the receiver's line join style, which will be one
* of the constants <code>SWT.JOIN_MITER</code>, <code>SWT.JOIN_ROUND</code>,
* or <code>SWT.JOIN_BEVEL</code>.
*
* @return the join style used for drawing lines
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public int getLineJoin() {
checkDisposed();
return lineJoin;
}
/**
* Sets the receiver's line attributes.
* <p>
* This operation requires the operating system's advanced
* graphics subsystem which may not be available on some
* platforms.
* </p>
* @param attributes the line attributes
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the attributes is null</li>
* <li>ERROR_INVALID_ARGUMENT - if any of the line attributes is not valid</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
* </ul>
*
* @see LineAttributes
*/
public void setLineAttributes( final LineAttributes attributes ) {
checkDisposed();
if( attributes == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
setLineWidth( ( int )attributes.width );
setLineCap( attributes.cap );
setLineJoin( attributes.join );
}
/**
* Returns the receiver's line attributes.
*
* @return the line attributes used for drawing lines
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public LineAttributes getLineAttributes() {
checkDisposed();
return new LineAttributes( lineWidth, lineCap, lineJoin );
}
/**
* Draws a line, using the foreground color, between the points
* (<code>x1</code>, <code>y1</code>) and (<code>x2</code>, <code>y2</code>).
*
* @param x1 the first point's x coordinate
* @param y1 the first point's y coordinate
* @param x2 the second point's x coordinate
* @param y2 the second point's y coordinate
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawLine( final int x1, final int y1, final int x2, final int y2 )
{
checkDisposed();
DrawLine operation = new DrawLine( x1, y1, x2, y2 );
addGCOperation( operation );
}
/**
* Draws the outline of the specified rectangle, using the receiver's
* foreground color. The left and right edges of the rectangle are at
* <code>rect.x</code> and <code>rect.x + rect.width</code>. The top
* and bottom edges are at <code>rect.y</code> and
* <code>rect.y + rect.height</code>.
*
* @param rect the rectangle to draw
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawRectangle( final Rectangle rect ) {
if( rect == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
drawRectangle( rect.x, rect.y, rect.width, rect.height );
}
/**
* Draws the outline of the rectangle specified by the arguments,
* using the receiver's foreground color. The left and right edges
* of the rectangle are at <code>x</code> and <code>x + width</code>.
* The top and bottom edges are at <code>y</code> and <code>y + height</code>.
*
* @param x the x coordinate of the rectangle to be drawn
* @param y the y coordinate of the rectangle to be drawn
* @param width the width of the rectangle to be drawn
* @param height the height of the rectangle to be drawn
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawRectangle( final int x,
final int y,
final int width,
final int height )
{
drawRectangle( x, y, width, height, 0, 0, false );
}
/**
* Draws a rectangle, based on the specified arguments, which has
* the appearance of the platform's <em>focus rectangle</em> if the
* platform supports such a notion, and otherwise draws a simple
* rectangle in the receiver's foreground color.
*
* @param x the x coordinate of the rectangle
* @param y the y coordinate of the rectangle
* @param width the width of the rectangle
* @param height the height of the rectangle
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawRectangle(int, int, int, int)
*/
public void drawFocus( final int x,
final int y,
final int width,
final int height )
{
drawRectangle( x, y, width, height );
}
/**
* Fills the interior of the specified rectangle, using the receiver's
* background color.
*
* @param rect the rectangle to be filled
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawRectangle(int, int, int, int)
*/
public void fillRectangle( final Rectangle rect ) {
if( rect == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
fillRectangle( rect.x, rect.y, rect.width, rect.height );
}
/**
* Fills the interior of the rectangle specified by the arguments,
* using the receiver's background color.
*
* @param x the x coordinate of the rectangle to be filled
* @param y the y coordinate of the rectangle to be filled
* @param width the width of the rectangle to be filled
* @param height the height of the rectangle to be filled
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawRectangle(int, int, int, int)
*/
public void fillRectangle( final int x,
final int y,
final int width,
final int height )
{
drawRectangle( x, y, width, height, 0, 0, true );
}
/**
* Fills the interior of the specified rectangle with a gradient
* sweeping from left to right or top to bottom progressing
* from the receiver's foreground color to its background color.
*
* @param x the x coordinate of the rectangle to be filled
* @param y the y coordinate of the rectangle to be filled
* @param width the width of the rectangle to be filled, may be negative
* (inverts direction of gradient if horizontal)
* @param height the height of the rectangle to be filled, may be negative
* (inverts direction of gradient if vertical)
* @param vertical if true sweeps from top to bottom, else
* sweeps from left to right
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawRectangle(int, int, int, int)
*/
public void fillGradientRectangle( final int x,
final int y,
final int width,
final int height,
final boolean vertical )
{
checkDisposed();
if( width != 0 && height != 0 ) {
if( background.equals( foreground ) ) {
fillRectangle( x, y, width, height );
} else {
FillGradientRectangle operation
= new FillGradientRectangle( x, y, width, height, vertical );
addGCOperation( operation );
}
}
}
/**
* Draws the outline of the round-cornered rectangle specified by
* the arguments, using the receiver's foreground color. The left and
* right edges of the rectangle are at <code>x</code> and <code>x + width</code>.
* The top and bottom edges are at <code>y</code> and <code>y + height</code>.
* The <em>roundness</em> of the corners is specified by the
* <code>arcWidth</code> and <code>arcHeight</code> arguments, which
* are respectively the width and height of the ellipse used to draw
* the corners.
*
* @param x the x coordinate of the rectangle to be drawn
* @param y the y coordinate of the rectangle to be drawn
* @param width the width of the rectangle to be drawn
* @param height the height of the rectangle to be drawn
* @param arcWidth the width of the arc
* @param arcHeight the height of the arc
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawRoundRectangle( final int x,
final int y,
final int width,
final int height,
final int arcWidth,
final int arcHeight )
{
drawRectangle( x, y, width, height, arcWidth, arcHeight, false );
}
/**
* Fills the interior of the round-cornered rectangle specified by
* the arguments, using the receiver's background color.
*
* @param x the x coordinate of the rectangle to be filled
* @param y the y coordinate of the rectangle to be filled
* @param width the width of the rectangle to be filled
* @param height the height of the rectangle to be filled
* @param arcWidth the width of the arc
* @param arcHeight the height of the arc
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawRoundRectangle
*/
public void fillRoundRectangle( final int x,
final int y,
final int width,
final int height,
final int arcWidth,
final int arcHeight )
{
drawRectangle( x, y, width, height, arcWidth, arcHeight, true );
}
/**
* Draws the outline of an oval, using the foreground color,
* within the specified rectangular area.
* <p>
* The result is a circle or ellipse that fits within the
* rectangle specified by the <code>x</code>, <code>y</code>,
* <code>width</code>, and <code>height</code> arguments.
* </p><p>
* The oval covers an area that is <code>width + 1</code>
* pixels wide and <code>height + 1</code> pixels tall.
* </p>
*
* @param x the x coordinate of the upper left corner of the oval to be drawn
* @param y the y coordinate of the upper left corner of the oval to be drawn
* @param width the width of the oval to be drawn
* @param height the height of the oval to be drawn
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawOval( final int x,
final int y,
final int width,
final int height )
{
drawArc( x, y, width, height, 0, 360, false );
}
/**
* Fills the interior of an oval, within the specified
* rectangular area, with the receiver's background
* color.
*
* @param x the x coordinate of the upper left corner of the oval to be filled
* @param y the y coordinate of the upper left corner of the oval to be filled
* @param width the width of the oval to be filled
* @param height the height of the oval to be filled
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawOval
*/
public void fillOval( final int x,
final int y,
final int width,
final int height )
{
drawArc( x, y, width, height, 0, 360, true );
}
/**
* Draws the outline of a circular or elliptical arc
* within the specified rectangular area.
* <p>
* The resulting arc begins at <code>startAngle</code> and extends
* for <code>arcAngle</code> degrees, using the current color.
* Angles are interpreted such that 0 degrees is at the 3 o'clock
* position. A positive value indicates a counter-clockwise rotation
* while a negative value indicates a clockwise rotation.
* </p><p>
* The center of the arc is the center of the rectangle whose origin
* is (<code>x</code>, <code>y</code>) and whose size is specified by the
* <code>width</code> and <code>height</code> arguments.
* </p><p>
* The resulting arc covers an area <code>width + 1</code> pixels wide
* by <code>height + 1</code> pixels tall.
* </p>
*
* @param x the x coordinate of the upper-left corner of the arc to be drawn
* @param y the y coordinate of the upper-left corner of the arc to be drawn
* @param width the width of the arc to be drawn
* @param height the height of the arc to be drawn
* @param startAngle the beginning angle
* @param arcAngle the angular extent of the arc, relative to the start angle
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawArc( final int x,
final int y,
final int width,
final int height,
final int startAngle,
final int arcAngle )
{
drawArc( x, y, width, height, startAngle, arcAngle, false );
}
/**
* Fills the interior of a circular or elliptical arc within
* the specified rectangular area, with the receiver's background
* color.
* <p>
* The resulting arc begins at <code>startAngle</code> and extends
* for <code>arcAngle</code> degrees, using the current color.
* Angles are interpreted such that 0 degrees is at the 3 o'clock
* position. A positive value indicates a counter-clockwise rotation
* while a negative value indicates a clockwise rotation.
* </p><p>
* The center of the arc is the center of the rectangle whose origin
* is (<code>x</code>, <code>y</code>) and whose size is specified by the
* <code>width</code> and <code>height</code> arguments.
* </p><p>
* The resulting arc covers an area <code>width + 1</code> pixels wide
* by <code>height + 1</code> pixels tall.
* </p>
*
* @param x the x coordinate of the upper-left corner of the arc to be filled
* @param y the y coordinate of the upper-left corner of the arc to be filled
* @param width the width of the arc to be filled
* @param height the height of the arc to be filled
* @param startAngle the beginning angle
* @param arcAngle the angular extent of the arc, relative to the start angle
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawArc
*/
public void fillArc( final int x,
final int y,
final int width,
final int height,
final int startAngle,
final int arcAngle )
{
drawArc( x, y, width, height, startAngle, arcAngle, true );
}
/**
* Draws the closed polygon which is defined by the specified array
* of integer coordinates, using the receiver's foreground color. The array
* contains alternating x and y values which are considered to represent
* points which are the vertices of the polygon. Lines are drawn between
* each consecutive pair, and between the first pair and last pair in the
* array.
*
* @param pointArray an array of alternating x and y values which are the vertices of the polygon
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT if pointArray is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawPolygon( final int[] pointArray ) {
checkDisposed();
DrawPolyline operation = new DrawPolyline( pointArray, true, false );
addGCOperation( operation );
}
/**
* Fills the interior of the closed polygon which is defined by the
* specified array of integer coordinates, using the receiver's
* background color. The array contains alternating x and y values
* which are considered to represent points which are the vertices of
* the polygon. Lines are drawn between each consecutive pair, and
* between the first pair and last pair in the array.
*
* @param pointArray an array of alternating x and y values which are the vertices of the polygon
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT if pointArray is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawPolygon
*/
public void fillPolygon( final int[] pointArray ) {
checkDisposed();
DrawPolyline operation = new DrawPolyline( pointArray, true, true );
addGCOperation( operation );
}
/**
* Draws the polyline which is defined by the specified array
* of integer coordinates, using the receiver's foreground color. The array
* contains alternating x and y values which are considered to represent
* points which are the corners of the polyline. Lines are drawn between
* each consecutive pair, but not between the first pair and last pair in
* the array.
*
* @param pointArray an array of alternating x and y values which are the corners of the polyline
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the point array is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawPolyline( final int[] pointArray ) {
checkDisposed();
DrawPolyline operation = new DrawPolyline( pointArray, false, false );
addGCOperation( operation );
}
/**
* Draws a pixel, using the foreground color, at the specified
* point (<code>x</code>, <code>y</code>).
* <p>
* Note that the receiver's line attributes do not affect this
* operation.
* </p>
*
* @param x the point's x coordinate
* @param y the point's y coordinate
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawPoint( final int x, final int y ) {
checkDisposed();
DrawPoint operation = new DrawPoint( x, y );
addGCOperation( operation );
}
/**
* Draws the given image in the receiver at the specified
* coordinates.
*
* @param image the image to draw
* @param x the x coordinate of where to draw
* @param y the y coordinate of where to draw
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the image is null</li>
* <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
* <li>ERROR_INVALID_ARGUMENT - if the given coordinates are outside the bounds of the image</li>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
* @exception SWTError <ul>
* <li>ERROR_NO_HANDLES - if no handles are available to perform the operation</li>
* </ul>
*/
public void drawImage( final Image image, final int x, final int y) {
checkDisposed();
if( image == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
if( image.isDisposed() ) {
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
DrawImage operation
= new DrawImage( image, 0, 0, -1, -1, x, y, -1, -1, true );
addGCOperation( operation );
}
/**
* Copies a rectangular area from the source image into a (potentially
* different sized) rectangular area in the receiver. If the source
* and destination areas are of differing sizes, then the source
* area will be stretched or shrunk to fit the destination area
* as it is copied. The copy fails if any part of the source rectangle
* lies outside the bounds of the source image, or if any of the width
* or height arguments are negative.
*
* @param image the source image
* @param srcX the x coordinate in the source image to copy from
* @param srcY the y coordinate in the source image to copy from
* @param srcWidth the width in pixels to copy from the source
* @param srcHeight the height in pixels to copy from the source
* @param destX the x coordinate in the destination to copy to
* @param destY the y coordinate in the destination to copy to
* @param destWidth the width in pixels of the destination rectangle
* @param destHeight the height in pixels of the destination rectangle
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the image is null</li>
* <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
* <li>ERROR_INVALID_ARGUMENT - if any of the width or height arguments are negative.
* <li>ERROR_INVALID_ARGUMENT - if the source rectangle is not contained within the bounds of the source image</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
* @exception SWTError <ul>
* <li>ERROR_NO_HANDLES - if no handles are available to perform the operation</li>
* </ul>
*/
public void drawImage( final Image image,
final int srcX,
final int srcY,
final int srcWidth,
final int srcHeight,
final int destX,
final int destY,
final int destWidth,
final int destHeight )
{
checkDisposed();
if( srcWidth != 0 && srcHeight != 0 && destWidth != 0 && destHeight != 0 ) {
if( srcX < 0
|| srcY < 0
|| srcWidth < 0
|| srcHeight < 0
|| destWidth < 0
|| destHeight < 0 )
{
SWT.error (SWT.ERROR_INVALID_ARGUMENT);
}
if( image == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
if( image.isDisposed() ) {
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
DrawImage operation = new DrawImage( image,
srcX,
srcY,
srcWidth,
srcHeight,
destX,
destY,
destWidth,
destHeight,
false );
addGCOperation( operation );
}
}
/**
* Draws the given string, using the receiver's current font and
* foreground color. No tab expansion or carriage return processing
* will be performed. The background of the rectangular area where
* the string is being drawn will be filled with the receiver's
* background color.
*
* @param string the string to be drawn
* @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
* @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawString( final String string, final int x, final int y ) {
drawString( string, x, y, false );
}
/**
* Draws the given string, using the receiver's current font and
* foreground color. No tab expansion or carriage return processing
* will be performed. If <code>isTransparent</code> is <code>true</code>,
* then the background of the rectangular area where the string is being
* drawn will not be modified, otherwise it will be filled with the
* receiver's background color.
*
* @param string the string to be drawn
* @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
* @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
* @param isTransparent if <code>true</code> the background will be transparent, otherwise it will be opaque
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawString( final String string,
final int x,
final int y,
final boolean isTransparent )
{
int flags = isTransparent ? SWT.DRAW_TRANSPARENT : SWT.NONE;
drawText( string, x, y, flags );
}
/**
* Draws the given string, using the receiver's current font and
* foreground color. Tab expansion and carriage return processing
* are performed. The background of the rectangular area where
* the text is being drawn will be filled with the receiver's
* background color.
*
* @param string the string to be drawn
* @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
* @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawText( final String string, final int x, final int y ) {
drawText( string, x, y, SWT.DRAW_DELIMITER | SWT.DRAW_TAB );
}
/**
* Draws the given string, using the receiver's current font and
* foreground color. Tab expansion and carriage return processing
* are performed. If <code>isTransparent</code> is <code>true</code>,
* then the background of the rectangular area where the text is being
* drawn will not be modified, otherwise it will be filled with the
* receiver's background color.
*
* @param string the string to be drawn
* @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
* @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
* @param isTransparent if <code>true</code> the background will be transparent, otherwise it will be opaque
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawText( final String string,
final int x,
final int y,
final boolean isTransparent )
{
int flags = SWT.DRAW_DELIMITER | SWT.DRAW_TAB;
if( isTransparent ) {
flags |= SWT.DRAW_TRANSPARENT;
}
drawText( string, x, y, flags );
}
/**
* Draws the given string, using the receiver's current font and
* foreground color. Tab expansion, line delimiter and mnemonic
* processing are performed according to the specified flags. If
* <code>flags</code> includes <code>DRAW_TRANSPARENT</code>,
* then the background of the rectangular area where the text is being
* drawn will not be modified, otherwise it will be filled with the
* receiver's background color.
* <p>
* The parameter <code>flags</code> may be a combination of:
* <dl>
* <dt><b>DRAW_DELIMITER</b></dt>
* <dd>draw multiple lines</dd>
* <dt><b>DRAW_TAB</b></dt>
* <dd>expand tabs</dd>
* <dt><b>DRAW_MNEMONIC</b></dt>
* <dd>underline the mnemonic character</dd>
* <dt><b>DRAW_TRANSPARENT</b></dt>
* <dd>transparent background</dd>
* </dl>
* </p>
*
* @param string the string to be drawn
* @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
* @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
* @param flags the flags specifying how to process the text
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawText( final String string,
final int x,
final int y,
final int flags )
{
checkDisposed();
if( string == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
if( string.length() != 0 ) {
DrawText operation = new DrawText( string, x, y, flags );
addGCOperation( operation );
}
}
/**
* Returns the receiver's style information.
* <p>
* Note that the value which is returned by this method <em>may
* not match</em> the value which was provided to the constructor
* when the receiver was created. This can occur when the underlying
* operating system does not support a particular combination of
* requested styles.
* </p>
*
* @return the style bits
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public int getStyle() {
checkDisposed();
return style;
}
private void drawArc( final int x,
final int y,
final int width,
final int height,
final int startAngle,
final int arcAngle,
final boolean fill )
{
checkDisposed();
Rectangle bounds = checkBounds( x, y, width, height );
if( bounds.width != 0 && bounds.height != 0 && arcAngle != 0 ) {
DrawArc operation = new DrawArc( bounds.x,
bounds.y,
bounds.width,
bounds.height,
startAngle,
arcAngle,
fill );
addGCOperation( operation );
}
}
private void drawRectangle( final int x,
final int y,
final int width,
final int height,
final int arcWidth,
final int arcHeight,
final boolean fill )
{
checkDisposed();
Rectangle bounds = checkBounds( x, y, width, height );
if( bounds.width != 0 && bounds.height != 0 ) {
GCOperation operation;
if( arcWidth == 0 || arcHeight == 0 ) {
operation = new DrawRectangle( bounds.x,
bounds.y,
bounds.width,
bounds.height,
fill );
} else {
operation = new DrawRoundRectangle( bounds.x,
bounds.y,
bounds.width,
bounds.height,
Math.abs( arcWidth ),
Math.abs( arcHeight ),
fill );
}
addGCOperation( operation );
}
}
private static Rectangle checkBounds( final int x,
final int y,
final int width,
final int height )
{
Rectangle result = new Rectangle( x, y, width, height );
if( width < 0 ) {
result.x = x + width;
result.width = -width;
}
if( height < 0 ) {
result.y = y + height;
result.height = -height;
}
return result;
}
private void checkDisposed() {
if( isDisposed() ) {
SWT.error( SWT.ERROR_GRAPHIC_DISPOSED );
}
}
private static int checkStyle( final int style ) {
return SWT.LEFT_TO_RIGHT;
}
GCAdapter getGCAdapter() {
GCAdapter result = null;
if( control != null ) {
result = ( GCAdapter )control.getAdapter( IGCAdapter.class );
}
return result;
}
private void addGCOperation( final GCOperation operation ) {
GCAdapter adapter = getGCAdapter();
if( adapter != null ) {
adapter.addGCOperation( operation );
}
}
private static Device determineDevice( final Drawable drawable ) {
Device result = null;
if( drawable instanceof Control ) {
result = ( ( Control )drawable ).getDisplay();
} else if( drawable instanceof Device ) {
result = ( Device )drawable;
}
return result;
}
private static Font determineFont( final Drawable drawable ) {
Font result = null;
if( drawable instanceof Control ) {
result = ( ( Control )drawable ).getFont();
} else if( drawable instanceof Display ) {
result = ( ( Display )drawable ).getSystemFont();
}
return result;
}
private static Color determineBackground( final Drawable drawable ) {
Color result = null;
if( drawable instanceof Control ) {
result = ( ( Control )drawable ).getBackground();
} else if( drawable instanceof Display ) {
result = ( ( Display )drawable ).getSystemColor( SWT.COLOR_WHITE );
}
return result;
}
private static Color determineForeground( final Drawable drawable ) {
Color result = null;
if( drawable instanceof Control ) {
result = ( ( Control )drawable ).getForeground();
} else if( drawable instanceof Display ) {
result = ( ( Display )drawable ).getSystemColor( SWT.COLOR_BLACK );
}
return result;
}
}