![JAR search and dependency download from the Maven repository](/logo.png)
org.graphstream.ui.j2dviewer.Backend.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gs-ui Show documentation
Show all versions of gs-ui Show documentation
The GraphStream library. With GraphStream you deal with
graphs. Static and Dynamic. You create them from scratch, from a file
or any source. You display and render them.
The newest version!
/*
* Copyright 2006 - 2015
* Stefan Balev
* Julien Baudry
* Antoine Dutot
* Yoann Pigné
* Guilhelm Savin
*
* This file is part of GraphStream .
*
* GraphStream is a library whose purpose is to handle static or dynamic
* graph, create them from scratch, file or any source and display them.
*
* This program is free software distributed under the terms of two licenses, the
* CeCILL-C license that fits European law, and the GNU Lesser General Public
* License. You can use, modify and/ or redistribute the software under the terms
* of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
* URL or under the terms of the GNU LGPL as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
*/
package org.graphstream.ui.j2dviewer
import java.awt.RenderingHints
import java.awt.geom.Point2D
import java.awt.geom.AffineTransform
import java.awt.geom.NoninvertibleTransformException
import java.util.logging.{Level, Logger}
import scala.collection.mutable.ArrayStack
import java.awt.Graphics2D
import org.graphstream.ui.geom.Point3
import org.graphstream.ui.j2dviewer.renderer.GraphBackgroundRenderer
import org.graphstream.ui.j2dviewer.renderer.shape.Shape
import org.graphstream.ui.graphicGraph.StyleGroup
import java.awt.Container
/**
* The graphic driver.
*
* The back-end can be for example Java2D or OpenGL.
*/
abstract class Backend {
// TODO, one day.
// The goal is to replace the use of Java2D by the back-end
// Then to produce a new back-end using OpenGL to accelerate
// things, since Java is a big Mammoth that will never follow
// actual technologies (on Linux, I doubt it will ever get
// real good OpenGL implementation).
/** Called before any prior use of this back-end. */
def open(drawingSurface:Container)
/** Called after finished using this object. */
def close()
/** Setup the back-end for a new rendering session. */
def prepareNewFrame(g2:Graphics2D)
/** Transform a point in graph units into pixel units.
* @return the transformed point. */
def transform(x:Double, y:Double, z:Double):Point3
/** Pass a point in transformed coordinates (pixels) into the reverse transform (into
* graph units).
* @return the transformed point. */
def inverseTransform(x:Double, y:Double, z:Double):Point3
/** Transform a point in graph units into pixel units, the given point is transformed in place
* and also returned. */
def transform(p:Point3):Point3
/** Transform a point in pixel units into graph units, the given point is transformed in
* place and also returned. */
def inverseTransform(p:Point3):Point3
/** Push the actual transformation on the matrix stack, installing
* a copy of it on the top of the stack. */
def pushTransform()
/** Begin the work on the actual transformation matrix. */
def beginTransform
/** Make the top-most matrix as an identity matrix. */
def setIdentity()
/** Multiply the to-most matrix by a translation matrix. */
def translate(tx:Double, ty:Double, tz:Double)
/** Multiply the top-most matrix by a rotation matrix. */
def rotate(angle:Double, ax:Double, ay:Double, az:Double)
/** Multiply the top-most matrix by a scaling matrix. */
def scale(sx:Double, sy:Double, sz:Double)
/** End the work on the actual transformation matrix, installing it as the actual modelview
* matrix. If you do not call this method, all the scaling, translation and rotation are
* lost. */
def endTransform
/** Pop the actual transformation of the matrix stack, restoring
* the previous one in the stack. */
def popTransform()
/** Enable or disable anti-aliasing. */
def setAntialias(on:Boolean)
/** Enable or disable the hi-quality mode. */
def setQuality(on:Boolean)
/** The Java2D graphics. */
def graphics2D:Graphics2D
def chooseNodeShape(oldShape:Shape, group:StyleGroup):Shape
def chooseEdgeShape(oldShape:Shape, group:StyleGroup):Shape
def chooseEdgeArrowShape(oldShape:Shape, group:StyleGroup):Shape
def chooseSpriteShape(oldShape:Shape, group:StyleGroup):Shape
def chooseGraphBackgroundRenderer():GraphBackgroundRenderer
/** The drawing surface.
* The drawing surface may be different than the one passed as
* argument to open(), the back-end is free to create a new surface
* as it sees fit. */
def drawingSurface():Container
}
/** A full Java-2D rendering back-end. */
class BackendJ2D extends Backend {
protected var surface:Container = null
protected var g2:Graphics2D = null
protected val matrixStack = new ArrayStack[AffineTransform]()
protected var Tx:AffineTransform = null
protected var xT:AffineTransform = null
protected val dummyPoint = new Point2D.Double()
def graphics2D:Graphics2D = g2
def open(drawingSurface:Container) {
surface = drawingSurface
}
def close() {
surface = null
}
override def prepareNewFrame(g2:Graphics2D) {
this.g2 = g2
Tx = g2.getTransform
matrixStack.clear
//matrixStack.push(Tx)
}
def beginTransform() {
}
def endTransform() {
//g2.setTransform(Tx)
Tx = g2.getTransform
computeInverse
}
protected def computeInverse() {
try {
xT = new AffineTransform(Tx)
xT.invert
} catch {
case e:NoninvertibleTransformException => Logger.getLogger(this.getClass().getSimpleName).log(Level.WARNING, "Cannot inverse matrix.", e)
}
}
def transform(x:Double, y:Double, z:Double):Point3 = {
dummyPoint.setLocation(x,y)
Tx.transform(dummyPoint, dummyPoint)
new Point3(dummyPoint.x, dummyPoint.y, 0)
}
def inverseTransform(x:Double, y:Double, z:Double):Point3 = {
dummyPoint.setLocation(x, y)
xT.transform(dummyPoint, dummyPoint)
new Point3(dummyPoint.x, dummyPoint.y, 0)
}
def transform(p:Point3):Point3 = {
dummyPoint.setLocation(p.x, p.y)
Tx.transform(dummyPoint, dummyPoint)
p.set(dummyPoint.x, dummyPoint.y, 0)
p
}
def inverseTransform(p:Point3):Point3 = {
dummyPoint.setLocation(p.x, p.y)
xT.transform(dummyPoint, dummyPoint)
p.set(dummyPoint.x, dummyPoint.y, 0)
p
}
/** Push the actual transformation on the matrix stack, installing
* a copy of it on the top of the stack. */
def pushTransform() {
//val newTx = new AffineTransform(Tx)
matrixStack.push(g2.getTransform)
//g2.setTransform(newTx)
//Tx = newTx
// xT not changed, since newTx is a copy of Tx
}
/** Pop the actual transformation of the matrix stack, installing
* the previous one in the stack. */
def popTransform() {
assert(!matrixStack.isEmpty)
g2.setTransform(matrixStack.top)
matrixStack.pop
//Tx = matrixStack.top
//computeInverse
}
def setIdentity() = Tx.setToIdentity
def translate(tx:Double, ty:Double, tz:Double) = g2.translate(tx, ty)
def rotate(angle:Double, ax:Double, ay:Double, az:Double) = g2.rotate(angle)
def scale(sx:Double, sy:Double, sz:Double) = g2.scale(sx, sy)
def setAntialias(on:Boolean) {
import RenderingHints._
if(on) {
g2.setRenderingHint(KEY_STROKE_CONTROL, VALUE_STROKE_PURE)
g2.setRenderingHint(KEY_TEXT_ANTIALIASING, VALUE_TEXT_ANTIALIAS_ON)
g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON)
} else {
g2.setRenderingHint(KEY_STROKE_CONTROL, VALUE_STROKE_DEFAULT)
g2.setRenderingHint(KEY_TEXT_ANTIALIASING, VALUE_TEXT_ANTIALIAS_OFF)
g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_OFF)
}
}
def setQuality(on:Boolean) {
import RenderingHints._
if(on) {
g2.setRenderingHint(KEY_RENDERING, VALUE_RENDER_QUALITY)
g2.setRenderingHint(KEY_INTERPOLATION, VALUE_INTERPOLATION_BICUBIC)
g2.setRenderingHint(KEY_COLOR_RENDERING, VALUE_COLOR_RENDER_QUALITY)
g2.setRenderingHint(KEY_ALPHA_INTERPOLATION, VALUE_ALPHA_INTERPOLATION_QUALITY)
} else {
g2.setRenderingHint(KEY_RENDERING, VALUE_RENDER_SPEED)
g2.setRenderingHint(KEY_INTERPOLATION, VALUE_INTERPOLATION_NEAREST_NEIGHBOR)
g2.setRenderingHint(KEY_COLOR_RENDERING, VALUE_COLOR_RENDER_SPEED)
g2.setRenderingHint(KEY_ALPHA_INTERPOLATION, VALUE_ALPHA_INTERPOLATION_SPEED)
}
}
def chooseNodeShape(oldShape:Shape, group:StyleGroup):Shape = {
import org.graphstream.ui.graphicGraph.stylesheet.StyleConstants.Shape._
import org.graphstream.ui.j2dviewer.renderer.shape.swing._
group.getShape match {
case CIRCLE => if(oldShape.isInstanceOf[CircleShape]) oldShape else new CircleShape
case BOX => if(oldShape.isInstanceOf[SquareShape]) oldShape else new SquareShape
case ROUNDED_BOX => if(oldShape.isInstanceOf[RoundedSquareShape]) oldShape else new RoundedSquareShape
case DIAMOND => if(oldShape.isInstanceOf[DiamondShape]) oldShape else new DiamondShape
case TRIANGLE => if(oldShape.isInstanceOf[TriangleShape]) oldShape else new TriangleShape
case CROSS => if(oldShape.isInstanceOf[CrossShape]) oldShape else new CrossShape
case FREEPLANE => if(oldShape.isInstanceOf[FreePlaneNodeShape]) oldShape else new FreePlaneNodeShape
case PIE_CHART => if(oldShape.isInstanceOf[PieChartShape]) oldShape else new PieChartShape
case POLYGON => if(oldShape.isInstanceOf[PolygonShape]) oldShape else new PolygonShape
// ------------------------------------------
case TEXT_BOX => Logger.getLogger(this.getClass.getSimpleName).warning("** SORRY text-box shape not yet implemented **"); new SquareShape
case TEXT_PARAGRAPH => Logger.getLogger(this.getClass.getSimpleName).warning("** SORRY text-para shape not yet implemented **"); new SquareShape
case TEXT_CIRCLE => Logger.getLogger(this.getClass.getSimpleName).warning("** SORRY text-circle shape not yet implemented **"); new CircleShape
case TEXT_DIAMOND => Logger.getLogger(this.getClass.getSimpleName).warning("** SORRY text-diamond shape not yet implemented **"); new CircleShape
case ARROW => Logger.getLogger(this.getClass.getSimpleName).warning("** SORRY arrow shape not yet implemented **"); new CircleShape
case IMAGES => Logger.getLogger(this.getClass.getSimpleName).warning("** SORRY images shape not yet implemented **"); new SquareShape
// ------------------------------------------
case JCOMPONENT => throw new RuntimeException("WTF, jcomponent should have its own renderer")
case x => throw new RuntimeException("%s shape cannot be set for nodes".format(x.toString))
}
}
def chooseEdgeShape(oldShape:Shape, group:StyleGroup):Shape = {
import org.graphstream.ui.graphicGraph.stylesheet.StyleConstants.Shape._
import org.graphstream.ui.j2dviewer.renderer.shape.swing._
group.getShape match {
case LINE => if(oldShape.isInstanceOf[LineShape]) oldShape else new LineShape
case ANGLE => if(oldShape.isInstanceOf[AngleShape]) oldShape else new AngleShape
case BLOB => if(oldShape.isInstanceOf[BlobShape]) oldShape else new BlobShape
case CUBIC_CURVE => if(oldShape.isInstanceOf[CubicCurveShape]) oldShape else new CubicCurveShape
case FREEPLANE => if(oldShape.isInstanceOf[FreePlaneEdgeShape]) oldShape else new FreePlaneEdgeShape
case POLYLINE => if(oldShape.isInstanceOf[PolylineEdgeShape]) oldShape else new PolylineEdgeShape
case SQUARELINE => Logger.getLogger(this.getClass.getSimpleName).warning("** SORRY square-line shape not yet implemented **"); new HorizontalSquareEdgeShape
case LSQUARELINE => if(oldShape.isInstanceOf[HorizontalSquareEdgeShape]) oldShape else new LSquareEdgeShape
case HSQUARELINE => if(oldShape.isInstanceOf[HorizontalSquareEdgeShape]) oldShape else new HorizontalSquareEdgeShape
case VSQUARELINE => Logger.getLogger(this.getClass.getSimpleName).warning("** SORRY square-line shape not yet implemented **"); new HorizontalSquareEdgeShape
case x => throw new RuntimeException("%s shape cannot be set for edges".format(x.toString))
}
}
def chooseEdgeArrowShape(oldShape:Shape, group:StyleGroup):Shape = {
import org.graphstream.ui.j2dviewer.renderer.shape.swing._
import org.graphstream.ui.graphicGraph.stylesheet.StyleConstants.ArrowShape._
group.getArrowShape match {
case NONE => null
case ARROW => if(oldShape.isInstanceOf[ArrowOnEdge]) oldShape else new ArrowOnEdge
case CIRCLE => if(oldShape.isInstanceOf[CircleOnEdge]) oldShape else new CircleOnEdge
case DIAMOND => if(oldShape.isInstanceOf[DiamondOnEdge]) oldShape else new DiamondOnEdge
case IMAGE => if(oldShape.isInstanceOf[ImageOnEdge]) oldShape else new ImageOnEdge
case x => throw new RuntimeException("%s shape cannot be set for edge arrows".format(x.toString))
}
}
def chooseSpriteShape(oldShape:Shape, group:StyleGroup):Shape = {
import org.graphstream.ui.j2dviewer.renderer.shape.swing._
import org.graphstream.ui.graphicGraph.stylesheet.StyleConstants.Shape._
group.getShape match {
case CIRCLE => if(oldShape.isInstanceOf[CircleShape]) oldShape else new CircleShape
case BOX => if(oldShape.isInstanceOf[OrientableSquareShape]) oldShape else new OrientableSquareShape
case ROUNDED_BOX => if(oldShape.isInstanceOf[RoundedSquareShape]) oldShape else new RoundedSquareShape
case DIAMOND => if(oldShape.isInstanceOf[DiamondShape]) oldShape else new DiamondShape
case TRIANGLE => if(oldShape.isInstanceOf[TriangleShape]) oldShape else new TriangleShape
case CROSS => if(oldShape.isInstanceOf[CrossShape]) oldShape else new CrossShape
case ARROW => if(oldShape.isInstanceOf[SpriteArrowShape]) oldShape else new SpriteArrowShape
case FLOW => if(oldShape.isInstanceOf[SpriteFlowShape]) oldShape else new SpriteFlowShape
case PIE_CHART => if(oldShape.isInstanceOf[PieChartShape]) oldShape else new PieChartShape
case POLYGON => if(oldShape.isInstanceOf[PolygonShape]) oldShape else new PolygonShape
// ------------------------------------------
case TEXT_BOX => Logger.getLogger(this.getClass.getSimpleName).warning("** SORRY text-box shape not yet implemented **"); new SquareShape
case TEXT_PARAGRAPH => Logger.getLogger(this.getClass.getSimpleName).warning("** SORRY text-para shape not yet implemented **"); new SquareShape
case TEXT_CIRCLE => Logger.getLogger(this.getClass.getSimpleName).warning("** SORRY text-circle shape not yet implemented **"); new CircleShape
case TEXT_DIAMOND => Logger.getLogger(this.getClass.getSimpleName).warning("** SORRY text-diamond shape not yet implemented **"); new CircleShape
case IMAGES => Logger.getLogger(this.getClass.getSimpleName).warning("** SORRY images shape not yet implemented **"); new SquareShape
// ------------------------------------------
case JCOMPONENT => throw new RuntimeException("WTF, jcomponent should have its own renderer")
case x => throw new RuntimeException("%s shape cannot be set for sprites".format(x.toString))
}
}
def chooseGraphBackgroundRenderer():GraphBackgroundRenderer = null
def drawingSurface():Container = surface
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy