diff --git a/app/build.xml b/app/build.xml index 2fdf8afe0..ed8e6f3b2 100644 --- a/app/build.xml +++ b/app/build.xml @@ -1,12 +1,22 @@ + + - + + + + + + + + + @@ -39,7 +49,8 @@ lib/ant.jar; lib/ant-launcher.jar; lib/jna.jar; - lib/jna-platform.jar" + lib/jna-platform.jar; + lib/VAqua7.jar" debug="on" nowarn="true"> diff --git a/app/src/processing/app/Sketch.java b/app/src/processing/app/Sketch.java index 573975f85..eac622bea 100644 --- a/app/src/processing/app/Sketch.java +++ b/app/src/processing/app/Sketch.java @@ -841,7 +841,10 @@ public class Sketch { // TODO rewrite this to use shared version from PApplet (But because that // specifies a callback function, this needs to wait until the refactoring) final String PROMPT = Language.text("save"); - if (Preferences.getBoolean("chooser.files.native")) { + + // https://github.com/processing/processing4/issues/77 + boolean useNative = Preferences.getBoolean("chooser.files.native"); + if (useNative) { // get new name for folder FileDialog fd = new FileDialog(editor, PROMPT, FileDialog.SAVE); if (isReadOnly() || isUntitled()) { diff --git a/app/src/processing/app/platform/DefaultPlatform.java b/app/src/processing/app/platform/DefaultPlatform.java index 97afad1fc..26711cddd 100644 --- a/app/src/processing/app/platform/DefaultPlatform.java +++ b/app/src/processing/app/platform/DefaultPlatform.java @@ -23,14 +23,19 @@ package processing.app.platform; +import java.awt.Color; +import java.awt.Component; import java.awt.Desktop; +import java.awt.Graphics; import java.io.File; import java.net.URI; +import javax.swing.Icon; import javax.swing.UIManager; import com.sun.jna.Library; import com.sun.jna.Native; +import org.violetlib.aqua.AquaLookAndFeel; import processing.app.Base; import processing.app.Preferences; @@ -75,7 +80,21 @@ public class DefaultPlatform { public void setLookAndFeel() throws Exception { String laf = Preferences.get("editor.laf"); if (laf == null || laf.length() == 0) { // normal situation - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + boolean isMac = System.getProperty("os.name", "").startsWith("Mac OS"); + if (isMac && Preferences.getBoolean("editor.allow_vaqua")) { + UIManager.setLookAndFeel("org.violetlib.aqua.AquaLookAndFeel"); + + Icon collapse = new MacTreeIcon(true); + Icon open = new MacTreeIcon(false); + Icon leaf = new MacEmptyIcon(); + UIManager.put("Tree.closedIcon", leaf); + UIManager.put("Tree.openIcon", leaf); + UIManager.put("Tree.collapsedIcon", open); + UIManager.put("Tree.expandedIcon", collapse); + UIManager.put("Tree.leafIcon", leaf); + } else { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } } else { UIManager.setLookAndFeel(laf); } @@ -188,4 +207,80 @@ public class DefaultPlatform { return ZOOM_DEFAULT_SIZING; } + /** + * Spacer icon for mac when using Vaqua. + * + *

+ * Due to potential rendering issues, this small spacer is used to ensure that rendering is stable + * while using Vaqua with non-standard swing components. Without this, some sizing calculations + * non-standard components may fail or become unreliable. + *

+ */ + class MacEmptyIcon implements Icon { + private final int SIZE = 1; + + /** + * Create a new single pixel spacer icon. + */ + public MacEmptyIcon() {} + + @Override + public int getIconWidth() { + return SIZE; + } + + @Override + public int getIconHeight() { + return SIZE; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) {} + } + + /** + * Replacement tree icon for mac when using Vaqua. + * + *

+ * Due to potential rendering issues with the regular tree icon set, this replacement tree icon + * for mac ensures stable rendering when using Vaqua with non-standard swing components. Without + * this, some sizing calculations within non-standard components may fail or become unreliable. + *

+ */ + private class MacTreeIcon implements Icon { + private final int SIZE = 12; + private final boolean isOpen; + + /** + * Create a new tree icon. + * + * @param newIsOpen Flag indicating if the icon should be in the open or closed state at + * construction. True if open false otherwise. + */ + public MacTreeIcon(boolean newIsOpen) { + isOpen = newIsOpen; + } + + @Override + public int getIconWidth() { + return SIZE; + } + + @Override + public int getIconHeight() { + return SIZE; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + g.setColor(Color.GRAY); + + g.drawLine(x + SIZE / 2 - 3, y + SIZE / 2, x + SIZE / 2 + 3, y + SIZE / 2); + + if (!isOpen) { + g.drawLine(x + SIZE / 2, y + SIZE / 2 - 3, x + SIZE / 2, y + SIZE / 2 + 3); + } + } + } + } diff --git a/app/src/processing/app/ui/EditorConsole.java b/app/src/processing/app/ui/EditorConsole.java index 186e692b9..ecdd6e897 100644 --- a/app/src/processing/app/ui/EditorConsole.java +++ b/app/src/processing/app/ui/EditorConsole.java @@ -188,7 +188,8 @@ public class EditorConsole extends JScrollPane { StyleConstants.setBold(errStyle, font.isBold()); StyleConstants.setItalic(errStyle, font.isItalic()); - if (UIManager.getLookAndFeel().getID().equals("Nimbus")) { + String lookAndFeel = UIManager.getLookAndFeel().getID(); + if (lookAndFeel.equals("Nimbus") || lookAndFeel.equals("VAqua")) { getViewport().setBackground(bgColor); consoleTextPane.setOpaque(false); consoleTextPane.setBackground(new Color(0, 0, 0, 0)); diff --git a/build/build.xml b/build/build.xml index 2f6a67109..8984edcd0 100644 --- a/build/build.xml +++ b/build/build.xml @@ -426,6 +426,7 @@ + @@ -706,7 +707,8 @@ copyright="© The Processing Foundation" shortVersion="${version}" version="${revision}" - mainClassName="processing.app.BaseSplash"> + mainClassName="processing.app.BaseSplash" + minimumSystemVersion="10.10.0"> diff --git a/build/shared/lib/defaults.txt b/build/shared/lib/defaults.txt index 843f706ef..0de02205d 100644 --- a/build/shared/lib/defaults.txt +++ b/build/shared/lib/defaults.txt @@ -74,6 +74,7 @@ recent.count = 10 # Default to the native (AWT) file selector where possible chooser.files.native = true +chooser.files.native.macosx = false # except on mac where it's broken # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -167,6 +168,9 @@ editor.watcher.debug = false # The window of time (in milliseconds) in which a change won't be counted editor.watcher.window = 1500 +# allow vaqua on mac +editor.allow_vaqua = true + # Format and search engine to use for online queries search.format = https://google.com/search?q=%s diff --git a/java/application/Info.plist.tmpl b/java/application/Info.plist.tmpl index 1fbe13859..1cd85f07b 100644 --- a/java/application/Info.plist.tmpl +++ b/java/application/Info.plist.tmpl @@ -38,7 +38,7 @@ @@sketch@@ LSMinimumSystemVersion - 10.8.5 + 10.10.0 NSHighResolutionCapable @@ -61,7 +61,7 @@ @@jvm_options_list@@ -Xdock:icon=$APP_ROOT/Contents/Resources/sketch.icns - -Djava.library.path=$APP_ROOT/Contents/Java + -Djava.library.path=$APP_ROOT/Contents/Java -Dapple.laf.useScreenMenuBar=true -Dcom.apple.macos.use-file-dialog-packages=true -Dcom.apple.macos.useScreenMenuBar=true diff --git a/java/build.xml b/java/build.xml index ff397d21e..36bf9b824 100644 --- a/java/build.xml +++ b/java/build.xml @@ -54,6 +54,7 @@ + diff --git a/java/src/processing/mode/java/debug/VariableInspector.java b/java/src/processing/mode/java/debug/VariableInspector.java index 7b1227150..682d7e8c5 100644 --- a/java/src/processing/mode/java/debug/VariableInspector.java +++ b/java/src/processing/mode/java/debug/VariableInspector.java @@ -610,7 +610,7 @@ public class VariableInspector extends JDialog { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - setForeground(tree.isEnabled() ? Color.BLACK : Color.GRAY); + //setForeground(tree.isEnabled() ? Color.BLACK : Color.GRAY); if (value instanceof VariableNode) { VariableNode var = (VariableNode) value;