command history, translate to english

This commit is contained in:
Radek Davidek 2026-01-16 15:57:26 +01:00
parent 61fb75854e
commit 2c32493e73
7 changed files with 190 additions and 101 deletions

View File

@ -5,21 +5,21 @@ import com.kfmanager.ui.MainWindow;
import javax.swing.*;
/**
* Hlavní třída aplikace KF File Manager
* Main application class for KF File Manager
*/
public class MainApp {
public static final String APP_VERSION = "0.0.2";
public static void main(String[] args) {
// Nastavení look and feel podle systému
// Set look and feel to system default
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
// Spuštění GUI v Event Dispatch Thread
// Start GUI in Event Dispatch Thread
SwingUtilities.invokeLater(() -> {
MainWindow mainWindow = new MainWindow();
mainWindow.setVisible(true);

View File

@ -28,7 +28,7 @@ public class AppConfig {
try (FileInputStream fis = new FileInputStream(configFile)) {
properties.load(fis);
} catch (IOException e) {
System.err.println("Nepodařilo se načíst konfiguraci: " + e.getMessage());
System.err.println("Could not load configuration: " + e.getMessage());
}
}
}
@ -48,7 +48,7 @@ public class AppConfig {
try (FileOutputStream fos = new FileOutputStream(configFile)) {
properties.store(fos, "KF File Manager Configuration");
} catch (IOException e) {
System.err.println("Nepodařilo se uložit konfiguraci: " + e.getMessage());
System.err.println("Could not save configuration: " + e.getMessage());
}
}
@ -110,7 +110,7 @@ public class AppConfig {
properties.setProperty("rightPanel.path", path);
}
// ViewMode konfigurace
// ViewMode configuration
public String getLeftPanelViewMode() {
return properties.getProperty("leftPanel.viewMode", "FULL");
}
@ -178,7 +178,7 @@ public class AppConfig {
properties.setProperty("rightPanel.selectedIndex", String.valueOf(selectedIndex));
}
// Font konfigurace
// Font configuration
public String getEditorFontName() {
return properties.getProperty("editor.font.name", "Monospaced");
}
@ -533,4 +533,32 @@ public class AppConfig {
properties.remove("search.content.history." + i);
}
}
// --- Command line history persistence ---
public java.util.List<String> getCommandLineHistory() {
java.util.List<String> list = new java.util.ArrayList<>();
int count = Integer.parseInt(properties.getProperty("cmd.history.count", "0"));
for (int i = 0; i < count; i++) {
String v = properties.getProperty("cmd.history." + i, null);
if (v != null && !v.isEmpty()) list.add(v);
}
return list;
}
public void saveCommandLineHistory(java.util.List<String> history) {
if (history == null) {
properties.setProperty("cmd.history.count", "0");
return;
}
int limit = Math.min(history.size(), 50);
properties.setProperty("cmd.history.count", String.valueOf(limit));
for (int i = 0; i < limit; i++) {
properties.setProperty("cmd.history." + i, history.get(i));
}
// remove old entries beyond limit
int old = Integer.parseInt(properties.getProperty("cmd.history.count", "0"));
for (int i = limit; i < old; i++) {
properties.remove("cmd.history." + i);
}
}
}

View File

@ -27,7 +27,7 @@ public class FileItem {
this.isDirectory = file.isDirectory();
this.marked = false;
// Načíst ikonu ze systému
// Load icon from system
this.icon = FileSystemView.getFileSystemView().getSystemIcon(file);
}

View File

@ -367,7 +367,7 @@ public class FileOperations {
// legacy matchesPattern removed filename wildcard handling is done via a precompiled Pattern
/**
* Callback pro progress operací
* Callback for operation progress
*/
public interface ProgressCallback {
void onProgress(long current, long total, String currentFile);
@ -375,7 +375,7 @@ public class FileOperations {
}
/**
* Callback pro vyhledávání
* Callback for search
*/
public interface SearchCallback {
void onFileFound(File file);

View File

@ -144,11 +144,11 @@ public class FilePanel extends JPanel {
add(topPanel, BorderLayout.NORTH);
// JTabbedPane pro taby
// JTabbedPane for tabs
tabbedPane = new JTabbedPane();
tabbedPane.setTabPlacement(JTabbedPane.TOP);
// Listener pro aktualizaci cesty a stylu při změně tabu
// Listener for updating path and style on tab change
tabbedPane.addChangeListener(e -> {
updatePathField();
updateTabStyles();
@ -174,19 +174,19 @@ public class FilePanel extends JPanel {
* Add a new tab with a directory
*/
public void addNewTab(String path) {
// Získat view mode z aktuálního tabu
// Get view mode from current tab
ViewMode currentMode = getViewMode();
FilePanelTab tab = new FilePanelTab(path);
if (appConfig != null) tab.setAppConfig(appConfig);
// Nastavit callback pro aktualizaci názvu tabu při změně adresáře
// Set callback for updating tab title on directory change
tab.setOnDirectoryChanged(() -> updateTabTitle(tab));
// Forward switchPanel callback to the tab so TAB works from any tab
tab.setOnSwitchPanelRequested(switchPanelCallback);
// Nastavit stejný view mode jako aktuální tab
// Set same view mode as current tab
if (currentMode != null) {
tab.setViewMode(currentMode);
}
@ -196,11 +196,11 @@ public class FilePanel extends JPanel {
tabbedPane.addTab(tabTitle, tab);
tabbedPane.setSelectedComponent(tab);
// Aktualizovat path field
// Update path field
updatePathField();
updateTabStyles();
// Nastavit focus na tabulku v novém tabu
// Set focus to the table in the new tab
SwingUtilities.invokeLater(() -> {
tab.getFileTable().requestFocusInWindow();
// Ensure renderers are attached now that the tab is added to the UI
@ -209,7 +209,7 @@ public class FilePanel extends JPanel {
}
/**
* Přidá nový tab a explicitně nastaví ViewMode pro tento tab.
* Add a new tab and explicitly set the ViewMode for this tab.
*/
public void addNewTabWithMode(String path, ViewMode mode) {
FilePanelTab tab = new FilePanelTab(path);
@ -278,7 +278,7 @@ public class FilePanel extends JPanel {
}
/**
* Obnoví sadu tabů podle zadaných cest a view módů. Pokud je seznam prázdný, nic se nestane.
* Restore the set of tabs according to specified paths and view modes. If the list is empty, nothing happens.
*/
public void restoreTabs(java.util.List<String> paths, java.util.List<String> viewModes, int selectedIndex) {
if (paths == null || paths.isEmpty()) return;
@ -338,7 +338,7 @@ public class FilePanel extends JPanel {
private String getTabTitle(String path) {
String tabTitle = new File(path).getName();
if (tabTitle.isEmpty()) {
tabTitle = path; // Pro root cesty jako "C:\"
tabTitle = path; // For root paths like "C:\"
}
return tabTitle;
}
@ -351,7 +351,7 @@ public class FilePanel extends JPanel {
}
/**
* Aktualizuje styl tabů - zvýrazní aktivní tab tučným písmem a barvou.
* Updates tab style - highlights the active tab with bold font and color.
*/
private void updateTabStyles() {
if (tabbedPane == null) return;
@ -364,11 +364,11 @@ public class FilePanel extends JPanel {
String title = getTabTitle(dir != null ? dir.getAbsolutePath() : "");
if (i == selectedIndex) {
// Aktivní tab: tučné písmo a tmavě modrá barva
// Active tab: bold font and dark blue color
tabbedPane.setTitleAt(i, "<html><b>" + title + "</b></html>");
tabbedPane.setForegroundAt(i, new Color(0, 51, 153));
} else {
// Neaktivní tab: normální písmo a výchozí barva
// Inactive tab: normal font and default color
tabbedPane.setTitleAt(i, title);
tabbedPane.setForegroundAt(i, null);
}
@ -479,7 +479,7 @@ public class FilePanel extends JPanel {
}
}
// Delegování metod na aktuální tab
// Delegation of methods to current tab
/**
* Switch to the next tab in this panel.

View File

@ -355,16 +355,16 @@ public class FilePanelTab extends JPanel {
// remain visible.
fileTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
// Nastavit Cell Selection mode pouze v BRIEF režimu
// Set Cell Selection mode only in BRIEF mode
fileTable.setCellSelectionEnabled(false);
fileTable.setRowSelectionAllowed(true);
fileTable.setColumnSelectionAllowed(false);
// Odstranit bordery z tabulky
// Remove table borders
fileTable.setShowGrid(false);
fileTable.setIntercellSpacing(new java.awt.Dimension(0, 0));
// Nastavit pozadí tabulky stejné jako pozadí panelu
// Set table background same as panel background
fileTable.setBackground(this.getBackground());
fileTable.setOpaque(true);
@ -383,9 +383,9 @@ public class FilePanelTab extends JPanel {
@Override
public void componentResized(java.awt.event.ComponentEvent e) {
if (viewMode == ViewMode.BRIEF) {
// Při změně velikosti v BRIEF módu přepočítat layout
// Recalculate layout on resize in BRIEF mode
SwingUtilities.invokeLater(() -> {
// Zapamatovat si vybranou položku
// Remember selected item
String selectedItemName = null;
int selectedRow = fileTable.getSelectedRow();
if (selectedRow >= 0) {
@ -395,13 +395,13 @@ public class FilePanelTab extends JPanel {
}
}
// Přepočítat layout
// Recalculate layout
tableModel.calculateBriefLayout();
tableModel.fireTableStructureChanged();
updateColumnRenderers();
updateColumnWidths();
// Znovu vybrat položku
// Re-select item
if (selectedItemName != null) {
selectItemByName(selectedItemName);
}
@ -716,7 +716,7 @@ public class FilePanelTab extends JPanel {
updateStatus();
// Oznámit změnu adresáře
// Notify directory change
if (onDirectoryChanged != null) {
onDirectoryChanged.run();
}
@ -1207,8 +1207,8 @@ public class FilePanelTab extends JPanel {
private void updateColumnRenderers() {
int columnCount = tableModel.getColumnCount();
if (columnCount == 0 || fileTable.getColumnModel().getColumnCount() != columnCount) {
// Sloupce tabulky se možná ještě nepřevedly po změně struktury.
// Zkusíme to znovu asynchronně po krátkém odložení.
// Table columns might not have been converted yet after structure change.
// Try again asynchronously after a short delay.
SwingUtilities.invokeLater(() -> updateColumnRenderers());
return;
}
@ -1296,7 +1296,7 @@ public class FilePanelTab extends JPanel {
}
}
// Zobrazit ikonu pro názvy souborů
// Show icon for file names
Icon icon = item.getIcon();
if (item.getName().equals("..")) {
icon = new UpArrowIcon(getForeground());
@ -1305,10 +1305,10 @@ public class FilePanelTab extends JPanel {
}
if (viewMode == ViewMode.BRIEF) {
// V BRIEF módu jsou všechny sloupce názvy
// In BRIEF mode all columns are names
setIcon(icon);
} else if (viewMode == ViewMode.FULL && column == 0) {
// V FULL módu je ikona pouze v prvním sloupci (názvy)
// In FULL mode the icon is only in the first column (names)
setIcon(icon);
} else {
setIcon(null);
@ -1340,9 +1340,9 @@ public class FilePanelTab extends JPanel {
return;
}
// Pokud se ColumnModel ještě nepřizpůsobil nové struktuře (např. po fireTableStructureChanged()),
// počkej a zkus nastavit renderery později - jinak nové sloupce nedostanou renderer a ikony se
// neprojeví v FULL módu.
// If ColumnModel has not yet adapted to the new structure (e.g. after fireTableStructureChanged()),
// wait and try to set renderers later - otherwise new columns won't get a renderer and icons won't
// show up in FULL mode.
if (fileTable.getColumnModel().getColumnCount() != columnCount) {
SwingUtilities.invokeLater(() -> updateColumnRenderers());
return;
@ -1423,7 +1423,7 @@ public class FilePanelTab extends JPanel {
}
if (markedCount > 0) {
statusLabel.setText(String.format(" Označeno: %d souborů, %d adresářů (%s)",
statusLabel.setText(String.format(" Selected: %d files, %d directories (%s)",
fileCount, dirCount, formatSize(totalSize)));
} else {
int selectedRow = fileTable.getSelectedRow();
@ -1448,10 +1448,10 @@ public class FilePanelTab extends JPanel {
item.getFormattedDate()));
}
} else {
statusLabel.setText(String.format(" Položek: %d", tableModel.items.size()));
statusLabel.setText(String.format(" Items: %d", tableModel.items.size()));
}
} else {
statusLabel.setText(String.format(" Položek: %d", tableModel.items.size()));
statusLabel.setText(String.format(" Items: %d", tableModel.items.size()));
}
}
}
@ -1794,7 +1794,7 @@ public class FilePanelTab extends JPanel {
}
}
// Gettery
// Getters
public JTable getFileTable() {
return fileTable;
}
@ -1807,10 +1807,10 @@ public class FilePanelTab extends JPanel {
return viewMode;
}
// FileTableModel - stejný jako v původním FilePanel
// FileTableModel
private class FileTableModel extends AbstractTableModel {
private List<FileItem> items = new ArrayList<>();
private String[] columnNames = {"Název", "Velikost", "Datum"};
private String[] columnNames = {"Name", "Size", "Date"};
public int briefColumns = 1;
public int briefRowsPerColumn = 10;

View File

@ -20,7 +20,7 @@ public class MainWindow extends JFrame {
private FilePanel rightPanel;
private FilePanel activePanel;
private JPanel buttonPanel;
private JTextField commandLine;
private JComboBox<String> commandLine;
private AppConfig config;
public MainWindow() {
@ -75,7 +75,7 @@ public class MainWindow extends JFrame {
ViewMode leftViewMode = ViewMode.valueOf(config.getLeftPanelViewMode());
leftPanel.setViewMode(leftViewMode);
} catch (IllegalArgumentException e) {
// Výchozí hodnota FULL je již nastavena
// Default value FULL is already set
}
// Right panel - load path and ViewMode from configuration
@ -91,7 +91,7 @@ public class MainWindow extends JFrame {
ViewMode rightViewMode = ViewMode.valueOf(config.getRightPanelViewMode());
rightPanel.setViewMode(rightViewMode);
} catch (IllegalArgumentException e) {
// Výchozí hodnota FULL je již nastavena
// Default value FULL is already set
}
mainPanel.add(leftPanel);
@ -146,19 +146,19 @@ public class MainWindow extends JFrame {
public void focusGained(FocusEvent e) {
activePanel = leftPanel;
updateActivePanelBorder();
// Zajistit, že je vybrán nějaký řádek
// Ensure some row is selected
JTable leftTable = leftPanel.getFileTable();
if (leftTable.getSelectedRow() == -1 && leftTable.getRowCount() > 0) {
leftTable.setRowSelectionInterval(0, 0);
}
// Překreslit oba panely
// Repaint both panels
leftPanel.getFileTable().repaint();
rightPanel.getFileTable().repaint();
}
@Override
public void focusLost(FocusEvent e) {
// Překreslit při ztrátě focusu
// Repaint on focus loss
leftPanel.getFileTable().repaint();
}
});
@ -168,19 +168,19 @@ public class MainWindow extends JFrame {
public void focusGained(FocusEvent e) {
activePanel = rightPanel;
updateActivePanelBorder();
// Zajistit, že je vybrán nějaký řádek
// Ensure some row is selected
JTable rightTable = rightPanel.getFileTable();
if (rightTable.getSelectedRow() == -1 && rightTable.getRowCount() > 0) {
rightTable.setRowSelectionInterval(0, 0);
}
// Překreslit oba panely
// Repaint both panels
leftPanel.getFileTable().repaint();
rightPanel.getFileTable().repaint();
}
@Override
public void focusLost(FocusEvent e) {
// Překreslit při ztrátě focusu
// Repaint on focus loss
rightPanel.getFileTable().repaint();
}
});
@ -218,28 +218,42 @@ public class MainWindow extends JFrame {
cmdLabel.setFont(new Font("Monospaced", Font.BOLD, 12));
cmdPanel.add(cmdLabel, BorderLayout.WEST);
commandLine = new JTextField();
commandLine = new JComboBox<>();
commandLine.setEditable(true);
commandLine.setFont(new Font("Monospaced", Font.PLAIN, 12));
commandLine.setFocusTraversalKeysEnabled(false);
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().requestFocusInWindow();
e.consume();
} else if (e.getKeyCode() == KeyEvent.VK_TAB) {
activePanel.getFileTable().requestFocusInWindow();
e.consume();
// Handle the editor component (usually a JTextField)
Component editorComp = commandLine.getEditor().getEditorComponent();
if (editorComp instanceof JTextField) {
JTextField tf = (JTextField) editorComp;
tf.setFocusTraversalKeysEnabled(false);
tf.addActionListener(e -> executeCommand(tf.getText()));
// Let the panels catch focus back if user presses ESC or TAB in command line
tf.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
tf.setText("");
activePanel.getFileTable().requestFocusInWindow();
e.consume();
} else if (e.getKeyCode() == KeyEvent.VK_TAB) {
activePanel.getFileTable().requestFocusInWindow();
e.consume();
}
}
}
});
});
}
cmdPanel.add(commandLine, BorderLayout.CENTER);
// Load history from config
java.util.List<String> history = config.getCommandLineHistory();
for (int i = 0; i < history.size(); i++) {
commandLine.addItem(history.get(i));
}
commandLine.getEditor().setItem(""); // Ensure it starts empty
bottomContainer.add(cmdPanel, BorderLayout.NORTH);
// Bottom panel with buttons
@ -285,7 +299,7 @@ public class MainWindow extends JFrame {
toolBar.addSeparator();
// Informační label
// Info label
JLabel infoLabel = new JLabel(" View Mode ");
infoLabel.setFont(infoLabel.getFont().deriveFont(Font.PLAIN, 10f));
toolBar.add(infoLabel);
@ -493,7 +507,7 @@ public class MainWindow extends JFrame {
private void setupKeyBindings() {
JRootPane rootPane = getRootPane();
// F3 - Prohlížeč
// F3 - Viewer
rootPane.registerKeyboardAction(e -> viewFile(),
KeyStroke.getKeyStroke(KeyEvent.VK_F3, 0),
JComponent.WHEN_IN_FOCUSED_WINDOW);
@ -560,7 +574,7 @@ public class MainWindow extends JFrame {
rootPane.registerKeyboardAction(e -> {
if (activePanel != null) {
// Always clear command line and return focus to panels
commandLine.setText("");
commandLine.getEditor().setItem("");
activePanel.getFileTable().requestFocusInWindow();
}
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
@ -616,6 +630,11 @@ public class MainWindow extends JFrame {
rootPane.registerKeyboardAction(e -> closeCurrentTabInActivePanel(),
KeyStroke.getKeyStroke(KeyEvent.VK_W, 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),
JComponent.WHEN_IN_FOCUSED_WINDOW);
}
/**
@ -687,7 +706,7 @@ public class MainWindow extends JFrame {
* Attach TAB handling to switch panels
*/
private void addTabKeyHandler(JTable table) {
// Odstraníme standardní chování TAB ve Swing
// Remove standard Swing TAB behavior
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "switchPanel");
table.getActionMap().put("switchPanel", new AbstractAction() {
@ -709,7 +728,7 @@ public class MainWindow extends JFrame {
}
});
// Přidáme F8 pro mazání s vyšší prioritou než defaultní Swing akce
// Add F8 for deleting with higher priority than default Swing actions
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_F8, 0), "deleteFiles");
table.getActionMap().put("deleteFiles", new AbstractAction() {
@ -757,7 +776,8 @@ public class MainWindow extends JFrame {
// 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);
String current = commandLine.getEditor().getItem().toString();
commandLine.getEditor().setItem(current + c);
e.consume();
}
}
@ -767,7 +787,7 @@ public class MainWindow extends JFrame {
private void copyFocusedToCommandLine(boolean fullPath) {
FileItem focused = activePanel.getFocusedItem();
if (focused != null && !focused.getName().equals("..")) {
String current = commandLine.getText();
String current = commandLine.getEditor().getItem().toString();
String toAdd = fullPath ? focused.getFile().getAbsolutePath() : focused.getName();
// If it contains spaces, wrap in quotes
@ -776,9 +796,9 @@ public class MainWindow extends JFrame {
}
if (!current.isEmpty() && !current.endsWith(" ")) {
commandLine.setText(current + " " + toAdd);
commandLine.getEditor().setItem(current + " " + toAdd);
} else {
commandLine.setText(current + toAdd);
commandLine.getEditor().setItem(current + toAdd);
}
commandLine.requestFocusInWindow();
}
@ -808,7 +828,7 @@ public class MainWindow extends JFrame {
if (result == JOptionPane.OK_OPTION) {
performFileOperation((callback) -> {
FileOperations.copy(selectedItems, targetDir, callback);
}, "Kopírování dokončeno", true, targetPanel);
}, "Copy completed", true, targetPanel);
}
}
@ -836,7 +856,7 @@ public class MainWindow extends JFrame {
if (result == JOptionPane.OK_OPTION) {
performFileOperation((callback) -> {
FileOperations.move(selectedItems, targetDir, callback);
}, "Přesouvání dokončeno", false, activePanel, targetPanel);
}, "Move completed", false, activePanel, targetPanel);
}
}
@ -867,14 +887,14 @@ public class MainWindow extends JFrame {
int result = JOptionPane.showConfirmDialog(this,
message.toString(),
"Mazání",
"Delete",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE);
if (result == JOptionPane.YES_OPTION) {
performFileOperation((callback) -> {
FileOperations.delete(selectedItems, callback);
}, "Mazání dokončeno", false, activePanel);
}, "Delete completed", false, activePanel);
// After deletion and refresh, restore selection: stay on same row if possible,
// otherwise move selection one row up.
@ -949,7 +969,7 @@ public class MainWindow extends JFrame {
final File finalTargetZip = targetZip;
performFileOperation((callback) -> {
FileOperations.zip(selectedItems, finalTargetZip, callback);
}, "Zabaleno do " + zipName, false, targetPanel);
}, "Zipped into " + zipName, false, targetPanel);
}
/**
@ -985,7 +1005,7 @@ public class MainWindow extends JFrame {
if (result == JOptionPane.OK_OPTION) {
performFileOperation((callback) -> {
FileOperations.unzip(zipFile, targetDir, callback);
}, "Rozbaleno do " + targetDir.getName(), false, targetPanel);
}, "Unzipped into " + targetDir.getName(), false, targetPanel);
}
}
@ -1014,7 +1034,7 @@ public class MainWindow extends JFrame {
if (newName != null && !newName.trim().isEmpty() && !newName.equals(item.getName())) {
performFileOperation((callback) -> {
FileOperations.rename(item.getFile(), newName.trim());
}, "Přejmenování dokončeno", false, activePanel);
}, "Rename completed", false, activePanel);
}
}
}
@ -1139,8 +1159,8 @@ public class MainWindow extends JFrame {
} catch (Exception ex) {
// Fall back to internal editor if external fails
JOptionPane.showMessageDialog(this,
"Nelze spustit externí editor: " + ex.getMessage() + "\nPoužije se interní editor.",
"Chyba", JOptionPane.ERROR_MESSAGE);
"Could not start external editor: " + ex.getMessage() + "\nUsing internal editor.",
"Error", JOptionPane.ERROR_MESSAGE);
}
}
@ -1153,8 +1173,8 @@ public class MainWindow extends JFrame {
* Refresh both panels
*/
private void refreshPanels() {
// Refresh je nyní automatický při změnách
// Pokud je potřeba manuální refresh, můžeme zavolat loadDirectory
// Refresh is now automatic upon changes
// If manual refresh is needed, we can call loadDirectory
if (leftPanel.getCurrentDirectory() != null) {
leftPanel.loadDirectory(leftPanel.getCurrentDirectory());
}
@ -1172,6 +1192,16 @@ public class MainWindow extends JFrame {
}
}
/**
* Show history of command line
*/
private void showCommandLineHistory() {
if (commandLine != null) {
commandLine.requestFocusInWindow();
commandLine.showPopup();
}
}
/**
* Add a new tab to the active panel
*/
@ -1247,8 +1277,8 @@ public class MainWindow extends JFrame {
} catch (Exception e) {
JOptionPane.showMessageDialog(this,
"Chyba při otevírání terminálu: " + e.getMessage(),
"Chyba",
"Error opening terminal: " + e.getMessage(),
"Error",
JOptionPane.ERROR_MESSAGE);
}
}
@ -1259,6 +1289,9 @@ public class MainWindow extends JFrame {
return;
}
// Add to history
addCommandToHistory(command.trim());
File currentDir = activePanel.getCurrentDirectory();
if (currentDir == null) {
currentDir = new File(System.getProperty("user.home"));
@ -1309,18 +1342,39 @@ public class MainWindow extends JFrame {
if (pb != null) {
pb.directory(currentDir);
pb.start();
commandLine.setText(""); // Clear after execution
// Clear after execution
Component editorComp = commandLine.getEditor().getEditorComponent();
if (editorComp instanceof JTextField) {
((JTextField) editorComp).setText("");
} else {
commandLine.setSelectedItem("");
}
activePanel.getFileTable().requestFocusInWindow();
}
} catch (Exception e) {
JOptionPane.showMessageDialog(this,
"Chyba při spouštění příkazu: " + e.getMessage(),
"Chyba",
"Error executing command: " + e.getMessage(),
"Error",
JOptionPane.ERROR_MESSAGE);
}
}
private void addCommandToHistory(String command) {
if (command == null || command.isEmpty()) return;
// Remove if already exists to move it to the top
for (int i = 0; i < commandLine.getItemCount(); i++) {
if (command.equals(commandLine.getItemAt(i))) {
commandLine.removeItemAt(i);
break;
}
}
commandLine.insertItemAt(command, 0);
// We don't necessarily want to select it here as it might interfere with the editor state
}
/**
* Show About dialog
*/
@ -1351,7 +1405,7 @@ public class MainWindow extends JFrame {
* Execute file operation with error handling
*/
private void performFileOperation(FileOperation operation, String successMessage, boolean showBytes, FilePanel... panelsToRefresh) {
ProgressDialog progressDialog = new ProgressDialog(this, "Operační systém");
ProgressDialog progressDialog = new ProgressDialog(this, "File Operation");
progressDialog.setDisplayAsBytes(showBytes);
FileOperations.ProgressCallback callback = new FileOperations.ProgressCallback() {
@ -1379,15 +1433,15 @@ public class MainWindow extends JFrame {
}
}
if (callback.isCancelled()) {
JOptionPane.showMessageDialog(MainWindow.this, "Operace byla přerušena uživatelem.");
JOptionPane.showMessageDialog(MainWindow.this, "Operation was cancelled by user.");
}
});
} catch (Exception e) {
SwingUtilities.invokeLater(() -> {
progressDialog.dispose();
JOptionPane.showMessageDialog(MainWindow.this,
"Chyba: " + e.getMessage(),
"Chyba",
"Error: " + e.getMessage(),
"Error",
JOptionPane.ERROR_MESSAGE);
});
}
@ -1446,7 +1500,14 @@ public class MainWindow extends JFrame {
// ignore
}
// Uložit konfiguraci do souboru
// Save command history
java.util.List<String> cmdHistory = new java.util.ArrayList<>();
for (int i = 0; i < commandLine.getItemCount(); i++) {
cmdHistory.add(commandLine.getItemAt(i));
}
config.saveCommandLineHistory(cmdHistory);
// Save configuration to file
config.saveConfig();
// Exit application