fixed panel empty space recognition
This commit is contained in:
parent
e811581107
commit
7074a0d0ad
@ -15,7 +15,7 @@ import java.io.InputStreamReader;
|
|||||||
*/
|
*/
|
||||||
public class MainApp {
|
public class MainApp {
|
||||||
|
|
||||||
public static final String APP_VERSION = "1.1.4";
|
public static final String APP_VERSION = "1.1.5";
|
||||||
|
|
||||||
public enum OS {
|
public enum OS {
|
||||||
WINDOWS, LINUX, MACOS, UNKNOWN
|
WINDOWS, LINUX, MACOS, UNKNOWN
|
||||||
|
|||||||
@ -1,9 +1,21 @@
|
|||||||
package cz.kamma.kfmanager.service;
|
package cz.kamma.kfmanager.service;
|
||||||
|
|
||||||
import cz.kamma.kfmanager.model.FileItem;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
import java.nio.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.BasicFileAttributes;
|
||||||
import java.nio.file.attribute.PosixFilePermission;
|
import java.nio.file.attribute.PosixFilePermission;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -11,9 +23,10 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.regex.Matcher;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.*;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
import cz.kamma.kfmanager.model.FileItem;
|
||||||
import net.lingala.zip4j.ZipFile;
|
import net.lingala.zip4j.ZipFile;
|
||||||
import net.lingala.zip4j.model.FileHeader;
|
import net.lingala.zip4j.model.FileHeader;
|
||||||
|
|
||||||
|
|||||||
@ -200,6 +200,11 @@ public class FilePanel extends JPanel {
|
|||||||
tabbedPane.addChangeListener(e -> {
|
tabbedPane.addChangeListener(e -> {
|
||||||
updatePathField();
|
updatePathField();
|
||||||
updateTabStyles();
|
updateTabStyles();
|
||||||
|
// Automatically focus the table in the newly selected tab
|
||||||
|
FilePanelTab tab = getCurrentTab();
|
||||||
|
if (tab != null) {
|
||||||
|
tab.getFileTable().requestFocusInWindow();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
add(tabbedPane, BorderLayout.CENTER);
|
add(tabbedPane, BorderLayout.CENTER);
|
||||||
@ -219,7 +224,9 @@ public class FilePanel extends JPanel {
|
|||||||
boolean isInteractive = comp instanceof JButton ||
|
boolean isInteractive = comp instanceof JButton ||
|
||||||
comp instanceof JComboBox ||
|
comp instanceof JComboBox ||
|
||||||
comp instanceof JTextField ||
|
comp instanceof JTextField ||
|
||||||
comp instanceof JTable;
|
comp instanceof JTable ||
|
||||||
|
comp instanceof JScrollBar ||
|
||||||
|
comp instanceof javax.swing.table.JTableHeader;
|
||||||
|
|
||||||
if (!isInteractive) {
|
if (!isInteractive) {
|
||||||
comp.addMouseListener(new java.awt.event.MouseAdapter() {
|
comp.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||||
|
|||||||
@ -292,6 +292,26 @@ public class FilePanelTab extends JPanel {
|
|||||||
// Also override mouse-motion processing to suppress drag events and
|
// Also override mouse-motion processing to suppress drag events and
|
||||||
// prevent any drag-and-drop transfer handling.
|
// prevent any drag-and-drop transfer handling.
|
||||||
fileTable = new JTable(tableModel) {
|
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
|
@Override
|
||||||
public void editingStopped(javax.swing.event.ChangeEvent e) {
|
public void editingStopped(javax.swing.event.ChangeEvent e) {
|
||||||
super.editingStopped(e);
|
super.editingStopped(e);
|
||||||
@ -657,6 +677,30 @@ public class FilePanelTab extends JPanel {
|
|||||||
fileTable.setOpaque(true);
|
fileTable.setOpaque(true);
|
||||||
|
|
||||||
fileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
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.
|
// Enforce that at least one item is always active (selected) if the table is not empty.
|
||||||
fileTable.getSelectionModel().addListSelectionListener(e -> {
|
fileTable.getSelectionModel().addListSelectionListener(e -> {
|
||||||
int row = fileTable.getSelectedRow();
|
int row = fileTable.getSelectedRow();
|
||||||
@ -3265,8 +3309,16 @@ public class FilePanelTab extends JPanel {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
briefRowsPerColumn = Math.max(1, availableHeight / rowHeight);
|
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);
|
briefColumns = (int) Math.ceil((double) items.size() / briefRowsPerColumn);
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate extra columns to allow snapping correctly at the end.
|
// Calculate extra columns to allow snapping correctly at the end.
|
||||||
// We want the scrolling to stop precisely when the last column is fully visible
|
// We want the scrolling to stop precisely when the last column is fully visible
|
||||||
|
|||||||
@ -121,11 +121,9 @@ public class MainWindow extends JFrame {
|
|||||||
leftPanel.setSwitchPanelCallback(() -> switchPanelsFromChild());
|
leftPanel.setSwitchPanelCallback(() -> switchPanelsFromChild());
|
||||||
leftPanel.setOnDirectoryChangedAll(() -> updateCommandLinePrompt());
|
leftPanel.setOnDirectoryChangedAll(() -> updateCommandLinePrompt());
|
||||||
leftPanel.setOnTableCreated(table -> {
|
leftPanel.setOnTableCreated(table -> {
|
||||||
addTabKeyHandler(table);
|
setupFileTable(table, leftPanel);
|
||||||
addCommandLineRedirect(table);
|
|
||||||
});
|
});
|
||||||
addCommandLineRedirect(leftPanel.getFileTable());
|
setupFileTable(leftPanel.getFileTable(), leftPanel);
|
||||||
addTabKeyHandler(leftPanel.getFileTable());
|
|
||||||
|
|
||||||
// Load and set ViewMode for left panel
|
// Load and set ViewMode for left panel
|
||||||
try {
|
try {
|
||||||
@ -143,11 +141,9 @@ public class MainWindow extends JFrame {
|
|||||||
rightPanel.setSwitchPanelCallback(() -> switchPanelsFromChild());
|
rightPanel.setSwitchPanelCallback(() -> switchPanelsFromChild());
|
||||||
rightPanel.setOnDirectoryChangedAll(() -> updateCommandLinePrompt());
|
rightPanel.setOnDirectoryChangedAll(() -> updateCommandLinePrompt());
|
||||||
rightPanel.setOnTableCreated(table -> {
|
rightPanel.setOnTableCreated(table -> {
|
||||||
addTabKeyHandler(table);
|
setupFileTable(table, rightPanel);
|
||||||
addCommandLineRedirect(table);
|
|
||||||
});
|
});
|
||||||
addCommandLineRedirect(rightPanel.getFileTable());
|
setupFileTable(rightPanel.getFileTable(), rightPanel);
|
||||||
addTabKeyHandler(rightPanel.getFileTable());
|
|
||||||
|
|
||||||
// Load and set ViewMode for right panel
|
// Load and set ViewMode for right panel
|
||||||
try {
|
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
|
// Click on panel anywhere should request focus to its table
|
||||||
leftPanel.addMouseListener(new MouseAdapter() {
|
leftPanel.addMouseListener(new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
@ -1456,6 +1397,42 @@ public class MainWindow extends JFrame {
|
|||||||
cmdLabel.setText(path + ">");
|
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
|
* Attach TAB handling to switch panels
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user