fixed scroll panel on archive exit

This commit is contained in:
Radek Davidek 2026-02-20 15:57:15 +01:00
parent a92fe10581
commit 01b8edabd4

View File

@ -65,6 +65,8 @@ public class FilePanelTab extends JPanel {
// we can cleanup older temp directories when navigation changes.
private Path currentArchiveTempDir = null;
private File currentArchiveSourceFile = null;
private File archiveReturnDirectory = null;
private Point archiveReturnViewPosition = null;
private boolean inlineRenameActive = false;
private boolean active = false;
private final Map<String, Long> changeTimestamps = new HashMap<>();
@ -1397,6 +1399,7 @@ public class FilePanelTab extends JPanel {
}
public void showArchiveFile(File archive, String entryName) {
rememberArchiveReturnState(archive);
Path temp = extractArchiveToTemp(archive);
if (temp != null) {
// Delete any previous temp dir if different
@ -1408,6 +1411,11 @@ public class FilePanelTab extends JPanel {
currentArchiveTempDir = temp;
currentArchiveSourceFile = archive;
if (entryName == null || entryName.isBlank()) {
loadDirectory(temp.toFile(), true, true);
return;
}
File targetFile = new File(temp.toFile(), entryName);
File targetDir = targetFile.isDirectory() ? targetFile : targetFile.getParentFile();
@ -1420,6 +1428,8 @@ public class FilePanelTab extends JPanel {
} else {
loadDirectory(temp.toFile(), true, true);
}
} else {
clearArchiveReturnState();
}
}
@ -1494,8 +1504,9 @@ public class FilePanelTab extends JPanel {
if (item.getName().equals("..")) {
navigateUp();
} else if (FileOperations.isArchiveFile(item.getFile())) {
rememberArchiveReturnState(item.getFile());
Path temp = extractArchiveToTemp(item.getFile());
if (temp != null) {
if (temp != null) {
// Delete any previous temp dir if different
try {
if (currentArchiveTempDir != null && !currentArchiveTempDir.equals(temp)) {
@ -1505,6 +1516,8 @@ public class FilePanelTab extends JPanel {
currentArchiveTempDir = temp;
currentArchiveSourceFile = item.getFile();
loadDirectory(temp.toFile());
} else {
clearArchiveReturnState();
}
} else if (item.isDirectory()) {
loadDirectory(item.getFile());
@ -1633,6 +1646,7 @@ public class FilePanelTab extends JPanel {
if (item.getName().equals("..")) {
navigateUp();
} else if (FileOperations.isArchiveFile(item.getFile())) {
rememberArchiveReturnState(item.getFile());
Path temp = extractArchiveToTemp(item.getFile());
if (temp != null) {
try {
@ -1643,6 +1657,8 @@ public class FilePanelTab extends JPanel {
currentArchiveTempDir = temp;
currentArchiveSourceFile = item.getFile();
loadDirectory(temp.toFile(), true, true);
} else {
clearArchiveReturnState();
}
} else if (item.isDirectory()) {
loadDirectory(item.getFile());
@ -2007,10 +2023,17 @@ public class FilePanelTab extends JPanel {
deleteTempDirRecursively(currentArchiveTempDir);
currentArchiveTempDir = null;
currentArchiveSourceFile = null;
loadDirectory(parent, false);
// Select the archive file we just left
SwingUtilities.invokeLater(() -> selectItemByName(archiveName));
loadDirectory(parent, false, true, () -> {
// Restore original viewport position and keep focus on archive item.
// In BRIEF mode some selection listeners may still run later, so apply once more on EDT tail.
restoreArchiveReturnPosition();
selectItemByName(archiveName, true, false);
SwingUtilities.invokeLater(() -> {
restoreArchiveReturnPosition();
selectItemByName(archiveName, true, false);
clearArchiveReturnState();
});
});
}
return;
}
@ -2032,6 +2055,10 @@ public class FilePanelTab extends JPanel {
}
public void selectItemByName(String name, boolean requestFocus) {
selectItemByName(name, requestFocus, true);
}
private void selectItemByName(String name, boolean requestFocus, boolean scrollToItem) {
if (viewMode == ViewMode.BRIEF) {
// Re-calculate layout if needed before searching to ensure current mapping
if (tableModel.items.size() > 0 && (tableModel.briefColumns == 0 || tableModel.briefRowsPerColumn == 0)) {
@ -2047,7 +2074,9 @@ public class FilePanelTab extends JPanel {
if (column < fileTable.getColumnCount()) {
briefCurrentColumn = column;
fileTable.setRowSelectionInterval(row, row);
fileTable.scrollRectToVisible(fileTable.getCellRect(row, column, true));
if (scrollToItem) {
fileTable.scrollRectToVisible(fileTable.getCellRect(row, column, true));
}
fileTable.repaint();
if (requestFocus) {
fileTable.requestFocusInWindow();
@ -2062,7 +2091,9 @@ public class FilePanelTab extends JPanel {
FileItem item = tableModel.getItem(i);
if (item != null && item.getName().equalsIgnoreCase(name)) {
fileTable.setRowSelectionInterval(i, i);
fileTable.scrollRectToVisible(fileTable.getCellRect(i, 0, true));
if (scrollToItem) {
fileTable.scrollRectToVisible(fileTable.getCellRect(i, 0, true));
}
if (requestFocus) {
fileTable.requestFocusInWindow();
}
@ -2073,6 +2104,37 @@ public class FilePanelTab extends JPanel {
}
}
private void rememberArchiveReturnState(File archiveFile) {
if (archiveFile == null) return;
archiveReturnDirectory = archiveFile.getParentFile();
Rectangle visibleRect = fileTable.getVisibleRect();
archiveReturnViewPosition = (visibleRect != null) ? visibleRect.getLocation() : null;
}
private void restoreArchiveReturnPosition() {
if (archiveReturnViewPosition == null || archiveReturnDirectory == null || currentDirectory == null) return;
if (!currentDirectory.equals(archiveReturnDirectory)) return;
Point target = new Point(archiveReturnViewPosition);
if (fileTable.getParent() instanceof JViewport viewport) {
Dimension pref = fileTable.getPreferredSize();
int contentW = Math.max(fileTable.getWidth(), pref != null ? pref.width : 0);
int contentH = Math.max(fileTable.getHeight(), pref != null ? pref.height : 0);
int maxX = Math.max(0, contentW - viewport.getWidth());
int maxY = Math.max(0, contentH - viewport.getHeight());
target.x = Math.max(0, Math.min(target.x, maxX));
target.y = Math.max(0, Math.min(target.y, maxY));
viewport.setViewPosition(target);
} else {
fileTable.scrollRectToVisible(new Rectangle(target.x, target.y, 1, 1));
}
}
private void clearArchiveReturnState() {
archiveReturnDirectory = null;
archiveReturnViewPosition = null;
}
/**
* Public wrapper to select an item by name from outside this class.
* Useful for other UI components to request focusing a specific file.