refresh panels

This commit is contained in:
Radek Davidek 2026-01-20 16:00:24 +01:00
parent 64da0a8b1f
commit 6a9a0f32aa
7 changed files with 179 additions and 35 deletions

View File

@ -465,6 +465,14 @@ public class AppConfig {
properties.setProperty("global.sort.ignore.leadingdot", String.valueOf(enabled));
}
public int getAutoRefreshInterval() {
return Integer.parseInt(properties.getProperty("panel.autoRefreshInterval", "2000"));
}
public void setAutoRefreshInterval(int interval) {
properties.setProperty("panel.autoRefreshInterval", String.valueOf(interval));
}
// -- Multiple sort criteria persistence
public java.util.List<String> getMultipleSortCriteria() {
java.util.List<String> list = new java.util.ArrayList<>();

View File

@ -69,6 +69,19 @@ public class FileItem {
return isDirectory;
}
/**
* Check if this item is the same as another item based on metadata.
*/
public boolean isSameAs(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
FileItem other = (FileItem) obj;
return isDirectory == other.isDirectory &&
size == other.size &&
(name != null ? name.equals(other.name) : other.name == null) &&
(modified != null ? modified.getTime() == other.modified.getTime() : other.modified == null);
}
public Icon getIcon() {
return icon;
}

View File

@ -718,6 +718,13 @@ public class FilePanel extends JPanel {
}
}
public void refresh(boolean requestFocus) {
FilePanelTab tab = getCurrentTab();
if (tab != null) {
tab.refresh(requestFocus);
}
}
public void toggleSelectionAndMoveDown() {
FilePanelTab tab = getCurrentTab();
if (tab != null) {

View File

@ -861,29 +861,7 @@ public class FilePanelTab extends JPanel {
lastValidRow = 0;
lastValidBriefColumn = 0;
File[] files = directory.listFiles();
List<FileItem> items = new ArrayList<>();
File parent = directory.getParentFile();
if (parent != null) {
items.add(new FileItem(parent) {
@Override
public String getName() {
return "..";
}
});
}
if (files != null && files.length > 0) {
Arrays.sort(files, Comparator
.comparing((File f) -> !f.isDirectory())
.thenComparing(File::getName, String.CASE_INSENSITIVE_ORDER));
for (File file : files) {
items.add(new FileItem(file));
}
}
List<FileItem> items = createFileItemList(directory);
tableModel.setItems(items);
if (viewMode == ViewMode.BRIEF) {
@ -912,13 +890,13 @@ public class FilePanelTab extends JPanel {
if (autoSelectFirst && fileTable.getRowCount() > 0) {
int startIndex = 0;
fileTable.setRowSelectionInterval(startIndex, startIndex);
}
if (requestFocus) {
SwingUtilities.invokeLater(() -> {
try { fileTable.requestFocusInWindow(); } catch (Exception ignore) {}
});
}
}
}
updateStatus();
@ -928,6 +906,94 @@ public class FilePanelTab extends JPanel {
}
}
/**
* Refresh the current directory while attempting to preserve selection and focus.
*/
public void refresh(boolean requestFocus) {
List<FileItem> newItems = createFileItemList(currentDirectory);
if (isSameContent(newItems, tableModel.items)) {
return;
}
FileItem focused = getFocusedItem();
final String focusedName = (focused != null) ? focused.getName() : null;
final List<String> markedNames = new ArrayList<>();
for (FileItem item : tableModel.items) {
if (item.isMarked()) {
markedNames.add(item.getName());
}
}
loadDirectory(currentDirectory, false, requestFocus);
SwingUtilities.invokeLater(() -> {
// Restore marks
for (FileItem item : tableModel.items) {
if (markedNames.contains(item.getName())) {
item.setMarked(true);
}
}
// Restore focus
if (focusedName != null) {
for (int i = 0; i < tableModel.items.size(); i++) {
if (tableModel.items.get(i).getName().equals(focusedName)) {
int row = i;
if (viewMode == ViewMode.BRIEF) {
int selRow = row % tableModel.briefRowsPerColumn;
int selCol = row / tableModel.briefRowsPerColumn;
briefCurrentColumn = selCol;
fileTable.getSelectionModel().setSelectionInterval(selRow, selRow);
fileTable.getColumnModel().getSelectionModel().setSelectionInterval(selCol, selCol);
fileTable.scrollRectToVisible(fileTable.getCellRect(selRow, selCol, true));
} else {
fileTable.getSelectionModel().setSelectionInterval(row, row);
fileTable.scrollRectToVisible(fileTable.getCellRect(row, 0, true));
}
break;
}
}
}
fileTable.repaint();
updateStatus();
});
}
private List<FileItem> createFileItemList(File directory) {
if (directory == null || !directory.isDirectory()) {
return new ArrayList<>();
}
File[] files = directory.listFiles();
List<FileItem> items = new ArrayList<>();
File parent = directory.getParentFile();
if (parent != null) {
items.add(new FileItem(parent) {
@Override
public String getName() {
return "..";
}
});
}
if (files != null && files.length > 0) {
Arrays.sort(files, Comparator
.comparing((File f) -> !f.isDirectory())
.thenComparing(File::getName, String.CASE_INSENSITIVE_ORDER));
for (File file : files) {
items.add(new FileItem(file));
}
}
return items;
}
private boolean isSameContent(List<FileItem> list1, List<FileItem> list2) {
if (list1.size() != list2.size()) return false;
for (int i = 0; i < list1.size(); i++) {
if (!list1.get(i).isSameAs(list2.get(i))) return false;
}
return true;
}
/**
* Cleanup previous archive temp dir when navigating away from it.
*/

View File

@ -28,6 +28,7 @@ public class MainWindow extends JFrame {
private JComboBox<String> commandLine;
private JLabel cmdLabel;
private AppConfig config;
private Timer autoRefreshTimer;
public MainWindow() {
super("KF Manager v" + MainApp.APP_VERSION);
@ -56,6 +57,14 @@ public class MainWindow extends JFrame {
}
});
// Refresh panels when application gains focus
addWindowFocusListener(new WindowAdapter() {
@Override
public void windowGainedFocus(WindowEvent e) {
refreshPanels();
}
});
// After start, set focus and selection to the active panel
String initialActiveSide = config.getActivePanel();
SwingUtilities.invokeLater(() -> {
@ -69,6 +78,9 @@ public class MainWindow extends JFrame {
updateActivePanelBorder();
updateCommandLinePrompt();
});
// Setup auto-refresh timer from config
updateAutoRefreshTimer();
}
private void loadAppIcon() {
@ -399,6 +411,18 @@ public class MainWindow extends JFrame {
toolBar.removeAll();
// Refresh button
JButton btnRefresh = new JButton("");
btnRefresh.setToolTipText("Refresh active panel");
btnRefresh.setFocusable(false);
btnRefresh.addActionListener(e -> {
if (activePanel != null && activePanel.getCurrentDirectory() != null) {
activePanel.refresh(true);
}
});
toolBar.add(btnRefresh);
toolBar.addSeparator();
// Button for BRIEF mode
JButton btnBrief = new JButton("☰ Brief");
btnBrief.setToolTipText("Brief mode - multiple columns (Ctrl+F1)");
@ -725,6 +749,7 @@ public class MainWindow extends JFrame {
* Apply appearance settings (font/colors) from config to UI components.
*/
private void applyAppearanceSettings() {
updateAutoRefreshTimer();
Font gfont = config.getGlobalFont();
if (gfont != null) {
// Apply to toolbars, buttons and tables
@ -1749,16 +1774,14 @@ public class MainWindow extends JFrame {
}
/**
* Refresh both panels
* Refresh both panels while preserving selection and active panel focus.
*/
private void refreshPanels() {
// Refresh is now automatic upon changes
// If manual refresh is needed, we can call loadDirectory
if (leftPanel.getCurrentDirectory() != null) {
leftPanel.loadDirectory(leftPanel.getCurrentDirectory());
if (leftPanel != null && leftPanel.getCurrentDirectory() != null) {
leftPanel.refresh(activePanel == leftPanel);
}
if (rightPanel.getCurrentDirectory() != null) {
rightPanel.loadDirectory(rightPanel.getCurrentDirectory());
if (rightPanel != null && rightPanel.getCurrentDirectory() != null) {
rightPanel.refresh(activePanel == rightPanel);
}
}
@ -2177,6 +2200,9 @@ public class MainWindow extends JFrame {
* Save configuration and exit application
*/
private void saveConfigAndExit() {
if (autoRefreshTimer != null) {
autoRefreshTimer.stop();
}
// Save window state
config.saveWindowState(this);
@ -2257,4 +2283,17 @@ public class MainWindow extends JFrame {
activePanel.getFileTable().requestFocusInWindow();
}
}
private void updateAutoRefreshTimer() {
if (autoRefreshTimer != null) {
autoRefreshTimer.stop();
}
int interval = config.getAutoRefreshInterval();
autoRefreshTimer = new Timer(interval, e -> {
if (activePanel != null && activePanel.getCurrentDirectory() != null) {
activePanel.refresh(false);
}
});
autoRefreshTimer.start();
}
}

View File

@ -209,6 +209,8 @@ public class SettingsDialog extends JDialog {
try {
JSpinner mws = (JSpinner) behaviorHolder.getClientProperty("mouseWheelSteps");
if (mws != null) config.setBriefMouseWheelSteps((Integer) mws.getValue());
JSpinner ari = (JSpinner) behaviorHolder.getClientProperty("autoRefreshInterval");
if (ari != null) config.setAutoRefreshInterval((Integer) ari.getValue());
} catch (Exception ignore) {}
}
@ -436,8 +438,17 @@ public class SettingsDialog extends JDialog {
gbc.gridx = 1; gbc.gridy = row++; gbc.weightx = 1.0;
grid.add(mwSteps, gbc);
// Auto-refresh interval
gbc.gridx = 0; gbc.gridy = row; gbc.weightx = 0.0;
grid.add(new JLabel("Auto-refresh interval (ms):"), gbc);
JSpinner refreshInt = new JSpinner(new SpinnerNumberModel(config.getAutoRefreshInterval(), 100, 600000, 100));
gbc.gridx = 1; gbc.gridy = row++; gbc.weightx = 1.0;
grid.add(refreshInt, gbc);
p.add(grid, BorderLayout.NORTH);
p.putClientProperty("mouseWheelSteps", mwSteps);
p.putClientProperty("autoRefreshInterval", refreshInt);
panels.put("Behavior", p);
return p;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 164 KiB