sshtools / two-slices

Simple library for desktop notifications from Java on Windows, Mac OS X and Linux.
Apache License 2.0
37 stars 2 forks source link
gntp growl java message notifications popup swt toast toaster

two-slices

Maven Central javadoc JPMS

Simple library for desktop notifications from Java on Windows, Mac OS X and Linux.

All Platforms

All platforms support Growls GNTP protocol. If you have have Growl for Mac OS X, Linux or Windows installed, and it is listening on the default port, it will be used in preference to all platform specific notification systems.

All platforms can use one of the Java GUI toolkit specific implementations, such as JavaFX or SWT. If these toolkit libraries are available, those will be chosen if the experience is superior to the native implementation.

Additionally on all platforms, if no notifier implementation can be found, the last resort fallback will be to display the messages on System.out.

In all cases, you can override the chosen provider using ToasterSettings.setPreferredToasterClassName, see below.

Windows

Windows support is currently provided in the following order :-

Mac OS X

Mac OS X support will be provided in the following order :-

Linux

Linux support will be provided in the following order :-

Configuring your project

The library is available in Maven Central, so configure your project according to the build system you use. For example, for Maven itself :-

    <dependencies>
        <dependency>
            <groupId>com.sshtools</groupId>
            <artifactId>two-slices</artifactId>
            <version>0.9.4</version>
        </dependency>
    </dependencies>

Snapshots

Development builds may be available in the snapshots repository


<repositories>
    <repository>
        <id>oss-snapshots</id>
        <url>https://oss.sonatype.org/content/repositories/snapshots</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
        <releases>
            <enabled>false</enabled>
        </releases>
    </repository>
</repositories>

..

<dependencies>
    <dependency>
        <groupId>com.sshtools</groupId>
        <artifactId>two-slices</artifactId>
        <version>0.9.5-SNAPSHOT</version>
    </dependency>
</dependencies>

SWT Support

At time of writing this, the SWT artifacts that are available on Maven Central are incompatible with having a cross-platform and fully JPMS compliant library or application. This is due to the module naming scheme chosen by the SWT packagers.

Two Slices is fully JPMS compliant otherwise, and including SWT as in the primary artifact would degrade this support.

For this reason, if you wish to use SWT you must also add the separate SWT artifact. This is not modular, other than having an Automatic-Module-Name. If you are using SWT, you probably do not care about this as you'll have other problems with JPMS anyway.

    <dependencies>
        <dependency>
            <groupId>com.sshtools</groupId>
            <artifactId>two-slices-swt</artifactId>
            <version>0.9.4</version>
        </dependency>
    </dependencies>

Showing A Message

For the simplest use, call Toast.toast() :-

Toast.toast(ToastType.INFO, "Information", "Here is some information you cannot do without.");

With A Custom Icon

You can pass in the full path to an icon too (requires support for this in selected platform)

Toast.toast(ToastType.INFO, "/usr/share/pixmaps/mypic.png", "Boo!", "See my image?");

Using The Builder

An alternative way to build more complex messages is using ToastBuilder.

var builder = Toast.builder();
builder.title("My Title");
builder.content("Some content");

builder.toast();

Closing

You can prematurely close messages if the toaster implementation supports it.

var builder = Toast.builder();
builder.title("My Title");
builder.content("Some content");
var slice = builder.toast();

// ...

slice.close();

If you want to be notified when a message is closed, e.g. dismissed by the user. Set a listener on the builder.

var builder = Toast.builder();
builder.content("Some content");
builder.closed(() -> {
    System.out.println("Message closed.");
});
builder.toast();

Actions

If the toaster implementation supports them, Actions may be added. An action would usually be represented as a button on a notification message.

There is a special action, the defaultAction(). This is usually invoked when the whole notification message is clicked, or it may simply be presented as another button.

Be aware different implementations have different restrictions on how many actions can be presented.

    var builder = Toast.builder();
    builder.content("Some content");
    builder.action("Action 1", () -> System.out.println("Do Action 1"));
    builder.action("Action 2", () -> System.out.println("Do Action 2"));
    builder.defaultAction(System.out.println("Do Default Action"));
    builder.toast();

