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. */