mirror of
https://github.com/arduino/Arduino.git
synced 2025-02-21 15:54:39 +01:00
commit
d893aa0b65
@ -38,12 +38,14 @@ import org.fife.ui.rtextarea.Gutter;
|
|||||||
import org.fife.ui.rtextarea.RTextScrollPane;
|
import org.fife.ui.rtextarea.RTextScrollPane;
|
||||||
import processing.app.debug.RunnerException;
|
import processing.app.debug.RunnerException;
|
||||||
import processing.app.forms.PasswordAuthorizationDialog;
|
import processing.app.forms.PasswordAuthorizationDialog;
|
||||||
|
import processing.app.helpers.Keys;
|
||||||
import processing.app.helpers.OSUtils;
|
import processing.app.helpers.OSUtils;
|
||||||
import processing.app.helpers.PreferencesMapException;
|
import processing.app.helpers.PreferencesMapException;
|
||||||
import processing.app.legacy.PApplet;
|
import processing.app.legacy.PApplet;
|
||||||
import processing.app.syntax.ArduinoTokenMakerFactory;
|
import processing.app.syntax.ArduinoTokenMakerFactory;
|
||||||
import processing.app.syntax.PdeKeywords;
|
import processing.app.syntax.PdeKeywords;
|
||||||
import processing.app.syntax.SketchTextArea;
|
import processing.app.syntax.SketchTextArea;
|
||||||
|
import processing.app.syntax.SketchTextAreaEditorKit;
|
||||||
import processing.app.tools.DiscourseFormat;
|
import processing.app.tools.DiscourseFormat;
|
||||||
import processing.app.tools.MenuScroller;
|
import processing.app.tools.MenuScroller;
|
||||||
import processing.app.tools.Tool;
|
import processing.app.tools.Tool;
|
||||||
@ -312,6 +314,12 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
// to fix ugliness.. normally macosx java 1.3 puts an
|
// to fix ugliness.. normally macosx java 1.3 puts an
|
||||||
// ugly white border around this object, so turn it off.
|
// ugly white border around this object, so turn it off.
|
||||||
splitPane.setBorder(null);
|
splitPane.setBorder(null);
|
||||||
|
// By default, the split pane binds Ctrl-Tab and Ctrl-Shift-Tab for changing
|
||||||
|
// focus. Since we do not use that, but want to use these shortcuts for
|
||||||
|
// switching tabs, remove the bindings from the split pane. This allows the
|
||||||
|
// events to bubble up and be handled by the EditorHeader.
|
||||||
|
Keys.killBinding(splitPane, Keys.ctrl(KeyEvent.VK_TAB));
|
||||||
|
Keys.killBinding(splitPane, Keys.ctrlShift(KeyEvent.VK_TAB));
|
||||||
|
|
||||||
// the default size on windows is too small and kinda ugly
|
// the default size on windows is too small and kinda ugly
|
||||||
int dividerSize = PreferencesData.getInteger("editor.divider.size");
|
int dividerSize = PreferencesData.getInteger("editor.divider.size");
|
||||||
@ -1033,7 +1041,6 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
textArea.setAntiAliasingEnabled(PreferencesData.getBoolean("editor.antialias"));
|
textArea.setAntiAliasingEnabled(PreferencesData.getBoolean("editor.antialias"));
|
||||||
textArea.setTabsEmulated(PreferencesData.getBoolean("editor.tabs.expand"));
|
textArea.setTabsEmulated(PreferencesData.getBoolean("editor.tabs.expand"));
|
||||||
textArea.setTabSize(PreferencesData.getInteger("editor.tabs.size"));
|
textArea.setTabSize(PreferencesData.getInteger("editor.tabs.size"));
|
||||||
textArea.setEditorListener(new EditorListener(this));
|
|
||||||
textArea.addHyperlinkListener(new HyperlinkListener() {
|
textArea.addHyperlinkListener(new HyperlinkListener() {
|
||||||
@Override
|
@Override
|
||||||
public void hyperlinkUpdate(HyperlinkEvent hyperlinkEvent) {
|
public void hyperlinkUpdate(HyperlinkEvent hyperlinkEvent) {
|
||||||
@ -1866,28 +1873,8 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
|
|
||||||
private void handleIndentOutdent(boolean indent) {
|
private void handleIndentOutdent(boolean indent) {
|
||||||
if (indent) {
|
if (indent) {
|
||||||
|
Action action = textarea.getActionMap().get(SketchTextAreaEditorKit.rtaIncreaseIndentAction);
|
||||||
int caretPosition = textarea.getCaretPosition();
|
|
||||||
boolean noSelec = !textarea.isSelectionActive();
|
|
||||||
|
|
||||||
// if no selection, focus on first char.
|
|
||||||
if (noSelec) {
|
|
||||||
try {
|
|
||||||
int line = textarea.getCaretLineNumber();
|
|
||||||
int startOffset = textarea.getLineStartOffset(line);
|
|
||||||
textarea.setCaretPosition(startOffset);
|
|
||||||
} catch (BadLocationException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert Tab or Spaces..
|
|
||||||
Action action = textarea.getActionMap().get(RSyntaxTextAreaEditorKit.insertTabAction);
|
|
||||||
action.actionPerformed(null);
|
action.actionPerformed(null);
|
||||||
|
|
||||||
if (noSelec) {
|
|
||||||
textarea.setCaretPosition(caretPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Action action = textarea.getActionMap().get(RSyntaxTextAreaEditorKit.rstaDecreaseIndentAction);
|
Action action = textarea.getActionMap().get(RSyntaxTextAreaEditorKit.rstaDecreaseIndentAction);
|
||||||
action.actionPerformed(null);
|
action.actionPerformed(null);
|
||||||
|
@ -63,6 +63,7 @@ public class EditorConsole extends JScrollPane {
|
|||||||
consoleTextPane.setEditable(false);
|
consoleTextPane.setEditable(false);
|
||||||
DefaultCaret caret = (DefaultCaret) consoleTextPane.getCaret();
|
DefaultCaret caret = (DefaultCaret) consoleTextPane.getCaret();
|
||||||
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
|
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
|
||||||
|
consoleTextPane.setFocusTraversalKeysEnabled(false);
|
||||||
|
|
||||||
Color backgroundColour = Theme.getColor("console.color");
|
Color backgroundColour = Theme.getColor("console.color");
|
||||||
consoleTextPane.setBackground(backgroundColour);
|
consoleTextPane.setBackground(backgroundColour);
|
||||||
|
@ -22,7 +22,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
package processing.app;
|
package processing.app;
|
||||||
|
|
||||||
|
import processing.app.helpers.Keys;
|
||||||
import processing.app.helpers.OSUtils;
|
import processing.app.helpers.OSUtils;
|
||||||
|
import processing.app.helpers.SimpleAction;
|
||||||
import processing.app.tools.MenuScroller;
|
import processing.app.tools.MenuScroller;
|
||||||
import static processing.app.I18n.tr;
|
import static processing.app.I18n.tr;
|
||||||
|
|
||||||
@ -72,12 +75,69 @@ public class EditorHeader extends JComponent {
|
|||||||
|
|
||||||
static Image[][] pieces;
|
static Image[][] pieces;
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
Image offscreen;
|
Image offscreen;
|
||||||
int sizeW, sizeH;
|
int sizeW, sizeH;
|
||||||
int imageW, imageH;
|
int imageW, imageH;
|
||||||
|
|
||||||
|
public class Actions {
|
||||||
|
public final Action newTab = new SimpleAction(tr("New Tab"),
|
||||||
|
Keys.ctrlShift(KeyEvent.VK_N),
|
||||||
|
() -> editor.getSketch().handleNewCode());
|
||||||
|
|
||||||
|
public final Action renameTab = new SimpleAction(tr("Rename"),
|
||||||
|
() -> editor.getSketch().handleRenameCode());
|
||||||
|
|
||||||
|
public final Action deleteTab = new SimpleAction(tr("Delete"), () -> {
|
||||||
|
try {
|
||||||
|
editor.getSketch().handleDeleteCode();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public final Action prevTab = new SimpleAction(tr("Previous Tab"),
|
||||||
|
Keys.ctrlAlt(KeyEvent.VK_LEFT),
|
||||||
|
() -> editor.sketch.handlePrevCode());
|
||||||
|
|
||||||
|
public final Action nextTab = new SimpleAction(tr("Next Tab"),
|
||||||
|
Keys.ctrlAlt(KeyEvent.VK_RIGHT),
|
||||||
|
() -> editor.sketch.handleNextCode());
|
||||||
|
|
||||||
|
Actions() {
|
||||||
|
// Explicitly bind keybindings for the actions with accelerators above
|
||||||
|
// Normally, this happens automatically for any actions bound to menu
|
||||||
|
// items, but only for menus attached to a window, not for popup menus.
|
||||||
|
Keys.bind(EditorHeader.this, newTab);
|
||||||
|
Keys.bind(EditorHeader.this, prevTab);
|
||||||
|
Keys.bind(EditorHeader.this, nextTab);
|
||||||
|
|
||||||
|
// Add alternative keybindings to switch tabs
|
||||||
|
Keys.bind(EditorHeader.this, prevTab, Keys.ctrlShift(KeyEvent.VK_TAB));
|
||||||
|
Keys.bind(EditorHeader.this, nextTab, Keys.ctrl(KeyEvent.VK_TAB));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Actions actions = new Actions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called whenever we, or any of our ancestors, is added to a container.
|
||||||
|
*/
|
||||||
|
public void addNotify() {
|
||||||
|
super.addNotify();
|
||||||
|
/*
|
||||||
|
* Once we get added to a window, remove Ctrl-Tab and Ctrl-Shift-Tab from
|
||||||
|
* the keys used for focus traversal (so our bindings for these keys will
|
||||||
|
* work). All components inherit from the window eventually, so this should
|
||||||
|
* work whenever the focus is inside our window. Some components (notably
|
||||||
|
* JTextPane / JEditorPane) keep their own focus traversal keys, though, and
|
||||||
|
* have to be treated individually (either the same as below, or by
|
||||||
|
* disabling focus traversal entirely).
|
||||||
|
*/
|
||||||
|
Window window = SwingUtilities.getWindowAncestor(this);
|
||||||
|
if (window != null) {
|
||||||
|
Keys.killFocusTraversalBinding(window, Keys.ctrl(KeyEvent.VK_TAB));
|
||||||
|
Keys.killFocusTraversalBinding(window, Keys.ctrlShift(KeyEvent.VK_TAB));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public EditorHeader(Editor eddie) {
|
public EditorHeader(Editor eddie) {
|
||||||
this.editor = eddie; // weird name for listener
|
this.editor = eddie; // weird name for listener
|
||||||
@ -236,7 +296,6 @@ public class EditorHeader extends JComponent {
|
|||||||
|
|
||||||
|
|
||||||
public void rebuildMenu() {
|
public void rebuildMenu() {
|
||||||
//System.out.println("rebuilding");
|
|
||||||
if (menu != null) {
|
if (menu != null) {
|
||||||
menu.removeAll();
|
menu.removeAll();
|
||||||
|
|
||||||
@ -244,143 +303,34 @@ public class EditorHeader extends JComponent {
|
|||||||
menu = new JMenu();
|
menu = new JMenu();
|
||||||
MenuScroller.setScrollerFor(menu);
|
MenuScroller.setScrollerFor(menu);
|
||||||
popup = menu.getPopupMenu();
|
popup = menu.getPopupMenu();
|
||||||
add(popup);
|
|
||||||
popup.setLightWeightPopupEnabled(true);
|
popup.setLightWeightPopupEnabled(true);
|
||||||
|
|
||||||
/*
|
|
||||||
popup.addPopupMenuListener(new PopupMenuListener() {
|
|
||||||
public void popupMenuCanceled(PopupMenuEvent e) {
|
|
||||||
// on redraw, the isVisible() will get checked.
|
|
||||||
// actually, a repaint may be fired anyway, so this
|
|
||||||
// may be redundant.
|
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { }
|
|
||||||
public void popupMenuWillBecomeVisible(PopupMenuEvent e) { }
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
JMenuItem item;
|
JMenuItem item;
|
||||||
|
|
||||||
// maybe this shouldn't have a command key anyways..
|
menu.add(new JMenuItem(actions.newTab));
|
||||||
// since we're not trying to make this a full ide..
|
menu.add(new JMenuItem(actions.renameTab));
|
||||||
//item = Editor.newJMenuItem("New", 'T');
|
menu.add(new JMenuItem(actions.deleteTab));
|
||||||
|
|
||||||
/*
|
|
||||||
item = Editor.newJMenuItem("Previous", KeyEvent.VK_PAGE_UP);
|
|
||||||
item.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
System.out.println("prev");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (editor.sketch != null) {
|
|
||||||
item.setEnabled(editor.sketch.codeCount > 1);
|
|
||||||
}
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
item = Editor.newJMenuItem("Next", KeyEvent.VK_PAGE_DOWN);
|
|
||||||
item.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
System.out.println("ext");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (editor.sketch != null) {
|
|
||||||
item.setEnabled(editor.sketch.codeCount > 1);
|
|
||||||
}
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
*/
|
menu.add(new JMenuItem(actions.prevTab));
|
||||||
|
menu.add(new JMenuItem(actions.nextTab));
|
||||||
//item = new JMenuItem("New Tab");
|
|
||||||
item = Editor.newJMenuItemShift(tr("New Tab"), 'N');
|
|
||||||
item.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
editor.getSketch().handleNewCode();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
item = new JMenuItem(tr("Rename"));
|
|
||||||
item.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
editor.getSketch().handleRenameCode();
|
|
||||||
/*
|
|
||||||
// this is already being called by nameCode(), the second stage of rename
|
|
||||||
if (editor.sketch.current == editor.sketch.code[0]) {
|
|
||||||
editor.sketchbook.rebuildMenus();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
item = new JMenuItem(tr("Delete"));
|
|
||||||
item.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent event) {
|
|
||||||
try {
|
|
||||||
editor.getSketch().handleDeleteCode();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
menu.addSeparator();
|
|
||||||
|
|
||||||
// KeyEvent.VK_LEFT and VK_RIGHT will make Windows beep
|
|
||||||
|
|
||||||
item = new JMenuItem(tr("Previous Tab"));
|
|
||||||
KeyStroke ctrlAltLeft = KeyStroke
|
|
||||||
.getKeyStroke(KeyEvent.VK_LEFT, Editor.SHORTCUT_ALT_KEY_MASK);
|
|
||||||
item.setAccelerator(ctrlAltLeft);
|
|
||||||
item.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
editor.sketch.handlePrevCode();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
item = new JMenuItem(tr("Next Tab"));
|
|
||||||
KeyStroke ctrlAltRight = KeyStroke
|
|
||||||
.getKeyStroke(KeyEvent.VK_RIGHT, Editor.SHORTCUT_ALT_KEY_MASK);
|
|
||||||
item.setAccelerator(ctrlAltRight);
|
|
||||||
item.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
editor.sketch.handleNextCode();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
Sketch sketch = editor.getSketch();
|
Sketch sketch = editor.getSketch();
|
||||||
if (sketch != null) {
|
if (sketch != null) {
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
int i = 0;
|
||||||
ActionListener jumpListener = new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
editor.getSketch().setCurrentCode(e.getActionCommand());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
for (SketchCode code : sketch.getCodes()) {
|
for (SketchCode code : sketch.getCodes()) {
|
||||||
|
final int index = i++;
|
||||||
item = new JMenuItem(code.isExtension(sketch.getDefaultExtension()) ?
|
item = new JMenuItem(code.isExtension(sketch.getDefaultExtension()) ?
|
||||||
code.getPrettyName() : code.getFileName());
|
code.getPrettyName() : code.getFileName());
|
||||||
item.setActionCommand(code.getFileName());
|
item.addActionListener((ActionEvent e) -> {
|
||||||
item.addActionListener(jumpListener);
|
editor.getSketch().setCurrentCode(index);
|
||||||
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void deselectMenu() {
|
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Dimension getPreferredSize() {
|
public Dimension getPreferredSize() {
|
||||||
return getMinimumSize();
|
return getMinimumSize();
|
||||||
}
|
}
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
package processing.app;
|
|
||||||
|
|
||||||
import java.awt.Toolkit;
|
|
||||||
import java.awt.event.InputEvent;
|
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
import java.awt.event.KeyListener;
|
|
||||||
|
|
||||||
import processing.app.syntax.SketchTextArea;
|
|
||||||
|
|
||||||
public class EditorListener implements KeyListener {
|
|
||||||
|
|
||||||
private Editor editor;
|
|
||||||
|
|
||||||
public EditorListener(Editor editor) {
|
|
||||||
super();
|
|
||||||
this.editor = editor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** ctrl-alt on windows and linux, cmd-alt on mac os x */
|
|
||||||
private static final int CTRL = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
|
|
||||||
private static final int CTRL_ALT = InputEvent.ALT_MASK | CTRL;
|
|
||||||
private static final int CTRL_SHIFT = InputEvent.SHIFT_MASK | CTRL;
|
|
||||||
|
|
||||||
public void keyTyped(KeyEvent event) {
|
|
||||||
char c = event.getKeyChar();
|
|
||||||
|
|
||||||
if ((event.getModifiers() & KeyEvent.CTRL_MASK) != 0) {
|
|
||||||
// The char is not control code when CTRL key pressed? It should be a shortcut.
|
|
||||||
if (!Character.isISOControl(c)) {
|
|
||||||
event.consume();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void keyPressed(KeyEvent event) {
|
|
||||||
|
|
||||||
SketchTextArea textarea = editor.getTextArea();
|
|
||||||
|
|
||||||
if (!textarea.isEditable()) return;
|
|
||||||
|
|
||||||
Sketch sketch = editor.getSketch();
|
|
||||||
|
|
||||||
int code = event.getKeyCode();
|
|
||||||
|
|
||||||
// Navigation..
|
|
||||||
if ((event.getModifiers() & CTRL) == CTRL && code == KeyEvent.VK_TAB) {
|
|
||||||
sketch.handleNextCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Navigation..
|
|
||||||
// FIXME: not working on LINUX !!!
|
|
||||||
if ((event.getModifiers() & CTRL_SHIFT) == CTRL_SHIFT && code == KeyEvent.VK_TAB) {
|
|
||||||
sketch.handlePrevCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Navigation..
|
|
||||||
if ((event.getModifiers() & CTRL_ALT) == CTRL_ALT) {
|
|
||||||
if (code == KeyEvent.VK_LEFT) {
|
|
||||||
sketch.handlePrevCode();
|
|
||||||
} else if (code == KeyEvent.VK_RIGHT) {
|
|
||||||
sketch.handleNextCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (event.isAltDown() && code == KeyEvent.VK_T) {
|
|
||||||
// int line = textarea.getCaretLineNumber();
|
|
||||||
// textarea.setActiveLineRange(line, line + 3);
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void keyReleased(KeyEvent e) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
233
app/src/processing/app/helpers/Keys.java
Normal file
233
app/src/processing/app/helpers/Keys.java
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Arduino.
|
||||||
|
*
|
||||||
|
* Copyright 2015 Matthijs Kooijman <matthijs@stdin.nl>
|
||||||
|
*
|
||||||
|
* Arduino is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* As a special exception, you may use this file as part of a free software
|
||||||
|
* library without restriction. Specifically, if other files instantiate
|
||||||
|
* templates or use macros or inline functions from this file, or you compile
|
||||||
|
* this file and link it with other files to produce an executable, this
|
||||||
|
* file does not by itself cause the resulting executable to be covered by
|
||||||
|
* the GNU General Public License. This exception does not however
|
||||||
|
* invalidate any other reasons why the executable file might be covered by
|
||||||
|
* the GNU General Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package processing.app.helpers;
|
||||||
|
|
||||||
|
import java.awt.AWTKeyStroke;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.KeyboardFocusManager;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.event.InputEvent;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.swing.Action;
|
||||||
|
import javax.swing.InputMap;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.KeyStroke;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class contains some keybinding-related helper methods.
|
||||||
|
*/
|
||||||
|
public class Keys {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a keybinding in the given components WHEN_IN_FOCUSED_WINDOW input
|
||||||
|
* map, runing the given action when the action's accelerator key is pressed.
|
||||||
|
*
|
||||||
|
* Note that this is typically automatically handled when the action is
|
||||||
|
* assigned to a JMenuItem, but it can still be needed for other actions, or
|
||||||
|
* actions mapped to JMenuItems in a popup menu that is not added to any
|
||||||
|
* window normally (and thus does not fire when the popup is closed).
|
||||||
|
*
|
||||||
|
* When the action is disabled, the keybinding is unregistered, and when it is
|
||||||
|
* enabled, it is registered again.
|
||||||
|
*/
|
||||||
|
public static void bind(final JComponent component, final Action action) {
|
||||||
|
bind(component, action,
|
||||||
|
(KeyStroke) action.getValue(Action.ACCELERATOR_KEY));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a keybinding, running the given action when the given keystroke is
|
||||||
|
* pressed when the given component is in the focused window.
|
||||||
|
*
|
||||||
|
* This is typically used to bind an additional keystroke to a menu item, in
|
||||||
|
* addition to the primary accelerator key.
|
||||||
|
*
|
||||||
|
* When the action is disabled, the keybinding is unregistered, and when it is
|
||||||
|
* enabled, it is registered again.
|
||||||
|
*/
|
||||||
|
public static void bind(final JComponent component, final Action action,
|
||||||
|
KeyStroke keystroke) {
|
||||||
|
bind(component, action, keystroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a keybinding to be handled in given condition, running the given
|
||||||
|
* action when the given keystroke is pressed.
|
||||||
|
*
|
||||||
|
* When the action is disabled, the keybinding is unregistered, and when it is
|
||||||
|
* enabled, it is registered again.
|
||||||
|
*
|
||||||
|
* @param component
|
||||||
|
* The component to register the keybinding on.
|
||||||
|
* @param action
|
||||||
|
* The action to run when the keystroke is pressed
|
||||||
|
* @param action
|
||||||
|
* The keystroke to bind
|
||||||
|
* @param condition
|
||||||
|
* The condition under which to run the keystroke. Should be one of
|
||||||
|
* JComponent.WHEN_FOCUSED,
|
||||||
|
* JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT or
|
||||||
|
* JComponent.WHEN_IN_FOCUSED_WINDOW.
|
||||||
|
*/
|
||||||
|
public static void bind(final JComponent component, final Action action,
|
||||||
|
KeyStroke keystroke, int condition) {
|
||||||
|
// The input map maps keystrokes to arbitrary objects (originally strings
|
||||||
|
// that described the option, we just use the Action object itself).
|
||||||
|
if (action.isEnabled())
|
||||||
|
enableBind(component, action, keystroke, condition);
|
||||||
|
|
||||||
|
// The action map maps the arbitrary option to an Action to execute. These
|
||||||
|
// be kept in the component even when the action is disabled.
|
||||||
|
component.getActionMap().put(action, action);
|
||||||
|
|
||||||
|
// Enable and disable the binding when the action is enabled / disabled.
|
||||||
|
action.addPropertyChangeListener((PropertyChangeEvent e) -> {
|
||||||
|
if (e.getPropertyName().equals("enabled")) {
|
||||||
|
if (e.getNewValue().equals(Boolean.TRUE))
|
||||||
|
enableBind(component, action, keystroke, condition);
|
||||||
|
else
|
||||||
|
disableBind(component, action, keystroke, condition);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kill an existing binding from the given condition. If the binding is
|
||||||
|
* defined on the given component, it is removed, but if it is defined through
|
||||||
|
* a parent inputmap (typically shared by multiple components, so best not
|
||||||
|
* touched), this adds a dummy binding for this component, that will never
|
||||||
|
* match an action in the component's action map, effectively disabling the
|
||||||
|
* binding.
|
||||||
|
*
|
||||||
|
* This method is not intended to unbind a binding created by bind(), since
|
||||||
|
* such a binding would get re-enabled when the action is re-enabled.
|
||||||
|
*/
|
||||||
|
public static void killBinding(final JComponent component,
|
||||||
|
final KeyStroke keystroke, int condition) {
|
||||||
|
InputMap map = component.getInputMap(condition);
|
||||||
|
// First, try removing it
|
||||||
|
map.remove(keystroke);
|
||||||
|
// If the binding is defined in a parent map, defining it will not work, so
|
||||||
|
// instead add an override that will never appear in the action map.
|
||||||
|
if (map.get(keystroke) != null)
|
||||||
|
map.put(keystroke, new Object());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kill an existing binding like above, but from all three conditions
|
||||||
|
* (WHEN_FOCUSED, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, WHEN_IN_FOCUSED_WINDOW).
|
||||||
|
*/
|
||||||
|
public static void killBinding(final JComponent component,
|
||||||
|
final KeyStroke key) {
|
||||||
|
killBinding(component, key, JComponent.WHEN_FOCUSED);
|
||||||
|
killBinding(component, key, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
|
||||||
|
killBinding(component, key, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a keystroke from the keys used to shift focus in or below the given
|
||||||
|
* component. This modifies all sets of focus traversal keys on the given
|
||||||
|
* component to remove the given keystroke. These sets are inherited down the
|
||||||
|
* component hierarchy (until a component that has a custom set itself).
|
||||||
|
*/
|
||||||
|
public static void killFocusTraversalBinding(final Component component,
|
||||||
|
final KeyStroke keystroke) {
|
||||||
|
int[] sets = { KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
|
||||||
|
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
|
||||||
|
KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
|
||||||
|
KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS };
|
||||||
|
for (int set : sets) {
|
||||||
|
Set<AWTKeyStroke> keys = component.getFocusTraversalKeys(set);
|
||||||
|
// keys is immutable, so create a new set to allow changes
|
||||||
|
keys = new HashSet<>(keys);
|
||||||
|
if (set == 0)
|
||||||
|
keys.add(ctrlAlt('Z'));
|
||||||
|
|
||||||
|
// If the given keystroke was present in the set, replace it with the
|
||||||
|
// updated set with the keystroke removed.
|
||||||
|
if (keys.remove(keystroke))
|
||||||
|
component.setFocusTraversalKeys(set, keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void enableBind(final JComponent component,
|
||||||
|
final Action action, final KeyStroke keystroke,
|
||||||
|
int condition) {
|
||||||
|
component.getInputMap(condition).put(keystroke, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void disableBind(final JComponent component,
|
||||||
|
final Action action,
|
||||||
|
final KeyStroke keystroke, int condition) {
|
||||||
|
component.getInputMap(condition).put(keystroke, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int CTRL = Toolkit.getDefaultToolkit()
|
||||||
|
.getMenuShortcutKeyMask();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a KeyCode for the "menu shortcut" + the key passed in. By default,
|
||||||
|
* the menu shortcut is the ctrl key (hence the method name), but platforms
|
||||||
|
* might use a different key (like the Apple key on OSX).
|
||||||
|
*
|
||||||
|
* keyCode should be a KeyEvent.VK_* constant (it can also be a char constant,
|
||||||
|
* but this does not work for all characters, so is not recommended).
|
||||||
|
*/
|
||||||
|
public static KeyStroke ctrl(int keyCode) {
|
||||||
|
return KeyStroke.getKeyStroke(keyCode, CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a KeyCode for the "menu shortcut" + shift + the key passed in. By
|
||||||
|
* default, the menu shortcut is the ctrl key (hence the method name), but
|
||||||
|
* platforms might use a different key (like the Apple key on OSX).
|
||||||
|
*
|
||||||
|
* keyCode should be a KeyEvent.VK_* constant (it can also be a char constant,
|
||||||
|
* but this does not work for all characters, so is not recommended).
|
||||||
|
*/
|
||||||
|
public static KeyStroke ctrlShift(int keyCode) {
|
||||||
|
return KeyStroke.getKeyStroke(keyCode, CTRL | InputEvent.SHIFT_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a KeyCode for the "menu shortcut" + shift + the key passed in. By
|
||||||
|
* default, the menu shortcut is the ctrl key (hence the method name), but
|
||||||
|
* platforms might use a different key (like the Apple key on OSX).
|
||||||
|
*
|
||||||
|
* keyCode should be a KeyEvent.VK_* constant (it can also be a char constant,
|
||||||
|
* but this does not work for all characters, so is not recommended).
|
||||||
|
*/
|
||||||
|
public static KeyStroke ctrlAlt(int keyCode) {
|
||||||
|
return KeyStroke.getKeyStroke(keyCode, CTRL | InputEvent.ALT_MASK);
|
||||||
|
}
|
||||||
|
}
|
112
app/src/processing/app/helpers/SimpleAction.java
Normal file
112
app/src/processing/app/helpers/SimpleAction.java
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Arduino.
|
||||||
|
*
|
||||||
|
* Copyright 2015 Matthijs Kooijman <matthijs@stdin.nl>
|
||||||
|
*
|
||||||
|
* Arduino is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* As a special exception, you may use this file as part of a free software
|
||||||
|
* library without restriction. Specifically, if other files instantiate
|
||||||
|
* templates or use macros or inline functions from this file, or you compile
|
||||||
|
* this file and link it with other files to produce an executable, this
|
||||||
|
* file does not by itself cause the resulting executable to be covered by
|
||||||
|
* the GNU General Public License. This exception does not however
|
||||||
|
* invalidate any other reasons why the executable file might be covered by
|
||||||
|
* the GNU General Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package processing.app.helpers;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
import javax.swing.AbstractAction;
|
||||||
|
import javax.swing.KeyStroke;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to easily define instances of the Swing Action interface.
|
||||||
|
*
|
||||||
|
* When using AbstractAction, you have to create a subclass that implements the
|
||||||
|
* actionPerformed() method, and sets attributes in the constructor, which gets
|
||||||
|
* verbose quickly. This class implements actionPerformed for you, and forwards
|
||||||
|
* it to the ActionListener passed to the constructor (intended to be a lambda
|
||||||
|
* expression). Additional Action attributes can be set by passing constructor
|
||||||
|
* arguments.
|
||||||
|
*
|
||||||
|
* The name of this class refers to the fact that it's simple to create an
|
||||||
|
* action using this class, but perhaps a better name can be found for it.
|
||||||
|
*
|
||||||
|
* @see javax.swing.Action
|
||||||
|
*/
|
||||||
|
public class SimpleAction extends AbstractAction {
|
||||||
|
private ActionListener listener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version of ActionListener that does not take an ActionEvent as an argument
|
||||||
|
* This can be used when you do not care about the event itself, just that it
|
||||||
|
* happened, typically for passing a argumentless lambda or method reference
|
||||||
|
* to the SimpleAction constructor.
|
||||||
|
*/
|
||||||
|
public interface AnonymousActionListener {
|
||||||
|
public void actionPerformed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleAction(String name, ActionListener listener) {
|
||||||
|
this(name, null, null, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleAction(String name, AnonymousActionListener listener) {
|
||||||
|
this(name, null, null, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleAction(String name, KeyStroke accelerator,
|
||||||
|
ActionListener listener) {
|
||||||
|
this(name, null, accelerator, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleAction(String name, KeyStroke accelerator,
|
||||||
|
AnonymousActionListener listener) {
|
||||||
|
this(name, null, accelerator, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleAction(String name, String description,
|
||||||
|
ActionListener listener) {
|
||||||
|
this(name, description, null, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleAction(String name, String description,
|
||||||
|
AnonymousActionListener listener) {
|
||||||
|
this(name, description, null, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleAction(String name, String description, KeyStroke accelerator,
|
||||||
|
AnonymousActionListener listener) {
|
||||||
|
this(name, description, accelerator,
|
||||||
|
(ActionEvent) -> listener.actionPerformed());
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleAction(String name, String description, KeyStroke accelerator,
|
||||||
|
ActionListener listener) {
|
||||||
|
this.putValue(NAME, name);
|
||||||
|
this.putValue(SHORT_DESCRIPTION, description);
|
||||||
|
this.putValue(ACCELERATOR_KEY, accelerator);
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
listener.actionPerformed(e);
|
||||||
|
}
|
||||||
|
}
|
@ -38,10 +38,8 @@ import org.fife.ui.rtextarea.RTextAreaUI;
|
|||||||
import org.fife.ui.rtextarea.RUndoManager;
|
import org.fife.ui.rtextarea.RUndoManager;
|
||||||
import processing.app.Base;
|
import processing.app.Base;
|
||||||
import processing.app.BaseNoGui;
|
import processing.app.BaseNoGui;
|
||||||
import processing.app.EditorListener;
|
|
||||||
import processing.app.PreferencesData;
|
import processing.app.PreferencesData;
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import javax.swing.event.EventListenerList;
|
import javax.swing.event.EventListenerList;
|
||||||
import javax.swing.event.HyperlinkEvent;
|
import javax.swing.event.HyperlinkEvent;
|
||||||
import javax.swing.event.HyperlinkListener;
|
import javax.swing.event.HyperlinkListener;
|
||||||
@ -50,16 +48,13 @@ import javax.swing.text.Document;
|
|||||||
import javax.swing.text.Segment;
|
import javax.swing.text.Segment;
|
||||||
import javax.swing.undo.UndoManager;
|
import javax.swing.undo.UndoManager;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,8 +67,6 @@ public class SketchTextArea extends RSyntaxTextArea {
|
|||||||
|
|
||||||
private final static Logger LOG = Logger.getLogger(SketchTextArea.class.getName());
|
private final static Logger LOG = Logger.getLogger(SketchTextArea.class.getName());
|
||||||
|
|
||||||
private EditorListener editorListener;
|
|
||||||
|
|
||||||
private PdeKeywords pdeKeywords;
|
private PdeKeywords pdeKeywords;
|
||||||
|
|
||||||
public SketchTextArea(PdeKeywords pdeKeywords) throws IOException {
|
public SketchTextArea(PdeKeywords pdeKeywords) throws IOException {
|
||||||
@ -91,8 +84,6 @@ public class SketchTextArea extends RSyntaxTextArea {
|
|||||||
|
|
||||||
setLinkGenerator(new DocLinkGenerator(pdeKeywords));
|
setLinkGenerator(new DocLinkGenerator(pdeKeywords));
|
||||||
|
|
||||||
fixControlTab();
|
|
||||||
|
|
||||||
setSyntaxEditingStyle(SYNTAX_STYLE_CPLUSPLUS);
|
setSyntaxEditingStyle(SYNTAX_STYLE_CPLUSPLUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,53 +144,10 @@ public class SketchTextArea extends RSyntaxTextArea {
|
|||||||
getSyntaxScheme().setStyle(tokenType, style);
|
getSyntaxScheme().setStyle(tokenType, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removing the default focus traversal keys
|
|
||||||
// This is because the DefaultKeyboardFocusManager handles the keypress and consumes the event
|
|
||||||
private void fixControlTab() {
|
|
||||||
removeCTRLTabFromFocusTraversal();
|
|
||||||
|
|
||||||
removeCTRLSHIFTTabFromFocusTraversal();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeCTRLSHIFTTabFromFocusTraversal() {
|
|
||||||
KeyStroke ctrlShiftTab = KeyStroke.getKeyStroke("ctrl shift TAB");
|
|
||||||
Set<AWTKeyStroke> backwardKeys = new HashSet<>(this.getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));
|
|
||||||
backwardKeys.remove(ctrlShiftTab);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeCTRLTabFromFocusTraversal() {
|
|
||||||
KeyStroke ctrlTab = KeyStroke.getKeyStroke("ctrl TAB");
|
|
||||||
Set<AWTKeyStroke> forwardKeys = new HashSet<>(this.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
|
|
||||||
forwardKeys.remove(ctrlTab);
|
|
||||||
this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, forwardKeys);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean isSelectionActive() {
|
public boolean isSelectionActive() {
|
||||||
return this.getSelectedText() != null;
|
return this.getSelectedText() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processKeyEvent(KeyEvent evt) {
|
|
||||||
|
|
||||||
// this had to be added because the menu key events weren't making it up to the frame.
|
|
||||||
|
|
||||||
switch (evt.getID()) {
|
|
||||||
case KeyEvent.KEY_TYPED:
|
|
||||||
if (editorListener != null) editorListener.keyTyped(evt);
|
|
||||||
break;
|
|
||||||
case KeyEvent.KEY_PRESSED:
|
|
||||||
if (editorListener != null) editorListener.keyPressed(evt);
|
|
||||||
break;
|
|
||||||
case KeyEvent.KEY_RELEASED:
|
|
||||||
// inputHandler.keyReleased(evt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!evt.isConsumed()) {
|
|
||||||
super.processKeyEvent(evt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void switchDocument(Document document, UndoManager newUndo) {
|
public void switchDocument(Document document, UndoManager newUndo) {
|
||||||
|
|
||||||
// HACK: Dont discard changes on curret UndoManager.
|
// HACK: Dont discard changes on curret UndoManager.
|
||||||
@ -233,11 +181,6 @@ public class SketchTextArea extends RSyntaxTextArea {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setEditorListener(EditorListener editorListener) {
|
|
||||||
this.editorListener = editorListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class DocLinkGenerator implements LinkGenerator {
|
private static class DocLinkGenerator implements LinkGenerator {
|
||||||
|
|
||||||
private final PdeKeywords pdeKeywords;
|
private final PdeKeywords pdeKeywords;
|
||||||
|
@ -23,6 +23,15 @@ public class SketchTextAreaDefaultInputMap extends RSyntaxTextAreaDefaultInputMa
|
|||||||
|
|
||||||
remove(KeyStroke.getKeyStroke(KeyEvent.VK_K, defaultModifier));
|
remove(KeyStroke.getKeyStroke(KeyEvent.VK_K, defaultModifier));
|
||||||
|
|
||||||
|
// Remove a troublesome binding for the / key. By default, RSyntaxTextArea
|
||||||
|
// binds the / KEY_TYPED event to insert a / and optionally complete any XML
|
||||||
|
// tags. However, since this also triggeres on ctrl-slash, this means that
|
||||||
|
// in addition to toggling comments on ctrl-slash, it also inserts a slash.
|
||||||
|
// Since we don't need the XML completion feature anyway, just unbind it
|
||||||
|
// here. A future version of RSyntaxTextArea might fix this, see
|
||||||
|
// https://github.com/bobbylight/RSyntaxTextArea/issues/157.
|
||||||
|
remove(KeyStroke.getKeyStroke('/'));
|
||||||
|
|
||||||
if (PreferencesData.getBoolean("editor.advanced")) {
|
if (PreferencesData.getBoolean("editor.advanced")) {
|
||||||
put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, alt), RTextAreaEditorKit.rtaLineDownAction);
|
put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, alt), RTextAreaEditorKit.rtaLineDownAction);
|
||||||
put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, alt), RTextAreaEditorKit.rtaLineUpAction);
|
put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, alt), RTextAreaEditorKit.rtaLineUpAction);
|
||||||
@ -45,8 +54,8 @@ public class SketchTextAreaDefaultInputMap extends RSyntaxTextAreaDefaultInputMa
|
|||||||
|
|
||||||
remove(KeyStroke.getKeyStroke(KeyEvent.VK_J, defaultModifier));
|
remove(KeyStroke.getKeyStroke(KeyEvent.VK_J, defaultModifier));
|
||||||
|
|
||||||
put(KeyStroke.getKeyStroke(KeyEvent.VK_OPEN_BRACKET, defaultModifier), DefaultEditorKit.insertTabAction);
|
put(KeyStroke.getKeyStroke(KeyEvent.VK_OPEN_BRACKET, defaultModifier), RSyntaxTextAreaEditorKit.rstaDecreaseIndentAction);
|
||||||
put(KeyStroke.getKeyStroke(KeyEvent.VK_CLOSE_BRACKET, defaultModifier), RSyntaxTextAreaEditorKit.rstaDecreaseIndentAction);
|
put(KeyStroke.getKeyStroke(KeyEvent.VK_CLOSE_BRACKET, defaultModifier), SketchTextAreaEditorKit.rtaIncreaseIndentAction);
|
||||||
|
|
||||||
put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, defaultModifier | shift), DefaultEditorKit.selectionBeginAction);
|
put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, defaultModifier | shift), DefaultEditorKit.selectionBeginAction);
|
||||||
put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, defaultModifier | shift), DefaultEditorKit.selectionEndAction);
|
put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, defaultModifier | shift), DefaultEditorKit.selectionEndAction);
|
||||||
|
@ -13,10 +13,12 @@ public class SketchTextAreaEditorKit extends RSyntaxTextAreaEditorKit {
|
|||||||
|
|
||||||
public static final String rtaDeleteNextWordAction = "RTA.DeleteNextWordAction";
|
public static final String rtaDeleteNextWordAction = "RTA.DeleteNextWordAction";
|
||||||
public static final String rtaDeleteLineToCursorAction = "RTA.DeleteLineToCursorAction";
|
public static final String rtaDeleteLineToCursorAction = "RTA.DeleteLineToCursorAction";
|
||||||
|
public static final String rtaIncreaseIndentAction = "RTA.IncreaseIndentAction";
|
||||||
|
|
||||||
private static final Action[] defaultActions = {
|
private static final Action[] defaultActions = {
|
||||||
new DeleteNextWordAction(),
|
new DeleteNextWordAction(),
|
||||||
new DeleteLineToCursorAction(),
|
new DeleteLineToCursorAction(),
|
||||||
|
new IncreaseIndentAction(),
|
||||||
new SelectWholeLineAction(),
|
new SelectWholeLineAction(),
|
||||||
new ToggleCommentAction()
|
new ToggleCommentAction()
|
||||||
};
|
};
|
||||||
@ -103,6 +105,39 @@ public class SketchTextAreaEditorKit extends RSyntaxTextAreaEditorKit {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increases the indent of the selected or current line(s).
|
||||||
|
*/
|
||||||
|
public static class IncreaseIndentAction extends RSyntaxTextAreaEditorKit.InsertTabAction {
|
||||||
|
|
||||||
|
public IncreaseIndentAction() {
|
||||||
|
super(rtaIncreaseIndentAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformedImpl(ActionEvent e, RTextArea textArea) {
|
||||||
|
int caretPosition = textArea.getCaretPosition();
|
||||||
|
boolean noSelec = textArea.getSelectedText() == null;
|
||||||
|
|
||||||
|
// if no selection, focus on first char.
|
||||||
|
if (noSelec) {
|
||||||
|
try {
|
||||||
|
int line = textArea.getCaretLineNumber();
|
||||||
|
int startOffset = textArea.getLineStartOffset(line);
|
||||||
|
textArea.setCaretPosition(startOffset);
|
||||||
|
} catch (BadLocationException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert Tab or Spaces..
|
||||||
|
super.actionPerformedImpl(e, textArea);
|
||||||
|
|
||||||
|
if (noSelec) {
|
||||||
|
textArea.setCaretPosition(caretPosition + (textArea.getTabsEmulated() ? textArea.getTabSize() : 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the line around the caret.
|
* Selects the line around the caret.
|
||||||
*/
|
*/
|
||||||
|
@ -29,18 +29,20 @@
|
|||||||
|
|
||||||
package processing.app.debug;
|
package processing.app.debug;
|
||||||
|
|
||||||
import cc.arduino.packages.BoardPort;
|
import static org.junit.Assert.assertTrue;
|
||||||
import cc.arduino.packages.Uploader;
|
|
||||||
import cc.arduino.packages.UploaderFactory;
|
|
||||||
import cc.arduino.packages.uploaders.SSHUploader;
|
|
||||||
import cc.arduino.packages.uploaders.SerialUploader;
|
|
||||||
import org.junit.Test;
|
|
||||||
import processing.app.AbstractWithPreferencesTest;
|
|
||||||
import processing.app.helpers.PreferencesMap;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import cc.arduino.packages.BoardPort;
|
||||||
|
import cc.arduino.packages.Uploader;
|
||||||
|
import cc.arduino.packages.UploaderFactory;
|
||||||
|
import cc.arduino.packages.uploaders.GenericNetworkUploader;
|
||||||
|
import cc.arduino.packages.uploaders.SSHUploader;
|
||||||
|
import cc.arduino.packages.uploaders.SerialUploader;
|
||||||
|
import processing.app.AbstractWithPreferencesTest;
|
||||||
|
import processing.app.helpers.PreferencesMap;
|
||||||
|
|
||||||
public class UploaderFactoryTest extends AbstractWithPreferencesTest {
|
public class UploaderFactoryTest extends AbstractWithPreferencesTest {
|
||||||
|
|
||||||
@ -52,11 +54,26 @@ public class UploaderFactoryTest extends AbstractWithPreferencesTest {
|
|||||||
boardPort.setBoardName("yun");
|
boardPort.setBoardName("yun");
|
||||||
boardPort.setAddress("192.168.0.1");
|
boardPort.setAddress("192.168.0.1");
|
||||||
boardPort.setProtocol("network");
|
boardPort.setProtocol("network");
|
||||||
|
boardPort.getPrefs().put("ssh_upload", "yes");
|
||||||
Uploader uploader = new UploaderFactory().newUploader(board, boardPort, false);
|
Uploader uploader = new UploaderFactory().newUploader(board, boardPort, false);
|
||||||
|
|
||||||
assertTrue(uploader instanceof SSHUploader);
|
assertTrue(uploader instanceof SSHUploader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCreateAnInstanceOfGenericNetworkUploader() throws Exception {
|
||||||
|
TargetBoard board = new LegacyTargetBoard("yun", new PreferencesMap(new HashMap<String, String>()), new TargetPlatformStub("id", new TargetPackageStub("id")));
|
||||||
|
|
||||||
|
BoardPort boardPort = new BoardPort();
|
||||||
|
boardPort.setBoardName("yun");
|
||||||
|
boardPort.setAddress("192.168.0.1");
|
||||||
|
boardPort.setProtocol("network");
|
||||||
|
boardPort.getPrefs().put("ssh_upload", "no");
|
||||||
|
Uploader uploader = new UploaderFactory().newUploader(board, boardPort, false);
|
||||||
|
|
||||||
|
assertTrue(uploader instanceof GenericNetworkUploader);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldCreateAnInstanceOfBasicUploaderWhenPortIsSerial() throws Exception {
|
public void shouldCreateAnInstanceOfBasicUploaderWhenPortIsSerial() throws Exception {
|
||||||
TargetBoard board = new LegacyTargetBoard("uno", new PreferencesMap(new HashMap<String, String>()), new TargetPlatformStub("id", new TargetPackageStub("id")));
|
TargetBoard board = new LegacyTargetBoard("uno", new PreferencesMap(new HashMap<String, String>()), new TargetPlatformStub("id", new TargetPackageStub("id")));
|
||||||
|
@ -108,6 +108,24 @@ public abstract class ContributedPlatform extends DownloadableContribution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ContributedPlatform obj1 = (ContributedPlatform) obj;
|
ContributedPlatform obj1 = (ContributedPlatform) obj;
|
||||||
return getParentPackage().getName().equals(obj1.getParentPackage().getName()) && getArchitecture().equals(obj1.getArchitecture()) && getVersion().equals(obj1.getVersion()) && getName().equals(obj1.getName());
|
|
||||||
|
ContributedPackage parentPackage = getParentPackage();
|
||||||
|
ContributedPackage parentPackage1 = obj1.getParentPackage();
|
||||||
|
if (parentPackage == null) {
|
||||||
|
if (parentPackage1 != null)
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (parentPackage1 == null)
|
||||||
|
return false;
|
||||||
|
if (!parentPackage.getName().equals(parentPackage1.getName()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!getArchitecture().equals(obj1.getArchitecture())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!getVersion().equals(obj1.getVersion())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return getName().equals(obj1.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,9 +39,9 @@ import static processing.app.helpers.filefilters.OnlyDirs.ONLY_DIRS;
|
|||||||
public class BaseNoGui {
|
public class BaseNoGui {
|
||||||
|
|
||||||
/** Version string to be used for build */
|
/** Version string to be used for build */
|
||||||
public static final int REVISION = 10607;
|
public static final int REVISION = 10608;
|
||||||
/** Extended version string displayed on GUI */
|
/** Extended version string displayed on GUI */
|
||||||
public static final String VERSION_NAME = "1.6.7";
|
public static final String VERSION_NAME = "1.6.8";
|
||||||
public static final String VERSION_NAME_LONG;
|
public static final String VERSION_NAME_LONG;
|
||||||
|
|
||||||
// Current directory to use for relative paths specified on the
|
// Current directory to use for relative paths specified on the
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
ARDUINO 1.6.8
|
||||||
|
|
||||||
|
[ide]
|
||||||
|
* Fixed a NullPointerException when dealing with some rare combination of package_*.json files
|
||||||
|
* Fixed incorrect key bindings handling for changing tab. Thanks @matthijskooijman
|
||||||
|
* MacOSX: Fixed handling of add indent/remove indent shortcuts (CMD+[ and CMD+])
|
||||||
|
|
||||||
|
[core]
|
||||||
|
* avr: fixed USB_SendControl(...) for buffer with len > 64. Thanks @NicoHood
|
||||||
|
|
||||||
ARDUINO 1.6.7 - 2015.12.17
|
ARDUINO 1.6.7 - 2015.12.17
|
||||||
|
|
||||||
[ide]
|
[ide]
|
||||||
|
@ -193,6 +193,7 @@ bool CDC_Setup(USBSetup& setup);
|
|||||||
|
|
||||||
int USB_SendControl(uint8_t flags, const void* d, int len);
|
int USB_SendControl(uint8_t flags, const void* d, int len);
|
||||||
int USB_RecvControl(void* d, int len);
|
int USB_RecvControl(void* d, int len);
|
||||||
|
int USB_RecvControlLong(void* d, int len);
|
||||||
|
|
||||||
uint8_t USB_Available(uint8_t ep);
|
uint8_t USB_Available(uint8_t ep);
|
||||||
uint8_t USB_SendSpace(uint8_t ep);
|
uint8_t USB_SendSpace(uint8_t ep);
|
||||||
|
@ -89,7 +89,7 @@ void httpRequest() {
|
|||||||
// if there's a successful connection:
|
// if there's a successful connection:
|
||||||
if (client.connect(server, 80)) {
|
if (client.connect(server, 80)) {
|
||||||
Serial.println("connecting...");
|
Serial.println("connecting...");
|
||||||
// send the HTTP PUT request:
|
// send the HTTP GET request:
|
||||||
client.println("GET /latest.txt HTTP/1.1");
|
client.println("GET /latest.txt HTTP/1.1");
|
||||||
client.println("Host: www.arduino.cc");
|
client.println("Host: www.arduino.cc");
|
||||||
client.println("User-Agent: arduino-ethernet");
|
client.println("User-Agent: arduino-ethernet");
|
||||||
@ -103,5 +103,3 @@ void httpRequest() {
|
|||||||
Serial.println("connection failed");
|
Serial.println("connection failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user