├── .github ├── FUNDING.yml └── workflows │ └── main.yml ├── .gitignore ├── .travis.yml ├── BuilderTutorial.md ├── LICENSE ├── README.md ├── img ├── FXTCheck.gif ├── animation.gif ├── fxtrayicon-1.png ├── fxtrayicon-2.png ├── showDefault.png ├── showError.png ├── showInfo.png └── showWarn.png ├── pom.xml └── src ├── main ├── java │ ├── com │ │ └── dustinredmond │ │ │ └── fxtrayicon │ │ │ ├── AWTUtils.java │ │ │ ├── Animation.java │ │ │ ├── BuildOrderUtil.java │ │ │ ├── FXTrayIcon.java │ │ │ ├── IconScale.java │ │ │ ├── ItemType.java │ │ │ ├── Restricted.java │ │ │ ├── RestrictedInterface.java │ │ │ └── annotations │ │ │ └── API.java │ └── module-info.java └── resources │ └── com │ └── dustinredmond │ └── fxtrayicon │ ├── FXIconBlueWhite.png │ ├── FXIconBlueYellow.png │ ├── FXIconGreenWhite.png │ ├── FXIconGreenYellow.png │ ├── FXIconRedWhite.png │ ├── FXIconRedYellow.png │ ├── i-Icon-Glass-Blue.png │ ├── i-Icon-Glass-Blue2.png │ └── i-Icon-Glass-Green.png └── test ├── java └── com │ └── dustinredmond │ └── fxtrayicon │ ├── CheckIsSupportedByPlatform.java │ ├── CheckMenu.java │ ├── CheckMenuBuilder.java │ ├── DefaultIconTest.java │ ├── MultipleItemsOneLine.java │ ├── NestedSubMenus.java │ ├── RunnableTest.java │ ├── TestAddDefaultMenuItem.java │ ├── TestBareFXTrayIcon.java │ ├── TestBuilderClass.java │ ├── TestFXTrayIcon.java │ ├── TestRestrictedAccess.java │ ├── TestSwitchIconsOnTheFly.java │ ├── TestTextChangeInFXItem.java │ ├── animation │ ├── Animation.java │ └── Launcher.java │ ├── issue71 │ ├── AddMenuItem.java │ └── Launcher.java │ └── notaskbaricon │ ├── Main.java │ └── Start.java └── resources └── com └── dustinredmond └── fxtrayicon └── animate ├── One ├── 01.png ├── 02.png ├── 03.png ├── 04.png ├── 05.png ├── 06.png ├── 07.png ├── 08.png ├── 09.png ├── 10.png ├── 11.png ├── 12.png ├── 13.png ├── 14.png ├── 15.png ├── 16.png ├── 17.png ├── 18.png ├── 19.png ├── 20.png ├── 21.png ├── 22.png ├── 23.png ├── 24.png ├── 25.png ├── 26.png ├── 27.png ├── 28.png ├── 29.png ├── 30.png ├── 31.png ├── 32.png ├── 33.png ├── 34.png ├── 35.png ├── 36.png ├── 37.png ├── 38.png ├── 39.png ├── 40.png ├── 41.png ├── 42.png ├── 43.png ├── 44.png ├── 45.png ├── 46.png ├── 47.png ├── 48.png └── Tray.png ├── Three ├── 00.png ├── 01.png ├── 02.png ├── 03.png ├── 04.png ├── 05.png ├── 06.png ├── 07.png ├── 08.png ├── 09.png ├── 10.png ├── 11.png ├── 12.png ├── 13.png ├── 14.png ├── 15.png ├── 16.png ├── 17.png ├── 18.png ├── 19.png ├── 20.png ├── 21.png ├── 22.png ├── 23.png ├── 24.png ├── 25.png ├── 26.png ├── 27.png ├── 28.png ├── 29.png ├── 30.png ├── 31.png ├── 32.png ├── 33.png ├── 34.png ├── 35.png ├── 36.png ├── 37.png ├── 38.png ├── 39.png ├── 40.png ├── 41.png └── Tray.png └── Two ├── 01.png ├── 02.png ├── 03.png ├── 04.png ├── 05.png ├── 06.png ├── 07.png ├── 08.png ├── 09.png ├── 10.png ├── 11.png ├── 12.png ├── 13.png ├── 14.png ├── 15.png ├── 16.png ├── 17.png ├── 18.png ├── 19.png ├── 20.png ├── 21.png ├── 22.png ├── 23.png ├── 24.png ├── 25.png ├── 26.png ├── 27.png ├── 28.png ├── 29.png ├── 30.png ├── 31.png ├── 32.png ├── 33.png ├── 34.png ├── 35.png ├── 36.png ├── 37.png ├── 38.png ├── 39.png ├── 40.png ├── 41.png ├── 42.png ├── 43.png ├── 44.png ├── 45.png ├── 46.png ├── 47.png ├── 48.png └── Tray.png /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: dustinkredmond 4 | 5 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI build 2 | 3 | on: [push] 4 | 5 | jobs: 6 | builds: 7 | name: '${{ matrix.os }} with Java ${{ matrix.jdk }}' 8 | runs-on: ${{ matrix.os }} 9 | strategy: 10 | matrix: 11 | jdk: [17,21] 12 | os: [windows-latest, ubuntu-latest] 13 | fail-fast: false 14 | max-parallel: 6 15 | timeout-minutes: 10 16 | 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v4 20 | - name: Setup Java ${{ matrix.jdk }} 21 | uses: actions/setup-java@v4 22 | with: 23 | distribution: 'temurin' 24 | java-version: ${{ matrix.jdk }} 25 | - name: Compile 26 | run: | 27 | mvn clean package -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.log 3 | *.jar 4 | hs_err_pid* 5 | *.iml 6 | .idea 7 | /target 8 | /.java-version 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | dist: bionic 3 | install: true 4 | jdk: 5 | - openjdk11 6 | branches: 7 | only: 8 | - main 9 | -------------------------------------------------------------------------------- /BuilderTutorial.md: -------------------------------------------------------------------------------- 1 | ## FXTrayIcon Builder Class 2 | ### This document outlines the various ways you can instantiate FXTrayIcon using its Builder class 3 | 4 | Perhaps the most convenient way to instantiate FXTray Icon is through the Builder class. With the Builder, 5 | you can set any option, add menuItems and even subMenus to your tray icon, all in one line of code, and 6 | FXTrayIcon will build the menu in the order in which you add the items into your build sentence. 7 | 8 | Here are the constructor options for the Builder 9 | ```Java 10 | FXTrayIcon trayIcon = new FXTrayIcon.Builder(primaryStage, URL iconImagePath) 11 | FXTrayIcon trayIcon = new FXTrayIcon.Builder(primaryStage, java.io.File iconImageFile) 12 | FXTrayIcon trayIcon = new FXTrayIcon.Builder(primaryStage, javafx.scene.image.Image iconJavaFXImage) 13 | FXTrayIcon trayIcon = new FXTrayIcon.Builder(primaryStage, java.awt.Image iconJavaAWTImage) 14 | ``` 15 | 16 | OR any of the above options with the addition of the icon size. For example: 17 | ```java 18 | FXTrayIcon trayIcon = new FXTrayIcon.Builder(primaryStage, URL iconImagePath, int width, int height) 19 | ``` 20 | After you state the constructor, you have these options available to build your tray icon: 21 | 22 | Add menuItems dynamically without needing to pre-build them, by passing in the label and the 23 | event that the menuItem will execute: 24 | ```java 25 | new FXTrayIcon.Builder(stage,icon).menuItem("My Menu", e -> myMenuMethod()).build(); 26 | ``` 27 | OR, you can pre-build them and add them into the Builder like this 28 | ```java 29 | MenuItem myMenuItem = new MenuItem(); 30 | myMenuItem.setOnAction(e-> myMenuMethod()); 31 | new FXTrayIcon.Builder(stage,icon).menuItem(myMenuItem).build(); 32 | ``` 33 | 34 | You can also include multiple menuItems in one statement like this 35 | 36 | ```java 37 | new FXTrayIcon.Builder(stage,icon) 38 | .menuItem("My Menu 1", e -> myMenuMethod1()) 39 | .menuItem("My Menu 2", e -> myMenuMethod2()) 40 | .build(); 41 | ``` 42 | OR pre-built 43 | ```java 44 | MenuItem myMenuItem1 = new MenuItem(); 45 | myMenuItem1.setOnAction(e-> myMenuMethod1()); 46 | 47 | MenuItem myMenuItem2 = new MenuItem(); 48 | myMenuItem2.setOnAction(e-> myMenuMethod2()); 49 | 50 | new FXTrayIcon.Builder(stage,icon).menuItems(myMenuItem1, myMenuItem2).build(); 51 | ``` 52 | 53 | Or you can even pre-build an entire Menu with MenuItems, then add that in as a branched submenu: 54 | 55 | ```java 56 | Menu menu = new Menu("My Sub Menu"); 57 | 58 | MenuItem myMenuItem1 = new MenuItem(); 59 | myMenuItem1.setOnAction(e-> myMenuMethod1()); 60 | 61 | MenuItem myMenuItem2 = new MenuItem(); 62 | myMenuItem2.setOnAction(e-> myMenuMethod2()); 63 | 64 | menu.getItems().addAll(myMenuItem1, myMenuItem2); 65 | 66 | new FXTrayIcon.Builder(stage,icon).menu(menu).build(); 67 | ``` 68 | 69 | Or even include CheckMenuItems: 70 | ```java 71 | Menu menu = new Menu("My Sub Menu"); 72 | 73 | MenuItem myMenuItem1 = new MenuItem(); 74 | CheckMenuItem myCheckMenuItem = new CheckMenuItem(); 75 | myMenuItem1.setOnAction(e-> myMenuMethod1()); 76 | myCheckMenuItem.setOnAction(e-> myCheckMenuMethod()); 77 | 78 | MenuItem myMenuItem2 = new MenuItem(); 79 | myMenuItem2.setOnAction(e-> myMenuMethod2()); 80 | 81 | menu.getItems().addAll(myMenuItem1, myMenuItem2); 82 | 83 | new FXTrayIcon.Builder(stage,icon).menu(menu).checkMenuItem(myCheckMenuItem).build(); 84 | 85 | ``` 86 | 87 | You can also add a branched sub-menu dynamically by calling the menu Builder method, giving 88 | the sub-menu a label then passing in MenuItem objects like this 89 | 90 | ```java 91 | MenuItem myMenuItem1 = new MenuItem(); 92 | myMenuItem1.setOnAction(e-> myMenuMethod1()); 93 | 94 | MenuItem myMenuItem2 = new MenuItem(); 95 | myMenuItem2.setOnAction(e-> myMenuMethod2()); 96 | 97 | new FXTrayIcon.Builder(stage,icon).menu("My Sub Menu", menuItem1, menuItem2).build(); 98 | ``` 99 | 100 | Add menu separator lines like this and FXTray Icon will place the separators (and all 101 | objects you include), in the order that you have them in your build sentence. 102 | 103 | ```java 104 | new FXTrayIcon.Builder(stage,icon) 105 | .menuItem("My Menu 1", e -> myMenuMethod1()) 106 | .menuItem("My Menu 2", e -> myMenuMethod2()) 107 | .separator() 108 | .menuItem("My Menu 3", e -> myMenuMethod3()) 109 | .checkMenuItem("Selection", e -> myCheckMenuMethod()) 110 | .separator() 111 | .menuItem("My Menu 4", e -> myMenuMethod4()) 112 | .build(); 113 | ``` 114 | 115 | Add a tooltip that will display when the mouse pointer is hovered over the trayIcon 116 | 117 | ```java 118 | new FXTrayIcon.Builder(stage,icon) 119 | .menuItem("My Menu 1", e -> myMenuMethod1()) 120 | .tooltip("This is your Tray Icon") 121 | .build(); 122 | ``` 123 | 124 | FXTray Icon has something called a TitleItem, that is simply a MenuItem with the label 125 | set to the Applications Title String, that will call the Stage that you passed into the 126 | main constructor and bring it into view. When you use this option, that menuItem will 127 | always be at the top of your menu list. 128 | ```java 129 | new FXTrayIcon.Builder(stage,icon).addTitleItem(true).build(); 130 | ``` 131 | 132 | Alternatively, you can do the same thing, but assign the actual AppTitle string with 133 | the call 134 | ```java 135 | new FXTrayIcon.Builder(stage,icon).applicationTitle("My Application Title").build(); 136 | ``` 137 | 138 | Next, we have the onAction option. This is an option that will run an event that you pass 139 | into the argument and will run differently depending on the operating system. Under Windows, 140 | a simple left click on the tray Icon will invoke the event. On a Mac, it will be necessary 141 | to click both the left and right mouse buttons at the same time. 142 | ```java 143 | new FXTrayIcon.Builder(stage,icon).onAction(e -> myMethod()).build(); 144 | ``` 145 | 146 | Then we have the Exit menu item. This is a special MenuItem that will ALWAYS be placed 147 | at the bottom of the menu list, even if you add or remove items from the list during 148 | runtime. Invoking the menuItem will close the application. There are three ways to use 149 | this option: 150 | 151 | With the default label 152 | ```java 153 | new FXTrayIcon.Builder(stage,icon).addExitMenuItem().build(); 154 | ``` 155 | 156 | With a label of your choosing 157 | ```java 158 | new FXTrayIcon.Builder(stage,icon).addExitMenuItem("My Exit Menu Label").build(); 159 | ``` 160 | 161 | Or by passing in your own event that will close your app however you decide it needs to 162 | be closed 163 | ```java 164 | new FXTrayIcon.Builder(stage,icon).addExitMenuItem("My Exit Label", e -> myExitMethod()).build(); 165 | ``` 166 | 167 | Last, we have the show() option, which will simply cause FXTrayIcon to show the icon 168 | immediately after it's built so that you don't have to add call the show method after you 169 | create your build sentence. 170 | 171 | So for example, this Builder call will build the trayIcon, and show it all at the same time 172 | ```java 173 | new FXTrayIcon.Builder(stage,icon) 174 | .menuItem("My Menu 1", e -> myMenuMethod1()) 175 | .menuItem("My Menu 2", e -> myMenuMethod2()) 176 | .separator() 177 | .menuItem("My Menu 3", e -> myMenuMethod3()) 178 | .separator() 179 | .menuItem("My Menu 4", e -> myMenuMethod4()) 180 | .addExitMenuItem() 181 | .show() 182 | .build(); 183 | ``` 184 | 185 | Have Fun! 186 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Dustin K. Redmond 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FXTrayIcon 2 | 3 | [![Maven Central](https://img.shields.io/maven-central/v/com.dustinredmond.fxtrayicon/FXTrayIcon.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.dustinredmond.fxtrayicon%22%20AND%20a:%22FXTrayIcon%22) 4 | [![Travis CI Build](https://travis-ci.com/dustinkredmond/FXTrayIcon.svg?branch=main)](https://travis-ci.com/dustinkredmond/FXTrayIcon) 5 | 6 | Library for use in JavaFX applications that makes adding a System Tray icon easier. 7 | The FXTrayIcon class handles all the messy AWT and Swing parts of constructing an icon, 8 | displaying notifications, creating a context menu, etc. This means that users of FXTrayIcon can 9 | work solely with its public API and JavaFX classes that they are already familiar with. 10 | 11 | Check out the [runnable test application](./src/test/java/com/dustinredmond/fxtrayicon/RunnableTest.java) in the test directory for an example of how this works. 12 | 13 | ## Usage 14 | 15 | From within your JavaFX application, adding a tray icon is as simple as two lines of code. 16 | Yes, really, that's it! 17 | 18 | ```java 19 | // Pass in the app's main stage, and path to the icon image 20 | FXTrayIcon icon = new FXTrayIcon(stage, getClass().getResource("someImageFile.png")); 21 | icon.show(); 22 | ``` 23 | 24 | ## Or use Builder Style 25 | 26 | ```java 27 | FXTrayIcon icon = new FXTrayIcon.Builder(stage, iconURL).menuItem("Menu 1", e-> myMethod()).addExitItem().show().build(); 28 | ``` 29 | 30 | [Click here for a Builder tutorial](https://github.com/dustinkredmond/FXTrayIcon/blob/main/BuilderTutorial.md) 31 | 32 | ## How do I add to my project 33 | 34 | The project is available as a Maven dependency on Central. Add the following to POM.xml 35 | 36 | ```xml 37 | 38 | com.dustinredmond.fxtrayicon 39 | FXTrayIcon 40 | 41 | 42 | ``` 43 | 44 | Or, if using Gradle to build, add the below to your Gradle build file 45 | 46 | ```groovy 47 | compile group: 'com.dustinredmond.fxtrayicon', name: 'FXTrayIcon', version: '' 48 | ``` 49 | 50 | You can even use it from a Groovy script! 51 | 52 | ```groovy 53 | @Grapes( 54 | @Grab(group='com.dustinredmond.fxtrayicon', module='FXTrayIcon', version='') 55 | ) 56 | ``` 57 | 58 | *Note, for the current stable version number, use the following:* 59 | [![Maven Central](https://img.shields.io/maven-central/v/com.dustinredmond.fxtrayicon/FXTrayIcon.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.dustinredmond.fxtrayicon%22%20AND%20a:%22FXTrayIcon%22) 60 | 61 | ## Features & Screenshots 62 | 63 | ### CheckMenuItems 64 | 65 | FXTrayIcon now supports the use of CheckMenuItems - See Javadocs for specifics. 66 | 67 | ![FXTCheck](./img/FXTCheck.gif) 68 | 69 | ## Animated Icons 70 | 71 | FXTrayIcon now offers a convenient way to animate the icon in the tray. This is great 72 | for things like letting the user know when the program is processing something or even 73 | to subtly get their attention. 74 | 75 | ![animation](./img/animation.gif) 76 | 77 | The way you use it is straightforward. First, create all the frames of the animation and 78 | save each frame into a file. The turning circle above, for example, took 45 files to create. 79 | Once you have the files, 80 | you can load them into FXTrayIcon in one of two ways: Pass in `LinkedList` or 81 | `LinkedList`. 82 | 83 | For example, create a `LinkedList` containing the `File` objects of each frame, 84 | and then pass them into FXTrayIcon using the Builder or after FXTrayIcon has been instantiated. 85 | We recommend putting the files into their own folder; numbered in sequence, then create the 86 | list from that folder. 87 | 88 | Creating the list: 89 | 90 | ```Java 91 | File[] files = new File("path/to/my/imageFiles").listFiles(); 92 | LinkedList fileList = new LinkedList<>(Arrays.asList(files)); 93 | fileList.sort(Comparator.comparing(File::getName)); 94 | ``` 95 | 96 | Using the list with the Builder: 97 | ```Java 98 | trayIcon = new FXTrayIcon.Builder(primaryStage, iconFile) 99 | .animate(fileList, 75) 100 | .addExitMenuItem("Exit", e -> Main.stopRunning()) 101 | .show() 102 | .build(); 103 | ``` 104 | 105 | Or after instantiation: 106 | ```Java 107 | trayIcon.newAnimation(fileList, 75); 108 | ``` 109 | 110 | The `.newAnimation()` method can also be used to replace an existing animation. 111 | 112 | The number after `fileList` is the amount of time that each frame will be shown, specified in milliseconds. 113 | 114 | These methods can be used to play and control the animation: 115 | 116 | ```Java 117 | trayIcon.play(); 118 | trayIcon.playFromStart(); 119 | trayIcon.stop(); 120 | trayIcon.pause(); 121 | trayIcon.pauseResume(); 122 | trayIcon.stopReset(); 123 | trayIcon.resetIcon(); 124 | ``` 125 | 126 | Use these methods to get the state of the animation: 127 | ```Java 128 | trayIcon.isRunning(); 129 | trayIcon.isPaused(); 130 | trayIcon.isStopped(); 131 | ``` 132 | 133 | And if you need access to the timeline of the animation for any reason, just use `trayIcon.getTimeline()` 134 | 135 | There is a full working program in the test folder called Animation. It will show you everything you need 136 | to know. The JavaDocs are also available and are very thorough. 137 | 138 | 139 | ### FXTrayIcon on Windows 10's tray 140 | 141 | ![FXTrayIcon example](./img/fxtrayicon-1.png) 142 | 143 | Above is an example of FXTrayIcon running on Windows 10, of course, you choose your own icon file. 144 | Here we used a link icon from [Icons8](https://www.icons8.com), they provide thousands of amazing 145 | icons for developers, both free (with an attribution) and paid. 146 | 147 | ### Context Menu - uses JavaFX MenuItem 148 | 149 | ![FXTrayIcon menu example](./img/fxtrayicon-2.png) 150 | 151 | An example of FXTrayIcon's custom context menu, built using JavaFX MenuItems. 152 | Surprise, surprise, JavaFX MenuItems get translated into AWT MenuItems by FXTrayIcon, 153 | so there's no need to use those! A developer can work solely with JavaFX Menus and MenuItems. 154 | 155 | ### Tray notifications 156 | 157 | The following can be used to show notifications. Note that the `showMessage()` method 158 | uses the icon from FXTrayIcon in the notification, while the others use different icons 159 | to indicate the level of severity of the message. 160 | 161 | - `showMessage(String caption, String content)` 162 | - or `showMessage(String content)` 163 | 164 | ![showMessage](./img/showDefault.png) 165 | 166 | - `showInfoMessage(String caption, String content)` 167 | - or `showInfoMessage(String content)` 168 | 169 | ![showInfoMessage](./img/showInfo.png) 170 | 171 | - `showWarnMessage(String caption, String content)` 172 | - or `showWarnMessage(String content)` 173 | 174 | ![showWarnMessage](./img/showWarn.png) 175 | 176 | - `showErrorMessage(String caption, String content)` 177 | - or `showErrorMessage(String content)` 178 | 179 | ![showErrorMessage](./img/showError.png) 180 | 181 | ## Supported operating systems 182 | 183 | | OS | Support Status | Unsupported Features | 184 | |------------|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 185 | | Windows 11 | Fully supported | N/A | 186 | | Mac OS | Partially supported | In the `displayMessage()` methods. Custom notification icons are not supported in AppleScript calls, but the TrayIcon is. | 187 | | Linux | Partially supported | Some desktop environments that support `java.awt.SystemTray` are supported. Many are **not**. You should not rely on the `isSupported` method as a matter of truth, testing on individual desktop environments is strongly encouraged. | 188 | 189 | Call `FXTrayIcon.isSupported()` to see if the current platform 190 | supports the system tray. 191 | 192 | ### Access to TrayIcon 193 | 194 | Being a JavaFX library, much care has gone into keeping the AWT portions of the library out of sight within your IDE while using FXTrayIcon. However, we realize that there are situations where it would be useful to have access to the 195 | underlying TrayIcon awt object, so this can be done in two different ways. 196 | 197 | - You can extend FXTrayIcon and in that extended class, you can access the `getTrayIcon()` protected method. 198 | - Once you have FXTrayIcon instantiated, you can call the `getRestricted()` method then gain access to the TrayIcon object through that method. 199 | 200 | ### About icon sizes 201 | The nature of how FXTrayIcon needing to be a library that works side by side with Swing, because we still do not 202 | have a native JavaFX means for utilizing the system tray, icon sizing can be problematic with different operating systems. 203 | If you use the methods that do not require you to specify the icon size, then FXTrayIcon will use the best 204 | size for whichever operating system you're running it on. Windows requires a slightly smaller size than Macs. 205 | 206 | This animation feature does not have any options for specifying the size of the icon because it is best to just 207 | let it use the defaults. However, if you still want to control the size of the icon and the animation icon, 208 | then you can override the defauoy by using: 209 | 210 | ```Java 211 | .setIconSize(width, height); 212 | .setIconSize(oneValueWH); 213 | ``` 214 | 215 | Then those values will become the default icon size that the Builder uses anywhere an icon size isn't required, 216 | and also the animation feature will use those values. 217 | 218 | You can use that method in the build statement or after instantiation. The Builder will not build anything until 219 | the end so that you have an opportunity to change those values if desired. 220 | 221 | ## Projects using `FXTrayIcon` 222 | 223 | - [JDKMon](https://github.com/HanSolo/JDKMon) - A tool that monitors your installed JDK's and informs you about updates. 224 | - [GlucoStatusFX](https://github.com/HanSolo/glucostatusfx) - Glucose status monitor for Nightscout implemented in JavaFX. 225 | - [GistFX](https://github.com/RedmondSims/GistFX) - A utility that makes managing and organizing your GitHub Gists easy and convenient. 226 | - [NFC4PC](https://github.com/martinpaljak/NFC4PC) - Makes your desktop PC react to NFC tags by opening them just like a mobile phone. 227 | - [JFXCentral](https://www.jfx-central.com/) - Home to everything JavaFX related. Website is written in JavaFX with [JPro](https://www.jpro.one/) - Desktop Version uses FXTrayIcon. 228 | 229 | If your project uses FXTrayIcon, let us know via Pull Request, and we'll feature your project on this README. 230 | -------------------------------------------------------------------------------- /img/FXTCheck.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/img/FXTCheck.gif -------------------------------------------------------------------------------- /img/animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/img/animation.gif -------------------------------------------------------------------------------- /img/fxtrayicon-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/img/fxtrayicon-1.png -------------------------------------------------------------------------------- /img/fxtrayicon-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/img/fxtrayicon-2.png -------------------------------------------------------------------------------- /img/showDefault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/img/showDefault.png -------------------------------------------------------------------------------- /img/showError.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/img/showError.png -------------------------------------------------------------------------------- /img/showInfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/img/showInfo.png -------------------------------------------------------------------------------- /img/showWarn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/img/showWarn.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | com.dustinredmond.fxtrayicon 7 | FXTrayIcon 8 | 4.2.2 9 | 10 | FXTrayIcon 11 | Easily add system tray icons to JavaFX projects 12 | https://github.com/dustinkredmond/FXTrayIcon 13 | 14 | 15 | 16 | The MIT License 17 | http://opensource.org/licenses/MIT 18 | 19 | 20 | 21 | 22 | 23 | Dustin Redmond 24 | dustin@dustinredmond.com 25 | 26 | 27 | 28 | 29 | UTF-8 30 | 31 | 32 | 33 | scm:git:git://github.com/dustinkredmond/FXTrayIcon.git 34 | scm:git:git@github.com:dustinkredmond/FXTrayIcon.git 35 | https://github.com/dustinkredmond/FXTrayIcon 36 | HEAD 37 | 38 | 39 | 40 | 41 | junit 42 | junit 43 | 4.13.2 44 | test 45 | 46 | 47 | 48 | org.openjfx 49 | javafx-controls 50 | 19 51 | 52 | 53 | org.openjfx 54 | javafx-swing 55 | 19 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | release-sign-artifacts 64 | 65 | 66 | performRelease 67 | true 68 | 69 | 70 | 71 | 72 | 73 | org.apache.maven.plugins 74 | maven-gpg-plugin 75 | 3.0.1 76 | 77 | 78 | sign-artifacts 79 | verify 80 | 81 | sign 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | ossrh 94 | https://oss.sonatype.org/content/repositories/snapshots 95 | 96 | 97 | ossrh 98 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 99 | 100 | 101 | 102 | 103 | 104 | 105 | org.apache.maven.plugins 106 | maven-compiler-plugin 107 | 3.10.1 108 | 109 | 11 110 | 11 111 | 112 | 113 | 114 | default-testCompile 115 | none 116 | 117 | 118 | 119 | 120 | 121 | org.apache.maven.plugins 122 | maven-deploy-plugin 123 | 3.0.0-M2 124 | 125 | 126 | default-deploy 127 | deploy 128 | 129 | deploy 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | org.apache.maven.plugins 138 | maven-release-plugin 139 | 3.0.0-M5 140 | 141 | true 142 | false 143 | forked-path 144 | -Dgpg.passphrase=${gpg.passphrase} 145 | 146 | 147 | 148 | org.apache.maven.scm 149 | maven-scm-provider-gitexe 150 | 2.0.0-M1 151 | 152 | 153 | 154 | 155 | 156 | 157 | org.sonatype.plugins 158 | nexus-staging-maven-plugin 159 | 1.6.13 160 | true 161 | 162 | ossrh 163 | https://oss.sonatype.org/ 164 | false 165 | 166 | 167 | 168 | 169 | 170 | org.apache.maven.plugins 171 | maven-source-plugin 172 | 3.2.1 173 | 174 | 175 | attach-sources 176 | 177 | jar 178 | 179 | 180 | 181 | 182 | com.dustinkredmond.fxtrayicon 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | org.apache.maven.plugins 193 | maven-javadoc-plugin 194 | 3.4.0 195 | 196 | UTF-8 197 | 198 | 199 | 200 | attach-javadoc 201 | 202 | jar 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | org.apache.maven.plugins 211 | maven-gpg-plugin 212 | 3.0.1 213 | 214 | 215 | sign-artifact 216 | verify 217 | 218 | sign 219 | 220 | 221 | 222 | 223 | 224 | org.apache.maven.plugins 225 | maven-surefire-plugin 226 | 3.0.0-M6 227 | 228 | 229 | **/*.java 230 | 231 | 232 | 233 | 234 | 235 | 236 | -------------------------------------------------------------------------------- /src/main/java/com/dustinredmond/fxtrayicon/AWTUtils.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin K. Redmond & contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | import java.awt.*; 26 | import java.util.StringJoiner; 27 | import javafx.application.Platform; 28 | import javafx.event.ActionEvent; 29 | import javafx.scene.control.CheckMenuItem; 30 | 31 | class AWTUtils { 32 | 33 | /** 34 | * Converts a JavaFX MenuItem to a AWT MenuItem 35 | * @param fxItem The JavaFX MenuItem 36 | * @return The converted AWT MenuItem 37 | * @throws UnsupportedOperationException If the user 38 | * has called methods on the JavaFX MenuItem which are 39 | * unable to be replicated using AWT or other means. 40 | */ 41 | protected static MenuItem convertFromJavaFX(javafx.scene.control.MenuItem fxItem) 42 | throws UnsupportedOperationException { 43 | MenuItem awtItem; 44 | final String menuItemText = fxItem.getText() != null ? fxItem.getText() : ""; 45 | if (fxItem instanceof CheckMenuItem) { 46 | CheckboxMenuItem checkboxMenuItem = new CheckboxMenuItem(menuItemText); 47 | checkboxMenuItem.setState(((CheckMenuItem) fxItem).isSelected()); 48 | if (fxItem.getOnAction() != null) { 49 | checkboxMenuItem.addItemListener(e -> Platform.runLater(() -> { 50 | CheckMenuItem fxCheck = (CheckMenuItem) fxItem; 51 | fxCheck.setSelected(checkboxMenuItem.getState()); // sync AWT -> FX 52 | fxCheck.getOnAction().handle(new ActionEvent()); // trigger FX handler 53 | })); 54 | } 55 | awtItem = checkboxMenuItem; 56 | ((CheckMenuItem) fxItem).selectedProperty().addListener(e -> ((CheckboxMenuItem) awtItem).setState(((CheckMenuItem) fxItem).isSelected())); 57 | } else { 58 | 59 | awtItem = new MenuItem(menuItemText); 60 | } 61 | 62 | // some JavaFX to AWT translations aren't possible/supported 63 | // build list of which unsupported methods have been called on 64 | // the passed JavaFX MenuItem 65 | StringJoiner sj = new StringJoiner(","); 66 | if (fxItem.getGraphic() != null) { 67 | sj.add("setGraphic()"); 68 | } 69 | if (fxItem.getAccelerator() != null) { 70 | sj.add("setAccelerator()"); 71 | } 72 | if (fxItem.getCssMetaData().size() > 0) { 73 | sj.add("getCssMetaData().add()"); 74 | } 75 | if (fxItem.getOnMenuValidation() != null) { 76 | sj.add("setOnMenuValidation()"); 77 | } 78 | if (fxItem.getStyle() != null) { 79 | sj.add("setStyle()"); 80 | } 81 | String errors = sj.toString(); 82 | if (!errors.isEmpty()) { 83 | throw new UnsupportedOperationException(String.format( 84 | "The following methods were called on the " + 85 | "passed JavaFX MenuItem (%s), these methods are not " + 86 | "supported by FXTrayIcon.", errors)); 87 | } 88 | 89 | // Set the onAction event to be performed via ActionListener action 90 | if (fxItem.getOnAction() != null) { 91 | awtItem.addActionListener(e -> Platform 92 | .runLater(() -> fxItem.getOnAction().handle(new ActionEvent()))); 93 | } 94 | // Disable the MenuItem if the FX item is disabled 95 | awtItem.setEnabled(!fxItem.isDisable()); 96 | 97 | fxItem.disableProperty().addListener(e -> awtItem.setEnabled(!fxItem.isDisable())); 98 | 99 | fxItem.textProperty().addListener(e -> awtItem.setLabel(fxItem.getText())); 100 | 101 | return awtItem; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/dustinredmond/fxtrayicon/Animation.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin K. Redmond & contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | import javafx.animation.KeyFrame; 27 | import javafx.animation.Timeline; 28 | import javafx.util.Duration; 29 | 30 | import java.awt.*; 31 | import java.util.LinkedList; 32 | 33 | /** 34 | * This class is documented in the FXTrayIcon classes Builder class. 35 | * The commands are documented in the FXTrayIcon class 36 | */ 37 | class Animation { 38 | 39 | private final LinkedList imageList; 40 | private final int frameRateMS; 41 | private final FXTrayIcon trayIcon; 42 | private final Timeline timeline; 43 | 44 | private Timeline getTimeline() { 45 | Timeline timeline = new Timeline(); 46 | timeline.getKeyFrames().add(new KeyFrame(Duration.millis(frameRateMS), e -> updateImage())); 47 | timeline.setCycleCount(javafx.animation.Animation.INDEFINITE); 48 | return timeline; 49 | } 50 | 51 | private void updateImage() { 52 | Image image = imageList.removeFirst(); 53 | trayIcon.setAnimationFrame(image); 54 | imageList.addLast(image); 55 | } 56 | 57 | Animation(FXTrayIcon trayIcon, LinkedList imageList, int frameRateMS) { 58 | this.imageList = imageList; 59 | this.frameRateMS = frameRateMS; 60 | this.trayIcon = trayIcon; 61 | this.timeline = this.getTimeline(); 62 | } 63 | 64 | public Timeline timeline() { 65 | return timeline; 66 | } 67 | 68 | public void playFromStart() { 69 | timeline.playFromStart(); 70 | } 71 | 72 | public void play() { 73 | timeline.play(); 74 | } 75 | 76 | public void pause() { 77 | timeline.pause(); 78 | } 79 | 80 | public void stop() { 81 | timeline.stop(); 82 | } 83 | 84 | public boolean isRunning() { 85 | return timeline.getStatus().equals(javafx.animation.Animation.Status.RUNNING); 86 | } 87 | 88 | public boolean isPaused() { 89 | return timeline.getStatus().equals(javafx.animation.Animation.Status.PAUSED); 90 | } 91 | 92 | public boolean isStopped() { 93 | return timeline.getStatus().equals(javafx.animation.Animation.Status.STOPPED); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/dustinredmond/fxtrayicon/BuildOrderUtil.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin K. Redmond & contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | import javafx.scene.control.Menu; 26 | import javafx.scene.control.MenuItem; 27 | 28 | import java.util.HashMap; 29 | import java.util.Map; 30 | 31 | class BuildOrderUtil { 32 | 33 | private static Integer index = 0; 34 | private static final Map objectMap = new HashMap<>(); 35 | 36 | /** 37 | * Used by Builder class to add a {@code javafx.scene.control.Menu} 38 | * object into FXTrayIcon, maintaining the order in which it is added 39 | * within the build sentence. 40 | * @param menu a {@code javafx.scene.control.Menu} object 41 | */ 42 | static void addMenu(Menu menu) { 43 | objectMap.put(index, new MenuObject(menu)); 44 | index++; 45 | } 46 | 47 | /** 48 | * Used by Builder class to add a {@code javafx.scene.control.MenuItem} 49 | * object into FXTrayIcon, maintaining the order in which it is added 50 | * within the build sentence. 51 | * @param menuItem a {@code javafx.scene.control.MenuItem} object 52 | */ 53 | static void addMenuItem(MenuItem menuItem) { 54 | objectMap.put(index, new MenuObject(menuItem)); 55 | index++; 56 | } 57 | 58 | /** 59 | * Used by Builder class to add many {@code javafx.scene.control.MenuItem} 60 | * objects into FXTrayIcon, maintaining the order in which it is added 61 | * within the build sentence. 62 | * @param menuItems an array of {@code javafx.scene.control.MenuItem} objects 63 | */ 64 | static void addMenuItems(MenuItem... menuItems) { 65 | for(MenuItem menuItem : menuItems) { 66 | addMenuItem(menuItem); 67 | } 68 | } 69 | 70 | /** 71 | * Used by Builder class to add a separator object to FXTrayIcon while 72 | * maintaining the order in which the separator was added in the build sentence. 73 | */ 74 | static void addSeparator() { 75 | objectMap.put(index, new MenuObject()); 76 | index++; 77 | } 78 | 79 | /** 80 | * Used by the Builder class to get the number of objects that were 81 | * passed via the build sentence. Used for iteration to extract each 82 | * object then add it into FXTrayIcon after instantiation. 83 | */ 84 | static Integer getItemCount() { 85 | return index; //since current index value is not used, this number is accurate 86 | } 87 | 88 | /** 89 | * Used by the Builder class during iteration of the objects that are 90 | * stored in this class. 91 | * @param index an Integer 92 | */ 93 | static Menu getMenu(Integer index) { 94 | return objectMap.get(index).getMenu(); 95 | } 96 | 97 | /** 98 | * Used by the Builder class during iteration of the objects that are 99 | * stored in this class. 100 | * @param index an Integer 101 | */ 102 | static MenuItem getMenuItem(Integer index) { 103 | return objectMap.get(index).getMenuItem(); 104 | } 105 | 106 | /** 107 | * Used by the Builder class during iteration of the objects that are 108 | * stored in this class. 109 | * @param index an Integer 110 | */ 111 | static ItemType getItemType(Integer index) { 112 | return objectMap.get(index).getItemType(); 113 | } 114 | 115 | /** 116 | * This is a pseudo record class that is used by class 117 | * BuildOrderUtil in a Map, so that the objects that are passed 118 | * to Builder in the build sentence can have their serial 119 | * order maintained. 120 | */ 121 | private static class MenuObject { 122 | 123 | private Menu menu; 124 | private MenuItem menuItem; 125 | private final ItemType itemType; 126 | 127 | /** 128 | * class constructor that only accepts a {@code javafx.scene.control.Menu} object 129 | * @param menu a {@code javafx.scene.control.Menu} object 130 | */ 131 | MenuObject(Menu menu) { 132 | this.menu = menu; 133 | this.itemType = ItemType.MENU; 134 | } 135 | 136 | /** 137 | * class constructor that only accepts a {@code javafx.scene.control.MenuItem} object 138 | * @param menuItem a {@code javafx.scene.control.MenuItem} object 139 | */ 140 | MenuObject(MenuItem menuItem) { 141 | this.menuItem = menuItem; 142 | this.itemType = ItemType.MENU_ITEM; 143 | } 144 | 145 | /** 146 | * Default class constructor, used to track when the Builder build sentence 147 | * had a separator passed into the Builder class. 148 | */ 149 | MenuObject() { 150 | this.itemType = ItemType.SEPARATOR; 151 | } 152 | 153 | /** 154 | * @return ItemType 155 | */ 156 | ItemType getItemType() { 157 | return itemType; 158 | } 159 | 160 | /** 161 | * @return {@code javafx.scene.control.Menu} object 162 | */ 163 | Menu getMenu() { 164 | return menu; 165 | } 166 | 167 | /** 168 | * @return {@code javafx.scene.control.MenuItem} object 169 | */ 170 | MenuItem getMenuItem() { 171 | return menuItem; 172 | } 173 | 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src/main/java/com/dustinredmond/fxtrayicon/IconScale.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | public class IconScale { 4 | 5 | private final int width; 6 | private final int height; 7 | 8 | public IconScale(int width, int height) { 9 | this.width = width; 10 | this.height = height; 11 | } 12 | 13 | public IconScale(int sizeWH) { 14 | this.width = sizeWH; 15 | this.height = sizeWH; 16 | } 17 | 18 | public int width() { 19 | return width; 20 | } 21 | 22 | public int height() { 23 | return height; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/dustinredmond/fxtrayicon/ItemType.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin K. Redmond & contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | enum ItemType { 26 | MENU, 27 | MENU_ITEM, 28 | SEPARATOR 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/dustinredmond/fxtrayicon/Restricted.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin K. Redmond & contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | import java.awt.*; 26 | 27 | /** 28 | * This is a package local class 29 | */ 30 | class Restricted implements RestrictedInterface { 31 | 32 | /** 33 | * This is the working instantiation of the TrayIcon object. 34 | * This is the only instantiation that will exist for any 35 | * instantiation of the FXTrayIcon class. 36 | */ 37 | private final TrayIcon trayIcon; 38 | 39 | /** 40 | * Class Constructor used by FXTrayIcon class 41 | */ 42 | public Restricted(Image image, String title, PopupMenu popupMenu ) { 43 | this.trayIcon = new TrayIcon(image, title, popupMenu); 44 | } 45 | 46 | /** 47 | * public getter for the trayIcon object. This method is only 48 | * obtainable through the getRestricted() method in FXTrayIcon class. 49 | */ 50 | @Override 51 | public TrayIcon getTrayIcon() { 52 | return trayIcon; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/dustinredmond/fxtrayicon/RestrictedInterface.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | import java.awt.*; 4 | 5 | public interface RestrictedInterface { 6 | 7 | public TrayIcon getTrayIcon(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/dustinredmond/fxtrayicon/annotations/API.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon.annotations; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin K. Redmond & contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | import java.lang.annotation.ElementType; 26 | import java.lang.annotation.Retention; 27 | import java.lang.annotation.RetentionPolicy; 28 | import java.lang.annotation.Target; 29 | 30 | /** 31 | * Annotation to indicate public API for FXTrayIcon 32 | * This annotation is not retained at runtime, and 33 | * is only to ease developmental determination of 34 | * publicly available API. 35 | *

