1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-02-20 14:54:31 +01:00

Merge NicoHood's fix for USB_SendControl with len>64

Fix #4325
This commit is contained in:
Cristian Maglie 2015-12-23 15:33:14 +01:00
commit d893aa0b65
15 changed files with 532 additions and 297 deletions

View File

@ -38,12 +38,14 @@ import org.fife.ui.rtextarea.Gutter;
import org.fife.ui.rtextarea.RTextScrollPane;
import processing.app.debug.RunnerException;
import processing.app.forms.PasswordAuthorizationDialog;
import processing.app.helpers.Keys;
import processing.app.helpers.OSUtils;
import processing.app.helpers.PreferencesMapException;
import processing.app.legacy.PApplet;
import processing.app.syntax.ArduinoTokenMakerFactory;
import processing.app.syntax.PdeKeywords;
import processing.app.syntax.SketchTextArea;
import processing.app.syntax.SketchTextAreaEditorKit;
import processing.app.tools.DiscourseFormat;
import processing.app.tools.MenuScroller;
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
// ugly white border around this object, so turn it off.
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
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.setTabsEmulated(PreferencesData.getBoolean("editor.tabs.expand"));
textArea.setTabSize(PreferencesData.getInteger("editor.tabs.size"));
textArea.setEditorListener(new EditorListener(this));
textArea.addHyperlinkListener(new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent hyperlinkEvent) {
@ -1866,28 +1873,8 @@ public class Editor extends JFrame implements RunnerListener {
private void handleIndentOutdent(boolean indent) {
if (indent) {
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 action = textarea.getActionMap().get(SketchTextAreaEditorKit.rtaIncreaseIndentAction);
action.actionPerformed(null);
if (noSelec) {
textarea.setCaretPosition(caretPosition);
}
} else {
Action action = textarea.getActionMap().get(RSyntaxTextAreaEditorKit.rstaDecreaseIndentAction);
action.actionPerformed(null);

View File

@ -63,6 +63,7 @@ public class EditorConsole extends JScrollPane {
consoleTextPane.setEditable(false);
DefaultCaret caret = (DefaultCaret) consoleTextPane.getCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
consoleTextPane.setFocusTraversalKeysEnabled(false);
Color backgroundColour = Theme.getColor("console.color");
consoleTextPane.setBackground(backgroundColour);

View File

@ -22,7 +22,10 @@
*/
package processing.app;
import processing.app.helpers.Keys;
import processing.app.helpers.OSUtils;
import processing.app.helpers.SimpleAction;
import processing.app.tools.MenuScroller;
import static processing.app.I18n.tr;
@ -72,12 +75,69 @@ public class EditorHeader extends JComponent {
static Image[][] pieces;
//
Image offscreen;
int sizeW, sizeH;
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) {
this.editor = eddie; // weird name for listener
@ -236,7 +296,6 @@ public class EditorHeader extends JComponent {
public void rebuildMenu() {
//System.out.println("rebuilding");
if (menu != null) {
menu.removeAll();
@ -244,143 +303,34 @@ public class EditorHeader extends JComponent {
menu = new JMenu();
MenuScroller.setScrollerFor(menu);
popup = menu.getPopupMenu();
add(popup);
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;
// maybe this shouldn't have a command key anyways..
// since we're not trying to make this a full ide..
//item = Editor.newJMenuItem("New", 'T');
/*
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.add(new JMenuItem(actions.newTab));
menu.add(new JMenuItem(actions.renameTab));
menu.add(new JMenuItem(actions.deleteTab));
menu.addSeparator();
*/
//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);
menu.add(new JMenuItem(actions.prevTab));
menu.add(new JMenuItem(actions.nextTab));
Sketch sketch = editor.getSketch();
if (sketch != null) {
menu.addSeparator();
ActionListener jumpListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
editor.getSketch().setCurrentCode(e.getActionCommand());
}
};
int i = 0;
for (SketchCode code : sketch.getCodes()) {
final int index = i++;
item = new JMenuItem(code.isExtension(sketch.getDefaultExtension()) ?
code.getPrettyName() : code.getFileName());
item.setActionCommand(code.getFileName());
item.addActionListener(jumpListener);
item.addActionListener((ActionEvent e) -> {
editor.getSketch().setCurrentCode(index);
});
menu.add(item);
}
}
}
public void deselectMenu() {
repaint();
}
public Dimension getPreferredSize() {
return getMinimumSize();
}

View File

@ -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
}
}

View 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);
}
}

View 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);
}
}

