diff --git a/src/main/java/com/cecilia/AppStart.java b/src/main/java/com/cecilia/AppStart.java new file mode 100644 index 0000000..4713dc8 --- /dev/null +++ b/src/main/java/com/cecilia/AppStart.java @@ -0,0 +1,7 @@ +package com.cecilia; + +public class AppStart { + public static void main(String[] args) { + AppUI.main(args); + } +} diff --git a/src/main/java/com/cecilia/AppUI.java b/src/main/java/com/cecilia/AppUI.java index e45ca2e..5660626 100644 --- a/src/main/java/com/cecilia/AppUI.java +++ b/src/main/java/com/cecilia/AppUI.java @@ -1,5 +1,9 @@ package com.cecilia; +import com.cecilia.event.BrowseEvent; +import com.cecilia.event.DefaultEventBus; +import com.cecilia.event.HotkeyEvent; +import com.cecilia.event.Listener; import com.goxr3plus.fxborderlessscene.borderless.BorderlessPane; import com.goxr3plus.fxborderlessscene.borderless.BorderlessScene; import com.cecilia.theme.ThemeManager; @@ -11,10 +15,17 @@ import fr.brouillard.oss.cssfx.CSSFX; import fr.brouillard.oss.cssfx.api.URIToPathConverter; import fr.brouillard.oss.cssfx.impl.log.CSSFXLogger; import javafx.application.Application; +import javafx.application.ConditionalFeature; +import javafx.application.Platform; import javafx.css.PseudoClass; import javafx.geometry.Insets; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.SceneAntialiasing; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyCodeCombination; +import javafx.scene.input.KeyCombination; +import javafx.scene.input.KeyEvent; import javafx.scene.paint.Color; import javafx.stage.Stage; import javafx.stage.StageStyle; @@ -23,6 +34,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.URI; import java.nio.file.Paths; +import java.util.List; import java.util.Properties; import static java.nio.charset.StandardCharsets.UTF_8; @@ -36,66 +48,80 @@ public class AppUI extends Application { Resources.getPropertyOrEnv("app.profiles.active", "app.profiles.active") ); + public static final List SUPPORTED_HOTKEYS = List.of( + new KeyCodeCombination(KeyCode.SLASH), + new KeyCodeCombination(KeyCode.T, KeyCombination.CONTROL_DOWN), + new KeyCodeCombination(KeyCode.W, KeyCombination.CONTROL_DOWN) + ); + + public static void main(String[] args) { + launch(args); + } @Override - public void start(Stage primaryStage) throws IOException { - Thread.currentThread().setUncaughtExceptionHandler(new DefaultExceptionHandler(primaryStage)); - - if ("DEV".equalsIgnoreCase(System.getProperty("app.profiles.active"))) { - System.out.println("-------[WARNING] Application is running in development mode."); - } + public void start(Stage stage) throws IOException { + Thread.currentThread().setUncaughtExceptionHandler(new DefaultExceptionHandler(stage)); loadApplicationProperties(); -// Application.setUserAgentStylesheet(new NordDark().getUserAgentStylesheet()); + if (IS_DEV_MODE) { + System.out.println("[WARNING] Application is running in development mode."); + } + var antialiasing = Platform.isSupported(ConditionalFeature.SCENE3D) + ? SceneAntialiasing.BALANCED + : SceneAntialiasing.DISABLED; ViewTuple viewTuple = FluentViewLoader.fxmlView(WindowView.class).load(); Parent mainView = viewTuple.getView(); - - - BorderlessScene scene = new BorderlessScene(primaryStage, StageStyle.TRANSPARENT, mainView, 250, 250); + BorderlessScene scene = new BorderlessScene(stage, StageStyle.TRANSPARENT, mainView, 950, 650); BorderlessPane rootPane = (BorderlessPane) scene.getRoot(); rootPane.setPadding(new Insets(15, 15, 15, 15)); + scene.setOnKeyPressed(this::dispatchHotkeys); + scene.removeDefaultCSS(); + scene.setMoveControl(mainView); + scene.setFill(Color.TRANSPARENT); + var tm = ThemeManager.getInstance(); tm.setScene(scene); tm.setTheme(tm.getDefaultTheme()); - if ("DEV".equalsIgnoreCase(System.getProperty("app.profiles.active"))) { + if (IS_DEV_MODE) { startCssFX(scene); } - scene.removeDefaultCSS(); - scene.setMoveControl(mainView); - scene.setFill(Color.TRANSPARENT); -// viewTuple.getViewModel().setTitle(System.getProperty("app.name")); - primaryStage.setTitle(System.getProperty("app.name")); - scene.getStylesheets().addAll(AppUI.class.getResource("/styles/index.css").toExternalForm()); - scene.maximizedProperty().addListener((observableValue, oldVal, newVal) -> { if (newVal) { rootPane.setPadding(new Insets(0, 0, 0, 0)); } else { rootPane.setPadding(new Insets(15, 15, 15, 15)); } -// viewTuple.getViewModel().setMaximized(newVal); }); + scene.getStylesheets().addAll(Resources.resolve("assets/styles/index.css")); PseudoClass CUSTOM_THEME = PseudoClass.getPseudoClass("custom-theme"); scene.getRoot().pseudoClassStateChanged(CUSTOM_THEME, true); //Show - primaryStage.setScene(scene); - primaryStage.setWidth(900); - primaryStage.setHeight(600); + stage.setScene(scene); + stage.setTitle(System.getProperty("app.name")); + loadIcons(stage); + stage.setResizable(true); + stage.setOnCloseRequest(t -> Platform.exit()); -// primaryStage.titleProperty().bind(viewTuple.getViewModel().titleProperty()); - primaryStage.show(); + // register event listeners + DefaultEventBus.getInstance().subscribe(BrowseEvent.class, this::onBrowseEvent); + + Platform.runLater(() -> { + stage.show(); + stage.requestFocus(); + }); } private void loadApplicationProperties() { - try { - var properties = new Properties(); - properties.load(new InputStreamReader(Resources.getResourceAsStream("application.properties"), UTF_8)); + Properties properties = new Properties(); + try (InputStreamReader in = new InputStreamReader(Resources.getResourceAsStream("/application.properties"), + UTF_8)) { + properties.load(in); properties.forEach((key, value) -> System.setProperty( String.valueOf(key), String.valueOf(value) @@ -118,16 +144,39 @@ public class AppUI extends Application { }; CSSFX.addConverter(fileUrlConverter).start(); - CSSFXLogger.setLoggerFactory(loggerName -> (level, message, args) -> - System.out.println("[CSSFX] " + String.format(message, args)) - ); + CSSFXLogger.setLoggerFactory(loggerName -> (level, message, args) -> { + if (level.ordinal() <= CSSFXLogger.LogLevel.INFO.ordinal()) { + System.out.println("[" + level + "] CSSFX: " + String.format(message, args)); + } + }); CSSFX.start(scene); } + private void dispatchHotkeys(KeyEvent event) { + for (KeyCodeCombination k : SUPPORTED_HOTKEYS) { + if (k.match(event)) { + DefaultEventBus.getInstance().publish(new HotkeyEvent(k)); + return; + } + } + } + private void loadIcons(Stage stage) { + int iconSize = 16; + while (iconSize <= 1024) { + iconSize *= 2; + } + } + @Override + public void init() throws Exception { + super.init(); + } + @Override + public void stop() throws Exception { + super.stop(); - public static void main(String[] args) { - - - launch(args); + } + @Listener + private void onBrowseEvent(BrowseEvent event) { + getHostServices().showDocument(event.getUri().toString()); }