Settings

Some settings may be provided to alter the behaviour of the toasters. These are only hints, and specific toasters can ignore any and all of them.

ToasterFactory.setSettings(new ToasterSettings().setAppName("My App Name"));

Some toaster implementations have additional hints that can be passed. These hints are only generally only supported by individual toolkits. For example, to resize icons or images in the SWT implementation, you would do the following.

ToasterSettings settings = new ToasterSettings();
settings.getHints().put(BasicToastHint.ICON_SIZE, 64);
ToasterFactory.setSettings(settings);

BasicToastHint contains a generic list of hints that a provider may or may not support. See the class documentation for more detail.

Hints may also be set on individual toast, see ToastBuilder.hints().

The Tray Icon Mode

Some implementations will require and/or show an icon in your system tray. This will be where the notification messages are anchored to. You can set a hint as to how to treat this icon via the configuration.

ToasterSettings settings = new ToasterSettings();
settings.setAppName("My App Name");
settings.setSystemTrayIconMode(SystemTrayIconMode.HIDDEN);
ToasterFactory.setSettings(settings);

The options for system tray icon mode are :-

When you are providing a 'parent' tray item, the icon mode above may be ignored.

SWT

If you have an SWT application that already has an icon on the tray, you can re-use this for your notification settings when the SWT notifier is used.

For SWT, you must already be running an event loop (see SWT toolkit documentation). At the moment it is not possible to automatically start a loop mainly due to restrictions on OS X where SWT must be on the main thread.

TrayItem myTrayItem = .....  // this is the reference to your org.eclipse.swt.widgets.TrayItem
ToasterFactory.setSettings(new ToasterSettings().setParent(myTrayItem));

Then, whenever the SWT notifier is used, the balloon message will be anchored to your tray item.

AWT

If you have a Swing/AWT application that already has an icon on the tray, you can re-use this for your notification settings when the AWT notifier is used.

TrayIcon myTrayIcon = .....  // this is the reference to your java.awt.TrayIcon
ToasterFactory.setSettings(new ToasterSettings().setParent(myTrayIcon));

Then, whenever the AWT notifier is used, the balloon message will be anchored to your tray item.

Extending

You can add your own notifier implementations and customise the factory if you have any special requirements.

Implementing a Toaster

Implement the Toaster interface. An abstract implementation AbstractToaster is provided for your convenience and should be used where possible. By convention, all Toasters take a ToasterSettings in their constructor.

In the constructor of your implementation, you should test if this implementation is for the current enviroment. E.g. if you were writing an OS X specific notifier, then you would test for running on that platform and the availability of any libraries or external tools you might need. By convention, if the environment is not sufficient, an UnsupportedOperationException should be thrown.

Adding The Service

Before your new Toaster implementation can be used, you must provide a ToasterService implementation that creates it based on the given configuration. By convention, you place this as an inner class inside the Toaster implementation.

public class MyToaster extends AbstractToaster {

    public static class Service implements ToasterService {
        @Override
        public Toaster create(ToasterSettings settings) {
            return new MyToaster(settings);
        }
    }

    public MyToaster(ToasterSettings configuration) {
        super(configuration);
    }

    @Override
    public Slice toast(ToastBuilder builder) {
        // TODO
    }
}

For Java to automatically find this service, you must add it's full class name, e.g. com.mypackage.MyToaster$Service to a file in META-INF/services/com.sshtools.twoslices.ToasterService, and/or add it to module-info.java using the appropriate syntax for Java services.

Installing Your Own Factory

If you do not wish to use Java's ServiceLoader feature to locate toaster implementations, you can extend ToasterFactory and provide your own toaster() method. This will be registered as the default factory the first time you instantiate it (so make sure you do this before ever asking for toast) :-

new ToasterFactory() {
    @Override
    public Toaster toaster() {
        return new MyToaster(); 
    }
};

Your Custom Toast

Just call Toast.toast as you normally would.