View File

@ -38,10 +38,8 @@ import org.fife.ui.rtextarea.RTextAreaUI;
import org.fife.ui.rtextarea.RUndoManager;
import processing.app.Base;
import processing.app.BaseNoGui;
import processing.app.EditorListener;
import processing.app.PreferencesData;
import javax.swing.*;
import javax.swing.event.EventListenerList;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
@ -50,16 +48,13 @@ import javax.swing.text.Document;
import javax.swing.text.Segment;
import javax.swing.undo.UndoManager;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
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 EditorListener editorListener;
private PdeKeywords pdeKeywords;
public SketchTextArea(PdeKeywords pdeKeywords) throws IOException {
@ -91,8 +84,6 @@ public class SketchTextArea extends RSyntaxTextArea {
setLinkGenerator(new DocLinkGenerator(pdeKeywords));
fixControlTab();
setSyntaxEditingStyle(SYNTAX_STYLE_CPLUSPLUS);
}
@ -153,53 +144,10 @@ public class SketchTextArea extends RSyntaxTextArea {
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() {
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) {
// 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 final PdeKeywords pdeKeywords;

View File

@ -23,6 +23,15 @@ public class SketchTextAreaDefaultInputMap extends RSyntaxTextAreaDefaultInputMa
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")) {
put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, alt), RTextAreaEditorKit.rtaLineDownAction);
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));
put(KeyStroke.getKeyStroke(KeyEvent.VK_OPEN_BRACKET, defaultModifier), DefaultEditorKit.insertTabAction);
put(KeyStroke.getKeyStroke(KeyEvent.VK_CLOSE_BRACKET, defaultModifier), RSyntaxTextAreaEditorKit.rstaDecreaseIndentAction);
put(KeyStroke.getKeyStroke(KeyEvent.VK_OPEN_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_DOWN, defaultModifier | shift), DefaultEditorKit.selectionEndAction);

View File

@ -13,10 +13,12 @@ public class SketchTextAreaEditorKit extends RSyntaxTextAreaEditorKit {
public static final String rtaDeleteNextWordAction = "RTA.DeleteNextWordAction";
public static final String rtaDeleteLineToCursorAction = "RTA.DeleteLineToCursorAction";
public static final String rtaIncreaseIndentAction = "RTA.IncreaseIndentAction";
private static final Action[] defaultActions = {
new DeleteNextWordAction(),
new DeleteLineToCursorAction(),
new IncreaseIndentAction(),
new SelectWholeLineAction(),
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.
*/

View File

@ -29,18 +29,20 @@
package processing.app.debug;
import cc.arduino.packages.BoardPort;
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 static org.junit.Assert.assertTrue;
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 {
@ -52,11 +54,26 @@ public class UploaderFactoryTest extends AbstractWithPreferencesTest {
boardPort.setBoardName("yun");
boardPort.setAddress("192.168.0.1");
boardPort.setProtocol("network");
boardPort.getPrefs().put("ssh_upload", "yes");
Uploader uploader = new UploaderFactory().newUploader(board, boardPort, false);
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
public void shouldCreateAnInstanceOfBasicUploaderWhenPortIsSerial() throws Exception {
TargetBoard board = new LegacyTargetBoard("uno", new PreferencesMap(new HashMap<String, String>()), new TargetPlatformStub("id", new TargetPackageStub("id")));

View File

@ -108,6 +108,24 @@ public abstract class ContributedPlatform extends DownloadableContribution {
}
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());
}
}

View File

@ -39,9 +39,9 @@ import static processing.app.helpers.filefilters.OnlyDirs.ONLY_DIRS;
public class BaseNoGui {
/** 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 */
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;
// Current directory to use for relative paths specified on the

View File

@ -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
[ide]

View File

@ -193,6 +193,7 @@ bool CDC_Setup(USBSetup& setup);
int USB_SendControl(uint8_t flags, const 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_SendSpace(uint8_t ep);

View File

@ -89,7 +89,7 @@ void httpRequest() {
// if there's a successful connection:
if (client.connect(server, 80)) {
Serial.println("connecting...");
// send the HTTP PUT request:
// send the HTTP GET request:
client.println("GET /latest.txt HTTP/1.1");
client.println("Host: www.arduino.cc");
client.println("User-Agent: arduino-ethernet");
@ -103,5 +103,3 @@ void httpRequest() {
Serial.println("connection failed");
}
}