windows support added
This commit is contained in:
parent
5762e24df6
commit
3418313aeb
10
pom.xml
10
pom.xml
@ -97,5 +97,15 @@
|
|||||||
<artifactId>junrar</artifactId>
|
<artifactId>junrar</artifactId>
|
||||||
<version>7.4.1</version>
|
<version>7.4.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.formdev</groupId>
|
||||||
|
<artifactId>flatlaf</artifactId>
|
||||||
|
<version>3.5.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.formdev</groupId>
|
||||||
|
<artifactId>flatlaf-extras</artifactId>
|
||||||
|
<version>3.5.1</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@ -1,10 +1,14 @@
|
|||||||
package cz.kamma.kfmanager;
|
package cz.kamma.kfmanager;
|
||||||
|
|
||||||
import cz.kamma.kfmanager.ui.MainWindow;
|
import cz.kamma.kfmanager.ui.MainWindow;
|
||||||
|
import com.formdev.flatlaf.FlatDarkLaf;
|
||||||
|
import com.formdev.flatlaf.FlatLightLaf;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main application class for KF File Manager
|
* Main application class for KF File Manager
|
||||||
@ -17,11 +21,26 @@ public class MainApp {
|
|||||||
// Set application name for X11/Wayland WM_CLASS
|
// Set application name for X11/Wayland WM_CLASS
|
||||||
System.setProperty("awt.app.name", "cz-kamma-kfmanager-MainApp");
|
System.setProperty("awt.app.name", "cz-kamma-kfmanager-MainApp");
|
||||||
|
|
||||||
// Set look and feel to system default
|
// Use FlatLaf for modern look and better system theme support
|
||||||
|
try {
|
||||||
|
if (System.getProperty("os.name").toLowerCase().contains("win")) {
|
||||||
|
// On Windows, use FlatLaf and detect system theme (light/dark)
|
||||||
|
if (isWindowsDarkMode()) {
|
||||||
|
FlatDarkLaf.setup();
|
||||||
|
} else {
|
||||||
|
FlatLightLaf.setup();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// On Linux and macOS, use FlatLaf as a better-looking alternative
|
||||||
|
// to the default system L&F
|
||||||
|
FlatLightLaf.setup();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
try {
|
try {
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
} catch (Exception e) {
|
} catch (Exception ex) {
|
||||||
e.printStackTrace();
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable arrow key navigation in JOptionPane dialogs
|
// Enable arrow key navigation in JOptionPane dialogs
|
||||||
@ -34,6 +53,22 @@ public class MainApp {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isWindowsDarkMode() {
|
||||||
|
try {
|
||||||
|
Process process = Runtime.getRuntime().exec("reg query \"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\" /v AppsUseLightTheme");
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
if (line.contains("AppsUseLightTheme")) {
|
||||||
|
return line.contains("0x0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignore and fallback to light
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private static void setupGlobalKeyNavigation() {
|
private static void setupGlobalKeyNavigation() {
|
||||||
Toolkit.getDefaultToolkit().addAWTEventListener(event -> {
|
Toolkit.getDefaultToolkit().addAWTEventListener(event -> {
|
||||||
if (event instanceof KeyEvent) {
|
if (event instanceof KeyEvent) {
|
||||||
|
|||||||
@ -774,6 +774,13 @@ public class FilePanel extends JPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void navigateUp() {
|
||||||
|
FilePanelTab tab = getCurrentTab();
|
||||||
|
if (tab != null) {
|
||||||
|
tab.navigateUp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void showArchiveFile(File archive, String entryName) {
|
public void showArchiveFile(File archive, String entryName) {
|
||||||
FilePanelTab tab = getCurrentTab();
|
FilePanelTab tab = getCurrentTab();
|
||||||
if (tab != null) {
|
if (tab != null) {
|
||||||
|
|||||||
@ -63,7 +63,7 @@ public class FilePanelTab extends JPanel {
|
|||||||
private Runnable onDirectoryChanged;
|
private Runnable onDirectoryChanged;
|
||||||
private Runnable onSwitchPanelRequested;
|
private Runnable onSwitchPanelRequested;
|
||||||
// Appearance customization
|
// Appearance customization
|
||||||
private Color selectionColor = new Color(184, 207, 229);
|
private Color selectionColor = null;
|
||||||
private Color markedColor = new Color(204, 153, 0);
|
private Color markedColor = new Color(204, 153, 0);
|
||||||
// Sorting state for FULL mode header clicks
|
// Sorting state for FULL mode header clicks
|
||||||
private int sortColumn = -1; // 0=name,1=size,2=date
|
private int sortColumn = -1; // 0=name,1=size,2=date
|
||||||
@ -1462,7 +1462,21 @@ public class FilePanelTab extends JPanel {
|
|||||||
cmdList.add(fullPath);
|
cmdList.add(fullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
new ProcessBuilder(cmdList).directory(file.getParentFile()).start();
|
new ProcessBuilder(cmdList).directory(file.getParentFile()).start();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
String osName = System.getProperty("os.name").toLowerCase();
|
||||||
|
if (osName.contains("win")) {
|
||||||
|
// Try via cmd.exe for Windows shell commands/scripts
|
||||||
|
new ProcessBuilder("cmd", "/c", trimmedCmd + (hasPlaceholder ? "" : " \"" + fullPath + "\""))
|
||||||
|
.directory(file.getParentFile()).start();
|
||||||
|
} else if (osName.contains("linux") || osName.contains("mac")) {
|
||||||
|
new ProcessBuilder("sh", "-c", trimmedCmd + (hasPlaceholder ? "" : " '" + fullPath + "'"))
|
||||||
|
.directory(file.getParentFile()).start();
|
||||||
|
} else {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
try { JOptionPane.showMessageDialog(this, "Cannot execute command: " + ex.getMessage()); } catch (Exception ignore) {}
|
try { JOptionPane.showMessageDialog(this, "Cannot execute command: " + ex.getMessage()); } catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
@ -2368,6 +2382,15 @@ public class FilePanelTab extends JPanel {
|
|||||||
// Hide table header in BRIEF mode to save vertical space and match requirements
|
// Hide table header in BRIEF mode to save vertical space and match requirements
|
||||||
if (fileTable.getTableHeader() != null) {
|
if (fileTable.getTableHeader() != null) {
|
||||||
fileTable.getTableHeader().setVisible(mode != ViewMode.BRIEF);
|
fileTable.getTableHeader().setVisible(mode != ViewMode.BRIEF);
|
||||||
|
// In JScrollPane, manually managing columnHeader might be necessary to reclaim space
|
||||||
|
Component parent = fileTable.getParent();
|
||||||
|
if (parent instanceof JViewport) {
|
||||||
|
Component scroll = parent.getParent();
|
||||||
|
if (scroll instanceof JScrollPane) {
|
||||||
|
JScrollPane sp = (JScrollPane) scroll;
|
||||||
|
sp.setColumnHeaderView(mode == ViewMode.BRIEF ? null : fileTable.getTableHeader());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
briefCurrentColumn = 0;
|
briefCurrentColumn = 0;
|
||||||
updateColumnRenderers();
|
updateColumnRenderers();
|
||||||
@ -2557,7 +2580,7 @@ public class FilePanelTab extends JPanel {
|
|||||||
// Show selection highlight even when the table doesn't have focus, but only
|
// Show selection highlight even when the table doesn't have focus, but only
|
||||||
// if this panel/tab is the active one.
|
// if this panel/tab is the active one.
|
||||||
if (isCurrentCell && FilePanelTab.this.active) {
|
if (isCurrentCell && FilePanelTab.this.active) {
|
||||||
setBackground(selectionColor);
|
setBackground(selectionColor != null ? selectionColor : table.getSelectionBackground());
|
||||||
} else {
|
} else {
|
||||||
setBackground(FilePanelTab.this.getBackground());
|
setBackground(FilePanelTab.this.getBackground());
|
||||||
}
|
}
|
||||||
@ -2581,7 +2604,11 @@ public class FilePanelTab extends JPanel {
|
|||||||
setFont(baseFont.deriveFont(baseStyle));
|
setFont(baseFont.deriveFont(baseStyle));
|
||||||
// Automatically adjust foreground contrast
|
// Automatically adjust foreground contrast
|
||||||
if (isCurrentCell && FilePanelTab.this.active) {
|
if (isCurrentCell && FilePanelTab.this.active) {
|
||||||
|
if (selectionColor != null) {
|
||||||
setForeground(isDark(selectionColor) ? Color.WHITE : Color.BLACK);
|
setForeground(isDark(selectionColor) ? Color.WHITE : Color.BLACK);
|
||||||
|
} else {
|
||||||
|
setForeground(table.getSelectionForeground());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setForeground(isDark(FilePanelTab.this.getBackground()) ? Color.WHITE : Color.BLACK);
|
setForeground(isDark(FilePanelTab.this.getBackground()) ? Color.WHITE : Color.BLACK);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2138,8 +2138,21 @@ public class MainWindow extends JFrame {
|
|||||||
ProcessBuilder pb = null;
|
ProcessBuilder pb = null;
|
||||||
|
|
||||||
if (osName.contains("win")) {
|
if (osName.contains("win")) {
|
||||||
// Windows
|
// Windows - try Windows Terminal first, then PowerShell, then cmd
|
||||||
|
try {
|
||||||
|
// Try to use Windows Terminal if available
|
||||||
|
new ProcessBuilder("wt.exe", "-d", currentDir.getAbsolutePath()).start();
|
||||||
|
return;
|
||||||
|
} catch (Exception e1) {
|
||||||
|
try {
|
||||||
|
// Fallback to PowerShell
|
||||||
|
new ProcessBuilder("powershell.exe").directory(currentDir).start();
|
||||||
|
return;
|
||||||
|
} catch (Exception e2) {
|
||||||
|
// Final fallback to cmd
|
||||||
pb = new ProcessBuilder("cmd.exe", "/c", "start", "cmd.exe");
|
pb = new ProcessBuilder("cmd.exe", "/c", "start", "cmd.exe");
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (osName.contains("mac")) {
|
} else if (osName.contains("mac")) {
|
||||||
// macOS
|
// macOS
|
||||||
pb = new ProcessBuilder("open", "-a", "Terminal", currentDir.getAbsolutePath());
|
pb = new ProcessBuilder("open", "-a", "Terminal", currentDir.getAbsolutePath());
|
||||||
@ -2191,15 +2204,46 @@ public class MainWindow extends JFrame {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String trimmed = command.trim();
|
||||||
// Add to history
|
// Add to history
|
||||||
addCommandToHistory(command.trim());
|
addCommandToHistory(trimmed);
|
||||||
|
|
||||||
|
// Handle internal commands like 'cd'
|
||||||
|
if (trimmed.toLowerCase().startsWith("cd ") || trimmed.toLowerCase().equals("cd..") || trimmed.equals("..")) {
|
||||||
|
String targetPath = null;
|
||||||
|
if (trimmed.equals("..") || trimmed.toLowerCase().equals("cd..")) {
|
||||||
|
targetPath = "..";
|
||||||
|
} else {
|
||||||
|
targetPath = trimmed.substring(3).trim();
|
||||||
|
if (targetPath.startsWith("\"") && targetPath.endsWith("\"")) {
|
||||||
|
targetPath = targetPath.substring(1, targetPath.length() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activePanel != null) {
|
||||||
|
if ("..".equals(targetPath)) {
|
||||||
|
activePanel.navigateUp();
|
||||||
|
} else {
|
||||||
|
File targetDir = new File(activePanel.getCurrentDirectory(), targetPath);
|
||||||
|
if (targetDir.exists() && targetDir.isDirectory()) {
|
||||||
|
activePanel.loadDirectory(targetDir);
|
||||||
|
} else {
|
||||||
|
// try absolute path
|
||||||
|
targetDir = new File(targetPath);
|
||||||
|
if (targetDir.exists() && targetDir.isDirectory()) {
|
||||||
|
activePanel.loadDirectory(targetDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Execute natively for other commands
|
||||||
|
executeNative(trimmed, null);
|
||||||
|
}
|
||||||
|
|
||||||
// Final prompt update after command execution (path might have changed)
|
// Final prompt update after command execution (path might have changed)
|
||||||
updateCommandLinePrompt();
|
updateCommandLinePrompt();
|
||||||
|
|
||||||
// Execute natively, not via bash wrapper
|
|
||||||
executeNative(command.trim(), null);
|
|
||||||
|
|
||||||
// Clear after execution and return focus
|
// Clear after execution and return focus
|
||||||
Component editorComp = commandLine.getEditor().getEditorComponent();
|
Component editorComp = commandLine.getEditor().getEditorComponent();
|
||||||
if (editorComp instanceof JTextField) {
|
if (editorComp instanceof JTextField) {
|
||||||
@ -2224,7 +2268,20 @@ public class MainWindow extends JFrame {
|
|||||||
currentDir = new File(System.getProperty("user.home"));
|
currentDir = new File(System.getProperty("user.home"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String osName = System.getProperty("os.name").toLowerCase();
|
||||||
try {
|
try {
|
||||||
|
String trimmedCmd = command.trim();
|
||||||
|
|
||||||
|
// Special case for Windows terminal commands - launch in a new window
|
||||||
|
if (osName.contains("win")) {
|
||||||
|
String cmdLower = trimmedCmd.toLowerCase();
|
||||||
|
if (cmdLower.equals("cmd") || cmdLower.equals("powershell") ||
|
||||||
|
cmdLower.equals("pwsh") || cmdLower.equals("wt")) {
|
||||||
|
new ProcessBuilder("cmd", "/c", "start", cmdLower).directory(currentDir).start();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if it's a file path that exists (and not a complex command)
|
// Check if it's a file path that exists (and not a complex command)
|
||||||
if (!command.contains(" ") || (command.startsWith("\"") && command.endsWith("\"") && !command.substring(1, command.length()-1).contains("\""))) {
|
if (!command.contains(" ") || (command.startsWith("\"") && command.endsWith("\"") && !command.substring(1, command.length()-1).contains("\""))) {
|
||||||
String path = command.startsWith("\"") ? command.substring(1, command.length()-1) : command;
|
String path = command.startsWith("\"") ? command.substring(1, command.length()-1) : command;
|
||||||
@ -2247,10 +2304,11 @@ public class MainWindow extends JFrame {
|
|||||||
try {
|
try {
|
||||||
new ProcessBuilder(cmdList).directory(currentDir).start();
|
new ProcessBuilder(cmdList).directory(currentDir).start();
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
// Fallback for Linux/macOS: try via shell
|
// Fallback for different OS: try via shell
|
||||||
String osName = System.getProperty("os.name").toLowerCase();
|
|
||||||
if (osName.contains("linux") || osName.contains("mac")) {
|
if (osName.contains("linux") || osName.contains("mac")) {
|
||||||
new ProcessBuilder("sh", "-c", command).directory(currentDir).start();
|
new ProcessBuilder("sh", "-c", command).directory(currentDir).start();
|
||||||
|
} else if (osName.contains("win")) {
|
||||||
|
new ProcessBuilder("cmd", "/c", command).directory(currentDir).start();
|
||||||
} else {
|
} else {
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user