fixed panel empty space recognition

This commit is contained in:
Radek Davidek 2026-02-10 19:50:14 +01:00
parent e811581107
commit 7074a0d0ad
5 changed files with 122 additions and 73 deletions

View File

@ -15,7 +15,7 @@ import java.io.InputStreamReader;
*/
public class MainApp {
public static final String APP_VERSION = "1.1.4";
public static final String APP_VERSION = "1.1.5";
public enum OS {
WINDOWS, LINUX, MACOS, UNKNOWN

View File

@ -1,9 +1,21 @@
package cz.kamma.kfmanager.service;
import cz.kamma.kfmanager.model.FileItem;
import java.io.*;
import java.nio.file.*;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.file.AccessDeniedException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.util.ArrayList;
@ -11,9 +23,10 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.zip.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import cz.kamma.kfmanager.model.FileItem;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.FileHeader;

View File

@ -200,6 +200,11 @@ public class FilePanel extends JPanel {
tabbedPane.addChangeListener(e -> {
updatePathField();
updateTabStyles();
// Automatically focus the table in the newly selected tab
FilePanelTab tab = getCurrentTab();
if (tab != null) {
tab.getFileTable().requestFocusInWindow();
}
});
add(tabbedPane, BorderLayout.CENTER);
@ -219,7 +224,9 @@ public class FilePanel extends JPanel {
boolean isInteractive = comp instanceof JButton ||
comp instanceof JComboBox ||
comp instanceof JTextField ||
comp instanceof JTable;
comp instanceof JTable ||
comp instanceof JScrollBar ||
comp instanceof javax.swing.table.JTableHeader;
if (!isInteractive) {
comp.addMouseListener(new java.awt.event.MouseAdapter() {

View File

@ -292,6 +292,26 @@ public class FilePanelTab extends JPanel {
// Also override mouse-motion processing to suppress drag events and
// prevent any drag-and-drop transfer handling.
fileTable = new JTable(tableModel) {
@Override
public int rowAtPoint(Point p) {
int r = super.rowAtPoint(p);
int c = super.columnAtPoint(p);
if (viewMode == ViewMode.BRIEF && r >= 0 && c >= 0) {
if (tableModel.getItemFromBriefLayout(r, c) == null) return -1;
}
return r;
}
@Override
public int columnAtPoint(Point p) {
int c = super.columnAtPoint(p);
int r = super.rowAtPoint(p);
if (viewMode == ViewMode.BRIEF && r >= 0 && c >= 0) {
if (tableModel.getItemFromBriefLayout(r, c) == null) return -1;
}
return c;
}
@Override
public void editingStopped(javax.swing.event.ChangeEvent e) {
super.editingStopped(e);
@ -657,6 +677,30 @@ public class FilePanelTab extends JPanel {
fileTable.setOpaque(true);
fileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// Ensure selection when table gains focus
fileTable.addFocusListener(new java.awt.event.FocusAdapter() {
@Override
public void focusGained(java.awt.event.FocusEvent e) {
if (fileTable.getSelectionModel().isSelectionEmpty() && fileTable.getRowCount() > 0) {
int targetRow = Math.min(lastValidRow, fileTable.getRowCount() - 1);
if (targetRow < 0) targetRow = 0;
final int finalRow = targetRow;
final int finalCol = lastValidBriefColumn;
SwingUtilities.invokeLater(() -> {
if (fileTable != null && fileTable.getSelectionModel().isSelectionEmpty() && fileTable.getRowCount() > 0) {
briefCurrentColumn = finalCol;
fileTable.setRowSelectionInterval(finalRow, finalRow);
try {
fileTable.scrollRectToVisible(fileTable.getCellRect(finalRow, finalCol, true));
} catch (Exception ignore) {}
updateStatus();
}
});
}
}
});
// Enforce that at least one item is always active (selected) if the table is not empty.
fileTable.getSelectionModel().addListSelectionListener(e -> {
int row = fileTable.getSelectedRow();
@ -3265,8 +3309,16 @@ public class FilePanelTab extends JPanel {
return;
}
briefRowsPerColumn = Math.max(1, availableHeight / rowHeight);
briefColumns = (int) Math.ceil((double) items.size() / briefRowsPerColumn);
int viewportRows = Math.max(1, availableHeight / rowHeight);
if (items.size() <= viewportRows) {
// If everything fits in one column, use only necessary rows
briefRowsPerColumn = Math.max(1, items.size());
briefColumns = 1;
} else {
// Multi-column mode: use full height available
briefRowsPerColumn = viewportRows;
briefColumns = (int) Math.ceil((double) items.size() / briefRowsPerColumn);
}
// Calculate extra columns to allow snapping correctly at the end.
// We want the scrolling to stop precisely when the last column is fully visible

View File

@ -121,11 +121,9 @@ public class MainWindow extends JFrame {
leftPanel.setSwitchPanelCallback(() -> switchPanelsFromChild());
leftPanel.setOnDirectoryChangedAll(() -> updateCommandLinePrompt());
leftPanel.setOnTableCreated(table -> {
addTabKeyHandler(table);
addCommandLineRedirect(table);
setupFileTable(table, leftPanel);
});
addCommandLineRedirect(leftPanel.getFileTable());
addTabKeyHandler(leftPanel.getFileTable());
setupFileTable(leftPanel.getFileTable(), leftPanel);
// Load and set ViewMode for left panel
try {
@ -143,11 +141,9 @@ public class MainWindow extends JFrame {
rightPanel.setSwitchPanelCallback(() -> switchPanelsFromChild());
rightPanel.setOnDirectoryChangedAll(() -> updateCommandLinePrompt());
rightPanel.setOnTableCreated(table -> {
addTabKeyHandler(table);
addCommandLineRedirect(table);
setupFileTable(table, rightPanel);
});
addCommandLineRedirect(rightPanel.getFileTable());
addTabKeyHandler(rightPanel.getFileTable());
setupFileTable(rightPanel.getFileTable(), rightPanel);
// Load and set ViewMode for right panel
try {
@ -275,61 +271,6 @@ public class MainWindow extends JFrame {
}
});
// Focus listeners to track active panel and ensure selection
leftPanel.getFileTable().addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
activePanel = leftPanel;
updateActivePanelBorder();
updateCommandLinePrompt();
// Ensure some row is selected
JTable leftTable = leftPanel.getFileTable();
if (leftTable.getSelectedRow() == -1 && leftTable.getRowCount() > 0) {
leftTable.setRowSelectionInterval(0, 0);
}
}
@Override
public void focusLost(FocusEvent e) {
// Repaint on focus loss
leftPanel.getFileTable().repaint();
}
});
// Add selection listeners for Quick View updates
leftPanel.getFileTable().getSelectionModel().addListSelectionListener(e -> {
if (!e.getValueIsAdjusting() && activePanel == leftPanel) {
updateQuickViewInfo();
}
});
rightPanel.getFileTable().addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
activePanel = rightPanel;
updateActivePanelBorder();
updateCommandLinePrompt();
// Ensure some row is selected
JTable rightTable = rightPanel.getFileTable();
if (rightTable.getSelectedRow() == -1 && rightTable.getRowCount() > 0) {
rightTable.setRowSelectionInterval(0, 0);
}
}
@Override
public void focusLost(FocusEvent e) {
// Repaint on focus loss
rightPanel.getFileTable().repaint();
}
});
// Add selection listeners for Quick View updates
rightPanel.getFileTable().getSelectionModel().addListSelectionListener(e -> {
if (!e.getValueIsAdjusting() && activePanel == rightPanel) {
updateQuickViewInfo();
}
});
// Click on panel anywhere should request focus to its table
leftPanel.addMouseListener(new MouseAdapter() {
@Override
@ -1456,6 +1397,42 @@ public class MainWindow extends JFrame {
cmdLabel.setText(path + ">");
}
/**
* Attach all necessary listeners and handlers to a file table
*/
private void setupFileTable(JTable table, FilePanel panel) {
if (table == null) return;
addTabKeyHandler(table);
addCommandLineRedirect(table);
// Focus listener to track active panel and ensure selection
table.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
activePanel = panel;
updateActivePanelBorder();
updateCommandLinePrompt();
// Ensure some row is selected
if (table.getSelectedRow() == -1 && table.getRowCount() > 0) {
table.setRowSelectionInterval(0, 0);
}
}
@Override
public void focusLost(FocusEvent e) {
table.repaint();
}
});
// Selection listener for Quick View updates
table.getSelectionModel().addListSelectionListener(e -> {
if (!e.getValueIsAdjusting() && activePanel == panel) {
updateQuickViewInfo();
}
});
}
/**
* Attach TAB handling to switch panels
*/