pref: I18n 自动绑定
Some checks failed
Auto Alpha Tag / auto-tag (x64, x64) (push) Has been cancelled
Release / meta (push) Has been cancelled
Release / windows (x64, x64) (push) Has been cancelled
Release / release (push) Has been cancelled

This commit is contained in:
octopus_yan 2024-09-20 22:06:08 +08:00
parent 1b3a4f5569
commit 0660674f7f
17 changed files with 214 additions and 153 deletions

View File

@ -2,19 +2,28 @@ package cn.octopusyan.alistgui.base;
import cn.octopusyan.alistgui.Application;
import cn.octopusyan.alistgui.config.Context;
import cn.octopusyan.alistgui.config.I18n;
import cn.octopusyan.alistgui.util.FxmlUtil;
import cn.octopusyan.alistgui.util.WindowsUtil;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Labeled;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
/**
@ -43,6 +52,29 @@ public abstract class BaseController<VM extends BaseViewModel> implements Initia
}
}
viewModel = vm;
}
/**
* 国际化绑定
*/
private void bindI18n() {
// i18n 绑定
try {
for (Field field : getAllField(this.getClass())) {
I18n i18n = field.getAnnotation(I18n.class);
if (i18n != null && StringUtils.isNoneEmpty(i18n.key())) {
switch (field.get(this)) {
case Labeled labeled -> labeled.textProperty().bind(Context.getLanguageBinding(i18n.key()));
case Tab tab -> tab.textProperty().bind(Context.getLanguageBinding(i18n.key()));
case MenuItem mi -> mi.textProperty().bind(Context.getLanguageBinding(i18n.key()));
default -> {}
}
}
}
} catch (IllegalAccessException e) {
logger.error("获取属性失败", e);
}
}
@FXML
@ -54,6 +86,9 @@ public abstract class BaseController<VM extends BaseViewModel> implements Initia
WindowsUtil.bindDragged(getRootPanel());
}
// 国际化绑定
bindI18n();
// 初始化数据
initData();
@ -109,4 +144,16 @@ public abstract class BaseController<VM extends BaseViewModel> implements Initia
* 视图事件
*/
public abstract void initViewAction();
private static List<Field> getAllField(Class<?> class1) {
List<Field> list = new ArrayList<>();
while (class1 != Object.class) {
list.addAll(Arrays.stream(class1.getDeclaredFields()).toList());
//获取父类
class1 = class1.getSuperclass();
}
return list;
}
}

View File

