com.sun.javafx.tk.quantum.GlassScene Maven / Gradle / Ivy
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.javafx.tk.quantum;
import javafx.application.Platform;
import javafx.scene.input.InputMethodRequests;
import javafx.stage.StageStyle;
import com.sun.glass.ui.Clipboard;
import com.sun.glass.ui.ClipboardAssistance;
import com.sun.glass.ui.View;
import com.sun.javafx.sg.PGCamera;
import com.sun.javafx.sg.PGNode;
import com.sun.javafx.sg.prism.NGCamera;
import com.sun.javafx.sg.prism.NGNode;
import com.sun.javafx.tk.TKClipboard;
import com.sun.javafx.tk.TKDragGestureListener;
import com.sun.javafx.tk.TKDragSourceListener;
import com.sun.javafx.tk.TKDropTargetListener;
import com.sun.javafx.tk.TKScene;
import com.sun.javafx.tk.TKSceneListener;
import com.sun.javafx.tk.TKScenePaintListener;
import com.sun.prism.camera.PrismCameraImpl;
import com.sun.prism.camera.PrismDefaultCamera;
import com.sun.prism.impl.PrismSettings;
import com.sun.prism.paint.Color;
import com.sun.prism.paint.Paint;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.atomic.AtomicBoolean;
abstract class GlassScene implements TKScene {
private GlassStage stage;
protected TKSceneListener sceneListener;
protected TKDragGestureListener dragGestureListener;
protected TKDragSourceListener dragSourceListener;
protected TKDropTargetListener dropTargetListener;
protected InputMethodRequests inputMethodRequests;
private TKScenePaintListener scenePaintListener;
private TKClipboard dragSourceClipboard;
private NGNode root;
private PrismCameraImpl camera;
private Paint fillPaint;
private boolean entireSceneDirty = true;
private boolean doPresent = true;
private final AtomicBoolean painting = new AtomicBoolean(false);
private boolean depthBuffer = false;
SceneState sceneState;
private AccessControlContext accessCtrlCtx = null;
protected GlassScene(boolean depthBuffer) {
this.depthBuffer = depthBuffer;
sceneState = new SceneState(this);
}
@Override
public void dispose() {
assert stage == null; // dispose() is called after setStage(null)
}
// To be used by subclasses to enforce context check
final AccessControlContext getAccessControlContext() {
if (accessCtrlCtx == null) {
throw new RuntimeException("Scene security context has not been set!");
}
return accessCtrlCtx;
}
@Override public final void setSecurityContext(AccessControlContext ctx) {
if (accessCtrlCtx != null) {
throw new RuntimeException("Scene security context has been already set!");
}
accessCtrlCtx = ctx;
}
public void waitForRenderingToComplete() {
PaintCollector.getInstance().waitForRenderingToComplete();
}
@Override
public void waitForSynchronization() {
AbstractPainter.renderLock.lock();
}
@Override
public void releaseSynchronization() {
// The UI thread has just synchronized the render tree and
// is about to release the lock so that the render thread
// can process the new tree. Capture the current state of
// the view (such as the width and height) so that the view
// state matches the state in the render tree
updateSceneState();
AbstractPainter.renderLock.unlock();
}
boolean getDepthBuffer() {
return depthBuffer;
}
protected abstract boolean isSynchronous();
@Override public void setTKSceneListener(final TKSceneListener listener) {
this.sceneListener = listener;
}
@Override public synchronized void setTKScenePaintListener(final TKScenePaintListener listener) {
this.scenePaintListener = listener;
}
public void setTKDropTargetListener(final TKDropTargetListener listener) {
this.dropTargetListener = listener;
}
public void setTKDragSourceListener(final TKDragSourceListener listener) {
this.dragSourceListener = listener;
}
public void setTKDragGestureListener(final TKDragGestureListener listener) {
this.dragGestureListener = listener;
}
public void setInputMethodRequests(final InputMethodRequests requests) {
this.inputMethodRequests = requests;
}
@Override
public void setRoot(PGNode root) {
this.root = (NGNode)root;
entireSceneNeedsRepaint();
}
protected NGNode getRoot() {
return root;
}
PrismCameraImpl getCamera() {
return camera;
}
// List of all attached PGLights
private Object lights[];
public Object[] getLights() { return lights; }
public void setLights(Object[] lights) { this.lights = lights; }
@Override
public void setCamera(PGCamera camera) {
if (camera != null) {
this.camera = ((NGCamera) camera).getCameraImpl();
} else {
this.camera = PrismDefaultCamera.getInstance();
}
entireSceneNeedsRepaint();
}
Paint getFillPaint() {
return fillPaint;
}
@Override
public void setFillPaint(Object fillPaint) {
this.fillPaint = (Paint)fillPaint;
entireSceneNeedsRepaint();
}
@Override
public void setCursor(Object cursor) {
// Do nothing, cursors are implemented in subclasses
}
@Override
public final void markDirty() {
sceneChanged();
}
public void entireSceneNeedsRepaint() {
if (Platform.isFxApplicationThread()) {
entireSceneDirty = true;
sceneChanged();
} else {
Platform.runLater(new Runnable() {
@Override public void run() {
entireSceneDirty = true;
sceneChanged();
}
});
}
}
public boolean isEntireSceneDirty() {
return entireSceneDirty;
}
public void clearEntireSceneDirty() {
entireSceneDirty = false;
}
@Override
public TKClipboard createDragboard(boolean isDragSource) {
ClipboardAssistance assistant = new ClipboardAssistance(Clipboard.DND) {
@Override public void actionPerformed(final int performedAction) {
AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Void run() {
if ((dragSourceClipboard != null) && (dragSourceListener != null)) {
dragSourceListener.dragDropEnd(0, 0, 0, 0,
QuantumToolkit.clipboardActionToTransferMode(performedAction));
}
dragSourceClipboard = null;
return null;
}
}, getAccessControlContext());
}
};
QuantumClipboard dragboard = QuantumClipboard.getDragboardInstance(assistant);
if (isDragSource) {
dragSourceClipboard = dragboard;
}
return dragboard;
}
protected final GlassStage getStage() {
return stage;
}
void setStage(GlassStage stage) {
this.stage = stage;
sceneChanged();
}
final SceneState getSceneState() {
return sceneState;
}
final void updateSceneState() {
// should only be called on the event thread
sceneState.update();
}
protected View getPlatformView() {
return null;
}
boolean setPainting(boolean value) {
return painting.getAndSet(value);
}
void repaint() {
// Overridden in subclasses
}
final void stageVisible(boolean visible) {
// if the stage became invisible (for example before being destroyed)
// we need to remove the scene from the repainter list to prevent
// potential leak
if (!visible && PrismSettings.forceRepaint) {
PaintCollector.getInstance().removeDirtyScene(this);
}
if (visible) {
PaintCollector.getInstance().addDirtyScene(this);
}
}
public void sceneChanged() {
if (stage != null) {
// don't mark this scene dirty and add it to the dirty scene list if
// it is not attached to a Stage. When it does get attached the
// scene will be marked dirty anyway.
PaintCollector.getInstance().addDirtyScene(this);
} else {
// the scene is no longer associated with a stage, remove from
// the dirty list and clear. it will be marked dirty if it becomes
// active again
PaintCollector.getInstance().removeDirtyScene(this);
}
}
public final synchronized void frameRendered() {
if (scenePaintListener != null) {
scenePaintListener.frameRendered();
}
}
public final synchronized void setDoPresent(boolean value) {
doPresent = value;
}
public final synchronized boolean getDoPresent() {
return doPresent;
}
protected final Color getClearColor() {
WindowStage windowStage = stage instanceof WindowStage ? (WindowStage)stage : null;
if (windowStage != null && windowStage.getPlatformWindow().isTransparentWindow()) {
return (Color.TRANSPARENT);
} else {
if (fillPaint == null) {
return Color.WHITE;
} else if (fillPaint.isOpaque() ||
(windowStage != null && windowStage.getPlatformWindow().isUnifiedWindow())) {
//For bare windows the transparent fill is allowed
if (fillPaint.getType() == Paint.Type.COLOR) {
return (Color)fillPaint;
} else if (depthBuffer) {
// Must set clearColor in order for the depthBuffer to be cleared
return Color.TRANSPARENT;
} else {
return null;
}
} else {
return Color.WHITE;
}
}
}
protected final Paint getCurrentPaint() {
WindowStage windowStage = stage instanceof WindowStage ? (WindowStage)stage : null;
if ((windowStage != null) && windowStage.getStyle() == StageStyle.TRANSPARENT) {
return Color.TRANSPARENT.equals(fillPaint) ? null : fillPaint;
}
if ((fillPaint != null) && fillPaint.isOpaque() && (fillPaint.getType() == Paint.Type.COLOR)) {
return null;
}
return fillPaint;
}
@Override public String toString() {
return (" scene: " + hashCode() + ")");
}
}