mirror of
https://github.com/arduino/Arduino.git
synced 2025-03-14 11:29:26 +01:00
Use a separate RSyntaxTextArea for each editor tab
RSyntaxTextArea appears to support using a single instance and replacing the underlying text and document when switching between tabs, but in practice this support is not complete and even though the RSyntaxTextArea developers did some work to improve the situation, they recommend to just use a seperate instance for each tab. This commit implements exactly that. A new class EditorTab is introduce to wrap the RSyntaxTextArea and containing scroll pane, and to encapsulate the code related to handling the text area itself. Doing so removes some quirks and prepares for some later additions. In particular, error highlights are now no longer shared between all tabs, which was previously the case. This commit mostly moves code from Editor into EditorTab, and updates the callers to use getCurrentTab() and call methods on the result instead of calling them on Editor. Some code is added to take care of creating multiple EditorTab objects and switching between them. Some small changes have been made to make the flow of opening files work, though these are mostly a bit hacky. While moving code, changes to the rest of the code were kept minimal, retaining existing interfaces as much as possible. This sometimes result in less than ideal code, which should be cleaned up in subsequent commits. The SketchCodeDocument class has been pretty much emptied out, since it was mostly used to store things for tabs in the background, which are now just stored in each RSyntaxTextArea separately. The last remaining bits of this class can probably be moved or implemented differently later, so it can be removed. The entire flow of working with sketches and files needs to be cleaned up next, so no thorough attempt at testing this commit was done. It is likely that there are plenty of corner cases and race conditions, which will be fixed once the reset of the code is cleaned up. Fixes #3441
This commit is contained in:
parent
c945b6c30a
commit
982d4f3fbf
@ -78,7 +78,7 @@ public class AStyle implements Tool {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
String originalText = editor.getText();
|
String originalText = editor.getCurrentTab().getText();
|
||||||
String formattedText = aStyleInterface.AStyleMain(originalText, formatterConfiguration);
|
String formattedText = aStyleInterface.AStyleMain(originalText, formatterConfiguration);
|
||||||
|
|
||||||
if (formattedText.equals(originalText)) {
|
if (formattedText.equals(originalText)) {
|
||||||
@ -86,14 +86,14 @@ public class AStyle implements Tool {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SketchTextArea textArea = editor.getTextArea();
|
SketchTextArea textArea = editor.getCurrentTab().getTextArea();
|
||||||
|
|
||||||
int line = getLineOfOffset(textArea);
|
int line = getLineOfOffset(textArea);
|
||||||
int lineOffset = getLineOffset(textArea, line);
|
int lineOffset = getLineOffset(textArea, line);
|
||||||
|
|
||||||
textArea.getUndoManager().beginInternalAtomicEdit();
|
textArea.getUndoManager().beginInternalAtomicEdit();
|
||||||
editor.removeAllLineHighlights();
|
editor.removeAllLineHighlights();
|
||||||
editor.setText(formattedText);
|
editor.getCurrentTab().setText(formattedText);
|
||||||
editor.getSketch().setModified(true);
|
editor.getSketch().setModified(true);
|
||||||
textArea.getUndoManager().endInternalAtomicEdit();
|
textArea.getUndoManager().endInternalAtomicEdit();
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ public class GoToLineNumber extends javax.swing.JDialog {
|
|||||||
private void okActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okActionPerformed
|
private void okActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okActionPerformed
|
||||||
try {
|
try {
|
||||||
int line = Integer.parseInt(lineNumber.getText());
|
int line = Integer.parseInt(lineNumber.getText());
|
||||||
editor.goToLine(line);
|
editor.getCurrentTab().goToLine(line);
|
||||||
cancelActionPerformed(evt);
|
cancelActionPerformed(evt);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// ignore
|
// ignore
|
||||||
|
@ -292,7 +292,7 @@ public class FindReplace extends javax.swing.JFrame {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String text = editor.getText();
|
String text = editor.getCurrentTab().getText();
|
||||||
|
|
||||||
if (ignoreCaseBox.isSelected()) {
|
if (ignoreCaseBox.isSelected()) {
|
||||||
search = search.toLowerCase();
|
search = search.toLowerCase();
|
||||||
@ -302,7 +302,7 @@ public class FindReplace extends javax.swing.JFrame {
|
|||||||
int nextIndex;
|
int nextIndex;
|
||||||
if (!backwards) {
|
if (!backwards) {
|
||||||
// int selectionStart = editor.textarea.getSelectionStart();
|
// int selectionStart = editor.textarea.getSelectionStart();
|
||||||
int selectionEnd = editor.getSelectionStop();
|
int selectionEnd = editor.getCurrentTab().getSelectionStop();
|
||||||
|
|
||||||
nextIndex = text.indexOf(search, selectionEnd);
|
nextIndex = text.indexOf(search, selectionEnd);
|
||||||
if (wrap && nextIndex == -1) {
|
if (wrap && nextIndex == -1) {
|
||||||
@ -311,7 +311,7 @@ public class FindReplace extends javax.swing.JFrame {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// int selectionStart = editor.textarea.getSelectionStart();
|
// int selectionStart = editor.textarea.getSelectionStart();
|
||||||
int selectionStart = editor.getSelectionStart() - 1;
|
int selectionStart = editor.getCurrentTab().getSelectionStart() - 1;
|
||||||
|
|
||||||
if (selectionStart >= 0) {
|
if (selectionStart >= 0) {
|
||||||
nextIndex = text.lastIndexOf(search, selectionStart);
|
nextIndex = text.lastIndexOf(search, selectionStart);
|
||||||
@ -346,12 +346,12 @@ public class FindReplace extends javax.swing.JFrame {
|
|||||||
if (backwards) {
|
if (backwards) {
|
||||||
sketch.handlePrevCode();
|
sketch.handlePrevCode();
|
||||||
this.setVisible(true);
|
this.setVisible(true);
|
||||||
int l = editor.getText().length() - 1;
|
int l = editor.getCurrentTab().getText().length() - 1;
|
||||||
editor.setSelection(l, l);
|
editor.getCurrentTab().setSelection(l, l);
|
||||||
} else {
|
} else {
|
||||||
sketch.handleNextCode();
|
sketch.handleNextCode();
|
||||||
this.setVisible(true);
|
this.setVisible(true);
|
||||||
editor.setSelection(0, 0);
|
editor.getCurrentTab().setSelection(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return find(wrap, backwards, true, originTab);
|
return find(wrap, backwards, true, originTab);
|
||||||
@ -365,7 +365,7 @@ public class FindReplace extends javax.swing.JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nextIndex != -1) {
|
if (nextIndex != -1) {
|
||||||
editor.setSelection(nextIndex, nextIndex + search.length());
|
editor.getCurrentTab().setSelection(nextIndex, nextIndex + search.length());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,17 +381,17 @@ public class FindReplace extends javax.swing.JFrame {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int newpos = editor.getSelectionStart() - findField.getText().length();
|
int newpos = editor.getCurrentTab().getSelectionStart() - findField.getText().length();
|
||||||
if (newpos < 0) {
|
if (newpos < 0) {
|
||||||
newpos = 0;
|
newpos = 0;
|
||||||
}
|
}
|
||||||
editor.setSelection(newpos, newpos);
|
editor.getCurrentTab().setSelection(newpos, newpos);
|
||||||
|
|
||||||
boolean foundAtLeastOne = false;
|
boolean foundAtLeastOne = false;
|
||||||
|
|
||||||
if (find(false, false, searchAllFilesBox.isSelected(), -1)) {
|
if (find(false, false, searchAllFilesBox.isSelected(), -1)) {
|
||||||
foundAtLeastOne = true;
|
foundAtLeastOne = true;
|
||||||
editor.setSelectedText(replaceField.getText());
|
editor.getCurrentTab().setSelectedText(replaceField.getText());
|
||||||
editor.getSketch().setModified(true); // TODO is this necessary?
|
editor.getSketch().setModified(true); // TODO is this necessary?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,13 +423,13 @@ public class FindReplace extends javax.swing.JFrame {
|
|||||||
editor.getSketch().setCurrentCode(0); // select the first tab
|
editor.getSketch().setCurrentCode(0); // select the first tab
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.setSelection(0, 0); // move to the beginning
|
editor.getCurrentTab().setSelection(0, 0); // move to the beginning
|
||||||
|
|
||||||
boolean foundAtLeastOne = false;
|
boolean foundAtLeastOne = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (find(false, false, searchAllFilesBox.isSelected(), -1)) {
|
if (find(false, false, searchAllFilesBox.isSelected(), -1)) {
|
||||||
foundAtLeastOne = true;
|
foundAtLeastOne = true;
|
||||||
editor.setSelectedText(replaceField.getText());
|
editor.getCurrentTab().setSelectedText(replaceField.getText());
|
||||||
editor.getSketch().setModified(true); // TODO is this necessary?
|
editor.getSketch().setModified(true); // TODO is this necessary?
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -608,10 +608,10 @@ public class Base {
|
|||||||
activeEditor.rebuildRecentSketchesMenu();
|
activeEditor.rebuildRecentSketchesMenu();
|
||||||
if (PreferencesData.getBoolean("editor.external")) {
|
if (PreferencesData.getBoolean("editor.external")) {
|
||||||
try {
|
try {
|
||||||
int previousCaretPosition = activeEditor.getTextArea().getCaretPosition();
|
int previousCaretPosition = activeEditor.getCurrentTab().getTextArea().getCaretPosition();
|
||||||
activeEditor.getSketch().load(true);
|
activeEditor.getSketch().load(true);
|
||||||
if (previousCaretPosition < activeEditor.getText().length()) {
|
if (previousCaretPosition < activeEditor.getCurrentTab().getText().length()) {
|
||||||
activeEditor.getTextArea().setCaretPosition(previousCaretPosition);
|
activeEditor.getCurrentTab().getTextArea().setCaretPosition(previousCaretPosition);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// noop
|
// noop
|
||||||
|
@ -29,34 +29,21 @@ import cc.arduino.packages.uploaders.SerialUploader;
|
|||||||
import cc.arduino.view.GoToLineNumber;
|
import cc.arduino.view.GoToLineNumber;
|
||||||
import cc.arduino.view.StubMenuListener;
|
import cc.arduino.view.StubMenuListener;
|
||||||
import cc.arduino.view.findreplace.FindReplace;
|
import cc.arduino.view.findreplace.FindReplace;
|
||||||
import cc.arduino.UpdatableBoardsLibsFakeURLsHandler;
|
|
||||||
import com.jcraft.jsch.JSchException;
|
import com.jcraft.jsch.JSchException;
|
||||||
import jssc.SerialPortException;
|
import jssc.SerialPortException;
|
||||||
import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;
|
|
||||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaEditorKit;
|
|
||||||
import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;
|
|
||||||
import org.fife.ui.rtextarea.Gutter;
|
|
||||||
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.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.PdeKeywords;
|
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.MenuScroller;
|
||||||
import processing.app.tools.Tool;
|
import processing.app.tools.Tool;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.MatteBorder;
|
|
||||||
import javax.swing.event.*;
|
import javax.swing.event.*;
|
||||||
import javax.swing.text.BadLocationException;
|
import javax.swing.text.BadLocationException;
|
||||||
import javax.swing.text.Element;
|
|
||||||
import javax.swing.text.PlainDocument;
|
|
||||||
import javax.swing.undo.CannotRedoException;
|
import javax.swing.undo.CannotRedoException;
|
||||||
import javax.swing.undo.CannotUndoException;
|
import javax.swing.undo.CannotUndoException;
|
||||||
import javax.swing.undo.UndoManager;
|
import javax.swing.undo.UndoManager;
|
||||||
@ -91,9 +78,12 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
|
|
||||||
public static final int MAX_TIME_AWAITING_FOR_RESUMING_SERIAL_MONITOR = 10000;
|
public static final int MAX_TIME_AWAITING_FOR_RESUMING_SERIAL_MONITOR = 10000;
|
||||||
|
|
||||||
private final Platform platform;
|
final Platform platform;
|
||||||
private JMenu recentSketchesMenu;
|
private JMenu recentSketchesMenu;
|
||||||
private JMenu programmersMenu;
|
private JMenu programmersMenu;
|
||||||
|
private final Box upper;
|
||||||
|
private ArrayList<EditorTab> tabs = new ArrayList<>();
|
||||||
|
private int currentTabIndex = -1;
|
||||||
|
|
||||||
private static class ShouldSaveIfModified implements Predicate<Sketch> {
|
private static class ShouldSaveIfModified implements Predicate<Sketch> {
|
||||||
|
|
||||||
@ -170,12 +160,12 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
// currently opened program
|
// currently opened program
|
||||||
Sketch sketch;
|
Sketch sketch;
|
||||||
|
|
||||||
private EditorLineStatus lineStatus;
|
EditorLineStatus lineStatus;
|
||||||
|
|
||||||
//JEditorPane editorPane;
|
//JEditorPane editorPane;
|
||||||
|
|
||||||
private SketchTextArea textarea;
|
/** Contains all EditorTabs, of which only one will be visible */
|
||||||
private RTextScrollPane scrollPane;
|
private JPanel codePanel;
|
||||||
|
|
||||||
//Runner runtime;
|
//Runner runtime;
|
||||||
|
|
||||||
@ -263,7 +253,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
contentPain.add(pane, BorderLayout.CENTER);
|
contentPain.add(pane, BorderLayout.CENTER);
|
||||||
|
|
||||||
Box box = Box.createVerticalBox();
|
Box box = Box.createVerticalBox();
|
||||||
Box upper = Box.createVerticalBox();
|
upper = Box.createVerticalBox();
|
||||||
|
|
||||||
if (toolbarMenu == null) {
|
if (toolbarMenu == null) {
|
||||||
toolbarMenu = new JMenu();
|
toolbarMenu = new JMenu();
|
||||||
@ -275,9 +265,6 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
header = new EditorHeader(this);
|
header = new EditorHeader(this);
|
||||||
upper.add(header);
|
upper.add(header);
|
||||||
|
|
||||||
textarea = createTextArea();
|
|
||||||
textarea.setName("editor");
|
|
||||||
|
|
||||||
// assemble console panel, consisting of status area and the console itself
|
// assemble console panel, consisting of status area and the console itself
|
||||||
JPanel consolePanel = new JPanel();
|
JPanel consolePanel = new JPanel();
|
||||||
consolePanel.setLayout(new BorderLayout());
|
consolePanel.setLayout(new BorderLayout());
|
||||||
@ -294,19 +281,9 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
lineStatus = new EditorLineStatus();
|
lineStatus = new EditorLineStatus();
|
||||||
consolePanel.add(lineStatus, BorderLayout.SOUTH);
|
consolePanel.add(lineStatus, BorderLayout.SOUTH);
|
||||||
|
|
||||||
// RTextScrollPane
|
codePanel = new JPanel(new BorderLayout());
|
||||||
scrollPane = new RTextScrollPane(textarea, true);
|
upper.add(codePanel);
|
||||||
scrollPane.setBorder(new MatteBorder(0, 6, 0, 0, Theme.getColor("editor.bgcolor")));
|
|
||||||
scrollPane.setViewportBorder(BorderFactory.createEmptyBorder());
|
|
||||||
scrollPane.setLineNumbersEnabled(PreferencesData.getBoolean("editor.linenumbers"));
|
|
||||||
scrollPane.setIconRowHeaderEnabled(false);
|
|
||||||
|
|
||||||
Gutter gutter = scrollPane.getGutter();
|
|
||||||
gutter.setBookmarkingEnabled(false);
|
|
||||||
//gutter.setBookmarkIcon(CompletionsRenderer.getIcon(CompletionType.TEMPLATE));
|
|
||||||
gutter.setIconRowHeaderInheritsGutterBackground(true);
|
|
||||||
|
|
||||||
upper.add(scrollPane);
|
|
||||||
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, upper, consolePanel);
|
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, upper, consolePanel);
|
||||||
|
|
||||||
// repaint child panes while resizing
|
// repaint child panes while resizing
|
||||||
@ -466,44 +443,11 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
* with things in the Preferences window.
|
* with things in the Preferences window.
|
||||||
*/
|
*/
|
||||||
public void applyPreferences() {
|
public void applyPreferences() {
|
||||||
|
|
||||||
// apply the setting for 'use external editor'
|
|
||||||
boolean external = PreferencesData.getBoolean("editor.external");
|
boolean external = PreferencesData.getBoolean("editor.external");
|
||||||
|
|
||||||
textarea.setEditable(!external);
|
|
||||||
saveMenuItem.setEnabled(!external);
|
saveMenuItem.setEnabled(!external);
|
||||||
saveAsMenuItem.setEnabled(!external);
|
saveAsMenuItem.setEnabled(!external);
|
||||||
|
for (EditorTab tab: tabs)
|
||||||
textarea.setCodeFoldingEnabled(PreferencesData.getBoolean("editor.code_folding"));
|
tab.applyPreferences();
|
||||||
scrollPane.setFoldIndicatorEnabled(PreferencesData.getBoolean("editor.code_folding"));
|
|
||||||
scrollPane.setLineNumbersEnabled(PreferencesData.getBoolean("editor.linenumbers"));
|
|
||||||
|
|
||||||
if (external) {
|
|
||||||
// disable line highlight and turn off the caret when disabling
|
|
||||||
textarea.setBackground(Theme.getColor("editor.external.bgcolor"));
|
|
||||||
textarea.setHighlightCurrentLine(false);
|
|
||||||
textarea.setEditable(false);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
textarea.setBackground(Theme.getColor("editor.bgcolor"));
|
|
||||||
textarea.setHighlightCurrentLine(Theme.getBoolean("editor.linehighlight"));
|
|
||||||
textarea.setEditable(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply changes to the font size for the editor
|
|
||||||
Font editorFont = scale(PreferencesData.getFont("editor.font"));
|
|
||||||
textarea.setFont(editorFont);
|
|
||||||
scrollPane.getGutter().setLineNumberFont(editorFont);
|
|
||||||
|
|
||||||
// in case tab expansion stuff has changed
|
|
||||||
// listener.applyPreferences();
|
|
||||||
|
|
||||||
// in case moved to a new location
|
|
||||||
// For 0125, changing to async version (to be implemented later)
|
|
||||||
//sketchbook.rebuildMenus();
|
|
||||||
// For 0126, moved into Base, which will notify all editors.
|
|
||||||
//base.rebuildMenusAsync();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1005,53 +949,12 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private SketchTextArea createTextArea() throws IOException {
|
|
||||||
final SketchTextArea textArea = new SketchTextArea(base.getPdeKeywords());
|
|
||||||
textArea.setFocusTraversalKeysEnabled(false);
|
|
||||||
textArea.requestFocusInWindow();
|
|
||||||
textArea.setMarkOccurrences(PreferencesData.getBoolean("editor.advanced"));
|
|
||||||
textArea.setMarginLineEnabled(false);
|
|
||||||
textArea.setCodeFoldingEnabled(PreferencesData.getBoolean("editor.code_folding"));
|
|
||||||
textArea.setAntiAliasingEnabled(PreferencesData.getBoolean("editor.antialias"));
|
|
||||||
textArea.setTabsEmulated(PreferencesData.getBoolean("editor.tabs.expand"));
|
|
||||||
textArea.setTabSize(PreferencesData.getInteger("editor.tabs.size"));
|
|
||||||
textArea.addHyperlinkListener(evt -> {
|
|
||||||
try {
|
|
||||||
UpdatableBoardsLibsFakeURLsHandler boardLibHandler = new UpdatableBoardsLibsFakeURLsHandler(base);
|
|
||||||
boardLibHandler.openBoardLibManager(evt.getURL());
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
try {
|
|
||||||
platform.openURL(sketch.getFolder(), evt.getURL().toExternalForm());
|
|
||||||
} catch (Exception f) {
|
|
||||||
Base.showWarning(f.getMessage(), f.getMessage(), f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
textArea.addCaretListener(e -> {
|
|
||||||
Element root = textArea.getDocument().getDefaultRootElement();
|
|
||||||
int lineStart = root.getElementIndex(e.getMark());
|
|
||||||
int lineEnd = root.getElementIndex(e.getDot());
|
|
||||||
|
|
||||||
lineStatus.set(lineStart, lineEnd);
|
|
||||||
});
|
|
||||||
ToolTipManager.sharedInstance().registerComponent(textArea);
|
|
||||||
|
|
||||||
configurePopupMenu(textArea);
|
|
||||||
return textArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateKeywords(PdeKeywords keywords) {
|
public void updateKeywords(PdeKeywords keywords) {
|
||||||
// update GUI for "Find In Reference"
|
for (EditorTab tab : tabs)
|
||||||
textarea.setKeywords(keywords);
|
tab.updateKeywords(keywords);
|
||||||
// update document for syntax highlighting
|
|
||||||
RSyntaxDocument document = (RSyntaxDocument) textarea.getDocument();
|
|
||||||
document.setTokenMakerFactory(new ArduinoTokenMakerFactory(keywords));
|
|
||||||
document.setSyntaxStyle(RSyntaxDocument.SYNTAX_STYLE_CPLUSPLUS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private JMenuItem createToolMenuItem(String className) {
|
JMenuItem createToolMenuItem(String className) {
|
||||||
try {
|
try {
|
||||||
Class<?> toolClass = Class.forName(className);
|
Class<?> toolClass = Class.forName(className);
|
||||||
final Tool tool = (Tool) toolClass.newInstance();
|
final Tool tool = (Tool) toolClass.newInstance();
|
||||||
@ -1381,7 +1284,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
JMenuItem cutItem = newJMenuItem(tr("Cut"), 'X');
|
JMenuItem cutItem = newJMenuItem(tr("Cut"), 'X');
|
||||||
cutItem.addActionListener(new ActionListener() {
|
cutItem.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
handleCut();
|
getCurrentTab().handleCut();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(cutItem);
|
menu.add(cutItem);
|
||||||
@ -1389,7 +1292,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
JMenuItem copyItem = newJMenuItem(tr("Copy"), 'C');
|
JMenuItem copyItem = newJMenuItem(tr("Copy"), 'C');
|
||||||
copyItem.addActionListener(new ActionListener() {
|
copyItem.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
textarea.copy();
|
getCurrentTab().getTextArea().copy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(copyItem);
|
menu.add(copyItem);
|
||||||
@ -1397,11 +1300,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
JMenuItem copyForumItem = newJMenuItemShift(tr("Copy for Forum"), 'C');
|
JMenuItem copyForumItem = newJMenuItemShift(tr("Copy for Forum"), 'C');
|
||||||
copyForumItem.addActionListener(new ActionListener() {
|
copyForumItem.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
// SwingUtilities.invokeLater(new Runnable() {
|
getCurrentTab().handleHTMLCopy();
|
||||||
// public void run() {
|
|
||||||
new DiscourseFormat(Editor.this, false).show();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(copyForumItem);
|
menu.add(copyForumItem);
|
||||||
@ -1409,11 +1308,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
JMenuItem copyHTMLItem = newJMenuItemAlt(tr("Copy as HTML"), 'C');
|
JMenuItem copyHTMLItem = newJMenuItemAlt(tr("Copy as HTML"), 'C');
|
||||||
copyHTMLItem.addActionListener(new ActionListener() {
|
copyHTMLItem.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
// SwingUtilities.invokeLater(new Runnable() {
|
getCurrentTab().handleDiscourseCopy();
|
||||||
// public void run() {
|
|
||||||
new DiscourseFormat(Editor.this, true).show();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(copyHTMLItem);
|
menu.add(copyHTMLItem);
|
||||||
@ -1421,7 +1316,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
JMenuItem pasteItem = newJMenuItem(tr("Paste"), 'V');
|
JMenuItem pasteItem = newJMenuItem(tr("Paste"), 'V');
|
||||||
pasteItem.addActionListener(new ActionListener() {
|
pasteItem.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
textarea.paste();
|
getCurrentTab().handlePaste();
|
||||||
sketch.setModified(true);
|
sketch.setModified(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -1430,7 +1325,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
JMenuItem selectAllItem = newJMenuItem(tr("Select All"), 'A');
|
JMenuItem selectAllItem = newJMenuItem(tr("Select All"), 'A');
|
||||||
selectAllItem.addActionListener(new ActionListener() {
|
selectAllItem.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
textarea.selectAll();
|
getCurrentTab().handleSelectAll();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(selectAllItem);
|
menu.add(selectAllItem);
|
||||||
@ -1448,7 +1343,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
JMenuItem commentItem = newJMenuItem(tr("Comment/Uncomment"), '/');
|
JMenuItem commentItem = newJMenuItem(tr("Comment/Uncomment"), '/');
|
||||||
commentItem.addActionListener(new ActionListener() {
|
commentItem.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
handleCommentUncomment();
|
getCurrentTab().handleCommentUncomment();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(commentItem);
|
menu.add(commentItem);
|
||||||
@ -1457,7 +1352,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
increaseIndentItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0));
|
increaseIndentItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0));
|
||||||
increaseIndentItem.addActionListener(new ActionListener() {
|
increaseIndentItem.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
handleIndentOutdent(true);
|
getCurrentTab().handleIndentOutdent(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(increaseIndentItem);
|
menu.add(increaseIndentItem);
|
||||||
@ -1467,7 +1362,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
decreseIndentItem.setName("menuDecreaseIndent");
|
decreseIndentItem.setName("menuDecreaseIndent");
|
||||||
decreseIndentItem.addActionListener(new ActionListener() {
|
decreseIndentItem.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
handleIndentOutdent(false);
|
getCurrentTab().handleIndentOutdent(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(decreseIndentItem);
|
menu.add(decreseIndentItem);
|
||||||
@ -1481,7 +1376,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
find = new FindReplace(Editor.this, Base.FIND_DIALOG_STATE);
|
find = new FindReplace(Editor.this, Base.FIND_DIALOG_STATE);
|
||||||
}
|
}
|
||||||
if (!OSUtils.isMacOS()) {
|
if (!OSUtils.isMacOS()) {
|
||||||
find.setFindText(getSelectedText());
|
find.setFindText(getCurrentTab().getSelectedText());
|
||||||
}
|
}
|
||||||
find.setLocationRelativeTo(Editor.this);
|
find.setLocationRelativeTo(Editor.this);
|
||||||
find.setVisible(true);
|
find.setVisible(true);
|
||||||
@ -1516,7 +1411,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
if (find == null) {
|
if (find == null) {
|
||||||
find = new FindReplace(Editor.this, Base.FIND_DIALOG_STATE);
|
find = new FindReplace(Editor.this, Base.FIND_DIALOG_STATE);
|
||||||
}
|
}
|
||||||
find.setFindText(getSelectedText());
|
find.setFindText(getCurrentTab().getSelectedText());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(useSelectionForFindItem);
|
menu.add(useSelectionForFindItem);
|
||||||
@ -1586,7 +1481,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
try {
|
try {
|
||||||
textarea.undoLastAction();
|
getCurrentTab().handleUndo();
|
||||||
sketch.setModified(true);
|
sketch.setModified(true);
|
||||||
} catch (CannotUndoException ex) {
|
} catch (CannotUndoException ex) {
|
||||||
//System.out.println("Unable to undo: " + ex);
|
//System.out.println("Unable to undo: " + ex);
|
||||||
@ -1595,8 +1490,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void updateUndoState() {
|
protected void updateUndoState() {
|
||||||
|
UndoManager undo = getCurrentTab().getUndoManager();
|
||||||
UndoManager undo = textarea.getUndoManager();
|
|
||||||
|
|
||||||
if (undo.canUndo()) {
|
if (undo.canUndo()) {
|
||||||
this.setEnabled(true);
|
this.setEnabled(true);
|
||||||
@ -1621,7 +1515,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
try {
|
try {
|
||||||
textarea.redoLastAction();
|
getCurrentTab().handleRedo();
|
||||||
sketch.setModified(true);
|
sketch.setModified(true);
|
||||||
} catch (CannotRedoException ex) {
|
} catch (CannotRedoException ex) {
|
||||||
//System.out.println("Unable to redo: " + ex);
|
//System.out.println("Unable to redo: " + ex);
|
||||||
@ -1630,7 +1524,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void updateRedoState() {
|
protected void updateRedoState() {
|
||||||
UndoManager undo = textarea.getUndoManager();
|
UndoManager undo = getCurrentTab().getUndoManager();
|
||||||
|
|
||||||
if (undo.canRedo()) {
|
if (undo.canRedo()) {
|
||||||
redoItem.setEnabled(true);
|
redoItem.setEnabled(true);
|
||||||
@ -1677,240 +1571,82 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
return sketch;
|
return sketch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the TextArea object for use (not recommended). This should only
|
* Gets the currently displaying tab.
|
||||||
* be used in obscure cases that really need to hack the internals of the
|
|
||||||
* JEditTextArea. Most tools should only interface via the get/set functions
|
|
||||||
* found in this class. This will maintain compatibility with future releases,
|
|
||||||
* which will not use TextArea.
|
|
||||||
*/
|
*/
|
||||||
public SketchTextArea getTextArea() {
|
public EditorTab getCurrentTab() {
|
||||||
return textarea;
|
return tabs.get(currentTabIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the contents of the current buffer. Used by the Sketch class.
|
|
||||||
*/
|
|
||||||
public String getText() {
|
|
||||||
return textarea.getText();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace the entire contents of the front-most tab.
|
|
||||||
*/
|
|
||||||
public void setText(String what) {
|
|
||||||
textarea.setText(what);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called to update the text but not switch to a different set of code
|
|
||||||
* (which would affect the undo manager).
|
|
||||||
*/
|
|
||||||
// public void setText2(String what, int start, int stop) {
|
|
||||||
// beginCompoundEdit();
|
|
||||||
// textarea.setText(what);
|
|
||||||
// endCompoundEdit();
|
|
||||||
//
|
|
||||||
// // make sure that a tool isn't asking for a bad location
|
|
||||||
// start = Math.max(0, Math.min(start, textarea.getDocumentLength()));
|
|
||||||
// stop = Math.max(0, Math.min(start, textarea.getDocumentLength()));
|
|
||||||
// textarea.select(start, stop);
|
|
||||||
//
|
|
||||||
// textarea.requestFocus(); // get the caret blinking
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
public String getSelectedText() {
|
|
||||||
return textarea.getSelectedText();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setSelectedText(String what) {
|
|
||||||
textarea.replaceSelection(what);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSelection(int start, int stop) {
|
|
||||||
textarea.select(start, stop);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the beginning point of the current selection.
|
|
||||||
*/
|
|
||||||
public int getSelectionStart() {
|
|
||||||
return textarea.getSelectionStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the end point of the current selection.
|
|
||||||
*/
|
|
||||||
public int getSelectionStop() {
|
|
||||||
return textarea.getSelectionEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get text for a specified line.
|
|
||||||
*/
|
|
||||||
private String getLineText(int line) {
|
|
||||||
try {
|
|
||||||
return textarea.getText(textarea.getLineStartOffset(line), textarea.getLineEndOffset(line));
|
|
||||||
} catch (BadLocationException e) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public int getScrollPosition() {
|
|
||||||
return scrollPane.getVerticalScrollBar().getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
/**
|
||||||
|
* Change the currently displayed tab.
|
||||||
|
* Note that the GUI might not update immediately, since this needs
|
||||||
|
* to run in the Event dispatch thread.
|
||||||
|
* @param index The index of the tab to select
|
||||||
|
*/
|
||||||
|
public void selectTab(final int index) {
|
||||||
|
currentTabIndex = index;
|
||||||
|
undoAction.updateUndoState();
|
||||||
|
redoAction.updateRedoState();
|
||||||
|
updateTitle();
|
||||||
|
|
||||||
|
// This must be run in the GUI thread
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
codePanel.removeAll();
|
||||||
|
codePanel.add(tabs.get(index), BorderLayout.CENTER);
|
||||||
|
tabs.get(index).requestFocus(); // get the caret blinking
|
||||||
|
// For some reason, these are needed. Revalidate says it should be
|
||||||
|
// automatically called when components are added or removed, but without
|
||||||
|
// it, the component switched to is not displayed. repaint() is needed to
|
||||||
|
// clear the entire text area of any previous text.
|
||||||
|
codePanel.revalidate();
|
||||||
|
codePanel.repaint();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public EditorTab findTab(final SketchCode doc) {
|
||||||
|
return tabs.get(findTabIndex(doc));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int findTabIndex(final SketchCode doc) {
|
||||||
|
for (int i = 0; i < tabs.size(); ++i) {
|
||||||
|
if (tabs.get(i).getSketchCode() == doc)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sketchLoaded(Sketch sketch) {
|
||||||
|
tabs.clear();
|
||||||
|
currentTabIndex = -1;
|
||||||
|
tabs.ensureCapacity(sketch.getCodeCount());
|
||||||
|
for (SketchCode code : sketch.getCodes()) {
|
||||||
|
try {
|
||||||
|
addTab(code);
|
||||||
|
} catch(IOException e) {
|
||||||
|
// TODO: Improve / move error handling
|
||||||
|
System.err.println(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch between tabs, this swaps out the Document object
|
* Switch between tabs, this swaps out the Document object
|
||||||
* that's currently being manipulated.
|
* that's currently being manipulated.
|
||||||
*/
|
*/
|
||||||
protected void setCode(final SketchCodeDocument codeDoc) {
|
protected void setCode(final SketchCodeDocument codeDoc) {
|
||||||
RSyntaxDocument document = (RSyntaxDocument) codeDoc.getDocument();
|
selectTab(findTabIndex(codeDoc.getCode()));
|
||||||
|
|
||||||
if (document == null) { // this document not yet inited
|
|
||||||
document = new RSyntaxDocument(new ArduinoTokenMakerFactory(base.getPdeKeywords()), RSyntaxDocument.SYNTAX_STYLE_CPLUSPLUS);
|
|
||||||
document.putProperty(PlainDocument.tabSizeAttribute, PreferencesData.getInteger("editor.tabs.size"));
|
|
||||||
|
|
||||||
// insert the program text into the document object
|
|
||||||
try {
|
|
||||||
document.insertString(0, codeDoc.getCode().getProgram(), null);
|
|
||||||
} catch (BadLocationException bl) {
|
|
||||||
bl.printStackTrace();
|
|
||||||
}
|
|
||||||
// set up this guy's own undo manager
|
|
||||||
// code.undo = new UndoManager();
|
|
||||||
|
|
||||||
codeDoc.setDocument(document);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(codeDoc.getUndo() == null){
|
protected void addTab(SketchCode code) throws IOException {
|
||||||
codeDoc.setUndo(new LastUndoableEditAwareUndoManager(textarea, this));
|
EditorTab tab = new EditorTab(this, code);
|
||||||
document.addUndoableEditListener(codeDoc.getUndo());
|
tabs.add(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the document object that's in use
|
|
||||||
textarea.switchDocument(document, codeDoc.getUndo());
|
|
||||||
|
|
||||||
// HACK multiple tabs: for update Listeners of Gutter, forcin call: Gutter.setTextArea(RTextArea)
|
|
||||||
// BUG: https://github.com/bobbylight/RSyntaxTextArea/issues/84
|
|
||||||
scrollPane.setViewportView(textarea);
|
|
||||||
|
|
||||||
textarea.select(codeDoc.getSelectionStart(), codeDoc.getSelectionStop());
|
|
||||||
textarea.requestFocus(); // get the caret blinking
|
|
||||||
|
|
||||||
final int position = codeDoc.getScrollPosition();
|
|
||||||
|
|
||||||
// invokeLater: Expect the document to be rendered correctly to set the new position
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
scrollPane.getVerticalScrollBar().setValue(position);
|
|
||||||
undoAction.updateUndoState();
|
|
||||||
redoAction.updateRedoState();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
updateTitle();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
|
||||||
|
void handleFindReference(ActionEvent e) {
|
||||||
/**
|
String text = getCurrentTab().getCurrentKeyword();
|
||||||
* Implements Edit → Cut.
|
|
||||||
*/
|
|
||||||
private void handleCut() {
|
|
||||||
textarea.cut();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void handleDiscourseCopy() {
|
|
||||||
new DiscourseFormat(Editor.this, false).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void handleHTMLCopy() {
|
|
||||||
new DiscourseFormat(Editor.this, true).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void handleCommentUncomment() {
|
|
||||||
|
|
||||||
Action action = textarea.getActionMap().get(RSyntaxTextAreaEditorKit.rstaToggleCommentAction);
|
|
||||||
action.actionPerformed(null);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void handleIndentOutdent(boolean indent) {
|
|
||||||
if (indent) {
|
|
||||||
Action action = textarea.getActionMap().get(SketchTextAreaEditorKit.rtaIncreaseIndentAction);
|
|
||||||
action.actionPerformed(null);
|
|
||||||
} else {
|
|
||||||
Action action = textarea.getActionMap().get(RSyntaxTextAreaEditorKit.rstaDecreaseIndentAction);
|
|
||||||
action.actionPerformed(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCurrentKeyword() {
|
|
||||||
String text = "";
|
|
||||||
if (textarea.getSelectedText() != null)
|
|
||||||
text = textarea.getSelectedText().trim();
|
|
||||||
|
|
||||||
try {
|
|
||||||
int current = textarea.getCaretPosition();
|
|
||||||
int startOffset = 0;
|
|
||||||
int endIndex = current;
|
|
||||||
String tmp = textarea.getDocument().getText(current, 1);
|
|
||||||
// TODO probably a regexp that matches Arduino lang special chars
|
|
||||||
// already exists.
|
|
||||||
String regexp = "[\\s\\n();\\\\.!='\\[\\]{}]";
|
|
||||||
|
|
||||||
while (!tmp.matches(regexp)) {
|
|
||||||
endIndex++;
|
|
||||||
tmp = textarea.getDocument().getText(endIndex, 1);
|
|
||||||
}
|
|
||||||
// For some reason document index start at 2.
|
|
||||||
// if( current - start < 2 ) return;
|
|
||||||
|
|
||||||
tmp = "";
|
|
||||||
while (!tmp.matches(regexp)) {
|
|
||||||
startOffset++;
|
|
||||||
if (current - startOffset < 0) {
|
|
||||||
tmp = textarea.getDocument().getText(0, 1);
|
|
||||||
break;
|
|
||||||
} else
|
|
||||||
tmp = textarea.getDocument().getText(current - startOffset, 1);
|
|
||||||
}
|
|
||||||
startOffset--;
|
|
||||||
|
|
||||||
int length = endIndex - current + startOffset;
|
|
||||||
text = textarea.getDocument().getText(current - startOffset, length);
|
|
||||||
|
|
||||||
} catch (BadLocationException bl) {
|
|
||||||
bl.printStackTrace();
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleFindReference(ActionEvent e) {
|
|
||||||
String text = getCurrentKeyword();
|
|
||||||
|
|
||||||
String referenceFile = base.getPdeKeywords().getReference(text);
|
String referenceFile = base.getPdeKeywords().getReference(text);
|
||||||
if (referenceFile == null) {
|
if (referenceFile == null) {
|
||||||
@ -2000,12 +1736,13 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeAllLineHighlights() {
|
public void removeAllLineHighlights() {
|
||||||
textarea.removeAllLineHighlights();
|
for (EditorTab tab : tabs)
|
||||||
|
tab.getTextArea().removeAllLineHighlights();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLineHighlight(int line) throws BadLocationException {
|
public void addLineHighlight(int line) throws BadLocationException {
|
||||||
textarea.addLineHighlight(line, new Color(1, 0, 0, 0.2f));
|
getCurrentTab().getTextArea().addLineHighlight(line, new Color(1, 0, 0, 0.2f));
|
||||||
textarea.setCaretPosition(textarea.getLineStartOffset(line));
|
getCurrentTab().getTextArea().setCaretPosition(getCurrentTab().getTextArea().getLineStartOffset(line));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DefaultStopHandler implements Runnable {
|
private class DefaultStopHandler implements Runnable {
|
||||||
@ -2130,11 +1867,10 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
untitled = false;
|
untitled = false;
|
||||||
|
|
||||||
sketch.setCurrentCode(codeIndex);
|
sketch.setCurrentCode(codeIndex);
|
||||||
textarea.select(selStart, selStop);
|
getCurrentTab().setSelection(selStart, selStop);
|
||||||
scrollPane.getVerticalScrollBar().setValue(scrollPos);
|
getCurrentTab().setScrollPosition(scrollPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Second stage of open, occurs after having checked to see if the
|
* Second stage of open, occurs after having checked to see if the
|
||||||
* modifications (if any) to the previous sketch need to be saved.
|
* modifications (if any) to the previous sketch need to be saved.
|
||||||
@ -2205,6 +1941,7 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
Base.showWarning(tr("Error"), tr("Could not create the sketch."), e);
|
Base.showWarning(tr("Error"), tr("Could not create the sketch."), e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
header.rebuild();
|
header.rebuild();
|
||||||
updateTitle();
|
updateTitle();
|
||||||
// Disable untitled setting from previous document, if any
|
// Disable untitled setting from previous document, if any
|
||||||
@ -2842,9 +2579,9 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
PrinterJob printerJob = PrinterJob.getPrinterJob();
|
PrinterJob printerJob = PrinterJob.getPrinterJob();
|
||||||
if (pageFormat != null) {
|
if (pageFormat != null) {
|
||||||
//System.out.println("setting page format " + pageFormat);
|
//System.out.println("setting page format " + pageFormat);
|
||||||
printerJob.setPrintable(textarea, pageFormat);
|
printerJob.setPrintable(getCurrentTab().getTextArea(), pageFormat);
|
||||||
} else {
|
} else {
|
||||||
printerJob.setPrintable(textarea);
|
printerJob.setPrintable(getCurrentTab().getTextArea());
|
||||||
}
|
}
|
||||||
// set the name of the job to the code name
|
// set the name of the job to the code name
|
||||||
printerJob.setJobName(sketch.getCurrentCode().getPrettyName());
|
printerJob.setJobName(sketch.getCurrentCode().getPrettyName());
|
||||||
@ -2897,17 +2634,17 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
if (re.hasCodeLine()) {
|
if (re.hasCodeLine()) {
|
||||||
int line = re.getCodeLine();
|
int line = re.getCodeLine();
|
||||||
// subtract one from the end so that the \n ain't included
|
// subtract one from the end so that the \n ain't included
|
||||||
if (line >= textarea.getLineCount()) {
|
if (line >= getCurrentTab().getTextArea().getLineCount()) {
|
||||||
// The error is at the end of this current chunk of code,
|
// The error is at the end of this current chunk of code,
|
||||||
// so the last line needs to be selected.
|
// so the last line needs to be selected.
|
||||||
line = textarea.getLineCount() - 1;
|
line = getCurrentTab().getTextArea().getLineCount() - 1;
|
||||||
if (getLineText(line).length() == 0) {
|
if (getCurrentTab().getLineText(line).length() == 0) {
|
||||||
// The last line may be zero length, meaning nothing to select.
|
// The last line may be zero length, meaning nothing to select.
|
||||||
// If so, back up one more line.
|
// If so, back up one more line.
|
||||||
line--;
|
line--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (line < 0 || line >= textarea.getLineCount()) {
|
if (line < 0 || line >= getCurrentTab().getTextArea().getLineCount()) {
|
||||||
System.err.println(I18n.format(tr("Bad error line: {0}"), line));
|
System.err.println(I18n.format(tr("Bad error line: {0}"), line));
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@ -2952,7 +2689,6 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
statusNotice(EMPTY);
|
statusNotice(EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
|
||||||
protected void onBoardOrPortChange() {
|
protected void onBoardOrPortChange() {
|
||||||
@ -2966,110 +2702,4 @@ public class Editor extends JFrame implements RunnerListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void configurePopupMenu(final SketchTextArea textarea){
|
|
||||||
|
|
||||||
JPopupMenu menu = textarea.getPopupMenu();
|
|
||||||
|
|
||||||
menu.addSeparator();
|
|
||||||
|
|
||||||
JMenuItem item = createToolMenuItem("cc.arduino.packages.formatter.AStyle");
|
|
||||||
if (item == null) {
|
|
||||||
throw new NullPointerException("Tool cc.arduino.packages.formatter.AStyle unavailable");
|
|
||||||
}
|
|
||||||
item.setName("menuToolsAutoFormat");
|
|
||||||
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
item = newJMenuItem(tr("Comment/Uncomment"), '/');
|
|
||||||
item.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
handleCommentUncomment();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
item = newJMenuItem(tr("Increase Indent"), ']');
|
|
||||||
item.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
handleIndentOutdent(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
item = newJMenuItem(tr("Decrease Indent"), '[');
|
|
||||||
item.setName("menuDecreaseIndent");
|
|
||||||
item.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
handleIndentOutdent(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
item = new JMenuItem(tr("Copy for Forum"));
|
|
||||||
item.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
handleDiscourseCopy();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
item = new JMenuItem(tr("Copy as HTML"));
|
|
||||||
item.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
handleHTMLCopy();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
final JMenuItem referenceItem = new JMenuItem(tr("Find in Reference"));
|
|
||||||
referenceItem.addActionListener(this::handleFindReference);
|
|
||||||
menu.add(referenceItem);
|
|
||||||
|
|
||||||
final JMenuItem openURLItem = new JMenuItem(tr("Open URL"));
|
|
||||||
openURLItem.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
Base.openURL(e.getActionCommand());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(openURLItem);
|
|
||||||
|
|
||||||
menu.addPopupMenuListener(new PopupMenuListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
|
|
||||||
String referenceFile = base.getPdeKeywords().getReference(getCurrentKeyword());
|
|
||||||
referenceItem.setEnabled(referenceFile != null);
|
|
||||||
|
|
||||||
int offset = textarea.getCaretPosition();
|
|
||||||
org.fife.ui.rsyntaxtextarea.Token token = RSyntaxUtilities.getTokenAtOffset(textarea, offset);
|
|
||||||
if (token != null && token.isHyperlink()) {
|
|
||||||
openURLItem.setEnabled(true);
|
|
||||||
openURLItem.setActionCommand(token.getLexeme());
|
|
||||||
} else {
|
|
||||||
openURLItem.setEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void popupMenuCanceled(PopupMenuEvent e) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void goToLine(int line) {
|
|
||||||
if (line <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
textarea.setCaretPosition(textarea.getLineStartOffset(line - 1));
|
|
||||||
} catch (BadLocationException e) {
|
|
||||||
//ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
481
app/src/processing/app/EditorTab.java
Normal file
481
app/src/processing/app/EditorTab.java
Normal file
@ -0,0 +1,481 @@
|
|||||||
|
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Part of the Arduino project - http://www.arduino.cc
|
||||||
|
|
||||||
|
Copyright (c) 2015 Matthijs Kooijman
|
||||||
|
Copyright (c) 2004-09 Ben Fry and Casey Reas
|
||||||
|
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License version 2
|
||||||
|
as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package processing.app;
|
||||||
|
|
||||||
|
import static processing.app.I18n.tr;
|
||||||
|
import static processing.app.Theme.scale;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.swing.Action;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
|
import javax.swing.ToolTipManager;
|
||||||
|
import javax.swing.border.MatteBorder;
|
||||||
|
import javax.swing.event.PopupMenuEvent;
|
||||||
|
import javax.swing.event.PopupMenuListener;
|
||||||
|
import javax.swing.text.BadLocationException;
|
||||||
|
import javax.swing.text.Element;
|
||||||
|
import javax.swing.text.PlainDocument;
|
||||||
|
import javax.swing.undo.UndoManager;
|
||||||
|
|
||||||
|
import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;
|
||||||
|
import org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaEditorKit;
|
||||||
|
import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;
|
||||||
|
import org.fife.ui.rtextarea.Gutter;
|
||||||
|
import org.fife.ui.rtextarea.RTextScrollPane;
|
||||||
|
|
||||||
|
import cc.arduino.UpdatableBoardsLibsFakeURLsHandler;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Single tab, editing a single file, in the main window.
|
||||||
|
*/
|
||||||
|
public class EditorTab extends JPanel {
|
||||||
|
protected Editor editor;
|
||||||
|
protected SketchTextArea textarea;
|
||||||
|
protected RTextScrollPane scrollPane;
|
||||||
|
protected SketchCode code;
|
||||||
|
|
||||||
|
public EditorTab(Editor editor, SketchCode code) throws IOException {
|
||||||
|
super(new BorderLayout());
|
||||||
|
this.editor = editor;
|
||||||
|
this.code = code;
|
||||||
|
this.textarea = createTextArea();
|
||||||
|
this.scrollPane = createScrollPane(this.textarea);
|
||||||
|
applyPreferences();
|
||||||
|
add(this.scrollPane, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
UndoManager undo = new LastUndoableEditAwareUndoManager(this.textarea, this.editor);
|
||||||
|
((RSyntaxDocument)textarea.getDocument()).addUndoableEditListener(undo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RSyntaxDocument createDocument() {
|
||||||
|
RSyntaxDocument document = new RSyntaxDocument(new ArduinoTokenMakerFactory(editor.base.getPdeKeywords()), RSyntaxDocument.SYNTAX_STYLE_CPLUSPLUS);
|
||||||
|
document.putProperty(PlainDocument.tabSizeAttribute, PreferencesData.getInteger("editor.tabs.size"));
|
||||||
|
|
||||||
|
// insert the program text into the document object
|
||||||
|
try {
|
||||||
|
document.insertString(0, code.getProgram(), null);
|
||||||
|
} catch (BadLocationException bl) {
|
||||||
|
bl.printStackTrace();
|
||||||
|
}
|
||||||
|
((SketchCodeDocument) code.getMetadata()).setDocument(document);
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RTextScrollPane createScrollPane(SketchTextArea textArea) throws IOException {
|
||||||
|
RTextScrollPane scrollPane = new RTextScrollPane(textArea, true);
|
||||||
|
scrollPane.setBorder(new MatteBorder(0, 6, 0, 0, Theme.getColor("editor.bgcolor")));
|
||||||
|
scrollPane.setViewportBorder(BorderFactory.createEmptyBorder());
|
||||||
|
scrollPane.setLineNumbersEnabled(PreferencesData.getBoolean("editor.linenumbers"));
|
||||||
|
scrollPane.setIconRowHeaderEnabled(false);
|
||||||
|
|
||||||
|
Gutter gutter = scrollPane.getGutter();
|
||||||
|
gutter.setBookmarkingEnabled(false);
|
||||||
|
//gutter.setBookmarkIcon(CompletionsRenderer.getIcon(CompletionType.TEMPLATE));
|
||||||
|
gutter.setIconRowHeaderInheritsGutterBackground(true);
|
||||||
|
|
||||||
|
return scrollPane;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SketchTextArea createTextArea() throws IOException {
|
||||||
|
RSyntaxDocument document = createDocument();
|
||||||
|
final SketchTextArea textArea = new SketchTextArea(document, editor.base.getPdeKeywords());
|
||||||
|
textArea.setName("editor");
|
||||||
|
textArea.setFocusTraversalKeysEnabled(false);
|
||||||
|
//textArea.requestFocusInWindow();
|
||||||
|
textArea.setMarkOccurrences(PreferencesData.getBoolean("editor.advanced"));
|
||||||
|
textArea.setMarginLineEnabled(false);
|
||||||
|
textArea.setCodeFoldingEnabled(PreferencesData.getBoolean("editor.code_folding"));
|
||||||
|
textArea.setAntiAliasingEnabled(PreferencesData.getBoolean("editor.antialias"));
|
||||||
|
textArea.setTabsEmulated(PreferencesData.getBoolean("editor.tabs.expand"));
|
||||||
|
textArea.setTabSize(PreferencesData.getInteger("editor.tabs.size"));
|
||||||
|
textArea.addHyperlinkListener(evt -> {
|
||||||
|
try {
|
||||||
|
UpdatableBoardsLibsFakeURLsHandler boardLibHandler = new UpdatableBoardsLibsFakeURLsHandler(editor.base);
|
||||||
|
boardLibHandler.openBoardLibManager(evt.getURL());
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
try {
|
||||||
|
editor.platform.openURL(editor.getSketch().getFolder(), evt.getURL().toExternalForm());
|
||||||
|
} catch (Exception f) {
|
||||||
|
Base.showWarning(f.getMessage(), f.getMessage(), f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
textArea.addCaretListener(e -> {
|
||||||
|
Element root = textArea.getDocument().getDefaultRootElement();
|
||||||
|
int lineStart = root.getElementIndex(e.getMark());
|
||||||
|
int lineEnd = root.getElementIndex(e.getDot());
|
||||||
|
|
||||||
|
editor.lineStatus.set(lineStart, lineEnd);
|
||||||
|
});
|
||||||
|
|
||||||
|
ToolTipManager.sharedInstance().registerComponent(textArea);
|
||||||
|
|
||||||
|
configurePopupMenu(textArea);
|
||||||
|
return textArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configurePopupMenu(final SketchTextArea textarea){
|
||||||
|
|
||||||
|
JPopupMenu menu = textarea.getPopupMenu();
|
||||||
|
|
||||||
|
menu.addSeparator();
|
||||||
|
|
||||||
|
JMenuItem item = editor.createToolMenuItem("cc.arduino.packages.formatter.AStyle");
|
||||||
|
if (item == null) {
|
||||||
|
throw new NullPointerException("Tool cc.arduino.packages.formatter.AStyle unavailable");
|
||||||
|
}
|
||||||
|
item.setName("menuToolsAutoFormat");
|
||||||
|
|
||||||
|
menu.add(item);
|
||||||
|
|
||||||
|
item = new JMenuItem(tr("Comment/Uncomment"), '/');
|
||||||
|
item.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
handleCommentUncomment();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.add(item);
|
||||||
|
|
||||||
|
item = new JMenuItem(tr("Increase Indent"), ']');
|
||||||
|
item.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
handleIndentOutdent(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.add(item);
|
||||||
|
|
||||||
|
item = new JMenuItem(tr("Decrease Indent"), '[');
|
||||||
|
item.setName("menuDecreaseIndent");
|
||||||
|
item.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
handleIndentOutdent(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.add(item);
|
||||||
|
|
||||||
|
item = new JMenuItem(tr("Copy for Forum"));
|
||||||
|
item.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
handleDiscourseCopy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.add(item);
|
||||||
|
|
||||||
|
item = new JMenuItem(tr("Copy as HTML"));
|
||||||
|
item.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
handleHTMLCopy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.add(item);
|
||||||
|
|
||||||
|
final JMenuItem referenceItem = new JMenuItem(tr("Find in Reference"));
|
||||||
|
referenceItem.addActionListener(editor::handleFindReference);
|
||||||
|
menu.add(referenceItem);
|
||||||
|
|
||||||
|
final JMenuItem openURLItem = new JMenuItem(tr("Open URL"));
|
||||||
|
openURLItem.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
Base.openURL(e.getActionCommand());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.add(openURLItem);
|
||||||
|
|
||||||
|
menu.addPopupMenuListener(new PopupMenuListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
|
||||||
|
String referenceFile = editor.base.getPdeKeywords().getReference(getCurrentKeyword());
|
||||||
|
referenceItem.setEnabled(referenceFile != null);
|
||||||
|
|
||||||
|
int offset = textarea.getCaretPosition();
|
||||||
|
org.fife.ui.rsyntaxtextarea.Token token = RSyntaxUtilities.getTokenAtOffset(textarea, offset);
|
||||||
|
if (token != null && token.isHyperlink()) {
|
||||||
|
openURLItem.setEnabled(true);
|
||||||
|
openURLItem.setActionCommand(token.getLexeme());
|
||||||
|
} else {
|
||||||
|
openURLItem.setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void popupMenuCanceled(PopupMenuEvent e) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyPreferences() {
|
||||||
|
textarea.setCodeFoldingEnabled(PreferencesData.getBoolean("editor.code_folding"));
|
||||||
|
scrollPane.setFoldIndicatorEnabled(PreferencesData.getBoolean("editor.code_folding"));
|
||||||
|
scrollPane.setLineNumbersEnabled(PreferencesData.getBoolean("editor.linenumbers"));
|
||||||
|
|
||||||
|
// apply the setting for 'use external editor'
|
||||||
|
if (PreferencesData.getBoolean("editor.external")) {
|
||||||
|
// disable line highlight and turn off the caret when disabling
|
||||||
|
textarea.setBackground(Theme.getColor("editor.external.bgcolor"));
|
||||||
|
textarea.setHighlightCurrentLine(false);
|
||||||
|
textarea.setEditable(false);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
textarea.setBackground(Theme.getColor("editor.bgcolor"));
|
||||||
|
textarea.setHighlightCurrentLine(Theme.getBoolean("editor.linehighlight"));
|
||||||
|
textarea.setEditable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply changes to the font size for the editor
|
||||||
|
Font editorFont = scale(PreferencesData.getFont("editor.font"));
|
||||||
|
textarea.setFont(editorFont);
|
||||||
|
scrollPane.getGutter().setLineNumberFont(editorFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateKeywords(PdeKeywords keywords) {
|
||||||
|
// update GUI for "Find In Reference"
|
||||||
|
textarea.setKeywords(keywords);
|
||||||
|
// update document for syntax highlighting
|
||||||
|
RSyntaxDocument document = (RSyntaxDocument) textarea.getDocument();
|
||||||
|
document.setTokenMakerFactory(new ArduinoTokenMakerFactory(keywords));
|
||||||
|
document.setSyntaxStyle(RSyntaxDocument.SYNTAX_STYLE_CPLUSPLUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the TextArea object for use (not recommended). This should only
|
||||||
|
* be used in obscure cases that really need to hack the internals of the
|
||||||
|
* JEditTextArea. Most tools should only interface via the get/set functions
|
||||||
|
* found in this class. This will maintain compatibility with future releases,
|
||||||
|
* which will not use TextArea.
|
||||||
|
*/
|
||||||
|
public SketchTextArea getTextArea() {
|
||||||
|
return textarea;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the sketch this tab is editing a file from.
|
||||||
|
*/
|
||||||
|
public Sketch getSketch() {
|
||||||
|
return editor.getSketch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the SketchCodeDocument that is being edited in this tab.
|
||||||
|
*/
|
||||||
|
public SketchCode getSketchCode() {
|
||||||
|
return this.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the contents of the text area.
|
||||||
|
*/
|
||||||
|
public String getText() {
|
||||||
|
return textarea.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace the entire contents of this tab.
|
||||||
|
*/
|
||||||
|
public void setText(String what) {
|
||||||
|
textarea.setText(what);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSelectedText() {
|
||||||
|
return textarea.getSelectedText();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setSelectedText(String what) {
|
||||||
|
textarea.replaceSelection(what);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelection(int start, int stop) {
|
||||||
|
textarea.select(start, stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getScrollPosition() {
|
||||||
|
return scrollPane.getVerticalScrollBar().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScrollPosition(int pos) {
|
||||||
|
scrollPane.getVerticalScrollBar().setValue(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the beginning point of the current selection.
|
||||||
|
*/
|
||||||
|
public int getSelectionStart() {
|
||||||
|
return textarea.getSelectionStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the end point of the current selection.
|
||||||
|
*/
|
||||||
|
public int getSelectionStop() {
|
||||||
|
return textarea.getSelectionEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get text for a specified line.
|
||||||
|
*/
|
||||||
|
public String getLineText(int line) {
|
||||||
|
try {
|
||||||
|
return textarea.getText(textarea.getLineStartOffset(line), textarea.getLineEndOffset(line));
|
||||||
|
} catch (BadLocationException e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jump to the given line
|
||||||
|
* @param line The line number to jump to, 1-based.
|
||||||
|
*/
|
||||||
|
public void goToLine(int line) {
|
||||||
|
if (line <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
textarea.setCaretPosition(textarea.getLineStartOffset(line - 1));
|
||||||
|
} catch (BadLocationException e) {
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleCut() {
|
||||||
|
textarea.cut();
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleCopy() {
|
||||||
|
textarea.copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void handlePaste() {
|
||||||
|
textarea.paste();
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleSelectAll() {
|
||||||
|
textarea.selectAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleCommentUncomment() {
|
||||||
|
Action action = textarea.getActionMap().get(RSyntaxTextAreaEditorKit.rstaToggleCommentAction);
|
||||||
|
action.actionPerformed(null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleDiscourseCopy() {
|
||||||
|
new DiscourseFormat(editor, this, false).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleHTMLCopy() {
|
||||||
|
new DiscourseFormat(editor, this, true).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleIndentOutdent(boolean indent) {
|
||||||
|
if (indent) {
|
||||||
|
Action action = textarea.getActionMap().get(SketchTextAreaEditorKit.rtaIncreaseIndentAction);
|
||||||
|
action.actionPerformed(null);
|
||||||
|
} else {
|
||||||
|
Action action = textarea.getActionMap().get(RSyntaxTextAreaEditorKit.rstaDecreaseIndentAction);
|
||||||
|
action.actionPerformed(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleUndo() {
|
||||||
|
textarea.undoLastAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleRedo() {
|
||||||
|
textarea.redoLastAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UndoManager getUndoManager() {
|
||||||
|
return textarea.getUndoManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCurrentKeyword() {
|
||||||
|
String text = "";
|
||||||
|
if (textarea.getSelectedText() != null)
|
||||||
|
text = textarea.getSelectedText().trim();
|
||||||
|
|
||||||
|
try {
|
||||||
|
int current = textarea.getCaretPosition();
|
||||||
|
int startOffset = 0;
|
||||||
|
int endIndex = current;
|
||||||
|
String tmp = textarea.getDocument().getText(current, 1);
|
||||||
|
// TODO probably a regexp that matches Arduino lang special chars
|
||||||
|
// already exists.
|
||||||
|
String regexp = "[\\s\\n();\\\\.!='\\[\\]{}]";
|
||||||
|
|
||||||
|
while (!tmp.matches(regexp)) {
|
||||||
|
endIndex++;
|
||||||
|
tmp = textarea.getDocument().getText(endIndex, 1);
|
||||||
|
}
|
||||||
|
// For some reason document index start at 2.
|
||||||
|
// if( current - start < 2 ) return;
|
||||||
|
|
||||||
|
tmp = "";
|
||||||
|
while (!tmp.matches(regexp)) {
|
||||||
|
startOffset++;
|
||||||
|
if (current - startOffset < 0) {
|
||||||
|
tmp = textarea.getDocument().getText(0, 1);
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
tmp = textarea.getDocument().getText(current - startOffset, 1);
|
||||||
|
}
|
||||||
|
startOffset--;
|
||||||
|
|
||||||
|
int length = endIndex - current + startOffset;
|
||||||
|
text = textarea.getDocument().getText(current - startOffset, length);
|
||||||
|
|
||||||
|
} catch (BadLocationException bl) {
|
||||||
|
bl.printStackTrace();
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestFocus() {
|
||||||
|
/** If focus is requested, focus the textarea instead. */
|
||||||
|
textarea.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -95,6 +95,7 @@ public class Sketch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void load(boolean forceUpdate) throws IOException {
|
protected void load(boolean forceUpdate) throws IOException {
|
||||||
|
current = null;
|
||||||
data.load();
|
data.load();
|
||||||
|
|
||||||
for (SketchCode code : data.getCodes()) {
|
for (SketchCode code : data.getCodes()) {
|
||||||
@ -104,6 +105,7 @@ public class Sketch {
|
|||||||
|
|
||||||
// set the main file to be the current tab
|
// set the main file to be the current tab
|
||||||
if (editor != null) {
|
if (editor != null) {
|
||||||
|
editor.sketchLoaded(this);
|
||||||
setCurrentCode(currentIndex, forceUpdate);
|
setCurrentCode(currentIndex, forceUpdate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -317,7 +319,7 @@ public class Sketch {
|
|||||||
|
|
||||||
// first get the contents of the editor text area
|
// first get the contents of the editor text area
|
||||||
if (current.getCode().isModified()) {
|
if (current.getCode().isModified()) {
|
||||||
current.getCode().setProgram(editor.getText());
|
current.getCode().setProgram(editor.getCurrentTab().getText());
|
||||||
try {
|
try {
|
||||||
// save this new SketchCode
|
// save this new SketchCode
|
||||||
current.getCode().save();
|
current.getCode().save();
|
||||||
@ -362,9 +364,9 @@ public class Sketch {
|
|||||||
// (unfortunately this will kill positions for carets etc)
|
// (unfortunately this will kill positions for carets etc)
|
||||||
editor.handleOpenUnchecked(newMainFile,
|
editor.handleOpenUnchecked(newMainFile,
|
||||||
currentIndex,
|
currentIndex,
|
||||||
editor.getSelectionStart(),
|
editor.getCurrentTab().getSelectionStart(),
|
||||||
editor.getSelectionStop(),
|
editor.getCurrentTab().getSelectionStop(),
|
||||||
editor.getScrollPosition());
|
editor.getCurrentTab().getScrollPosition());
|
||||||
|
|
||||||
// get the changes into the sketchbook menu
|
// get the changes into the sketchbook menu
|
||||||
// (re-enabled in 0115 to fix bug #332)
|
// (re-enabled in 0115 to fix bug #332)
|
||||||
@ -398,7 +400,17 @@ public class Sketch {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ensureExistence();
|
ensureExistence();
|
||||||
data.addCode((new SketchCodeDocument(this, newFile)).getCode());
|
SketchCode code = (new SketchCodeDocument(this, newFile)).getCode();
|
||||||
|
try {
|
||||||
|
editor.addTab(code);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Base.showWarning(tr("Error"),
|
||||||
|
I18n.format(
|
||||||
|
"Failed to open tab for new file"
|
||||||
|
), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data.addCode(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort the entries
|
// sort the entries
|
||||||
@ -542,7 +554,7 @@ public class Sketch {
|
|||||||
|
|
||||||
// first get the contents of the editor text area
|
// first get the contents of the editor text area
|
||||||
if (current.getCode().isModified()) {
|
if (current.getCode().isModified()) {
|
||||||
current.getCode().setProgram(editor.getText());
|
current.getCode().setProgram(editor.getCurrentTab().getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't do anything if not actually modified
|
// don't do anything if not actually modified
|
||||||
@ -698,7 +710,7 @@ public class Sketch {
|
|||||||
// grab the contents of the current tab before saving
|
// grab the contents of the current tab before saving
|
||||||
// first get the contents of the editor text area
|
// first get the contents of the editor text area
|
||||||
if (current.getCode().isModified()) {
|
if (current.getCode().isModified()) {
|
||||||
current.getCode().setProgram(editor.getText());
|
current.getCode().setProgram(editor.getCurrentTab().getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
// save the other tabs to their new location
|
// save the other tabs to their new location
|
||||||
@ -734,9 +746,9 @@ public class Sketch {
|
|||||||
|
|
||||||
editor.handleOpenUnchecked(newFile,
|
editor.handleOpenUnchecked(newFile,
|
||||||
currentIndex,
|
currentIndex,
|
||||||
editor.getSelectionStart(),
|
editor.getCurrentTab().getSelectionStart(),
|
||||||
editor.getSelectionStop(),
|
editor.getCurrentTab().getSelectionStop(),
|
||||||
editor.getScrollPosition());
|
editor.getCurrentTab().getScrollPosition());
|
||||||
|
|
||||||
// Name changed, rebuild the sketch menus
|
// Name changed, rebuild the sketch menus
|
||||||
//editor.sketchbook.rebuildMenusAsync();
|
//editor.sketchbook.rebuildMenusAsync();
|
||||||
@ -950,9 +962,9 @@ public class Sketch {
|
|||||||
buffer.append(">\n");
|
buffer.append(">\n");
|
||||||
}
|
}
|
||||||
buffer.append('\n');
|
buffer.append('\n');
|
||||||
buffer.append(editor.getText());
|
buffer.append(editor.getCurrentTab().getText());
|
||||||
editor.setText(buffer.toString());
|
editor.getCurrentTab().setText(buffer.toString());
|
||||||
editor.setSelection(0, 0); // scroll to start
|
editor.getCurrentTab().setSelection(0, 0); // scroll to start
|
||||||
setModified(true);
|
setModified(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -976,26 +988,12 @@ public class Sketch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the text currently being edited
|
// get the text currently being edited
|
||||||
if (current != null) {
|
if (current != null)
|
||||||
current.getCode().setProgram(editor.getText());
|
current.getCode().setProgram(editor.getCurrentTab().getText());
|
||||||
current.setSelectionStart(editor.getSelectionStart());
|
|
||||||
current.setSelectionStop(editor.getSelectionStop());
|
|
||||||
current.setScrollPosition(editor.getScrollPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
current = (SketchCodeDocument) data.getCode(which).getMetadata();
|
current = (SketchCodeDocument) data.getCode(which).getMetadata();
|
||||||
currentIndex = which;
|
currentIndex = which;
|
||||||
|
|
||||||
if (SwingUtilities.isEventDispatchThread()) {
|
|
||||||
editor.setCode(current);
|
editor.setCode(current);
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
SwingUtilities.invokeAndWait(() -> editor.setCode(current));
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
editor.header.rebuild();
|
editor.header.rebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1051,7 +1049,7 @@ public class Sketch {
|
|||||||
// make sure the user didn't hide the sketch folder
|
// make sure the user didn't hide the sketch folder
|
||||||
ensureExistence();
|
ensureExistence();
|
||||||
|
|
||||||
current.getCode().setProgram(editor.getText());
|
current.getCode().setProgram(editor.getCurrentTab().getText());
|
||||||
|
|
||||||
// TODO record history here
|
// TODO record history here
|
||||||
//current.history.record(program, SketchHistory.RUN);
|
//current.history.record(program, SketchHistory.RUN);
|
||||||
|
@ -5,23 +5,11 @@ import java.io.File;
|
|||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.DocumentEvent;
|
||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
import javax.swing.text.Document;
|
import javax.swing.text.Document;
|
||||||
import javax.swing.undo.UndoManager;
|
|
||||||
|
|
||||||
public class SketchCodeDocument implements DocumentListener{
|
public class SketchCodeDocument implements DocumentListener {
|
||||||
|
|
||||||
private SketchCode code;
|
private SketchCode code;
|
||||||
private Sketch sketch;
|
private Sketch sketch;
|
||||||
private Document document;
|
|
||||||
|
|
||||||
// Undo Manager for this tab, each tab keeps track of their own Editor.undo
|
|
||||||
// will be set to this object when this code is the tab that's currently the
|
|
||||||
// front.
|
|
||||||
private UndoManager undo;
|
|
||||||
|
|
||||||
// saved positions from last time this tab was used
|
|
||||||
private int selectionStart;
|
|
||||||
private int selectionStop;
|
|
||||||
private int scrollPosition;
|
|
||||||
|
|
||||||
public SketchCodeDocument(Sketch sketch, SketchCode code) {
|
public SketchCodeDocument(Sketch sketch, SketchCode code) {
|
||||||
this.code = code;
|
this.code = code;
|
||||||
@ -30,40 +18,7 @@ public class SketchCodeDocument implements DocumentListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public SketchCodeDocument(Sketch sketch, File file) {
|
public SketchCodeDocument(Sketch sketch, File file) {
|
||||||
this.code = new SketchCode(file, this);
|
this(sketch, new SketchCode(file));
|
||||||
this.sketch = sketch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UndoManager getUndo() {
|
|
||||||
return undo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUndo(UndoManager undo) {
|
|
||||||
this.undo = undo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSelectionStart() {
|
|
||||||
return selectionStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSelectionStart(int selectionStart) {
|
|
||||||
this.selectionStart = selectionStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSelectionStop() {
|
|
||||||
return selectionStop;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSelectionStop(int selectionStop) {
|
|
||||||
this.selectionStop = selectionStop;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getScrollPosition() {
|
|
||||||
return scrollPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setScrollPosition(int scrollPosition) {
|
|
||||||
this.scrollPosition = scrollPosition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SketchCode getCode() {
|
public SketchCode getCode() {
|
||||||
@ -74,12 +29,7 @@ public class SketchCodeDocument implements DocumentListener{
|
|||||||
this.code = code;
|
this.code = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Document getDocument() {
|
|
||||||
return document;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDocument(Document document) {
|
public void setDocument(Document document) {
|
||||||
this.document = document;
|
|
||||||
document.addDocumentListener(this);
|
document.addDocumentListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +46,7 @@ public class SketchCodeDocument implements DocumentListener{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void changedUpdate(DocumentEvent e) {
|
public void changedUpdate(DocumentEvent e) {
|
||||||
// Callback for when styles in the current document change.
|
// ignore
|
||||||
// This method is never called.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,6 @@ import org.fife.ui.rsyntaxtextarea.*;
|
|||||||
import org.fife.ui.rsyntaxtextarea.Token;
|
import org.fife.ui.rsyntaxtextarea.Token;
|
||||||
import org.fife.ui.rtextarea.RTextArea;
|
import org.fife.ui.rtextarea.RTextArea;
|
||||||
import org.fife.ui.rtextarea.RTextAreaUI;
|
import org.fife.ui.rtextarea.RTextAreaUI;
|
||||||
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.PreferencesData;
|
import processing.app.PreferencesData;
|
||||||
@ -47,9 +46,7 @@ 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;
|
||||||
import javax.swing.text.BadLocationException;
|
import javax.swing.text.BadLocationException;
|
||||||
import javax.swing.text.Document;
|
|
||||||
import javax.swing.text.Segment;
|
import javax.swing.text.Segment;
|
||||||
import javax.swing.undo.UndoManager;
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -73,7 +70,8 @@ public class SketchTextArea extends RSyntaxTextArea {
|
|||||||
|
|
||||||
private PdeKeywords pdeKeywords;
|
private PdeKeywords pdeKeywords;
|
||||||
|
|
||||||
public SketchTextArea(PdeKeywords pdeKeywords) throws IOException {
|
public SketchTextArea(RSyntaxDocument document, PdeKeywords pdeKeywords) throws IOException {
|
||||||
|
super(document);
|
||||||
this.pdeKeywords = pdeKeywords;
|
this.pdeKeywords = pdeKeywords;
|
||||||
installFeatures();
|
installFeatures();
|
||||||
fixCtrlDeleteBehavior();
|
fixCtrlDeleteBehavior();
|
||||||
@ -153,25 +151,6 @@ public class SketchTextArea extends RSyntaxTextArea {
|
|||||||
return this.getSelectedText() != null;
|
return this.getSelectedText() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void switchDocument(Document document, UndoManager newUndo) {
|
|
||||||
|
|
||||||
// HACK: Dont discard changes on curret UndoManager.
|
|
||||||
// BUG: https://github.com/bobbylight/RSyntaxTextArea/issues/84
|
|
||||||
setUndoManager(null); // bypass reset current undo manager...
|
|
||||||
|
|
||||||
super.setDocument(document);
|
|
||||||
|
|
||||||
setUndoManager((RUndoManager) newUndo);
|
|
||||||
|
|
||||||
// HACK: Complement previous hack (hide code folding on switch) | Drawback: Lose folding state
|
|
||||||
// if(sketch.getCodeCount() > 1 && textarea.isCodeFoldingEnabled()){
|
|
||||||
// textarea.setCodeFoldingEnabled(false);
|
|
||||||
// textarea.setCodeFoldingEnabled(true);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RTAMouseListener createMouseListener() {
|
protected RTAMouseListener createMouseListener() {
|
||||||
return new SketchTextAreaMouseListener(this);
|
return new SketchTextAreaMouseListener(this);
|
||||||
|
@ -25,6 +25,7 @@ package processing.app.tools;
|
|||||||
|
|
||||||
import org.fife.ui.rsyntaxtextarea.Token;
|
import org.fife.ui.rsyntaxtextarea.Token;
|
||||||
import processing.app.Editor;
|
import processing.app.Editor;
|
||||||
|
import processing.app.EditorTab;
|
||||||
import processing.app.syntax.SketchTextArea;
|
import processing.app.syntax.SketchTextArea;
|
||||||
|
|
||||||
import javax.swing.text.BadLocationException;
|
import javax.swing.text.BadLocationException;
|
||||||
@ -65,9 +66,9 @@ public class DiscourseFormat {
|
|||||||
* from the actual Processing Tab ready to send to the processing discourse
|
* from the actual Processing Tab ready to send to the processing discourse
|
||||||
* web (copy & paste)
|
* web (copy & paste)
|
||||||
*/
|
*/
|
||||||
public DiscourseFormat(Editor editor, boolean html) {
|
public DiscourseFormat(Editor editor, EditorTab tab, boolean html) {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
this.textarea = editor.getTextArea();
|
this.textarea = tab.getTextArea();
|
||||||
this.html = html;
|
this.html = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,10 +69,8 @@ public class FixEncoding implements Tool {
|
|||||||
SketchCode code = sketch.getCode(i);
|
SketchCode code = sketch.getCode(i);
|
||||||
code.setProgram(loadWithLocalEncoding(code.getFile()));
|
code.setProgram(loadWithLocalEncoding(code.getFile()));
|
||||||
code.setModified(true); // yes, because we want them to save this
|
code.setModified(true); // yes, because we want them to save this
|
||||||
|
editor.findTab(code).setText(code.getProgram());
|
||||||
}
|
}
|
||||||
// Update the currently visible program with its code
|
|
||||||
editor.setText(sketch.getCurrentCode().getProgram());
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
String msg =
|
String msg =
|
||||||
tr("An error occurred while trying to fix the file encoding.\nDo not attempt to save this sketch as it may overwrite\nthe old version. Use Open to re-open the sketch and try again.\n") +
|
tr("An error occurred while trying to fix the file encoding.\nDo not attempt to save this sketch as it may overwrite\nthe old version. Use Open to re-open the sketch and try again.\n") +
|
||||||
|
@ -55,7 +55,7 @@ public class BlockCommentGeneratesOneUndoActionTest extends AbstractGUITest {
|
|||||||
GuiActionRunner.execute(new GuiQuery<Frame>() {
|
GuiActionRunner.execute(new GuiQuery<Frame>() {
|
||||||
|
|
||||||
protected Frame executeInEDT() {
|
protected Frame executeInEDT() {
|
||||||
window.getEditor().handleCommentUncomment();
|
window.getEditor().getCurrentTab().handleCommentUncomment();
|
||||||
return window.getEditor();
|
return window.getEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user