{"id":21387173,"url":"https://github.com/sshtools/two-slices","last_synced_at":"2026-03-14T15:02:22.979Z","repository":{"id":84133129,"uuid":"146993543","full_name":"sshtools/two-slices","owner":"sshtools","description":"Simple library for desktop notifications from Java on Windows, Mac OS X and Linux. ","archived":false,"fork":false,"pushed_at":"2024-07-09T22:06:22.000Z","size":1847,"stargazers_count":45,"open_issues_count":5,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-13T15:43:07.166Z","etag":null,"topics":["gntp","growl","java","message","notifications","popup","swt","toast","toaster"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sshtools.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-09-01T11:41:42.000Z","updated_at":"2025-06-19T20:35:39.000Z","dependencies_parsed_at":null,"dependency_job_id":"99db81ad-4751-465e-ae9a-a004ee9764f8","html_url":"https://github.com/sshtools/two-slices","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sshtools/two-slices","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshtools%2Ftwo-slices","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshtools%2Ftwo-slices/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshtools%2Ftwo-slices/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshtools%2Ftwo-slices/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sshtools","download_url":"https://codeload.github.com/sshtools/two-slices/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshtools%2Ftwo-slices/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271215037,"owners_count":24720098,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-19T02:00:09.176Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gntp","growl","java","message","notifications","popup","swt","toast","toaster"],"created_at":"2024-11-22T12:12:02.796Z","updated_at":"2026-03-14T15:02:22.966Z","avatar_url":"https://github.com/sshtools.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# two-slices\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.sshtools/two-slices/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.sshtools/two-slices)\n[![javadoc](https://javadoc.io/badge2/com.sshtools/two-slices/javadoc.svg)](https://javadoc.io/doc/com.sshtools/two-slices)\n![JPMS](https://img.shields.io/badge/JPMS-com.sshtools.twoslices-purple) \n\nSimple library for desktop notifications from Java on Windows, Mac OS X and Linux.\n \n * One-line of code to show a notification for most cases.\n * Tries to find the best implementation available to give the best looking and most integrated experience..\n * No hard dependencies, although can be augmented with AWT, Swing, SWT or JavaFX to provide further options.\n * Supports NONE, INFO, ERROR and WARNING notifications types, each with it's own icon.\n * Depending on provider, can support custom icons, images and actions.\n * Can integrate with your existing system tray icon if required (SWT and Swing/AWT)\n * Cross platform and custom JavaFX and SWT popup notifications included.\n\n## All Platforms\n\nAll 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.\n\nAll 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. \n\nAdditionally on all platforms, if no notifier implementation can be found, the last resort fallback will be to display the messages on *System.out*.\n\nIn all cases, you can override the chosen provider using `ToasterSettings.setPreferredToasterClassName`, see below.\n\n## Windows\n\n![](src/web/images/windows-awt.png) ![](src/web/images/windows-swt.png)\n\nWindows support is currently provided in the following order :-\n\n * JavaFX. If JavaFX and ControlsFX is on the CLASSPATH, [ControlsFX](http://controlsfx.com) based notification popups will be used.\n * SWT. If SWT is on the CLASSPATH, the custom SWT popup component will be used. The alternative System Tray based support and balloon tooltip can be used by explicitly requesting it.\n * AWT. If no SWT is available, the built-in AWT System Tray support will be used. \n\n## Mac OS X\n\n![](src/web/images/osx-notification-centre.png) ![](src/web/images/osx-swt.png) \n\nMac OS X support will be provided in the following order :-\n\n * If native notification centre support is available (Mountain Lion and above), it will be used first.\n * Growl (via AppleScript). If Growl via AppleScript is available, it will be used.\n * If there is no growl, but osascript is an available command, the default Notification Centre will be used\n * JavaFX. If JavaFX and ControlsFX is on the CLASSPATH, [ControlsFX](http://controlsfx.com) based notification \n * SWT. If SWT is on the CLASSPATH, the custom SWT popup component will be used. The alternative System Tray based support and balloon tooltip can be used by explicitly requesting it.\n * AWT. If no SWT is available, the built-in AWT System Tray support will be used.    \n \n## Linux\n\n![](src/web/images/linux-notify.png) ![](src/web/images/linux-swt.png)\n\nLinux support will be provided in the following order :-\n\n * If `dbus-java` is available, native DBus notifications will be used.\n * notify-send. If this is an available command, the default desktop notifications will be used\n * JavaFX. If JavaFX and ControlsFX is on the CLASSPATH, [ControlsFX](http://controlsfx.com) based notification \n * SWT. If SWT is on the CLASSPATH, the custom SWT popup component will be used. The alternative System Tray based support and balloon tooltip can be used by explicitly requesting it.\n * AWT. If no SWT is available, the built-in AWT System Tray support will be used.\n\n## Configuring your project\n\nThe library is available in Maven Central, so configure your project according to the\nbuild system you use. For example, for Maven itself :-\n\n```xml\n\t\u003cdependencies\u003e\n\t\t\u003cdependency\u003e\n\t\t\t\u003cgroupId\u003ecom.sshtools\u003c/groupId\u003e\n\t\t\t\u003cartifactId\u003etwo-slices\u003c/artifactId\u003e\n\t\t\t\u003cversion\u003e0.9.6\u003c/version\u003e\n\t\t\u003c/dependency\u003e\n\t\u003c/dependencies\u003e\n```\n\n### Snapshots\n\n*Development builds may be available in the snapshots repository*\n\n```xml\n\n\u003crepositories\u003e\n\t\u003crepository\u003e\n\t\t\u003cid\u003eoss-snapshots\u003c/id\u003e\n\t\t\u003curl\u003ehttps://oss.sonatype.org/content/repositories/snapshots\u003c/url\u003e\n\t\t\u003csnapshots\u003e\n\t\t\t\u003cenabled\u003etrue\u003c/enabled\u003e\n\t\t\u003c/snapshots\u003e\n\t\t\u003creleases\u003e\n\t\t\t\u003cenabled\u003efalse\u003c/enabled\u003e\n\t\t\u003c/releases\u003e\n\t\u003c/repository\u003e\n\u003c/repositories\u003e\n\t\n..\n\n\u003cdependencies\u003e\n\t\u003cdependency\u003e\n\t\t\u003cgroupId\u003ecom.sshtools\u003c/groupId\u003e\n\t\t\u003cartifactId\u003etwo-slices\u003c/artifactId\u003e\n\t\t\u003cversion\u003e0.9.7-SNAPSHOT\u003c/version\u003e\n\t\u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\n### SWT Support\n\nAt time of writing this, the SWT artifacts that are available on Maven Central are\nincompatible with having a cross-platform and fully JPMS compliant library or application.\nThis is due to the module naming scheme chosen by the SWT packagers.\n\nTwo Slices is fully JPMS compliant otherwise, and including SWT as in the primary artifact\nwould degrade this support. \n\nFor this reason, if you wish to use SWT you must also add the separate SWT artifact. \nThis is *not* modular, other than having an `Automatic-Module-Name`. If you are using\nSWT, you probably do not care about this as you'll have other problems with JPMS\nanyway.\n\n   \n```xml\n\t\u003cdependencies\u003e\n\t\t\u003cdependency\u003e\n\t\t\t\u003cgroupId\u003ecom.sshtools\u003c/groupId\u003e\n\t\t\t\u003cartifactId\u003etwo-slices-swt\u003c/artifactId\u003e\n\t\t\t\u003cversion\u003e0.9.4\u003c/version\u003e\n\t\t\u003c/dependency\u003e\n\t\u003c/dependencies\u003e\n```\n\n## Showing A Message\n\nFor the simplest use, call Toast.toast() :-\n\n```java\nToast.toast(ToastType.INFO, \"Information\", \"Here is some information you cannot do without.\");\n```\n\n### With A Custom Icon\n\nYou can pass in the full path to an icon too (requires support for this in selected platform)\n\n```java\nToast.toast(ToastType.INFO, \"/usr/share/pixmaps/mypic.png\", \"Boo!\", \"See my image?\");\n```\n\n## Using The Builder\n\nAn alternative way to build more complex messages is using `ToastBuilder`. \n\n```java\nvar builder = Toast.builder();\nbuilder.title(\"My Title\");\nbuilder.content(\"Some content\");\n\nbuilder.toast();\n```\n\n### Closing\n\nYou can prematurely close messages if the toaster implementation supports it.\n\n```java\nvar builder = Toast.builder();\nbuilder.title(\"My Title\");\nbuilder.content(\"Some content\");\nvar slice = builder.toast();\n\n// ...\n\nslice.close();\n\n```\n\nIf you want to be notified when a message is closed, e.g. dismissed by the user. Set a listener on the builder.\n\n```java\nvar builder = Toast.builder();\nbuilder.content(\"Some content\");\nbuilder.closed(() -\u003e {\n    System.out.println(\"Message closed.\");\n});\nbuilder.toast();\n\n```\n\n### Actions\n\nIf the toaster implementation supports them, *Actions* may be added. An action would usually be represented as a button on a notification message. \n\nThere 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.\n\nBe aware different implementations have different restrictions on how many actions can be presented.\n\n```java\n\tvar builder = Toast.builder();\n\tbuilder.content(\"Some content\");\n\tbuilder.action(\"Action 1\", () -\u003e System.out.println(\"Do Action 1\"));\n\tbuilder.action(\"Action 2\", () -\u003e System.out.println(\"Do Action 2\"));\n\tbuilder.defaultAction(System.out.println(\"Do Default Action\"));\n\tbuilder.toast();\n```\n\n## Settings\n\nSome settings may be provided to alter the behaviour of the toasters. These are only hints, and specific \ntoasters can ignore any and all of them.  \n\n```java\nToasterFactory.setSettings(new ToasterSettings().setAppName(\"My App Name\"));\n```\n\nSome toaster implementations have additional hints that can be passed. These hints are only\ngenerally only supported by individual toolkits. For example, to resize icons or images in \nthe SWT implementation, you would do the following.\n\n```java\nToasterSettings settings = new ToasterSettings();\nsettings.getHints().put(BasicToastHint.ICON_SIZE, 64);\nToasterFactory.setSettings(settings);\n```\n\n`BasicToastHint` contains a generic list of hints that a provider may or may not support. See\nthe class documentation for more detail.\n\nHints may also be set on individual toast, see `ToastBuilder.hints()`. \n\n### The Tray Icon Mode\n\nSome implementations will require and/or show an icon in your system tray. This will be where the notification\nmessages are anchored to. You can set a hint as to how to treat this icon via the configuration.\n\n```java\nToasterSettings settings = new ToasterSettings();\nsettings.setAppName(\"My App Name\");\nsettings.setSystemTrayIconMode(SystemTrayIconMode.HIDDEN);\nToasterFactory.setSettings(settings);\n```\n\nThe options for system tray icon mode are :-\n * HIDDEN. The icon will be hidden at all times. This may require the use of a transparent image depending on the platform.\n * SHOW_TOAST_TYPE_WHEN_ACTIVE. When active, the icon in the system tray will reflect the type of the current message that is being displayed.\n * SHOW_DEFAULT_WHEN_ACTIVE. When a message is shown, the default tray icon will be show (see `ToasterSettings.setDefaultImage()`).\n * SHW_DEFAULT_ALWAYS. The default image (see above) will always be visible as soon as the first notification message is sent.\n\n*When you are providing a 'parent' tray item, the icon mode above may be ignored.*\n\n### SWT\n\nIf you have an SWT application that already has an icon on the tray, you can re-use this for your notification\nsettings when the SWT notifier is used.\n\n*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.*\n\n```java\nTrayItem myTrayItem = .....  // this is the reference to your org.eclipse.swt.widgets.TrayItem\nToasterFactory.setSettings(new ToasterSettings().setParent(myTrayItem));\n```\n\nThen, whenever the SWT notifier is used, the balloon message will be anchored to your tray item.\n\n### AWT\n\nIf you have a Swing/AWT application that already has an icon on the tray, you can re-use this for your notification\nsettings when the AWT notifier is used.\n\n```java\nTrayIcon myTrayIcon = .....  // this is the reference to your java.awt.TrayIcon\nToasterFactory.setSettings(new ToasterSettings().setParent(myTrayIcon));\n```\n\nThen, whenever the AWT notifier is used, the balloon message will be anchored to your tray item.\n\n## Extending\n\nYou can add your own notifier implementations and customise the factory if you have any special requirements.\n\n### Implementing a Toaster\n\nImplement 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. \n\nIn 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.\n\n#### Adding The Service\n\nBefore 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.\n\n```java\npublic class MyToaster extends AbstractToaster {\n\t\n\tpublic static class Service implements ToasterService {\n\t\t@Override\n\t\tpublic Toaster create(ToasterSettings settings) {\n\t\t\treturn new MyToaster(settings);\n\t\t}\n\t}\n\n\tpublic MyToaster(ToasterSettings configuration) {\n\t\tsuper(configuration);\n\t}\n\n\t@Override\n\tpublic Slice toast(ToastBuilder builder) {\n\t\t// TODO\n\t}\n}\n```\n\nFor 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.\n\n### Installing Your Own Factory\n\nIf 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) :-\n\n```java\nnew ToasterFactory() {\n\t@Override\n\tpublic Toaster toaster() {\n\t\treturn new MyToaster(); \n\t}\n};\n```\n\n### Your Custom Toast\n\nJust call `Toast.toast` as you normally would.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsshtools%2Ftwo-slices","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsshtools%2Ftwo-slices","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsshtools%2Ftwo-slices/lists"}