Skip to content

Commit 8873038

Browse files
committed
fix(gui): save current caret position and add it to tab code jump event (#2409)
1 parent bf58f03 commit 8873038

8 files changed

+62
-39
lines changed

jadx-gui/src/main/java/jadx/gui/ui/codearea/AbstractCodeArea.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,12 @@ private void highlightAllMatches(@Nullable String str) {
429429
SearchEngine.markAll(this, context);
430430
}
431431

432-
public JumpPosition getCurrentPosition() {
433-
return new JumpPosition(node, getCaretPosition());
432+
public @Nullable JumpPosition getCurrentPosition() {
433+
int pos = getCaretPosition();
434+
if (pos == 0) {
435+
return null;
436+
}
437+
return new JumpPosition(node, pos);
434438
}
435439

436440
public int getLineStartFor(int pos) throws BadLocationException {

jadx-gui/src/main/java/jadx/gui/ui/tab/ITabStatesListener.java

+18-1
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,35 @@
22

33
import java.util.List;
44

5+
import org.jetbrains.annotations.Nullable;
6+
57
import jadx.gui.ui.codearea.EditorViewState;
68
import jadx.gui.utils.JumpPosition;
79

10+
/**
11+
* Tabbed pane events listener
12+
*/
813
public interface ITabStatesListener {
914

15+
/**
16+
* Tab added to tabbed pane without become active (selected)
17+
*/
1018
default void onTabOpen(TabBlueprint blueprint) {
1119
}
1220

21+
/**
22+
* Tab become active (selected)
23+
*/
1324
default void onTabSelect(TabBlueprint blueprint) {
1425
}
1526

16-
default void onTabCodeJump(TabBlueprint blueprint, JumpPosition position) {
27+
/**
28+
* Caret position changes.
29+
*
30+
* @param prevPos previous caret position; can be null if unknown; can be from another tab
31+
* @param newPos new caret position, node refer to jump target node
32+
*/
33+
default void onTabCodeJump(TabBlueprint blueprint, @Nullable JumpPosition prevPos, JumpPosition newPos) {
1734
}
1835

1936
default void onTabSmaliJump(TabBlueprint blueprint, int pos, boolean debugMode) {

jadx-gui/src/main/java/jadx/gui/ui/tab/LogTabStates.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.List;
44

5+
import org.jetbrains.annotations.Nullable;
56
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
78

@@ -25,8 +26,8 @@ public void onTabClose(TabBlueprint blueprint) {
2526
}
2627

2728
@Override
28-
public void onTabCodeJump(TabBlueprint blueprint, JumpPosition position) {
29-
LOG.debug("onTabCodeJump: blueprint={}, position={}", blueprint, position);
29+
public void onTabCodeJump(TabBlueprint blueprint, @Nullable JumpPosition prevPos, JumpPosition newPos) {
30+
LOG.debug("onTabCodeJump: blueprint={}, prevPos={}, newPos={}", blueprint, prevPos, newPos);
3031
}
3132

3233
@Override

jadx-gui/src/main/java/jadx/gui/ui/tab/NavigationController.java

+4-18
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,10 @@ public NavigationController(MainWindow mainWindow) {
2020
}
2121

2222
public void navBack() {
23-
if (jumps.size() > 1) {
24-
jumps.updateCurPosition(mainWindow.getTabbedPane().getCurrentPosition());
25-
}
2623
jump(jumps.getPrev());
2724
}
2825

2926
public void navForward() {
30-
if (jumps.size() > 1) {
31-
jumps.updateCurPosition(mainWindow.getTabbedPane().getCurrentPosition());
32-
}
3327
jump(jumps.getNext());
3428
}
3529

@@ -40,28 +34,20 @@ private void jump(@Nullable JumpPosition pos) {
4034
}
4135

4236
@Override
43-
public void onTabCodeJump(TabBlueprint blueprint, JumpPosition position) {
44-
if (position.equals(jumps.getCurrent())) {
37+
public void onTabCodeJump(TabBlueprint blueprint, @Nullable JumpPosition prevPos, JumpPosition newPos) {
38+
if (newPos.equals(jumps.getCurrent())) {
4539
// ignore self-initiated jumps
4640
return;
4741
}
48-
saveCurrentPosition();
49-
jumps.addPosition(position);
42+
jumps.addPosition(prevPos);
43+
jumps.addPosition(newPos);
5044
}
5145

5246
@Override
5347
public void onTabSmaliJump(TabBlueprint blueprint, int pos, boolean debugMode) {
54-
saveCurrentPosition();
5548
// TODO: save smali jump
5649
}
5750

58-
private void saveCurrentPosition() {
59-
JumpPosition curPos = mainWindow.getTabbedPane().getCurrentPosition();
60-
if (curPos != null) {
61-
jumps.addPosition(curPos);
62-
}
63-
}
64-
6551
public void reset() {
6652
jumps.reset();
6753
}

jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,8 @@ public TabsController getTabsController() {
211211
private @Nullable ContentPanel showCode(JumpPosition jumpPos) {
212212
ContentPanel contentPanel = getContentPanel(jumpPos.getNode());
213213
if (contentPanel != null) {
214-
scrollToPos(contentPanel, jumpPos.getPos());
215214
selectTab(contentPanel);
215+
scrollToPos(contentPanel, jumpPos.getPos());
216216
}
217217
return contentPanel;
218218
}
@@ -224,8 +224,8 @@ private void scrollToPos(ContentPanel contentPanel, int pos) {
224224
}
225225
if (contentPanel instanceof AbstractCodeContentPanel) {
226226
AbstractCodeArea codeArea = ((AbstractCodeContentPanel) contentPanel).getCodeArea();
227-
codeArea.scrollToPos(pos);
228227
codeArea.requestFocus();
228+
codeArea.scrollToPos(pos);
229229
}
230230
}
231231

@@ -414,7 +414,7 @@ public void onTabSelect(TabBlueprint blueprint) {
414414
}
415415

416416
@Override
417-
public void onTabCodeJump(TabBlueprint blueprint, JumpPosition position) {
417+
public void onTabCodeJump(TabBlueprint blueprint, @Nullable JumpPosition prevPos, JumpPosition position) {
418418
showCode(position);
419419
}
420420

jadx-gui/src/main/java/jadx/gui/ui/tab/TabsController.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public class TabsController {
3737

3838
public TabsController(MainWindow mainWindow) {
3939
this.mainWindow = mainWindow;
40+
// addListener(new LogTabStates());
4041
}
4142

4243
public MainWindow getMainWindow() {
@@ -76,6 +77,10 @@ public TabBlueprint openTab(JNode node, boolean hidden) {
7677
}
7778

7879
public void selectTab(JNode node) {
80+
if (selectedTab != null && selectedTab.getNode() == node) {
81+
// already selected
82+
return;
83+
}
7984
TabBlueprint blueprint = openTab(node);
8085
selectedTab = blueprint;
8186
listeners.forEach(l -> l.onTabSelect(blueprint));
@@ -141,10 +146,11 @@ private void jumpToInnerClass(JNode node, JavaClass codeParent, JClass jumpCls)
141146
* Prefer {@link TabsController#codeJump(JNode)} method
142147
*/
143148
public void codeJump(JumpPosition pos) {
149+
JumpPosition currentPosition = mainWindow.getTabbedPane().getCurrentPosition();
144150
if (selectedTab == null || selectedTab.getNode() != pos.getNode()) {
145151
selectTab(pos.getNode());
146152
}
147-
listeners.forEach(l -> l.onTabCodeJump(selectedTab, pos));
153+
listeners.forEach(l -> l.onTabCodeJump(selectedTab, currentPosition, pos));
148154
}
149155

150156
public void smaliJump(JClass cls, int pos, boolean debugMode) {

jadx-gui/src/main/java/jadx/gui/utils/JumpManager.java

+20-11
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,40 @@
66
import org.jetbrains.annotations.Nullable;
77

88
public class JumpManager {
9+
/**
10+
* Maximum number of elements to store in a jump list
11+
*/
12+
private static final int MAX_JUMPS = 100;
913

10-
private final List<JumpPosition> list = new ArrayList<>();
14+
/**
15+
* This number of elements will be removed from the start if a list becomes bigger than MAX_JUMPS.
16+
* List grow most of the time, so removing should be done in big batches to not run very often.
17+
* Because of this, an effective jump history size will vary
18+
* from (MAX_JUMPS - LIST_SHRINK_COUNT) to MAX_JUMPS over time.
19+
*/
20+
private static final int LIST_SHRINK_COUNT = 50;
21+
22+
private final List<JumpPosition> list = new ArrayList<>(MAX_JUMPS);
1123
private int currentPos = 0;
1224

13-
public void addPosition(JumpPosition pos) {
14-
if (ignoreJump(pos)) {
25+
public void addPosition(@Nullable JumpPosition pos) {
26+
if (pos == null || ignoreJump(pos)) {
1527
return;
1628
}
1729
currentPos++;
1830
if (currentPos >= list.size()) {
1931
list.add(pos);
32+
if (list.size() >= MAX_JUMPS) {
33+
list.subList(0, LIST_SHRINK_COUNT).clear();
34+
}
2035
currentPos = list.size() - 1;
2136
} else {
37+
// discard forward history after navigating back and jumping to a new place
2238
list.set(currentPos, pos);
23-
int size = list.size();
24-
for (int i = currentPos + 1; i < size; i++) {
25-
list.set(i, null);
26-
}
39+
list.subList(currentPos + 1, list.size()).clear();
2740
}
2841
}
2942

30-
public void updateCurPosition(JumpPosition pos) {
31-
list.set(currentPos, pos);
32-
}
33-
3443
public int size() {
3544
return list.size();
3645
}

jadx-gui/src/main/java/jadx/gui/utils/JumpPosition.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@ public int hashCode() {
4747

4848
@Override
4949
public String toString() {
50-
return "Jump: " + node + " : " + pos;
50+
return "Jump{" + node + ":" + pos + '}';
5151
}
5252
}

0 commit comments

Comments
 (0)