@ -10,7 +10,6 @@ import cn.octopusyan.alistgui.manager.ConfigManager;
import cn.octopusyan.alistgui.manager.ConsoleLog;
import cn.octopusyan.alistgui.util.FxmlUtil;
import cn.octopusyan.alistgui.util.ProcessesUtil;
import javafx.application.Platform;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
@ -161,14 +160,6 @@ public class Context {
* @return Scene
*/
public static Scene initScene() {
// locale监听; 切换后重新加载界面
currentLocaleProperty().addListener((_, _, locale) -> Platform.runLater(Context::loadScene));
// 加载
loadScene();
return scene;
}
private static void loadScene() {
try {
FXMLLoader loader = FxmlUtil.load("root-view");
//底层面板
@ -185,6 +176,7 @@ public class Context {
} catch (Throwable e) {
log.error("loadScene error", e);
}
return scene;
}
public static int currentViewIndex() {

View File

@ -0,0 +1,15 @@
package cn.octopusyan.alistgui.config;
import java.lang.annotation.*;
/**
* 显示文本绑定
*
* @author octopus_yan
*/
@Documented
@Target({ElementType.FIELD})//用此注解用在属性上
@Retention(RetentionPolicy.RUNTIME)
public @interface I18n {
String key() default "";
}

View File

@ -1,5 +1,6 @@
package cn.octopusyan.alistgui.config;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
@ -26,15 +27,6 @@ public class ObservableResourceBundleFactory {
}
public StringBinding getStringBinding(String key) {
return new StringBinding() {
{
bind(resourceBundleProperty);
}
@Override
protected String computeValue() {
return getResourceBundle().getString(key);
}
};
return Bindings.createStringBinding(() -> getResourceBundle().getString(key), resourceBundleProperty);
}
}

View File

@ -1,10 +1,11 @@
package cn.octopusyan.alistgui.controller;
import cn.octopusyan.alistgui.base.BaseController;
import cn.octopusyan.alistgui.config.I18n;
import cn.octopusyan.alistgui.manager.ConfigManager;
import cn.octopusyan.alistgui.view.alert.AlertUtil;
import cn.octopusyan.alistgui.viewModel.AboutViewModule;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import org.slf4j.Logger;
@ -18,12 +19,22 @@ import org.slf4j.LoggerFactory;
public class AboutController extends BaseController<AboutViewModule> {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@FXML
public VBox aboutView;
@FXML
public Label aListVersion;
@I18n(key = "about.alist.version")
public Label aListVersionLabel;
@I18n(key = "about.app.version")
public Label appVersionLabel;
@I18n(key = "about.app.update")
public Button checkAppVersion;
@I18n(key = "about.alist.update")
public Button checkAListVersion;
@Override
public VBox getRootPanel() {
return aboutView;
@ -44,12 +55,10 @@ public class AboutController extends BaseController<AboutViewModule> {
aListVersion.textProperty().bindBidirectional(viewModel.aListVersionProperty());
}
@FXML
public void checkAListUpdate() {
viewModel.checkUpdate(ConfigManager.aList());
}
@FXML
public void checkGuiUpdate() {
// TODO 检查 gui 版本
AlertUtil.info("待开发。。。").show();

View File

@ -2,13 +2,16 @@ package cn.octopusyan.alistgui.controller;
import cn.octopusyan.alistgui.base.BaseController;
import cn.octopusyan.alistgui.config.Context;
import cn.octopusyan.alistgui.config.I18n;
import cn.octopusyan.alistgui.manager.AListManager;
import cn.octopusyan.alistgui.manager.ConsoleLog;
import cn.octopusyan.alistgui.util.FxmlUtil;
import cn.octopusyan.alistgui.viewModel.MainViewModel;
import javafx.fxml.FXML;
import javafx.application.Platform;
import javafx.beans.binding.StringBinding;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;
@ -25,19 +28,34 @@ import java.io.IOException;
public class MainController extends BaseController<MainViewModel> {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@FXML
public VBox mainView;
@FXML
public VBox logArea;
@FXML
public ScrollPane logAreaSp;
@FXML
@I18n(key = "main.status.label-stop")
public Button statusLabel;
@FXML
@I18n(key = "main.control.start")
public Button startButton;
@FXML
@I18n(key = "main.control.password")
public Button passwordButton;
@I18n(key = "main.control.restart")
public Button restartButton;
@I18n(key = "main.control.more")
public MenuButton moreButton;
@I18n(key = "main.more.browser")
public MenuItem browserButton;
@I18n(key = "main.more.open-config")
public MenuItem configButton;
@I18n(key = "main.more.open-log")
public MenuItem logButton;
private PasswordController controller;
@Override
@ -52,19 +70,18 @@ public class MainController extends BaseController<MainViewModel> {
@Override
public void initViewStyle() {
// 运行状态监听
viewModel.runningProperty().addListener((_, _, running) -> {
resetStatus(running);
browserButton.disableProperty().set(!running);
});
}
@Override
public void initViewAction() {
viewModel.startBtnStyleCssProperty().bindContentBidirectional(startButton.getStyleClass());
viewModel.statusLabelStyleCssProperty().bindContentBidirectional(statusLabel.getStyleClass());
viewModel.startBtnTextProperty().bindBidirectional(startButton.textProperty());
viewModel.statusLabelTextProperty().bindBidirectional(statusLabel.textProperty());
viewModel.browserButtonDisableProperty().bindBidirectional(browserButton.disableProperty());
}
// start button
@FXML
public void start() {
if (AListManager.isRunning()) {
AListManager.stop();
@ -74,7 +91,6 @@ public class MainController extends BaseController<MainViewModel> {
}
// password button
@FXML
public void adminPassword() throws IOException {
if (controller == null) {
FXMLLoader load = FxmlUtil.load("admin-panel");
@ -85,29 +101,43 @@ public class MainController extends BaseController<MainViewModel> {
}
// restart button
@FXML
public void restart() {
AListManager.restart();
}
// more button
@FXML
public void openInBrowser() {
AListManager.openScheme();
}
@FXML
public void openLogFolder() {
AListManager.openLogFolder();
}
@FXML
public void openConfig() {
AListManager.openConfig();
}
private String getText(String key) {
return Context.getLanguageBinding(key).get();
/**
* 根据运行状态改变按钮样式
*
* @param running 运行状态
*/
private void resetStatus(boolean running) {
String removeStyle = running ? "success" : "danger";
String addStyle = running ? "danger" : "success";
StringBinding button = Context.getLanguageBinding(STR."main.control.\{running ? "stop" : "start"}");
StringBinding status = Context.getLanguageBinding(STR."main.status.label-\{running ? "running" : "stop"}");
Platform.runLater(() -> {
startButton.getStyleClass().remove(removeStyle);
startButton.getStyleClass().add(addStyle);
startButton.textProperty().bind(button);
statusLabel.getStyleClass().remove(addStyle);
statusLabel.getStyleClass().add(removeStyle);
statusLabel.textProperty().bind(status);
});
}
}

View File

@ -4,12 +4,14 @@ import atlantafx.base.controls.Popover;
import cn.hutool.core.swing.clipboard.ClipboardUtil;
import cn.octopusyan.alistgui.base.BaseController;
import cn.octopusyan.alistgui.config.Context;
import cn.octopusyan.alistgui.config.I18n;
import cn.octopusyan.alistgui.manager.AListManager;
import cn.octopusyan.alistgui.viewModel.AdminPanelViewModel;
import javafx.beans.value.ChangeListener;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
@ -23,20 +25,20 @@ import org.apache.commons.lang3.StringUtils;
* @author octopus_yan
*/
public class PasswordController extends BaseController<AdminPanelViewModel> {
@FXML
private AnchorPane adminPanel;
public AnchorPane adminPanel;
@FXML
@I18n(key = "admin.pwd.toptip")
public Label toptip;
@I18n(key = "admin.pwd.user-field")
public Label usernameLabel;
public TextField usernameField;
@FXML
public Button copyUsername;
@FXML
@I18n(key = "admin.pwd.pwd-field")
public Label passwordLabel;
public PasswordField passwordField;
@FXML
public Button refreshPassword;
@FXML
public Button savePassword;
@FXML
public Button copyPassword;
private RootController root;

View File

@ -3,6 +3,7 @@ package cn.octopusyan.alistgui.controller;
import atlantafx.base.controls.ModalPane;
import cn.octopusyan.alistgui.base.BaseController;
import cn.octopusyan.alistgui.config.Context;
import cn.octopusyan.alistgui.config.I18n;
import cn.octopusyan.alistgui.manager.ConfigManager;
import cn.octopusyan.alistgui.manager.SystemTrayManager;
import cn.octopusyan.alistgui.util.WindowsUtil;
@ -11,10 +12,10 @@ import com.gluonhq.emoji.EmojiData;
import com.gluonhq.emoji.util.EmojiImageUtils;
import javafx.application.Platform;
import javafx.css.PseudoClass;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
@ -31,27 +32,28 @@ import java.util.Locale;
*/
public class RootController extends BaseController<RootViewModel> {
// 布局
@FXML
private StackPane rootPane;
@FXML
private HBox windowHeader;
@FXML
private FontIcon alwaysOnTopIcon;
@FXML
private FontIcon minimizeIcon;
@FXML
private FontIcon closeIcon;
public StackPane rootPane;
public HBox windowHeader;
public FontIcon alwaysOnTopIcon;
public FontIcon minimizeIcon;
public FontIcon closeIcon;
// 界面
@FXML
private TabPane tabPane;
public TabPane tabPane;
@I18n(key = "root.tab.main")
public Tab mainTab;
@I18n(key = "root.tab.setup")
public Tab setupTab;
@I18n(key = "root.tab.about")
public Tab aboutTab;
// footer
@FXML
@I18n(key = "root.foot.doc")
public Button document;
@FXML
@I18n(key = "root.foot.github")
public Button github;
@FXML
@I18n(key = "root.foot.sponsor")
public Button sponsor;
private final ModalPane modalPane = new ModalPane();
@ -94,6 +96,7 @@ public class RootController extends BaseController<RootViewModel> {
sponsor.setGraphic(juice);
});
// 遮罩
getRootPanel().getChildren().add(modalPane);
modalPane.setId("modalPane");
// reset side and transition to reuse a single modal pane between different examples
@ -131,13 +134,11 @@ public class RootController extends BaseController<RootViewModel> {
viewModel.currentViewIndexProperty().bind(tabPane.getSelectionModel().selectedIndexProperty());
}
@FXML
public void openDocument() {
String locale = Context.getCurrentLocale().equals(Locale.ENGLISH) ? "" : "zh/";
Context.openUrl(STR."https://alist.nn.ci/\{locale}");
}
@FXML
public void openGithub() {
Context.openUrl("https://github.com/alist-org/alist");
}

View File

@ -3,16 +3,14 @@ package cn.octopusyan.alistgui.controller;
import atlantafx.base.theme.Theme;
import cn.octopusyan.alistgui.base.BaseController;
import cn.octopusyan.alistgui.config.Context;
import cn.octopusyan.alistgui.config.I18n;
import cn.octopusyan.alistgui.enums.ProxySetup;
import cn.octopusyan.alistgui.manager.ConfigManager;
import cn.octopusyan.alistgui.viewModel.SetupViewModel;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.control.*;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.util.StringConverter;
@ -32,26 +30,24 @@ public class SetupController extends BaseController<SetupViewModel> implements I
@FXML
public VBox setupView;
@FXML
@I18n(key = "setup.auto-start.label")
public CheckBox autoStartCheckBox;
@FXML
@I18n(key = "setup.silent-startup.label")
public CheckBox silentStartupCheckBox;
@FXML
@I18n(key = "setup.close-to-tray.label")
public CheckBox closeToTrayCheckBox;
@FXML
public ComboBox<Locale> languageComboBox;
@FXML
public ComboBox<Theme> themeComboBox;
@FXML
public ComboBox<ProxySetup> proxySetupComboBox;
@FXML
public Pane proxySetupPane;
@FXML
@I18n(key = "setup.proxy.test")
public Button proxyCheck;
@FXML
public TextField proxyHost;
@FXML
public TextField proxyPort;
@I18n(key = "setup.proxy.host")
public Label hostLabel;
@I18n(key = "setup.proxy.port")
public Label portLabel;
@Override
public VBox getRootPanel() {
@ -103,7 +99,6 @@ public class SetupController extends BaseController<SetupViewModel> implements I
viewModel.proxySetupProperty().bind(proxySetupComboBox.getSelectionModel().selectedItemProperty());
}
@FXML
public void proxyTest() {
viewModel.proxyTest();
}

View File

@ -6,6 +6,7 @@ import cn.octopusyan.alistgui.config.Context;
import cn.octopusyan.alistgui.util.WindowsUtil;
import cn.octopusyan.alistgui.view.PopupMenu;
import javafx.application.Platform;
import javafx.beans.binding.StringBinding;
import javafx.scene.control.MenuItem;
import javafx.stage.Stage;
import lombok.extern.slf4j.Slf4j;
@ -148,14 +149,15 @@ public class SystemTrayManager {
if (popupMenu != null) return;
MenuItem start = PopupMenu.menuItem(
getString(STR."main.control.\{running ? "stop" : "start"}"),
getStringBinding(STR."main.control.\{running ? "stop" : "start"}"),
_ -> AListManager.openScheme()
);
MenuItem browser = PopupMenu.menuItem(getString("main.more.browser"), _ -> AListManager.openScheme());
MenuItem browser = PopupMenu.menuItem(getStringBinding("main.more.browser"), _ -> AListManager.openScheme());
browser.setDisable(!running);
AListManager.runningProperty().addListener((_, _, newValue) -> {
start.setText(getString(STR."main.control.\{newValue ? "stop" : "start"}"));
start.textProperty().unbind();
start.textProperty().bind(getStringBinding(STR."main.control.\{newValue ? "stop" : "start"}"));
browser.disableProperty().set(!newValue);
toolTip(STR."AList \{newValue ? "running" : "stopped"}");
icon(STR."/assets/logo\{newValue ? "" : "-disabled"}.png");
@ -172,16 +174,16 @@ public class SystemTrayManager {
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()))
.addItem(getStringBinding("main.control.restart"), _ -> AListManager.restart())
.addMenu(getStringBinding("main.control.more"), browser,
PopupMenu.menuItem(getStringBinding("main.more.open-config"), _ -> AListManager.openConfig()),
PopupMenu.menuItem(getStringBinding("main.more.open-log"), _ -> AListManager.openLogFolder()))
.addSeparator()
.addExitItem();
}
private static String getString(String key) {
return Context.getLanguageBinding(key).get();
private static StringBinding getStringBinding(String key) {
return Context.getLanguageBinding(key);
}
private static Stage stage() {

View File

@ -4,6 +4,7 @@ import atlantafx.base.controls.CaptionMenuItem;
import cn.octopusyan.alistgui.config.Constants;
import cn.octopusyan.alistgui.util.WindowsUtil;
import javafx.application.Platform;
import javafx.beans.binding.StringBinding;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
@ -47,6 +48,12 @@ public class PopupMenu {
return addItem(new MenuItem(label), handler);
}
public PopupMenu addItem(StringBinding bind, EventHandler<ActionEvent> handler) {
MenuItem menuItem = new MenuItem();
menuItem.textProperty().bind(bind);
return addItem(menuItem, handler);
}
public PopupMenu addItem(MenuItem node, EventHandler<ActionEvent> handler) {
node.setOnAction(handler);
return addItem(node);
@ -68,6 +75,12 @@ public class PopupMenu {
return addMenu(new Menu(label), items);
}
public PopupMenu addMenu(StringBinding label, MenuItem... items) {
Menu menu = new Menu();
menu.textProperty().bind(label);
return addMenu(menu, items);
}
public PopupMenu addMenu(Menu menu, MenuItem... items) {
menu.getItems().addAll(items);
return addItem(menu);
@ -114,4 +127,11 @@ public class PopupMenu {
menuItem.setOnAction(handler);
return menuItem;
}
public static MenuItem menuItem(StringBinding stringBinding, EventHandler<ActionEvent> handler) {
MenuItem menuItem = new MenuItem();
menuItem.textProperty().bind(stringBinding);
menuItem.setOnAction(handler);
return menuItem;
}
}

View File

@ -1,11 +1,9 @@
package cn.octopusyan.alistgui.viewModel;
import cn.octopusyan.alistgui.base.BaseViewModel;
import cn.octopusyan.alistgui.config.Context;
import cn.octopusyan.alistgui.manager.AListManager;
import javafx.application.Platform;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
/**
* 主界面VM
@ -13,56 +11,14 @@ import javafx.collections.FXCollections;
* @author octopus_yan
*/
public class MainViewModel extends BaseViewModel {
private final ListProperty<String> startBtnStyleCss = new SimpleListProperty<>(FXCollections.observableArrayList());
private final StringProperty startBtnText = new SimpleStringProperty();
private final ListProperty<String> statusLabelStyleCss = new SimpleListProperty<>(FXCollections.observableArrayList());
private final StringProperty statusLabelText = new SimpleStringProperty();
private final BooleanProperty browserButtonDisable = new SimpleBooleanProperty();
private final BooleanProperty running = new SimpleBooleanProperty();
public MainViewModel() {
running.addListener((_, _, running) -> {
resetStatus(running);
browserButtonDisable.set(!running);
});
// 先添加监听再绑定解决切换locale后界面状态显示错误的问题
running.bind(AListManager.runningProperty());
}
public ListProperty<String> startBtnStyleCssProperty() {
return startBtnStyleCss;
}
public StringProperty startBtnTextProperty() {
return startBtnText;
}
public ListProperty<String> statusLabelStyleCssProperty() {
return statusLabelStyleCss;
}
public StringProperty statusLabelTextProperty() {
return statusLabelText;
}
public BooleanProperty browserButtonDisableProperty() {
return browserButtonDisable;
}
public void resetStatus(boolean running) {
String removeStyle = running ? "success" : "danger";
String addStyle = running ? "danger" : "success";
String button = Context.getLanguageBinding(STR."main.control.\{running ? "stop" : "start"}").get();
String status = Context.getLanguageBinding(STR."main.status.label-\{running ? "running" : "stop"}").get();
Platform.runLater(() -> {
startBtnStyleCss.remove(removeStyle);
startBtnStyleCss.add(addStyle);
startBtnText.set(button);
statusLabelStyleCss.remove(addStyle);
statusLabelStyleCss.add(removeStyle);
statusLabelText.set(status);
});
public BooleanProperty runningProperty() {
return running;
}
}

View File

@ -22,11 +22,11 @@
</StackPane>
<HBox alignment="CENTER" styleClass="shield">
<Label styleClass="shield-name" text="%about.alist.version"/>
<Label fx:id="aListVersionLabel" styleClass="shield-name" text="%about.alist.version"/>
<Label fx:id="aListVersion" styleClass="shield-version"/>
</HBox>
<HBox alignment="CENTER" styleClass="shield">
<Label styleClass="shield-name" text="%about.app.version"/>
<Label fx:id="appVersionLabel" styleClass="shield-name" text="%about.app.version"/>
<Label styleClass="shield-version" text="v${project.version}"/>
</HBox>
<Button fx:id="checkAppVersion" onAction="#checkGuiUpdate" styleClass="flat" text="%about.app.update"/>

View File

@ -21,13 +21,13 @@
<VBox alignment="CENTER" spacing="20"
AnchorPane.bottomAnchor="30" AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0">
<Label style="-fx-background-radius: 10;-fx-background-color: -color-button-bg-hover;"
<Label fx:id="toptip" style="-fx-background-radius: 10;-fx-background-color: -color-button-bg-hover;"
styleClass="admin-toptip, button, flat, danger" text="%admin.pwd.toptip"/>
<Pane style="-fx-background-color: transparent"/>
<HBox alignment="CENTER" styleClass="admin-field">
<Label text="%admin.pwd.user-field"/>
<Label fx:id="usernameLabel" text="%admin.pwd.user-field"/>
<InputGroup fx:id="userField" styleClass="admin-field-value">
<TextField fx:id="usernameField" text="admin" editable="false"/>
<Button fx:id="copyUsername" onAction="#copyUsername">
@ -39,7 +39,7 @@
</HBox>
<HBox alignment="CENTER" styleClass="admin-field">
<Label text="%admin.pwd.pwd-field"/>
<Label fx:id="passwordLabel" text="%admin.pwd.pwd-field"/>
<InputGroup styleClass="admin-field-value">
<PasswordField fx:id="passwordField" editable="false"/>
<Button fx:id="refreshPassword" onAction="#savePassword" visible="false" managed="false">

View File

@ -34,8 +34,8 @@
<MenuButton fx:id="moreButton" styleClass="button-outlined, no-arrow" text="%main.control.more">
<items>
<MenuItem fx:id="browserButton" onAction="#openInBrowser" disable="true" text="%main.more.browser"/>
<MenuItem onAction="#openConfig" text="%main.more.open-config"/>
<MenuItem onAction="#openLogFolder" text="%main.more.open-log"/>
<MenuItem fx:id="configButton" onAction="#openConfig" text="%main.more.open-config"/>
<MenuItem fx:id="logButton" onAction="#openLogFolder" text="%main.more.open-log"/>
</items>
</MenuButton>
</HBox>

View File

@ -24,14 +24,14 @@
<padding>
<Insets left="20.0" right="20.0"/>
</padding>
<Tab text="%root.tab.main">
<Tab fx:id="mainTab" text="%root.tab.main">
<graphic>
<FontIcon iconColor="white" iconLiteral="fa-th-large"/>
</graphic>
<!-- 引入主页 -->
<fx:include fx:id="mainController" source="main-view.fxml" prefWidth="Infinity" prefHeight="-Infinity"/>
</Tab>
<Tab text="%root.tab.setup">
<Tab fx:id="setupTab" text="%root.tab.setup">
<graphic>
<FontIcon iconColor="white" iconLiteral="fa-cog"/>
</graphic>
@ -39,7 +39,7 @@
<fx:include fx:id="setupController" source="setup-view.fxml" prefWidth="Infinity"
prefHeight="-Infinity"/>
</Tab>
<Tab text="%root.tab.about">
<Tab fx:id="aboutTab" text="%root.tab.about">
<graphic>
<FontIcon iconColor="white" iconLiteral="fa-info-circle"/>
</graphic>

View File

@ -38,9 +38,9 @@
<padding>
<Insets left="30"/>
</padding>
<Label text="%setup.proxy.host"/>
<Label fx:id="hostLabel" text="%setup.proxy.host"/>
<TextField fx:id="proxyHost" promptText="127.0.0.1" GridPane.columnIndex="1"/>
<Label text="%setup.proxy.port" GridPane.rowIndex="1"/>
<Label fx:id="portLabel" text="%setup.proxy.port" GridPane.rowIndex="1"/>
<TextField fx:id="proxyPort" promptText="8080" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
</GridPane>
</VBox>