fixed focus on restart app

This commit is contained in:
rdavidek 2026-01-18 11:59:43 +01:00
parent 5454ac5a5c
commit 3b1065bc81
5 changed files with 104 additions and 28 deletions

View File

@ -4,7 +4,6 @@ import cz.kamma.kfmanager.ui.MainWindow;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.event.AWTEventListener;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
/** /**

View File

@ -93,6 +93,14 @@ public class AppConfig {
public void setWindowMaximized(boolean maximized) { public void setWindowMaximized(boolean maximized) {
properties.setProperty("window.maximized", String.valueOf(maximized)); properties.setProperty("window.maximized", String.valueOf(maximized));
} }
public String getActivePanel() {
return properties.getProperty("active.panel", "left");
}
public void setActivePanel(String panel) {
properties.setProperty("active.panel", panel);
}
public String getLeftPanelPath() { public String getLeftPanelPath() {
return properties.getProperty("leftPanel.path", System.getProperty("user.home")); return properties.getProperty("leftPanel.path", System.getProperty("user.home"));

View File

@ -21,7 +21,7 @@ public class FilePanel extends JPanel {
public FilePanel(String initialPath) { public FilePanel(String initialPath) {
initComponents(); initComponents();
addNewTab(initialPath); addNewTab(initialPath, false);
} }
public void setOnDirectoryChangedAll(Runnable callback) { public void setOnDirectoryChangedAll(Runnable callback) {
@ -215,11 +215,15 @@ public class FilePanel extends JPanel {
* Add a new tab with a directory * Add a new tab with a directory
*/ */
public void addNewTab(String path) { public void addNewTab(String path) {
addNewTab(path, true);
}
public void addNewTab(String path, boolean requestFocus) {
// Get view mode from current tab // Get view mode from current tab
ViewMode currentMode = getViewMode(); ViewMode currentMode = getViewMode();
FilePanelTab tab = new FilePanelTab(path); FilePanelTab tab = new FilePanelTab(path, requestFocus);
if (appConfig != null) tab.setAppConfig(appConfig); if (appConfig != null) tab.setAppConfig(appConfig);
// Set callback for updating tab title on directory change // Set callback for updating tab title on directory change
tab.setOnDirectoryChanged(() -> { tab.setOnDirectoryChanged(() -> {
@ -227,8 +231,8 @@ public class FilePanel extends JPanel {
if (onDirectoryChangedAll != null) onDirectoryChangedAll.run(); if (onDirectoryChangedAll != null) onDirectoryChangedAll.run();
}); });
// Forward switchPanel callback to the tab so TAB works from any tab // Forward switchPanel callback to the tab so TAB works from any tab
tab.setOnSwitchPanelRequested(switchPanelCallback); tab.setOnSwitchPanelRequested(switchPanelCallback);
// Set same view mode as current tab // Set same view mode as current tab
if (currentMode != null) { if (currentMode != null) {
@ -244,12 +248,13 @@ public class FilePanel extends JPanel {
addMouseListenerToComponents(tab); addMouseListenerToComponents(tab);
// Update path field // Update path field
updatePathField();
updateTabStyles(); updateTabStyles();
// Set focus to the table in the new tab // Set focus to the table in the new tab
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
tab.getFileTable().requestFocusInWindow(); if (requestFocus) {
tab.getFileTable().requestFocusInWindow();
}
// Ensure renderers are attached now that the tab is added to the UI // Ensure renderers are attached now that the tab is added to the UI
tab.ensureRenderers(); tab.ensureRenderers();
}); });
@ -259,7 +264,11 @@ public class FilePanel extends JPanel {
* Add a new tab and explicitly set the ViewMode for this tab. * Add a new tab and explicitly set the ViewMode for this tab.
*/ */
public void addNewTabWithMode(String path, ViewMode mode) { public void addNewTabWithMode(String path, ViewMode mode) {
FilePanelTab tab = new FilePanelTab(path); addNewTabWithMode(path, mode, true);
}
public void addNewTabWithMode(String path, ViewMode mode, boolean requestFocus) {
FilePanelTab tab = new FilePanelTab(path, requestFocus);
if (appConfig != null) tab.setAppConfig(appConfig); if (appConfig != null) tab.setAppConfig(appConfig);
tab.setOnDirectoryChanged(() -> { tab.setOnDirectoryChanged(() -> {
updateTabTitle(tab); updateTabTitle(tab);
@ -282,7 +291,9 @@ public class FilePanel extends JPanel {
updateTabStyles(); updateTabStyles();
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
tab.getFileTable().requestFocusInWindow(); if (requestFocus) {
tab.getFileTable().requestFocusInWindow();
}
tab.ensureRenderers(); tab.ensureRenderers();
}); });
} }
@ -346,6 +357,10 @@ public class FilePanel extends JPanel {
* Restore the set of tabs according to specified paths and view modes. If the list is empty, nothing happens. * 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, java.util.List<String> focusedItems, int selectedIndex) { public void restoreTabs(java.util.List<String> paths, java.util.List<String> viewModes, java.util.List<String> focusedItems, int selectedIndex) {
restoreTabs(paths, viewModes, focusedItems, selectedIndex, true);
}
public void restoreTabs(java.util.List<String> paths, java.util.List<String> viewModes, java.util.List<String> focusedItems, int selectedIndex, boolean requestFocus) {
if (paths == null || paths.isEmpty()) return; if (paths == null || paths.isEmpty()) return;
tabbedPane.removeAll(); tabbedPane.removeAll();
@ -360,13 +375,13 @@ public class FilePanel extends JPanel {
mode = ViewMode.FULL; mode = ViewMode.FULL;
} }
} }
addNewTabWithMode(p, mode); addNewTabWithMode(p, mode, false);
// Restore focus to the specific item if provided // Restore focus to the specific item if provided
if (focusedItems != null && i < focusedItems.size() && focusedItems.get(i) != null) { if (focusedItems != null && i < focusedItems.size() && focusedItems.get(i) != null) {
final String focusName = focusedItems.get(i); final String focusName = focusedItems.get(i);
final FilePanelTab currentTab = (FilePanelTab) tabbedPane.getComponentAt(i); final FilePanelTab currentTab = (FilePanelTab) tabbedPane.getComponentAt(i);
SwingUtilities.invokeLater(() -> currentTab.selectItem(focusName)); SwingUtilities.invokeLater(() -> currentTab.selectItem(focusName, requestFocus));
} }
} }
@ -639,9 +654,13 @@ public class FilePanel extends JPanel {
} }
public void setViewMode(ViewMode mode) { public void setViewMode(ViewMode mode) {
setViewMode(mode, true);
}
public void setViewMode(ViewMode mode, boolean requestFocus) {
FilePanelTab tab = getCurrentTab(); FilePanelTab tab = getCurrentTab();
if (tab != null) { if (tab != null) {
tab.setViewMode(mode); tab.setViewMode(mode, requestFocus);
} }
} }

