package com.keenwrite;
import com.keenwrite.cmdline.HeadlessApp;
import com.keenwrite.events.HyperlinkOpenEvent;
import com.keenwrite.preferences.Workspace;
import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventType;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
import org.greenrobot.eventbus.Subscribe;
import java.util.function.BooleanSupplier;
import static com.keenwrite.Bootstrap.APP_TITLE;
import static com.keenwrite.constants.GraphicsConstants.LOGOS;
import static com.keenwrite.events.Bus.register;
import static com.keenwrite.preferences.AppKeys.*;
import static com.keenwrite.util.FontLoader.initFonts;
import static javafx.scene.input.KeyCode.ALT;
import static javafx.scene.input.KeyCode.F11;
import static javafx.scene.input.KeyEvent.KEY_PRESSED;
import static javafx.scene.input.KeyEvent.KEY_RELEASED;
public final class MainApp extends Application {
private Workspace mWorkspace;
private MainScene mMainScene;
public static void main( final String[] args ) {
launch( args );
}
public static Event keyDown( final KeyCode code, final boolean shift ) {
return keyEvent( KEY_PRESSED, code, shift );
}
public static Event keyUp( final KeyCode code, final boolean shift ) {
return keyEvent( KEY_RELEASED, code, shift );
}
public static Event keyUp( final KeyCode code ) {
return keyUp( code, false );
}
private static Event keyEvent(
final EventType<KeyEvent> type, final KeyCode code, final boolean shift ) {
return new KeyEvent(
type, "", "", code, shift, false, false, false
);
}
@Override
public void start( final Stage stage ) {
mWorkspace = new Workspace();
initFonts();
initState( stage );
initStage( stage );
initIcons( stage );
initScene( stage );
stage.show();
register( this );
}
private void initState( final Stage stage ) {
final var enable = createBoundsEnabledSupplier( stage );
stage.setX( mWorkspace.getDouble( KEY_UI_WINDOW_X ) );
stage.setY( mWorkspace.getDouble( KEY_UI_WINDOW_Y ) );
stage.setWidth( mWorkspace.getDouble( KEY_UI_WINDOW_W ) );
stage.setHeight( mWorkspace.getDouble( KEY_UI_WINDOW_H ) );
stage.setMaximized( mWorkspace.getBoolean( KEY_UI_WINDOW_MAX ) );
stage.setFullScreen( mWorkspace.getBoolean( KEY_UI_WINDOW_FULL ) );
mWorkspace.listen( KEY_UI_WINDOW_X, stage.xProperty(), enable );
mWorkspace.listen( KEY_UI_WINDOW_Y, stage.yProperty(), enable );
mWorkspace.listen( KEY_UI_WINDOW_W, stage.widthProperty(), enable );
mWorkspace.listen( KEY_UI_WINDOW_H, stage.heightProperty(), enable );
mWorkspace.listen( KEY_UI_WINDOW_MAX, stage.maximizedProperty() );
mWorkspace.listen( KEY_UI_WINDOW_FULL, stage.fullScreenProperty() );
}
private void initStage( final Stage stage ) {
stage.setTitle( APP_TITLE );
stage.addEventHandler( KEY_PRESSED, event -> {
if( F11.equals( event.getCode() ) ) {
stage.setFullScreen( !stage.isFullScreen() );
}
} );
stage.focusedProperty().addListener( ( c, lost, show ) -> {
for( final var menu : mMainScene.getMenuBar().getMenus() ) {
menu.hide();
}
for( final var mnemonics : stage.getScene().getMnemonics().values() ) {
for( final var mnemonic : mnemonics ) {
mnemonic.getNode().fireEvent( keyUp( ALT ) );
}
}
} );
}
private void initIcons( final Stage stage ) {
stage.getIcons().addAll( LOGOS );
}
private void initScene( final Stage stage ) {
mMainScene = new MainScene( mWorkspace );
stage.setScene( mMainScene.getScene() );
}
@Subscribe
public void handle( final HyperlinkOpenEvent event ) {
getHostServices().showDocument( event.getUri().toString() );
}
private BooleanSupplier createBoundsEnabledSupplier( final Stage stage ) {
return () ->
!(stage.isMaximized() || stage.isFullScreen() || stage.isIconified());
}
}