Skip to content

Commit 86bb1fb

Browse files
committed
Initial implementation of bookmarks
Toggle on the left, find next with F3
1 parent 47b83d6 commit 86bb1fb

File tree

2 files changed

+136
-2
lines changed

2 files changed

+136
-2
lines changed

app/src/cc/arduino/view/preferences/Preferences.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ private void initComponents() {
130130
checkboxesContainer = new javax.swing.JPanel();
131131
displayLineNumbersBox = new javax.swing.JCheckBox();
132132
enableCodeFoldingBox = new javax.swing.JCheckBox();
133+
enableBookmarks = new javax.swing.JCheckBox();
133134
verifyUploadBox = new javax.swing.JCheckBox();
134135
externalEditorBox = new javax.swing.JCheckBox();
135136
cacheCompiledCore = new javax.swing.JCheckBox();
@@ -257,6 +258,9 @@ public void mouseEntered(java.awt.event.MouseEvent evt) {
257258
enableCodeFoldingBox.setText(tr("Enable Code Folding"));
258259
checkboxesContainer.add(enableCodeFoldingBox);
259260

261+
enableBookmarks.setText(tr("Enable Bookmarks"));
262+
checkboxesContainer.add(enableBookmarks);
263+
260264
verifyUploadBox.setText(tr("Verify code after upload"));
261265
checkboxesContainer.add(verifyUploadBox);
262266

@@ -732,6 +736,7 @@ private void autoScaleCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//
732736
private javax.swing.JLabel comboWarningsLabel;
733737
private javax.swing.JCheckBox displayLineNumbersBox;
734738
private javax.swing.JCheckBox enableCodeFoldingBox;
739+
private javax.swing.JCheckBox enableBookmarks;
735740
private javax.swing.JButton extendedAdditionalUrlFieldWindow;
736741
private javax.swing.JCheckBox externalEditorBox;
737742
private javax.swing.JCheckBox cacheCompiledCore;
@@ -833,6 +838,8 @@ private void savePreferencesData() {
833838

834839
PreferencesData.setBoolean("editor.code_folding", enableCodeFoldingBox.isSelected());
835840

841+
PreferencesData.setBoolean("editor.bookmarks", enableBookmarks.isSelected());
842+
836843
PreferencesData.setBoolean("upload.verify", verifyUploadBox.isSelected());
837844

838845
PreferencesData.setBoolean("editor.save_on_verify", saveVerifyUploadBox.isSelected());
@@ -909,6 +916,8 @@ private void showPrerefencesData() {
909916

910917
enableCodeFoldingBox.setSelected(PreferencesData.getBoolean("editor.code_folding"));
911918

919+
enableBookmarks.setSelected(PreferencesData.getBoolean("editor.bookmarks"));
920+
912921
verifyUploadBox.setSelected(PreferencesData.getBoolean("upload.verify"));
913922

914923
externalEditorBox.setSelected(PreferencesData.getBoolean("editor.external"));

app/src/processing/app/EditorTab.java

Lines changed: 127 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,28 @@
2828

2929
import java.awt.BorderLayout;
3030
import java.awt.Font;
31+
import java.awt.Toolkit;
3132
import java.awt.event.ActionEvent;
3233
import java.awt.event.ActionListener;
34+
import java.awt.event.InputEvent;
35+
import java.awt.event.KeyEvent;
3336
import java.awt.event.MouseWheelListener;
3437
import java.awt.event.MouseWheelEvent;
3538

3639
import java.io.IOException;
3740

3841
import javax.swing.Action;
3942
import javax.swing.BorderFactory;
43+
import javax.swing.Icon;
44+
import javax.swing.InputMap;
45+
import javax.swing.JComponent;
4046
import javax.swing.JMenuItem;
4147
import javax.swing.JPanel;
4248
import javax.swing.JPopupMenu;
49+
import javax.swing.KeyStroke;
50+
import javax.swing.SwingUtilities;
4351
import javax.swing.ToolTipManager;
52+
import javax.swing.UIManager;
4453
import javax.swing.border.MatteBorder;
4554
import javax.swing.event.PopupMenuEvent;
4655
import javax.swing.event.PopupMenuListener;
@@ -52,20 +61,29 @@
5261

5362
import static java.nio.file.StandardWatchEventKinds.*;
5463
import java.nio.file.WatchService;
64+
import java.util.ArrayList;
65+
import java.util.List;
5566
import java.nio.file.WatchKey;
5667
import java.nio.file.WatchEvent;
5768
import java.nio.file.FileSystems;
5869
import java.nio.file.Path;
5970
import java.io.File;
6071

6172
import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;
73+
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
6274
import org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaEditorKit;
6375
import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;
6476
import org.fife.ui.rtextarea.Gutter;
77+
import org.fife.ui.rtextarea.GutterIconInfo;
78+
import org.fife.ui.rtextarea.RTADefaultInputMap;
79+
import org.fife.ui.rtextarea.RTextArea;
80+
import org.fife.ui.rtextarea.RTextAreaEditorKit;
6581
import org.fife.ui.rtextarea.RTextScrollPane;
82+
import org.fife.ui.rtextarea.RecordableTextAction;
6683

6784
import cc.arduino.UpdatableBoardsLibsFakeURLsHandler;
6885
import processing.app.helpers.DocumentTextChangeListener;
86+
import processing.app.helpers.PreferencesMap;
6987
import processing.app.syntax.ArduinoTokenMakerFactory;
7088
import processing.app.syntax.PdeKeywords;
7189
import processing.app.syntax.SketchTextArea;
@@ -136,6 +154,8 @@ private RSyntaxDocument createDocument(String contents) {
136154
return document;
137155
}
138156

157+
public static final String rtaNextBookmarkAction = "RTA.NextBookmarkAction";
158+
139159
private RTextScrollPane createScrollPane(SketchTextArea textArea) throws IOException {
140160
RTextScrollPane scrollPane = new RTextScrollPane(textArea, true);
141161
scrollPane.setBorder(new MatteBorder(0, 6, 0, 0, Theme.getColor("editor.bgcolor")));
@@ -144,13 +164,118 @@ private RTextScrollPane createScrollPane(SketchTextArea textArea) throws IOExcep
144164
scrollPane.setIconRowHeaderEnabled(false);
145165

146166
Gutter gutter = scrollPane.getGutter();
147-
gutter.setBookmarkingEnabled(false);
148-
//gutter.setBookmarkIcon(CompletionsRenderer.getIcon(CompletionType.TEMPLATE));
167+
168+
if (PreferencesData.getBoolean("editor.bookmarks")) {
169+
gutter.setBookmarkingEnabled(true);
170+
gutter.setBookmarkIcon(CompletionsRenderer.getIcon(CompletionType.FUNCTION));
171+
InputMap map = SwingUtilities.getUIInputMap(textArea, JComponent.WHEN_FOCUSED);
172+
NextBookmarkAction action = new NextBookmarkAction(rtaNextBookmarkAction);
173+
map.put(KeyStroke.getKeyStroke(KeyEvent.VK_F3, 0), action);
174+
SwingUtilities.replaceUIInputMap(textArea,JComponent.WHEN_FOCUSED,map);
175+
}
176+
149177
gutter.setIconRowHeaderInheritsGutterBackground(true);
150178

151179
return scrollPane;
152180
}
153181

182+
public class GutterIconInfoTabs {
183+
GutterIconInfo bookmark;
184+
SketchFile file;
185+
RTextArea textArea;
186+
187+
public String toString( ) {
188+
return "File:" + file.getFileName() + " -- Line:" + bookmark.getMarkedOffset();
189+
}
190+
}
191+
192+
/**
193+
* Action that moves the caret to the next bookmark.
194+
*/
195+
public class NextBookmarkAction extends RecordableTextAction {
196+
197+
public NextBookmarkAction(String name) {
198+
super(name);
199+
}
200+
201+
@Override
202+
public void actionPerformedImpl(ActionEvent e, RTextArea textArea) {
203+
204+
Gutter gutter = RSyntaxUtilities.getGutter(textArea);
205+
206+
List<GutterIconInfoTabs> bookmarks = new ArrayList<GutterIconInfoTabs>();
207+
208+
try {
209+
210+
for (EditorTab tab : editor.getTabs()) {
211+
gutter = RSyntaxUtilities.getGutter(tab.getTextArea());
212+
213+
if (gutter!=null) {
214+
GutterIconInfo[] tabBookmarks = gutter.getBookmarks();
215+
for (GutterIconInfo element : tabBookmarks) {
216+
GutterIconInfoTabs bookmark = new GutterIconInfoTabs();
217+
bookmark.file = tab.getSketchFile();
218+
bookmark.bookmark = element;
219+
bookmark.textArea = tab.getTextArea();
220+
bookmarks.add(bookmark);
221+
}
222+
}
223+
}
224+
225+
if (bookmarks.size()==0) {
226+
UIManager.getLookAndFeel().
227+
provideErrorFeedback(textArea);
228+
return;
229+
}
230+
231+
GutterIconInfoTabs moveTo = null;
232+
int curLine = textArea.getCaretLineNumber();
233+
234+
for (int i=0; i<bookmarks.size(); i++) {
235+
GutterIconInfo bookmark = bookmarks.get(i).bookmark;
236+
int offs = bookmark.getMarkedOffset();
237+
int line = 0;
238+
int curTabIndex = editor.getCurrentTabIndex();
239+
int bookmarkTabIndex = editor.findTabIndex(bookmarks.get(i).file);
240+
if (curTabIndex == bookmarkTabIndex) {
241+
line = textArea.getLineOfOffset(offs);
242+
}
243+
if ((curTabIndex == bookmarkTabIndex && line>curLine) || (curTabIndex < bookmarkTabIndex)) {
244+
moveTo = bookmarks.get(i);
245+
break;
246+
}
247+
}
248+
if (moveTo==null) { // Loop back to beginning
249+
moveTo = bookmarks.get(0);
250+
}
251+
252+
editor.selectTab(editor.findTabIndex(moveTo.file));
253+
254+
int offs = moveTo.bookmark.getMarkedOffset();
255+
if (moveTo.textArea instanceof RSyntaxTextArea) {
256+
RSyntaxTextArea rsta = (RSyntaxTextArea)moveTo.textArea;
257+
if (rsta.isCodeFoldingEnabled()) {
258+
rsta.getFoldManager().
259+
ensureOffsetNotInClosedFold(offs);
260+
}
261+
}
262+
int line = moveTo.textArea.getLineOfOffset(offs);
263+
offs = moveTo.textArea.getLineStartOffset(line);
264+
moveTo.textArea.setCaretPosition(offs);
265+
266+
} catch (BadLocationException ble) { // Never happens
267+
UIManager.getLookAndFeel().
268+
provideErrorFeedback(textArea);
269+
ble.printStackTrace();
270+
}
271+
}
272+
273+
@Override
274+
public String getMacroID() {
275+
return getName();
276+
}
277+
}
278+
154279
private SketchTextArea createTextArea(RSyntaxDocument document)
155280
throws IOException {
156281
final SketchTextArea textArea = new SketchTextArea(document, editor.base.getPdeKeywords());

0 commit comments

Comments
 (0)