test on linux
This commit is contained in:
parent
fd47239832
commit
7529cb31eb
@ -6,6 +6,7 @@ import javax.swing.*;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -166,6 +167,44 @@ public class FilePanelTab extends JPanel {
|
||||
fileTable = new JTable(tableModel) {
|
||||
@Override
|
||||
protected void processMouseEvent(java.awt.event.MouseEvent e) {
|
||||
// Show system-like context menu on popup trigger (right-click) without
|
||||
// changing default mouse-driven selection behavior.
|
||||
try {
|
||||
if (e.isPopupTrigger()) {
|
||||
int col = columnAtPoint(e.getPoint());
|
||||
int row = rowAtPoint(e.getPoint());
|
||||
FileItem item = null;
|
||||
if (row >= 0) {
|
||||
if (viewMode == ViewMode.BRIEF) {
|
||||
item = tableModel.getItemFromBriefLayout(row, col);
|
||||
if (item != null) {
|
||||
int index = tableModel.items.indexOf(item);
|
||||
if (index >= 0) {
|
||||
int selRow = index % tableModel.briefRowsPerColumn;
|
||||
int selCol = index / tableModel.briefRowsPerColumn;
|
||||
briefCurrentColumn = selCol;
|
||||
// Select the logical row so actions apply to this item
|
||||
fileTable.setRowSelectionInterval(selRow, selRow);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
item = tableModel.getItem(row);
|
||||
if (item != null) {
|
||||
fileTable.setRowSelectionInterval(row, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (item != null) {
|
||||
// Delegate to outer class to build and show the menu
|
||||
FilePanelTab.this.showContextMenuForItem(item, e.getPoint());
|
||||
}
|
||||
e.consume();
|
||||
return;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// best-effort: ignore exceptions here to avoid breaking mouse handling
|
||||
}
|
||||
// Intercept mouse events to prevent changing selection via mouse.
|
||||
// Allow single-click to toggle marking of an item, allow BRIEF column
|
||||
// tracking, and preserve double-click to open items. Dragging/presses
|
||||
@ -809,6 +848,129 @@ public class FilePanelTab extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a context popup menu for a specific file item at the given point (table coordinates).
|
||||
*/
|
||||
private void showContextMenuForItem(FileItem item, Point tablePoint) {
|
||||
if (item == null) return;
|
||||
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
|
||||
// Open
|
||||
JMenuItem openItem = new JMenuItem("Open");
|
||||
openItem.addActionListener(ae -> {
|
||||
if (item.getName().equals("..")) return;
|
||||
if (item.isDirectory()) {
|
||||
loadDirectory(item.getFile());
|
||||
} else {
|
||||
try {
|
||||
if (Desktop.isDesktopSupported()) {
|
||||
Desktop.getDesktop().open(item.getFile());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
try { JOptionPane.showMessageDialog(FilePanelTab.this, "Cannot open: " + ex.getMessage()); } catch (Exception ignore) {}
|
||||
}
|
||||
}
|
||||
});
|
||||
menu.add(openItem);
|
||||
|
||||
// Edit
|
||||
JMenuItem editItem = new JMenuItem("Edit");
|
||||
editItem.addActionListener(ae -> {
|
||||
if (item.isDirectory() || item.getName().equals("..")) return;
|
||||
try {
|
||||
String ext = persistedConfig != null ? persistedConfig.getExternalEditorPath() : null;
|
||||
if (ext != null && !ext.trim().isEmpty()) {
|
||||
java.util.List<String> cmd = new java.util.ArrayList<>();
|
||||
cmd.add(ext);
|
||||
cmd.add(item.getFile().getAbsolutePath());
|
||||
new ProcessBuilder(cmd).start();
|
||||
} else if (Desktop.isDesktopSupported()) {
|
||||
Desktop.getDesktop().edit(item.getFile());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
try { JOptionPane.showMessageDialog(FilePanelTab.this, "Cannot edit: " + ex.getMessage()); } catch (Exception ignore) {}
|
||||
}
|
||||
});
|
||||
menu.add(editItem);
|
||||
|
||||
// Show in folder / Reveal
|
||||
JMenuItem revealItem = new JMenuItem("Show in folder");
|
||||
revealItem.addActionListener(ae -> {
|
||||
try {
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
File f = item.getFile();
|
||||
if (os.contains("win")) {
|
||||
new ProcessBuilder("explorer.exe", "/select,", f.getAbsolutePath()).start();
|
||||
} else if (os.contains("mac")) {
|
||||
new ProcessBuilder("open", "-R", f.getAbsolutePath()).start();
|
||||
} else {
|
||||
File parent = f.getParentFile();
|
||||
if (parent != null) new ProcessBuilder("xdg-open", parent.getAbsolutePath()).start();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
try { JOptionPane.showMessageDialog(FilePanelTab.this, "Cannot reveal file: " + ex.getMessage()); } catch (Exception ignore) {}
|
||||
}
|
||||
});
|
||||
menu.add(revealItem);
|
||||
|
||||
// Copy path
|
||||
JMenuItem copyPath = new JMenuItem("Copy path");
|
||||
copyPath.addActionListener(ae -> {
|
||||
try {
|
||||
StringSelection sel = new StringSelection(item.getFile().getAbsolutePath());
|
||||
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(sel, null);
|
||||
} catch (Exception ex) {
|
||||
try { JOptionPane.showMessageDialog(FilePanelTab.this, "Cannot copy path: " + ex.getMessage()); } catch (Exception ignore) {}
|
||||
}
|
||||
});
|
||||
menu.add(copyPath);
|
||||
|
||||
// Delete
|
||||
JMenuItem deleteItem = new JMenuItem("Delete");
|
||||
deleteItem.addActionListener(ae -> {
|
||||
int res = JOptionPane.showConfirmDialog(FilePanelTab.this,
|
||||
"Really delete '" + item.getName() + "'?",
|
||||
"Delete",
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
if (res == JOptionPane.YES_OPTION) {
|
||||
try {
|
||||
java.util.List<FileItem> toDelete = new java.util.ArrayList<>();
|
||||
toDelete.add(item);
|
||||
com.kfmanager.service.FileOperations.delete(toDelete, null);
|
||||
// reload current directory
|
||||
loadDirectory(getCurrentDirectory());
|
||||
} catch (Exception ex) {
|
||||
try { JOptionPane.showMessageDialog(FilePanelTab.this, "Delete failed: " + ex.getMessage()); } catch (Exception ignore) {}
|
||||
}
|
||||
}
|
||||
});
|
||||
menu.add(deleteItem);
|
||||
|
||||
// Properties
|
||||
JMenuItem props = new JMenuItem("Properties");
|
||||
props.addActionListener(ae -> {
|
||||
try {
|
||||
File f = item.getFile();
|
||||
String info = String.format("Name: %s\nPath: %s\nSize: %s\nModified: %s\nReadable: %b, Writable: %b, Executable: %b",
|
||||
f.getName(), f.getAbsolutePath(), item.isDirectory() ? "<DIR>" : formatSize(f.length()),
|
||||
new java.util.Date(f.lastModified()).toString(), f.canRead(), f.canWrite(), f.canExecute());
|
||||
JOptionPane.showMessageDialog(FilePanelTab.this, info, "Properties", JOptionPane.INFORMATION_MESSAGE);
|
||||
} catch (Exception ex) {
|
||||
try { JOptionPane.showMessageDialog(FilePanelTab.this, "Cannot show properties: " + ex.getMessage()); } catch (Exception ignore) {}
|
||||
}
|
||||
});
|
||||
menu.add(props);
|
||||
|
||||
// Show the popup at the click location
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
try {
|
||||
menu.show(fileTable, tablePoint.x, tablePoint.y);
|
||||
} catch (Exception ignore) {}
|
||||
});
|
||||
}
|
||||
|
||||
public void navigateUp() {
|
||||
// If we're currently browsing an extracted archive root, navigate back to the
|
||||
// original archive's parent and select the archive file.
|
||||
@ -1065,10 +1227,10 @@ public class FilePanelTab extends JPanel {
|
||||
isCurrentCell = isSelected;
|
||||
}
|
||||
|
||||
// Only show selection highlight when this table has keyboard focus.
|
||||
// If the table is not focused, do not highlight any row (show normal background).
|
||||
if (isCurrentCell && table.hasFocus()) {
|
||||
setBackground(selectionColor);
|
||||
} else if (isCurrentCell) {
|
||||
setBackground(selectionInactiveColor);
|
||||
} else {
|
||||
setBackground(FilePanelTab.this.getBackground());
|
||||
}
|
||||
@ -1085,7 +1247,8 @@ public class FilePanelTab extends JPanel {
|
||||
} else {
|
||||
// Preserve whatever style the base font has (do not force plain)
|
||||
setFont(baseFont.deriveFont(baseStyle));
|
||||
setForeground(Color.BLACK);
|
||||
// Use a light foreground color for better contrast on dark backgrounds
|
||||
setForeground(new Color(240, 240, 240));
|
||||
}
|
||||
|
||||
// Zobrazit ikonu pro názvy souborů
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user