2
0

JDK9 platform-independent way of managing application events.

This commit is contained in:
Maarten Billemont 2018-07-29 00:08:09 -04:00
parent 37a7cfa530
commit 8377c9c615
6 changed files with 144 additions and 48 deletions

View File

@ -5,7 +5,7 @@ plugins {
} }
description = 'Master Password GUI' description = 'Master Password GUI'
mainClassName = 'com.lyndir.masterpassword.gui.GUI' mainClassName = 'com.lyndir.masterpassword.gui.Main'
dependencies { dependencies {
implementation group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.7-p2' implementation group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.7-p2'

View File

@ -23,14 +23,10 @@ import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.google.common.io.ByteSource; import com.google.common.io.ByteSource;
import com.lyndir.lhunath.opal.system.logging.Logger; import com.lyndir.lhunath.opal.system.logging.Logger;
import com.lyndir.lhunath.opal.system.util.TypeUtils; import com.lyndir.masterpassword.gui.platform.BaseGUI;
import com.lyndir.masterpassword.gui.util.Res;
import com.lyndir.masterpassword.gui.view.MasterPasswordFrame;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.*; import java.net.*;
import java.util.Optional;
import javax.swing.*; import javax.swing.*;
@ -39,20 +35,15 @@ import javax.swing.*;
* *
* @author mbillemo * @author mbillemo
*/ */
public class GUI { public final class Main {
@SuppressWarnings("UnusedDeclaration") @SuppressWarnings("UnusedDeclaration")
private static final Logger logger = Logger.get( GUI.class ); private static final Logger logger = Logger.get( Main.class );
private final MasterPasswordFrame frame = new MasterPasswordFrame();
public static void main(final String... args) { public static void main(final String... args) {
// Thread.setDefaultUncaughtExceptionHandler( // Thread.setDefaultUncaughtExceptionHandler(
// (t, e) -> logger.bug( e, "Uncaught: %s", e.getLocalizedMessage() ) ); // (t, e) -> logger.bug( e, "Uncaught: %s", e.getLocalizedMessage() ) );
if (Config.get().checkForUpdates())
checkUpdate();
// Try and set the system look & feel, if available. // Try and set the system look & feel, if available.
try { try {
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() ); UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
@ -60,29 +51,17 @@ public class GUI {
catch (final UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException ignored) { catch (final UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException ignored) {
} }
create().open(); // Check online to see if this version has been superseded.
} if (Config.get().checkForUpdates())
checkUpdate();
private static GUI create() { // Create a platform-specific GUI and open it.
try { BaseGUI.createPlatformGUI().open();
// AppleGUI adds support for macOS features.
Optional<Class<GUI>> appleGUI = TypeUtils.loadClass( "com.lyndir.masterpassword.gui.platform.mac.AppleGUI" );
if (appleGUI.isPresent())
return appleGUI.get().getConstructor().newInstance();
}
catch (@SuppressWarnings("ErrorNotRethrown") final LinkageError ignored) {
}
catch (final IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
throw logger.bug( e );
}
// Use platform-independent GUI.
return new GUI();
} }
private static void checkUpdate() { private static void checkUpdate() {
try { try {
String implementationVersion = GUI.class.getPackage().getImplementationVersion(); String implementationVersion = Main.class.getPackage().getImplementationVersion();
String latestVersion = new ByteSource() { String latestVersion = new ByteSource() {
@Override @Override
public InputStream openStream() public InputStream openStream()
@ -111,10 +90,4 @@ public class GUI {
logger.wrn( e, "Couldn't check for version update." ); logger.wrn( e, "Couldn't check for version update." );
} }
} }
protected void open() {
Res.ui( () -> {
frame.setVisible( true );
} );
}
} }

View File

@ -16,29 +16,34 @@
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>. // LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//============================================================================== //==============================================================================
package com.lyndir.masterpassword.gui.platform.macos; package com.lyndir.masterpassword.gui.platform;
import com.apple.eawt.*; import com.apple.eawt.*;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.lyndir.masterpassword.gui.GUI; import com.lyndir.masterpassword.gui.view.MasterPasswordFrame;
import javax.swing.*;
/** /**
* @author lhunath, 2014-06-10 * @author lhunath, 2014-06-10
*/ */
public class AppleGUI extends GUI { public class AppleGUI extends BaseGUI {
static Application application; static Application application = Preconditions.checkNotNull(
Application.getApplication(), "Not an Apple Java application." );
static {
application = Preconditions.checkNotNull( Application.getApplication(), "Not an Apple Java application." );
}
public AppleGUI() { public AppleGUI() {
application.addAppEventListener( new ApplicationListener() ); application.addAppEventListener( new AppEventHandler() );
} }
private class ApplicationListener implements AppForegroundListener, AppReOpenedListener { @Override
protected MasterPasswordFrame createFrame() {
MasterPasswordFrame frame = super.createFrame();
frame.setDefaultCloseOperation( WindowConstants.HIDE_ON_CLOSE );
return frame;
}
private class AppEventHandler implements AppForegroundListener, AppReOpenedListener {
@Override @Override
public void appMovedToBackground(final AppEvent.AppForegroundEvent arg0) { public void appMovedToBackground(final AppEvent.AppForegroundEvent arg0) {

View File

@ -0,0 +1,58 @@
package com.lyndir.masterpassword.gui.platform;
import com.lyndir.lhunath.opal.system.logging.Logger;
import com.lyndir.lhunath.opal.system.util.TypeUtils;
import com.lyndir.masterpassword.gui.util.Res;
import com.lyndir.masterpassword.gui.view.MasterPasswordFrame;
import java.lang.reflect.InvocationTargetException;
import java.util.Optional;
import javax.annotation.Nullable;
/**
* @author lhunath, 2018-07-28
*/
public class BaseGUI {
private static final Logger logger = Logger.get( BaseGUI.class );
private final MasterPasswordFrame frame = createFrame();
public static BaseGUI createPlatformGUI() {
BaseGUI jdk9GUI = construct( "com.lyndir.masterpassword.gui.platform.JDK9GUI" );
if (jdk9GUI != null)
return jdk9GUI;
BaseGUI appleGUI = construct( "com.lyndir.masterpassword.gui.platform.AppleGUI" );
if (appleGUI != null)
return appleGUI;
// Use platform-independent GUI.
return new BaseGUI();
}
@Nullable
private static BaseGUI construct(final String typeName) {
try {
// AppleGUI adds support for macOS features.
Optional<Class<BaseGUI>> gui = TypeUtils.loadClass( typeName );
if (gui.isPresent())
return gui.get().getConstructor().newInstance();
}
catch (@SuppressWarnings("ErrorNotRethrown") final LinkageError ignored) {
}
catch (final IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
throw logger.bug( e );
}
return null;
}
protected MasterPasswordFrame createFrame() {
return new MasterPasswordFrame();
}
public void open() {
Res.ui( () -> frame.setVisible( true ) );
}
}

View File

@ -0,0 +1,60 @@
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
//
// Master Password is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Master Password is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
package com.lyndir.masterpassword.gui.platform;
import com.lyndir.masterpassword.gui.view.MasterPasswordFrame;
import java.awt.*;
import java.awt.desktop.*;
import javax.swing.*;
/**
* @author lhunath, 2014-06-10
*/
@SuppressWarnings("Since15")
public class JDK9GUI extends BaseGUI {
public JDK9GUI() {
Desktop.getDesktop().addAppEventListener( new AppEventHandler() );
}
@Override
protected MasterPasswordFrame createFrame() {
MasterPasswordFrame frame = super.createFrame();
frame.setDefaultCloseOperation( WindowConstants.HIDE_ON_CLOSE );
return frame;
}
private class AppEventHandler implements AppForegroundListener, AppReopenedListener {
@Override
public void appRaisedToForeground(final AppForegroundEvent e) {
open();
}
@Override
public void appMovedToBackground(final AppForegroundEvent e) {
}
@Override
public void appReopened(final AppReopenedEvent e) {
open();
}
}
}

View File

@ -20,6 +20,6 @@
* @author lhunath, 2018-04-26 * @author lhunath, 2018-04-26
*/ */
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
package com.lyndir.masterpassword.gui.platform.macos; package com.lyndir.masterpassword.gui.platform;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;