Jump to: navigation, search

Difference between revisions of "GEF/GEF4/Graphics"

< GEF‎ | GEF4
m
Line 5: Line 5:
 
== Introduction ==
 
== Introduction ==
  
The GEF4 Graphics component provides a level of abstraction over different drawing toolkits. At the moment, SWT and AWT backends are in development. Its goal is to be as complete as possible, i.e. you should have access to all the functionality that you have access to when working directly with one of the underlying drawing toolkits. Of course, this is not always viable, but rather the greatest common divisor of the underlying drawing toolkits is accessible via the abstraction layer.
+
The GEF4 Graphics component provides a level of abstraction over different drawing toolkits. At the moment, SWT and AWT backends are in development. Its goal is to be as complete as possible, i.e. you should have access to all the functionality that you have access to when working directly with one of the underlying drawing toolkits (SWT or AWT). Of course, this is not always viable. But we aim to provide for one thing at least the greatest common divisor of them and for another thing decent simulations for operations which are possible in one of them when using another backend.
  
 
== IGraphics ==
 
== IGraphics ==
Line 30: Line 30:
 
import org.eclipse.gef4.geometry.planar.Polygon;
 
import org.eclipse.gef4.geometry.planar.Polygon;
 
import org.eclipse.gef4.geometry.planar.Rectangle;
 
import org.eclipse.gef4.geometry.planar.Rectangle;
import org.eclipse.gef4.graphics.Color;
+
import org.eclipse.gef4.graphics.IGraphics;
import org.eclipse.gef4.graphics.render.IDrawProperties.LineCap;
+
import org.eclipse.gef4.graphics.LineCap;
import org.eclipse.gef4.graphics.render.IDrawProperties.LineJoin;
+
import org.eclipse.gef4.graphics.LineJoin;
import org.eclipse.gef4.graphics.render.IGraphics;
+
import org.eclipse.gef4.graphics.color.Color;
import org.eclipse.gef4.graphics.render.swt.SWTGraphics;
+
import org.eclipse.gef4.graphics.swt.SwtGraphics;
 
import org.eclipse.swt.SWT;
 
import org.eclipse.swt.SWT;
 
import org.eclipse.swt.events.PaintEvent;
 
import org.eclipse.swt.events.PaintEvent;
Line 41: Line 41:
 
import org.eclipse.swt.widgets.Shell;
 
import org.eclipse.swt.widgets.Shell;
  