Some IDEs allow disabling warnings for unused 36 | * methods with a certain annotation. This is the primary 37 | * purpose for this annotation.

38 | */ 39 | @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR}) 40 | @Retention(RetentionPolicy.SOURCE) 41 | public @interface API { 42 | /** 43 | * Optionally, describes the version in which the API was added. 44 | * @return The version in which the API was added or an empty String 45 | * if one is not provided. 46 | */ 47 | @SuppressWarnings("unused") String version() default ""; 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * FXTrayIcon java 9+ JPMS compatible 3 | */ 4 | module com.dustinredmond.fxtrayicon{ 5 | requires javafx.controls; 6 | requires java.desktop; 7 | requires javafx.swing; 8 | requires javafx.graphics; 9 | 10 | 11 | exports com.dustinredmond.fxtrayicon; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/resources/com/dustinredmond/fxtrayicon/FXIconBlueWhite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/main/resources/com/dustinredmond/fxtrayicon/FXIconBlueWhite.png -------------------------------------------------------------------------------- /src/main/resources/com/dustinredmond/fxtrayicon/FXIconBlueYellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/main/resources/com/dustinredmond/fxtrayicon/FXIconBlueYellow.png -------------------------------------------------------------------------------- /src/main/resources/com/dustinredmond/fxtrayicon/FXIconGreenWhite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/main/resources/com/dustinredmond/fxtrayicon/FXIconGreenWhite.png -------------------------------------------------------------------------------- /src/main/resources/com/dustinredmond/fxtrayicon/FXIconGreenYellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/main/resources/com/dustinredmond/fxtrayicon/FXIconGreenYellow.png -------------------------------------------------------------------------------- /src/main/resources/com/dustinredmond/fxtrayicon/FXIconRedWhite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/main/resources/com/dustinredmond/fxtrayicon/FXIconRedWhite.png -------------------------------------------------------------------------------- /src/main/resources/com/dustinredmond/fxtrayicon/FXIconRedYellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/main/resources/com/dustinredmond/fxtrayicon/FXIconRedYellow.png -------------------------------------------------------------------------------- /src/main/resources/com/dustinredmond/fxtrayicon/i-Icon-Glass-Blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/main/resources/com/dustinredmond/fxtrayicon/i-Icon-Glass-Blue.png -------------------------------------------------------------------------------- /src/main/resources/com/dustinredmond/fxtrayicon/i-Icon-Glass-Blue2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/main/resources/com/dustinredmond/fxtrayicon/i-Icon-Glass-Blue2.png -------------------------------------------------------------------------------- /src/main/resources/com/dustinredmond/fxtrayicon/i-Icon-Glass-Green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/main/resources/com/dustinredmond/fxtrayicon/i-Icon-Glass-Green.png -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/CheckIsSupportedByPlatform.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin Redmond and contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | public class CheckIsSupportedByPlatform { 25 | public static boolean isWindows() { 26 | return System.getProperty("os.name").startsWith("Windows"); 27 | } 28 | 29 | public static boolean isMacOS() { 30 | final String os = System.getProperty("os.name"); 31 | return os.contains("mac") || os.contains("darwin"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/CheckMenu.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin Redmond and contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | import javafx.application.Application; 26 | import javafx.scene.control.CheckMenuItem; 27 | import javafx.stage.Stage; 28 | 29 | import java.util.List; 30 | 31 | public class CheckMenu extends Application { 32 | 33 | CheckMenuItem cmuApples = new CheckMenuItem("Apples"); 34 | CheckMenuItem cmuOranges = new CheckMenuItem("Oranges"); 35 | CheckMenuItem cmuPears = new CheckMenuItem("Pears"); 36 | 37 | @Override 38 | public void start(Stage primaryStage) { 39 | primaryStage.setTitle("Default Icon"); 40 | 41 | FXTrayIcon fxti = new FXTrayIcon.Builder(primaryStage) 42 | .show() 43 | .build(); 44 | 45 | cmuApples.setOnAction(e -> { 46 | List list = fxti.getCheckMenuItems(); 47 | for (java.awt.CheckboxMenuItem cbmi : list) { 48 | if (!cbmi.getLabel().equals("Apples")) { 49 | cbmi.setState(false); 50 | } 51 | } 52 | }); 53 | 54 | cmuOranges.setOnAction(e -> { 55 | fxti.getCheckMenuItem("Pears").setState(false); 56 | fxti.getCheckMenuItem("Apples").setState(false); 57 | }); 58 | 59 | cmuPears.setOnAction(e -> { 60 | fxti.getCheckMenuItem("Oranges").setState(false); 61 | fxti.getCheckMenuItem("Apples").setState(false); 62 | }); 63 | 64 | fxti.addMenuItem(cmuApples); 65 | fxti.addMenuItem(cmuOranges); 66 | fxti.addMenuItem(cmuPears); 67 | } 68 | 69 | public static void main(String[] args) { 70 | launch(args); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/CheckMenuBuilder.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | import javafx.application.Application; 4 | import javafx.stage.Stage; 5 | import java.util.List; 6 | 7 | /* 8 | * Copyright (c) 2022 Dustin Redmond and contributors 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in all 18 | * copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | public class CheckMenuBuilder extends Application { 30 | 31 | FXTrayIcon fxti; 32 | 33 | @Override 34 | public void start(Stage primaryStage) { 35 | primaryStage.setTitle("Default Icon"); 36 | 37 | fxti = new FXTrayIcon.Builder(primaryStage) 38 | .checkMenuItem("Apples", e-> checkApples()) 39 | .checkMenuItem("Oranges", e-> checkOranges()) 40 | .checkMenuItem("Pears", e-> checkPears()) 41 | .separator() 42 | .addExitMenuItem() 43 | .show() 44 | .build(); 45 | 46 | } 47 | 48 | private void checkApples() { 49 | List list = fxti.getCheckMenuItems(); 50 | for (java.awt.CheckboxMenuItem cbmi : list) { 51 | if (!cbmi.getLabel().equals("Apples")) { 52 | cbmi.setState(false); 53 | } 54 | } 55 | } 56 | 57 | private void checkOranges() { 58 | fxti.getCheckMenuItem("Pears").setState(false); 59 | fxti.getCheckMenuItem("Apples").setState(false); 60 | } 61 | 62 | private void checkPears() { 63 | fxti.getCheckMenuItem("Oranges").setState(false); 64 | fxti.getCheckMenuItem("Apples").setState(false); 65 | } 66 | 67 | public static void main(String[] args) { 68 | launch(args); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/DefaultIconTest.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | import javafx.application.Application; 4 | import javafx.stage.Stage; 5 | 6 | /* 7 | * Copyright (c) 2022 Dustin Redmond and contributors 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in all 17 | * copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | * SOFTWARE. 26 | */ 27 | 28 | public class DefaultIconTest extends Application { 29 | 30 | @Override 31 | public void start(Stage primaryStage) { 32 | primaryStage.setTitle("Default Icon"); 33 | 34 | new FXTrayIcon 35 | .Builder(primaryStage) 36 | .menuItem("Option 1", e -> menu1()) 37 | .menuItem("Option 2", e -> menu2()) 38 | .separator() 39 | .menuItem("Exit", e -> System.exit(0)) 40 | .show() 41 | .build(); 42 | } 43 | 44 | private void menu1() {System.out.println("Option 1");} 45 | private void menu2() {System.out.println("Option 2");} 46 | 47 | public static void main(String[] args) { 48 | launch(args); 49 | } 50 | } -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/MultipleItemsOneLine.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | import javafx.application.Application; 4 | import javafx.stage.Stage; 5 | 6 | /* 7 | * Copyright (c) 2022 Dustin Redmond and contributors 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in all 17 | * copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | * SOFTWARE. 26 | */ 27 | 28 | public class MultipleItemsOneLine extends Application { 29 | 30 | @Override 31 | public void start(Stage primaryStage) { 32 | primaryStage.setTitle("Many From One"); 33 | new FXTrayIcon 34 | .Builder(primaryStage) 35 | .menuItem("Option 1", e -> menu1()) 36 | .menuItem("Option 2", e -> menu2()) 37 | .separator() 38 | .menuItem("Exit", e -> System.exit(0)) 39 | .show() 40 | .build(); 41 | } 42 | 43 | private void menu1() {System.out.println("Option 1");} 44 | private void menu2() {System.out.println("Option 2");} 45 | 46 | public static void main(String[] args) { 47 | launch(args); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/NestedSubMenus.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | import javafx.application.Application; 4 | import javafx.application.Platform; 5 | import javafx.event.ActionEvent; 6 | import javafx.event.EventHandler; 7 | import javafx.geometry.Insets; 8 | import javafx.scene.Scene; 9 | import javafx.scene.control.Label; 10 | import javafx.scene.control.MenuItem; 11 | import javafx.scene.control.SplitPane; 12 | import javafx.scene.control.TextField; 13 | import javafx.scene.layout.VBox; 14 | import javafx.stage.Stage; 15 | 16 | /* 17 | * Copyright (c) 2022 Dustin Redmond and contributors 18 | * 19 | * Permission is hereby granted, free of charge, to any person obtaining a copy 20 | * of this software and associated documentation files (the "Software"), to deal 21 | * in the Software without restriction, including without limitation the rights 22 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | * copies of the Software, and to permit persons to whom the Software is 24 | * furnished to do so, subject to the following conditions: 25 | * 26 | * The above copyright notice and this permission notice shall be included in all 27 | * copies or substantial portions of the Software. 28 | * 29 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 35 | * SOFTWARE. 36 | */ 37 | 38 | public class NestedSubMenus extends Application { 39 | 40 | 41 | private Label lblRightMessage; 42 | private Label lblLeftMessage; 43 | private TextField tfLeftMessage; 44 | private TextField tfRightMessage; 45 | 46 | @Override public void start(Stage stage) throws Exception { 47 | SplitPane splitPane; 48 | Label lblRight = new Label("Right Side"); 49 | Label lblLeft = new Label("Left Side"); 50 | lblRightMessage = new Label(); 51 | lblLeftMessage = new Label(); 52 | Label lblRightText = new Label("Type message, then use tray menu to send it to the left"); 53 | Label lblLeftText = new Label("Type message, then use tray menu to send it to the right"); 54 | tfLeftMessage = new TextField(); 55 | tfRightMessage = new TextField(); 56 | VBox vboxLeft = new VBox(10,lblLeft, tfLeftMessage, lblLeftMessage, lblLeftText); 57 | vboxLeft.setPadding(new Insets(5,15,5,15)); 58 | VBox vboxRight = new VBox(10,lblRight, tfRightMessage, lblRightMessage, lblRightText); 59 | vboxRight.setPadding(new Insets(5,15,5,15)); 60 | splitPane = new SplitPane(vboxLeft, vboxRight); 61 | Scene scene = new Scene(splitPane); 62 | stage.setScene(scene); 63 | 64 | new FXTrayIcon.Builder(stage) 65 | .applicationTitle("Nested Sub Menus") 66 | .addTitleItem(true) 67 | .menu("Send Right", newMenuItem("Send Text", e-> sendTextRight()), newMenuItem("Clear Text", e->clearRightMessage())) 68 | .menu("Send Left", newMenuItem("Send Text", e-> sendTextLeft()), newMenuItem("Clear Text", e->clearLeftMessage())) 69 | .addExitMenuItem() 70 | .show() 71 | .build(); 72 | } 73 | 74 | private MenuItem newMenuItem(String label, EventHandler event) { 75 | MenuItem menuItem = new MenuItem(label); 76 | menuItem.setOnAction(event); 77 | return menuItem; 78 | } 79 | 80 | private void sendTextRight() { 81 | Platform.runLater(() -> lblRightMessage.setText(tfLeftMessage.getText())); 82 | } 83 | 84 | private void sendTextLeft() { 85 | Platform.runLater(() -> lblLeftMessage.setText(tfRightMessage.getText())); 86 | } 87 | 88 | private void clearRightMessage() { 89 | Platform.runLater(() -> lblRightMessage.setText("")); 90 | } 91 | 92 | private void clearLeftMessage() { 93 | Platform.runLater(() -> lblLeftMessage.setText("")); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/RunnableTest.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin K. Redmond & contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | import javafx.application.Application; 26 | import javafx.scene.Scene; 27 | import javafx.scene.control.Alert; 28 | import javafx.scene.control.Button; 29 | import javafx.scene.control.Label; 30 | import javafx.scene.control.Menu; 31 | import javafx.scene.control.MenuItem; 32 | import javafx.scene.layout.BorderPane; 33 | import javafx.scene.layout.HBox; 34 | import javafx.scene.layout.VBox; 35 | import javafx.stage.Stage; 36 | import java.net.URL; 37 | 38 | 39 | /** 40 | * A test of the FXTrayIcon functionality in the form 41 | * of a runnable JavaFX application. Compile and run this 42 | * class to test the features of FXTrayIcon. 43 | */ 44 | public class RunnableTest extends Application { 45 | 46 | @Override 47 | public void start(Stage stage) { 48 | 49 | BorderPane root = new BorderPane(); 50 | stage.setScene(new Scene(root)); 51 | 52 | // By default, our FXTrayIcon will have an entry with our Application's title in bold font, 53 | // when clicked, this MenuItem will call stage.show() 54 | // 55 | // This can be disabled by simply removing the MenuItem after instantiating the FXTrayIcon 56 | // though, by convention, most applications implement this functionality. 57 | stage.setTitle("FXTrayIcon test!"); 58 | 59 | // Instantiate the FXTrayIcon providing the parent Stage and a path to an Image file 60 | FXTrayIcon trayIcon = new FXTrayIcon(stage, getClass().getResource("FXIconRedWhite.png")); 61 | trayIcon.show(); 62 | 63 | // By default the FXTrayIcon's tooltip will be the parent stage's title, that we used in the constructor 64 | // This method can override this 65 | trayIcon.setTrayIconTooltip("An alternative tooltip!"); 66 | 67 | // We can now add JavaFX MenuItems to the menu 68 | MenuItem menuItemTest = new MenuItem("Create some JavaFX component!"); 69 | menuItemTest.setOnAction(e -> 70 | new Alert(Alert.AlertType.INFORMATION, "We just ran some JavaFX code from an AWT MenuItem!").showAndWait()); 71 | trayIcon.addMenuItem(menuItemTest); 72 | 73 | // We can also nest menus, below is an Options menu with sub-items 74 | Menu menuOptions = new Menu("Options"); 75 | MenuItem miOn = new MenuItem("On"); 76 | miOn.setOnAction(e -> System.out.println("Options -> On clicked")); 77 | MenuItem miOff = new MenuItem("Off"); 78 | miOff.setOnAction(e -> System.out.println("Options -> Off clicked")); 79 | menuOptions.getItems().addAll(miOn, miOff); 80 | trayIcon.addMenuItem(menuOptions); 81 | 82 | VBox vBox = new VBox(5); 83 | vBox.getChildren().add(new Label("You should see a tray icon!\nTry closing this window " + 84 | "and double-clicking the icon.\n" + 85 | "Try single-clicking it.")); 86 | Button buttonRemoveTrayIcon = new Button("Remove TrayIcon"); 87 | vBox.getChildren().add(buttonRemoveTrayIcon); 88 | 89 | // Removing the FXTrayIcon, this will also cause the JVM to terminate 90 | // after the last JavaFX Stage is hidden 91 | buttonRemoveTrayIcon.setOnAction(e -> trayIcon.hide()); 92 | 93 | Button buttonDefaultMsg = new Button("Show a \"Default\" message"); 94 | // showDefaultMessage uses the FXTrayIcon image in the notification 95 | buttonDefaultMsg.setOnAction(e -> trayIcon.showMessage("A caption text", "Some content text.")); 96 | 97 | Button buttonInfoMsg = new Button("Show a \"Info\" message"); 98 | // other showXXX methods use an icon appropriate for the message type 99 | buttonInfoMsg.setOnAction(e -> trayIcon.showInfoMessage("A caption text", "Some content text")); 100 | 101 | Button buttonWarnMsg = new Button("Show a \"Warn\" message"); 102 | buttonWarnMsg.setOnAction(e -> trayIcon.showWarningMessage("A caption text", "Some content text")); 103 | 104 | Button buttonErrorMsg = new Button("Show a \"Error\" message"); 105 | buttonErrorMsg.setOnAction(e -> trayIcon.showErrorMessage("A caption text", "Some content text")); 106 | 107 | HBox hBox = new HBox(5, buttonDefaultMsg, buttonInfoMsg, buttonWarnMsg, buttonErrorMsg); 108 | vBox.getChildren().add(hBox); 109 | 110 | root.setCenter(vBox); 111 | stage.sizeToScene(); 112 | stage.show(); 113 | } 114 | 115 | /** 116 | * Test icon used for FXTrayIcon runnable tests 117 | * 118 | * @return URL to an example icon PNG 119 | */ 120 | public URL getIcon() { 121 | return getClass().getResource("FXIconRedWhite.png"); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/TestAddDefaultMenuItem.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin K. Redmond & contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | import javafx.application.Application; 26 | import javafx.stage.Stage; 27 | 28 | public class TestAddDefaultMenuItem extends Application { 29 | 30 | @Override 31 | public void start(Stage primaryStage) throws Exception { 32 | primaryStage.setTitle("My App"); 33 | 34 | FXTrayIcon icon = new FXTrayIcon(primaryStage, getClass().getResource("FXIconRedWhite.png")); 35 | icon.addTitleItem(true); 36 | icon.addExitItem(true); 37 | icon.show(); 38 | } 39 | 40 | public static void main(String[] args) { 41 | Application.launch(TestAddDefaultMenuItem.class, args); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/TestBareFXTrayIcon.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin K. Redmond & contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | import javafx.application.Application; 26 | import javafx.stage.Stage; 27 | 28 | public class TestBareFXTrayIcon extends Application { 29 | 30 | @Override 31 | public void start(Stage stage) throws Exception { 32 | stage.setTitle("Test FXTrayIcon with empty menu"); 33 | FXTrayIcon trayIcon = new FXTrayIcon(stage, getClass().getResource("FXIconRedWhite.png")); 34 | trayIcon.show(); 35 | } 36 | 37 | public static void main(String[] args) { 38 | Application.launch(TestBareFXTrayIcon.class); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/TestBuilderClass.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin K. Redmond & contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | import javafx.application.Application; 26 | import javafx.scene.Scene; 27 | import javafx.scene.control.*; 28 | import javafx.scene.layout.BorderPane; 29 | import javafx.scene.layout.HBox; 30 | import javafx.scene.layout.VBox; 31 | import javafx.stage.Stage; 32 | import java.net.URL; 33 | 34 | /** 35 | * A test of the FXTrayIcon functionality in the form 36 | * of a runnable JavaFX application. Compile and run this 37 | * class to test the features of FXTrayIcon. 38 | */ 39 | public class TestBuilderClass extends Application { 40 | 41 | private FXTrayIcon trayIcon = null; 42 | 43 | @Override 44 | public void start(Stage stage) { 45 | 46 | 47 | BorderPane root = new BorderPane(); 48 | stage.setScene(new Scene(root)); 49 | 50 | // By default, our FXTrayIcon will have an entry with our Application's title in bold font, 51 | // when clicked, this MenuItem will call stage.show() 52 | // 53 | // This can be disabled by simply removing the MenuItem after instantiating the FXTrayIcon 54 | // though, by convention, most applications implement this functionality. 55 | stage.setTitle("FXTrayIcon Test Builder Class!"); 56 | stage.setOnCloseRequest(e -> System.exit(0)); 57 | 58 | // We first create the MenuItems that we want to add into FXTrayIcon 59 | MenuItem menuItemTest = new MenuItem("Create some JavaFX component!"); 60 | menuItemTest.setOnAction(e -> new Alert(Alert.AlertType.INFORMATION, "We just ran some JavaFX code from an AWT MenuItem!").showAndWait()); 61 | MenuItem menuExit = new MenuItem("Exit Application"); 62 | menuExit.setOnAction(e -> System.exit(0)); 63 | 64 | 65 | // We can also nest menus, below is an Options menu with sub-items 66 | Menu menuOptions = new Menu("Options"); 67 | MenuItem miOn = new MenuItem("On"); 68 | miOn.setOnAction(e -> System.out.println("Options -> On clicked")); 69 | MenuItem miOff = new MenuItem("Off"); 70 | miOff.setOnAction(e -> System.out.println("Options -> Off clicked")); 71 | menuOptions.getItems().addAll(miOn, miOff); 72 | 73 | VBox vBox = new VBox(5); 74 | vBox.getChildren().add(new Label("You should see a tray icon!\nTry closing this window " + 75 | "and double-clicking the icon.\n" + 76 | "Try single-clicking it.")); 77 | Button buttonRemoveTrayIcon = new Button("Remove TrayIcon"); 78 | vBox.getChildren().add(buttonRemoveTrayIcon); 79 | 80 | 81 | // Removing the FXTrayIcon, this will also cause the JVM to terminate 82 | // after the last JavaFX Stage is hidden 83 | buttonRemoveTrayIcon.setOnAction(e -> trayIcon.hide()); 84 | 85 | Button buttonDefaultMsg = new Button("Show a \"Default\" message"); 86 | // showDefaultMessage uses the FXTrayIcon image in the notification 87 | buttonDefaultMsg.setOnAction(e -> trayIcon.showMessage("A caption text", "Some content text.")); 88 | 89 | Button buttonInfoMsg = new Button("Show a \"Info\" message"); 90 | // other showXXX methods use an icon appropriate for the message type 91 | buttonInfoMsg.setOnAction(e -> trayIcon.showInfoMessage("A caption text", "Some content text")); 92 | 93 | Button buttonWarnMsg = new Button("Show a \"Warn\" message"); 94 | buttonWarnMsg.setOnAction(e -> trayIcon.showWarningMessage("A caption text", "Some content text")); 95 | 96 | Button buttonErrorMsg = new Button("Show a \"Error\" message"); 97 | buttonErrorMsg.setOnAction(e -> trayIcon.showErrorMessage("A caption text", "Some content text")); 98 | 99 | HBox hBox = new HBox(5, buttonDefaultMsg, buttonInfoMsg, buttonWarnMsg, buttonErrorMsg); 100 | vBox.getChildren().add(hBox); 101 | 102 | root.setCenter(vBox); 103 | stage.sizeToScene(); 104 | stage.show(); 105 | 106 | // Once we have built our Stage and Scene, we invoke FXTrayIcons Builder class 107 | // providing it with the parent Stage and a path to an image file. 108 | // The Builder class brings everything together in a single sentence, including 109 | // all of our menus and separators. 110 | 111 | trayIcon = new FXTrayIcon.Builder(stage, getClass().getResource("FXIconRedYellow.png")) 112 | .toolTip("An alternative tooltip!") 113 | .menuItem(menuItemTest) 114 | .menuItem(menuOptions) 115 | .applicationTitle("FXTrayIcon Builder Text") 116 | .separator() 117 | .addExitMenuItem() 118 | .build(); 119 | 120 | trayIcon.show(); 121 | } 122 | 123 | /** 124 | * Test icon used for FXTrayIcon runnable tests 125 | * 126 | * @return URL to an example icon PNG 127 | */ 128 | public URL getIcon() { 129 | return getClass().getResource("FXIconRedYellow.png"); 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/TestFXTrayIcon.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin K. Redmond & contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | import javafx.application.Application; 26 | import javafx.application.Platform; 27 | import javafx.scene.control.Label; 28 | import javafx.scene.control.MenuItem; 29 | import javafx.stage.Stage; 30 | import org.junit.Test; 31 | import java.awt.*; 32 | import static org.junit.Assert.*; 33 | 34 | /** 35 | * Serves as a basic smoke test for FXTrayIcon and associated 36 | * helper classes. 37 | */ 38 | public class TestFXTrayIcon extends Application { 39 | 40 | private static final String TEST_ICON = "FXIconRedWhite.png"; 41 | 42 | /** 43 | * Entry point for runnable tests. 44 | * Determines if we're running the tests in a headless 45 | * environment or an environment without desktop support 46 | * and runs the appropriate tests. 47 | */ 48 | @Test 49 | public void runTestOnFXApplicationThread() { 50 | if (!Desktop.isDesktopSupported()) { 51 | System.err.println("Tests unable to be run on headless environment."); 52 | return; 53 | } 54 | if (System.getenv("CI") != null) { 55 | System.err.println("Tests unable to be run on headless CI platform."); 56 | return; 57 | } 58 | Application.launch(TestFXTrayIcon.class, (String) null); 59 | } 60 | 61 | @Override 62 | public void start(Stage stage) { 63 | testShouldConvertSuccessful(); 64 | testShouldConvertFail(); 65 | testTrayIconSupported(); 66 | testNotNullTestResource(); 67 | testInitialization(); 68 | if (CheckIsSupportedByPlatform.isMacOS() || CheckIsSupportedByPlatform.isWindows()) { 69 | assertTrue(FXTrayIcon.isSupported()); 70 | } 71 | Platform.exit(); 72 | } 73 | 74 | /** 75 | * Test for making sure that we're able to 'convert' a 76 | * JavaFX MenuItem into an AWT MenuItem via AWTUtils.convertFromJavaFX() 77 | */ 78 | @Test public void testShouldConvertSuccessful() { 79 | MenuItem fxItem = new MenuItem("SomeText"); 80 | fxItem.setDisable(true); 81 | fxItem.setOnAction(e -> {/* ignored */}); 82 | 83 | java.awt.MenuItem awtItem = AWTUtils.convertFromJavaFX(fxItem); 84 | assertEquals(fxItem.getText(), awtItem.getLabel()); 85 | assertEquals(fxItem.isDisable(), !awtItem.isEnabled()); 86 | assertEquals(1, awtItem.getActionListeners().length); 87 | } 88 | 89 | /** 90 | * Test that an Exception is thrown when AWTUtils cannot 91 | * translate and AWT MenuItem behavior over to JavaFX MenuItem 92 | */ 93 | @Test public void testShouldConvertFail() { 94 | MenuItem fxItem = new MenuItem(); 95 | fxItem.setGraphic(new Label()); 96 | try { 97 | //noinspection unused 98 | java.awt.MenuItem awtItem = AWTUtils.convertFromJavaFX(fxItem); 99 | fail("Should not be able to assign graphic in AWTUtils"); 100 | } catch (Exception ignored) { /* should always reach here */ } 101 | } 102 | 103 | /** 104 | * Sanity test to make sure that FXTrayIcon.isSupported() does not 105 | * give a different result than java.awt.SystemTray.isSupported() 106 | */ 107 | @Test public void testTrayIconSupported() { 108 | assertEquals(SystemTray.isSupported(), FXTrayIcon.isSupported()); 109 | } 110 | 111 | /** 112 | * Make sure that our test icon is not null. If this fails, other 113 | * tests will not run successfully. 114 | */ 115 | @Test public void testNotNullTestResource() { 116 | try { 117 | assertNotNull(getClass().getResource(TEST_ICON)); 118 | } catch (Exception e) { 119 | fail("Error retrieving resources (FXTrayIcon graphic) for unit tests"); 120 | } 121 | } 122 | 123 | /** 124 | * Stupid sanity test, if this fails for any reason, we have issues. 125 | */ 126 | @Test public void testInitialization() { 127 | if (FXTrayIcon.isSupported()) { 128 | FXTrayIcon icon = new FXTrayIcon(new Stage(), getClass().getResource(TEST_ICON)); 129 | assertNotNull(icon); 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/TestRestrictedAccess.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | import javafx.application.Application; 4 | import javafx.application.Platform; 5 | import javafx.geometry.Pos; 6 | import javafx.scene.Scene; 7 | import javafx.scene.control.Label; 8 | import javafx.scene.layout.VBox; 9 | import javafx.stage.Stage; 10 | 11 | import java.awt.event.MouseEvent; 12 | import java.awt.event.MouseListener; 13 | import java.net.URL; 14 | 15 | public class TestRestrictedAccess extends Application { 16 | 17 | public static void main(String[] args) { 18 | launch(args); 19 | } 20 | 21 | @Override public void start(Stage primaryStage) throws Exception { 22 | createScene(primaryStage); 23 | FXTrayIcon icon = new FXTrayIcon.Builder(primaryStage,getIcon(),24,24) 24 | .menuItem("This does nothing", e->{}) 25 | .separator() 26 | .addExitMenuItem("Exit") 27 | .show() 28 | .build(); 29 | 30 | /** 31 | * This accesses the restricted trayIcon object and adds a right click 32 | * event listener, which when clicked, shows the stage. 33 | */ 34 | icon.getRestricted().getTrayIcon().addMouseListener(new MouseListener() { 35 | 36 | /** 37 | * This event is fired when the mouse is clicked on the tray icon 38 | * @param - MouseEvent 39 | */ 40 | @Override public void mouseClicked(MouseEvent e) { 41 | if(e.getButton() == 3) { 42 | Platform.runLater(() -> { 43 | primaryStage.show(); 44 | }); 45 | } 46 | } 47 | 48 | /** 49 | * Ignored 50 | * @param - MouseEvent 51 | */ 52 | @Override public void mousePressed(MouseEvent ignored) { 53 | 54 | } 55 | 56 | /** 57 | * Ignored 58 | * @param - MouseEvent 59 | */ 60 | @Override public void mouseReleased(MouseEvent ignored) { 61 | 62 | } 63 | 64 | /** 65 | * Ignored 66 | * @param - MouseEvent 67 | */ 68 | @Override public void mouseEntered(MouseEvent ignored) { 69 | 70 | } 71 | 72 | /** 73 | * Ignored 74 | * @param - MouseEvent 75 | */ 76 | @Override public void mouseExited(MouseEvent ignored) { 77 | 78 | } 79 | }); 80 | } 81 | 82 | private void createScene(Stage stage) { 83 | Label label = new Label("Right clicking works!"); 84 | label.setPrefSize(150,55); 85 | label.setAlignment(Pos.CENTER); 86 | VBox box = new VBox(label); 87 | scene = new Scene(box); 88 | stage.setScene(scene); 89 | } 90 | 91 | Scene scene; 92 | 93 | private URL getIcon() { 94 | return getClass().getResource("FXIconRedYellow.png"); 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/TestSwitchIconsOnTheFly.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | /* 4 | * Copyright (c) 2022 Dustin K. Redmond & contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | import javafx.application.Application; 26 | import javafx.collections.FXCollections; 27 | import javafx.collections.ObservableList; 28 | import javafx.scene.Node; 29 | import javafx.scene.Scene; 30 | import javafx.scene.control.Button; 31 | import javafx.scene.control.ChoiceBox; 32 | import javafx.scene.control.Label; 33 | import javafx.scene.control.MenuItem; 34 | import javafx.scene.image.Image; 35 | import javafx.scene.image.ImageView; 36 | import javafx.scene.layout.AnchorPane; 37 | import javafx.scene.layout.HBox; 38 | import javafx.scene.layout.VBox; 39 | import javafx.stage.Stage; 40 | import java.net.URL; 41 | import java.util.Arrays; 42 | import java.util.Random; 43 | 44 | import static javafx.scene.layout.AnchorPane.*; 45 | 46 | public class TestSwitchIconsOnTheFly extends Application { 47 | 48 | AnchorPane root; 49 | 50 | private final String fileName1 = "FXIconRedWhite.png"; 51 | private final String fileName2 = "FXIconRedYellow.png"; 52 | private final String fileName3 = "FXIconBlueWhite.png"; 53 | private final String fileName4 = "FXIconBlueYellow.png"; 54 | private final String fileName5 = "FXIconGreenWhite.png"; 55 | private final String fileName6 = "FXIconGreenYellow.png"; 56 | private final String fileName7 = "i-Icon-Glass-Blue2.png"; 57 | private final String fileName8 = "i-Icon-Glass-Green.png"; 58 | 59 | URL icon1 = getClass().getResource(fileName1); 60 | URL icon2 = getClass().getResource(fileName2); 61 | URL icon3 = getClass().getResource(fileName3); 62 | URL icon4 = getClass().getResource(fileName4); 63 | URL icon5 = getClass().getResource(fileName5); 64 | URL icon6 = getClass().getResource(fileName6); 65 | URL icon7 = getClass().getResource(fileName7); 66 | URL icon8 = getClass().getResource(fileName8); 67 | 68 | private final String name1 = "Red-White"; 69 | private final String name2 = "Red-Yellow"; 70 | private final String name3 = "Blue-White"; 71 | private final String name4 = "Blue-Yellow"; 72 | private final String name5 = "Green-White"; 73 | private final String name6 = "Green-Yellow"; 74 | private final String name7 = "Blue-Glass"; 75 | private final String name8 = "Green-Glass"; 76 | 77 | private FXTrayIcon trayIcon = null; 78 | private final URL[] imageURLs = new URL[]{icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8}; 79 | private final ObservableList nameList = FXCollections.observableArrayList(Arrays.asList(name1, name2, name3, name4, name5, name6, name7, name8)); 80 | public final String style1 = "-fx-background-color: radial-gradient(radius 180%, orange, derive(darkred, -30%), derive(yellow, 30%));"; 81 | public final String style2 = "-fx-background-color: radial-gradient(radius 180%, pink, derive(purple, -30%), derive(purple, 30%));"; 82 | public final String style3 = "-fx-background-color: radial-gradient(radius 180%, yellow, derive(darkorange, -30%), derive(lightsalmon, 30%));"; 83 | 84 | private ImageView iView; 85 | 86 | private void choseRandomIcon() { 87 | Random random = new Random(); 88 | changeIcon(imageURLs[random.nextInt(6)]); 89 | } 90 | 91 | @Override public void start(Stage stage) { 92 | root = new AnchorPane(); 93 | root.setStyle(style3); 94 | stage.setWidth(650); 95 | stage.setHeight(450); 96 | 97 | //Windows likes 16 x 16 icons 98 | 99 | stage.setScene(new Scene(root)); 100 | 101 | // By default, our FXTrayIcon will have an entry with our Application's title in bold font, 102 | // when clicked, this MenuItem will call stage.show() 103 | // 104 | // This can be disabled by simply removing the MenuItem after instantiating the FXTrayIcon 105 | // though, by convention, most applications implement this functionality. 106 | stage.setTitle("FXTrayIcon Switch Icons On The Fly Test"); 107 | 108 | // Instantiate the FXTrayIcon providing the parent Stage and a path to an Image file 109 | MenuItem menuRandom = new MenuItem("Random Icon"); 110 | MenuItem menuExit = new MenuItem("Exit Application"); 111 | menuRandom.setOnAction(e->choseRandomIcon()); 112 | menuExit.setOnAction(e-> System.exit(0)); 113 | 114 | // With the Builder class, we can quickly create our FXTrayIcon Menu 115 | trayIcon = new FXTrayIcon.Builder(stage).menuItem("Exit",e-> System.exit(0)).show().build(); 116 | 117 | ChoiceBox iconChoiceBox = new ChoiceBox<>(nameList); 118 | iconChoiceBox.setOnAction(e-> newIconChoice(iconChoiceBox.getValue())); 119 | 120 | // We can also nest menus, below is an Options' menu with sub-items 121 | VBox vBox = new VBox(5); 122 | Label lblChoose = new Label("Chose an Icon"); 123 | iView = new ImageView(); 124 | iView.setPreserveRatio(true); 125 | //setNodePosition(getNode(root,iView),10,10,50,50); 126 | setNodePosition(getNode(root,lblChoose),10,-1,12.5,-1); 127 | setNodePosition(getNode(root,iconChoiceBox),95,-1,10,-1); 128 | 129 | 130 | Button buttonDefaultMsg = new Button("Show a \"Default\" message"); 131 | 132 | // showDefaultMessage uses the FXTrayIcon image in the notification 133 | buttonDefaultMsg.setOnAction(e -> trayIcon.showMessage("A caption text", "Some content text.")); 134 | 135 | Button buttonInfoMsg = new Button("Show a \"Info\" message"); 136 | // other showXXX methods use an icon appropriate for the message type 137 | buttonInfoMsg.setOnAction(e -> trayIcon.showInfoMessage("A caption text", "Some content text")); 138 | 139 | Button buttonWarnMsg = new Button("Show a \"Warn\" message"); 140 | buttonWarnMsg.setOnAction(e -> trayIcon.showWarningMessage("A caption text", "Some content text")); 141 | 142 | Button buttonErrorMsg = new Button("Show a \"Error\" message"); 143 | buttonErrorMsg.setOnAction(e -> trayIcon.showErrorMessage("A caption text", "Some content text")); 144 | 145 | HBox hBox = new HBox(5, buttonDefaultMsg, buttonInfoMsg, buttonWarnMsg, buttonErrorMsg); 146 | vBox.getChildren().addAll(iView,hBox); 147 | setNodePosition(getNode(root,vBox),10,10,-1,10); 148 | stage.show(); 149 | } 150 | 151 | private void changeIcon(URL iconURL) { 152 | Image image = new Image(iconURL.toExternalForm()); 153 | iView.setImage(image); 154 | iView.setPreserveRatio(true); 155 | double height = iView.getScene().getWindow().getHeight(); 156 | //iView.setFitWidth(w - (w * .25)); 157 | iView.setFitHeight(height - (height * .25)); 158 | trayIcon.setGraphic(image); 159 | } 160 | 161 | private void newIconChoice(String iconName) { 162 | int index; 163 | switch(iconName) { 164 | case name2: 165 | index = 1; 166 | root.setStyle(style1); 167 | break; 168 | 169 | case name3: 170 | index = 2; 171 | root.setStyle(style1); 172 | break; 173 | 174 | case name4: 175 | index = 3; 176 | root.setStyle(style2); 177 | break; 178 | 179 | case name5: 180 | index = 4; 181 | root.setStyle(style3); 182 | break; 183 | 184 | case name6: 185 | index = 5; 186 | root.setStyle(style3); 187 | break; 188 | 189 | case name7: 190 | index = 6; 191 | root.setStyle(style2); 192 | break; 193 | 194 | case name8: 195 | index = 7; 196 | root.setStyle(style3); 197 | break; 198 | 199 | default: 200 | index = 0; 201 | root.setStyle(style1); 202 | break; 203 | } 204 | System.out.println(index); 205 | changeIcon(imageURLs[index]); 206 | } 207 | 208 | private Node getNode(AnchorPane root, VBox control) { 209 | root.getChildren().add(control); 210 | return root.getChildren().get(root.getChildren().indexOf(control)); 211 | } 212 | 213 | private Node getNode(AnchorPane root, Label control) { 214 | root.getChildren().add(control); 215 | return root.getChildren().get(root.getChildren().indexOf(control)); 216 | } 217 | 218 | private Node getNode(AnchorPane root, ChoiceBox control) { 219 | root.getChildren().add(control); 220 | return root.getChildren().get(root.getChildren().indexOf(control)); 221 | } 222 | 223 | private void setNodePosition(Node node, double left, double right, double top, double bottom) { 224 | if (top != -1) setTopAnchor(node, top); 225 | if (bottom != -1) setBottomAnchor(node, bottom); 226 | if (left != -1) setLeftAnchor(node, left); 227 | if (right != -1) setRightAnchor(node, right); 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/TestTextChangeInFXItem.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon; 2 | 3 | import javafx.application.Application; 4 | import javafx.scene.control.MenuItem; 5 | import javafx.stage.Stage; 6 | 7 | public class TestTextChangeInFXItem extends Application { 8 | 9 | @Override 10 | public void start(Stage primaryStage) throws Exception { 11 | FXTrayIcon icon = new FXTrayIcon(primaryStage); 12 | MenuItem item = new MenuItem("Change Me"); 13 | icon.addMenuItem(item); 14 | icon.show(); 15 | item.setText("Changed"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/animation/Animation.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon.animation; 2 | 3 | import com.dustinredmond.fxtrayicon.FXTrayIcon; 4 | import com.sun.javafx.iio.ImageLoader; 5 | import javafx.application.Application; 6 | import javafx.geometry.Insets; 7 | import javafx.geometry.Pos; 8 | import javafx.scene.Scene; 9 | import javafx.scene.control.Button; 10 | import javafx.scene.image.Image; 11 | import javafx.scene.layout.HBox; 12 | import javafx.scene.layout.VBox; 13 | import javafx.stage.Stage; 14 | 15 | import java.io.File; 16 | import java.net.MalformedURLException; 17 | import java.net.URL; 18 | import java.util.LinkedList; 19 | 20 | public class Animation extends Application { 21 | 22 | private FXTrayIcon fxTrayIcon; 23 | private String filePath = "com/dustinredmond/fxtrayicon/animate/%s/%s.png"; 24 | private String iconPath = "com/dustinredmond/fxtrayicon/animate/%s/Tray.png"; 25 | private Button btnOne; 26 | private Button btnTwo; 27 | private Button btnThree; 28 | private Button btnStart; 29 | private Button btnStop; 30 | private Button btnPause; 31 | private Button btnReset; 32 | private Scene scene; 33 | private HBox boxButtons; 34 | 35 | private LinkedList animationFiles(int max, String folder) { 36 | LinkedList fileImages = new LinkedList<>(); 37 | for (int x = 1; x <= max; x++) { 38 | try { 39 | String fileNumber = (x < 10) ? "0" + x : String.valueOf(x); 40 | File file = getResourceFile(String.format(filePath, folder, fileNumber)); 41 | Image image = new Image(file.toURI().toURL().toString()); 42 | fileImages.addLast(file); 43 | } 44 | catch (MalformedURLException e) { 45 | throw new RuntimeException(e); 46 | } 47 | } 48 | return fileImages; 49 | } 50 | 51 | private LinkedList animationImages(int max, String folder) { 52 | LinkedList fxImages = new LinkedList<>(); 53 | for (int x = 1; x <= max; x++) { 54 | try { 55 | String fileNumber = (x < 10) ? "0" + x : String.valueOf(x); 56 | File file = getResourceFile(String.format(filePath, folder, fileNumber)); 57 | Image image = new Image(file.toURI().toURL().toString()); 58 | fxImages.addLast(image); 59 | } 60 | catch (MalformedURLException e) { 61 | throw new RuntimeException(e); 62 | } 63 | } 64 | return fxImages; 65 | } 66 | 67 | @Override 68 | public void start(Stage primaryStage) { 69 | primaryStage.setTitle("Animation"); 70 | this.primaryStage = primaryStage; 71 | makeForm(); 72 | } 73 | 74 | public static void main(String[] args) { 75 | launch(args); 76 | } 77 | 78 | private Stage primaryStage; 79 | 80 | private void makeForm() { 81 | btnOne = new Button("Example One (White)"); 82 | btnTwo = new Button("Example Two (Black)"); 83 | btnThree = new Button("Example Three (Different)"); 84 | btnOne.setPrefWidth(200); 85 | btnTwo.setPrefWidth(200); 86 | btnThree.setPrefWidth(200); 87 | btnOne.setOnAction(e -> startOne()); 88 | btnTwo.setOnAction(e -> startTwo()); 89 | btnThree.setOnAction(e -> startThree()); 90 | btnStart = new Button("Start"); 91 | btnStop = new Button("Stop"); 92 | btnPause = new Button("Pause"); 93 | btnReset = new Button("Reset Icon"); 94 | btnStart.setOnAction(e -> startAnimation()); 95 | btnStop.setOnAction(e -> stopAnimation()); 96 | btnPause.setOnAction(e -> pauseAnimation()); 97 | btnReset.setOnAction(e -> setDefaultIcon()); 98 | btnStart.setPrefWidth(55); 99 | btnStop.setPrefWidth(55); 100 | btnPause.setPrefWidth(55); 101 | btnReset.setPrefWidth(95); 102 | boxButtons = new HBox(15, btnStart, btnStop, btnPause, btnReset); 103 | boxButtons.setAlignment(Pos.CENTER); 104 | VBox vbox = new VBox(15, btnOne, btnTwo, btnThree, boxButtons); 105 | vbox.setPadding(new Insets(25)); 106 | vbox.setAlignment(Pos.CENTER); 107 | scene = new Scene(vbox); 108 | primaryStage.setScene(scene); 109 | primaryStage.show(); 110 | } 111 | 112 | private void startOne() { 113 | File icon = getResourceFile(String.format(iconPath, "One")); 114 | LinkedList fileList = animationImages(48, "One"); 115 | if (fxTrayIcon == null) { 116 | startTrayIcon(fileList, icon, 100); 117 | } 118 | else { 119 | fxTrayIcon.stop(); 120 | fxTrayIcon.newAnimation(fileList, 100); 121 | fxTrayIcon.setGraphic(icon, 24, 24); 122 | } 123 | } 124 | 125 | private void startTwo() { 126 | File icon = getResourceFile(String.format(iconPath, "Two")); 127 | LinkedList fileList = animationImages(48, "Two"); 128 | if (fxTrayIcon == null) { 129 | startTrayIcon(fileList, icon, 100); 130 | } 131 | else { 132 | fxTrayIcon.stop(); 133 | fxTrayIcon.newAnimation(fileList, 100); 134 | fxTrayIcon.setGraphic(icon, 24, 24); 135 | } 136 | } 137 | 138 | private void startThree() { 139 | File icon = getResourceFile(String.format(iconPath, "Three")); 140 | LinkedList fileList = animationImages(41, "Three"); 141 | if (fxTrayIcon == null) { 142 | startTrayIcon(fileList, icon, 150); 143 | } 144 | else { 145 | fxTrayIcon.stop(); 146 | fxTrayIcon.newAnimation(fileList, 150); 147 | if (icon.exists()) 148 | fxTrayIcon.setGraphic(icon, 24, 24); 149 | else { 150 | System.out.println("File does not exist"); 151 | } 152 | } 153 | } 154 | 155 | 156 | private void startTrayIcon(LinkedList fileList, File icon, int frameRate, boolean sortList) { 157 | fxTrayIcon = new FXTrayIcon.Builder(primaryStage, icon) 158 | .animate(fileList, frameRate, sortList) 159 | .menuItem("Start", e -> startAnimation()) 160 | .menuItem("Stop", e -> stopAnimation()) 161 | .separator() 162 | .addExitMenuItem() 163 | .show() 164 | .build(); 165 | } 166 | 167 | private void startTrayIcon(LinkedList imageList, File icon, int frameRate) { 168 | fxTrayIcon = new FXTrayIcon.Builder(primaryStage, icon) 169 | .animate(imageList, frameRate) 170 | .menuItem("Start", e -> startAnimation()) 171 | .menuItem("Stop", e -> stopAnimation()) 172 | .separator() 173 | .addExitMenuItem() 174 | .show() 175 | .build(); 176 | } 177 | 178 | private void startAnimation() { 179 | if (fxTrayIcon != null) { 180 | fxTrayIcon.playFromStart(); 181 | } 182 | } 183 | 184 | private void stopAnimation() { 185 | if (fxTrayIcon != null) { 186 | fxTrayIcon.stop(); 187 | } 188 | } 189 | 190 | private void pauseAnimation() { 191 | if (fxTrayIcon != null) { 192 | fxTrayIcon.pause(); 193 | } 194 | } 195 | 196 | private void setDefaultIcon() { 197 | if (fxTrayIcon != null) { 198 | fxTrayIcon.resetIcon(); 199 | } 200 | } 201 | 202 | private File getResourceFile(String resourcePath) { 203 | ClassLoader classLoader = ImageLoader.class.getClassLoader(); 204 | URL resourceUrl = classLoader.getResource(resourcePath); 205 | 206 | if (resourceUrl != null) { 207 | return new File(resourceUrl.getFile()); 208 | } 209 | else { 210 | throw new IllegalArgumentException("Resource not found: " + resourcePath); 211 | } 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/animation/Launcher.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon.animation; 2 | 3 | import java.awt.*; 4 | 5 | public class Launcher { 6 | 7 | public static void main(String[] args) { 8 | System.setProperty("apple.awt.UIElement", "false"); 9 | Toolkit.getDefaultToolkit(); 10 | Animation.main(args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/issue71/AddMenuItem.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon.issue71; 2 | 3 | import com.dustinredmond.fxtrayicon.FXTrayIcon; 4 | import javafx.application.Application; 5 | import javafx.geometry.Insets; 6 | import javafx.geometry.Pos; 7 | import javafx.scene.Scene; 8 | import javafx.scene.control.Button; 9 | import javafx.scene.control.Label; 10 | import javafx.scene.control.MenuItem; 11 | import javafx.scene.control.TextField; 12 | import javafx.scene.layout.VBox; 13 | import javafx.stage.Stage; 14 | 15 | /** 16 | * This test class is meant to illustrate that the problem from 17 | * Issue #71 has been fixed. 18 | */ 19 | 20 | 21 | public class AddMenuItem extends Application { 22 | 23 | private FXTrayIcon fxTrayIcon; 24 | private Label lblAfter; 25 | 26 | 27 | @Override 28 | public void start(Stage primaryStage) throws Exception { 29 | fxTrayIcon = new FXTrayIcon 30 | .Builder(primaryStage) 31 | .build(); 32 | show(); 33 | } 34 | 35 | public static void main(String[] args) { 36 | launch(args); 37 | } 38 | 39 | private void show() { 40 | fxTrayIcon.show(); 41 | fxTrayIcon.addExitItem("Exit"); 42 | Stage stage = new Stage(); 43 | double width = 300; 44 | double height = 225; 45 | Button btnAdd = new Button("Add"); 46 | Button btnClose = new Button("Close"); 47 | Label lblTitle = new Label("Type in a MenuItem name then press Add"); 48 | TextField tfName = new TextField(); 49 | lblAfter = new Label(); 50 | lblAfter.setPrefWidth(225); 51 | tfName.setPrefWidth(150); 52 | VBox vBox = new VBox(10, lblTitle, tfName, btnAdd, lblAfter, btnClose); 53 | btnAdd.setOnAction(e->{ 54 | addMenuItem(tfName.getText()); 55 | lblAfter.setText("Now try the " + tfName.getText() + " menu item"); 56 | }); 57 | vBox.setPadding(new Insets(20)); 58 | vBox.setAlignment(Pos.CENTER); 59 | Scene scene = new Scene(vBox, width, height); 60 | stage.setScene(scene); 61 | stage.show(); 62 | btnClose.setOnAction(e->System.exit(0)); 63 | } 64 | 65 | private void addMenuItem(String menuName) { 66 | MenuItem menuItem = new MenuItem(menuName); 67 | menuItem.setOnAction(e-> { 68 | show(menuName); 69 | lblAfter.setText(""); 70 | }); 71 | fxTrayIcon.addMenuItem(menuItem); 72 | } 73 | 74 | private void show(String menuItemName) { 75 | double width = 250; 76 | double height = 100; 77 | Button btnOK = new Button("OK"); 78 | Label lblMenuItem = new Label(menuItemName + " Works!"); 79 | lblMenuItem.setPrefWidth(width); 80 | VBox vBox = new VBox(15, lblMenuItem, btnOK); 81 | vBox.setPadding(new Insets(20)); 82 | vBox.setAlignment(Pos.CENTER); 83 | Stage stage = new Stage(); 84 | Scene scene = new Scene(vBox, width, height); 85 | stage.setScene(scene); 86 | stage.show(); 87 | btnOK.setOnAction(e->stage.hide()); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/issue71/Launcher.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon.issue71; 2 | 3 | import java.awt.*; 4 | 5 | public class Launcher { 6 | 7 | public static void main(String[] args) { 8 | System.setProperty("apple.awt.UIElement", "false"); 9 | Toolkit.getDefaultToolkit(); 10 | AddMenuItem.main(args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/notaskbaricon/Main.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon.notaskbaricon; 2 | 3 | /* 4 | * Copyright (c) 2022 Michael Sims, Dustin Redmond and contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | import com.dustinredmond.fxtrayicon.FXTrayIcon; 26 | import com.dustinredmond.fxtrayicon.RunnableTest; 27 | import javafx.application.Application; 28 | import javafx.application.Platform; 29 | import javafx.geometry.Insets; 30 | import javafx.geometry.Pos; 31 | import javafx.scene.Scene; 32 | import javafx.scene.control.Button; 33 | import javafx.scene.control.Label; 34 | import javafx.scene.control.TextField; 35 | import javafx.scene.layout.StackPane; 36 | import javafx.scene.layout.VBox; 37 | import javafx.stage.Stage; 38 | import javafx.stage.StageStyle; 39 | import java.net.URL; 40 | 41 | public class Main extends Application { 42 | 43 | /** 44 | * Launch the Start class FIRST! 45 | * @param stage The default JavaFX Stage 46 | */ 47 | @Override 48 | public void start(Stage stage) { 49 | URL iconFile = new RunnableTest().getIcon(); 50 | stage.initStyle(StageStyle.UTILITY); 51 | stage.setHeight(0); 52 | stage.setWidth(0); 53 | Stage mainStage = new Stage(); 54 | mainStage.initOwner(stage); 55 | mainStage.initStyle(StageStyle.UNDECORATED); 56 | 57 | Label label = new Label("No TaskBar Icon"); 58 | Label label2 = new Label("Type a message and click the button"); 59 | label2.setAlignment(Pos.CENTER_LEFT); 60 | TextField tfInput = new TextField(); 61 | Button button = new Button("Show Alert"); 62 | button.setOnAction(e -> showMessage(tfInput.getText())); 63 | 64 | VBox vbox = new VBox(); 65 | vbox.setPadding(new Insets(10,20,10,20)); 66 | vbox.setAlignment(Pos.CENTER); 67 | vbox.setSpacing(20); 68 | vbox.getChildren().addAll(label, label2, tfInput, button); 69 | 70 | StackPane root = new StackPane(); 71 | root.getChildren().add(vbox); 72 | mainStage.setScene(new Scene(root, 250, 200)); 73 | mainStage.initStyle(StageStyle.UTILITY); //This is what makes the icon disappear in Windows. 74 | if (FXTrayIcon.isSupported()) { 75 | icon = new FXTrayIcon.Builder(stage, iconFile) 76 | .menuItem("Show Stage",e -> { 77 | Platform.runLater(()-> stage.setIconified(false)); 78 | mainStage.show();}) 79 | .menuItem("Hide Stage",e -> {Platform.runLater(() -> stage.setIconified(true) ); 80 | mainStage.hide();}) 81 | .menuItem("Show Message",e -> showMessage()) 82 | .separator() 83 | .menuItem("Exit", e -> System.exit(0)) 84 | .show() 85 | .build(); 86 | } 87 | } 88 | 89 | private FXTrayIcon icon; 90 | 91 | private void showMessage() { 92 | icon.showInfoMessage("Check It Out!","Look Ma, No Taskbar Icon!"); 93 | } 94 | 95 | private void showMessage(String message) { 96 | icon.showInfoMessage("Message For You!",message); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/test/java/com/dustinredmond/fxtrayicon/notaskbaricon/Start.java: -------------------------------------------------------------------------------- 1 | package com.dustinredmond.fxtrayicon.notaskbaricon; 2 | 3 | /* 4 | * Copyright (c) 2022 Michael Sims, Dustin Redmond and contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | import javafx.application.Application; 26 | 27 | public class Start { 28 | 29 | /** 30 | * THIS CLASS MUST BE RUN FIRST! 31 | * 32 | * Kicks off the com.dustinredmond.fxtrayicon.notaskbaricon.Main runnable test 33 | * @param args Command line arguments 34 | */ 35 | public static void main(String[] args) { 36 | // This is an awt property which removes the icon 37 | // from the Dock on a mac and the TaskBar on Windows 38 | System.setProperty("apple.awt.UIElement", "true"); 39 | java.awt.Toolkit.getDefaultToolkit(); 40 | 41 | // This is a call to JavaFX application main method. 42 | // From now on we are transferring control to FX application. 43 | Application.launch(Main.class, args); 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/01.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/02.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/03.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/04.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/05.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/06.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/07.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/08.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/09.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/10.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/11.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/12.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/13.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/14.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/15.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/16.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/17.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/18.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/19.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/20.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/21.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/22.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/23.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/24.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/25.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/26.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/27.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/28.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/29.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/30.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/31.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/32.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/33.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/34.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/35.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/36.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/37.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/38.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/39.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/40.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/41.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/42.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/43.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/43.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/44.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/45.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/46.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/47.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/47.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/48.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/One/Tray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/One/Tray.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/00.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/01.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/02.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/03.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/04.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/05.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/06.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/07.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/08.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/09.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/10.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/11.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/12.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/13.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/14.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/15.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/16.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/17.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/18.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/19.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/20.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/21.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/22.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/23.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/24.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/25.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/26.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/27.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/28.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/29.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/30.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/31.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/32.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/33.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/34.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/35.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/36.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/37.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/38.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/39.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/40.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/41.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/Tray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Three/Tray.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/01.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/02.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/03.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/04.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/05.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/06.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/07.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/08.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/09.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/10.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/11.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/12.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/13.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/14.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/15.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/16.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/17.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/18.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/19.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/20.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/21.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/22.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/23.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/24.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/25.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/26.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/27.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/28.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/29.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/30.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/31.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/32.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/33.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/34.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/35.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/36.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/37.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/38.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/39.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/40.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/41.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/42.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/43.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/43.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/44.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/45.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/46.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/47.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/47.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/48.png -------------------------------------------------------------------------------- /src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/Tray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustinkredmond/FXTrayIcon/47dff815b31ada7a898e86b7b6cd23df4e096f9f/src/test/resources/com/dustinredmond/fxtrayicon/animate/Two/Tray.png --------------------------------------------------------------------------------