added command line

This commit is contained in:
Radek Davidek 2026-01-15 11:53:33 +01:00
parent 25ce987859
commit b4226db038
3 changed files with 235 additions and 4 deletions

View File

@ -455,6 +455,21 @@ public class FilePanel extends JPanel {
// Delegování metod na aktuální tab
/**
* Switch to the next tab in this panel.
*/
public void nextTab() {
int count = tabbedPane.getTabCount();
if (count > 1) {
int nextIndex = (tabbedPane.getSelectedIndex() + 1) % count;
tabbedPane.setSelectedIndex(nextIndex);
FilePanelTab tab = getCurrentTab();
if (tab != null) {
tab.getFileTable().requestFocusInWindow();
}
}
}
public JTable getFileTable() {
FilePanelTab tab = getCurrentTab();
return tab != null ? tab.getFileTable() : null;
@ -470,6 +485,11 @@ public class FilePanel extends JPanel {
return tab != null ? tab.getSelectedItems() : java.util.Collections.emptyList();
}
public FileItem getFocusedItem() {
FilePanelTab tab = getCurrentTab();
return tab != null ? tab.getFocusedItem() : null;
}
public void setViewMode(ViewMode mode) {
FilePanelTab tab = getCurrentTab();
if (tab != null) {

View File

@ -301,6 +301,7 @@ public class FilePanelTab extends JPanel {
// to ensure no drag gestures or DnD occur.
fileTable.setDragEnabled(false);
fileTable.setTransferHandler(null);
fileTable.setFocusTraversalKeysEnabled(false);
try {
fileTable.setDropMode(null);
} catch (Exception ignore) {
@ -433,7 +434,7 @@ public class FilePanelTab extends JPanel {
fileTable.addKeyListener(new java.awt.event.KeyAdapter() {
@Override
public void keyPressed(java.awt.event.KeyEvent e) {
if (e.getKeyCode() == java.awt.event.KeyEvent.VK_ENTER) {
if (e.getKeyCode() == java.awt.event.KeyEvent.VK_ENTER && !e.isControlDown()) {
openSelectedItem();
e.consume();
} else if (e.getKeyCode() == java.awt.event.KeyEvent.VK_BACK_SPACE) {
@ -1143,6 +1144,18 @@ public class FilePanelTab extends JPanel {
return selected;
}
public FileItem getFocusedItem() {
int selectedRow = fileTable.getSelectedRow();
if (selectedRow >= 0) {
if (viewMode == ViewMode.BRIEF) {
return tableModel.getItemFromBriefLayout(selectedRow, briefCurrentColumn);
} else {
return tableModel.getItem(selectedRow);
}
}
return null;
}
public void setViewMode(ViewMode mode) {
if (this.viewMode != mode) {
String selectedItemName = null;

View File

@ -19,10 +19,11 @@ public class MainWindow extends JFrame {
private FilePanel rightPanel;
private FilePanel activePanel;
private JPanel buttonPanel;
private JTextField commandLine;
private AppConfig config;
public MainWindow() {
super("KF File Manager");
super("KF Manager");
// Load configuration
config = new AppConfig();
@ -183,13 +184,67 @@ public class MainWindow extends JFrame {
}
});
// Click on panel anywhere should request focus to its table
leftPanel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
leftPanel.getFileTable().requestFocusInWindow();
}
});
rightPanel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
rightPanel.getFileTable().requestFocusInWindow();
}
});
// Add TAB handler to switch between panels
addTabKeyHandler(leftPanel.getFileTable());
addTabKeyHandler(rightPanel.getFileTable());
// Add command line focus redirection
addCommandLineRedirect(leftPanel.getFileTable());
addCommandLineRedirect(rightPanel.getFileTable());
// Container for everything below the file panels
JPanel bottomContainer = new JPanel(new BorderLayout());
// Command line panel
JPanel cmdPanel = new JPanel(new BorderLayout(5, 0));
cmdPanel.setBorder(BorderFactory.createEmptyBorder(2, 5, 0, 5));
JLabel cmdLabel = new JLabel(System.getProperty("user.name") + ">");
cmdLabel.setFont(new Font("Monospaced", Font.BOLD, 12));
cmdPanel.add(cmdLabel, BorderLayout.WEST);
commandLine = new JTextField();
commandLine.setFont(new Font("Monospaced", Font.PLAIN, 12));
commandLine.addActionListener(e -> executeCommand(commandLine.getText()));
// Let the panels catch focus back if user presses ESC or TAB in command line
commandLine.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
commandLine.setText("");
activePanel.getFileTable().requestFocus();
e.consume();
} else if (e.getKeyCode() == KeyEvent.VK_TAB) {
activePanel.getFileTable().requestFocus();
e.consume();
}
}
});
cmdPanel.add(commandLine, BorderLayout.CENTER);
bottomContainer.add(cmdPanel, BorderLayout.NORTH);
// Bottom panel with buttons
createButtonPanel();
add(buttonPanel, BorderLayout.SOUTH);
bottomContainer.add(buttonPanel, BorderLayout.SOUTH);
add(bottomContainer, BorderLayout.SOUTH);
// Menu
createMenuBar();
@ -491,6 +546,14 @@ public class MainWindow extends JFrame {
KeyStroke.getKeyStroke(KeyEvent.VK_F9, 0),
JComponent.WHEN_IN_FOCUSED_WINDOW);
// Ctrl+TAB - switch tabs in active panel
rootPane.registerKeyboardAction(e -> {
if (activePanel != null) {
activePanel.nextTab();
}
}, KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_DOWN_MASK),
JComponent.WHEN_IN_FOCUSED_WINDOW);
// Delete key - global delete binding (also added per-table)
rootPane.registerKeyboardAction(e -> deleteFiles(),
KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0),
@ -622,6 +685,18 @@ public class MainWindow extends JFrame {
}
});
// Add Ctrl+Tab handling at the table level
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_DOWN_MASK), "nextTab");
table.getActionMap().put("nextTab", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (activePanel != null) {
activePanel.nextTab();
}
}
});
// Přidáme F8 pro mazání s vyšší prioritou než defaultní Swing akce
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_F8, 0), "deleteFiles");
@ -639,6 +714,63 @@ public class MainWindow extends JFrame {
.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, InputEvent.SHIFT_DOWN_MASK), "deleteFiles");
}
/**
* Automatically focus command line when user starts typing on a table
*/
private void addCommandLineRedirect(JTable table) {
// Use InputMap/ActionMap for Ctrl+Enter and Ctrl+Shift+Enter as KeyListener might be bypassed by JTable
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK), "copyNameToCmd");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK), "copyPathToCmd");
table.getActionMap().put("copyNameToCmd", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
copyFocusedToCommandLine(false);
}
});
table.getActionMap().put("copyPathToCmd", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
copyFocusedToCommandLine(true);
}
});
table.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
// Printable characters only (exclude control keys like Enter, Backspace, Esc, Tab)
if (c != KeyEvent.CHAR_UNDEFINED && c != '\b' && c != '\n' && c != '\t' && c != 27) {
commandLine.requestFocusInWindow();
commandLine.setText(commandLine.getText() + c);
e.consume();
}
}
});
}
private void copyFocusedToCommandLine(boolean fullPath) {
FileItem focused = activePanel.getFocusedItem();
if (focused != null && !focused.getName().equals("..")) {
String current = commandLine.getText();
String toAdd = fullPath ? focused.getFile().getAbsolutePath() : focused.getName();
// If it contains spaces, wrap in quotes
if (toAdd.contains(" ")) {
toAdd = "\"" + toAdd + "\"";
}
if (!current.isEmpty() && !current.endsWith(" ")) {
commandLine.setText(current + " " + toAdd);
} else {
commandLine.setText(current + toAdd);
}
}
}
/**
* Copy selected files to the opposite panel
*/
@ -1108,6 +1240,72 @@ public class MainWindow extends JFrame {
}
}
private void executeCommand(String command) {
if (command == null || command.trim().isEmpty()) {
return;
}
File currentDir = activePanel.getCurrentDirectory();
if (currentDir == null) {
currentDir = new File(System.getProperty("user.home"));
}
try {
String osName = System.getProperty("os.name").toLowerCase();
ProcessBuilder pb;
if (osName.contains("win")) {
// Windows: cmd /c command && pause
pb = new ProcessBuilder("cmd.exe", "/c", "start", "cmd.exe", "/k", command);
} else if (osName.contains("mac")) {
// macOS: Open terminal and execute
String appleScript = String.format(
"tell application \"Terminal\" to do script \"cd '%s' && %s\"",
currentDir.getAbsolutePath(), command.replace("\"", "\\\"")
);
pb = new ProcessBuilder("osascript", "-e", appleScript);
} else {
// Linux: Try common terminals with -e or --command
String[] terminals = {"gnome-terminal", "konsole", "xfce4-terminal", "mate-terminal", "xterm"};
pb = null;
for (String terminal : terminals) {
try {
Process p = Runtime.getRuntime().exec(new String[]{"which", terminal});
if (p.waitFor() == 0) {
if (terminal.equals("gnome-terminal") || terminal.equals("xfce4-terminal") || terminal.equals("mate-terminal")) {
pb = new ProcessBuilder(terminal, "--working-directory=" + currentDir.getAbsolutePath(), "--", "bash", "-c", command + "; echo; echo 'Press Enter to close...'; read");
} else if (terminal.equals("konsole")) {
pb = new ProcessBuilder(terminal, "--workdir", currentDir.getAbsolutePath(), "-e", "bash", "-c", command + "; echo; echo 'Press Enter to close...'; read");
} else {
pb = new ProcessBuilder(terminal, "-e", "bash -c \"" + command + "; echo; echo 'Press Enter to close...'; read\"");
}
break;
}
} catch (Exception e) {
// try next
}
}
if (pb == null) {
pb = new ProcessBuilder("xterm", "-e", "bash -c \"" + command + "; echo; echo 'Press Enter to close...'; read\"");
}
}
if (pb != null) {
pb.directory(currentDir);
pb.start();
commandLine.setText(""); // Clear after execution
}
} catch (Exception e) {
JOptionPane.showMessageDialog(this,
"Chyba při spouštění příkazu: " + e.getMessage(),
"Chyba",
JOptionPane.ERROR_MESSAGE);
}
}
/**
* Show About dialog
*/