├── .github
└── workflows
│ └── ci.yaml
├── .gitignore
├── LICENSE
├── README.md
├── build.gradle
├── build_app_linux.sh
├── build_app_macos.sh
├── build_app_windows.bat
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── icon.afdesign
├── icon.png
├── icon_rounded.afdesign
├── releases
├── GlucoStatusFX-23.0.0.jar
└── GlucoStatusFX-23.0.1.jar
├── settings.gradle
└── src
└── main
├── java
├── eu
│ └── hansolo
│ │ └── fx
│ │ └── glucostatus
│ │ ├── ButtonShape.java
│ │ ├── Constants.java
│ │ ├── DataPoint.java
│ │ ├── DayShape.java
│ │ ├── Fonts.java
│ │ ├── GlucoEntry.java
│ │ ├── GlucoEntryDto.java
│ │ ├── Helper.java
│ │ ├── Interval.java
│ │ ├── Launcher.java
│ │ ├── Main.java
│ │ ├── PoincarePlot.java
│ │ ├── PropertyManager.java
│ │ ├── StackedLineChart.java
│ │ ├── Statistics.java
│ │ ├── Status.java
│ │ ├── ThirtyDayView.java
│ │ ├── Trend.java
│ │ ├── ZoneCell.java
│ │ ├── i18n
│ │ ├── DynamicMessage.java
│ │ ├── I18nKeys.java
│ │ ├── Internationalization.java
│ │ ├── LocaleObserver.java
│ │ ├── Translator.java
│ │ └── Utf8ResourceBundle.java
│ │ └── notification
│ │ ├── Notification.java
│ │ ├── NotificationBuilder.java
│ │ ├── NotificationEvent.java
│ │ ├── Notifier.java
│ │ └── NotifierBuilder.java
└── module-info.java
└── resources
└── eu
└── hansolo
└── fx
└── glucostatus
├── SF-Compact-Display-Bold.ttf
├── SF-Compact-Display-Medium.ttf
├── SF-Pro-Rounded-Bold.ttf
├── SF-Pro-Rounded-Regular.ttf
├── SF-Pro-Rounded-Semibold.ttf
├── SF-Pro-Text-Bold.ttf
├── SF-Pro-Text-Regular.ttf
├── alarm.wav
├── exclamationMark.svg
├── glucostatus.css
├── i18n
├── gsfx.properties
├── gsfx_de.properties
├── gsfx_en.properties
├── gsfx_it.properties
├── gsfx_nl.properties
└── gsfx_us.properties
├── icon.icns
├── icon.ico
├── icon128x128.png
├── icon16x16.png
├── icon256x256.png
├── icon32x32.png
├── icon48x48.png
├── matrix.svg
├── notification
├── error.png
├── info.png
├── notification.css
├── success.png
└── warning.png
├── pattern.svg
├── range.svg
├── reload.svg
├── settings.svg
├── stacked.svg
├── thirty-day-view.css
└── version.properties
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build-windows:
7 | runs-on: [ windows-latest ]
8 | steps:
9 | - uses: actions/checkout@v4
10 | - name: Set up JDK 21
11 | uses: actions/setup-java@v4
12 | with:
13 | java-version: 21
14 | distribution: 'zulu'
15 | gpg-private-key: ${{ secrets.GPG_KEY }}
16 | gpg-passphrase: PASSPHRASE
17 | - name: Build with Gradle
18 | run: ./gradlew.bat build
19 | env:
20 | PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
21 | - name: Create Distribution
22 | run: .\build_app_windows.bat
23 | - uses: actions/upload-artifact@v4
24 | with:
25 | name: GlucoStatusFX-Windows-x64
26 | path: |
27 | build/installer
28 | build/libs
29 |
30 | build-mac-aarch64:
31 | runs-on: [ macos-latest ]
32 | steps:
33 | - uses: actions/checkout@v4
34 | - name: Set up JDK 21
35 | uses: actions/setup-java@v4
36 | with:
37 | java-version: 21
38 | distribution: 'zulu'
39 | gpg-private-key: ${{ secrets.GPG_KEY }}
40 | gpg-passphrase: PASSPHRASE
41 | - name: Build with Gradle
42 | run: ./gradlew build
43 | env:
44 | PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
45 | - name: Grant execute permission for build_app_macos.sh
46 | run: chmod +x ./build_app_macos.sh
47 | - name: Create Distribution
48 | run: ./build_app_macos.sh
49 | - uses: actions/upload-artifact@v4
50 | with:
51 | name: GlucoStatusFX-Mac-aarch64
52 | path: |
53 | build/installer
54 | build/libs
55 |
56 | build-mac-x64:
57 | runs-on: [ macos-13 ]
58 | steps:
59 | - uses: actions/checkout@v4
60 | - name: Set up JDK 21
61 | uses: actions/setup-java@v4
62 | with:
63 | java-version: 21
64 | distribution: 'zulu'
65 | gpg-private-key: ${{ secrets.GPG_KEY }}
66 | gpg-passphrase: PASSPHRASE
67 | - name: Build with Gradle
68 | run: ./gradlew build
69 | env:
70 | PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
71 | - name: Grant execute permission for build_app_macos.sh
72 | run: chmod +x ./build_app_macos.sh
73 | - name: Create Distribution
74 | run: ./build_app_macos.sh
75 | - uses: actions/upload-artifact@v4
76 | with:
77 | name: GlucoStatusFX-Mac-x64
78 | path: |
79 | build/installer
80 | build/libs
81 |
82 | build-linux:
83 | runs-on: [ ubuntu-latest ]
84 | steps:
85 | - uses: actions/checkout@v4
86 | - name: Set up JDK 21
87 | uses: actions/setup-java@v4
88 | with:
89 | java-version: 21
90 | distribution: 'zulu'
91 | gpg-private-key: ${{ secrets.GPG_KEY }}
92 | gpg-passphrase: PASSPHRASE
93 | - name: Build with Gradle
94 | run: ./gradlew build
95 | env:
96 | PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
97 | - name: Grant execute permission for build_app_linux.sh
98 | run: chmod +x ./build_app_linux.sh
99 | - name: Create Distribution
100 | run: ./build_app_linux.sh
101 | - uses: actions/upload-artifact@v4
102 | with:
103 | name: GlucoStatusFX-Linux-x64
104 | path: |
105 | build/installer
106 | build/libs
107 |
108 | build-linux-arm64:
109 | runs-on: [ ubuntu-24.04-arm ]
110 | steps:
111 | - uses: actions/checkout@v4
112 | - name: Set up JDK 21
113 | uses: actions/setup-java@v4
114 | with:
115 | java-version: 21
116 | distribution: 'zulu'
117 | gpg-private-key: ${{ secrets.GPG_KEY }}
118 | gpg-passphrase: PASSPHRASE
119 | - name: Build with Gradle
120 | run: ./gradlew build
121 | env:
122 | PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
123 | - name: Grant execute permission for build_app_linux.sh
124 | run: chmod +x ./build_app_linux.sh
125 | - name: Create Distribution
126 | run: ./build_app_linux.sh
127 | - uses: actions/upload-artifact@v4
128 | with:
129 | name: GlucoStatusFX-Linux-arm64
130 | path: |
131 | build/installer
132 | build/libs
133 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /.gradle
3 | .DS_Store
4 | /build
5 | /out
6 | /classes
7 | /RUNNING_PID
8 | /src/main/resources/jpro.conf
9 | /logs
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## GlucoStatusFX
2 |
3 | 
4 |
5 |
6 | A glucose status monitor for Nightscout implemented in JavaFX.
7 |
8 |
9 |
10 |
11 | 
12 | 
13 | 
14 | 
15 | 
16 |
17 | [](https://www.jfx-central.com/downloads/glucostatusfx)
18 |
19 |
20 |
21 | Running on Linux
22 |
23 | When running as jar file you might need to start with on Linux
24 |
25 | ```java -Djdk.gtk.version=2 -jar GlucoStatusFX-17.0.61.jar```
26 |
27 |
28 |
29 |
30 | ## Intro
31 | GlucoStatusFX is a JavaFX application that will sit in your menu bar and is visualizing
32 | data coming from a nightscout server.
33 | To use this app you need to have a nightscout server which url you have to put in the
34 | text field in the settings dialog.
35 |
36 | To set up the nightscout url in the settings dialog, just put in the url of your server e.g.
37 |
38 | ```https://my-glucose.herokuapp.com```
39 |
40 | The api secret field is optional (but it is recommended to set it up as described [here](https://nightscout.github.io/nightscout/setup_variables/))
41 |
42 | The token field is also optional (find more info [here](https://nightscout.github.io/nightscout/security/))
43 |
44 | In the settings dialog you can will find the following parameters:
45 |
46 | "Unit mg/dl":
47 | Whatever unit you have defined on your nightscout server you can change the display to either mg/dl or mmol/l. In case you would like to see the values in mg/dl, please enable the switch "Unit mg/dl". If you disable this switch the values will be shown in mmol/l.
48 |
49 | "Low value notification":
50 | Enable the switch if you would like to receive notifications for low values (in GlucoStatusFX acceptable low means values between min acceptable and 55 mg/dl which is min critical).
51 |
52 | "Acceptable low value notification":
53 | Enable the switch if you would like to receive notifications for acceptable low values (in GlucoStatusFX acceptable low means values between min normal and min acceptable values).
54 |
55 | "Acceptable high value notification":
56 | Enable the switch if you would like to receive notifications for acceptable high values (in GlucoStatusFX acceptable high means values between max normal and max acceptable values).
57 |
58 | "High value notification":
59 | Enable the switch if you would like to receive notifications for high values (in GlucoStatusFX high means values between max acceptable and 350 mg/dl which is max critical).
60 |
61 |
62 | "Too low notification interval":
63 | You can define the interval for notifications of too low values in a range of 5-10 minutes. In case of too low values you will receive notifications in the given interval.
64 |
65 | "Too high notification interval":
66 | You can define the interval for notifications of too high values in a range of 5-30 minutes. In case of too high values you will receive notifications in the given interval.
67 |
68 |
69 | "Min acceptable":
70 | The min acceptable value can be defined in the range of 60-70 mg/dl.
71 |
72 | "Min normal":
73 | The min normal value can be defined in the range of 70-80 mg/dl.
74 |
75 | "Max normal":
76 | The max normal value can be defined in the range of 120-160 mg/dl.
77 |
78 | "Max acceptable":
79 | The max acceptable value can be defined in the range of 120-250 mg/dl.
80 |
81 |
82 | ## Overview
83 | 
84 |
85 | 
86 |
87 | 
88 |
89 | 
90 |
91 | 
92 |
93 | 
94 |
95 | 
96 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | import java.text.SimpleDateFormat
2 |
3 | buildscript {
4 | repositories {
5 | mavenCentral()
6 | maven {
7 | url "https://plugins.gradle.org/m2/"
8 | }
9 | }
10 | dependencies {
11 | classpath 'com.google.gradle:osdetector-gradle-plugin:1.7.3'
12 | classpath 'org.javamodularity:moduleplugin:1.8.12'
13 | }
14 | }
15 |
16 | plugins {
17 | id 'java'
18 | id 'application'
19 | id 'signing'
20 | id 'com.google.osdetector' version '1.7.3'
21 | id 'org.javamodularity.moduleplugin' version '1.8.15'
22 | id 'net.nemerosa.versioning' version '3.1.0'
23 | }
24 |
25 | apply plugin: 'signing'
26 |
27 | normalization {
28 | runtimeClasspath {
29 | ignore('/META-INF/MANIFEST.MF')
30 | }
31 | }
32 |
33 | repositories {
34 | mavenCentral()
35 | flatDir {
36 | dirs 'libs'
37 | }
38 | }
39 |
40 | Date buildTimeAndDate = new Date()
41 | ext {
42 | buildDate = new SimpleDateFormat('yyyy-MM-dd').format(buildTimeAndDate)
43 | buildTime = new SimpleDateFormat('HH:mm:ss.SSSZ').format(buildTimeAndDate)
44 | platform = osdetector.os == 'osx' ? osdetector.arch == 'aarch_64' ? 'mac-aarch64' : 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os == 'linux' ? osdetector.arch == 'aarch_64' ? 'linux-aarch64' : 'linux' : osdetector.os
45 | ciOssrhUsername = System.getenv('OSSRH_USERNAME')
46 | ciOssrhPassword = System.getenv('OSSRH_PASSWORD')
47 | ciGHUser = System.getenv('GH_USER')
48 | ciGHToken = System.getenv('GH_TOKEN')
49 | gpgkey = System.getenv("GPG_PRIVATE_KEY")
50 | gpgpassphrase = System.getenv("PASSPHRASE")
51 | }
52 |
53 | dependencies {
54 | implementation fileTree(dir: 'libs', include: '*.jar')
55 | implementation "org.openjfx:javafx-base:${javafxVersion}:${platform}"
56 | implementation "org.openjfx:javafx-graphics:${javafxVersion}:${platform}"
57 | implementation "org.openjfx:javafx-controls:${javafxVersion}:${platform}"
58 | implementation "org.openjfx:javafx-media:${javafxVersion}:${platform}"
59 | implementation "org.openjfx:javafx-swing:${javafxVersion}:${platform}"
60 | implementation 'eu.hansolo:jdktools:21.0.19'
61 | implementation 'eu.hansolo:toolbox:21.0.17'
62 | implementation 'eu.hansolo:toolboxfx:21.0.7'
63 | implementation 'eu.hansolo:applefx:21.0.3'
64 | implementation 'com.google.code.gson:gson:2.10.1'
65 | //implementation 'com.dustinredmond.fxtrayicon:FXTrayIcon:4.0.1'
66 | implementation 'com.dustinredmond.fxtrayicon:FXTrayIcon:3.1.2'
67 | }
68 |
69 | application {
70 | mainModule = 'eu.hansolo.fx.glucostatus'
71 | }
72 |
73 | mainClassName = 'eu.hansolo.fx.glucostatus.Launcher'
74 | description = 'GlucostatusFX is a tool to visualize data coming from a nightscout server'
75 |
76 |
77 | jar {
78 | from {
79 | duplicatesStrategy = DuplicatesStrategy.EXCLUDE
80 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
81 | } {
82 | exclude "META-INF/*.SF"
83 | exclude "META-INF/*.DSA"
84 | exclude "META-INF/*.RSA"
85 | }
86 | manifest {
87 | attributes(
88 | 'Built-By' : System.properties['user.name'],
89 | 'Created-By' : System.properties['java.version'] + " (" + System.properties['java.vendor'] + " " + System.properties['java.vm.version'] + ")",
90 | 'Build-Date' : project.buildDate,
91 | 'Build-Time' : project.buildTime,
92 | 'Build-Revision' : versioning.info.commit,
93 | 'Specification-Title' : project.name,
94 | 'Specification-Version' : project.version,
95 | 'Implementation-Title' : project.name,
96 | 'Implementation-Version': project.version,
97 | 'Bundle-Name' : project.name,
98 | 'Bundle-License' : 'https://www.apache.org/licenses/LICENSE-2.0;description=Apache License Version 2.0;link=https://spdx.org/licenses/Apache-2.0.html',
99 | 'Bundle-Description' : description,
100 | 'Bundle-SymbolicName' : 'eu.hansolo.fx.glucostatus',
101 | 'Class-Path' : '${project.name}-${project.version}.jar',
102 | 'Main-Class' : 'eu.hansolo.fx.glucostatus.Launcher'
103 | )
104 | }
105 | }
106 |
107 |
108 | // start app from gradle
109 | task Main(type: JavaExec) {
110 | mainClass = "eu.hansolo.fx.glucostatus.Launcher"
111 | classpath = sourceSets.main.runtimeClasspath
112 | }
113 |
114 |
115 | // create properties file including the version
116 | task createProperties(dependsOn: processResources) {
117 | doLast {
118 | new File("$buildDir//classes/java/main/eu/hansolo/fx/glucostatus/version.properties").withWriter { w ->
119 | Properties p = new Properties()
120 | p['version'] = project.version.toString()
121 | p.store w, null
122 | }
123 | }
124 | }
125 |
126 | classes {
127 | dependsOn createProperties
128 | }
129 |
130 |
131 | // Fix problems with loading resources
132 | sourceSets {
133 | main {
134 | //output.setResourcesDir(java.outputDir)
135 | output.resourcesDir = file('build/classes/java/main')
136 | //java.destinationDirectory.set(file('build/classes/java/main'))
137 | }
138 | }
139 |
140 |
141 | //processResources {
142 | // from(sourceSets.main.java.srcDirs) {
143 | // include '**/*.properties'
144 | // }
145 | //}
146 |
147 | run {
148 | inputs.property("moduleName", moduleName)
149 | doFirst {
150 | jvmArgs = [
151 | '--module-path', classpath.asPath,
152 | '--module', mainClassName
153 | ]
154 | classpath = files()
155 | }
156 | }
157 |
158 | /*
159 | signing {
160 | useGpgCmd()
161 | sign configurations.archives
162 | }
163 | */
--------------------------------------------------------------------------------
/build_app_linux.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # SPDX-License-Identifier: Apache-2.0
5 | #
6 | # Copyright 2022 Gerrit Grunwald.
7 | #
8 | # Licensed under the Apache License, Version 2.0 (the "License");
9 | # you may not use this file except in compliance with the License.
10 | # You may obtain a copy of the License at
11 | #
12 | # https://www.apache.org/licenses/LICENSE-2.0
13 | #
14 | # Unless required by applicable law or agreed to in writing, software
15 | # distributed under the License is distributed on an "AS IS" BASIS,
16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | # See the License for the specific language governing permissions and
18 | # limitations under the License.
19 | #
20 |
21 | JAVA_VERSION=23
22 | MAIN_JAR="GlucoStatusFX-23.0.1.jar"
23 | APP_VERSION=23.0.1
24 |
25 | echo "java home: $JAVA_HOME"
26 | echo "project version: $PROJECT_VERSION"
27 | echo "app version: $APP_VERSION"
28 | echo "main JAR file: $MAIN_JAR"
29 |
30 | # ------ SETUP DIRECTORIES AND FILES ----------------------------------------
31 | # Remove previously generated java runtime and installers. Copy all required
32 | # jar files into the input/libs folder.
33 |
34 | rm -rfd ./build/java-runtime/
35 | rm -rfd build/installer/
36 |
37 | mkdir -p build/installer/input/libs/
38 |
39 | cp build/libs/* build/installer/input/libs/
40 | cp build/libs/${MAIN_JAR} build/installer/input/libs/
41 |
42 | # ------ REQUIRED MODULES ---------------------------------------------------
43 | # Use jlink to detect all modules that are required to run the application.
44 | # Starting point for the jdep analysis is the set of jars being used by the
45 | # application.
46 |
47 | echo "detecting required modules"
48 | detected_modules=`$JAVA_HOME/bin/jdeps \
49 | --multi-release ${JAVA_VERSION} \
50 | --ignore-missing-deps \
51 | --print-module-deps \
52 | --class-path "build/installer/input/libs/*" \
53 | build/classes/java/main/eu/hansolo/fx/glucostatus/Main.class`
54 | echo "detected modules: ${detected_modules}"
55 |
56 |
57 | # ------ MANUAL MODULES -----------------------------------------------------
58 | # jdk.crypto.ec has to be added manually bound via --bind-services or
59 | # otherwise HTTPS does not work.
60 | #
61 | # See: https://bugs.openjdk.java.net/browse/JDK-8221674
62 | #
63 | # In addition we need jdk.localedata if the application is localized.
64 | # This can be reduced to the actually needed locales via a jlink paramter,
65 | # e.g., --include-locales=en,de.
66 |
67 | manual_modules=jdk.crypto.ec,jdk.localedata
68 | echo "manual modules: ${manual_modules}"
69 |
70 | # ------ RUNTIME IMAGE ------------------------------------------------------
71 | # Use the jlink tool to create a runtime image for our application. We are
72 | # doing this is a separate step instead of letting jlink do the work as part
73 | # of the jpackage tool. This approach allows for finer configuration and also
74 | # works with dependencies that are not fully modularized, yet.
75 |
76 | echo "creating java runtime image"
77 | $JAVA_HOME/bin/jlink \
78 | --no-header-files \
79 | --no-man-pages \
80 | --compress=2 \
81 | --strip-debug \
82 | --add-modules "${detected_modules},${manual_modules}" \
83 | --include-locales=en,de \
84 | --output build/java-runtime
85 |
86 | # ------ PACKAGING ----------------------------------------------------------
87 | # A loop iterates over the various packaging types supported by jpackage. In
88 | # the end we will find all packages inside the build/installer directory.
89 |
90 | for type in "deb" "rpm"
91 | do
92 | echo "Creating installer of type ... $type"
93 |
94 | $JAVA_HOME/bin/jpackage \
95 | --type $type \
96 | --dest build/installer \
97 | --input build/installer/input/libs \
98 | --name GlucoStatusFX \
99 | --main-class eu.hansolo.fx.glucostatus.Launcher \
100 | --main-jar ${MAIN_JAR} \
101 | --java-options -Xmx2048m \
102 | --java-options '--enable-preview' \
103 | --java-options '-Djdk.gtk.version=2' \
104 | --runtime-image build/java-runtime \
105 | --icon src/main/resources/eu/hansolo/fx/glucostatus/icon128x128.png \
106 | --linux-shortcut \
107 | --linux-menu-group "GlucoStatusFX" \
108 | --app-version ${APP_VERSION} \
109 | --vendor "Gerrit Grunwald" \
110 | --copyright "Copyright © 2022 Gerrit Grunwald" \
111 | --description "Glucose status monitor" \
112 |
113 | done
114 |
115 |
116 | # ------ CHECKSUM FILE --------------------------------------------------------
117 | arch_name="$(uname -m)"
118 |
119 | if [ "${arch_name}" = "aarch64" ]; then
120 | sha256sum "build/installer/glucostatusfx_$APP_VERSION-1_arm64.deb" > "build/installer/glucostatusfx_$APP_VERSION-1_arm64.deb.sha256"
121 | sha256sum "build/installer/glucostatusfx-$APP_VERSION-1.aarch64.rpm" > "build/installer/glucostatusfx_$APP_VERSION-1.aarch64.rpm.sha256"
122 | else
123 | sha256sum "build/installer/glucostatusfx_${APP_VERSION}-1_amd64.deb" > "build/installer/glucostatusfx_${APP_VERSION}-1_amd64.deb.sha256"
124 | sha256sum "build/installer/glucostatusfx-${APP_VERSION}-1.x86_64.rpm" > "build/installer/glucostatusfx-${APP_VERSION}-1.x86_64.rpm.sha256"
125 | fi
126 |
--------------------------------------------------------------------------------
/build_app_macos.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # SPDX-License-Identifier: Apache-2.0
5 | #
6 | # Copyright 2022 Gerrit Grunwald.
7 | #
8 | # Licensed under the Apache License, Version 2.0 (the "License");
9 | # you may not use this file except in compliance with the License.
10 | # You may obtain a copy of the License at
11 | #
12 | # https://www.apache.org/licenses/LICENSE-2.0
13 | #
14 | # Unless required by applicable law or agreed to in writing, software
15 | # distributed under the License is distributed on an "AS IS" BASIS,
16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | # See the License for the specific language governing permissions and
18 | # limitations under the License.
19 | #
20 |
21 | JAVA_VERSION=23
22 | MAIN_JAR="GlucoStatusFX-23.0.1.jar"
23 | APP_VERSION=23.0.1
24 |
25 | echo "java home: $JAVA_HOME"
26 | echo "project version: $PROJECT_VERSION"
27 | echo "app version: $APP_VERSION"
28 | echo "main JAR file: $MAIN_JAR"
29 |
30 | # ------ SETUP DIRECTORIES AND FILES ------------------------------------------
31 | # Remove previously generated java runtime and installers. Copy all required
32 | # jar files into the input/libs folder.
33 |
34 | rm -rfd ./build/java-runtime/
35 | rm -rfd build/installer/
36 |
37 | mkdir -p build/installer/input/libs/
38 |
39 | cp build/libs/* build/installer/input/libs/
40 | cp build/libs/${MAIN_JAR} build/installer/input/libs/
41 |
42 | # ------ REQUIRED MODULES -----------------------------------------------------
43 | # Use jlink to detect all modules that are required to run the application.
44 | # Starting point for the jdep analysis is the set of jars being used by the
45 | # application.
46 | echo "-------------------------------------------------------------------------"
47 | echo "detecting required modules"
48 | detected_modules=`$JAVA_HOME/bin/jdeps \
49 | --multi-release ${JAVA_VERSION} \
50 | --ignore-missing-deps \
51 | --print-module-deps \
52 | --class-path "build/installer/input/libs/*" \
53 | build/classes/java/main/eu/hansolo/fx/glucostatus/Main.class`
54 | echo "detected modules: ${detected_modules}"
55 | echo "-------------------------------------------------------------------------"
56 |
57 | # ------ MANUAL MODULES -------------------------------------------------------
58 | # jdk.crypto.ec has to be added manually bound via --bind-services or
59 | # otherwise HTTPS does not work.
60 | #
61 | # See: https://bugs.openjdk.java.net/browse/JDK-8221674
62 | #
63 | # In addition we need jdk.localedata if the application is localized.
64 | # This can be reduced to the actually needed locales via a jlink paramter,
65 | # e.g., --include-locales=en,de.
66 |
67 | manual_modules=jdk.crypto.ec,jdk.localedata
68 | echo "manual modules: ${manual_modules}"
69 | echo "-------------------------------------------------------------------------"
70 |
71 | # ------ RUNTIME IMAGE --------------------------------------------------------
72 | # Use the jlink tool to create a runtime image for our application. We are
73 | # doing this is a separate step instead of letting jlink do the work as part
74 | # of the jpackage tool. This approach allows for finer configuration and also
75 | # works with dependencies that are not fully modularized, yet.
76 |
77 | echo "creating java runtime image"
78 | $JAVA_HOME/bin/jlink \
79 | --no-header-files \
80 | --no-man-pages \
81 | --compress=2 \
82 | --strip-debug \
83 | --add-modules "${detected_modules},${manual_modules}" \
84 | --include-locales=en,de \
85 | --output build/java-runtime
86 |
87 |
88 | # ------ PACKAGING ------------------------------------------------------------
89 | # A loop iterates over the various packaging types supported by jpackage. In
90 | # the end we will find all packages inside the build/installer directory.
91 |
92 | # Somehow before signing there needs to be another step: xattr -cr build/installer/GlucoStatusFX.app
93 | echo "-------------------------------------------------------------------------"
94 | for type in "app-image" "dmg" "pkg"
95 | do
96 | echo "Creating installer of type ... $type"
97 |
98 | $JAVA_HOME/bin/jpackage \
99 | --type $type \
100 | --dest build/installer \
101 | --input build/installer/input/libs \
102 | --name GlucoStatusFX \
103 | --main-class eu.hansolo.fx.glucostatus.Launcher \
104 | --main-jar ${MAIN_JAR} \
105 | --java-options -Xmx2048m \
106 | --java-options '--enable-preview' \
107 | --runtime-image build/java-runtime \
108 | --icon src/main/resources/eu/hansolo/fx/glucostatus/icon.icns \
109 | --app-version ${APP_VERSION} \
110 | --vendor "Gerrit Grunwald" \
111 | --copyright "Copyright © 2022 Gerrit Grunwald" \
112 | --description "Glucose status monitor" \
113 | --mac-package-name "GlucoStatusFX"
114 |
115 | done
116 |
117 | # ------ CHECKSUM FILE --------------------------------------------------------
118 | arch_name="$(uname -m)"
119 |
120 | if [ "${arch_name}" = "arm64" ]; then
121 | mv "build/installer/GlucoStatusFX-${APP_VERSION}.pkg" "build/installer/GlucoStatusFX-${APP_VERSION}-aarch64.pkg"
122 | shasum -a 256 "build/installer/GlucoStatusFX-${APP_VERSION}-aarch64.pkg" > "build/installer/GlucoStatusFX-${APP_VERSION}-aarch64.pkg.sha256"
123 | else
124 | shasum -a 256 "build/installer/GlucoStatusFX-${APP_VERSION}.pkg" > "build/installer/GlucoStatusFX-${APP_VERSION}.pkg.sha256"
125 | fi
126 |
--------------------------------------------------------------------------------
/build_app_windows.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | set JAVA_VERSION=23
4 | set MAIN_JAR=GlucoStatusFX-23.0.1.jar
5 | set APP_VERSION=23.0.1
6 |
7 | rem ------ SETUP DIRECTORIES AND FILES ----------------------------------------
8 | rem Remove previously generated java runtime and installers. Copy all required
9 | rem jar files into the input/libs folder.
10 |
11 | IF EXIST build\java-runtime rmdir /S /Q .\build\java-runtime
12 | IF EXIST build\installer rmdir /S /Q target\installer
13 |
14 | xcopy /S /Q build\libs\* build\installer\input\libs\
15 | copy build\libs\%MAIN_JAR% build\installer\input\libs\
16 |
17 | rem ------ REQUIRED MODULES ---------------------------------------------------
18 | rem Use jlink to detect all modules that are required to run the application.
19 | rem Starting point for the jdep analysis is the set of jars being used by the
20 | rem application.
21 |
22 | echo detecting required modules
23 |
24 | "%JAVA_HOME%\bin\jdeps" ^
25 | --multi-release %JAVA_VERSION% ^
26 | --ignore-missing-deps ^
27 | --class-path "build\installer\input\libs\*" ^
28 | --print-module-deps build\classes\java\main\eu\hansolo\fx\glucostatus\Main.class > temp.txt
29 |
30 | set /p detected_modules= "build\installer\GlucoStatusFX-%APP_VERSION%.msi.sha256"
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # SPDX-License-Identifier: Apache-2.0
3 | #
4 | # Copyright 2022 Gerrit Grunwald.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governi permissions and
16 | # limitations under the License.
17 | #
18 |
19 | sourceCompatibility = 21
20 | targetCompatibility = 21
21 |
22 | group = eu.hansolo
23 | version = 23.0.1
24 | javafxVersion = 23
25 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #
2 | # SPDX-License-Identifier: Apache-2.0
3 | #
4 | # Copyright 2022 Gerrit Grunwald.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | distributionBase=GRADLE_USER_HOME
20 | distributionPath=wrapper/dists
21 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
22 | zipStoreBase=GRADLE_USER_HOME
23 | zipStorePath=wrapper/dists
24 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # SPDX-License-Identifier: Apache-2.0
5 | #
6 | # Copyright 2022 Gerrit Grunwald.
7 | #
8 | # Licensed under the Apache License, Version 2.0 (the "License");
9 | # you may not use this file except in compliance with the License.
10 | # You may obtain a copy of the License at
11 | #
12 | # https://www.apache.org/licenses/LICENSE-2.0
13 | #
14 | # Unless required by applicable law or agreed to in writing, software
15 | # distributed under the License is distributed on an "AS IS" BASIS,
16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | # See the License for the specific language governing permissions and
18 | # limitations under the License.
19 | #
20 |
21 | ##############################################################################
22 | ##
23 | ## Gradle start up script for UN*X
24 | ##
25 | ##############################################################################
26 |
27 | # Attempt to set APP_HOME
28 | # Resolve links: $0 may be a link
29 | PRG="$0"
30 | # Need this for relative symlinks.
31 | while [ -h "$PRG" ] ; do
32 | ls=`ls -ld "$PRG"`
33 | link=`expr "$ls" : '.*-> \(.*\)$'`
34 | if expr "$link" : '/.*' > /dev/null; then
35 | PRG="$link"
36 | else
37 | PRG=`dirname "$PRG"`"/$link"
38 | fi
39 | done
40 | SAVED="`pwd`"
41 | cd "`dirname \"$PRG\"`/" >/dev/null
42 | APP_HOME="`pwd -P`"
43 | cd "$SAVED" >/dev/null
44 |
45 | APP_NAME="Gradle"
46 | APP_BASE_NAME=`basename "$0"`
47 |
48 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
49 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
50 |
51 | # Use the maximum available, or set MAX_FD != -1 to use that value.
52 | MAX_FD="maximum"
53 |
54 | warn () {
55 | echo "$*"
56 | }
57 |
58 | die () {
59 | echo
60 | echo "$*"
61 | echo
62 | exit 1
63 | }
64 |
65 | # OS specific support (must be 'true' or 'false').
66 | cygwin=false
67 | msys=false
68 | darwin=false
69 | nonstop=false
70 | case "`uname`" in
71 | CYGWIN* )
72 | cygwin=true
73 | ;;
74 | Darwin* )
75 | darwin=true
76 | ;;
77 | MSYS* | MINGW* )
78 | msys=true
79 | ;;
80 | NONSTOP* )
81 | nonstop=true
82 | ;;
83 | esac
84 |
85 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
86 |
87 |
88 | # Determine the Java command to use to start the JVM.
89 | if [ -n "$JAVA_HOME" ] ; then
90 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
91 | # IBM's JDK on AIX uses strange locations for the executables
92 | JAVACMD="$JAVA_HOME/jre/sh/java"
93 | else
94 | JAVACMD="$JAVA_HOME/bin/java"
95 | fi
96 | if [ ! -x "$JAVACMD" ] ; then
97 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
98 |
99 | Please set the JAVA_HOME variable in your environment to match the
100 | location of your Java installation."
101 | fi
102 | else
103 | JAVACMD="java"
104 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
105 |
106 | Please set the JAVA_HOME variable in your environment to match the
107 | location of your Java installation."
108 | fi
109 |
110 | # Increase the maximum file descriptors if we can.
111 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
112 | MAX_FD_LIMIT=`ulimit -H -n`
113 | if [ $? -eq 0 ] ; then
114 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
115 | MAX_FD="$MAX_FD_LIMIT"
116 | fi
117 | ulimit -n $MAX_FD
118 | if [ $? -ne 0 ] ; then
119 | warn "Could not set maximum file descriptor limit: $MAX_FD"
120 | fi
121 | else
122 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
123 | fi
124 | fi
125 |
126 | # For Darwin, add options to specify how the application appears in the dock
127 | if $darwin; then
128 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
129 | fi
130 |
131 | # For Cygwin or MSYS, switch paths to Windows format before running java
132 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
133 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
134 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
135 |
136 | JAVACMD=`cygpath --unix "$JAVACMD"`
137 |
138 | # We build the pattern for arguments to be converted via cygpath
139 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
140 | SEP=""
141 | for dir in $ROOTDIRSRAW ; do
142 | ROOTDIRS="$ROOTDIRS$SEP$dir"
143 | SEP="|"
144 | done
145 | OURCYGPATTERN="(^($ROOTDIRS))"
146 | # Add a user-defined pattern to the cygpath arguments
147 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
148 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
149 | fi
150 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
151 | i=0
152 | for arg in "$@" ; do
153 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
154 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
155 |
156 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
157 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
158 | else
159 | eval `echo args$i`="\"$arg\""
160 | fi
161 | i=`expr $i + 1`
162 | done
163 | case $i in
164 | 0) set -- ;;
165 | 1) set -- "$args0" ;;
166 | 2) set -- "$args0" "$args1" ;;
167 | 3) set -- "$args0" "$args1" "$args2" ;;
168 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
169 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
170 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
171 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
172 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
173 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
174 | esac
175 | fi
176 |
177 | # Escape application args
178 | save () {
179 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
180 | echo " "
181 | }
182 | APP_ARGS=`save "$@"`
183 |
184 | # Collect all arguments for the java command, following the shell quoting and substitution rules
185 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
186 |
187 | exec "$JAVACMD" "$@"
188 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/icon.afdesign:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/icon.afdesign
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/icon.png
--------------------------------------------------------------------------------
/icon_rounded.afdesign:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/icon_rounded.afdesign
--------------------------------------------------------------------------------
/releases/GlucoStatusFX-23.0.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/releases/GlucoStatusFX-23.0.0.jar
--------------------------------------------------------------------------------
/releases/GlucoStatusFX-23.0.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/releases/GlucoStatusFX-23.0.1.jar
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'GlucoStatusFX'
2 |
3 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/ButtonShape.java:
--------------------------------------------------------------------------------
1 | package eu.hansolo.fx.glucostatus;
2 |
3 | import eu.hansolo.toolboxfx.geom.Rectangle;
4 |
5 |
6 | public record ButtonShape(int daysToShow, Rectangle shape) { }
7 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/DataPoint.java:
--------------------------------------------------------------------------------
1 | package eu.hansolo.fx.glucostatus;
2 |
3 | public record DataPoint(double minValue, double maxValue, double avgValue, double percentile10, double percentile25, double percentile75, double percentile90, double median) { }
4 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/DayShape.java:
--------------------------------------------------------------------------------
1 | package eu.hansolo.fx.glucostatus;
2 |
3 | import eu.hansolo.toolboxfx.geom.Rectangle;
4 |
5 | import java.time.DayOfWeek;
6 |
7 |
8 | public record DayShape(DayOfWeek day, Rectangle shape) { }
9 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/Fonts.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus;
20 |
21 | import javafx.scene.text.Font;
22 |
23 |
24 | public class Fonts {
25 | private static final String SF_PRO_ROUNDED_REGULAR_NAME;
26 | private static final String SF_PRO_ROUNDED_SEMI_BOLD_NAME;
27 | private static final String SF_PRO_ROUNDED_BOLD_NAME;
28 | private static final String SF_PRO_TEXT_REGULAR_NAME;
29 | private static final String SF_PRO_TEXT_BOLD_NAME;
30 | //private static final String SF_COMPACT_DISPLAY_MEDIUM_NAME;
31 | //private static final String SF_COMPACT_DISPLAY_BOLD_NAME;
32 | private static String sfProRoundedSemiBoldName;
33 | private static String sfProRoundedRegularName;
34 | private static String sfProRoundedBoldName;
35 | private static String sfProTextRegularName;
36 | private static String sfProTextBoldName;
37 | //private static String sfCompactDisplayMediumName;
38 | //private static String sfCompactDisplayBoldName;
39 |
40 | static {
41 | try {
42 | sfProRoundedRegularName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/fx/glucostatus/SF-Pro-Rounded-Regular.ttf"), 10).getName();
43 | sfProRoundedSemiBoldName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/fx/glucostatus/SF-Pro-Rounded-Semibold.ttf"), 10).getName();
44 | sfProRoundedBoldName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/fx/glucostatus/SF-Pro-Rounded-Bold.ttf"), 10).getName();
45 | sfProTextRegularName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/fx/glucostatus/SF-Pro-Text-Regular.ttf"), 10).getName();
46 | sfProTextBoldName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/fx/glucostatus/SF-Pro-Text-Bold.ttf"), 10).getName();
47 | //sfCompactDisplayMediumName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/fx/glucostatus/SF-Compact-Display-Medium.ttf"), 10).getName();
48 | //sfCompactDisplayBoldName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/fx/glucostatus/SF-Compact-Display-Bold.ttf"), 10).getName();
49 | } catch (Exception exception) { }
50 | SF_PRO_ROUNDED_REGULAR_NAME = sfProRoundedRegularName;
51 | SF_PRO_ROUNDED_SEMI_BOLD_NAME = sfProRoundedSemiBoldName;
52 | SF_PRO_ROUNDED_BOLD_NAME = sfProRoundedBoldName;
53 | SF_PRO_TEXT_REGULAR_NAME = sfProTextRegularName;
54 | SF_PRO_TEXT_BOLD_NAME = sfProTextBoldName;
55 | //SF_COMPACT_DISPLAY_MEDIUM_NAME = sfCompactDisplayMediumName;
56 | //SF_COMPACT_DISPLAY_BOLD_NAME = sfCompactDisplayBoldName;
57 | }
58 |
59 |
60 | // ******************** Methods *******************************************
61 | public static Font sfProRoundedRegular(final double size) { return new Font(SF_PRO_ROUNDED_REGULAR_NAME, size); }
62 | public static Font sfProRoundedSemiBold(final double size) { return new Font(SF_PRO_ROUNDED_SEMI_BOLD_NAME, size); }
63 | public static Font sfProRoundedBold(final double size) { return new Font(SF_PRO_ROUNDED_BOLD_NAME, size); }
64 | public static Font sfProTextRegular(final double size) { return new Font(SF_PRO_TEXT_REGULAR_NAME, size); }
65 | public static Font sfProTextBold(final double size) { return new Font(SF_PRO_TEXT_BOLD_NAME, size); }
66 | //public static Font sfCompactDisplayMedium(final double size) { return new Font(SF_COMPACT_DISPLAY_MEDIUM_NAME, size); }
67 | //public static Font sfCompactDisplayBold(final double size) { return new Font(SF_COMPACT_DISPLAY_BOLD_NAME, size); }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/GlucoEntry.java:
--------------------------------------------------------------------------------
1 | package eu.hansolo.fx.glucostatus;
2 |
3 | import java.time.OffsetDateTime;
4 | import java.util.Objects;
5 |
6 |
7 | public record GlucoEntry(String id, double sgv, long datelong, OffsetDateTime date, String dateString, Trend trend, String direction, String device, String type, int utcOffset, int noise, double filtered, double unfiltered, int rssi,
8 | double delta, String sysTime) implements Comparable {
9 |
10 | @Override public int compareTo(final GlucoEntry other) { return Long.compare(datelong, other.datelong()); }
11 |
12 | @Override public boolean equals(final Object o) {
13 | if (this == o) { return true; }
14 | if (o == null || getClass() != o.getClass()) { return false; }
15 | GlucoEntry that = (GlucoEntry) o;
16 | return Double.compare(that.sgv, sgv) == 0 && datelong == that.datelong && utcOffset == that.utcOffset && noise == that.noise && Double.compare(that.filtered, filtered) == 0 && Double.compare(that.unfiltered, unfiltered) == 0 &&
17 | rssi == that.rssi && Double.compare(that.delta, delta) == 0 && id.equals(that.id) && Objects.equals(date, that.date) && Objects.equals(dateString, that.dateString) && trend == that.trend &&
18 | Objects.equals(direction, that.direction) && Objects.equals(device, that.device) && Objects.equals(type, that.type) && Objects.equals(sysTime, that.sysTime);
19 | }
20 |
21 | @Override public int hashCode() {
22 | return Objects.hash(id, sgv, datelong, date, dateString, trend, direction, device, type, utcOffset, noise, filtered, unfiltered, rssi, delta, sysTime);
23 | }
24 |
25 | @Override public String toString() {
26 | return new StringBuilder().append("{").append("\"date\":\"").append(Constants.DTF.format(date)).append("\",").append("\"sgv\":").append(sgv).append("}").toString();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/GlucoEntryDto.java:
--------------------------------------------------------------------------------
1 | package eu.hansolo.fx.glucostatus;
2 |
3 | import java.time.Instant;
4 | import java.time.OffsetDateTime;
5 | import java.time.ZoneId;
6 |
7 |
8 | public record GlucoEntryDto(String _id, double sgv, long date, String dateString, int trend, String direction, String device, String type, int utcOffset, String sysTime) {
9 | public GlucoEntry getGlucoEntry() {
10 | return new GlucoEntry(this._id, this.sgv, this.date, OffsetDateTime.ofInstant(Instant.ofEpochSecond(this.date), ZoneId.systemDefault()), dateString, Trend.getFromText(Integer.toString(this.trend)), direction, device, type,
11 | this.utcOffset, 0, 0, 0, 0, 0, this.sysTime);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/Interval.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus;
20 |
21 | import eu.hansolo.fx.glucostatus.i18n.I18nKeys;
22 | import eu.hansolo.fx.glucostatus.i18n.Translator;
23 |
24 | import java.time.format.DateTimeFormatter;
25 |
26 |
27 | public enum Interval {
28 | LAST_2160_HOURS(25_920, 2_160, 7_776_000, DateTimeFormatter.ofPattern("DD"), 0.75), // 90 Days
29 | LAST_720_HOURS(8_640, 720, 2_592_000, DateTimeFormatter.ofPattern("DD"), 0.75), // 30 Days
30 | LAST_336_HOURS(4_032, 336, 1_209_600, DateTimeFormatter.ofPattern("DD"), 1.0), // 14 Days
31 | LAST_168_HOURS(2_016, 168, 604_800, DateTimeFormatter.ofPattern("DD"), 1.0), // 7 Days
32 | LAST_72_HOURS(864, 72, 259_200, DateTimeFormatter.ofPattern("HH"), 1.5), // 3 Days
33 | LAST_48_HOURS(576, 48, 172_800, DateTimeFormatter.ofPattern("HH"), 1.5), // 2 Days
34 | LAST_24_HOURS(288, 24, 86_400, DateTimeFormatter.ofPattern("HH"), 1.5), // 1 Day
35 | LAST_12_HOURS(144, 12, 43_200, DateTimeFormatter.ofPattern("HH"), 2.0),
36 | LAST_6_HOURS(72, 6, 21_600, DateTimeFormatter.ofPattern("HH:mm"), 2.0),
37 | LAST_3_HOURS(36, 3, 10_800, DateTimeFormatter.ofPattern("HH:mm"), 2.0);
38 |
39 | private final Translator translator = new Translator(I18nKeys.RESOURCE_NAME);
40 | private final int noOfEntries;
41 | private final int hours;
42 | private final long seconds;
43 | private final DateTimeFormatter formatter;
44 | private final double lineWidth;
45 |
46 |
47 | // ******************** Constructors **************************************
48 | Interval(final int noOfEntries, final int hours, final int seconds, final DateTimeFormatter formatter, final double lineWidth) {
49 | this.noOfEntries = noOfEntries;
50 | this.hours = hours;
51 | this.seconds = seconds;
52 | this.formatter = formatter;
53 | this.lineWidth = lineWidth;
54 | }
55 |
56 |
57 | // ******************** Methods *******************************************
58 | public String getUiString() {
59 | switch(this) {
60 | case LAST_2160_HOURS -> { return translator.get(I18nKeys.TIME_RANGE_2160_HOURS); }
61 | case LAST_720_HOURS -> { return translator.get(I18nKeys.TIME_RANGE_720_HOURS); }
62 | case LAST_336_HOURS -> { return translator.get(I18nKeys.TIME_RANGE_336_HOURS); }
63 | case LAST_168_HOURS -> { return translator.get(I18nKeys.TIME_RANGE_168_HOURS); }
64 | case LAST_72_HOURS -> { return translator.get(I18nKeys.TIME_RANGE_72_HOURS); }
65 | case LAST_48_HOURS -> { return translator.get(I18nKeys.TIME_RANGE_48_HOURS); }
66 | case LAST_24_HOURS -> { return translator.get(I18nKeys.TIME_RANGE_24_HOURS); }
67 | case LAST_12_HOURS -> { return translator.get(I18nKeys.TIME_RANGE_12_HOURS); }
68 | case LAST_6_HOURS -> { return translator.get(I18nKeys.TIME_RANGE_6_HOURS); }
69 | case LAST_3_HOURS -> { return translator.get(I18nKeys.TIME_RANGE_3_HOURS); }
70 | default -> { return ""; }
71 | }
72 | }
73 |
74 | public int getNoOfEntries() { return noOfEntries; }
75 |
76 | public int getHours() { return hours; }
77 |
78 | public long getSeconds() { return seconds; }
79 |
80 | public DateTimeFormatter getFormatter() { return formatter; }
81 |
82 | public double getLineWidth() { return lineWidth; }
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/Launcher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus;
20 |
21 | public class Launcher {
22 | public static void main(String[] args) { Main.main(args); }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/PoincarePlot.java:
--------------------------------------------------------------------------------
1 | package eu.hansolo.fx.glucostatus;
2 |
3 | import eu.hansolo.toolbox.unit.UnitDefinition;
4 | import javafx.beans.DefaultProperty;
5 | import javafx.collections.ObservableList;
6 | import javafx.geometry.Insets;
7 | import javafx.scene.Node;
8 | import javafx.scene.canvas.Canvas;
9 | import javafx.scene.canvas.GraphicsContext;
10 | import javafx.scene.layout.Region;
11 | import javafx.scene.paint.Color;
12 | import javafx.scene.text.Font;
13 | import javafx.scene.text.TextAlignment;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | import static eu.hansolo.toolbox.Helper.clamp;
19 | import static eu.hansolo.toolbox.unit.UnitDefinition.MILLIGRAM_PER_DECILITER;
20 |
21 |
22 | @DefaultProperty("children")
23 | public class PoincarePlot extends Region {
24 | private static final double PREFERRED_WIDTH = 250;
25 | private static final double PREFERRED_HEIGHT = 250;
26 | private static final double MINIMUM_WIDTH = 50;
27 | private static final double MINIMUM_HEIGHT = 50;
28 | private static final double MAXIMUM_WIDTH = 1024;
29 | private static final double MAXIMUM_HEIGHT = 1024;
30 | private static final double MIN_SYMBOL_SIZE = 2;
31 | private static final double MAX_SYMBOL_SIZE = 6;
32 | private static final Insets GRAPH_INSETS = new Insets(5, 10, 5, 10);
33 | private double size;
34 | private double width;
35 | private double height;
36 | private double availableWidth;
37 | private double availableHeight;
38 | private double stepX;
39 | private double stepY;
40 | private double symbolSize;
41 | private double halfSymbolSize;
42 | private Canvas canvas;
43 | private GraphicsContext ctx;
44 | private Font ticklabelFont;
45 | private double min;
46 | private double max;
47 | private double range;
48 | private UnitDefinition unit;
49 | private List values;
50 |
51 |
52 | // ******************** Constructors **************************************
53 | public PoincarePlot() {
54 | loadSettings();
55 |
56 | values = new ArrayList<>();
57 |
58 | initGraphics();
59 | registerListeners();
60 | }
61 |
62 |
63 | // ******************** Initialization ************************************
64 | private void initGraphics() {
65 | if (Double.compare(getPrefWidth(), 0.0) <= 0 || Double.compare(getPrefHeight(), 0.0) <= 0 || Double.compare(getWidth(), 0.0) <= 0 || Double.compare(getHeight(), 0.0) <= 0) {
66 | if (getPrefWidth() > 0 && getPrefHeight() > 0) {
67 | setPrefSize(getPrefWidth(), getPrefHeight());
68 | } else {
69 | setPrefSize(PREFERRED_WIDTH, PREFERRED_HEIGHT);
70 | }
71 | }
72 |
73 | canvas = new Canvas(PREFERRED_WIDTH, PREFERRED_HEIGHT);
74 | ctx = canvas.getGraphicsContext2D();
75 |
76 | getChildren().setAll(canvas);
77 | }
78 |
79 | private void registerListeners() {
80 | widthProperty().addListener(o -> resize());
81 | heightProperty().addListener(o -> resize());
82 | }
83 |
84 |
85 | // ******************** Methods *******************************************
86 | @Override protected double computeMinWidth(final double height) { return MINIMUM_WIDTH; }
87 | @Override protected double computeMinHeight(final double width) { return MINIMUM_HEIGHT; }
88 | @Override protected double computePrefWidth(final double height) { return super.computePrefWidth(height); }
89 | @Override protected double computePrefHeight(final double width) { return super.computePrefHeight(width); }
90 | @Override protected double computeMaxWidth(final double height) { return MAXIMUM_WIDTH; }
91 | @Override protected double computeMaxHeight(final double width) { return MAXIMUM_HEIGHT; }
92 |
93 | @Override public ObservableList getChildren() { return super.getChildren(); }
94 |
95 | public void loadSettings() {
96 | min = PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MIN_VALUE);
97 | max = PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MAX_VALUE);
98 | range = max - min;
99 | unit = PropertyManager.INSTANCE.getBoolean(Constants.PROPERTIES_UNIT_MG) ? UnitDefinition.MILLIGRAM_PER_DECILITER : UnitDefinition.MILLIMOL_PER_LITER;
100 | }
101 |
102 | public void setValues(final UnitDefinition currentUnit, final List values) {
103 | this.unit = currentUnit;
104 | this.values.clear();
105 | this.values.addAll(values);
106 | redraw();
107 | }
108 |
109 |
110 | // ******************** Layout *******************************************
111 | @Override public void layoutChildren() {
112 | super.layoutChildren();
113 | }
114 |
115 | private void resize() {
116 | width = getWidth() - getInsets().getLeft() - getInsets().getRight();
117 | height = getHeight() - getInsets().getTop() - getInsets().getBottom();
118 | size = width < height ? width : height;
119 |
120 | if (width > 0 && height > 0) {
121 | canvas.setWidth(width);
122 | canvas.setHeight(height);
123 | canvas.relocate((getWidth() - width) * 0.5, (getHeight() - height) * 0.5);
124 |
125 | availableWidth = (width - GRAPH_INSETS.getLeft() - GRAPH_INSETS.getRight());
126 | availableHeight = (height - GRAPH_INSETS.getTop() - GRAPH_INSETS.getBottom());
127 | stepX = width / range;
128 | stepY = height / range;
129 | symbolSize = clamp(MIN_SYMBOL_SIZE, MAX_SYMBOL_SIZE, size * 0.016);
130 | halfSymbolSize = symbolSize * 0.5;
131 | ticklabelFont = Fonts.sfProTextRegular(10);
132 |
133 | redraw();
134 | }
135 | }
136 |
137 | private void redraw() {
138 | boolean darkMode = PropertyManager.INSTANCE.getBoolean(Constants.PROPERTIES_DARK_MODE, true);
139 |
140 | ctx.clearRect(0, 0, width, height);
141 | ctx.setFill(darkMode ? Constants.DARK_BACKGROUND : Color.rgb(255, 255, 255));
142 | ctx.fillRect(0, 0, width, height);
143 |
144 | ctx.setFont(ticklabelFont);
145 | ctx.setFill(darkMode ? Constants.BRIGHT_TEXT : Constants.DARK_TEXT);
146 | ctx.setStroke(darkMode ? Color.rgb(81, 80, 78) : Color.rgb(184, 183, 183));
147 | ctx.setLineDashes(3, 4);
148 | ctx.setLineWidth(1);
149 | List axisLabels = MILLIGRAM_PER_DECILITER == unit ? Constants.yAxisLabelsMgPerDeciliter : Constants.yAxisLabelsMmolPerLiter;
150 |
151 | ctx.setFill(darkMode ? Constants.BRIGHT_TEXT : Constants.DARK_TEXT);
152 | ctx.setTextAlign(TextAlignment.CENTER);
153 |
154 | // Draw horizontal grid lines
155 | ctx.setTextAlign(TextAlignment.RIGHT);
156 | double yLabelStep = availableHeight / axisLabels.size();
157 | for (int i = 0 ; i < axisLabels.size() ; i++) {
158 | double y = height - GRAPH_INSETS.getBottom() - i * yLabelStep - yLabelStep;
159 | ctx.strokeLine(GRAPH_INSETS.getLeft(), y, width - GRAPH_INSETS.getRight(), y);
160 | ctx.fillText(axisLabels.get(i), GRAPH_INSETS.getLeft() * 2.5, y + 4);
161 | }
162 |
163 | // Draw vertical grid lines
164 | ctx.setTextAlign(TextAlignment.RIGHT);
165 | double xLabelStep = availableWidth / axisLabels.size();
166 | for (int i = 0 ; i < axisLabels.size() ; i++) {
167 | double x = GRAPH_INSETS.getLeft() + i * xLabelStep + xLabelStep;
168 | ctx.strokeLine(x, GRAPH_INSETS.getTop(), x, height - GRAPH_INSETS.getBottom());
169 | ctx.fillText(axisLabels.get(i), x, height - GRAPH_INSETS.getBottom() * 0.25);
170 | }
171 |
172 | // Draw points
173 | for (int i = 0 ; i < values.size() - 2 ; i++) {
174 | final double value = values.get(i);
175 | final double nextValue = values.get(i + 1);
176 | final double x = value * stepX;
177 | final double y = (max - nextValue + min) * stepY;
178 | final Color fill = Helper.getColorForValue(unit, UnitDefinition.MILLIGRAM_PER_DECILITER == unit ? value : Helper.mgPerDeciliterToMmolPerLiter(value));
179 |
180 | ctx.setFill(fill);
181 | ctx.fillOval(x - halfSymbolSize, y - halfSymbolSize, symbolSize, symbolSize);
182 | }
183 | }
184 | }
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/PropertyManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus;
20 |
21 | import eu.hansolo.jdktools.versioning.VersionNumber;
22 |
23 | import java.io.File;
24 | import java.io.FileInputStream;
25 | import java.io.FileOutputStream;
26 | import java.io.IOException;
27 | import java.io.OutputStream;
28 | import java.nio.file.Files;
29 | import java.nio.file.Path;
30 | import java.nio.file.Paths;
31 | import java.util.Properties;
32 |
33 |
34 | public enum PropertyManager {
35 | INSTANCE;
36 |
37 | public static final String VERSION_PROPERTIES = "version.properties";
38 | public static final String GLUCO_STATUS_FX_PROPERTIES = "glucostatusfx.properties";
39 | public static final String VERSION = "version";
40 | private Properties properties;
41 | private Properties versionProperties;
42 |
43 |
44 | // ******************** Constructors **************************************
45 | PropertyManager() {
46 | properties = new Properties();
47 | // Load properties
48 | final String homeFilePath = new StringBuilder(Constants.HOME_FOLDER).append(GLUCO_STATUS_FX_PROPERTIES).toString();
49 |
50 | // Create properties file if not exists
51 | Path path = Paths.get(homeFilePath);
52 | if (!Files.exists(path)) { createProperties(properties); }
53 |
54 | // Load properties file
55 | try (FileInputStream propertiesFile = new FileInputStream(homeFilePath)) {
56 | properties.load(propertiesFile);
57 | } catch (IOException ex) {
58 | System.out.println("Error reading Gluco Status FX properties file. " + ex);
59 | }
60 |
61 | // If properties empty, fill with default values
62 | if (properties.isEmpty()) {
63 | createProperties(properties);
64 | }
65 |
66 | // Version number properties
67 | versionProperties = new Properties();
68 | try {
69 | versionProperties.load(Main.class.getResourceAsStream(VERSION_PROPERTIES));
70 | } catch (IOException ex) {
71 | System.out.println("Error reading version properties file. " + ex);
72 | }
73 | }
74 |
75 |
76 | // ******************** Methods *******************************************
77 | public Properties getProperties() { return properties; }
78 |
79 | public Object get(final String KEY) { return properties.getOrDefault(KEY, ""); }
80 | public void set(final String KEY, final String VALUE) {
81 | properties.setProperty(KEY, VALUE);
82 | try {
83 | properties.store(new FileOutputStream(String.join(File.separator, System.getProperty("user.dir"), GLUCO_STATUS_FX_PROPERTIES)), null);
84 | } catch (IOException exception) {
85 | System.out.println("Error writing properties file: " + exception);
86 | }
87 | }
88 |
89 | public String getString(final String key) { return getString(key, ""); }
90 | public String getString(final String key, final String defaultValue) { return properties.getOrDefault(key, defaultValue).toString(); }
91 | public void setString(final String key, final String value) { properties.setProperty(key, value); }
92 |
93 | public double getDouble(final String key) { return getDouble(key, 0); }
94 | public double getDouble(final String key, final double defaultValue) { return Double.parseDouble(properties.getOrDefault(key, Double.toString(defaultValue)).toString()); }
95 | public void setDouble(final String key, final double value) { properties.setProperty(key, Double.toString(value)); }
96 |
97 | public float getFloat(final String key) { return getFloat(key, 0); }
98 | public float getFloat(final String key, final float defaultValue) { return Float.parseFloat(properties.getOrDefault(key, Float.toString(defaultValue)).toString()); }
99 | public void setFloat(final String key, final float value) { properties.setProperty(key, Float.toString(value)); }
100 |
101 | public int getInt(final String key) { return getInt(key, 0); }
102 | public int getInt(final String key, final int defaultValue) { return Integer.parseInt(properties.getOrDefault(key, Integer.toString(defaultValue)).toString()); }
103 | public void setInt(final String key, final int value) { properties.setProperty(key, Integer.toString(value)); }
104 |
105 | public long getLong(final String key) { return getLong(key, 0); }
106 | public long getLong(final String key, final long defaultValue) { return Long.parseLong(properties.getOrDefault(key, Long.toString(defaultValue)).toString()); }
107 | public void setLong(final String key, final long value) { properties.setProperty(key, Long.toString(value)); }
108 |
109 | public boolean getBoolean(final String key) { return getBoolean(key, false); }
110 | public boolean getBoolean(final String key, final boolean defaultValue) { return Boolean.parseBoolean(properties.getOrDefault(key, Boolean.toString(defaultValue)).toString()); }
111 | public void setBoolean(final String key, final boolean value) { properties.setProperty(key, Boolean.toString(value)); }
112 |
113 | public boolean hasKey(final String key) { return properties.containsKey(key); }
114 |
115 |
116 | public void storeProperties() {
117 | if (null == properties) { return; }
118 | final String propFilePath = new StringBuilder(Constants.HOME_FOLDER).append(GLUCO_STATUS_FX_PROPERTIES).toString();
119 | try (OutputStream output = new FileOutputStream(propFilePath)) {
120 | properties.store(output, null);
121 | } catch (IOException ex) {
122 | ex.printStackTrace();
123 | }
124 | }
125 |
126 |
127 | public VersionNumber getVersionNumber() {
128 | return VersionNumber.fromText(versionProperties.getProperty(VERSION));
129 | }
130 |
131 |
132 | // ******************** Properties ****************************************
133 | private void createProperties(Properties properties) {
134 | final String propFilePath = new StringBuilder(Constants.HOME_FOLDER).append(GLUCO_STATUS_FX_PROPERTIES).toString();
135 | try (OutputStream output = new FileOutputStream(propFilePath)) {
136 | properties.put(Constants.PROPERTIES_NIGHTSCOUT_URL, "");
137 | properties.put(Constants.PROPERTIES_API_SECRET, "");
138 | properties.put(Constants.PROPERTIES_NIGHTSCOUT_TOKEN, "");
139 | properties.put(Constants.PROPERTIES_UNIT_MG, "TRUE");
140 | properties.put(Constants.PROPERTIES_SHOW_DELTA_CHART, "TRUE");
141 | properties.put(Constants.PROPERTIES_VOICE_OUTPUT, "FALSE");
142 | properties.put(Constants.PROPERTIES_VOICE_OUTPUT_INTERVAL, "5");
143 | properties.put(Constants.PROPERTIES_MIN_ACCEPTABLE_MIN, "60.0");
144 | properties.put(Constants.PROPERTIES_MIN_ACCEPTABLE_MAX, "70.0");
145 | properties.put(Constants.PROPERTIES_MIN_NORMAL_MIN, "70.0");
146 | properties.put(Constants.PROPERTIES_MIN_NORMAL_MAX, "80.0");
147 | properties.put(Constants.PROPERTIES_MAX_NORMAL_MIN, "120.0");
148 | properties.put(Constants.PROPERTIES_MAX_NORMAL_MAX, "160.0");
149 | properties.put(Constants.PROPERTIES_MAX_ACCEPTABLE_MIN, "120.0");
150 | properties.put(Constants.PROPERTIES_MAX_ACCEPTABLE_MAX, "250.0");
151 | properties.put(Constants.PROPERTIES_MIN_VALUE, "0.0");
152 | properties.put(Constants.PROPERTIES_MAX_VALUE, "400.0");
153 | properties.put(Constants.PROPERTIES_MIN_CRITICAL, "55.0");
154 | properties.put(Constants.PROPERTIES_MIN_ACCEPTABLE, "65.0");
155 | properties.put(Constants.PROPERTIES_MIN_NORMAL, "70.0");
156 | properties.put(Constants.PROPERTIES_MAX_NORMAL, "140.0");
157 | properties.put(Constants.PROPERTIES_MAX_ACCEPTABLE, "180.0");
158 | properties.put(Constants.PROPERTIES_MAX_CRITICAL, "350.0");
159 | properties.put(Constants.PROPERTIES_SHOW_LOW_VALUE_NOTIFICATION, "TRUE");
160 | properties.put(Constants.PROPERTIES_SHOW_ACCEPTABLE_LOW_VALUE_NOTIFICATION, "TRUE");
161 | properties.put(Constants.PROPERTIES_SHOW_ACCEPTABLE_HIGH_VALUE_NOTIFICATION, "TRUE");
162 | properties.put(Constants.PROPERTIES_SHOW_HIGH_VALUE_NOTIFICATION, "TRUE");
163 | properties.put(Constants.PROPERTIES_PLAY_SOUND_FOR_TOO_LOW_NOTIFICATION, "TRUE");
164 | properties.put(Constants.PROPERTIES_SPEAK_TOO_LOW_NOTIFICATION, "FALSE");
165 | properties.put(Constants.PROPERTIES_PLAY_SOUND_FOR_LOW_NOTIFICATION, "TRUE");
166 | properties.put(Constants.PROPERTIES_SPEAK_LOW_NOTIFICATION, "FALSE");
167 | properties.put(Constants.PROPERTIES_PLAY_SOUND_FOR_ACCEPTABLE_LOW_NOTIFICATION, "TRUE");
168 | properties.put(Constants.PROPERTIES_PLAY_SOUND_FOR_ACCEPTABLE_HIGH_NOTIFICATION, "TRUE");
169 | properties.put(Constants.PROPERTIES_PLAY_SOUND_FOR_HIGH_NOTIFICATION, "TRUE");
170 | properties.put(Constants.PROPERTIES_PLAY_SOUND_FOR_TOO_HIGH_NOTIFICATION, "TRUE");
171 | properties.put(Constants.PROPERTIES_CRITICAL_MAX_NOTIFICATION_INTERVAL, "5");
172 | properties.put(Constants.PROPERTIES_CRITICAL_MIN_NOTIFICATION_INTERVAL, "5");
173 | properties.put(Constants.PROPERTIES_DARK_MODE, "TRUE");
174 |
175 | properties.store(output, null);
176 | } catch (IOException ex) {
177 | ex.printStackTrace();
178 | }
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/Status.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus;
20 |
21 | import eu.hansolo.toolbox.unit.UnitDefinition;
22 | import javafx.scene.paint.Color;
23 |
24 |
25 | public enum Status {
26 | NONE(0, Constants.GRAY, Constants.GRAY),
27 | TOO_LOW(1, Constants.RED, Constants.BLUE),
28 | LOW(2, Constants.ORANGE, Constants.LIGHT_BLUE),
29 | ACCEPTABLE_LOW(3, Constants.YELLOW, Constants.DARK_GREEN),
30 | NORMAL(4, Constants.GREEN, Constants.GREEN),
31 | ACCEPTABLE_HIGH(5, Constants.YELLOW, Constants.YELLOW),
32 | HIGH(6, Constants.ORANGE, Constants.ORANGE),
33 | TOO_HIGH(7, Constants.RED, Constants.RED);
34 |
35 | private final int id;
36 | private final Color color;
37 | private final Color color2;
38 |
39 |
40 | // ******************** Constructors **************************************
41 | Status(final int id, final Color color, final Color color2) {
42 | this.id = id;
43 | this.color = color;
44 | this.color2 = color2;
45 | }
46 |
47 |
48 | // ******************** Methods *******************************************
49 | public int getId() { return id; }
50 |
51 | public Color getColor() { return color; }
52 |
53 | public Color getColor2() { return color2; }
54 |
55 |
56 | public static final Status getByValue(final UnitDefinition unit, final double value) {
57 | switch(unit) {
58 | case MILLIMOL_PER_LITER -> {
59 | if (value <= Helper.mgPerDeciliterToMmolPerLiter(PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MIN_CRITICAL))) {
60 | return TOO_LOW;
61 | } else if (Helper.mgPerDeciliterToMmolPerLiter(PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MIN_CRITICAL)) <= value && value < Helper.mgPerDeciliterToMmolPerLiter(PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MIN_ACCEPTABLE))) {
62 | return LOW;
63 | } else if (Helper.mgPerDeciliterToMmolPerLiter(PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MIN_ACCEPTABLE)) <= value && value < Helper.mgPerDeciliterToMmolPerLiter(PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MIN_NORMAL))) {
64 | return ACCEPTABLE_LOW;
65 | } else if (Helper.mgPerDeciliterToMmolPerLiter(PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MIN_NORMAL)) <= value && value < Helper.mgPerDeciliterToMmolPerLiter(PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MAX_NORMAL))) {
66 | return NORMAL;
67 | } else if (Helper.mgPerDeciliterToMmolPerLiter(PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MAX_NORMAL)) <= value && value < Helper.mgPerDeciliterToMmolPerLiter(PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MAX_ACCEPTABLE))) {
68 | return ACCEPTABLE_HIGH;
69 | } else if (Helper.mgPerDeciliterToMmolPerLiter(PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MAX_ACCEPTABLE)) <= value && value < Helper.mgPerDeciliterToMmolPerLiter(PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MAX_CRITICAL))) {
70 | return HIGH;
71 | } else if (value > Helper.mgPerDeciliterToMmolPerLiter(PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MAX_CRITICAL))) {
72 | return TOO_HIGH;
73 | } else {
74 | return NONE;
75 | }
76 | }
77 | default -> {
78 | if (value <= PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MIN_CRITICAL)) {
79 | return TOO_LOW;
80 | } else if (PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MIN_CRITICAL) <= value && value < PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MIN_ACCEPTABLE)) {
81 | return LOW;
82 | } else if (PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MIN_ACCEPTABLE) <= value && value < PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MIN_NORMAL)) {
83 | return ACCEPTABLE_LOW;
84 | } else if (PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MIN_NORMAL) <= value && value < PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MAX_NORMAL)) {
85 | return NORMAL;
86 | } else if (PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MAX_NORMAL) <= value && value < PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MAX_ACCEPTABLE)) {
87 | return ACCEPTABLE_HIGH;
88 | } else if (PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MAX_ACCEPTABLE) <= value && value < PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MAX_CRITICAL)) {
89 | return HIGH;
90 | } else if (value > PropertyManager.INSTANCE.getDouble(Constants.PROPERTIES_MAX_CRITICAL)) {
91 | return TOO_HIGH;
92 | } else {
93 | return NONE;
94 | }
95 | }
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/Trend.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus;
20 |
21 | import eu.hansolo.fx.glucostatus.i18n.I18nKeys;
22 |
23 | import java.util.Arrays;
24 | import java.util.Optional;
25 |
26 |
27 | public enum Trend {
28 | FLAT("Flat", 0, "\u2192", I18nKeys.TREND_FLAT),
29 | SINGLE_UP("SingleUp", 1, "\u2191", I18nKeys.TREND_SINGLE_UP),
30 | DOUBLE_UP("DoubleUp", 2, "\u2191\u2191", I18nKeys.TREND_DOUBLE_UP),
31 | DOUBLE_DOWN("DoubleDown", 3, "\u2193\u2193", I18nKeys.TREND_DOUBLE_DOWN),
32 | SINGLE_DOWN("SingleDown", 4, "\u2193", I18nKeys.TREND_SINGLE_DOWN),
33 | FORTY_FIVE_DOWN("FortyFiveDown", 5, "\u2198", I18nKeys.TREND_FORTY_FIVE_DOWN),
34 | FORTY_FIVE_UP("FortyFiveUp", 6, "\u2197", I18nKeys.TREND_FORTY_FIVE_UP),
35 | NONE("", 7, "", "");
36 |
37 | private final String textKey;
38 | private final int key;
39 | private final String symbol;
40 | private final String speakText;
41 |
42 |
43 | // ******************** Constructors **************************************
44 | Trend(final String textKey, final int key, final String symbol, final String speakText) {
45 | this.textKey = textKey;
46 | this.key = key;
47 | this.symbol = symbol;
48 | this.speakText = speakText;
49 | }
50 |
51 |
52 | // ******************** Methods *******************************************
53 | public String getTextKey() { return textKey; }
54 |
55 | public int getKey() { return key; }
56 |
57 | public String getSymbol() { return symbol; }
58 |
59 | public String getSpeakText() { return speakText; }
60 |
61 | public static Trend getFromText(final String text) {
62 | Optional optTrend = Arrays.stream(Trend.values()).filter(trend -> trend.getTextKey().toLowerCase().equals(text.toLowerCase())).findFirst();
63 | if (optTrend.isPresent()) {
64 | return optTrend.get();
65 | } else {
66 | optTrend = Arrays.stream(Trend.values()).filter(trend -> Integer.toString(trend.getKey()).equals(text)).findFirst();
67 | if (optTrend.isPresent()) {
68 | return optTrend.get();
69 | } else {
70 | return NONE;
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/ZoneCell.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus;
20 |
21 | import javafx.geometry.Pos;
22 | import javafx.scene.control.ContentDisplay;
23 | import javafx.scene.control.Label;
24 | import javafx.scene.control.ListCell;
25 | import javafx.scene.text.TextAlignment;
26 |
27 |
28 | public class ZoneCell extends ListCell {
29 | private Label zoneLabel;
30 |
31 |
32 | // ******************** Constructors **************************************
33 | public ZoneCell(final boolean darkMode) {
34 | zoneLabel = new Label();
35 | zoneLabel.setTextFill(darkMode ? Constants.BRIGHT_TEXT : Constants.DARK_TEXT);
36 | zoneLabel.setFont(Fonts.sfProTextRegular(12));
37 | zoneLabel.setAlignment(Pos.CENTER);
38 | zoneLabel.setTextAlignment(TextAlignment.CENTER);
39 | zoneLabel.setContentDisplay(ContentDisplay.CENTER);
40 | zoneLabel.setPrefWidth(Label.USE_COMPUTED_SIZE);
41 | zoneLabel.setMaxWidth(Double.MAX_VALUE);
42 | setStyle("-fx-background-color: transparent;");
43 | }
44 |
45 |
46 | // ******************** Methods *******************************************
47 | @Override protected void updateItem(final String zoneText, final boolean empty) {
48 | setText(null);
49 | if (empty || null == zoneText || zoneText.isEmpty()) {
50 | setGraphic(null);
51 | } else {
52 | zoneLabel.setText(zoneText);
53 | setGraphic(zoneLabel);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/i18n/DynamicMessage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus.i18n;
20 |
21 | import java.util.Objects;
22 |
23 |
24 | public class DynamicMessage {
25 | private final String key;
26 | private final Object[] values;
27 |
28 |
29 | // ******************** Constructors **************************************
30 | public DynamicMessage(final String key, final Object... values) {
31 | this.key = key;
32 | this.values = values;
33 | }
34 |
35 |
36 | // ******************** Methods *******************************************
37 | public String getKey() {
38 | return key;
39 | }
40 |
41 | public Object[] getValues() {
42 | return values;
43 | }
44 |
45 | public String getText(final Translator translator) {
46 | Objects.requireNonNull(translator);
47 | return translator.get(this);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/i18n/I18nKeys.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus.i18n;
20 |
21 | public interface I18nKeys {
22 | String RESOURCE_NAME = "eu.hansolo.fx.glucostatus.i18n.gsfx";
23 | String APP_NAME = "app_name";
24 | String MENU = "menu";
25 | String ABOUT_MENU_ITEM = "about_menu_item";
26 | String CHART_MENU_ITEM = "chart_menu_item";
27 | String PREFERENCES_MENU_ITEM = "preferences_menu_item";
28 | String QUIT_MENU_ITEM = "quit_menu_item";
29 | String ABOUT_ALERT_CLOSE_BUTTON = "about_alert_close_button";
30 | String BACK_BUTTON = "back_button";
31 | String SETTINGS_BUTTON = "settings_button";
32 | String DATE_TIME_FORMAT = "date_time_format";
33 | String DATE_FORMAT = "date_format";
34 | String TIME_FORMAT = "time_format";
35 | String TIME_NAME_2160_HOURS = "time_name_2160_hours";
36 | String TIME_NAME_720_HOURS = "time_name_720_hours";
37 | String TIME_NAME_336_HOURS = "time_name_336_hours";
38 | String TIME_NAME_168_HOURS = "time_name_168_hours";
39 | String TIME_NAME_72_HOURS = "time_name_72_hours";
40 | String TIME_NAME_48_HOURS = "time_name_48_hours";
41 | String TIME_NAME_24_HOURS = "time_name_24_hours";
42 | String TIME_NAME_12_HOURS = "time_name_12_hours";
43 | String TIME_NAME_6_HOURS = "time_name_6_hours";
44 | String TIME_NAME_3_HOURS = "time_name_3_hours";
45 | String TIME_RANGE_2160_HOURS = "time_range_2160_hours";
46 | String TIME_RANGE_720_HOURS = "time_range_720_hours";
47 | String TIME_RANGE_336_HOURS = "time_range_336_hours";
48 | String TIME_RANGE_168_HOURS = "time_range_168_hours";
49 | String TIME_RANGE_72_HOURS = "time_range_72_hours";
50 | String TIME_RANGE_48_HOURS = "time_range_48_hours";
51 | String TIME_RANGE_24_HOURS = "time_range_24_hours";
52 | String TIME_RANGE_12_HOURS = "time_range_12_hours";
53 | String TIME_RANGE_6_HOURS = "time_range_6_hours";
54 | String TIME_RANGE_3_HOURS = "time_range_3_hours";
55 | String STATUS_NAME_NONE = "status_name_none";
56 | String STATUS_NAME_TOO_LOW = "status_name_too_low";
57 | String STATUS_NAME_LOW = "status_name_low";
58 | String STATUS_NAME_ACCEPTABLE_LOW = "status_name_acceptable_low";
59 | String STATUS_NORMAL = "status_normal";
60 | String STATUS_ACCEPTABLE_HIGH = "status_acceptable_high";
61 | String STATUS_HIGH = "status_high";
62 | String STATUS_TOO_HIGH = "status_too_high";
63 | String PATTERN_TITLE = "pattern_title";
64 | String PATTERN_CLOSE_BUTTON = "pattern_close_button";
65 | String PATTERN_GENERALLY_TOO_HIGH = "pattern_generally_too_high";
66 | String PATTERN_GENERALLY_TOO_LOW = "pattern_generally_too_low";
67 | String HBA1C_RANGE = "hba1c_range";
68 | String MATRIX_TITLE = "matrix_title";
69 | String MATRIX_SUBTITLE = "matrix_subtitle";
70 | String MATRIX_CLOSE_BUTTON = "matrix_close_button";
71 | String STACKED_CHART_TITLE = "stacked_chart_title";
72 | String STACKED_CHART_SUBTITLE = "stacked_chart_subtitle";
73 | String STACKED_CHART_CLOSE_BUTTON = "stacked_chart_close_button";
74 | String STATISTICS_TITLE = "statistic_title";
75 | String STATISTICS_TOO_HIGH = "statistic_too_high";
76 | String STATISTICS_HIGH = "statistic_high";
77 | String STATISTICS_NORMAL = "statistic_normal";
78 | String STATISTICS_LOW = "statistic_low";
79 | String STATISTICS_TOO_LOW = "statistic_too_low";
80 | String STATISTICS_CLOSE_BUTTON = "statistic_close_button";
81 | String STATISTICS_LOW_ZONE = "statistic_low_zone";
82 | String STATISTICS_HIGH_ZONE = "statistic_high_zone";
83 | String STATISTICS_NIGHT = "statistic_night";
84 | String STATISTICS_MORNING = "statistic_morning";
85 | String STATISTICS_LUNCHTIME = "statistic_lunchtime";
86 | String STATISTICS_AFTERNOON = "statistic_afternoon";
87 | String STATISTICS_DAY = "statistic_day";
88 | String STATISTICS_EVENING = "statistic_evening";
89 | String NOTIFICATION_TITLE = "notification_title";
90 | String NOTIFICATION_GLUCOSE_TOO_HIGH = "notification_glucose_too_high";
91 | String NOTIFICATION_GLUCOSE_TOO_HIGH_SOON = "notification_glucose_soon_too_high";
92 | String NOTIFICATION_GLUCOSE_HIGH = "notification_glucose_high";
93 | String NOTIFICATION_GLUCOSE_HIGH_SOON = "notification_glucose_soon_high";
94 | String NOTIFICATION_GLUCOSE_A_BIT_HIGH = "notification_glucose_a_bit_high";
95 | String NOTIFICATION_GLUCOSE_LOW_SOON = "notification_glucose_soon_low";
96 | String NOTIFICATION_GLUCOSE_A_BIT_LOW = "notification_glucose_a_bit_low";
97 | String NOTIFICATION_GLUCOSE_TOO_LOW_SOON = "notification_glucose_soon_too_low";
98 | String NOTIFICATION_GLUCOSE_LOW = "notification_glucose_low";
99 | String NOTIFICATION_GLUCOSE_TOO_LOW = "notification_glucose_too_low";
100 | String SETTINGS_TITLE = "settings_title";
101 | String SETTINGS_DARK_MODE = "settings_dark_mode";
102 | String SETTINGS_NIGHTSCOUT_URL = "settings_nightscouturl";
103 | String SETTINGS_API_SECRET = "settings_api_secret";
104 | String SETTINGS_NIGHTSCOUT_TOKEN = "settings_nightscout_token";
105 | String SETTINGS_UNIT = "settings_unit";
106 | String SETTINGS_SHOW_DELTA_CHART = "settings_show_deltachart";
107 | String SETTINGS_VOICE_OUTPUT = "settings_voice_output";
108 | String SETTINGS_VOICE_OUTPUT_INTERVAL = "settings_voice_output_interval";
109 | String SETTINGS_NOTIFICATION_TITLE = "settings_notifications_title";
110 | String SETTINGS_TOO_LOW_VALUE_NOTIFICATION = "settings_too_low_value_notification";
111 | String SETTINGS_TOO_LOW_VALUE_NOTIFICATION_SOUND = "settings_too_low_value_notification_sound";
112 | String SETTINGS_TOO_LOW_VALUE_NOTIFICATION_SPEAK = "settings_too_low_value_notification_speak";
113 | String SETTINGS_LOW_VALUE_NOTIFICATION = "settings_low_value_notification";
114 | String SETTINGS_LOW_VALUE_NOTIFICATION_SOUND = "settings_low_value_notification_sound";
115 | String SETTINGS_LOW_VALUE_NOTIFICATION_SPEAK = "settings_low_value_notification_speak";
116 | String SETTINGS_ACCEPTABLE_LOW_VALUE_NOTIFICATION = "settings_acceptable_low_value_notification";
117 | String SETTINGS_ACCEPTABLE_LOW_VALUE_NOTIFICATION_SOUND = "settings_acceptable_low_value_notification_sound";
118 | String SETTINGS_ACCEPTABLE_HIGH_VALUE_NOTIFICATION = "settings_acceptable_high_value_notification";
119 | String SETTINGS_ACCEPTABLE_HIGH_VALUE_NOTIFICATION_SOUND = "settings_acceptable_high_value_notification_sound";
120 | String SETTINGS_HIGH_VALUE_NOTIFICATION = "settings_high_value_notification";
121 | String SETTINGS_HIGH_VALUE_NOTIFICATION_SOUND = "settings_high_value_notification_sound";
122 | String SETTINGS_TOO_HIGH_VALUE_NOTIFICATION = "settings_too_high_value_notification";
123 | String SETTINGS_TOO_HIGH_VALUE_NOTIFICATION_SOUND = "settings_too_high_value_notification_sound";
124 | String SETTINGS_TOO_LOW_NOTIFICATION_INTERVAL = "settings_too_low_notification_interval";
125 | String SETTINGS_TOO_HIGH_NOTIFICATION_INTERVAL = "settings_too_high_notification_interval";
126 | String SETTINGS_RANGES_TITLE = "settings_ranges_title";
127 | String SETTINGS_MIN_ACCEPTABLE = "settings_min_acceptable";
128 | String SETTINGS_MIN_NORMAL = "settings_min_normal";
129 | String SETTINGS_MAX_NORMAL = "settings_max_normal";
130 | String SETTINGS_MAX_ACCEPTABLE = "settings_max_acceptable";
131 | String SETTINGS_SMOOTHED_CHARS = "settings_smoothed_charts";
132 | String PREDICTION_TITLE_TOO_LOW = "prediction_title_too_low";
133 | String PREDICTION_TOO_LOW = "prediction_too_low";
134 | String PREDICTION_TITLE_TOO_HIGH = "prediction_title_too_high";
135 | String PREDICTION_TOO_HIGH = "prediction_too_high";
136 | String PATTERN_VIEW_NOT_PATTERNS = "pattern_view_no_patterns";
137 | String TREND_FLAT = "trend_flat";
138 | String TREND_SINGLE_UP = "trend_single_up";
139 | String TREND_DOUBLE_UP = "trend_double_up";
140 | String TREND_DOUBLE_DOWN = "trend_double_down";
141 | String TREND_SINGLE_DOWN = "trend_single_down";
142 | String TREND_FORTY_FIVE_DOWN = "trend_forty_five_down";
143 | String TREND_FORTY_FIVE_UP = "trend_forty_five_up";
144 | String RELOAD_BUTTON = "reload_button";
145 | String PATTERN_CHART_BUTTON = "pattern_chart_button";
146 | String THIRTY_DAY_CHART_BUTTON = "thirty_day_chart_button";
147 | String OVERLAY_CHART_BUTTON = "overlay_chart_button";
148 | String TIME_IN_RANGE_CHART_BUTTON = "time_in_range_chart_button";
149 | }
150 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/i18n/Internationalization.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus.i18n;
20 |
21 | import java.lang.ref.WeakReference;
22 | import java.util.List;
23 | import java.util.Locale;
24 | import java.util.Objects;
25 | import java.util.ResourceBundle;
26 | import java.util.concurrent.CopyOnWriteArrayList;
27 |
28 |
29 | public enum Internationalization {
30 | INSTANCE;
31 |
32 | private final List> localeObservers = new CopyOnWriteArrayList<>();
33 |
34 |
35 | // ******************** Constructors **************************************
36 | Internationalization() { }
37 |
38 |
39 | // ******************** Methods *******************************************
40 | public void addObserver(final LocaleObserver observer) {
41 | final WeakReference observerWeakReference = new WeakReference<>(observer);
42 | localeObservers.add(observerWeakReference);
43 | }
44 |
45 | public void setLocale(final Locale locale) {
46 | Locale.setDefault(locale);
47 | update();
48 | }
49 |
50 | public void update() {
51 | ResourceBundle.clearCache();
52 | localeObservers.stream()
53 | .map(o -> o.get())
54 | .filter(Objects::nonNull)
55 | .forEach(o -> o.onLocaleChanged(Locale.getDefault()));
56 | }
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/i18n/LocaleObserver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus.i18n;
20 |
21 | import java.util.Locale;
22 |
23 |
24 | @FunctionalInterface
25 | public interface LocaleObserver {
26 | void onLocaleChanged(Locale locale);
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/i18n/Translator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus.i18n;
20 |
21 | import java.text.MessageFormat;
22 | import java.util.Locale;
23 | import java.util.ResourceBundle;
24 |
25 |
26 | public class Translator {
27 | private final String bundleBaseName;
28 |
29 |
30 | // ******************** Constructors **************************************
31 | public Translator(String bundleBaseName) {
32 | this.bundleBaseName = bundleBaseName;
33 | }
34 |
35 |
36 | // ******************** Methods *******************************************
37 | public String get(final String key) {
38 | ResourceBundle resourceBundle = Utf8ResourceBundle.getBundle(bundleBaseName, Locale.getDefault());
39 | return resourceBundle.getString(key);
40 | }
41 |
42 | public String get(final DynamicMessage message) {
43 | return MessageFormat.format(get(message.getKey()), message.getValues());
44 | }
45 | }
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/i18n/Utf8ResourceBundle.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus.i18n;
20 |
21 | import java.io.UnsupportedEncodingException;
22 | import java.nio.charset.StandardCharsets;
23 | import java.util.Enumeration;
24 | import java.util.Locale;
25 | import java.util.MissingResourceException;
26 | import java.util.PropertyResourceBundle;
27 | import java.util.ResourceBundle;
28 | import java.util.Set;
29 |
30 |
31 | public class Utf8ResourceBundle {
32 | private final static String ISO_8859_1 = "ISO-8859-1";
33 | private final static String UTF_8 = "UTF-8";
34 |
35 |
36 | // ******************** Methods *******************************************
37 | public static final ResourceBundle getBundle(final String baseName, final Locale locale) {
38 | return createUtf8PropertyResourceBundle(ResourceBundle.getBundle(baseName, locale));
39 | }
40 |
41 | private static ResourceBundle createUtf8PropertyResourceBundle(final ResourceBundle bundle) {
42 | if (!(bundle instanceof PropertyResourceBundle)) { return bundle; }
43 | return new Utf8PropertyResourceBundle((PropertyResourceBundle) bundle);
44 | }
45 |
46 |
47 | // ******************** Inner classes *************************************
48 | private static class Utf8PropertyResourceBundle extends ResourceBundle {
49 | private final PropertyResourceBundle bundle;
50 |
51 |
52 | // ******************** Constructors **************************************
53 | private Utf8PropertyResourceBundle(final PropertyResourceBundle bundle) {
54 | this.bundle = bundle;
55 | }
56 |
57 |
58 | // ******************** Methods *******************************************
59 | @Override public String getBaseBundleName() {
60 | return bundle.getBaseBundleName();
61 | }
62 |
63 | @Override public Locale getLocale() {
64 | return bundle.getLocale();
65 | }
66 |
67 | @Override public boolean containsKey(final String key) {
68 | return bundle.containsKey(key);
69 | }
70 |
71 | @Override public Set keySet() {
72 | return bundle.keySet();
73 | }
74 |
75 | @Override public Enumeration getKeys() {
76 | return bundle.getKeys();
77 | }
78 |
79 | @Override protected Object handleGetObject(final String key) {
80 | try {
81 | final String value = bundle.getString(key);
82 | if (value == null) { return null; }
83 | try {
84 | return new String(value.getBytes(UTF_8), UTF_8);
85 | } catch (final UnsupportedEncodingException e) {
86 | throw new RuntimeException("Encoding not supported", e);
87 | }
88 | } catch (MissingResourceException e) {
89 | return key;
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/notification/Notification.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus.notification;
20 |
21 | import javafx.scene.image.Image;
22 |
23 |
24 | public record Notification (String title, String message, Image image) {
25 |
26 | // ******************** Constructors **************************************
27 | public Notification(final String title, final String message) {
28 | this(title, message, null);
29 | }
30 | public Notification(final String message, final Image image) {
31 | this("", message, image);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/notification/NotificationBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus.notification;
20 |
21 | import javafx.beans.property.ObjectProperty;
22 | import javafx.beans.property.Property;
23 | import javafx.beans.property.SimpleObjectProperty;
24 | import javafx.beans.property.SimpleStringProperty;
25 | import javafx.beans.property.StringProperty;
26 | import javafx.scene.image.Image;
27 |
28 | import java.util.Map;
29 | import java.util.concurrent.ConcurrentHashMap;
30 |
31 |
32 | public class NotificationBuilder> {
33 | private Map properties = new ConcurrentHashMap<>();
34 |
35 |
36 | // ******************** Constructors **************************************
37 | protected NotificationBuilder() {
38 | }
39 |
40 |
41 | // ******************** Methods *******************************************
42 | public final static NotificationBuilder create() {
43 | return new NotificationBuilder();
44 | }
45 |
46 | public final B title(final String title) {
47 | properties.put("title", new SimpleStringProperty(title));
48 | return (B) this;
49 | }
50 |
51 | public final B message(final String message) {
52 | properties.put("message", new SimpleStringProperty(message));
53 | return (B) this;
54 | }
55 |
56 | public final B image(final Image image) {
57 | properties.put("image", new SimpleObjectProperty<>(image));
58 | return (B) this;
59 | }
60 |
61 | public final Notification build() {
62 | final Notification notification;
63 | if (properties.keySet().contains("title") && properties.keySet().contains("message") && properties.keySet().contains("image")) {
64 | notification = new Notification(((StringProperty) properties.get("title")).get(), ((StringProperty) properties.get("message")).get(), ((ObjectProperty) properties.get("image")).get());
65 | } else if (properties.keySet().contains("title") && properties.keySet().contains("message")) {
66 | notification = new Notification(((StringProperty) properties.get("title")).get(), ((StringProperty) properties.get("message")).get());
67 | } else if (properties.keySet().contains("message") && properties.keySet().contains("image")) {
68 | notification = new Notification(((StringProperty) properties.get("message")).get(), ((ObjectProperty) properties.get("image")).get());
69 | } else {
70 | throw new IllegalArgumentException("Wrong or missing parameters.");
71 | }
72 | return notification;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/notification/NotificationEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus.notification;
20 |
21 | import javafx.event.Event;
22 | import javafx.event.EventTarget;
23 | import javafx.event.EventType;
24 |
25 |
26 | public class NotificationEvent extends Event {
27 | public static final EventType NOTIFICATION_PRESSED = new EventType(ANY, "NOTIFICATION_PRESSED");
28 | public static final EventType SHOW_NOTIFICATION = new EventType(ANY, "SHOW_NOTIFICATION");
29 | public static final EventType HIDE_NOTIFICATION = new EventType(ANY, "HIDE_NOTIFICATION");
30 |
31 | public final Notification notification;
32 |
33 |
34 | // ******************** Constructors **************************************
35 | public NotificationEvent(final Notification notification, final Object source, final EventTarget target, EventType type) {
36 | super(source, target, type);
37 | this.notification = notification;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/eu/hansolo/fx/glucostatus/notification/NotifierBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package eu.hansolo.fx.glucostatus.notification;
20 |
21 | import javafx.beans.property.DoubleProperty;
22 | import javafx.beans.property.ObjectProperty;
23 | import javafx.beans.property.Property;
24 | import javafx.beans.property.SimpleDoubleProperty;
25 | import javafx.beans.property.SimpleObjectProperty;
26 | import javafx.beans.property.SimpleStringProperty;
27 | import javafx.beans.property.StringProperty;
28 | import javafx.geometry.Pos;
29 | import javafx.stage.Stage;
30 | import javafx.util.Duration;
31 |
32 | import java.util.HashMap;
33 |
34 |
35 | public class NotifierBuilder> {
36 | private HashMap properties = new HashMap<>();
37 |
38 |
39 | // ******************** Constructors **************************************
40 | protected NotifierBuilder() {
41 | }
42 |
43 |
44 | // ******************** Methods *******************************************
45 | public final static NotifierBuilder create() {
46 | return new NotifierBuilder();
47 | }
48 |
49 | public final B owner(final Stage owner) {
50 | properties.put("stage", new SimpleObjectProperty<>(owner));
51 | return (B)this;
52 | }
53 |
54 | public final B popupLocation(final Pos location) {
55 | properties.put("popupLocation", new SimpleObjectProperty<>(location));
56 | return (B)this;
57 | }
58 |
59 | public final B width(final double width) {
60 | properties.put("width", new SimpleDoubleProperty(width));
61 | return (B) this;
62 | }
63 |
64 | public final B height(final double height) {
65 | properties.put("height", new SimpleDoubleProperty(height));
66 | return (B) this;
67 | }
68 |
69 | public final B spacingY(final double spacingY) {
70 | properties.put("spacingY", new SimpleDoubleProperty(spacingY));
71 | return (B) this;
72 | }
73 |
74 | public final B popupLifeTime(final Duration popupLifetime) {
75 | properties.put("popupLifeTime", new SimpleObjectProperty<>(popupLifetime));
76 | return (B) this;
77 | }
78 |
79 | public final B popupAnimationTime(final Duration popupAnimationTime) {
80 | properties.put("popupAnimationTime", new SimpleObjectProperty<>(popupAnimationTime));
81 | return (B) this;
82 | }
83 |
84 | public final B styleSheet(final String styleSheet) {
85 | properties.put("styleSheet", new SimpleStringProperty(styleSheet));
86 | return (B) this;
87 | }
88 |
89 | public final Notifier build() {
90 | final Notifier notifier = Notifier.INSTANCE;
91 | for (String key : properties.keySet()) {
92 | if ("owner".equals(key)) {
93 | notifier.setNotificationOwner(((ObjectProperty) properties.get(key)).get());
94 | } else if ("popupLocation".equals(key)) {
95 | notifier.setPopupLocation(null, ((ObjectProperty) properties.get(key)).get());
96 | } else if ("width".equals(key)) {
97 | notifier.setWidth(((DoubleProperty) properties.get(key)).get());
98 | } else if ("height".equals(key)) {
99 | notifier.setHeight(((DoubleProperty) properties.get(key)).get());
100 | } else if ("spacingY".equals(key)) {
101 | notifier.setSpacingY(((DoubleProperty) properties.get(key)).get());
102 | } else if ("popupLifeTime".equals(key)) {
103 | notifier.setPopupLifetime(((ObjectProperty) properties.get(key)).get());
104 | } else if ("popupAnimationTime".equals(key)) {
105 | notifier.setPopupAnimationTime(((ObjectProperty) properties.get(key)).get());
106 | } else if ("styleSheet".equals(key)) {
107 | notifier.setStyleSheet(((StringProperty) properties.get(key)).get());
108 | }
109 | }
110 | return notifier;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/src/main/java/module-info.java:
--------------------------------------------------------------------------------
1 | module eu.hansolo.fx.glucostatus {
2 | // Java
3 | requires java.base;
4 | requires java.net.http;
5 |
6 | // Java-FX
7 | requires javafx.base;
8 | requires javafx.graphics;
9 | requires javafx.controls;
10 | requires javafx.media;
11 | requires javafx.swing;
12 |
13 | // 3rd Party
14 | requires transitive eu.hansolo.jdktools;
15 | requires transitive eu.hansolo.toolbox;
16 | requires transitive eu.hansolo.toolboxfx;
17 | requires transitive eu.hansolo.applefx;
18 | requires com.google.gson;
19 | //requires com.dustinredmond.fxtrayicon;
20 | requires FXTrayIcon;
21 |
22 | exports eu.hansolo.fx.glucostatus;
23 | exports eu.hansolo.fx.glucostatus.notification;
24 | }
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/SF-Compact-Display-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/SF-Compact-Display-Bold.ttf
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/SF-Compact-Display-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/SF-Compact-Display-Medium.ttf
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/SF-Pro-Rounded-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/SF-Pro-Rounded-Bold.ttf
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/SF-Pro-Rounded-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/SF-Pro-Rounded-Regular.ttf
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/SF-Pro-Rounded-Semibold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/SF-Pro-Rounded-Semibold.ttf
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/SF-Pro-Text-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/SF-Pro-Text-Bold.ttf
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/SF-Pro-Text-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/SF-Pro-Text-Regular.ttf
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/alarm.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/alarm.wav
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/exclamationMark.svg:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
24 |
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/glucostatus.css:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | @font-face {
20 | font-family: "SF Pro";
21 | src: url('SF-Pro-Text-Regular.ttf');
22 | }
23 |
24 | .gluco-status {
25 |
26 | }
27 |
28 | /*
29 | .button {
30 | -fx-background-color : rgb(105, 103, 103);
31 | -fx-background-insets: 0 0 -1 0, 0, 1, 2;
32 | -fx-background-radius: 5;
33 | -fx-padding : 2 4 2 4;
34 | -fx-text-fill : white;
35 | -fx-alignment : CENTER;
36 | -fx-content-display : CENTER;
37 | }
38 |
39 | .toggle-button {
40 | -fx-background-color : transparent;
41 | -fx-background-insets: 0 0 -1 0, 0, 1, 2;
42 | -fx-background-radius: 0;
43 | -fx-padding : 2 4 2 4;
44 | -fx-text-fill : white;
45 | -fx-alignment : CENTER;
46 | -fx-content-display : CENTER;
47 | }
48 | .toggle-button:selected {
49 | -fx-background-color : rgb(105, 103, 103);
50 | -fx-background-radius: 5;
51 | }
52 | .toggle-button:pressed,
53 | .toggle-button:pressed:selected {
54 | -fx-background-color : rgb(125, 123, 123);
55 | -fx-background-radius: 5;
56 | }
57 |
58 | .button-bar {
59 | -fx-background-color : linear-gradient(to bottom, rgb(52, 51, 49) 0%, rgb(51, 49, 48) 85%, rgb(81, 80, 78) 100%), rgb(45, 43, 42);
60 | -fx-background-radius: 5, 4;
61 | -fx-background-insets: 0, 1;
62 | -fx-padding : 1;
63 | -fx-fill-height : true;
64 | -fx-spacing : 0;
65 | }
66 | */
67 |
68 | .dialog-button-bar {
69 | -fx-background-color : transparent;
70 | -fx-background-radius: 0;
71 | -fx-background-insets: 0;
72 | -fx-padding : 0;
73 | }
74 |
75 | /*
76 | .button {
77 | -fx-pref-height : 20;
78 | -fx-background-insets: 0, 0.5 0 0 0;
79 | -fx-background-color : linear-gradient(to bottom, rgb(136, 132, 132) 0%, rgb(26, 20, 21) 100%), rgb(89, 85, 85);
80 | -fx-background-radius: 5, 4;
81 | -fx-padding : 2 10 2 10;
82 | -fx-text-fill : white;
83 | -fx-alignment : CENTER;
84 | -fx-content-display : LEFT;
85 | -fx-font-family : 'SF Pro Regular';
86 | -fx-font-size : 13px;
87 | }
88 | .button:armed {
89 | -fx-alignment : CENTER;
90 | -fx-content-display : LEFT;
91 | -fx-pref-height : 20;
92 | -fx-background-color : derive(rgb(89, 85, 85), +10%), derive(rgb(89, 85, 85), +20%);
93 | -fx-background-insets: 0, 0.5 0 0 0;
94 | -fx-text-fill : white;
95 | }
96 | .button:disabled {
97 | -fx-background-color: rgb(89, 85, 85);
98 | -fx-text-fill : rgb(180, 180, 180);
99 | }
100 | */
101 |
102 | .list-view > .virtual-flow > .scroll-bar:horizontal {
103 | visibility : hidden;
104 | -fx-background : transparent;
105 | -fx-background-color : transparent;
106 | -fx-background-insets: 0;
107 | -fx-padding : 0;
108 | }
109 |
110 | .list-view > .virtual-flow > .scroll-bar:vertical {
111 | -fx-background : transparent;
112 | -fx-background-color : transparent;
113 | -fx-background-insets: 0;
114 | -fx-padding : 0;
115 | }
116 |
117 | /* Track */
118 | .list-view > .virtual-flow > .scroll-bar:horizontal .track {
119 | -fx-background-color : transparent;
120 | -fx-background-insets: 0;
121 | -fx-padding : 0;
122 | }
123 |
124 | .list-view > .virtual-flow > .scroll-bar:vertical .track {
125 | -fx-background-color : transparent;
126 | -fx-background-insets: 0;
127 | -fx-padding : 0;
128 | }
129 |
130 | /* Thumb */
131 | .list-view > .virtual-flow > .scroll-bar:horizontal .thumb {
132 | -fx-background-insets: 0;
133 | -fx-padding : 0;
134 | -fx-background-radius: 1em;
135 | -fx-background-color : #3A4A5B;
136 | }
137 | .list-view > .virtual-flow > .scroll-bar:horizontal .thumb:hover {
138 | -fx-background-color : #4A5A6B;
139 | }
140 | .list-view > .virtual-flow > .scroll-bar:horizontal .thumb:pressed {
141 | -fx-background-color : #4A5A6B;
142 | }
143 |
144 | .list-view > .virtual-flow > .scroll-bar:vertical .thumb {
145 | -fx-background-insets: 0;
146 | -fx-padding : 0;
147 | -fx-background-radius: 1em;
148 | -fx-background-color : #3A4A5B;
149 | }
150 | .list-view > .virtual-flow > .scroll-bar:vertical .thumb:hover {
151 | -fx-background-color : #4A5A6B;
152 | }
153 | .list-view > .virtual-flow > .scroll-bar:vertical .thumb:pressed {
154 | -fx-background-color : #4A5A6B;
155 | }
156 |
157 | /* Buttons */
158 | .list-view > .virtual-flow > .scroll-bar:horizontal > .increment-button {
159 | visibility : hidden;
160 | -fx-background-insets: 0;
161 | -fx-background-color : transparent;
162 | -fx-padding : 0;
163 | -fx-background-radius: 1em 0em 0em 1em;
164 | }
165 | .list-view > .virtual-flow > .scroll-bar:horizontal > .increment-button:hover {
166 | -fx-background-color : transparent;
167 | }
168 | .list-view > .virtual-flow > .scroll-bar:horizontal > .increment-button:pressed {
169 | -fx-background-color : transparent;
170 | }
171 | .list-view > .virtual-flow > .scroll-bar:horizontal > .increment-button > .increment-arrow {
172 | -fx-padding: 0;
173 | -fx-shape : null;
174 | -fx-effect : none;
175 | }
176 |
177 | .list-view > .virtual-flow > .scroll-bar:horizontal > .decrement-button {
178 | visibility : hidden;
179 | -fx-background-color : transparent;
180 | -fx-background-insets: 0;
181 | -fx-padding : 0;
182 | -fx-background-radius: 0em 1em 1em 0em;
183 | }
184 | .list-view > .virtual-flow > .scroll-bar:horizontal > .decrement-button:hover {
185 | -fx-background-color : transparent;
186 | }
187 | .list-view > .virtual-flow > .scroll-bar:horizontal > .decrement-button:pressed {
188 | -fx-background-color : transparent;
189 | }
190 | .list-view > .virtual-flow > .scroll-bar:horizontal > .decrement-button > .decrement-arrow {
191 | -fx-padding: 0;
192 | -fx-shape : null;
193 | -fx-effect : none;
194 | }
195 |
196 |
197 | .list-view > .virtual-flow > .scroll-bar:vertical > .increment-button {
198 | visibility : hidden;
199 | -fx-background-insets: 0;
200 | -fx-background-color : transparent;
201 | -fx-padding : 0;
202 | -fx-background-radius: 0em 0em 1em 1em;
203 | }
204 | .list-view > .virtual-flow > .scroll-bar:vertical > .increment-button:hover {
205 | -fx-background-color : transparent;
206 | }
207 | .list-view > .virtual-flow > .scroll-bar:vertical > .increment-button:pressed {
208 | -fx-background-color : transparent;
209 | }
210 | .list-view > .virtual-flow > .scroll-bar:vertical > .increment-button > .increment-arrow {
211 | -fx-padding: 0;
212 | -fx-shape : null;
213 | -fx-effect : none;
214 | }
215 |
216 | .list-view > .virtual-flow > .scroll-bar:vertical > .decrement-button {
217 | visibility : hidden;
218 | -fx-background-color : transparent;
219 | -fx-background-insets: 0;
220 | -fx-padding : 0;
221 | -fx-background-radius: 1em 1em 0em 0em;
222 | }
223 | .list-view > .virtual-flow > .scroll-bar:vertical > .decrement-button:hover {
224 | -fx-background-color : transparent;
225 | }
226 | .list-view > .virtual-flow > .scroll-bar:vertical > .decrement-button:pressed {
227 | -fx-background-color : transparent;
228 | }
229 | .list-view > .virtual-flow > .scroll-bar:vertical > .decrement-button > .decrement-arrow {
230 | -fx-padding: 0;
231 | -fx-shape : null;
232 | -fx-effect : none;
233 | }
234 |
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/i18n/gsfx.properties:
--------------------------------------------------------------------------------
1 | #
2 | # SPDX-License-Identifier: Apache-2.0
3 | #
4 | # Copyright 2022 Gerrit Grunwald.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 |
20 | app_name = Gluco Status FX
21 |
22 | menu = Menu
23 | about_menu_item = About
24 | chart_menu_item = Chart
25 | preferences_menu_item = Preferences
26 | quit_menu_item = Quit
27 |
28 | about_alert_close_button = Close
29 |
30 | back_button = back
31 | settings_button = Settings
32 |
33 | date_time_format = MM/dd/yy h\:mm a
34 | date_format = yyyy-MM-dd'T'HH\:mm\:ssZ
35 | time_format = h\:mm a
36 |
37 | time_name_2160_hours = 90 d
38 | time_name_720_hours = 30 d
39 | time_name_336_hours = 14 d
40 | time_name_168_hours = 7 d
41 | time_name_72_hours = 72 h
42 | time_name_48_hours = 48 h
43 | time_name_24_hours = 24 h
44 | time_name_12_hours = 12 h
45 | time_name_6_hours = 6 h
46 | time_name_3_hours = 3 h
47 |
48 | time_range_2160_hours = 90 Days
49 | time_range_720_hours = 30 Days
50 | time_range_336_hours = 14 Days
51 | time_range_168_hours = 7 Days
52 | time_range_72_hours = 72 Hours
53 | time_range_48_hours = 48 Hours
54 | time_range_24_hours = 24 Hours
55 | time_range_12_hours = 12 Hours
56 | time_range_6_hours = 6 Hours
57 | time_range_3_hours = 3 Hours
58 |
59 | status_name_none = None
60 | status_name_too_low = Too Low
61 | status_name_low = Low
62 | status_name_acceptable_low = Acceptable Low
63 | status_normal = Normal
64 | status_acceptable_high = Acceptable High
65 | status_high = High
66 | status_too_high = Too High
67 |
68 | pattern_title = Pattern 24h
69 | pattern_close_button = Close
70 | pattern_generally_too_high = Generally too high
71 | pattern_generally_too_low = Generally too low
72 |
73 | hba1c_range = (last 30 days)
74 |
75 | statistic_title = In target range
76 | statistic_too_high = Very high
77 | statistic_high = High
78 | statistic_normal = In target range
79 | statistic_low = Low
80 | statistic_too_low = Very low
81 | statistic_close_button = Close
82 | statistic_low_zone = Low values
83 | statistic_high_zone = High values
84 | statistic_night = overnight
85 | statistic_morning = in the morning
86 | statistic_lunchtime = during lunchtime
87 | statistic_afternoon = in the afternoon
88 | statistic_day = during daytime
89 | statistic_evening = in the evening
90 |
91 | matrix_title = Last 30 days
92 | matrix_subtitle = Daily average and\nPercentage in target range
93 | matrix_close_button = Close
94 |
95 | stacked_chart_title = Overlay selected days
96 | stacked_chart_subtitle = Overlay values from selected interval\nand selected day of week
97 | stacked_chart_close_button = Close
98 |
99 | notification_title = Attention
100 | notification_glucose_too_high = Glucose too high
101 | notification_glucose_soon_too_high = Glucose soon too high
102 | notification_glucose_high = Glucose high
103 | notification_glucose_soon_high = Glucose soon high
104 | notification_glucose_a_bit_high = Glucose a bit high
105 | notification_glucose_soon_low = Glucose soon low
106 | notification_glucose_a_bit_low = Glucose a bit low
107 | notification_glucose_soon_too_low = Glucose soon too low
108 | notification_glucose_low = Glucose low
109 | notification_glucose_too_low = Glucose too low
110 |
111 | settings_title = SETTINGS
112 | settings_dark_mode = Dark mode
113 | settings_nightscouturl = Nightscout URL
114 | settings_api_secret = API secret
115 | settings_nightscout_token = Token
116 | settings_unit = Unit
117 | settings_show_deltachart = Show chart of last 12 delta values
118 | settings_voice_output = Voice output
119 | settings_voice_output_interval = Voice output interval\:
120 | settings_notifications_title = Notifications
121 | settings_too_low_value_notification = Too low
122 | settings_too_low_value_notification_sound = Sound
123 | settings_too_low_value_notification_speak = Speak
124 | settings_low_value_notification = Low
125 | settings_low_value_notification_sound = Sound
126 | settings_low_value_notification_speak = Speak
127 | settings_acceptable_low_value_notification = Acceptable low
128 | settings_acceptable_low_value_notification_sound = Sound
129 | settings_acceptable_high_value_notification = Acceptable high
130 | settings_acceptable_high_value_notification_sound = Sound
131 | settings_high_value_notification = High
132 | settings_high_value_notification_sound = Sound
133 | settings_too_high_value_notification = Too high
134 | settings_too_high_value_notification_sound = Sound
135 | settings_too_low_notification_interval = Too low interval\:
136 | settings_too_high_notification_interval = Too high interval\:
137 | settings_ranges_title = Ranges
138 | settings_min_acceptable = Min acceptable
139 | settings_min_normal = Min normal
140 | settings_max_normal = Max normal
141 | settings_max_acceptable = Max acceptable
142 | settings_smoothed_charts = Smoothed charts
143 |
144 | prediction_title_too_low = Attention
145 | prediction_too_low = Glucose too low soon !
146 | prediction_title_too_high = Attention
147 | prediction_too_high = Glucose too high soon !
148 |
149 | pattern_view_no_patterns = No patterns found
150 |
151 | trend_flat = Steady
152 | trend_single_up = Rising
153 | trend_double_up = Strongly rising
154 | trend_double_down = Strongly falling
155 | trend_single_down = Falling
156 | trend_forty_five_down = Slightly falling
157 | trend_forty_five_up = Slightly rising
158 |
159 | reload_button = Reload
160 | pattern_chart_button = Patterns
161 | thirty_day_chart_button = Thirty days
162 | overlay_chart_button = Overlays
163 | time_in_range_chart_button = Time in range
164 |
165 |
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/i18n/gsfx_de.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/i18n/gsfx_de.properties
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/i18n/gsfx_en.properties:
--------------------------------------------------------------------------------
1 | #
2 | # SPDX-License-Identifier: Apache-2.0
3 | #
4 | # Copyright 2022 Gerrit Grunwald.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 |
20 | app_name = Gluco Status FX
21 |
22 | menu = Menu
23 | about_menu_item = About
24 | chart_menu_item = Chart
25 | preferences_menu_item = Preferences
26 | quit_menu_item = Quit
27 |
28 | about_alert_close_button = Close
29 |
30 | back_button = back
31 | settings_button = Settings
32 |
33 | date_time_format = dd.MM.yy HH\:mm
34 | date_format = dd-MM-yyyy'T'HH\:mm\:ssZ
35 | time_format = hh\:mm a
36 |
37 | time_name_2160_hours = 90 d
38 | time_name_720_hours = 30 d
39 | time_name_336_hours = 14 d
40 | time_name_168_hours = 7 d
41 | time_name_72_hours = 72 h
42 | time_name_48_hours = 48 h
43 | time_name_24_hours = 24 h
44 | time_name_12_hours = 12 h
45 | time_name_6_hours = 6 h
46 | time_name_3_hours = 3 h
47 |
48 | time_range_2160_hours = 90 Days
49 | time_range_720_hours = 30 Days
50 | time_range_336_hours = 14 Days
51 | time_range_168_hours = 7 Days
52 | time_range_72_hours = 72 Hours
53 | time_range_48_hours = 48 Hours
54 | time_range_24_hours = 24 Hours
55 | time_range_12_hours = 12 Hours
56 | time_range_6_hours = 6 Hours
57 | time_range_3_hours = 3 Hours
58 |
59 | status_name_none = None
60 | status_name_too_low = Too Low
61 | status_name_low = Low
62 | status_name_acceptable_low = Acceptable Low
63 | status_normal = Normal
64 | status_acceptable_high = Acceptable High
65 | status_high = High
66 | status_too_high = Too High
67 |
68 | pattern_title = Pattern 24h
69 | pattern_close_button = Close
70 | pattern_generally_too_high = Generally too high
71 | pattern_generally_too_low = Generally too low
72 |
73 | hba1c_range = (last 30 days)
74 |
75 | statistic_title = In target range
76 | statistic_too_high = Very high
77 | statistic_high = High
78 | statistic_normal = In target range
79 | statistic_low = Low
80 | statistic_too_low = Very low
81 | statistic_close_button = Close
82 | statistic_low_zone = Low values
83 | statistic_high_zone = High values
84 | statistic_night = overnight
85 | statistic_morning = in the morning
86 | statistic_lunchtime = during lunchtime
87 | statistic_afternoon = in the afternoon
88 | statistic_day = during daytime
89 | statistic_evening = in the evening
90 |
91 | matrix_title = Last 30 days
92 | matrix_subtitle = Daily average and\nPercentage in target range
93 | matrix_close_button = Close
94 |
95 | stacked_chart_title = Overlay selected days
96 | stacked_chart_subtitle = Overlay values from selected interval\nand selected day of week
97 | stacked_chart_close_button = Close
98 |
99 | notification_title = Attention
100 | notification_glucose_too_high = Glucose too high
101 | notification_glucose_soon_too_high = Glucose soon too high
102 | notification_glucose_high = Glucose high
103 | notification_glucose_soon_high = Glucose soon high
104 | notification_glucose_a_bit_high = Glucose a bit high
105 | notification_glucose_soon_low = Glucose soon low
106 | notification_glucose_a_bit_low = Glucose a bit low
107 | notification_glucose_soon_too_low = Glucose soon too low
108 | notification_glucose_low = Glucose low
109 | notification_glucose_too_low = Glucose too low
110 |
111 | settings_title = SETTINGS
112 | settings_dark_mode = Dark mode
113 | settings_nightscouturl = Nightscout URL
114 | settings_api_secret = API secret
115 | settings_nightscout_token = Token
116 | settings_unit = Unit
117 | settings_show_deltachart = Show chart of last 12 delta values
118 | settings_voice_output = Voice output
119 | settings_voice_output_interval = Voice output interval\:
120 | settings_notifications_title = Notifications
121 | settings_too_low_value_notification = Too low
122 | settings_too_low_value_notification_sound = Sound
123 | settings_too_low_value_notification_speak = Speak
124 | settings_low_value_notification = Low
125 | settings_low_value_notification_sound = Sound
126 | settings_low_value_notification_speak = Speak
127 | settings_acceptable_low_value_notification = Acceptable low
128 | settings_acceptable_low_value_notification_sound = Sound
129 | settings_acceptable_high_value_notification = Acceptable high
130 | settings_acceptable_high_value_notification_sound = Sound
131 | settings_high_value_notification = High
132 | settings_high_value_notification_sound = Sound
133 | settings_too_high_value_notification = Too high
134 | settings_too_high_value_notification_sound = Sound
135 | settings_too_low_notification_interval = Too low interval\:
136 | settings_too_high_notification_interval = Too high interval\:
137 | settings_ranges_title = Ranges
138 | settings_min_acceptable = Min acceptable
139 | settings_min_normal = Min normal
140 | settings_max_normal = Max normal
141 | settings_max_acceptable = Max acceptable
142 | settings_smoothed_charts = Smoothed charts
143 |
144 | prediction_title_too_low = Attention
145 | prediction_too_low = Glucose too low soon !
146 | prediction_title_too_high = Attention
147 | prediction_too_high = Glucose too high soon !
148 |
149 | pattern_view_no_patterns = No patterns found
150 |
151 | trend_flat = Steady
152 | trend_single_up = Rising
153 | trend_double_up = Strongly rising
154 | trend_double_down = Strongly falling
155 | trend_single_down = Falling
156 | trend_forty_five_down = Slightly falling
157 | trend_forty_five_up = Slightly rising
158 |
159 | reload_button = Reload
160 | pattern_chart_button = Patterns
161 | thirty_day_chart_button = Thirty days
162 | overlay_chart_button = Overlays
163 | time_in_range_chart_button = Time in range
164 |
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/i18n/gsfx_it.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/i18n/gsfx_it.properties
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/i18n/gsfx_nl.properties:
--------------------------------------------------------------------------------
1 | #
2 | # SPDX-License-Identifier: Apache-2.0
3 | #
4 | # Copyright 2022 Gerrit Grunwald.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 |
20 | app_name = Gluco Status FX
21 |
22 | menu = Menu
23 | about_menu_item = Over
24 | chart_menu_item = Grafiek
25 | preferences_menu_item = Verkeuren
26 | quit_menu_item = Stop
27 |
28 | about_alert_close_button = Sluiten
29 |
30 | back_button = Terug
31 | settings_button = Instellingen
32 |
33 | date_time_format = MM/dd/yy h\:mm a
34 | date_format = yyyy-MM-dd'T'HH\:mm\:ssZ
35 | time_format = h\:mm a
36 |
37 | time_name_2160_hours = 90 d
38 | time_name_720_hours = 30 d
39 | time_name_336_hours = 14 d
40 | time_name_168_hours = 7 d
41 | time_name_72_hours = 72 u
42 | time_name_48_hours = 48 u
43 | time_name_24_hours = 24 u
44 | time_name_12_hours = 12 u
45 | time_name_6_hours = 6 u
46 | time_name_3_hours = 3 u
47 |
48 | time_range_2160_hours = 90 dagen
49 | time_range_720_hours = 30 dagen
50 | time_range_336_hours = 14 dagen
51 | time_range_168_hours = 7 dagen
52 | time_range_72_hours = 72 uren
53 | time_range_48_hours = 48 uren
54 | time_range_24_hours = 24 uren
55 | time_range_12_hours = 12 uren
56 | time_range_6_hours = 6 uren
57 | time_range_3_hours = 3 uren
58 |
59 | status_name_none = Geen
60 | status_name_too_low = Te laag
61 | status_name_low = Laag
62 | status_name_acceptable_low = Aanvaardbaar laag
63 | status_normal = Normaal
64 | status_acceptable_high = Aanvaardbaar hoog
65 | status_high = Hoog
66 | status_too_high = Te hoog
67 |
68 | pattern_title = Patroon 24u
69 | pattern_close_button = Sluiten
70 | pattern_generally_too_high = Algemeen te hoog
71 | pattern_generally_too_low = Algemeen te laag
72 |
73 | hba1c_range = (laatste 30 dagen)
74 |
75 | statistic_title = Binnen juiste limieten
76 | statistic_too_high = Zeer hoog
77 | statistic_high = Hoog
78 | statistic_normal = Binnen ingestelde limiet
79 | statistic_low = Laag
80 | statistic_too_low = Zeer laag
81 | statistic_close_button = Sluiten
82 | statistic_low_zone = Lage waarden
83 | statistic_high_zone = Hoge waarden
84 | statistic_night = 's nachts
85 | statistic_morning = 's morgens
86 | statistic_lunchtime = 's middags
87 | statistic_afternoon = in de namiddag
88 | statistic_day = overdag
89 | statistic_evening = 's avonds
90 |
91 | matrix_title = Laatste 30 dagen
92 | matrix_subtitle = Dagelijks gemiddelde en\nPercentage in doelbereik
93 | matrix_close_button = Sluiten
94 |
95 | stacked_chart_title = Overlay van geselecteerde dagen
96 | stacked_chart_subtitle = Overlay-waarden van geselecteerd interval\nen geselecteerde dag van de week
97 | stacked_chart_close_button = Sluiten
98 |
99 | notification_title = Aandacht
100 | notification_glucose_too_high = Glucose te hoog
101 | notification_glucose_soon_too_high = Glucose binnenkort te hoog
102 | notification_glucose_high = Glucose hoog
103 | notification_glucose_soon_high = Glucose binnenkort hoog
104 | notification_glucose_a_bit_high = Glucose een beetje hoog
105 | notification_glucose_soon_low = Glucose binnenkort laag
106 | notification_glucose_a_bit_low = Glucose een beetje laag
107 | notification_glucose_soon_too_low = Glucose binnenkort te laag
108 | notification_glucose_low = Glucose laag
109 | notification_glucose_too_low = Glucose te laag
110 |
111 | settings_title = INSTELLINGEN
112 | settings_dark_mode = Donkere modus
113 | settings_nightscouturl = Nightscout URL
114 | settings_api_secret = API secret
115 | settings_nightscout_token = Token
116 | settings_unit = Eenheid
117 | settings_show_deltachart = Toon grafiek van de laatste 12 delta waardes
118 | settings_voice_output = Spraakuitvoer
119 | settings_voice_output_interval = Interval van de spraakuitvoer\:
120 | settings_notifications_title = Meldingen
121 | settings_too_low_value_notification = Te laag
122 | settings_too_low_value_notification_sound = Geluid
123 | settings_too_low_value_notification_speak = Spreek
124 | settings_low_value_notification = Laag
125 | settings_low_value_notification_sound = Geluid
126 | settings_low_value_notification_speak = Spreek
127 | settings_acceptable_low_value_notification = Aanvaardbaar laag
128 | settings_acceptable_low_value_notification_sound = Geluid
129 | settings_acceptable_high_value_notification = Aanvaardbaar hoog
130 | settings_acceptable_high_value_notification_sound = Geluid
131 | settings_high_value_notification = Hoog
132 | settings_high_value_notification_sound = Geluid
133 | settings_too_high_value_notification = Te hoog
134 | settings_too_high_value_notification_sound = Geluid
135 | settings_too_low_notification_interval = Te laag interval\:
136 | settings_too_high_notification_interval = Te hoog interval\:
137 | settings_ranges_title = Limieten
138 | settings_min_acceptable = Min aanvaardbaar
139 | settings_min_normal = Min normaal
140 | settings_max_normal = Max normaal
141 | settings_max_acceptable = Max aanvaardbaar
142 | settings_smoothed_charts = Afgeronde grafieken
143 |
144 | prediction_title_too_low = Opletten
145 | prediction_too_low = Glucose binnenkort te laag!
146 | prediction_title_too_high = Opletten
147 | prediction_too_high = Glucose binnenkort te hoog!
148 |
149 | pattern_view_no_patterns = Geen patronen gevonden
150 |
151 | trend_flat = Consistent
152 | trend_single_up = Stijgend
153 | trend_double_up = Sterk toenemend
154 | trend_double_down = Sterk dalend
155 | trend_single_down = Vallend
156 | trend_forty_five_down = Licht dalend
157 | trend_forty_five_up = Licht stijgend
158 |
159 | reload_button = Herladen
160 | pattern_chart_button = Steekproef
161 | thirty_day_chart_button = Dertig dagen
162 | overlay_chart_button = Overlays
163 | time_in_range_chart_button = Tijd in doelbereik
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/i18n/gsfx_us.properties:
--------------------------------------------------------------------------------
1 | #
2 | # SPDX-License-Identifier: Apache-2.0
3 | #
4 | # Copyright 2022 Gerrit Grunwald.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 |
20 | app_name = Gluco Status FX
21 |
22 | menu = Menu
23 | about_menu_item = About
24 | chart_menu_item = Chart
25 | preferences_menu_item = Preferences
26 | quit_menu_item = Quit
27 |
28 | about_alert_close_button = Close
29 |
30 | back_button = back
31 | settings_button = Settings
32 |
33 | date_time_format = MM/dd/yy h\:mm a
34 | date_format = yyyy-MM-dd'T'h\:mm\:ss a Z
35 | time_format = h\:mm a
36 |
37 | time_name_2160_hours = 90 d
38 | time_name_720_hours = 30 d
39 | time_name_336_hours = 14 d
40 | time_name_168_hours = 7 d
41 | time_name_72_hours = 72 h
42 | time_name_48_hours = 48 h
43 | time_name_24_hours = 24 h
44 | time_name_12_hours = 12 h
45 | time_name_6_hours = 6 h
46 | time_name_3_hours = 3 h
47 |
48 | time_range_2160_hours = 90 Days
49 | time_range_720_hours = 30 Days
50 | time_range_336_hours = 14 days
51 | time_range_168_hours = 7 Days
52 | time_range_72_hours = 72 Hours
53 | time_range_48_hours = 48 Hours
54 | time_range_24_hours = 24 Hours
55 | time_range_12_hours = 12 Hours
56 | time_range_6_hours = 6 Hours
57 | time_range_3_hours = 3 Hours
58 |
59 | status_name_none = None
60 | status_name_too_low = Too Low
61 | status_name_low = Low
62 | status_name_acceptable_low = Acceptable Low
63 | status_normal = Normal
64 | status_acceptable_high = Acceptable High
65 | status_high = High
66 | status_too_high = Too High
67 |
68 | pattern_title = Pattern 24h
69 | pattern_close_button = Close
70 | pattern_generally_too_high = Generally too high
71 | pattern_generally_too_low = Generally too low
72 |
73 | hba1c_range = (last 30 days)
74 |
75 | statistic_title = In target range
76 | statistic_too_high = Very high
77 | statistic_high = High
78 | statistic_normal = In target range
79 | statistic_low = Low
80 | statistic_too_low = Very low
81 | statistic_close_button = Close
82 | statistic_low_zone = Low values
83 | statistic_high_zone = High values
84 | statistic_night = overnight
85 | statistic_morning = in the morning
86 | statistic_lunchtime = during lunchtime
87 | statistic_afternoon = in the afternoon
88 | statistic_day = during daytime
89 | statistic_evening = in the evening
90 |
91 | matrix_title = Last 30 days
92 | matrix_subtitle = Daily average and\nPercentage in target range
93 | matrix_close_button = Close
94 |
95 | stacked_chart_title = Overlay selected days
96 | stacked_chart_subtitle = Overlay values from selected interval\nand selected day of week
97 | stacked_chart_close_button = Close
98 |
99 | notification_title = Attention
100 | notification_glucose_too_high = Glucose too high
101 | notification_glucose_soon_too_high = Glucose soon too high
102 | notification_glucose_high = Glucose high
103 | notification_glucose_soon_high = Glucose soon high
104 | notification_glucose_a_bit_high = Glucose a bit high
105 | notification_glucose_soon_low = Glucose soon low
106 | notification_glucose_a_bit_low = Glucose a bit low
107 | notification_glucose_soon_too_low = Glucose soon too low
108 | notification_glucose_low = Glucose low
109 | notification_glucose_too_low = Glucose too low
110 |
111 | settings_title = SETTINGS
112 | settings_dark_mode = Dark mode
113 | settings_nightscouturl = Nightscout URL
114 | settings_api_secret = API secret
115 | settings_nightscout_token = Token
116 | settings_unit = Unit
117 | settings_show_deltachart = Show chart of last 12 delta values
118 | settings_voice_output = Voice output
119 | settings_voice_output_interval = Voice output interval\:
120 | settings_notifications_title = Notifications
121 | settings_too_low_value_notification = Too low
122 | settings_too_low_value_notification_sound = Sound
123 | settings_too_low_value_notification_speak = Speak
124 | settings_low_value_notification = Low
125 | settings_low_value_notification_sound = Sound
126 | settings_low_value_notification_speak = Speak
127 | settings_acceptable_low_value_notification = Acceptable low
128 | settings_acceptable_low_value_notification_sound = Sound
129 | settings_acceptable_high_value_notification = Acceptable high
130 | settings_acceptable_high_value_notification_sound = Sound
131 | settings_high_value_notification = High
132 | settings_high_value_notification_sound = Sound
133 | settings_too_high_value_notification = Too high
134 | settings_too_high_value_notification_sound = Sound
135 | settings_too_low_notification_interval = Too low interval\:
136 | settings_too_high_notification_interval = Too high interval\:
137 | settings_ranges_title = Ranges
138 | settings_min_acceptable = Min acceptable
139 | settings_min_normal = Min normal
140 | settings_max_normal = Max normal
141 | settings_max_acceptable = Max acceptable
142 | settings_smoothed_charts = Smoothed charts
143 |
144 | prediction_title_too_low = Attention
145 | prediction_too_low = Glucose too low soon !
146 | prediction_title_too_high = Attention
147 | prediction_too_high = Glucose too high soon !
148 |
149 | pattern_view_no_patterns = No patterns found
150 |
151 | trend_flat = Steady
152 | trend_single_up = Rising
153 | trend_double_up = Strongly rising
154 | trend_double_down = Strongly falling
155 | trend_single_down = Falling
156 | trend_forty_five_down = Slightly falling
157 | trend_forty_five_up = Slightly rising
158 |
159 | reload_button = Reload
160 | pattern_chart_button = Patterns
161 | thirty_day_chart_button = Thirty days
162 | overlay_chart_button = Overlays
163 | time_in_range_chart_button = Time in range
164 |
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/icon.icns
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/icon.ico
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/icon128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/icon128x128.png
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/icon16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/icon16x16.png
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/icon256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/icon256x256.png
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/icon32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/icon32x32.png
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/icon48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/icon48x48.png
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/matrix.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/notification/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/notification/error.png
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/notification/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/notification/info.png
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/notification/notification.css:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | @font-face {
20 | font-family: "SF Pro";
21 | src: url('../SF-Pro-Text-Regular.ttf');
22 | }
23 | @font-face {
24 | font-family: "SF Pro";
25 | src: url('../SF-Pro-Text-Bold.ttf');
26 | }
27 | @font-face {
28 | font-family: "SF Compact Display";
29 | src: url('../SF-Compact-Display-Bold.ttf');
30 | }
31 | @font-face {
32 | font-family: "SF Compact Display";
33 | src: url('../SF-Compact-Display-Medium.ttf');
34 | }
35 |
36 | .root {
37 | -fx-background-color: transparent;
38 | -fx-fill : transparent;
39 | }
40 |
41 |
42 | /* Notifications for MacOS */
43 | .notification-mac {
44 | -fx-background-color : rgb(39, 25, 28);
45 | -fx-border-color : rgb(71, 59, 62);
46 | -fx-border-width : 1px;
47 | -fx-background-radius: 16.25px;
48 | -fx-border-radius : 16.25px;
49 | -fx-effect : none;
50 | -foreground-color : rgb(242, 241, 241);
51 | -background-color : rgb(119, 118, 118, 0.95);
52 | -icon-color : white;
53 | }
54 |
55 | .notification-mac .title {
56 | -fx-font-size : 1.0em;
57 | -fx-font-weight : bold;
58 | -fx-text-fill : rgba(242, 241, 241, 0.65);
59 | -fx-content-display : left;
60 | -fx-graphic-text-gap: 10px;
61 | -fx-font-family : "SF Pro Text";
62 | -fx-font-weight : bold;
63 | }
64 |
65 | .notification-mac .msg-area {
66 | -fx-background-color : transparent;
67 | -fx-background-insets: 0;
68 | -fx-font-size : 1.0em;
69 | -fx-text-fill : -foreground-color;
70 | -fx-wrap-text : true;
71 | -fx-font-family : "SF Compact Display";
72 | -fx-font-weight : medium;
73 | }
74 | .notification-mac .msg-area .content,
75 | .notification-mac .msg-area:focused .content {
76 | -fx-background-color : transparent;
77 | -fx-background-insets: 0;
78 | -fx-background-radius: 0;
79 | -fx-padding : 0px;
80 | }
81 | .notification-mac .msg-area > .scroll-pane {
82 | -fx-background-color : transparent;
83 | -fx-background-insets: 0;
84 | -fx-padding : 0;
85 | }
86 | .notification-mac .msg-area > .scroll-pane > .viewport {
87 | -fx-background-color : transparent;
88 | -fx-background-insets: 0;
89 | -fx-padding : 0;
90 | }
91 | .notification-mac .msg-area > .scroll-pane > .scroll-bar .increment-arrow,
92 | .notification-mac .msg-area > .scroll-pane > .scroll-bar .decrement-arrow {
93 | -fx-shape : "";
94 | -fx-background-insets: 2;
95 | -fx-padding : 0;
96 | }
97 | .notification-mac .msg-area > .scroll-pane > .scroll-bar:horizontal .thumb,
98 | .notification-mac .msg-area > .scroll-pane > .scroll-bar:vertical .thumb {
99 | -fx-background-color : rgba(0, 0, 0, 0.1);
100 | -fx-background-radius: 2em;
101 | }
102 | .notification-mac .msg-area > .scroll-pane > .scroll-bar:horizontal .thumb:hover,
103 | .notification-mac .msg-area > .scroll-pane > .scroll-bar:vertical .thumb:hover {
104 | -fx-background-color : rgba(0, 0, 0, 0.3);
105 | -fx-background-radius: 2em;
106 | }
107 | .notification-mac .msg-area > .scroll-pane > .scroll-bar:horizontal {
108 | visibility : hidden;
109 | -fx-background-insets: 0;
110 | -fx-padding : 0;
111 | }
112 | .notification-mac .msg-area > .scroll-pane > .scroll-bar:horizontal .track {
113 | -fx-background-color : -background-color;
114 | -fx-border-color : -background-color;
115 | -fx-background-radius: 0;
116 | -fx-border-radius : 2em;
117 | }
118 | .notification-mac .msg-area > .scroll-pane > .scroll-bar:horizontal > .increment-button,
119 | .notification-mac .msg-area > .scroll-pane > .scroll-bar:horizontal > .decrement-button {
120 | -fx-padding: 0;
121 | }
122 | .notification-mac .msg-area > .scroll-pane > .scroll-bar:vertical {
123 | visibility : hidden;
124 | -fx-background-insets: 0;
125 | -fx-padding : 0;
126 | }
127 | .notification-mac .msg-area > .scroll-pane > .scroll-bar:vertical .track {
128 | -fx-background-color : -background-color;
129 | -fx-border-color : -background-color;
130 | -fx-background-radius: 0;
131 | -fx-border-radius : 2em;
132 | }
133 | .notification-mac .msg-area > .scroll-pane > .scroll-bar:vertical > .increment-button,
134 | .notification-mac .msg-area > .scroll-pane > .scroll-bar:vertical > .decrement-button {
135 | -fx-padding: 0;
136 | }
137 | .notification-mac .msg-area > .scroll-pane > .corner {
138 | -fx-background-color: transparent;
139 | }
140 |
141 |
142 | /* Notifications for Windows 10 */
143 | .notification-win {
144 | -fx-background-color : rgb(31, 31, 31);
145 | -fx-border-color : rgb(31, 31, 31);
146 | -fx-border-width : 1px;
147 | -fx-background-radius: 0px;
148 | -fx-border-radius : 0px;
149 | -fx-effect : none;
150 | -foreground-color : rgb(160, 160, 160);
151 | -background-color : rgb(31, 31, 31);
152 | -icon-color : white;
153 | }
154 |
155 | .notification-win .title {
156 | -fx-font-size : 1em;
157 | -fx-font-weight : bold;
158 | -fx-text-fill : white;
159 | -fx-content-display : left;
160 | -fx-graphic-text-gap: 10px;
161 | }
162 |
163 | .notification-win .msg-area {
164 | -fx-background-color : -background-color;
165 | -fx-background-insets: 0;
166 | -fx-font-size : 1em;
167 | -fx-text-fill : -foreground-color;
168 | -fx-wrap-text : true;
169 | }
170 | .notification-win .msg-area .content,
171 | .notification-win .msg-area:focused .content {
172 | -fx-background-color : -background-color;
173 | -fx-background-insets: 0;
174 | -fx-background-radius: 0;
175 | -fx-padding : 0px;
176 | }
177 | .notification-win .msg-area > .scroll-pane {
178 | -fx-background-color : -background-color;
179 | -fx-background-insets: 0;
180 | -fx-padding : 0;
181 | }
182 | .notification-win .msg-area > .scroll-pane > .viewport {
183 | -fx-background-color : -background-color;
184 | -fx-background-insets: 0;
185 | -fx-padding : 0;
186 | }
187 | .notification-win .msg-area > .scroll-pane > .scroll-bar .increment-arrow,
188 | .notification-win .msg-area > .scroll-pane > .scroll-bar .decrement-arrow {
189 | -fx-shape : "";
190 | -fx-background-insets: 0;
191 | -fx-padding : 0;
192 | }
193 | .notification-win .msg-area > .scroll-pane > .scroll-bar:horizontal .thumb,
194 | .notification-win .msg-area > .scroll-pane > .scroll-bar:vertical .thumb {
195 | -fx-background-color : rgba(0, 0, 0, 0.1);
196 | -fx-background-radius: 0;
197 | }
198 | .notification-win .msg-area > .scroll-pane > .scroll-bar:horizontal .thumb:hover,
199 | .notification-win .msg-area > .scroll-pane > .scroll-bar:vertical .thumb:hover {
200 | -fx-background-color : rgba(0, 0, 0, 0.3);
201 | -fx-background-radius: 0;
202 | }
203 | .notification-win .msg-area > .scroll-pane > .scroll-bar:horizontal {
204 | visibility : hidden;
205 | -fx-background-insets: 0;
206 | -fx-padding : 0;
207 | }
208 | .notification-win .msg-area > .scroll-pane > .scroll-bar:horizontal .track {
209 | -fx-background-color : -background-color;
210 | -fx-border-color : -background-color;
211 | -fx-background-radius: 0;
212 | -fx-border-radius : 0;
213 | }
214 | .notification-win .msg-area > .scroll-pane > .scroll-bar:horizontal > .increment-button,
215 | .notification-win .msg-area > .scroll-pane > .scroll-bar:horizontal > .decrement-button {
216 | -fx-padding: 0;
217 | }
218 | .notification-win .msg-area > .scroll-pane > .scroll-bar:vertical {
219 | visibility : hidden;
220 | -fx-background-insets: 0;
221 | -fx-padding : 0;
222 | }
223 | .notification-win .msg-area > .scroll-pane > .scroll-bar:vertical .track {
224 | -fx-background-color : -background-color;
225 | -fx-border-color : -background-color;
226 | -fx-background-radius: 0;
227 | -fx-border-radius : 0;
228 | }
229 | .notification-win .msg-area > .scroll-pane > .scroll-bar:vertical > .increment-button,
230 | .notification-win .msg-area > .scroll-pane > .scroll-bar:vertical > .decrement-button {
231 | -fx-padding: 0;
232 | }
233 | .notification-win .msg-area > .scroll-pane > .corner {
234 | -fx-background-color: transparent;
235 | }
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/notification/success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/notification/success.png
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/notification/warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HanSolo/glucostatusfx/9c41e77b8b7debbed64a04f92660a2cb92a0d1c3/src/main/resources/eu/hansolo/fx/glucostatus/notification/warning.png
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/pattern.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/range.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/reload.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/settings.svg:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
24 |
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/stacked.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/thirty-day-view.css:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-License-Identifier: Apache-2.0
3 | *
4 | * Copyright 2022 Gerrit Grunwald.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | .thirty-day-view {
20 | -fx-background-color: white; /*rgb(226, 227, 229);*/
21 | }
22 | .thirty-day-view:dark {
23 | -fx-background-color: rgb(30, 28, 26);
24 | }
--------------------------------------------------------------------------------
/src/main/resources/eu/hansolo/fx/glucostatus/version.properties:
--------------------------------------------------------------------------------
1 | version=0
--------------------------------------------------------------------------------