introduce ShimAWT, moving selectInput/OutputFolder to PSurface, being AWT purge

This commit is contained in:
Ben Fry
2020-01-19 16:24:16 -05:00
parent 85d03ccbb2
commit d3feb64237
8 changed files with 453 additions and 35 deletions

View File

@@ -41,6 +41,7 @@ import java.awt.Toolkit;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.*;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.net.URL;
@@ -356,6 +357,41 @@ public class PSurfaceAWT extends PSurfaceNone {
*/
/*
@Override
public int displayDensity() {
return shim.displayDensity();
}
@Override
public int displayDensity(int display) {
return shim.displayDensity(display);
}
*/
@Override
public void selectInput(String prompt, String callback,
File file, Object callbackObject) {
ShimAWT.selectInput(prompt, callback, file, callbackObject);
}
@Override
public void selectOutput(String prompt, String callback,
File file, Object callbackObject) {
ShimAWT.selectOutput(prompt, callback, file, callbackObject);
}
@Override
public void selectFolder(String prompt, String callback,
File file, Object callbackObject) {
ShimAWT.selectFolder(prompt, callback, file, callbackObject);
}
// what needs to happen here?
@Override
public void initOffscreen(PApplet sketch) {

View File

@@ -0,0 +1,265 @@
package processing.awt;
import java.awt.EventQueue;
import java.awt.FileDialog;
import java.awt.Frame;
import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.UIManager;
import processing.core.PApplet;
import processing.core.PConstants;
/**
* This class exists as an abstraction layer to remove AWT from PApplet.
* It is a staging area for AWT-specific code that's shared by the Java2D,
* JavaFX, and JOGL renderers. Once PSurfaceFX and PSurfaceJOGL have
* their own implementations, these methods will move to PSurfaceAWT.
*/
public class ShimAWT {
/*
PGraphics graphics;
PApplet sketch;
public ShimAWT(PApplet sketch) {
this.graphics = graphics;
this.sketch = sketch;
}
*/
/*
public int displayDensity() {
if (sketch.display != PConstants.SPAN && (sketch.fullScreen || sketch.present)) {
return displayDensity(sketch.display);
}
// walk through all displays, use 2 if any display is 2
for (int i = 0; i < displayDevices.length; i++) {
if (displayDensity(i+1) == 2) {
return 2;
}
}
// If nobody's density is 2 then everyone is 1
return 1;
}
*/
/**
* @param display the display number to check
* (1-indexed to match the Preferences dialog box)
*/
/*
public int displayDensity(int display) {
if (display > 0 && display <= displayDevices.length) {
GraphicsConfiguration graphicsConfig =
displayDevices[display - 1].getDefaultConfiguration();
AffineTransform tx = graphicsConfig.getDefaultTransform();
return (int) Math.round(tx.getScaleX());
}
System.err.println("Display " + display + " does not exist, returning ");
return 1; // not the end of the world, so don't throw a RuntimeException
}
*/
static public void selectInput(String prompt, String callbackMethod,
File file, Object callbackObject) {
EventQueue.invokeLater(() -> {
selectImpl(prompt, callbackMethod, file,
callbackObject, null, FileDialog.LOAD);
});
}
/*
static public void selectOutput(String prompt, String callbackMethod,
File file, Object callbackObject, Frame parent) {
selectImpl(prompt, callbackMethod, file, callbackObject, parent, FileDialog.SAVE, null);
}
static public void selectOutput(String prompt, String callbackMethod,
File file, Object callbackObject, Frame parent,
PApplet sketch) {
selectImpl(prompt, callbackMethod, file, callbackObject, parent, FileDialog.SAVE, sketch);
}
*/
static public void selectOutput(String prompt, String callbackMethod,
File file, Object callbackObject) {
EventQueue.invokeLater(() -> {
selectImpl(prompt, callbackMethod, file,
callbackObject, null, FileDialog.SAVE);
});
}
/*
// Will remove the 'sketch' parameter once we get an upstream JOGL fix
// https://github.com/processing/processing/issues/3831
static protected void selectEvent(final String prompt,
final String callbackMethod,
final File defaultSelection,
final Object callbackObject,
final Frame parentFrame,
final int mode,
final PApplet sketch) {
EventQueue.invokeLater(new Runnable() {
public void run() {
boolean hide = (sketch != null) &&
(sketch.g instanceof PGraphicsOpenGL) &&
(PApplet.platform == PConstants.WINDOWS);
if (hide) sketch.getSurface().setVisible(false);
selectImpl(prompt, callbackMethod, defaultSelection, callbackObject,
parentFrame, mode, sketch);
if (hide) sketch.getSurface().setVisible(true);
}
});
}
*/
static public void selectImpl(final String prompt,
final String callbackMethod,
final File defaultSelection,
final Object callbackObject,
final Frame parentFrame,
final int mode) {
File selectedFile = null;
if (PApplet.useNativeSelect) {
FileDialog dialog = new FileDialog(parentFrame, prompt, mode);
if (defaultSelection != null) {
dialog.setDirectory(defaultSelection.getParent());
dialog.setFile(defaultSelection.getName());
}
dialog.setVisible(true);
String directory = dialog.getDirectory();
String filename = dialog.getFile();
if (filename != null) {
selectedFile = new File(directory, filename);
}
} else {
JFileChooser chooser = new JFileChooser();
chooser.setDialogTitle(prompt);
if (defaultSelection != null) {
chooser.setSelectedFile(defaultSelection);
}
int result = -1;
if (mode == FileDialog.SAVE) {
result = chooser.showSaveDialog(parentFrame);
} else if (mode == FileDialog.LOAD) {
result = chooser.showOpenDialog(parentFrame);
}
if (result == JFileChooser.APPROVE_OPTION) {
selectedFile = chooser.getSelectedFile();
}
}
PApplet.selectCallback(selectedFile, callbackMethod, callbackObject);
}
static public void selectFolder(final String prompt,
final String callbackMethod,
final File defaultSelection,
final Object callbackObject) {
EventQueue.invokeLater(() -> {
selectFolderImpl(prompt, callbackMethod, defaultSelection,
callbackObject, null);
});
}
/*
static public void selectFolder(final String prompt,
final String callbackMethod,
final File defaultSelection,
final Object callbackObject,
final Frame parentFrame) {
selectFolderEvent(prompt, callbackMethod, defaultSelection, callbackObject, parentFrame, null);
}
// Will remove the 'sketch' parameter once we get an upstream JOGL fix
// https://github.com/processing/processing/issues/3831
static public void selectFolderEvent(final String prompt,
final String callbackMethod,
final File defaultSelection,
final Object callbackObject,
final Frame parentFrame,
final PApplet sketch) {
EventQueue.invokeLater(() -> {
selectFolderImpl(prompt, callbackMethod, defaultSelection,
callbackObject, parentFrame, sketch);
});
}
*/
static public void selectFolderImpl(final String prompt,
final String callbackMethod,
final File defaultSelection,
final Object callbackObject,
final Frame parentFrame) {
File selectedFile = null;
if (PApplet.platform == PConstants.MACOS && PApplet.useNativeSelect) {
FileDialog fileDialog =
new FileDialog(parentFrame, prompt, FileDialog.LOAD);
if (defaultSelection != null) {
fileDialog.setDirectory(defaultSelection.getAbsolutePath());
}
System.setProperty("apple.awt.fileDialogForDirectories", "true");
fileDialog.setVisible(true);
System.setProperty("apple.awt.fileDialogForDirectories", "false");
String filename = fileDialog.getFile();
if (filename != null) {
selectedFile = new File(fileDialog.getDirectory(), fileDialog.getFile());
}
} else {
checkLookAndFeel();
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle(prompt);
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
if (defaultSelection != null) {
fileChooser.setCurrentDirectory(defaultSelection);
}
int result = fileChooser.showOpenDialog(parentFrame);
if (result == JFileChooser.APPROVE_OPTION) {
selectedFile = fileChooser.getSelectedFile();
}
}
PApplet.selectCallback(selectedFile, callbackMethod, callbackObject);
}
static private boolean lookAndFeelCheck;
/**
* Initialize the Look & Feel if it hasn't been already.
* Call this before using any Swing-related code in PApplet methods.
*/
static private void checkLookAndFeel() {
if (!lookAndFeelCheck) {
if (PApplet.platform == PConstants.WINDOWS) {
// Windows is defaulting to Metal or something else awful.
// Which also is not scaled properly with HiDPI interfaces.
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) { }
}
lookAndFeelCheck = true;
}
}
}

View File

@@ -47,14 +47,6 @@ import javax.imageio.ImageIO;
// allows us to remove our own MediaTracker code
import javax.swing.ImageIcon;
// used by selectInput(), selectOutput(), selectFolder()
import java.awt.EventQueue;
import java.awt.FileDialog;
import javax.swing.JFileChooser;
// set the look and feel, if specified
import javax.swing.UIManager;
// used by link()
import java.awt.Desktop;
@@ -6317,25 +6309,6 @@ public class PApplet implements PConstants {
*/
static private boolean lookAndFeelCheck;
/**
* Initialize the Look & Feel if it hasn't been already.
* Call this before using any Swing-related code in PApplet methods.
*/
static private void checkLookAndFeel() {
if (!lookAndFeelCheck) {
if (platform == WINDOWS) {
// Windows is defaulting to Metal or something else awful.
// Which also is not scaled properly with HiDPI interfaces.
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) { }
}
lookAndFeelCheck = true;
}
}
/**
* Open a platform-specific file chooser dialog to select a file for input.
* After the selection is made, the selected File will be passed to the
@@ -6377,10 +6350,12 @@ public class PApplet implements PConstants {
public void selectInput(String prompt, String callback,
File file, Object callbackObject) {
selectInput(prompt, callback, file, callbackObject, null, this); //selectFrame());
//selectInput(prompt, callback, file, callbackObject, null, this);
surface.selectInput(prompt, callback, file, callbackObject);
}
/*
static public void selectInput(String prompt, String callbackMethod,
File file, Object callbackObject, Frame parent,
PApplet sketch) {
@@ -6392,6 +6367,7 @@ public class PApplet implements PConstants {
File file, Object callbackObject, Frame parent) {
selectImpl(prompt, callbackMethod, file, callbackObject, parent, FileDialog.LOAD, null);
}
*/
/**
@@ -6413,10 +6389,12 @@ public class PApplet implements PConstants {
public void selectOutput(String prompt, String callback,
File file, Object callbackObject) {
selectOutput(prompt, callback, file, callbackObject, null, this); //selectFrame());
//selectOutput(prompt, callback, file, callbackObject, null, this);
surface.selectOutput(prompt, callback, file, callbackObject);
}
/*
static public void selectOutput(String prompt, String callbackMethod,
File file, Object callbackObject, Frame parent) {
selectImpl(prompt, callbackMethod, file, callbackObject, parent, FileDialog.SAVE, null);
@@ -6484,6 +6462,7 @@ public class PApplet implements PConstants {
}
});
}
*/
/**
@@ -6505,10 +6484,12 @@ public class PApplet implements PConstants {
public void selectFolder(String prompt, String callback,
File file, Object callbackObject) {
selectFolder(prompt, callback, file, callbackObject, null, this); //selectFrame());
//selectFolder(prompt, callback, file, callbackObject, null, this);
surface.selectFolder(prompt, callback, file, callbackObject);
}
/*
static public void selectFolder(final String prompt,
final String callbackMethod,
final File defaultSelection,
@@ -6567,11 +6548,12 @@ public class PApplet implements PConstants {
}
});
}
*/
static private void selectCallback(File selectedFile,
String callbackMethod,
Object callbackObject) {
static public void selectCallback(File selectedFile,
String callbackMethod,
Object callbackObject) {
try {
Class<?> callbackClass = callbackObject.getClass();
Method selectMethod =
@@ -6590,7 +6572,6 @@ public class PApplet implements PConstants {
}
//////////////////////////////////////////////////////////////
// LISTING DIRECTORIES

View File

@@ -22,6 +22,7 @@
package processing.core;
import java.io.File;
public interface PSurface {
/**
@@ -46,6 +47,19 @@ public interface PSurface {
// int deviceIndex, boolean fullScreen, boolean spanDisplays);
public void initFrame(PApplet sketch);
// public int displayDensity();
// public int displayDensity(int display);
public void selectInput(String prompt, String callback,
File file, Object callbackObject);
public void selectOutput(String prompt, String callback,
File file, Object callbackObject);
public void selectFolder(String prompt, String callback,
File file, Object callbackObject);
/**
* Get the native window object associated with this drawing surface.
* For Java2D, this will be an AWT Frame object. For OpenGL, the window.

View File

@@ -22,6 +22,7 @@
package processing.core;
import java.io.File;
/**
* Surface that's not really visible. Used for PDF and friends, or as a base
@@ -44,6 +45,31 @@ public class PSurfaceNone implements PSurface {
}
public int displayDensity() {
return 1;
}
public int displayDensity(int display) {
return 1;
}
public void selectInput(String prompt, String callback, File file,
Object callbackObject) {
}
public void selectOutput(String prompt, String callback, File file,
Object callbackObject) {
}
public void selectFolder(String prompt, String callback, File file,
Object callbackObject) {
}
@Override
public void initOffscreen(PApplet sketch) {
this.sketch = sketch;

View File

@@ -27,6 +27,7 @@ import com.sun.glass.ui.Screen;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
@@ -61,6 +62,7 @@ import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;
import javafx.util.Duration;
import processing.awt.ShimAWT;
import processing.core.*;
@@ -222,6 +224,27 @@ public class PSurfaceFX implements PSurface {
}
@Override
public void selectInput(String prompt, String callbackMethod,
File file, Object callbackObject) {
ShimAWT.selectInput(prompt, callbackMethod, file, callbackObject);
}
@Override
public void selectOutput(String prompt, String callbackMethod,
File file, Object callbackObject) {
ShimAWT.selectOutput(prompt, callbackMethod, file, callbackObject);
}
@Override
public void selectFolder(String prompt, String callbackMethod,
File file, Object callbackObject) {
ShimAWT.selectFolder(prompt, callbackMethod, file, callbackObject);
}
public void initOffscreen(PApplet sketch) {
}

View File

@@ -25,6 +25,8 @@
package processing.opengl;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.FileDialog;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
@@ -67,7 +69,7 @@ import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util.FPSAnimator;
import processing.awt.ShimAWT;
import processing.core.PApplet;
import processing.core.PConstants;
import processing.core.PGraphics;
@@ -81,6 +83,8 @@ public class PSurfaceJOGL implements PSurface {
/** Selected GL profile */
public static GLProfile profile;
ShimAWT shim;
public PJOGL pgl;
protected GLWindow window;
@@ -118,6 +122,71 @@ public class PSurfaceJOGL implements PSurface {
}
/*
@Override
public int displayDensity() {
return shim.displayDensity();
}
@Override
public int displayDensity(int display) {
return shim.displayDensity(display);
}
*/
@Override
public void selectInput(String prompt, String callbackMethod,
File file, Object callbackObject) {
EventQueue.invokeLater(() -> {
// https://github.com/processing/processing/issues/3831
boolean hide = (sketch != null) &&
(PApplet.platform == PConstants.WINDOWS);
if (hide) setVisible(false);
ShimAWT.selectImpl(prompt, callbackMethod, file,
callbackObject, null, FileDialog.LOAD);
if (hide) setVisible(true);
});
}
@Override
public void selectOutput(String prompt, String callbackMethod,
File file, Object callbackObject) {
EventQueue.invokeLater(() -> {
// https://github.com/processing/processing/issues/3831
boolean hide = (sketch != null) &&
(PApplet.platform == PConstants.WINDOWS);
if (hide) setVisible(false);
ShimAWT.selectImpl(prompt, callbackMethod, file,
callbackObject, null, FileDialog.SAVE);
if (hide) setVisible(true);
});
}
@Override
public void selectFolder(String prompt, String callbackMethod,
File file, Object callbackObject) {
EventQueue.invokeLater(() -> {
// https://github.com/processing/processing/issues/3831
boolean hide = (sketch != null) &&
(PApplet.platform == PConstants.WINDOWS);
if (hide) setVisible(false);
ShimAWT.selectFolderImpl(prompt, callbackMethod, file,
callbackObject, null);
if (hide) setVisible(true);
});
}
public void initOffscreen(PApplet sketch) {
this.sketch = sketch;
@@ -134,6 +203,7 @@ public class PSurfaceJOGL implements PSurface {
public void initFrame(PApplet sketch) {
this.sketch = sketch;
initIcons();
initDisplay();
initGL();

View File

@@ -9,6 +9,7 @@ X show 'displays have separate spaces' notice in the console
X allows us to get rid of JOptionPane
X show 'displays have separate spaces' message when the param is unset
X Catalina seems to have it un-set, but the default is the same
X move selectInput/Output/Folder to ShimAWT class
_ static versions of selectInput/selectOutput/selectFolder in PApplet have been removed
@@ -20,6 +21,8 @@ _ or even that it inits a surface-specific class for getting that info
before final release
_ implement selectInput/Output/Folder methods in PSurfaceJOGL
_ implement selectInput/Output/Folder methods in PSurfaceFX
_ Intel HD Graphics 3000 workaround is causing a big fat warning
_ https://github.com/processing/processing4/issues/50
_ ThinkDifferent unavailable with --disable-awt, needs workaround