All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graphstream.ui.j2dviewer.J2DGraphRenderer.scala Maven / Gradle / Ivy

/*
 * Copyright 2006 - 2011 
 *     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.{Container, Graphics2D}//, RenderingHints}
import java.util.ArrayList
import java.io.{File, IOException}
import java.awt.image.BufferedImage

import scala.collection.JavaConversions._

import org.graphstream.ui.geom.Point3

import org.graphstream.graph.Element

import org.graphstream.ui.swingViewer.{GraphRenderer, LayerRenderer}
import org.graphstream.ui.graphicGraph.{GraphicGraph, GraphicElement, StyleGroup, StyleGroupListener}
import org.graphstream.ui.graphicGraph.stylesheet.Selector

import org.graphstream.ui.util.Selection
import org.graphstream.ui.j2dviewer.renderer._
import org.graphstream.ScalaGS._

import javax.imageio.ImageIO

object J2DGraphRenderer {
	val DEFAULT_RENDERER = "j2d_def_rndr";
}

/**
 * 2D renderer using Swing and Java2D to render the graph.
 * 
 * 

* The role of this class is to equip each style group with a specific renderer and * to call these renderer to redraw the graph when needed. *

* *

* A render pass begins by using the camera instance to set up the projection (allows * to pass from graph units to pixels, make a rotation a zoom or a translation) and * render each style group once for the shadows, and once for the real rendering * in Z order. *

* *

* This class also handles a "selection" object that represents the current selection * and renders it. *

*/ class J2DGraphRenderer extends GraphRenderer with StyleGroupListener { // Attribute /** Set the view on the view port defined by the metrics. */ protected val camera = new Camera /** The graph to render. */ protected var graph:GraphicGraph = null /** The drawing surface. */ protected var surface:Container = null /** The current selection. */ protected val selection = new Selection /** The layer renderer for the background (under the graph), can be null. */ protected var backRenderer:LayerRenderer = null /** The layer renderer for the foreground (above the graph), can be null. */ protected var foreRenderer:LayerRenderer = null /** The rendering backend. */ protected var backend:Backend = null // Construction def open(graph:GraphicGraph, drawingSurface:Container) { if( this.graph == null ) { this.graph = graph this.surface = drawingSurface graph.getStyleGroups.addListener(this) } else { throw new RuntimeException("renderer already open, use close() first") } } def close() { if(graph != null) { graph.getStyleGroups.removeListener(this) graph = null surface = null } } // Access def getViewCenter():Point3 = camera.viewCenter def getViewPercent():Double = camera.viewPercent def getViewRotation():Double = camera.viewRotation def getGraphDimension():Double = camera.metrics.diagonal def findNodeOrSpriteAt(x:Double, y:Double):GraphicElement = camera.findNodeOrSpriteAt(graph, x, y) def allNodesOrSpritesIn(x1:Double, y1:Double, x2:Double, y2:Double):ArrayList[GraphicElement] = camera.allNodesOrSpritesIn(graph, x1, y1, x2, y2) /** The rendering surface this renderer uses. */ def renderingSurface:Container = surface // Access -- Renderer bindings protected def getStyleRenderer(graph:GraphicGraph):GraphBackgroundRenderer = { if(graph.getStyle.getRenderer("dr") == null) graph.getStyle.addRenderer("dr", new GraphBackgroundRenderer(graph, graph.getStyle)) graph.getStyle.getRenderer("dr").asInstanceOf[GraphBackgroundRenderer] } protected def getStyleRenderer(style:StyleGroup):StyleRenderer = { if( style.getRenderer("dr") == null) style.addRenderer("dr", StyleRenderer(style, this)) style.getRenderer("dr").asInstanceOf[StyleRenderer] } protected def getStyleRenderer(element:GraphicElement):StyleRenderer = { getStyleRenderer(element.getStyle) } // Command def setBounds(minx:Double, miny:Double, minz:Double, maxx:Double, maxy:Double, maxz:Double) { camera.setBounds(minx, miny, minz, maxx, maxy, maxz) } def resetView() { camera.setAutoFitView(true) camera.viewRotation = 0 } def setViewCenter(x:Double, y:Double, z:Double) { camera.setAutoFitView(false) camera.setViewCenter(x, y) } def setGraphViewport(minx:Double, miny:Double, maxx:Double, maxy:Double) { camera.setAutoFitView(false) camera.setViewCenter(minx + (maxx - minx), miny + (maxy - miny)) camera.setGraphViewport(minx, miny, maxx, maxy) camera.viewPercent = 1 } def removeGraphViewport() { camera.removeGraphViewport resetView(); } def setViewPercent(percent:Double) { camera.setAutoFitView(false) camera.viewPercent = percent } def setViewRotation(theta:Double) { camera.viewRotation = theta } def beginSelectionAt(x:Double, y:Double) { selection.active = true selection.begins(x, y) } def selectionGrowsAt(x:Double, y:Double) { selection.grows(x, y) } def endSelectionAt(x:Double, y:Double) { selection.grows(x, y) selection.active = false } def moveElementAtPx(element:GraphicElement, x:Double, y:Double) { val p = camera.inverseTransform(x, y) element.move(p.x, p.y, element.getZ) } // Commands -- Rendering def render(g:Graphics2D, width:Int, height:Int) { if(graph != null) { // Verify this view is not closed, the Swing repaint mechanism may trigger 1 or 2 // calls to this after being closed. if(backend eq null) backend = new BackendJ2D // TODO choose it according to some setting ... backend.prepareNewFrame(g) camera.setBackend(backend) val sgs = graph.getStyleGroups setupGraphics graph.computeBounds camera.setBounds(graph) camera.setViewport(width, height) getStyleRenderer(graph).render(backend, camera, width, height) renderBackLayer camera.pushView(graph) sgs.shadows.foreach { getStyleRenderer(_).renderShadow(backend, camera) } sgs.zIndex.foreach { groups => groups.foreach { group => if(group.getType != Selector.Type.GRAPH) { getStyleRenderer(group).render(backend, camera) } } } camera.popView renderForeLayer if( selection.renderer == null ) selection.renderer = new SelectionRenderer( selection, graph ) selection.renderer.render(backend, camera, width, height ) } } protected def renderBackLayer() { if(backRenderer ne null) renderLayer(backRenderer) } protected def renderForeLayer() { if(foreRenderer ne null) renderLayer(foreRenderer) } protected def renderLayer(renderer:LayerRenderer) { val metrics = camera.metrics renderer.render(backend.graphics2D, graph, metrics.ratioPx2Gu, metrics.viewport.data(0).toInt, metrics.viewport.data(1).toInt, metrics.loVisible.x, metrics.loVisible.y, metrics.hiVisible.x, metrics.hiVisible.y) } protected def setupGraphics() { backend.setAntialias(graph.hasAttribute("ui.antialias")) backend.setQuality(graph.hasAttribute("ui.quality")) } def screenshot(filename:String, width:Int, height:Int) { if(filename.endsWith("png") || filename.endsWith("PNG")) { val img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB) render(img.createGraphics, width, height) val file = new File(filename) ImageIO.write(img, "png", file) } else if(filename.endsWith("bmp") || filename.endsWith("BMP")) { val img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB) render(img.createGraphics, width, height) val file = new File(filename) ImageIO.write(img, "bmp", file) } else if(filename.endsWith("jpg") || filename.endsWith("JPG") || filename.endsWith("jpeg") || filename.endsWith("JPEG")) { val img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB) render(img.createGraphics, width, height) val file = new File(filename) ImageIO.write(img, "jpg", file) } else { System.err.println("unknown screenshot filename extension %s, saving to jpeg".format(filename)) val img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB) render(img.createGraphics, width, height) val file = new File(filename+".jpg") ImageIO.write(img, "jpg", file) } } def setBackLayerRenderer(renderer:LayerRenderer) { backRenderer = renderer } def setForeLayoutRenderer(renderer:LayerRenderer) { foreRenderer = renderer } // Commands -- Style group listener def elementStyleChanged(element:Element, oldStyle:StyleGroup, style:StyleGroup) { // XXX The element renderer should be the listener, not this. ... XXX if(oldStyle ne null) { } else if(oldStyle ne null) { val renderer = oldStyle.getRenderer(J2DGraphRenderer.DEFAULT_RENDERER) if((renderer ne null ) && renderer.isInstanceOf[JComponentRenderer]) renderer.asInstanceOf[JComponentRenderer].unequipElement(element.asInstanceOf[GraphicElement]) } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy