diff --git a/app/.classpath b/app/.classpath
index 51172fa7c..d43f5bcbe 100644
--- a/app/.classpath
+++ b/app/.classpath
@@ -4,7 +4,6 @@
-
@@ -53,4 +52,6 @@
+
+
diff --git a/app/lib/jtouchbar-0.2.0-20180827.120213-5.jar b/app/lib/jtouchbar-0.2.0-20180827.120213-5.jar
new file mode 100644
index 000000000..eb3902a65
Binary files /dev/null and b/app/lib/jtouchbar-0.2.0-20180827.120213-5.jar differ
diff --git a/app/lib/jtouchbar.LICENSE.MIT.txt b/app/lib/jtouchbar.LICENSE.MIT.txt
new file mode 100644
index 000000000..f4fa99707
--- /dev/null
+++ b/app/lib/jtouchbar.LICENSE.MIT.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 thizzer.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/app/src/processing/app/EditorToolbar.java b/app/src/processing/app/EditorToolbar.java
index 00da0f37a..b1f854ecd 100644
--- a/app/src/processing/app/EditorToolbar.java
+++ b/app/src/processing/app/EditorToolbar.java
@@ -23,11 +23,24 @@
package processing.app;
+import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.MouseInputListener;
+
+import com.thizzer.jtouchbar.JTouchBar;
+import com.thizzer.jtouchbar.item.TouchBarItem;
+import com.thizzer.jtouchbar.item.view.TouchBarButton;
+
+import processing.app.helpers.OSUtils;
+
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import static processing.app.I18n.tr;
import static processing.app.Theme.scale;
@@ -92,10 +105,13 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
private final Color bgcolor;
private static Image[][] buttonImages;
+ private static com.thizzer.jtouchbar.common.Image[][] touchBarImages;
private int currentRollover;
private JPopupMenu popup;
private final JMenu menu;
+ private JTouchBar touchBar;
+ private TouchBarButton[] touchBarButtons;
private int buttonCount;
private int[] state = new int[BUTTON_COUNT];
@@ -133,10 +149,47 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
statusFont = Theme.getFont("buttons.status.font");
statusColor = Theme.getColor("buttons.status.color");
+ if (OSUtils.isMacOS()) {
+ editor.addWindowListener(new WindowAdapter() {
+ public void windowActivated(WindowEvent e) {
+ if (touchBar == null) {
+ buildTouchBar();
+
+ touchBar.show(editor);
+ }
+ }
+ });
+ }
+
addMouseListener(this);
addMouseMotionListener(this);
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this);
}
+
+ private void buildTouchBar() {
+ loadTouchBarImages();
+
+ touchBar = new JTouchBar();
+ touchBarButtons = new TouchBarButton[BUTTON_COUNT];
+ touchBar.setCustomizationIdentifier("Arduino");
+
+ for (int i = 0; i < BUTTON_COUNT; i++) {
+ final int selection = i;
+
+ // add spacers before NEW and SERIAL buttons
+ if (i == NEW) {
+ touchBar.addItem(new TouchBarItem(TouchBarItem.NSTouchBarItemIdentifierFixedSpaceSmall));
+ } else if (i == SERIAL) {
+ touchBar.addItem(new TouchBarItem(TouchBarItem.NSTouchBarItemIdentifierFlexibleSpace));
+ }
+
+ touchBarButtons[i] = new TouchBarButton();
+ touchBarButtons[i].setImage(touchBarImages[i][ROLLOVER]);
+ touchBarButtons[i].setAction(event -> handleSelectionPressed(selection));
+
+ touchBar.addItem(new TouchBarItem(title[i], touchBarButtons[i]));
+ }
+ }
private void loadButtons() {
Image allButtons = Theme.getThemeImage("buttons", this,
@@ -157,6 +210,36 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
}
}
}
+
+ private void loadTouchBarImages() {
+ Image allButtonsRetina = Theme.getThemeImage("buttons", this,
+ BUTTON_IMAGE_SIZE * BUTTON_COUNT * 2,
+ BUTTON_IMAGE_SIZE * 3 * 2);
+ touchBarImages = new com.thizzer.jtouchbar.common.Image[BUTTON_COUNT][3];
+
+ for (int i = 0; i < BUTTON_COUNT; i++) {
+ for (int state = 0; state < 3; state++) {
+ BufferedImage image = new BufferedImage(BUTTON_WIDTH * 2, BUTTON_HEIGHT * 2,
+ BufferedImage.TYPE_INT_ARGB);
+ Graphics g = image.getGraphics();
+
+ int offset = (BUTTON_IMAGE_SIZE * 2 - BUTTON_WIDTH * 2) / 2;
+ g.drawImage(allButtonsRetina, -(i * BUTTON_IMAGE_SIZE * 2) - offset,
+ (-2 + state) * BUTTON_IMAGE_SIZE * 2, null);
+
+ // convert the image to a PNG to display on the touch bar
+ ByteArrayOutputStream pngStream = new ByteArrayOutputStream();
+
+ try {
+ ImageIO.write(image, "PNG", pngStream);
+
+ touchBarImages[i][state] = new com.thizzer.jtouchbar.common.Image(pngStream.toByteArray());
+ } catch (IOException e) {
+ // ignore errors
+ }
+ }
+ }
+ }
@Override
public void paintComponent(Graphics screen) {
@@ -305,6 +388,15 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
if (updateAfter) {
repaint();
}
+
+ if (touchBarButtons != null) {
+ if (newState == INACTIVE) {
+ // use ROLLOVER state when INACTIVE
+ newState = ROLLOVER;
+ }
+
+ touchBarButtons[slot].setImage(touchBarImages[slot][newState]);
+ }
}
@@ -339,6 +431,20 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
if (sel == -1) return;
currentRollover = -1;
+ handleSelectionPressed(sel, e.isShiftDown(), x, y);
+ }
+
+ public void mouseClicked(MouseEvent e) {
+ }
+
+ public void mouseReleased(MouseEvent e) {
+ }
+
+ private void handleSelectionPressed(int sel) {
+ handleSelectionPressed(sel, false, 0, 0);
+ }
+
+ private void handleSelectionPressed(int sel, boolean isShiftDown, int x, int y) {
switch (sel) {
case RUN:
if (!editor.avoidMultipleOperations) {
@@ -347,10 +453,10 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
}
break;
-// case STOP:
-// editor.handleStop();
-// break;
-//
+// case STOP:
+// editor.handleStop();
+// break;
+//
case OPEN:
popup = menu.getPopupMenu();
popup.show(EditorToolbar.this, x, y);
@@ -365,7 +471,7 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
break;
case SAVE:
- if (e.isShiftDown()) {
+ if (isShiftDown) {
editor.handleSaveAs();
} else {
editor.handleSave(false);
@@ -375,7 +481,7 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
case EXPORT:
// launch a timeout timer which can reenable to upload button functionality an
if (!editor.avoidMultipleOperations) {
- editor.handleExport(e.isShiftDown());
+ editor.handleExport(isShiftDown);
}
break;
@@ -388,15 +494,6 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
}
}
-
- public void mouseClicked(MouseEvent e) {
- }
-
-
- public void mouseReleased(MouseEvent e) {
- }
-
-
/**
* Set a particular button to be active.
*/