public class SWTGraphics001 implements PaintListener {
+
public class Ex001SimpleGraphics implements PaintListener {
  
 
public static void main(String[] args) {
 
public static void main(String[] args) {
new SWTGraphics001("Simple Graphics");
+
new Ex001SimpleGraphics("Simple Graphics");
 
}
 
}
  
public SWTGraphics001(String title) {
+
public Ex001SimpleGraphics(String title) {
 
Display display = new Display();
 
Display display = new Display();
  
Line 56: Line 56:
  
 
shell.addPaintListener(this);
 
shell.addPaintListener(this);
shell.redraw(); // triggers a PaintEvent platform independently
+
shell.redraw(); // platform independently triggers a PaintEvent
  
 
while (!shell.isDisposed()) {
 
while (!shell.isDisposed()) {
Line 66: Line 66:
  
 
public void paintControl(PaintEvent e) {
 
public void paintControl(PaintEvent e) {
SWTGraphics g = new SWTGraphics(e.gc);
+
SwtGraphics g = new SwtGraphics(e.gc);
 
renderScene(g);
 
renderScene(g);
 
g.cleanUp();
 
g.cleanUp();
Line 80: Line 80:
 
final Polygon triangle = new Polygon(260, 170, 190, 300, 330, 300);
 
final Polygon triangle = new Polygon(260, 170, 190, 300, 330, 300);
  
g.drawProperties().setLineWidth(4).setAntialiasing(true);
+
g.setFill(new Color(255, 0, 0)).setDraw(new Color(128, 0, 0))
g.fillProperties().setAntialiasing(true);
+
.setDashArray(25, 10);
  
g.pushState(); // saves the current set of properties on the stack
+
g.fill(ellipse).draw(ellipse.getOutline());
  
g.fillProperties().setColor(new Color(255, 0, 0));
+
g.setFill(new Color(0, 0, 255)).setLineJoin(LineJoin.ROUND)
g.drawProperties().setDashArray(25, 10).setColor(new Color(128, 0, 0));
+
 
+
g.fill(ellipse);
+
g.draw(ellipse.getOutline());
+
 
+
g.restoreState(); // restores the previously saved properties
+
 
+
g.fillProperties().setColor(new Color(0, 0, 255));
+
g.drawProperties().setLineJoin(LineJoin.ROUND)
+
 
.setLineCap(LineCap.ROUND);
 
.setLineCap(LineCap.ROUND);
  
g.fill(rectangle);
+
g.fill(rectangle).draw(rectangle.getOutline());
g.draw(rectangle.getOutline());
+
 
+
g.popState(); // removes the previously saved properties from the stack
+
// and enables the prior set of properties
+
  
g.fillProperties().setColor(new Color(0, 255, 0));
+
g.setFill(new Color(0, 255, 0)).setDraw(new Color(0, 128, 0))
g.drawProperties().setColor(new Color(0, 128, 0))
+
 
.setLineJoin(LineJoin.MITER);
 
.setLineJoin(LineJoin.MITER);
  
g.fill(triangle);
+
g.fill(triangle).draw(triangle.getOutline());
g.draw(triangle.getOutline());
+
 
}
 
}
  

Revision as of 09:16, 15 February 2013

Note to non-wiki readers: This documentation is generated from the Eclipse wiki - if you have corrections or additions it would be awesome if you added them in the original wiki page.


Introduction

The GEF4 Graphics component provides a level of abstraction over different drawing toolkits. At the moment, SWT and AWT backends are in development. Its goal is to be as complete as possible, i.e. you should have access to all the functionality that you have access to when working directly with one of the underlying drawing toolkits (SWT or AWT). Of course, this is not always viable. But we aim to provide for one thing at least the greatest common divisor of them and for another thing decent simulations for operations which are possible in one of them when using another backend.

IGraphics

The heart of the GEF4 Graphics component is the IGraphics interface. Normally, you will be handed over an IGraphics to accomplish your displaying tasks by a surrounding framework, but it can be used stand-alone, too. Thereto, you have to create a specific IGraphics implementation. Let us consider the following SWT example:

[Example 001: Simple Graphics]

/*******************************************************************************
 * Copyright (c) 2012 itemis AG 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:
 *     Matthias Wienand (itemis AG) - initial API and implementation
 *     
 *******************************************************************************/
package org.eclipse.gef4.graphics.examples.doc;
 
import org.eclipse.gef4.geometry.planar.Ellipse;
import org.eclipse.gef4.geometry.planar.Polygon;
import org.eclipse.gef4.geometry.planar.Rectangle;
import org.eclipse.gef4.graphics.IGraphics;
import org.eclipse.gef4.graphics.LineCap;
import org.eclipse.gef4.graphics.LineJoin;
import org.eclipse.gef4.graphics.color.Color;
import org.eclipse.gef4.graphics.swt.SwtGraphics;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
 
public class Ex001SimpleGraphics implements PaintListener {
 
	public static void main(String[] args) {
		new Ex001SimpleGraphics("Simple Graphics");
	}
 
	public Ex001SimpleGraphics(String title) {
		Display display = new Display();
 
		Shell shell = new Shell(display, SWT.SHELL_TRIM | SWT.DOUBLE_BUFFERED);
		shell.setText(title);
		shell.setBounds(0, 0, 640, 480);
		shell.open();
 
		shell.addPaintListener(this);
		shell.redraw(); // platform independently triggers a PaintEvent
 
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}
 
	public void paintControl(PaintEvent e) {
		SwtGraphics g = new SwtGraphics(e.gc);
		renderScene(g);
		g.cleanUp();
	}
 
	public void renderScene(IGraphics g) {
		// The rendering code goes here. It is independent of the actual
		// IGraphics implementation. Therefore, it is independent of the
		// underlying drawing toolkit, too.
 
		final Ellipse ellipse = new Ellipse(50, 50, 350, 200);
		final Rectangle rectangle = new Rectangle(100, 160, 125, 220);
		final Polygon triangle = new Polygon(260, 170, 190, 300, 330, 300);
 
		g.setFill(new Color(255, 0, 0)).setDraw(new Color(128, 0, 0))
				.setDashArray(25, 10);
 
		g.fill(ellipse).draw(ellipse.getOutline());
 
		g.setFill(new Color(0, 0, 255)).setLineJoin(LineJoin.ROUND)
				.setLineCap(LineCap.ROUND);
 
		g.fill(rectangle).draw(rectangle.getOutline());
 
		g.setFill(new Color(0, 255, 0)).setDraw(new Color(0, 128, 0))
				.setLineJoin(LineJoin.MITER);
 
		g.fill(triangle).draw(triangle.getOutline());
	}
 
}

Simple GEF4 Graphics example (SWT)

[Note: You can tryout the examples in your local GEF4 installation. Every example shown in this documentation exists in the org.eclipse.gef4.graphics.examples project under the org.eclipse.gef4.graphics.examples.doc package. The examples are easily found via their identification number which is written atop the source code.]

As you can see in this example, the SWTGraphics is an IGraphics implementation. It can be constructed via a SWT GC which is passed-in to the paintControl() event handler. The renderScene() method does not know anything about the actual IGraphics implemention that is used. That's why we do not need to adjust our rendering code when switching to AWT, for example. You may wonder why we have to call the cleanUp() method on the IGraphics. In the case of SWT, this is necessary to fully free the system resources that will be allocated during the rendering process. But let us concentrate on the renderScene() method.

There are two important things to notice:

  1. A set of property groups exists which control the state of the IGraphics. For every drawing operation, a corresponding IGraphicsProperties exists. The properties can be accessed/modified through the IGraphics, such as the fillProperties() calls in the example. The currently active IFillProperties will affect any fill() operation on our IGraphics.
  2. The GEF4 Geometry component is integrated into the IGraphics interface, so that we can easily display geometry objects.

IGraphics operations and properties

There are four different drawing operations available on an IGraphics: draw(), fill(), write(), and blit(). Correspondingly, you can get the active drawProperties(), fillProperties(), writeProperties(), and blitProperties() out of an IGraphics. Additionally, the canvasProperties() are used to control global IGraphics settings, such as the current drawing position. Changing the attributes of any of these IGraphicsProperties directly affects the next operation.

Using the IGraphics#draw(ICurve) and IGraphics#draw(Path) methods, you can display the (contour of the) passed-in geometry object. The operation is affected by the currently active IDrawProperties and ICanvasProperties. For a reference of all available geometry objects, take a look at the GEF4 Geometry component (GEF/GEF4/Geometry). Analogical, the IGraphics#fill(IShape), IGraphics#fill(IMultiShape), and IGraphics#fill(Path) methods will fill the interior of the passed-in geometry object. The operation is affected by the currently active IFillProperties and ICanvasProperties. Using the IGraphics#blit(Image) method, you can display the passed-in Image object. The operation is affected by the currently active IBlitProperties and ICanvasProperties. Using the IGraphics#write(String) method, you can display the passed-in String object. The operation is affected by the currently active IWriteProperties and ICanvasProperties.

The currently active IBlitProperties, ICanvasProperties, IDrawProperties, IFillProperties, and IWriteProperties are referred to as the current state of an IGraphics. You can save the current state via the pushState() method. A saved state can be restored later via the popState() method. Using this mechanism has the potential to ease the drawing code by eliminating many accesses to the individual IGraphicsProperties.

For every IGraphicsProperties you can modify multiple attributes in one method-chain, ...

IBlitProperties

The currently active IBlitProperties do affect every IGraphics#blit(Image) call according to the following setting options:

  • InterpolationHint = QUALITY
    When displaying a transformed Image, the InterpolationHint specifies whether to apply a fast and low-quality (InterpolationHint#SPEED) interpolation, or to apply a slower but higher-quality (InterpolationHint#QUALITY) interpolation.

ICanvasProperties

The currently active ICanvasProperties do affect every draw(), fill(), blit(), and write() call according to the following setting options:

  • AffineTransform = identity transform
    Transforms the coordinate system before applying any drawing operations.
  • ClippingArea = null
    Specifies an IMultiShape which serves as the clipping area for all subsequent drawing operations, i.e. trimming the parts out of the specified IMultiShape.

IDrawProperties

The currently active IDrawProperties do affect every IGraphics#draw(...) call according to the following setting options:

  • Color = black
    Specifies the drawing Color.
  • DashArray = null
    Specifies a double[] consisting of distance values which alternatingly specify opaque and transparent sections.
  • DashBegin = 0
    Specifies the initially assumed covered distance when applying the DashArray.
  • LineCap = FLAT
    Specifies how to display unconnected end points of displayed lines. A FLAT LineCap will not extend a drawn line beyond its unconnected end points. A ROUND LineCap will draw a semi-circle at the unconnected end points of a displayed line. A SQUARE LineCap will extend a drawn line beyond its unconnected end points by half the line's width.
  • LineJoin = BEVEL
    Specifies how to display the connection point of two displayed lines. A BEVEL LineJoin fills the bent corner triangular. A MITER LineJoin fills the bent corner up to the intersection point of the two outermost lines if its distance to the middle intersection is less than or equal to the MiterLimit. In case of exceeding the MiterLimit, the BEVEL LineJoin is used.
  • LineWidth = 1
    Specifies the width of displayed lines.
  • MiterLimit = 10
    Restricts the use of the MITER LineJoin, because for low intersection angles, the intersection point may lie far away from the original connection point. Its value is the maximal quotient of the distance between the intersection point and the connection point and the line width.
  • Antialiasing = true
    Enables or disables anti-aliasing.

Example:

g.drawProperties()
    .setColor(new Color(128, 128, 0, 255))
    .setDashArray(30, 10, 5, 10)
    .setDashBegin(15)
    .setLineCap(LineCap.ROUND)
    .setLineWidth(4);
g.draw(new Line(50, 50, 350, 50));

IDrawProperties example

IFillProperties

The currently active IFillProperties do affect every IGraphics#fill(...) call according to the following setting options:

  • Color = black
    Specfies the fill Color.
  • Antialiasing = true
    Enables or disables anti-aliasing.

IWriteProperties

The currently active IWriteProperties do affect every IGraphics#write(String) call according to the following setting options:

  • BackgroundColor = transparent white
  • ForegroundColor = black
  • Font = Times New Roman, 14pt
  • Antialiasing = true

Extension Mechanisms