mirror of
https://github.com/octopusYan/alist-gui.git
synced 2024-11-21 19:56:41 +08:00
feat: 添加系统托盘、静默启动功能
This commit is contained in:
parent
442940cf05
commit
08f0473814
@ -3,6 +3,7 @@ package cn.octopusyan.alistgui;
|
|||||||
import cn.octopusyan.alistgui.config.Constants;
|
import cn.octopusyan.alistgui.config.Constants;
|
||||||
import cn.octopusyan.alistgui.config.Context;
|
import cn.octopusyan.alistgui.config.Context;
|
||||||
import cn.octopusyan.alistgui.manager.ConfigManager;
|
import cn.octopusyan.alistgui.manager.ConfigManager;
|
||||||
|
import cn.octopusyan.alistgui.manager.SystemTrayManager;
|
||||||
import cn.octopusyan.alistgui.manager.http.HttpConfig;
|
import cn.octopusyan.alistgui.manager.http.HttpConfig;
|
||||||
import cn.octopusyan.alistgui.manager.http.HttpUtil;
|
import cn.octopusyan.alistgui.manager.http.HttpUtil;
|
||||||
import cn.octopusyan.alistgui.manager.thread.ThreadPoolManager;
|
import cn.octopusyan.alistgui.manager.thread.ThreadPoolManager;
|
||||||
@ -84,6 +85,13 @@ public class Application extends javafx.application.Application {
|
|||||||
primaryStage.setScene(scene);
|
primaryStage.setScene(scene);
|
||||||
primaryStage.show();
|
primaryStage.show();
|
||||||
|
|
||||||
|
// 静默启动
|
||||||
|
if (ConfigManager.silentStartup()) {
|
||||||
|
Platform.setImplicitExit(false);
|
||||||
|
primaryStage.hide();
|
||||||
|
SystemTrayManager.show();
|
||||||
|
}
|
||||||
|
|
||||||
logger.info("application start over ...");
|
logger.info("application start over ...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,10 +3,13 @@ package cn.octopusyan.alistgui.controller;
|
|||||||
import atlantafx.base.controls.ModalPane;
|
import atlantafx.base.controls.ModalPane;
|
||||||
import cn.octopusyan.alistgui.base.BaseController;
|
import cn.octopusyan.alistgui.base.BaseController;
|
||||||
import cn.octopusyan.alistgui.config.Context;
|
import cn.octopusyan.alistgui.config.Context;
|
||||||
|
import cn.octopusyan.alistgui.manager.ConfigManager;
|
||||||
|
import cn.octopusyan.alistgui.manager.SystemTrayManager;
|
||||||
import cn.octopusyan.alistgui.util.WindowsUtil;
|
import cn.octopusyan.alistgui.util.WindowsUtil;
|
||||||
import cn.octopusyan.alistgui.viewModel.RootViewModel;
|
import cn.octopusyan.alistgui.viewModel.RootViewModel;
|
||||||
import com.gluonhq.emoji.EmojiData;
|
import com.gluonhq.emoji.EmojiData;
|
||||||
import com.gluonhq.emoji.util.EmojiImageUtils;
|
import com.gluonhq.emoji.util.EmojiImageUtils;
|
||||||
|
import javafx.application.Platform;
|
||||||
import javafx.css.PseudoClass;
|
import javafx.css.PseudoClass;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
@ -107,7 +110,15 @@ public class RootController extends BaseController<RootViewModel> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void initViewAction() {
|
public void initViewAction() {
|
||||||
closeIcon.addEventHandler(MouseEvent.MOUSE_CLICKED, _ -> getWindow().close());
|
closeIcon.addEventHandler(MouseEvent.MOUSE_CLICKED, _ -> {
|
||||||
|
if (ConfigManager.closeToTray()) {
|
||||||
|
SystemTrayManager.show();
|
||||||
|
} else {
|
||||||
|
SystemTrayManager.hide();
|
||||||
|
}
|
||||||
|
Platform.setImplicitExit(!ConfigManager.closeToTray());
|
||||||
|
getWindow().close();
|
||||||
|
});
|
||||||
minimizeIcon.addEventHandler(MouseEvent.MOUSE_CLICKED, _ -> getWindow().setIconified(true));
|
minimizeIcon.addEventHandler(MouseEvent.MOUSE_CLICKED, _ -> getWindow().setIconified(true));
|
||||||
alwaysOnTopIcon.addEventHandler(MouseEvent.MOUSE_CLICKED, _ -> {
|
alwaysOnTopIcon.addEventHandler(MouseEvent.MOUSE_CLICKED, _ -> {
|
||||||
boolean newVal = !getWindow().isAlwaysOnTop();
|
boolean newVal = !getWindow().isAlwaysOnTop();
|
||||||
|
@ -37,6 +37,8 @@ public class SetupController extends BaseController<SetupViewModel> implements I
|
|||||||
@FXML
|
@FXML
|
||||||
public CheckBox silentStartupCheckBox;
|
public CheckBox silentStartupCheckBox;
|
||||||
@FXML
|
@FXML
|
||||||
|
public CheckBox closeToTrayCheckBox;
|
||||||
|
@FXML
|
||||||
public ComboBox<Locale> languageComboBox;
|
public ComboBox<Locale> languageComboBox;
|
||||||
@FXML
|
@FXML
|
||||||
public ComboBox<Theme> themeComboBox;
|
public ComboBox<Theme> themeComboBox;
|
||||||
@ -92,6 +94,7 @@ public class SetupController extends BaseController<SetupViewModel> implements I
|
|||||||
//
|
//
|
||||||
autoStartCheckBox.selectedProperty().bindBidirectional(viewModel.autoStartProperty());
|
autoStartCheckBox.selectedProperty().bindBidirectional(viewModel.autoStartProperty());
|
||||||
silentStartupCheckBox.selectedProperty().bindBidirectional(viewModel.silentStartupProperty());
|
silentStartupCheckBox.selectedProperty().bindBidirectional(viewModel.silentStartupProperty());
|
||||||
|
closeToTrayCheckBox.selectedProperty().bindBidirectional(viewModel.closeToTrayProperty());
|
||||||
proxyHost.textProperty().bindBidirectional(viewModel.proxyHostProperty());
|
proxyHost.textProperty().bindBidirectional(viewModel.proxyHostProperty());
|
||||||
proxyPort.textProperty().bindBidirectional(viewModel.proxyPortProperty());
|
proxyPort.textProperty().bindBidirectional(viewModel.proxyPortProperty());
|
||||||
|
|
||||||
|
@ -237,6 +237,16 @@ public class ConfigManager {
|
|||||||
guiConfig.setSilentStartup(startup);
|
guiConfig.setSilentStartup(startup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------{ 最小化到托盘 }------------------------------------------
|
||||||
|
|
||||||
|
public static boolean closeToTray() {
|
||||||
|
return guiConfig.getCloseToTray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void closeToTray(boolean check) {
|
||||||
|
guiConfig.setCloseToTray(check);
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------{ 版本检查 }------------------------------------------
|
// --------------------------------{ 版本检查 }------------------------------------------
|
||||||
|
|
||||||
public static UpgradeConfig upgradeConfig() {
|
public static UpgradeConfig upgradeConfig() {
|
||||||
|
@ -0,0 +1,186 @@
|
|||||||
|
package cn.octopusyan.alistgui.manager;
|
||||||
|
|
||||||
|
import cn.octopusyan.alistgui.Application;
|
||||||
|
import cn.octopusyan.alistgui.config.Constants;
|
||||||
|
import cn.octopusyan.alistgui.config.Context;
|
||||||
|
import cn.octopusyan.alistgui.util.WindowsUtil;
|
||||||
|
import cn.octopusyan.alistgui.view.PopupMenu;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.control.MenuItem;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统托盘管理
|
||||||
|
*
|
||||||
|
* @author octopus_yan
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class SystemTrayManager {
|
||||||
|
// 托盘工具
|
||||||
|
private static final SystemTray systemTray;
|
||||||
|
private static TrayIcon trayIcon;
|
||||||
|
private static PopupMenu popupMenu;
|
||||||
|
|
||||||
|
static {
|
||||||
|
//检查系统是否支持托盘
|
||||||
|
if (!SystemTray.isSupported()) {
|
||||||
|
//系统托盘不支持
|
||||||
|
log.info("{}:系统托盘不支持", Thread.currentThread().getStackTrace()[1].getClassName());
|
||||||
|
systemTray = null;
|
||||||
|
} else {
|
||||||
|
systemTray = SystemTray.getSystemTray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void toolTip(String toptip) {
|
||||||
|
if (trayIcon == null) return;
|
||||||
|
|
||||||
|
trayIcon.setToolTip(toptip);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void icon(String path) {
|
||||||
|
if (trayIcon == null) return;
|
||||||
|
icon(WindowsUtil.class.getResource(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void icon(URL url) {
|
||||||
|
if (trayIcon == null) return;
|
||||||
|
icon(Toolkit.getDefaultToolkit().getImage(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void icon(Image image) {
|
||||||
|
if (trayIcon == null) return;
|
||||||
|
trayIcon.setImage(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isShowing() {
|
||||||
|
if (systemTray == null) return false;
|
||||||
|
|
||||||
|
return List.of(systemTray.getTrayIcons()).contains(trayIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void show() {
|
||||||
|
|
||||||
|
// 是否启用托盘
|
||||||
|
if (!ConfigManager.closeToTray() || systemTray == null) {
|
||||||
|
if (trayIcon != null && isShowing()) {
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
initTrayIcon();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!isShowing())
|
||||||
|
systemTray.add(trayIcon);
|
||||||
|
} catch (AWTException e) {
|
||||||
|
//系统托盘添加失败
|
||||||
|
log.error("{}:系统添加失败", Thread.currentThread().getStackTrace()[1].getClassName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void hide() {
|
||||||
|
if (systemTray == null) return;
|
||||||
|
|
||||||
|
systemTray.remove(trayIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
//========================================={ private }===========================================
|
||||||
|
|
||||||
|
private static void initTrayIcon() {
|
||||||
|
if (trayIcon != null) return;
|
||||||
|
|
||||||
|
// 系统托盘图标
|
||||||
|
Image image = Toolkit.getDefaultToolkit().getImage(WindowsUtil.class.getResource("/assets/logo-disabled.png"));
|
||||||
|
trayIcon = new TrayIcon(image);
|
||||||
|
|
||||||
|
// 设置图标尺寸自动适应
|
||||||
|
trayIcon.setImageAutoSize(true);
|
||||||
|
|
||||||
|
// 弹出式菜单组件
|
||||||
|
// trayIcon.setPopupMenu(getMenu());
|
||||||
|
|
||||||
|
// 鼠标移到系统托盘,会显示提示文本
|
||||||
|
toolTip(Constants.APP_TITLE);
|
||||||
|
|
||||||
|
// 鼠标监听
|
||||||
|
trayIcon.addMouseListener(new MouseAdapter() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseReleased(MouseEvent event) {
|
||||||
|
maybeShowPopup(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mousePressed(MouseEvent event) {
|
||||||
|
maybeShowPopup(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void maybeShowPopup(MouseEvent event) {
|
||||||
|
// popup menu trigger event
|
||||||
|
if (event.isPopupTrigger()) {
|
||||||
|
// 弹出菜单
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
initPopupMenu();
|
||||||
|
popupMenu.show(event);
|
||||||
|
});
|
||||||
|
} else if (event.getButton() == MouseEvent.BUTTON1) {
|
||||||
|
// 显示 PrimaryStage
|
||||||
|
Platform.runLater(() -> Application.getPrimaryStage().show());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建托盘菜单
|
||||||
|
*/
|
||||||
|
private static void initPopupMenu() {
|
||||||
|
if (popupMenu != null) return;
|
||||||
|
|
||||||
|
MenuItem start = PopupMenu.menuItem(getString("main.control.start"), _ -> AListManager.openScheme());
|
||||||
|
MenuItem browser = PopupMenu.menuItem(getString("main.more.browser"), _ -> AListManager.openScheme());
|
||||||
|
browser.setDisable(true);
|
||||||
|
|
||||||
|
AListManager.runningProperty().addListener((_, _, newValue) -> {
|
||||||
|
start.setText(getString(STR."main.control.\{newValue ? "stop" : "start"}"));
|
||||||
|
browser.disableProperty().set(!newValue);
|
||||||
|
toolTip(STR."AList \{newValue ? "running" : "stopped"}");
|
||||||
|
icon(STR."/assets/logo\{newValue ? "" : "-disabled"}.png");
|
||||||
|
});
|
||||||
|
|
||||||
|
popupMenu = new PopupMenu()
|
||||||
|
.addItem(new MenuItem(Constants.APP_TITLE), _ -> stage().show())
|
||||||
|
.addSeparator()
|
||||||
|
.addCaptionItem("AList")
|
||||||
|
.addItem(start, _ -> {
|
||||||
|
if (AListManager.isRunning()) {
|
||||||
|
AListManager.stop();
|
||||||
|
} else {
|
||||||
|
AListManager.start();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.addItem(getString("main.control.restart"), _ -> AListManager.restart())
|
||||||
|
.addMenu(getString("main.control.more"), browser,
|
||||||
|
PopupMenu.menuItem(getString("main.more.open-config"), _ -> AListManager.openConfig()),
|
||||||
|
PopupMenu.menuItem(getString("main.more.open-log"), _ -> AListManager.openLogFolder()))
|
||||||
|
.addSeparator()
|
||||||
|
.addExitItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getString(String key) {
|
||||||
|
return Context.getLanguageBinding(key).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stage stage() {
|
||||||
|
return WindowsUtil.getStage();
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,7 @@ public class GuiConfig {
|
|||||||
|
|
||||||
private Boolean autoStart = false;
|
private Boolean autoStart = false;
|
||||||
private Boolean silentStartup = false;
|
private Boolean silentStartup = false;
|
||||||
|
private Boolean closeToTray = true;
|
||||||
@JsonProperty("proxy")
|
@JsonProperty("proxy")
|
||||||
private ProxyInfo proxyInfo;
|
private ProxyInfo proxyInfo;
|
||||||
@JsonProperty("proxy.testUrl")
|
@JsonProperty("proxy.testUrl")
|
||||||
|
@ -2,17 +2,25 @@ package cn.octopusyan.alistgui.util;
|
|||||||
|
|
||||||
import cn.octopusyan.alistgui.Application;
|
import cn.octopusyan.alistgui.Application;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
|
import javafx.stage.Screen;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 工具
|
||||||
|
*
|
||||||
* @author octopus_yan
|
* @author octopus_yan
|
||||||
*/
|
*/
|
||||||
public class WindowsUtil {
|
public class WindowsUtil {
|
||||||
public static final Map<Pane, Double> paneXOffset = new HashMap<>();
|
// 获取系统缩放比
|
||||||
public static final Map<Pane, Double> paneYOffset = new HashMap<>();
|
public static final double scaleX = Screen.getPrimary().getOutputScaleX();
|
||||||
|
public static final double scaleY = Screen.getPrimary().getOutputScaleY();
|
||||||
|
|
||||||
|
|
||||||
|
private static final Map<Pane, Double> paneXOffset = new HashMap<>();
|
||||||
|
private static final Map<Pane, Double> paneYOffset = new HashMap<>();
|
||||||
|
|
||||||
public static void bindShadow(Pane pane) {
|
public static void bindShadow(Pane pane) {
|
||||||
pane.setStyle("""
|
pane.setStyle("""
|
||||||
@ -29,6 +37,13 @@ public class WindowsUtil {
|
|||||||
bindDragged(pane, stage);
|
bindDragged(pane, stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void unbindDragged(Pane pane) {
|
||||||
|
pane.setOnMousePressed(null);
|
||||||
|
pane.setOnMouseDragged(null);
|
||||||
|
paneXOffset.remove(pane);
|
||||||
|
paneYOffset.remove(pane);
|
||||||
|
}
|
||||||
|
|
||||||
public static void bindDragged(Pane pane, Stage stage) {
|
public static void bindDragged(Pane pane, Stage stage) {
|
||||||
pane.setOnMousePressed(event -> {
|
pane.setOnMousePressed(event -> {
|
||||||
paneXOffset.put(pane, stage.getX() - event.getScreenX());
|
paneXOffset.put(pane, stage.getX() - event.getScreenX());
|
||||||
@ -40,11 +55,15 @@ public class WindowsUtil {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Stage getStage() {
|
||||||
|
return Application.getPrimaryStage();
|
||||||
|
}
|
||||||
|
|
||||||
public static Stage getStage(Pane pane) {
|
public static Stage getStage(Pane pane) {
|
||||||
try {
|
try {
|
||||||
return (Stage) pane.getScene().getWindow();
|
return (Stage) pane.getScene().getWindow();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
return Application.getPrimaryStage();
|
return getStage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
117
src/main/java/cn/octopusyan/alistgui/view/PopupMenu.java
Normal file
117
src/main/java/cn/octopusyan/alistgui/view/PopupMenu.java
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
package cn.octopusyan.alistgui.view;
|
||||||
|
|
||||||
|
import atlantafx.base.controls.CaptionMenuItem;
|
||||||
|
import cn.octopusyan.alistgui.config.Constants;
|
||||||
|
import cn.octopusyan.alistgui.util.WindowsUtil;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.control.ContextMenu;
|
||||||
|
import javafx.scene.control.Menu;
|
||||||
|
import javafx.scene.control.MenuItem;
|
||||||
|
import javafx.scene.control.SeparatorMenuItem;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
import javafx.stage.StageStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 托盘图标 菜单
|
||||||
|
*
|
||||||
|
* @author octopus_yan
|
||||||
|
*/
|
||||||
|
public class PopupMenu {
|
||||||
|
// 用来隐藏弹出窗口的任务栏图标
|
||||||
|
private static final Stage utilityStage = new Stage();
|
||||||
|
// 菜单栏
|
||||||
|
private final ContextMenu root = new ContextMenu();
|
||||||
|
|
||||||
|
static {
|
||||||
|
utilityStage.initStyle(StageStyle.UTILITY);
|
||||||
|
utilityStage.setScene(new Scene(new Region()));
|
||||||
|
utilityStage.setOpacity(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PopupMenu() {
|
||||||
|
|
||||||
|
root.focusedProperty().addListener((_, _, focused) -> {
|
||||||
|
if (!focused)
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
root.hide();
|
||||||
|
utilityStage.hide();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public PopupMenu addItem(String label, EventHandler<ActionEvent> handler) {
|
||||||
|
return addItem(new MenuItem(label), handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PopupMenu addItem(MenuItem node, EventHandler<ActionEvent> handler) {
|
||||||
|
node.setOnAction(handler);
|
||||||
|
return addItem(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PopupMenu addSeparator() {
|
||||||
|
return addItem(new SeparatorMenuItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PopupMenu addCaptionItem() {
|
||||||
|
return addCaptionItem(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PopupMenu addCaptionItem(String title) {
|
||||||
|
return addItem(new CaptionMenuItem(title));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PopupMenu addMenu(String label, MenuItem... items) {
|
||||||
|
return addMenu(new Menu(label), items);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PopupMenu addMenu(Menu menu, MenuItem... items) {
|
||||||
|
menu.getItems().addAll(items);
|
||||||
|
return addItem(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PopupMenu addTitleItem() {
|
||||||
|
return addTitleItem(Constants.APP_TITLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PopupMenu addTitleItem(String label) {
|
||||||
|
return addExitItem(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PopupMenu addExitItem() {
|
||||||
|
return addExitItem("Exit");
|
||||||
|
}
|
||||||
|
|
||||||
|
public PopupMenu addExitItem(String label) {
|
||||||
|
return addItem(label, _ -> Platform.exit());
|
||||||
|
}
|
||||||
|
|
||||||
|
private PopupMenu addItem(MenuItem node) {
|
||||||
|
root.getItems().add(node);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show(java.awt.event.MouseEvent event) {
|
||||||
|
// 必须调用show才会隐藏任务栏图标
|
||||||
|
utilityStage.show();
|
||||||
|
|
||||||
|
if (root.isShowing())
|
||||||
|
root.hide();
|
||||||
|
|
||||||
|
root.show(utilityStage,
|
||||||
|
event.getX() / WindowsUtil.scaleX,
|
||||||
|
event.getY() / WindowsUtil.scaleY
|
||||||
|
);
|
||||||
|
// 获取焦点 (失去焦点隐藏自身)
|
||||||
|
root.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MenuItem menuItem(String label, EventHandler<ActionEvent> handler) {
|
||||||
|
MenuItem menuItem = new MenuItem(label);
|
||||||
|
menuItem.setOnAction(handler);
|
||||||
|
return menuItem;
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,7 @@ import java.util.Locale;
|
|||||||
public class SetupViewModel extends BaseViewModel {
|
public class SetupViewModel extends BaseViewModel {
|
||||||
private final BooleanProperty autoStart = new SimpleBooleanProperty(ConfigManager.autoStart());
|
private final BooleanProperty autoStart = new SimpleBooleanProperty(ConfigManager.autoStart());
|
||||||
private final BooleanProperty silentStartup = new SimpleBooleanProperty(ConfigManager.silentStartup());
|
private final BooleanProperty silentStartup = new SimpleBooleanProperty(ConfigManager.silentStartup());
|
||||||
|
private final BooleanProperty closeToTray = new SimpleBooleanProperty(ConfigManager.closeToTray());
|
||||||
private final ObjectProperty<Theme> theme = new SimpleObjectProperty<>(ConfigManager.theme());
|
private final ObjectProperty<Theme> theme = new SimpleObjectProperty<>(ConfigManager.theme());
|
||||||
private final StringProperty proxyHost = new SimpleStringProperty(ConfigManager.proxyHost());
|
private final StringProperty proxyHost = new SimpleStringProperty(ConfigManager.proxyHost());
|
||||||
private final StringProperty proxyPort = new SimpleStringProperty(ConfigManager.proxyPort());
|
private final StringProperty proxyPort = new SimpleStringProperty(ConfigManager.proxyPort());
|
||||||
@ -50,6 +51,18 @@ public class SetupViewModel extends BaseViewModel {
|
|||||||
}
|
}
|
||||||
ConfigManager.autoStart(newValue);
|
ConfigManager.autoStart(newValue);
|
||||||
});
|
});
|
||||||
|
silentStartup.addListener((_, _, newValue) -> {
|
||||||
|
// 开启时检查托盘选项
|
||||||
|
if (newValue && !closeToTray.get()) closeToTray.set(true);
|
||||||
|
|
||||||
|
ConfigManager.silentStartup(newValue);
|
||||||
|
});
|
||||||
|
closeToTray.addListener((_, _, newValue) -> {
|
||||||
|
// 开启时检查托盘选项
|
||||||
|
if (!newValue && silentStartup.get()) silentStartup.set(false);
|
||||||
|
|
||||||
|
ConfigManager.closeToTray(newValue);
|
||||||
|
});
|
||||||
proxySetup.addListener((_, _, newValue) -> ConfigManager.proxySetup(newValue));
|
proxySetup.addListener((_, _, newValue) -> ConfigManager.proxySetup(newValue));
|
||||||
proxyTestUrl.addListener((_, _, newValue) -> ConfigManager.proxyTestUrl(newValue));
|
proxyTestUrl.addListener((_, _, newValue) -> ConfigManager.proxyTestUrl(newValue));
|
||||||
proxyHost.addListener((_, _, newValue) -> ConfigManager.proxyHost(newValue));
|
proxyHost.addListener((_, _, newValue) -> ConfigManager.proxyHost(newValue));
|
||||||
@ -69,6 +82,10 @@ public class SetupViewModel extends BaseViewModel {
|
|||||||
return silentStartup;
|
return silentStartup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BooleanProperty closeToTrayProperty() {
|
||||||
|
return closeToTray;
|
||||||
|
}
|
||||||
|
|
||||||
public ObjectProperty<Locale> languageProperty() {
|
public ObjectProperty<Locale> languageProperty() {
|
||||||
return language;
|
return language;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
module cn.octopusyan.alistgui {
|
module cn.octopusyan.alistgui {
|
||||||
|
requires java.desktop;
|
||||||
requires java.net.http;
|
requires java.net.http;
|
||||||
requires javafx.controls;
|
requires javafx.controls;
|
||||||
requires javafx.fxml;
|
requires javafx.fxml;
|
||||||
|
Before Width: | Height: | Size: 960 B After Width: | Height: | Size: 960 B |
@ -12,6 +12,7 @@
|
|||||||
</padding>
|
</padding>
|
||||||
<CheckBox fx:id="autoStartCheckBox" text="%setup.auto-start.label"/>
|
<CheckBox fx:id="autoStartCheckBox" text="%setup.auto-start.label"/>
|
||||||
<CheckBox fx:id="silentStartupCheckBox" text="%setup.silent-startup.label"/>
|
<CheckBox fx:id="silentStartupCheckBox" text="%setup.silent-startup.label"/>
|
||||||
|
<CheckBox fx:id="closeToTrayCheckBox" text="%setup.close-to-tray.label"/>
|
||||||
<HBox alignment="CENTER_LEFT" spacing="10">
|
<HBox alignment="CENTER_LEFT" spacing="10">
|
||||||
<Label text="%setup.theme"/>
|
<Label text="%setup.theme"/>
|
||||||
<ComboBox fx:id="themeComboBox"/>
|
<ComboBox fx:id="themeComboBox"/>
|
||||||
|
@ -48,6 +48,7 @@ admin.pwd.title=\u7BA1\u7406\u5458\u5BC6\u7801
|
|||||||
admin.pwd.toptip=\u65B0\u5BC6\u7801\u53EA\u4F1A\u663E\u793A\u4E00\u6B21
|
admin.pwd.toptip=\u65B0\u5BC6\u7801\u53EA\u4F1A\u663E\u793A\u4E00\u6B21
|
||||||
admin.pwd.user-field=\u7528\u6237\uFF1A
|
admin.pwd.user-field=\u7528\u6237\uFF1A
|
||||||
admin.pwd.pwd-field=\u5BC6\u7801\uFF1A
|
admin.pwd.pwd-field=\u5BC6\u7801\uFF1A
|
||||||
|
setup.close-to-tray.label=\u5173\u95ED\u65F6\u6700\u5C0F\u5316\u5230\u6258\u76D8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,5 +48,6 @@ admin.pwd.title=Admin Password
|
|||||||
admin.pwd.toptip=The new password will only be displayed once
|
admin.pwd.toptip=The new password will only be displayed once
|
||||||
admin.pwd.user-field=User:
|
admin.pwd.user-field=User:
|
||||||
admin.pwd.pwd-field=Password :
|
admin.pwd.pwd-field=Password :
|
||||||
|
setup.close-to-tray.label=Minimize to tray when closed
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,5 +48,6 @@ admin.pwd.title=\u7BA1\u7406\u5458\u5BC6\u7801
|
|||||||
admin.pwd.toptip=\u65B0\u5BC6\u7801\u53EA\u4F1A\u663E\u793A\u4E00\u6B21
|
admin.pwd.toptip=\u65B0\u5BC6\u7801\u53EA\u4F1A\u663E\u793A\u4E00\u6B21
|
||||||
admin.pwd.user-field=\u7528\u6237\uFF1A
|
admin.pwd.user-field=\u7528\u6237\uFF1A
|
||||||
admin.pwd.pwd-field=\u5BC6\u7801\uFF1A
|
admin.pwd.pwd-field=\u5BC6\u7801\uFF1A
|
||||||
|
setup.close-to-tray.label=\u5173\u95ED\u65F6\u6700\u5C0F\u5316\u5230\u6258\u76D8
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user