added item info ctrl+q
This commit is contained in:
parent
7962d8defc
commit
609e96145d
@ -746,6 +746,18 @@ public class FilePanel extends JPanel {
|
||||
return tab != null ? tab.getViewMode() : ViewMode.FULL;
|
||||
}
|
||||
|
||||
public ViewMode getPreviousViewMode() {
|
||||
FilePanelTab tab = getCurrentTab();
|
||||
return tab != null ? tab.getPreviousViewMode() : ViewMode.FULL;
|
||||
}
|
||||
|
||||
public void setInfoItem(FileItem item) {
|
||||
FilePanelTab tab = getCurrentTab();
|
||||
if (tab != null) {
|
||||
tab.setInfoItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadDirectory(File directory) {
|
||||
loadDirectory(directory, true);
|
||||
}
|
||||
|
||||
@ -39,6 +39,10 @@ import com.github.junrar.rarfile.FileHeader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.nio.file.attribute.PosixFileAttributes;
|
||||
import java.nio.file.attribute.PosixFilePermissions;
|
||||
import java.nio.file.attribute.DosFileAttributes;
|
||||
|
||||
/**
|
||||
* Single tab in a panel - displays the contents of one directory
|
||||
@ -50,6 +54,11 @@ public class FilePanelTab extends JPanel {
|
||||
private FileTableModel tableModel;
|
||||
private JLabel statusLabel;
|
||||
private ViewMode viewMode = ViewMode.FULL;
|
||||
private ViewMode previousViewMode = ViewMode.FULL; // Store mode before switching to INFO
|
||||
private JPanel cardPanel;
|
||||
private CardLayout cardLayout;
|
||||
private JTextArea infoTextArea;
|
||||
private JScrollPane infoScrollPane;
|
||||
private int briefCurrentColumn = 0;
|
||||
private Runnable onDirectoryChanged;
|
||||
private Runnable onSwitchPanelRequested;
|
||||
@ -170,6 +179,7 @@ public class FilePanelTab extends JPanel {
|
||||
public void applyGlobalFont(Font font) {
|
||||
if (font == null) return;
|
||||
fileTable.setFont(font);
|
||||
infoTextArea.setFont(font);
|
||||
statusLabel.setFont(font);
|
||||
// Update row height based on font metrics
|
||||
FontMetrics fm = fileTable.getFontMetrics(font);
|
||||
@ -587,6 +597,18 @@ public class FilePanelTab extends JPanel {
|
||||
// Enable horizontal scrollbar when needed so BRIEF mode can scroll left-right
|
||||
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
|
||||
// Info panel for Quick View (Ctrl+Q)
|
||||
infoTextArea = new JTextArea();
|
||||
infoTextArea.setEditable(false);
|
||||
infoTextArea.setFont(new Font("Monospaced", Font.PLAIN, 12));
|
||||
infoTextArea.setMargin(new Insets(10, 10, 10, 10));
|
||||
infoScrollPane = new JScrollPane(infoTextArea);
|
||||
|
||||
cardLayout = new CardLayout();
|
||||
cardPanel = new JPanel(cardLayout);
|
||||
cardPanel.add(scrollPane, "TABLE");
|
||||
cardPanel.add(infoScrollPane, "INFO");
|
||||
|
||||
// Implement mouse wheel navigation in BRIEF and FULL mode to match arrow key behavior
|
||||
fileTable.addMouseWheelListener(new java.awt.event.MouseWheelListener() {
|
||||
@Override
|
||||
@ -613,7 +635,7 @@ public class FilePanelTab extends JPanel {
|
||||
}
|
||||
});
|
||||
|
||||
add(scrollPane, BorderLayout.CENTER);
|
||||
add(cardPanel, BorderLayout.CENTER);
|
||||
|
||||
// Status bar
|
||||
statusLabel = new JLabel(" ");
|
||||
@ -2311,13 +2333,16 @@ public class FilePanelTab extends JPanel {
|
||||
|
||||
public void setViewMode(ViewMode mode, boolean requestFocus) {
|
||||
if (this.viewMode != mode) {
|
||||
if (this.viewMode != ViewMode.INFO) {
|
||||
this.previousViewMode = this.viewMode;
|
||||
}
|
||||
String selectedItemName = null;
|
||||
int selectedRow = fileTable.getSelectedRow();
|
||||
if (selectedRow >= 0) {
|
||||
FileItem item = null;
|
||||
if (this.viewMode == ViewMode.BRIEF) {
|
||||
item = tableModel.getItemFromBriefLayout(selectedRow, briefCurrentColumn);
|
||||
} else {
|
||||
} else if (this.viewMode == ViewMode.FULL) {
|
||||
item = tableModel.getItem(selectedRow);
|
||||
}
|
||||
if (item != null) {
|
||||
@ -2329,6 +2354,10 @@ public class FilePanelTab extends JPanel {
|
||||
final String itemToSelect = selectedItemName;
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (mode == ViewMode.INFO) {
|
||||
cardLayout.show(cardPanel, "INFO");
|
||||
} else {
|
||||
cardLayout.show(cardPanel, "TABLE");
|
||||
tableModel.updateViewMode(mode);
|
||||
// Switch auto-resize behavior depending on mode so BRIEF can scroll horizontally
|
||||
if (mode == ViewMode.BRIEF) {
|
||||
@ -2351,14 +2380,117 @@ public class FilePanelTab extends JPanel {
|
||||
} else if (fileTable.getRowCount() > 0) {
|
||||
fileTable.setRowSelectionInterval(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (requestFocus) {
|
||||
if (mode == ViewMode.INFO) {
|
||||
infoTextArea.requestFocusInWindow();
|
||||
} else {
|
||||
fileTable.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public ViewMode getViewMode() {
|
||||
return viewMode;
|
||||
}
|
||||
|
||||
public ViewMode getPreviousViewMode() {
|
||||
return previousViewMode;
|
||||
}
|
||||
|
||||
public void setInfoItem(FileItem item) {
|
||||
if (item == null || item.getName().equals("..")) {
|
||||
infoTextArea.setText("No item selected.");
|
||||
return;
|
||||
}
|
||||
|
||||
File file = item.getFile();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Name: ").append(file.getName()).append("\n");
|
||||
sb.append("Path: ").append(file.getAbsolutePath()).append("\n\n");
|
||||
sb.append("Modified: ").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(file.lastModified()))).append("\n");
|
||||
|
||||
if (!file.isDirectory()) {
|
||||
sb.append("Type: File\n");
|
||||
long size = file.length();
|
||||
sb.append("Size: ").append(FileItem.formatSize(size)).append(" (").append(size).append(" bytes)\n");
|
||||
addAttributes(sb, file);
|
||||
infoTextArea.setText(sb.toString());
|
||||
infoTextArea.setCaretPosition(0);
|
||||
} else {
|
||||
sb.append("Type: Directory\n");
|
||||
infoTextArea.setText(sb.toString());
|
||||
|
||||
// Calculate size and count contents in background to avoid freezing UI
|
||||
new SwingWorker<long[], Void>() {
|
||||
@Override
|
||||
protected long[] doInBackground() {
|
||||
long[] results = new long[3]; // [size, filesCount, dirsCount]
|
||||
calculateDirStats(file, results);
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
long[] res = get();
|
||||
sb.append("Total Size: ").append(FileItem.formatSize(res[0])).append(" (").append(res[0]).append(" bytes)\n");
|
||||
sb.append("Contains: ").append(res[1]).append(" files, ").append(res[2]).append(" directories\n");
|
||||
addAttributes(sb, file);
|
||||
infoTextArea.setText(sb.toString());
|
||||
infoTextArea.setCaretPosition(0);
|
||||
} catch (Exception e) {
|
||||
sb.append("Error calculating stats: ").append(e.getMessage());
|
||||
infoTextArea.setText(sb.toString());
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
|
||||
private void addAttributes(StringBuilder sb, File file) {
|
||||
sb.append("\nAttributes:\n");
|
||||
try {
|
||||
Path path = file.toPath();
|
||||
BasicFileAttributes basic = Files.readAttributes(path, BasicFileAttributes.class);
|
||||
sb.append(" Created: ").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(basic.creationTime().toMillis()))).append("\n");
|
||||
sb.append(" Last access: ").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(basic.lastAccessTime().toMillis()))).append("\n");
|
||||
|
||||
if (Files.getFileStore(path).supportsFileAttributeView("posix")) {
|
||||
PosixFileAttributes posix = Files.readAttributes(path, PosixFileAttributes.class);
|
||||
sb.append(" Owner: ").append(posix.owner().getName()).append("\n");
|
||||
sb.append(" Group: ").append(posix.group().getName()).append("\n");
|
||||
sb.append(" Permissions: ").append(PosixFilePermissions.toString(posix.permissions())).append("\n");
|
||||
} else if (Files.getFileStore(path).supportsFileAttributeView("dos")) {
|
||||
DosFileAttributes dos = Files.readAttributes(path, DosFileAttributes.class);
|
||||
sb.append(" Hidden: ").append(dos.isHidden()).append("\n");
|
||||
sb.append(" ReadOnly: ").append(dos.isReadOnly()).append("\n");
|
||||
sb.append(" System: ").append(dos.isSystem()).append("\n");
|
||||
sb.append(" Archive: ").append(dos.isArchive()).append("\n");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
sb.append(" Error reading attributes: ").append(e.getMessage()).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateDirStats(File dir, long[] results) {
|
||||
File[] items = dir.listFiles();
|
||||
if (items != null) {
|
||||
for (File item : items) {
|
||||
if (item.isFile()) {
|
||||
results[0] += item.length();
|
||||
results[1]++;
|
||||
} else {
|
||||
results[2]++;
|
||||
calculateDirStats(item, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateColumnRenderers() {
|
||||
int columnCount = tableModel.getColumnCount();
|
||||
if (columnCount == 0 || fileTable.getColumnModel().getColumnCount() != columnCount) {
|
||||
@ -2960,10 +3092,6 @@ public class FilePanelTab extends JPanel {
|
||||
return currentDirectory;
|
||||
}
|
||||
|
||||
public ViewMode getViewMode() {
|
||||
return viewMode;
|
||||
}
|
||||
|
||||
// FileTableModel
|
||||
private class FileTableModel extends AbstractTableModel {
|
||||
private List<FileItem> items = new ArrayList<>();
|
||||
|
||||
@ -235,6 +235,13 @@ public class MainWindow extends JFrame {
|
||||
}
|
||||
});
|
||||
|
||||
// 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) {
|
||||
@ -255,6 +262,13 @@ public class MainWindow extends JFrame {
|
||||
}
|
||||
});
|
||||
|
||||
// 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
|
||||
@ -463,7 +477,6 @@ public class MainWindow extends JFrame {
|
||||
|
||||
// Load custom shortcuts from config
|
||||
List<AppConfig.ToolbarShortcut> shortcuts = config.getToolbarShortcuts();
|
||||
int btnSize = config.getToolbarButtonSize();
|
||||
int iconSize = config.getToolbarIconSize();
|
||||
|
||||
// Group shortcuts: directories will go to the right, others stay on the left
|
||||
@ -1200,6 +1213,11 @@ public class MainWindow extends JFrame {
|
||||
}, KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK),
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
|
||||
// Ctrl+Q - Quick View
|
||||
rootPane.registerKeyboardAction(e -> toggleQuickView(),
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_DOWN_MASK),
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
|
||||
// Ctrl+E - Command line history
|
||||
rootPane.registerKeyboardAction(e -> showCommandLineHistory(),
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_DOWN_MASK),
|
||||
@ -1222,6 +1240,24 @@ public class MainWindow extends JFrame {
|
||||
/**
|
||||
* Switch between panels
|
||||
*/
|
||||
private void toggleQuickView() {
|
||||
FilePanel opposite = (activePanel == leftPanel) ? rightPanel : leftPanel;
|
||||
if (opposite.getViewMode() == ViewMode.INFO) {
|
||||
opposite.setViewMode(opposite.getPreviousViewMode(), false);
|
||||
} else {
|
||||
opposite.setViewMode(ViewMode.INFO, false);
|
||||
updateQuickViewInfo();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateQuickViewInfo() {
|
||||
FilePanel opposite = (activePanel == leftPanel) ? rightPanel : leftPanel;
|
||||
if (opposite.getViewMode() == ViewMode.INFO) {
|
||||
FileItem selected = activePanel.getFocusedItem();
|
||||
opposite.setInfoItem(selected);
|
||||
}
|
||||
}
|
||||
|
||||
private void switchPanels() {
|
||||
// Determine which panel currently (or recently) has focus by inspecting the focus owner.
|
||||
java.awt.Component owner = java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
|
||||
@ -5,5 +5,6 @@ package cz.kamma.kfmanager.ui;
|
||||
*/
|
||||
public enum ViewMode {
|
||||
FULL, // Full details (name, size, date)
|
||||
BRIEF // Names only in multiple columns
|
||||
BRIEF, // Names only in multiple columns
|
||||
INFO // Information about selected file from opposite panel
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user