View File

@ -64,9 +64,13 @@ public class FilePanelTab extends JPanel {
private File currentArchiveSourceFile = null; private File currentArchiveSourceFile = null;
public FilePanelTab(String initialPath) { public FilePanelTab(String initialPath) {
this(initialPath, true);
}
public FilePanelTab(String initialPath, boolean requestFocus) {
this.currentDirectory = new File(initialPath); this.currentDirectory = new File(initialPath);
initComponents(); initComponents();
loadDirectory(currentDirectory); loadDirectory(currentDirectory, true, requestFocus);
} }
/** Start inline rename for currently selected item (if single selection). */ /** Start inline rename for currently selected item (if single selection). */
@ -542,7 +546,7 @@ public class FilePanelTab extends JPanel {
// Re-select item // Re-select item
if (selectedItemName != null) { if (selectedItemName != null) {
selectItemByName(selectedItemName); selectItemByName(selectedItemName, false);
} }
}); });
} }
@ -1411,6 +1415,10 @@ public class FilePanelTab extends JPanel {
} }
private void selectItemByName(String name) { private void selectItemByName(String name) {
selectItemByName(name, true);
}
private void selectItemByName(String name, boolean requestFocus) {
if (viewMode == ViewMode.BRIEF) { if (viewMode == ViewMode.BRIEF) {
for (int i = 0; i < tableModel.items.size(); i++) { for (int i = 0; i < tableModel.items.size(); i++) {
FileItem item = tableModel.items.get(i); FileItem item = tableModel.items.get(i);
@ -1423,7 +1431,9 @@ public class FilePanelTab extends JPanel {
fileTable.setRowSelectionInterval(row, row); fileTable.setRowSelectionInterval(row, row);
fileTable.scrollRectToVisible(fileTable.getCellRect(row, column, true)); fileTable.scrollRectToVisible(fileTable.getCellRect(row, column, true));
fileTable.repaint(); fileTable.repaint();
fileTable.requestFocusInWindow(); if (requestFocus) {
fileTable.requestFocusInWindow();
}
updateStatus(); updateStatus();
} }
return; return;
@ -1435,7 +1445,9 @@ public class FilePanelTab extends JPanel {
if (item != null && item.getName().equals(name)) { if (item != null && item.getName().equals(name)) {
fileTable.setRowSelectionInterval(i, i); fileTable.setRowSelectionInterval(i, i);
fileTable.scrollRectToVisible(fileTable.getCellRect(i, 0, true)); fileTable.scrollRectToVisible(fileTable.getCellRect(i, 0, true));
fileTable.requestFocusInWindow(); if (requestFocus) {
fileTable.requestFocusInWindow();
}
updateStatus(); updateStatus();
return; return;
} }
@ -1448,7 +1460,11 @@ public class FilePanelTab extends JPanel {
* Useful for other UI components to request focusing a specific file. * Useful for other UI components to request focusing a specific file.
*/ */
public void selectItem(String name) { public void selectItem(String name) {
selectItemByName(name); selectItemByName(name, true);
}
public void selectItem(String name, boolean requestFocus) {
selectItemByName(name, requestFocus);
} }
public void toggleSelectionAndMoveDown() { public void toggleSelectionAndMoveDown() {
@ -1678,6 +1694,10 @@ public class FilePanelTab extends JPanel {
} }
public void setViewMode(ViewMode mode) { public void setViewMode(ViewMode mode) {
setViewMode(mode, true);
}
public void setViewMode(ViewMode mode, boolean requestFocus) {
if (this.viewMode != mode) { if (this.viewMode != mode) {
String selectedItemName = null; String selectedItemName = null;
int selectedRow = fileTable.getSelectedRow(); int selectedRow = fileTable.getSelectedRow();
@ -1715,12 +1735,14 @@ public class FilePanelTab extends JPanel {
fileTable.repaint(); fileTable.repaint();
if (itemToSelect != null) { if (itemToSelect != null) {
selectItemByName(itemToSelect); selectItemByName(itemToSelect, requestFocus);
} else if (fileTable.getRowCount() > 0) { } else if (fileTable.getRowCount() > 0) {
fileTable.setRowSelectionInterval(0, 0); fileTable.setRowSelectionInterval(0, 0);
} }
fileTable.requestFocusInWindow(); if (requestFocus) {
fileTable.requestFocusInWindow();
}
}); });
} }
} }

View File

@ -55,9 +55,18 @@ public class MainWindow extends JFrame {
} }
}); });
// After start, set focus and selection to the left panel // After start, set focus and selection to the active panel
String initialActiveSide = config.getActivePanel();
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
leftPanel.getFileTable().requestFocus(); if ("right".equalsIgnoreCase(initialActiveSide)) {
activePanel = rightPanel;
rightPanel.requestFocusOnCurrentTab();
} else {
activePanel = leftPanel;
leftPanel.requestFocusOnCurrentTab();
}
updateActivePanelBorder();
updateCommandLinePrompt();
}); });
} }
@ -94,7 +103,7 @@ public class MainWindow extends JFrame {
// Load and set ViewMode for left panel // Load and set ViewMode for left panel
try { try {
ViewMode leftViewMode = ViewMode.valueOf(config.getLeftPanelViewMode()); ViewMode leftViewMode = ViewMode.valueOf(config.getLeftPanelViewMode());
leftPanel.setViewMode(leftViewMode); leftPanel.setViewMode(leftViewMode, false);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// Default value FULL is already set // Default value FULL is already set
} }
@ -111,7 +120,7 @@ public class MainWindow extends JFrame {
// Load and set ViewMode for right panel // Load and set ViewMode for right panel
try { try {
ViewMode rightViewMode = ViewMode.valueOf(config.getRightPanelViewMode()); ViewMode rightViewMode = ViewMode.valueOf(config.getRightPanelViewMode());
rightPanel.setViewMode(rightViewMode); rightPanel.setViewMode(rightViewMode, false);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// Default value FULL is already set // Default value FULL is already set
} }
@ -121,8 +130,13 @@ public class MainWindow extends JFrame {
add(mainPanel, BorderLayout.CENTER); add(mainPanel, BorderLayout.CENTER);
// Set left panel as active by default // Restore active panel from configuration
activePanel = leftPanel; String savedActive = config.getActivePanel();
if ("right".equalsIgnoreCase(savedActive)) {
activePanel = rightPanel;
} else {
activePanel = leftPanel;
}
updateActivePanelBorder(); updateActivePanelBorder();
updateCommandLinePrompt(); updateCommandLinePrompt();
@ -141,7 +155,7 @@ public class MainWindow extends JFrame {
focusedItems.add(config.getLeftPanelTabFocusedItem(i)); focusedItems.add(config.getLeftPanelTabFocusedItem(i));
} }
int sel = config.getLeftPanelSelectedIndex(); int sel = config.getLeftPanelSelectedIndex();
leftPanel.restoreTabs(paths, modes, focusedItems, sel); leftPanel.restoreTabs(paths, modes, focusedItems, sel, false);
} }
} catch (Exception ex) { } catch (Exception ex) {
// ignore and keep default // ignore and keep default
@ -161,7 +175,7 @@ public class MainWindow extends JFrame {
focusedItems.add(config.getRightPanelTabFocusedItem(i)); focusedItems.add(config.getRightPanelTabFocusedItem(i));
} }
int sel = config.getRightPanelSelectedIndex(); int sel = config.getRightPanelSelectedIndex();
rightPanel.restoreTabs(paths, modes, focusedItems, sel); rightPanel.restoreTabs(paths, modes, focusedItems, sel, false);
} }
} catch (Exception ex) { } catch (Exception ex) {
// ignore and keep default // ignore and keep default
@ -304,6 +318,13 @@ public class MainWindow extends JFrame {
// Menu // Menu
createMenuBar(); createMenuBar();
// Request focus for the active panel
SwingUtilities.invokeLater(() -> {
if (activePanel != null && activePanel.getFileTable() != null) {
activePanel.getFileTable().requestFocusInWindow();
}
});
} }
/** /**
@ -1883,6 +1904,13 @@ public class MainWindow extends JFrame {
// Save window state // Save window state
config.saveWindowState(this); config.saveWindowState(this);
// Save active panel
if (activePanel == leftPanel) {
config.setActivePanel("left");
} else if (activePanel == rightPanel) {
config.setActivePanel("right");
}
// Save current panel paths (for backward compatibility) // Save current panel paths (for backward compatibility)
if (leftPanel.getCurrentDirectory() != null) { if (leftPanel.getCurrentDirectory() != null) {
config.setLeftPanelPath(leftPanel.getCurrentDirectory().getAbsolutePath()); config.setLeftPanelPath(leftPanel.getCurrentDirectory().getAbsolutePath());