1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
14 * @author Toni Kalajainen
\r
16 package org.simantics.g2d.chassis;
\r
18 import java.awt.AWTException;
\r
19 import java.awt.BufferCapabilities;
\r
20 import java.awt.Component;
\r
21 import java.awt.Cursor;
\r
22 import java.awt.DisplayMode;
\r
23 import java.awt.Frame;
\r
24 import java.awt.Graphics;
\r
25 import java.awt.Graphics2D;
\r
26 import java.awt.GraphicsConfiguration;
\r
27 import java.awt.GraphicsDevice;
\r
28 import java.awt.GraphicsEnvironment;
\r
29 import java.awt.ImageCapabilities;
\r
30 import java.awt.event.KeyAdapter;
\r
31 import java.awt.event.KeyEvent;
\r
32 import java.awt.event.KeyListener;
\r
33 import java.awt.event.WindowAdapter;
\r
34 import java.awt.event.WindowEvent;
\r
35 import java.awt.geom.Rectangle2D;
\r
36 import java.awt.image.BufferStrategy;
\r
37 import java.lang.reflect.Method;
\r
39 import org.simantics.g2d.canvas.ICanvasContext;
\r
40 import org.simantics.g2d.canvas.IContentContext;
\r
41 import org.simantics.g2d.canvas.IMouseCursorContext;
\r
42 import org.simantics.g2d.canvas.IMouseCursorListener;
\r
43 import org.simantics.g2d.canvas.IContentContext.IContentListener;
\r
44 import org.simantics.g2d.dnd.DragInteractor;
\r
45 import org.simantics.g2d.dnd.DropInteractor;
\r
46 import org.simantics.g2d.participant.RenderingQualityInteractor;
\r
47 import org.simantics.g2d.participant.TransformUtil;
\r
48 import org.simantics.scenegraph.g2d.G2DRenderingHints;
\r
49 import org.simantics.scenegraph.g2d.events.adapter.AWTFocusAdapter;
\r
50 import org.simantics.scenegraph.g2d.events.adapter.AWTKeyEventAdapter;
\r
51 import org.simantics.scenegraph.g2d.events.adapter.AWTMouseEventAdapter;
\r
52 import org.simantics.utils.threads.AWTThread;
\r
53 import org.simantics.utils.threads.Executable;
\r
54 import org.simantics.utils.threads.SyncListenerList;
\r
55 import org.simantics.utils.threads.ThreadUtils;
\r
59 * Full screen AWT Frame chassis for canvas editors.
\r
61 public class FullscreenChassis extends AbstractChassis implements ICanvasChassis {
\r
63 protected Frame frame;
\r
65 protected java.awt.Canvas canvas;
\r
67 protected BufferStrategy bufferStrategy;
\r
69 protected Graphics2D g2d;
\r
71 protected TransformUtil viewboxInteractor;
\r
73 protected AWTMouseEventAdapter mouseAdapter;
\r
74 protected AWTFocusAdapter focusAdapter;
\r
75 protected AWTKeyEventAdapter keyAdapter;
\r
77 transient boolean dirty = false;
\r
79 KeyListener escapeListener = new KeyAdapter() {
\r
81 public void keyPressed(KeyEvent e) {
\r
82 if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
\r
88 * Create full screen chassis in default monitor.
\r
90 * This constructor must be ran in AWT Thread.
\r
92 * @param canvasContext
\r
93 * @param windowTitle
\r
96 public FullscreenChassis(String windowTitle, boolean ruler) {
\r
97 this(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(), windowTitle, ruler);
\r
100 public void redraw() {
\r
105 * Create full screen chassis.
\r
107 * This constructor must be ran in AWT Thread.
\r
109 * @param monitor the monitor device
\r
110 * @param canvasContext
\r
111 * @param windowTitle
\r
114 public FullscreenChassis(GraphicsDevice monitor, String windowTitle, boolean ruler) {
\r
115 DisplayMode dm = monitor.getDisplayMode();
\r
117 frame = new Frame(windowTitle);
\r
118 frame.setSize(dm.getWidth(), dm.getHeight());
\r
119 frame.setUndecorated(true);
\r
122 frame.addWindowListener(new WindowAdapter() {
\r
124 public void windowClosing(WindowEvent e) {
\r
129 public void windowClosed(WindowEvent e) {
\r
134 fireChassisClosed();
\r
138 canvas = new java.awt.Canvas() {
\r
139 private static final long serialVersionUID = -3520733232931837755L;
\r
142 public void paint(Graphics g) {
\r
143 if (bufferStrategy==null)
\r
145 BufferCapabilities caps = new BufferCapabilities(new ImageCapabilities(true),
\r
146 new ImageCapabilities(true), BufferCapabilities.FlipContents.COPIED);
\r
148 canvas.createBufferStrategy(2, caps);
\r
149 } catch (AWTException e) {
\r
150 canvas.createBufferStrategy(2);
\r
152 bufferStrategy = canvas.getBufferStrategy();
\r
154 if (g2d!=null && bufferStrategy.contentsLost()) {
\r
159 g2d = (Graphics2D) bufferStrategy.getDrawGraphics();
\r
161 bufferStrategy.show();
\r
165 public void update(Graphics g) {
\r
172 canvas.addKeyListener(escapeListener);
\r
173 frame.addKeyListener(escapeListener);
\r
175 //monitor.setFullScreenWindow(frame);
\r
179 frame.invalidate();
\r
180 java.awt.Rectangle awtBounds = monitor.getDefaultConfiguration().getBounds();
\r
181 frame.setBounds(awtBounds);
\r
182 frame.setAlwaysOnTop(true);
\r
183 frame.setVisible(true);
\r
189 public void setCanvasContext(ICanvasContext canvasContext) {
\r
190 super.setCanvasContext(canvasContext);
\r
192 // quality interactor
\r
193 RenderingQualityInteractor rq = new RenderingQualityInteractor();
\r
194 canvasContext.add(rq);
\r
196 // Set bridge for mouse cursor changing
\r
197 IMouseCursorContext mctx = canvasContext.getMouseCursorContext();
\r
198 mctx.addCursorListener(new IMouseCursorListener() {
\r
200 public void onCursorSet(IMouseCursorContext sender, int mouseId, Cursor cursor) {
\r
201 if (mouseId!=0) return;
\r
202 canvas.setCursor(cursor);
\r
203 }}, AWTThread.getThreadAccess());
\r
207 assert(canvasContext.getAtMostOneItemOfClass(DropInteractor.class)==null);
\r
208 canvasContext.add( new DropInteractor(canvas) );
\r
211 assert(canvasContext.getAtMostOneItemOfClass(DragInteractor.class)==null);
\r
212 canvasContext.add( new DragInteractor(canvas) );
\r
214 // Delegate events to the canvas context
\r
215 mouseAdapter = new AWTMouseEventAdapter(canvasContext, canvasContext.getEventQueue());
\r
216 keyAdapter = new AWTKeyEventAdapter(canvasContext, canvasContext.getEventQueue());
\r
217 focusAdapter = new AWTFocusAdapter(canvasContext, canvasContext.getEventQueue());
\r
218 canvas.addMouseListener(mouseAdapter);
\r
219 canvas.addMouseMotionListener(mouseAdapter);
\r
220 canvas.addMouseWheelListener(mouseAdapter);
\r
221 canvas.addKeyListener(keyAdapter);
\r
222 canvas.addFocusListener(focusAdapter);
\r
224 canvasContext.getContentContext().addPaintableContextListener(new IContentListener() {
\r
226 public void onDirty(IContentContext sender) {
\r
236 public void paintCanvas(Graphics2D g) {
\r
237 if (canvasContext == null)
\r
239 if (canvasContext.isLocked())
\r
244 // Paint the canvas
\r
245 Rectangle2D bounds = new Rectangle2D.Double(0,0, frame.getSize().width, frame.getSize().height);
\r
246 g.setRenderingHint(G2DRenderingHints.KEY_CONTROL_BOUNDS, bounds);
\r
247 canvasContext.getSceneGraph().render(g);
\r
251 private final static Method CLOSED_METHOD = SyncListenerList.getMethod(IChassisListener.class, "chassisClosed");
\r
253 protected void fireChassisClosed() {
\r
254 Executable e[] = listeners.getExecutables(CLOSED_METHOD, this);
\r
255 ThreadUtils.multiSyncExec(e);
\r
258 public GraphicsConfiguration getGraphicsConfiguration() {
\r
259 return frame.getGraphicsConfiguration();
\r
262 public Component getAwtComponent() {
\r
266 public Frame getFrame() {
\r