refresh panels
This commit is contained in:
parent
64da0a8b1f
commit
6a9a0f32aa
@ -464,6 +464,14 @@ public class AppConfig {
|
|||||||
public void setIgnoreLeadingDot(boolean enabled) {
|
public void setIgnoreLeadingDot(boolean enabled) {
|
||||||
properties.setProperty("global.sort.ignore.leadingdot", String.valueOf(enabled));
|
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
|
// -- Multiple sort criteria persistence
|
||||||
public java.util.List<String> getMultipleSortCriteria() {
|
public java.util.List<String> getMultipleSortCriteria() {
|
||||||
|
|||||||
@ -69,6 +69,19 @@ public class FileItem {
|
|||||||
return isDirectory;
|
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() {
|
public Icon getIcon() {
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -717,6 +717,13 @@ public class FilePanel extends JPanel {
|
|||||||
updatePathField();
|
updatePathField();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void refresh(boolean requestFocus) {
|
||||||
|
FilePanelTab tab = getCurrentTab();
|
||||||
|
if (tab != null) {
|
||||||
|
tab.refresh(requestFocus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void toggleSelectionAndMoveDown() {
|
public void toggleSelectionAndMoveDown() {
|
||||||
FilePanelTab tab = getCurrentTab();
|
FilePanelTab tab = getCurrentTab();
|
||||||
|
|||||||
@ -861,29 +861,7 @@ public class FilePanelTab extends JPanel {
|
|||||||
lastValidRow = 0;
|
lastValidRow = 0;
|
||||||
lastValidBriefColumn = 0;
|
lastValidBriefColumn = 0;
|
||||||
|
|
||||||
File[] files = directory.listFiles();
|
List<FileItem> items = createFileItemList(directory);
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tableModel.setItems(items);
|
tableModel.setItems(items);
|
||||||
|
|
||||||
if (viewMode == ViewMode.BRIEF) {
|
if (viewMode == ViewMode.BRIEF) {
|
||||||
@ -912,11 +890,11 @@ public class FilePanelTab extends JPanel {
|
|||||||
if (autoSelectFirst && fileTable.getRowCount() > 0) {
|
if (autoSelectFirst && fileTable.getRowCount() > 0) {
|
||||||
int startIndex = 0;
|
int startIndex = 0;
|
||||||
fileTable.setRowSelectionInterval(startIndex, startIndex);
|
fileTable.setRowSelectionInterval(startIndex, startIndex);
|
||||||
if (requestFocus) {
|
}
|
||||||
SwingUtilities.invokeLater(() -> {
|
if (requestFocus) {
|
||||||
try { fileTable.requestFocusInWindow(); } catch (Exception ignore) {}
|
SwingUtilities.invokeLater(() -> {
|
||||||
});
|
try { fileTable.requestFocusInWindow(); } catch (Exception ignore) {}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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.
|
* Cleanup previous archive temp dir when navigating away from it.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -28,6 +28,7 @@ public class MainWindow extends JFrame {
|
|||||||
private JComboBox<String> commandLine;
|
private JComboBox<String> commandLine;
|
||||||
private JLabel cmdLabel;
|
private JLabel cmdLabel;
|
||||||
private AppConfig config;
|
private AppConfig config;
|
||||||
|
private Timer autoRefreshTimer;
|
||||||
|
|
||||||
public MainWindow() {
|
public MainWindow() {
|
||||||
super("KF Manager v" + MainApp.APP_VERSION);
|
super("KF Manager v" + MainApp.APP_VERSION);
|
||||||
@ -55,6 +56,14 @@ public class MainWindow extends JFrame {
|
|||||||
MainWindow.this.saveConfigAndExit();
|
MainWindow.this.saveConfigAndExit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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
|
// After start, set focus and selection to the active panel
|
||||||
String initialActiveSide = config.getActivePanel();
|
String initialActiveSide = config.getActivePanel();
|
||||||
@ -69,6 +78,9 @@ public class MainWindow extends JFrame {
|
|||||||
updateActivePanelBorder();
|
updateActivePanelBorder();
|
||||||
updateCommandLinePrompt();
|
updateCommandLinePrompt();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Setup auto-refresh timer from config
|
||||||
|
updateAutoRefreshTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadAppIcon() {
|
private void loadAppIcon() {
|
||||||
@ -399,6 +411,18 @@ public class MainWindow extends JFrame {
|
|||||||
|
|
||||||
toolBar.removeAll();
|
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
|
// Button for BRIEF mode
|
||||||
JButton btnBrief = new JButton("☰ Brief");
|
JButton btnBrief = new JButton("☰ Brief");
|
||||||
btnBrief.setToolTipText("Brief mode - multiple columns (Ctrl+F1)");
|
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.
|
* Apply appearance settings (font/colors) from config to UI components.
|
||||||
*/
|
*/
|
||||||
private void applyAppearanceSettings() {
|
private void applyAppearanceSettings() {
|
||||||
|
updateAutoRefreshTimer();
|
||||||
Font gfont = config.getGlobalFont();
|
Font gfont = config.getGlobalFont();
|
||||||
if (gfont != null) {
|
if (gfont != null) {
|
||||||
// Apply to toolbars, buttons and tables
|
// 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() {
|
private void refreshPanels() {
|
||||||
// Refresh is now automatic upon changes
|
if (leftPanel != null && leftPanel.getCurrentDirectory() != null) {
|
||||||
// If manual refresh is needed, we can call loadDirectory
|
leftPanel.refresh(activePanel == leftPanel);
|
||||||
if (leftPanel.getCurrentDirectory() != null) {
|
|
||||||
leftPanel.loadDirectory(leftPanel.getCurrentDirectory());
|
|
||||||
}
|
}
|
||||||
if (rightPanel.getCurrentDirectory() != null) {
|
if (rightPanel != null && rightPanel.getCurrentDirectory() != null) {
|
||||||
rightPanel.loadDirectory(rightPanel.getCurrentDirectory());
|
rightPanel.refresh(activePanel == rightPanel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2177,6 +2200,9 @@ public class MainWindow extends JFrame {
|
|||||||
* Save configuration and exit application
|
* Save configuration and exit application
|
||||||
*/
|
*/
|
||||||
private void saveConfigAndExit() {
|
private void saveConfigAndExit() {
|
||||||
|
if (autoRefreshTimer != null) {
|
||||||
|
autoRefreshTimer.stop();
|
||||||
|
}
|
||||||
// Save window state
|
// Save window state
|
||||||
config.saveWindowState(this);
|
config.saveWindowState(this);
|
||||||
|
|
||||||
@ -2257,4 +2283,17 @@ public class MainWindow extends JFrame {
|
|||||||
activePanel.getFileTable().requestFocusInWindow();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -209,6 +209,8 @@ public class SettingsDialog extends JDialog {
|
|||||||
try {
|
try {
|
||||||
JSpinner mws = (JSpinner) behaviorHolder.getClientProperty("mouseWheelSteps");
|
JSpinner mws = (JSpinner) behaviorHolder.getClientProperty("mouseWheelSteps");
|
||||||
if (mws != null) config.setBriefMouseWheelSteps((Integer) mws.getValue());
|
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) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,8 +438,17 @@ public class SettingsDialog extends JDialog {
|
|||||||
gbc.gridx = 1; gbc.gridy = row++; gbc.weightx = 1.0;
|
gbc.gridx = 1; gbc.gridy = row++; gbc.weightx = 1.0;
|
||||||
grid.add(mwSteps, gbc);
|
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.add(grid, BorderLayout.NORTH);
|
||||||
p.putClientProperty("mouseWheelSteps", mwSteps);
|
p.putClientProperty("mouseWheelSteps", mwSteps);
|
||||||
|
p.putClientProperty("autoRefreshInterval", refreshInt);
|
||||||
panels.put("Behavior", p);
|
panels.put("Behavior", p);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 164 KiB |
Loading…
x
Reference in New Issue
Block a user