test on linux

This commit is contained in:
Radek Davidek 2025-11-18 09:32:15 +01:00
parent fd47239832
commit 7529cb31eb

View File

@ -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
@ -808,6 +847,129 @@ public class FilePanelTab extends JPanel {
loadDirectory(item.getFile());
}
}
/**
* 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
@ -1064,11 +1226,11 @@ public class FilePanelTab extends JPanel {
} else {
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ů