From 868b33f175f841e36df0f4dd6d1fe0497d6e8857 Mon Sep 17 00:00:00 2001 From: Radek Davidek Date: Tue, 19 May 2026 10:19:16 +0200 Subject: [PATCH] UI fixes for brief view --- .../cz/kamma/kfmanager/ui/FilePanelTab.java | 95 +++++++++++++++---- .../cz/kamma/kfmanager/ui/MainWindow.java | 8 +- 2 files changed, 79 insertions(+), 24 deletions(-) diff --git a/src/main/java/cz/kamma/kfmanager/ui/FilePanelTab.java b/src/main/java/cz/kamma/kfmanager/ui/FilePanelTab.java index 37fd62a..d1bff22 100644 --- a/src/main/java/cz/kamma/kfmanager/ui/FilePanelTab.java +++ b/src/main/java/cz/kamma/kfmanager/ui/FilePanelTab.java @@ -245,6 +245,7 @@ public class FilePanelTab extends JPanel { SwingUtilities.invokeLater(() -> { updateColumnRenderers(); updateColumnWidths(); + alignTableItemsToViewportStart(); fileTable.revalidate(); fileTable.repaint(); }); @@ -574,7 +575,7 @@ public class FilePanelTab extends JPanel { int selCol = index / tableModel.briefRowsPerColumn; briefCurrentColumn = selCol; fileTable.setRowSelectionInterval(selRow, selRow); - fileTable.scrollRectToVisible(fileTable.getCellRect(selRow, selCol, true)); + scrollBriefCellToColumnStart(selRow, selCol); selected = true; } } @@ -878,7 +879,7 @@ public class FilePanelTab extends JPanel { briefCurrentColumn = finalCol; fileTable.setRowSelectionInterval(finalRow, finalRow); try { - fileTable.scrollRectToVisible(fileTable.getCellRect(finalRow, finalCol, true)); + scrollBriefCellToColumnStart(finalRow, finalCol); } catch (Exception ignore) {} updateStatus(); } @@ -913,7 +914,7 @@ public class FilePanelTab extends JPanel { fileTable.setRowSelectionInterval(finalRow, finalRow); // Ensure the restored selection is visible try { - fileTable.scrollRectToVisible(fileTable.getCellRect(finalRow, finalCol, true)); + scrollBriefCellToColumnStart(finalRow, finalCol); } catch (Exception ignore) {} updateStatus(); } @@ -1093,6 +1094,7 @@ public class FilePanelTab extends JPanel { tableModel.fireTableStructureChanged(); updateColumnRenderers(); updateColumnWidths(); + alignTableItemsToViewportStart(); // Re-select item if (selectedItemName != null) { @@ -1292,7 +1294,7 @@ public class FilePanelTab extends JPanel { if (tableModel.items.size() > 0) { briefCurrentColumn = 0; fileTable.setRowSelectionInterval(0, 0); - fileTable.scrollRectToVisible(fileTable.getCellRect(0, 0, true)); + scrollBriefCellToColumnStart(0, 0); fileTable.repaint(); updateStatus(); } @@ -1306,7 +1308,7 @@ public class FilePanelTab extends JPanel { if (lastColumn < tableModel.getColumnCount()) { briefCurrentColumn = lastColumn; fileTable.setRowSelectionInterval(lastRow, lastRow); - fileTable.scrollRectToVisible(fileTable.getCellRect(lastRow, lastColumn, true)); + scrollBriefCellToColumnStart(lastRow, lastColumn); fileTable.repaint(); updateStatus(); } @@ -1341,7 +1343,7 @@ public class FilePanelTab extends JPanel { if (newColumn < tableModel.getColumnCount()) { briefCurrentColumn = newColumn; fileTable.setRowSelectionInterval(newRow, newRow); - fileTable.scrollRectToVisible(fileTable.getCellRect(newRow, briefCurrentColumn, true)); + scrollBriefCellToColumnStart(newRow, briefCurrentColumn); fileTable.repaint(); updateStatus(); } @@ -1363,7 +1365,7 @@ public class FilePanelTab extends JPanel { int lastRow = lastIndex % tableModel.briefRowsPerColumn; briefCurrentColumn = Math.min(lastCol, Math.max(0, colCount - 1)); fileTable.setRowSelectionInterval(lastRow, lastRow); - fileTable.scrollRectToVisible(fileTable.getCellRect(lastRow, briefCurrentColumn, true)); + scrollBriefCellToColumnStart(lastRow, briefCurrentColumn); fileTable.repaint(); updateStatus(); } else if (!right && briefCurrentColumn <= 0) { @@ -1371,7 +1373,7 @@ public class FilePanelTab extends JPanel { briefCurrentColumn = 0; if (tableModel.items.size() > 0) { fileTable.setRowSelectionInterval(0, 0); - fileTable.scrollRectToVisible(fileTable.getCellRect(0, 0, true)); + scrollBriefCellToColumnStart(0, 0); } fileTable.repaint(); updateStatus(); @@ -1395,7 +1397,7 @@ public class FilePanelTab extends JPanel { briefCurrentColumn = newColumn; fileTable.setRowSelectionInterval(targetRow, targetRow); - fileTable.scrollRectToVisible(fileTable.getCellRect(targetRow, briefCurrentColumn, true)); + scrollBriefCellToColumnStart(targetRow, briefCurrentColumn); fileTable.repaint(); updateStatus(); } @@ -1456,10 +1458,40 @@ public class FilePanelTab extends JPanel { briefCurrentColumn = newColumn; fileTable.setRowSelectionInterval(newRow, newRow); - fileTable.scrollRectToVisible(fileTable.getCellRect(newRow, briefCurrentColumn, true)); + scrollBriefCellToColumnStart(newRow, briefCurrentColumn); fileTable.repaint(); updateStatus(); } + + private void scrollBriefCellToColumnStart(int row, int column) { + if (fileTable == null || viewMode != ViewMode.BRIEF || row < 0 || column < 0) { + return; + } + + Rectangle cell = fileTable.getCellRect(row, column, true); + Container parent = fileTable.getParent(); + if (parent instanceof JViewport viewport) { + Dimension preferredSize = fileTable.getPreferredSize(); + int viewWidth = Math.max(fileTable.getWidth(), preferredSize != null ? preferredSize.width : 0); + int viewHeight = Math.max(fileTable.getHeight(), preferredSize != null ? preferredSize.height : 0); + int maxX = Math.max(0, viewWidth - viewport.getWidth()); + int maxY = Math.max(0, viewHeight - viewport.getHeight()); + + Point position = viewport.getViewPosition(); + int targetX = Math.max(0, Math.min(cell.x, maxX)); + int targetY = position.y; + if (cell.y < position.y) { + targetY = cell.y; + } else if (cell.y + cell.height > position.y + viewport.getHeight()) { + targetY = cell.y + cell.height - viewport.getHeight(); + } + targetY = Math.max(0, Math.min(targetY, maxY)); + + viewport.setViewPosition(new Point(targetX, targetY)); + } else { + fileTable.scrollRectToVisible(cell); + } + } public void loadDirectory(File directory) { loadDirectory(directory, true, true); @@ -1541,6 +1573,7 @@ public class FilePanelTab extends JPanel { tableModel.fireTableStructureChanged(); updateColumnRenderers(); updateColumnWidths(); + alignTableItemsToViewportStart(); fileTable.revalidate(); fileTable.repaint(); @@ -1550,7 +1583,7 @@ public class FilePanelTab extends JPanel { int selCol = startIndex / tableModel.briefRowsPerColumn; briefCurrentColumn = selCol; fileTable.setRowSelectionInterval(selRow, selRow); - fileTable.scrollRectToVisible(fileTable.getCellRect(selRow, selCol, true)); + scrollBriefCellToColumnStart(selRow, selCol); } if (postLoadAction != null) { @@ -1564,6 +1597,7 @@ public class FilePanelTab extends JPanel { }); } else { SwingUtilities.invokeLater(() -> { + alignTableItemsToViewportStart(); if (autoSelectFirst && fileTable.getRowCount() > 0) { int startIndex = 0; fileTable.setRowSelectionInterval(startIndex, startIndex); @@ -1634,6 +1668,7 @@ public class FilePanelTab extends JPanel { } updateColumnRenderers(); updateColumnWidths(); + alignTableItemsToViewportStart(); fileTable.revalidate(); fileTable.repaint(); @@ -1817,7 +1852,7 @@ public class FilePanelTab extends JPanel { if (viewMode == ViewMode.BRIEF) { int r = row % tableModel.briefRowsPerColumn; int c = row / tableModel.briefRowsPerColumn; - fileTable.scrollRectToVisible(fileTable.getCellRect(r, c, true)); + scrollBriefCellToColumnStart(r, c); } else { fileTable.scrollRectToVisible(fileTable.getCellRect(row, 0, true)); } @@ -1832,7 +1867,7 @@ public class FilePanelTab extends JPanel { final int row = i; SwingUtilities.invokeLater(() -> { if (viewMode == ViewMode.BRIEF) { - fileTable.scrollRectToVisible(fileTable.getCellRect(row % tableModel.briefRowsPerColumn, row / tableModel.briefRowsPerColumn, true)); + scrollBriefCellToColumnStart(row % tableModel.briefRowsPerColumn, row / tableModel.briefRowsPerColumn); } else { fileTable.scrollRectToVisible(fileTable.getCellRect(row, 0, true)); } @@ -3108,7 +3143,7 @@ public class FilePanelTab extends JPanel { briefCurrentColumn = column; fileTable.setRowSelectionInterval(row, row); if (scrollToItem) { - fileTable.scrollRectToVisible(fileTable.getCellRect(row, column, true)); + scrollBriefCellToColumnStart(row, column); } fileTable.repaint(); if (requestFocus) { @@ -3343,7 +3378,7 @@ public class FilePanelTab extends JPanel { int row = index % tableModel.briefRowsPerColumn; if (briefCurrentColumn < fileTable.getColumnCount()) { fileTable.setRowSelectionInterval(row, row); - fileTable.scrollRectToVisible(fileTable.getCellRect(row, briefCurrentColumn, true)); + scrollBriefCellToColumnStart(row, briefCurrentColumn); } } else { fileTable.setRowSelectionInterval(index, index); @@ -3624,7 +3659,7 @@ public class FilePanelTab extends JPanel { briefCurrentColumn = lastIndex / tableModel.briefRowsPerColumn; int row = lastIndex % tableModel.briefRowsPerColumn; fileTable.setRowSelectionInterval(row, row); - fileTable.scrollRectToVisible(fileTable.getCellRect(row, briefCurrentColumn, true)); + scrollBriefCellToColumnStart(row, briefCurrentColumn); } else { int last = count - 1; fileTable.setRowSelectionInterval(last, last); @@ -3694,6 +3729,7 @@ public class FilePanelTab extends JPanel { briefCurrentColumn = 0; updateColumnRenderers(); updateColumnWidths(); + alignTableItemsToViewportStart(); fileTable.revalidate(); fileTable.repaint(); @@ -3938,7 +3974,8 @@ public class FilePanelTab extends JPanel { setIcon(null); } - setBorder(null); + setIconTextGap(2); + setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); return this; } }; @@ -4097,6 +4134,7 @@ public class FilePanelTab extends JPanel { fileTable.getColumnModel().getColumn(1).setPreferredWidth(100); fileTable.getColumnModel().getColumn(2).setPreferredWidth(150); } + alignTableItemsToViewportStart(); } else if (viewMode == ViewMode.BRIEF) { int columnCount = tableModel.getColumnCount(); if (columnCount == 0) { @@ -4142,6 +4180,27 @@ public class FilePanelTab extends JPanel { } } } + + private void alignTableItemsToViewportStart() { + if (fileTable == null || viewMode != ViewMode.FULL) { + return; + } + + Container parent = fileTable.getParent(); + if (parent instanceof JViewport viewport) { + Point position = viewport.getViewPosition(); + if (position.x != 0) { + viewport.setViewPosition(new Point(0, position.y)); + } + } + + if (tableScrollPane != null) { + JScrollBar horizontal = tableScrollPane.getHorizontalScrollBar(); + if (horizontal != null && horizontal.getValue() != 0) { + horizontal.setValue(0); + } + } + } private void updateStatus() { long totalSize = 0; @@ -4372,7 +4431,7 @@ public class FilePanelTab extends JPanel { briefCurrentColumn = selCol; fileTable.setRowSelectionInterval(selRow, selRow); fileTable.getColumnModel().getSelectionModel().setSelectionInterval(selCol, selCol); - fileTable.scrollRectToVisible(fileTable.getCellRect(selRow, selCol, true)); + scrollBriefCellToColumnStart(selRow, selCol); } else { fileTable.setRowSelectionInterval(i, i); fileTable.scrollRectToVisible(fileTable.getCellRect(i, 0, true)); diff --git a/src/main/java/cz/kamma/kfmanager/ui/MainWindow.java b/src/main/java/cz/kamma/kfmanager/ui/MainWindow.java index c511596..05af5c5 100644 --- a/src/main/java/cz/kamma/kfmanager/ui/MainWindow.java +++ b/src/main/java/cz/kamma/kfmanager/ui/MainWindow.java @@ -239,16 +239,14 @@ public class MainWindow extends JFrame { if (leftCount > 0) { java.util.List paths = new java.util.ArrayList<>(); java.util.List modes = new java.util.ArrayList<>(); - java.util.List focusedItems = new java.util.ArrayList<>(); for (int i = 0; i < leftCount; i++) { String p = config.getLeftPanelTabPath(i); if (p == null) p = System.getProperty("user.home"); paths.add(p); modes.add(config.getLeftPanelTabViewMode(i)); - focusedItems.add(config.getLeftPanelTabFocusedItem(i)); } int sel = config.getLeftPanelSelectedIndex(); - leftPanel.restoreTabs(paths, modes, focusedItems, sel, false); + leftPanel.restoreTabs(paths, modes, null, sel, false); } } catch (Exception ex) { // ignore and keep default @@ -259,16 +257,14 @@ public class MainWindow extends JFrame { if (rightCount > 0) { java.util.List paths = new java.util.ArrayList<>(); java.util.List modes = new java.util.ArrayList<>(); - java.util.List focusedItems = new java.util.ArrayList<>(); for (int i = 0; i < rightCount; i++) { String p = config.getRightPanelTabPath(i); if (p == null) p = System.getProperty("user.home"); paths.add(p); modes.add(config.getRightPanelTabViewMode(i)); - focusedItems.add(config.getRightPanelTabFocusedItem(i)); } int sel = config.getRightPanelSelectedIndex(); - rightPanel.restoreTabs(paths, modes, focusedItems, sel, false); + rightPanel.restoreTabs(paths, modes, null, sel, false); } } catch (Exception ex) { // ignore and keep default