├── .github └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── Overview.png ├── README.md ├── build.gradle ├── contributors.txt ├── gradle.properties ├── gradle ├── LICENSE_HEADER └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images ├── AmpSkin.png ├── BarSkin.png ├── BatterySkin.png ├── BulletChartSkin.png ├── ChargeSkin.png ├── ClockSkin.png ├── DBClockSkin.png ├── DashboardSkin.png ├── DesignClockSkin.png ├── DigitalClockSkin.png ├── DigitalSkin.png ├── FatClockSkin.png ├── FlatSkin.png ├── GaugeDescription.png ├── GaugeSkin.png ├── HSkin.png ├── IndicatorSkin.png ├── IndustrialClockSkin.png ├── KpiSkin.png ├── LcdClockSkin.png ├── LcdSkin.png ├── LevelSkin.png ├── LinearSkin.png ├── MedusaJS_Overview.png ├── Medusa_0.fw.png ├── MinimalClockSkin.png ├── ModernSkin.png ├── Overview.png ├── PearClockSkin.png ├── PlainClockSkin.png ├── QuarterSkin.png ├── RoundLcdClockSkin.png ├── SectionSkin.png ├── SimpleDigitalSkin.png ├── SimpleSectionSkin.png ├── SimpleSkin.png ├── SlimClockSkin.png ├── SlimSkin.png ├── SpaceXSkin.png ├── TextClockSkin.png ├── TileClockSkin.png ├── TileKpiSkin.png ├── TileSparklineSkin.png ├── TileTextKpiSkin.png ├── TinySkin.png ├── VSkin.png ├── WhiteSkin.png └── Yota2ClockSkin.png ├── license.txt ├── settings.gradle └── src └── main ├── java ├── eu │ └── hansolo │ │ └── medusa │ │ ├── Alarm.java │ │ ├── AlarmBuilder.java │ │ ├── Clock.java │ │ ├── ClockBuilder.java │ │ ├── Command.java │ │ ├── Demo.java │ │ ├── DemoLauncher.java │ │ ├── FGauge.java │ │ ├── FGaugeBuilder.java │ │ ├── Fonts.java │ │ ├── Gauge.java │ │ ├── GaugeBuilder.java │ │ ├── GaugeDesign.java │ │ ├── LcdDesign.java │ │ ├── LcdFont.java │ │ ├── Marker.java │ │ ├── MarkerBuilder.java │ │ ├── Needle.java │ │ ├── Section.java │ │ ├── SectionBuilder.java │ │ ├── Test.java │ │ ├── TestLauncher.java │ │ ├── TickLabelLocation.java │ │ ├── TickLabelOrientation.java │ │ ├── TickMarkType.java │ │ ├── TimeSection.java │ │ ├── TimeSectionBuilder.java │ │ ├── events │ │ ├── AlarmEvent.java │ │ ├── AlarmEventListener.java │ │ ├── TimeEvent.java │ │ ├── TimeEventListener.java │ │ ├── UpdateEvent.java │ │ └── UpdateEventListener.java │ │ ├── skins │ │ ├── AmpSkin.java │ │ ├── BarSkin.java │ │ ├── BatterySkin.java │ │ ├── BulletChartSkin.java │ │ ├── ChargeSkin.java │ │ ├── ClockSkin.java │ │ ├── ClockSkinBase.java │ │ ├── DBClockSkin.java │ │ ├── DashboardSkin.java │ │ ├── DesignClockSkin.java │ │ ├── DigitalClockSkin.java │ │ ├── DigitalSkin.java │ │ ├── FatClockSkin.java │ │ ├── FlatSkin.java │ │ ├── GaugeSkin.java │ │ ├── GaugeSkinBase.java │ │ ├── HSkin.java │ │ ├── IndicatorSkin.java │ │ ├── IndustrialClockSkin.java │ │ ├── KpiSkin.java │ │ ├── LcdClockSkin.java │ │ ├── LcdSkin.java │ │ ├── LevelSkin.java │ │ ├── LinearSkin.java │ │ ├── MinimalClockSkin.java │ │ ├── ModernSkin.java │ │ ├── MorphingClockSkin.java │ │ ├── NasaSkin.java │ │ ├── PearClockSkin.java │ │ ├── PlainAmpSkin.java │ │ ├── PlainClockSkin.java │ │ ├── QuarterSkin.java │ │ ├── RoundLcdClockSkin.java │ │ ├── SectionSkin.java │ │ ├── SimpleDigitalSkin.java │ │ ├── SimpleSectionSkin.java │ │ ├── SimpleSkin.java │ │ ├── SlimClockSkin.java │ │ ├── SlimSkin.java │ │ ├── SpaceXSkin.java │ │ ├── TextClockSkin.java │ │ ├── TileClockSkin.java │ │ ├── TileKpiSkin.java │ │ ├── TileSparklineSkin.java │ │ ├── TileTextKpiSkin.java │ │ ├── TinySkin.java │ │ ├── VSkin.java │ │ └── WhiteSkin.java │ │ └── tools │ │ ├── AngleConicalGradient.java │ │ ├── ConicalGradient.java │ │ ├── Data.java │ │ ├── GradientLookup.java │ │ ├── Helper.java │ │ ├── MarkerComparator.java │ │ ├── MovingAverage.java │ │ ├── SectionComparator.java │ │ ├── Statistics.java │ │ └── TimeSectionComparator.java └── module-info.java └── resources └── eu └── hansolo └── medusa ├── Estricta-Medium.otf ├── Estricta-MediumItalic.otf ├── Estricta-Regular.otf ├── Estricta-RegularItalic.otf ├── Lato-Bol.otf ├── Lato-Lig.otf ├── Lato-Reg.otf ├── Roboto-Bold.ttf ├── Roboto-Light.ttf ├── Roboto-Medium.ttf ├── Roboto-Regular.ttf ├── Roboto-Thin.ttf ├── RobotoCondensed-Bold.ttf ├── RobotoCondensed-Light.ttf ├── RobotoCondensed-Regular.ttf ├── clock.css ├── digital.ttf ├── digitalreadout.ttf ├── digitalreadoutb.ttf ├── elektra.ttf ├── framed-gauge.css └── gauge.css /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Java CI 3 | 4 | on: [push] 5 | 6 | jobs: 7 | test: 8 | runs-on: ${{ matrix.os }} 9 | strategy: 10 | matrix: 11 | os: [ubuntu-18.04, macOS-latest, windows-latest] 12 | java: [11, 11.0.3] 13 | fail-fast: false 14 | max-parallel: 4 15 | name: Test JDK ${{ matrix.java }}, ${{ matrix.os }} 16 | 17 | steps: 18 | - uses: actions/checkout@v1 19 | - name: Set up JDK 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: ${{ matrix.java }} 23 | - name: Build with Gradle 24 | run: ./gradlew build 25 | 26 | ... -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | medusa.iml 3 | build 4 | logos 5 | signing.properties 6 | cache.properties.lock 7 | fileHashes.bin 8 | fileSnapshots.bin 9 | outputFileStates.bin 10 | taskArtifacts.bin 11 | otherResources 12 | ._* 13 | .gradle 14 | .DS_Store 15 | /out 16 | /.nb-gradle/ 17 | /src/main/java/eu/hansolo/medusa/MedusaTest.java 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/Overview.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Medusa 2 | 3 |
4 | A JavaFX library for Gauges. The main focus of this project is to provide Gauges that can be configured in multiple ways. 5 | 6 | Donations are welcome at [Paypal](https://paypal.me/hans0l0) 7 | 8 | ## Overview 9 | ![Overview](https://github.com/HanSolo/Medusa/blob/master/Overview.png?raw=true) 10 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | /* 21 | * SPDX-License-Identifier: Apache-2.0 22 | * 23 | * Copyright 2016-2020 Gerrit Grunwald. 24 | * 25 | * Licensed under the Apache License, Version 2.0 (the "License"); 26 | * you may not use this file except in compliance with the License. 27 | * You may obtain a copy of the License at 28 | * 29 | * https://www.apache.org/licenses/LICENSE-2.0 30 | * 31 | * Unless required by applicable law or agreed to in writing, software 32 | * distributed under the License is distributed on an "AS IS" BASIS, 33 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 34 | * See the License for the specific language governing permissions and 35 | * limitations under the License. 36 | */ 37 | 38 | // Medusa main build file 39 | plugins { 40 | id 'idea' 41 | id 'java-library' 42 | id 'org.kordamp.gradle.java-project' 43 | id 'org.openjfx.javafxplugin' 44 | id 'biz.aQute.bnd.builder' 45 | } 46 | 47 | 48 | if (!project.hasProperty('bintrayUsername')) ext.bintrayUsername = '**undefined**' 49 | if (!project.hasProperty('bintrayApiKey')) ext.bintrayApiKey = '**undefined**' 50 | if (!project.hasProperty('sonatypeUsername')) ext.sonatypeUsername = '**undefined**' 51 | if (!project.hasProperty('sonatypePassword')) ext.sonatypePassword = '**undefined**' 52 | 53 | config { 54 | release = (rootProject.findProperty('release') ?: false).toBoolean() 55 | 56 | info { 57 | name = 'Medusa' 58 | description = 'Medusa is a JavaFX library containing gauges and clocks' 59 | vendor = 'Hansolo' 60 | inceptionYear = '2016' 61 | tags = ['javafx', 'gauges', 'clocks'] 62 | 63 | links { 64 | website = 'https://github.com/HanSolo/Medusax/wiki' 65 | issueTracker = 'https://github.com/HanSolo/Medusa/issues' 66 | scm = 'https://github.com/HanSolo/Medusa.git' 67 | } 68 | 69 | people { 70 | person { 71 | id = 'HanSolo' 72 | name = 'Gerrit Grunwald' 73 | url = 'https://harmoniccode.blogspot.com/' 74 | roles = ['developer'] 75 | } 76 | } 77 | 78 | credentials { 79 | sonatype { 80 | username = project.sonatypeUsername 81 | password = project.sonatypePassword 82 | } 83 | } 84 | 85 | repositories { 86 | repository { 87 | name = 'localRelease' 88 | url = "${project.rootProject.buildDir}/repos/local/release" 89 | } 90 | repository { 91 | name = 'localSnapshot' 92 | url = "${project.rootProject.buildDir}/repos/local/snapshot" 93 | } 94 | } 95 | } 96 | 97 | licensing { 98 | licenses { 99 | license { 100 | id = 'Apache-2.0' 101 | } 102 | } 103 | } 104 | 105 | bintray { 106 | enabled = true 107 | userOrg = 'hansolo' 108 | repo = 'Medusa' 109 | name = rootProject.name 110 | publish = config.release 111 | credentials { 112 | username = project.bintrayUsername 113 | password = project.bintrayApiKey 114 | } 115 | } 116 | 117 | publishing { 118 | signing = false 119 | releasesRepository = 'localRelease' 120 | snapshotsRepository = 'localSnapshot' 121 | } 122 | 123 | docs { 124 | javadoc { 125 | autoLinks { 126 | enabled = false 127 | } 128 | } 129 | } 130 | } 131 | 132 | normalization { 133 | runtimeClasspath { 134 | ignore('/META-INF/MANIFEST.MF') 135 | } 136 | } 137 | 138 | repositories { 139 | jcenter() 140 | mavenCentral() 141 | } 142 | 143 | javafx { 144 | version = javafxVersion 145 | modules = [ 'javafx.base', 'javafx.graphics', 'javafx.controls' ] 146 | } 147 | 148 | jar { 149 | manifest { 150 | attributes( 151 | 'Bundle-Name': project.name, 152 | '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', 153 | 'Bundle-Description': config.info.description, 154 | 'Bundle-SymbolicName': 'eu.hansolo', 155 | 'Export-Package': 'eu.hansolo.medusa,eu.hansolo.medusa.tools,eu.hansolo.medusa.skins,eu.hansolo.medusa.events' 156 | ) 157 | } 158 | } 159 | 160 | // start the demo from gradle 161 | task Demo(type: JavaExec) { 162 | main = "eu.hansolo.medusa.DemoLauncher" 163 | classpath = sourceSets.main.runtimeClasspath 164 | } 165 | 166 | // Only used for internal test 167 | task Test(type: JavaExec) { 168 | main = "eu.hansolo.medusa.TestLauncher" 169 | classpath = sourceSets.main.runtimeClasspath 170 | } 171 | 172 | publishing { 173 | publications { 174 | main(MavenPublication) { 175 | pom.withXml { 176 | asNode().dependencies.'*'.findAll { 177 | it.groupId.text() == 'org.openjfx' 178 | }.each { 179 | it.remove(it.classifier) 180 | } 181 | } 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /contributors.txt: -------------------------------------------------------------------------------- 1 | Gerrit Grunwald (han.solo.gg@gmail.com) 2 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-License-Identifier: Apache-2.0 3 | # 4 | # Copyright 2016-2021 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 | sourceCompatibility = 11 20 | targetCompatibility = 11 21 | 22 | group = eu.hansolo 23 | version = 11.7 24 | javafxVersion = 11.0.1 -------------------------------------------------------------------------------- /gradle/LICENSE_HEADER: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: Apache-2.0 2 | 3 | Copyright ${copyrightYear} ${author}. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | https://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-License-Identifier: Apache-2.0 3 | # 4 | # Copyright 2016-2020 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 | #Thu Dec 17 09:21:18 CET 2015 20 | distributionBase=GRADLE_USER_HOME 21 | distributionPath=wrapper/dists 22 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip 23 | zipStoreBase=GRADLE_USER_HOME 24 | zipStorePath=wrapper/dists 25 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /images/AmpSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/AmpSkin.png -------------------------------------------------------------------------------- /images/BarSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/BarSkin.png -------------------------------------------------------------------------------- /images/BatterySkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/BatterySkin.png -------------------------------------------------------------------------------- /images/BulletChartSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/BulletChartSkin.png -------------------------------------------------------------------------------- /images/ChargeSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/ChargeSkin.png -------------------------------------------------------------------------------- /images/ClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/ClockSkin.png -------------------------------------------------------------------------------- /images/DBClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/DBClockSkin.png -------------------------------------------------------------------------------- /images/DashboardSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/DashboardSkin.png -------------------------------------------------------------------------------- /images/DesignClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/DesignClockSkin.png -------------------------------------------------------------------------------- /images/DigitalClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/DigitalClockSkin.png -------------------------------------------------------------------------------- /images/DigitalSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/DigitalSkin.png -------------------------------------------------------------------------------- /images/FatClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/FatClockSkin.png -------------------------------------------------------------------------------- /images/FlatSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/FlatSkin.png -------------------------------------------------------------------------------- /images/GaugeDescription.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/GaugeDescription.png -------------------------------------------------------------------------------- /images/GaugeSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/GaugeSkin.png -------------------------------------------------------------------------------- /images/HSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/HSkin.png -------------------------------------------------------------------------------- /images/IndicatorSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/IndicatorSkin.png -------------------------------------------------------------------------------- /images/IndustrialClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/IndustrialClockSkin.png -------------------------------------------------------------------------------- /images/KpiSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/KpiSkin.png -------------------------------------------------------------------------------- /images/LcdClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/LcdClockSkin.png -------------------------------------------------------------------------------- /images/LcdSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/LcdSkin.png -------------------------------------------------------------------------------- /images/LevelSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/LevelSkin.png -------------------------------------------------------------------------------- /images/LinearSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/LinearSkin.png -------------------------------------------------------------------------------- /images/MedusaJS_Overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/MedusaJS_Overview.png -------------------------------------------------------------------------------- /images/Medusa_0.fw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/Medusa_0.fw.png -------------------------------------------------------------------------------- /images/MinimalClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/MinimalClockSkin.png -------------------------------------------------------------------------------- /images/ModernSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/ModernSkin.png -------------------------------------------------------------------------------- /images/Overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/Overview.png -------------------------------------------------------------------------------- /images/PearClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/PearClockSkin.png -------------------------------------------------------------------------------- /images/PlainClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/PlainClockSkin.png -------------------------------------------------------------------------------- /images/QuarterSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/QuarterSkin.png -------------------------------------------------------------------------------- /images/RoundLcdClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/RoundLcdClockSkin.png -------------------------------------------------------------------------------- /images/SectionSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/SectionSkin.png -------------------------------------------------------------------------------- /images/SimpleDigitalSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/SimpleDigitalSkin.png -------------------------------------------------------------------------------- /images/SimpleSectionSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/SimpleSectionSkin.png -------------------------------------------------------------------------------- /images/SimpleSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/SimpleSkin.png -------------------------------------------------------------------------------- /images/SlimClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/SlimClockSkin.png -------------------------------------------------------------------------------- /images/SlimSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/SlimSkin.png -------------------------------------------------------------------------------- /images/SpaceXSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/SpaceXSkin.png -------------------------------------------------------------------------------- /images/TextClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/TextClockSkin.png -------------------------------------------------------------------------------- /images/TileClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/TileClockSkin.png -------------------------------------------------------------------------------- /images/TileKpiSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/TileKpiSkin.png -------------------------------------------------------------------------------- /images/TileSparklineSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/TileSparklineSkin.png -------------------------------------------------------------------------------- /images/TileTextKpiSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/TileTextKpiSkin.png -------------------------------------------------------------------------------- /images/TinySkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/TinySkin.png -------------------------------------------------------------------------------- /images/VSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/VSkin.png -------------------------------------------------------------------------------- /images/WhiteSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/WhiteSkin.png -------------------------------------------------------------------------------- /images/Yota2ClockSkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/images/Yota2ClockSkin.png -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 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. -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | pluginManagement { 19 | repositories { 20 | jcenter() 21 | gradlePluginPortal() 22 | } 23 | plugins { 24 | id 'com.gradle.enterprise' version '3.5' 25 | id 'org.kordamp.gradle.java-project' version '0.42.1' 26 | id 'org.openjfx.javafxplugin' version '0.0.9' 27 | id 'biz.aQute.bnd.builder' version '5.2.0' 28 | } 29 | } 30 | 31 | rootProject.name = 'Medusa' 32 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/Alarm.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | 21 | import javafx.application.Platform; 22 | import javafx.beans.property.ObjectProperty; 23 | import javafx.beans.property.SimpleObjectProperty; 24 | import javafx.event.Event; 25 | import javafx.event.EventHandler; 26 | import javafx.event.EventTarget; 27 | import javafx.event.EventType; 28 | import javafx.scene.paint.Color; 29 | 30 | import java.time.ZonedDateTime; 31 | import java.time.temporal.ChronoUnit; 32 | import java.util.UUID; 33 | 34 | 35 | /** 36 | * Created by hansolo on 28.01.16. 37 | */ 38 | public class Alarm { 39 | public enum Repetition { ONCE, HALF_HOURLY, HOURLY, DAILY, WEEKLY } 40 | public static final boolean ARMED = true; 41 | public static final boolean UNARMED = false; 42 | 43 | public final AlarmMarkerEvent ALARM_MARKER_PRESSED_EVENT = new AlarmMarkerEvent(Alarm.this, null, AlarmMarkerEvent.ALARM_MARKER_PRESSED); 44 | public final AlarmMarkerEvent ALARM_MARKER_RELEASED_EVENT = new AlarmMarkerEvent(Alarm.this, null, AlarmMarkerEvent.ALARM_MARKER_RELEASED); 45 | 46 | private Repetition repetition; 47 | private ZonedDateTime time; 48 | private boolean armed; 49 | private String text; 50 | private Command command; 51 | private Color color; 52 | 53 | 54 | // ******************** Constructors ************************************** 55 | /** 56 | * Represents a point in time where something should be triggered. 57 | */ 58 | public Alarm() { 59 | this(Repetition.ONCE, ZonedDateTime.now().plus(5, ChronoUnit.MINUTES), true, "", null, Clock.DARK_COLOR); 60 | } 61 | public Alarm(final ZonedDateTime TIME) { 62 | this(Repetition.ONCE, TIME, true, "", null, Clock.DARK_COLOR); 63 | } 64 | public Alarm(final ZonedDateTime TIME, final Color COLOR) { 65 | this(Repetition.ONCE, TIME, true, "", null, COLOR); 66 | } 67 | public Alarm(final Repetition REPETITION, final ZonedDateTime TIME) { 68 | this(REPETITION, TIME, true, "", null, Clock.DARK_COLOR); 69 | } 70 | public Alarm(final Repetition REPETITION, final ZonedDateTime TIME, final Color COLOR) { 71 | this(REPETITION, TIME, true, "", null, COLOR); 72 | } 73 | public Alarm(final Repetition REPETITION, final ZonedDateTime TIME, final boolean ARMED) { 74 | this(REPETITION, TIME, ARMED, ""); 75 | } 76 | public Alarm(final Repetition REPETITION, final ZonedDateTime TIME, final boolean ARMED, final String TEXT) { 77 | this(REPETITION, TIME, ARMED, TEXT, null, Clock.DARK_COLOR); 78 | } 79 | public Alarm(final Repetition REPETITION, final ZonedDateTime TIME, final boolean ARMED, final String TEXT, final Command COMMAND) { 80 | this(REPETITION, TIME, ARMED, TEXT, COMMAND, Clock.DARK_COLOR); 81 | } 82 | public Alarm(final Repetition REPETITION, final ZonedDateTime TIME, final boolean ARMED, final String TEXT, final Command COMMAND, final Color COLOR) { 83 | repetition = REPETITION; 84 | time = TIME; 85 | armed = ARMED; 86 | text = TEXT; 87 | command = COMMAND; 88 | color = COLOR; 89 | } 90 | 91 | 92 | // ******************** Methods ******************************************* 93 | /** 94 | * Returns the repetition rate of the alarm. 95 | * The values are ONCE, HALF_HOURLY, HOURLY, DAILY, WEEKLY 96 | * @return the repetition rate of the alarm 97 | */ 98 | public Repetition getRepetition() { return repetition; } 99 | /** 100 | * Defines the repetition rate of the alarm. 101 | * The values are ONCE, HALF_HOURLY, HOURLY, DAILY, WEEKLY 102 | * @param REPETITION 103 | */ 104 | public void setRepetition(final Repetition REPETITION) { repetition = REPETITION; } 105 | 106 | /** 107 | * Returns the time of the alarm. 108 | * @return the time of the alarm 109 | */ 110 | public ZonedDateTime getTime() { return time; } 111 | /** 112 | * Defines the time of the alarm. 113 | * @param TIME 114 | */ 115 | public void setTime(final ZonedDateTime TIME) { time = TIME; } 116 | 117 | /** 118 | * Returns true if the alarm is activated. 119 | * If an alarm is not armed it will be drawn gray translucent. 120 | * @return true if the alarm is activated 121 | */ 122 | public boolean isArmed() { return armed; } 123 | /** 124 | * Defines if the alarm is activated. 125 | * If an alarm is not armed it will be drawn gray translucent. 126 | * @param ARMED 127 | */ 128 | public void setArmed(final boolean ARMED) { armed = ARMED; } 129 | 130 | /** 131 | * Returns the text that was defined for the alarm. 132 | * The text will be shown in tooltips. 133 | * @return the text that was defined for the alarm 134 | */ 135 | public String getText() { return text; } 136 | /** 137 | * Defines a text for the alarm. 138 | * The text will be shown in tooltips. 139 | * @param TEXT 140 | */ 141 | public void setText(final String TEXT) { text = TEXT; } 142 | 143 | /** 144 | * Returns an instance of a class that implements the Command interface. 145 | * This interface only contains one method execute() which will be called 146 | * when the alarm is triggered. With this one could execute specific tasks 147 | * defined in separate classes. 148 | * @return an instance of a class that implements the Command interface 149 | */ 150 | public Command getCommand() { return command; } 151 | /** 152 | * Defines a class that implements the Command interface and which execute() 153 | * method will be called when the alarm is triggered. 154 | * @param COMMAND 155 | */ 156 | public void setCommand(final Command COMMAND) { command = COMMAND; } 157 | public void executeCommand() { if (null != command) command.execute(); } 158 | 159 | /** 160 | * Returns the color that will be used to colorize the alarm in a clock. 161 | * @return the color that will be used to colorize the alarm 162 | */ 163 | public Color getColor() { return color; } 164 | /** 165 | * Defines the color that will be used to colorize the alarm 166 | * @param COLOR 167 | */ 168 | public void setColor(final Color COLOR) { color = COLOR; } 169 | 170 | @Override public String toString() { 171 | return new StringBuilder() 172 | .append("{\n") 173 | .append("\"reptition\":\"").append(repetition.name()).append("\",\n") 174 | .append("\"time\":\"").append(time).append("\",\n") 175 | .append("\"armed\":").append(armed).append(",\n") 176 | .append("\"color\":\"").append(getColor().toString().substring(0,8).replace("0x", "#")).append("\",\n") 177 | .append("\"text\":\"").append(text).append("\"\n") 178 | .append("}") 179 | .toString(); 180 | } 181 | 182 | 183 | // ******************** Event Handling ************************************ 184 | public final ObjectProperty> onMarkerPressedProperty() { return onMarkerPressed; } 185 | public final void setOnMarkerPressed(EventHandler value) { onMarkerPressedProperty().set(value); } 186 | public final EventHandler getOnMarkerPressed() { return onMarkerPressedProperty().get(); } 187 | private ObjectProperty> onMarkerPressed = new SimpleObjectProperty<>(Alarm.this, "onMarkerPressed"); 188 | 189 | public final ObjectProperty> onMarkerReleasedProperty() { return onMarkerReleased; } 190 | public final void setOnMarkerReleased(EventHandler value) { onMarkerReleasedProperty().set(value); } 191 | public final EventHandler getOnMarkerReleased() { return onMarkerReleasedProperty().get(); } 192 | private ObjectProperty> onMarkerReleased = new SimpleObjectProperty<>(Alarm.this, "onMarkerReleased"); 193 | 194 | public void fireAlarmMarkerEvent(final AlarmMarkerEvent EVENT) { 195 | final EventHandler HANDLER; 196 | final EventType TYPE = EVENT.getEventType(); 197 | 198 | if (AlarmMarkerEvent.ALARM_MARKER_PRESSED == TYPE) { 199 | HANDLER = getOnMarkerPressed(); 200 | } else if (AlarmMarkerEvent.ALARM_MARKER_RELEASED == TYPE) { 201 | HANDLER = getOnMarkerReleased(); 202 | } else { 203 | HANDLER = null; 204 | } 205 | if (null == HANDLER) return; 206 | Platform.runLater(() -> HANDLER.handle(EVENT)); 207 | } 208 | 209 | 210 | // ******************** Inner Classes ************************************* 211 | public static class AlarmMarkerEvent extends Event {; 212 | public static final EventType ALARM_MARKER_PRESSED = new EventType(ANY, "ALARM_MARKER_PRESSED" + UUID.randomUUID().toString()); 213 | public static final EventType ALARM_MARKER_RELEASED = new EventType(ANY, "ALARM_MARKER_RELEASED" + UUID.randomUUID().toString()); 214 | 215 | 216 | // ******************** Constructors ************************************** 217 | public AlarmMarkerEvent(final Object SOURCE, final EventTarget TARGET, EventType TYPE) { 218 | super(SOURCE, TARGET, TYPE); 219 | } 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/AlarmBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | import eu.hansolo.medusa.Alarm.AlarmMarkerEvent; 21 | import eu.hansolo.medusa.Alarm.Repetition; 22 | import javafx.beans.property.BooleanProperty; 23 | import javafx.beans.property.ObjectProperty; 24 | import javafx.beans.property.Property; 25 | import javafx.beans.property.SimpleBooleanProperty; 26 | import javafx.beans.property.SimpleObjectProperty; 27 | import javafx.beans.property.SimpleStringProperty; 28 | import javafx.beans.property.StringProperty; 29 | import javafx.event.EventHandler; 30 | import javafx.scene.paint.Color; 31 | 32 | import java.time.ZonedDateTime; 33 | import java.util.HashMap; 34 | 35 | 36 | /** 37 | * Created by hansolo on 31.01.16. 38 | */ 39 | public class AlarmBuilder> { 40 | private HashMap properties = new HashMap<>(); 41 | 42 | 43 | // ******************** Constructors ************************************** 44 | protected AlarmBuilder() {} 45 | 46 | 47 | // ******************** Methods ******************************************* 48 | public static final AlarmBuilder create() { 49 | return new AlarmBuilder(); 50 | } 51 | 52 | public final B time(final ZonedDateTime DATE_TIME) { 53 | properties.put("time", new SimpleObjectProperty(DATE_TIME)); 54 | return (B)this; 55 | } 56 | 57 | public final B repetition(final Repetition REPETITION) { 58 | properties.put("repetition", new SimpleObjectProperty(REPETITION)); 59 | return (B)this; 60 | } 61 | 62 | public final B text(final String TEXT) { 63 | properties.put("text", new SimpleStringProperty(TEXT)); 64 | return (B)this; 65 | } 66 | 67 | public final B armed(final boolean ARMED) { 68 | properties.put("armed", new SimpleBooleanProperty(ARMED)); 69 | return (B)this; 70 | } 71 | 72 | public final B command(final Command COMMAND) { 73 | properties.put("command", new SimpleObjectProperty<>(COMMAND)); 74 | return (B)this; 75 | } 76 | 77 | public final B color(final Color COLOR) { 78 | properties.put("color", new SimpleObjectProperty<>(COLOR)); 79 | return (B)this; 80 | } 81 | 82 | public final B onAlarmMarkerPressed(final EventHandler HANDLER) { 83 | properties.put("onAlarmMarkerPressed", new SimpleObjectProperty<>(HANDLER)); 84 | return (B)this; 85 | } 86 | 87 | public final B onAlarmMarkerReleased(final EventHandler HANDLER) { 88 | properties.put("onAlarmMarkerReleased", new SimpleObjectProperty<>(HANDLER)); 89 | return (B)this; 90 | } 91 | 92 | public final Alarm build() { 93 | final Alarm ALARM = new Alarm(); 94 | for (String key : properties.keySet()) { 95 | if ("time".equals(key)) { 96 | ALARM.setTime(((ObjectProperty) properties.get(key)).get()); 97 | } else if("repetition".equals(key)) { 98 | ALARM.setRepetition(((ObjectProperty) properties.get(key)).get()); 99 | } else if("text".equals(key)) { 100 | ALARM.setText(((StringProperty) properties.get(key)).get()); 101 | } else if("armed".equals(key)) { 102 | ALARM.setArmed(((BooleanProperty) properties.get(key)).get()); 103 | } else if ("command".equals(key)) { 104 | ALARM.setCommand(((ObjectProperty) properties.get(key)).get()); 105 | } else if ("color".equals(key)) { 106 | ALARM.setColor(((ObjectProperty) properties.get(key)).get()); 107 | } else if ("onAlarmMarkerPressed".equals(key)) { 108 | ALARM.setOnMarkerPressed(((ObjectProperty) properties.get(key)).get()); 109 | } else if ("onAlarmMarkerReleased".equals(key)) { 110 | ALARM.setOnMarkerReleased(((ObjectProperty) properties.get(key)).get()); 111 | } 112 | } 113 | return ALARM; 114 | } 115 | } 116 | 117 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/Command.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | /** 21 | * Created by hansolo on 28.01.16. 22 | */ 23 | @FunctionalInterface 24 | public interface Command { 25 | void execute(); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/DemoLauncher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | public class DemoLauncher { 21 | public static void main(final String[] args) { 22 | Demo.main(args); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/FGauge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | import eu.hansolo.medusa.Gauge.SkinType; 21 | import eu.hansolo.medusa.GaugeDesign.GaugeBackground; 22 | import eu.hansolo.medusa.skins.GaugeSkin; 23 | import javafx.scene.control.Skin; 24 | import javafx.scene.effect.BlurType; 25 | import javafx.scene.effect.InnerShadow; 26 | import javafx.scene.layout.Region; 27 | import javafx.scene.paint.Color; 28 | import javafx.scene.paint.CycleMethod; 29 | import javafx.scene.paint.RadialGradient; 30 | import javafx.scene.paint.Stop; 31 | import javafx.scene.shape.Circle; 32 | 33 | 34 | /** 35 | * A Region that embeds a given Gauge control. Keep in mind that 36 | * this only works with the round Medusa Skins and not with 37 | * skins like BulletChartSkin and QuarterSkin. 38 | * Created by hansolo on 08.01.16. 39 | */ 40 | public class FGauge extends Region { 41 | public static final double PREFERRED_WIDTH = 270; 42 | public static final double PREFERRED_HEIGHT = 270; 43 | public static final double MINIMUM_WIDTH = 50; 44 | public static final double MINIMUM_HEIGHT = 50; 45 | public static final double MAXIMUM_WIDTH = 1024; 46 | public static final double MAXIMUM_HEIGHT = 1024; 47 | 48 | // Model related 49 | private Gauge gauge; 50 | 51 | // View related 52 | private double size; 53 | private Region frame; 54 | private Circle background; 55 | private Circle foreground; 56 | private GaugeDesign gaugeDesign; 57 | private GaugeBackground gaugeBackground; 58 | private InnerShadow innerShadow; 59 | 60 | 61 | // ******************** Constructors ************************************** 62 | public FGauge() { 63 | this(new Gauge(), GaugeDesign.BLACK_METAL, GaugeBackground.BEIGE); 64 | } 65 | public FGauge(final Gauge GAUGE, final GaugeDesign DESIGN) { 66 | this(GAUGE, DESIGN, GaugeBackground.DARK_GRAY); 67 | } 68 | public FGauge(final Gauge GAUGE, final GaugeDesign DESIGN, final GaugeBackground BACKGROUND) { 69 | getStylesheets().add(getClass().getResource("framed-gauge.css").toExternalForm()); 70 | getStyleClass().setAll("framed-gauge"); 71 | gauge = GAUGE; 72 | gaugeDesign = DESIGN; 73 | gaugeBackground = BACKGROUND; 74 | 75 | Skin skin = gauge.getSkin(); 76 | 77 | if (null == skin) { 78 | throw new RuntimeException("Please use a valid Skin."); 79 | } 80 | 81 | init(); 82 | initGraphics(); 83 | registerListeners(); 84 | } 85 | 86 | 87 | // ******************** Initialization ************************************ 88 | private void init() { 89 | if (Double.compare(getWidth(), 0) <= 0 || Double.compare(getHeight(), 0) <= 0 || 90 | Double.compare(getPrefWidth(), 0) <= 0 || Double.compare(getPrefHeight(), 0) <= 0) { 91 | setPrefSize(PREFERRED_WIDTH, PREFERRED_HEIGHT); 92 | } 93 | if (Double.compare(getMinWidth(), 0) <= 0 || Double.compare(getMinHeight(), 0) <= 0) { 94 | setMinSize(MINIMUM_WIDTH, MINIMUM_HEIGHT); 95 | } 96 | if (Double.compare(getMaxWidth(), 0) <= 0 || Double.compare(getMaxHeight(), 0) <= 0) { 97 | setMaxSize(MAXIMUM_WIDTH, MAXIMUM_HEIGHT); 98 | } 99 | } 100 | 101 | private void initGraphics() { 102 | innerShadow = new InnerShadow(BlurType.TWO_PASS_BOX, Color.rgb(0, 0, 0, 0.35), 20, 0.0, 0, 20); 103 | 104 | frame = new Region(); 105 | 106 | background = new Circle(); 107 | background.setEffect(innerShadow); 108 | 109 | foreground = new Circle(); 110 | foreground.setMouseTransparent(true); 111 | 112 | getChildren().setAll(frame, background, gauge, foreground); 113 | } 114 | 115 | private void registerListeners() { 116 | widthProperty().addListener(o -> redraw()); 117 | heightProperty().addListener(o -> redraw()); 118 | } 119 | 120 | 121 | // ******************** Methods ******************************************* 122 | public GaugeDesign getGaugeDesign() { return gaugeDesign; } 123 | public void setGaugeDesign(final GaugeDesign DESIGN) { 124 | gaugeDesign = DESIGN; 125 | redraw(); 126 | } 127 | 128 | public GaugeBackground getGaugeBackground() { return gaugeBackground; } 129 | public void setGaugeBackground(final GaugeBackground BACKGROUND) { 130 | gaugeBackground = BACKGROUND; 131 | redraw(); 132 | } 133 | 134 | public boolean isForegroundVisible() { return foreground.isVisible(); } 135 | public void setForegroundVisible(final boolean VISIBLE) { 136 | foreground.setVisible(VISIBLE); 137 | foreground.setManaged(VISIBLE); 138 | } 139 | 140 | public Gauge getGauge() { return gauge; } 141 | public void setGauge(final Gauge GAUGE) { gauge = GAUGE; } 142 | 143 | 144 | // ******************** Resizing ****************************************** 145 | private void redraw() { 146 | double width = getWidth() - getInsets().getLeft() - getInsets().getRight(); 147 | double height = getHeight() - getInsets().getTop() - getInsets().getBottom(); 148 | size = width < height ? width : height; 149 | 150 | if (size > 0) { 151 | if (getWidth() > getHeight()) { 152 | setTranslateX(0.5 * (getWidth() - size)); 153 | } else if (getHeight() > getWidth()) { 154 | setTranslateY(0.5 * (getHeight() - size)); 155 | } 156 | 157 | frame.setPrefSize(size, size); 158 | frame.setBorder(gaugeDesign.getBorder(size)); 159 | 160 | background.setCenterX(size * 0.5); 161 | background.setCenterY(size * 0.5); 162 | background.setRadius(size * 0.4375); 163 | 164 | background.setFill(gaugeBackground.getPaint(background.getLayoutBounds().getMinX(), background.getLayoutBounds().getMinY(), 165 | background.getLayoutBounds().getMaxX(), background.getLayoutBounds().getMaxY())); 166 | 167 | switch(gaugeDesign) { 168 | case NONE: 169 | frame.setVisible(false); 170 | foreground.setVisible(false); 171 | background.setVisible(false); 172 | break; 173 | case ENZO: 174 | background.setFill(Color.rgb(240, 240, 240)); 175 | innerShadow.setRadius(0.07407407 * size); 176 | innerShadow.setOffsetX(0); 177 | innerShadow.setOffsetY(0.07407407 * size); 178 | innerShadow.setColor(Color.rgb(0, 0, 0, 0.35)); 179 | foreground.setFill(Color.TRANSPARENT); 180 | foreground.setStroke(null); 181 | break; 182 | default: 183 | frame.setVisible(true); 184 | foreground.setVisible(true); 185 | background.setVisible(true); 186 | innerShadow.setColor(Color.rgb(0, 0, 0, 0.65)); 187 | innerShadow.setRadius(0.08 * size); 188 | innerShadow.setOffsetX(0); 189 | innerShadow.setOffsetY(0.0 * size); 190 | foreground.setFill(new RadialGradient(0, 0, size * 0.5, size * gaugeDesign.FRAME_FACTOR * 0.5, size, false, CycleMethod.NO_CYCLE, 191 | new Stop(0, Color.rgb(255, 255, 255, 0.6)), 192 | new Stop(0.4, Color.TRANSPARENT))); 193 | foreground.setStroke(null); 194 | break; 195 | } 196 | 197 | gauge.setPrefSize(size * (1.0 - gaugeDesign.FRAME_FACTOR * 2.0), size * (1.0 - gaugeDesign.FRAME_FACTOR * 2.0)); 198 | gauge.relocate(gaugeDesign.FRAME_FACTOR * size, gaugeDesign.FRAME_FACTOR * size); 199 | 200 | foreground.setCenterX(size * 0.5); 201 | foreground.setCenterY(size * 0.5); 202 | foreground.setRadius(size * 0.42); 203 | } 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/FGaugeBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | import eu.hansolo.medusa.GaugeDesign.GaugeBackground; 21 | import eu.hansolo.medusa.skins.GaugeSkin; 22 | import javafx.beans.property.BooleanProperty; 23 | import javafx.beans.property.DoubleProperty; 24 | import javafx.beans.property.ObjectProperty; 25 | import javafx.beans.property.Property; 26 | import javafx.beans.property.SimpleBooleanProperty; 27 | import javafx.beans.property.SimpleDoubleProperty; 28 | import javafx.beans.property.SimpleObjectProperty; 29 | import javafx.geometry.Dimension2D; 30 | import javafx.scene.control.Skin; 31 | 32 | import java.util.HashMap; 33 | 34 | 35 | /** 36 | * Created by hansolo on 13.01.16. 37 | */ 38 | public class FGaugeBuilder> { 39 | private HashMap properties = new HashMap<>(); 40 | 41 | 42 | // ******************** Constructors ************************************** 43 | protected FGaugeBuilder() {} 44 | 45 | 46 | // ******************** Methods ******************************************* 47 | public static final FGaugeBuilder create() { 48 | return new FGaugeBuilder(); 49 | } 50 | 51 | public final B gauge(final Gauge GAUGE) { 52 | properties.put("gauge", new SimpleObjectProperty<>(GAUGE)); 53 | return (B)this; 54 | } 55 | 56 | public final B gaugeDesign(final GaugeDesign DESIGN) { 57 | properties.put("gaugeDesign", new SimpleObjectProperty<>(DESIGN)); 58 | return (B)this; 59 | } 60 | 61 | public final B gaugeBackground(final GaugeBackground BACKGROUND) { 62 | properties.put("gaugeBackground", new SimpleObjectProperty<>(BACKGROUND)); 63 | return (B)this; 64 | } 65 | 66 | public final B foregroundVisible(final boolean VISIBLE) { 67 | properties.put("foregroundVisible", new SimpleBooleanProperty(VISIBLE)); 68 | return (B)this; 69 | } 70 | 71 | public final B prefSize(final double WIDTH, final double HEIGHT) { 72 | properties.put("prefSize", new SimpleObjectProperty<>(new Dimension2D(WIDTH, HEIGHT))); 73 | return (B)this; 74 | } 75 | public final B minSize(final double WIDTH, final double HEIGHT) { 76 | properties.put("minSize", new SimpleObjectProperty<>(new Dimension2D(WIDTH, HEIGHT))); 77 | return (B)this; 78 | } 79 | public final B maxSize(final double WIDTH, final double HEIGHT) { 80 | properties.put("maxSize", new SimpleObjectProperty<>(new Dimension2D(WIDTH, HEIGHT))); 81 | return (B)this; 82 | } 83 | 84 | public final B prefWidth(final double PREF_WIDTH) { 85 | properties.put("prefWidth", new SimpleDoubleProperty(PREF_WIDTH)); 86 | return (B)this; 87 | } 88 | public final B prefHeight(final double PREF_HEIGHT) { 89 | properties.put("prefHeight", new SimpleDoubleProperty(PREF_HEIGHT)); 90 | return (B)this; 91 | } 92 | 93 | public final B minWidth(final double MIN_WIDTH) { 94 | properties.put("minWidth", new SimpleDoubleProperty(MIN_WIDTH)); 95 | return (B)this; 96 | } 97 | public final B minHeight(final double MIN_HEIGHT) { 98 | properties.put("minHeight", new SimpleDoubleProperty(MIN_HEIGHT)); 99 | return (B)this; 100 | } 101 | 102 | public final B maxWidth(final double MAX_WIDTH) { 103 | properties.put("maxWidth", new SimpleDoubleProperty(MAX_WIDTH)); 104 | return (B)this; 105 | } 106 | public final B maxHeight(final double MAX_HEIGHT) { 107 | properties.put("maxHeight", new SimpleDoubleProperty(MAX_HEIGHT)); 108 | return (B)this; 109 | } 110 | 111 | public final B scaleX(final double SCALE_X) { 112 | properties.put("scaleX", new SimpleDoubleProperty(SCALE_X)); 113 | return (B)this; 114 | } 115 | public final B scaleY(final double SCALE_Y) { 116 | properties.put("scaleY", new SimpleDoubleProperty(SCALE_Y)); 117 | return (B)this; 118 | } 119 | 120 | public final B layoutX(final double LAYOUT_X) { 121 | properties.put("layoutX", new SimpleDoubleProperty(LAYOUT_X)); 122 | return (B)this; 123 | } 124 | public final B layoutY(final double LAYOUT_Y) { 125 | properties.put("layoutY", new SimpleDoubleProperty(LAYOUT_Y)); 126 | return (B)this; 127 | } 128 | 129 | public final B translateX(final double TRANSLATE_X) { 130 | properties.put("translateX", new SimpleDoubleProperty(TRANSLATE_X)); 131 | return (B)this; 132 | } 133 | public final B translateY(final double TRANSLATE_Y) { 134 | properties.put("translateY", new SimpleDoubleProperty(TRANSLATE_Y)); 135 | return (B)this; 136 | } 137 | 138 | public final FGauge build() { 139 | Gauge gauge = null == properties.get("gauge") ? new Gauge() : ((ObjectProperty) properties.get("gauge")).get(); 140 | GaugeDesign design = null == properties.get("gaugeDesign") ? GaugeDesign.METAL : ((ObjectProperty) properties.get("gaugeDesign")).get(); 141 | GaugeBackground background = null == properties.get("gaugeBackground") ? GaugeBackground.DARK_GRAY : ((ObjectProperty) properties.get("gaugeBackground")).get(); 142 | 143 | Skin skin = gauge.getSkin(); 144 | if (null != skin && gauge.getSkin().getClass() != GaugeSkin.class) { 145 | throw new RuntimeException("Please change Skin to GaugeSkin."); 146 | } 147 | 148 | final FGauge CONTROL = new FGauge(gauge, design, background); 149 | for (String key : properties.keySet()) { 150 | if ("prefSize".equals(key)) { 151 | Dimension2D dim = ((ObjectProperty) properties.get(key)).get(); 152 | CONTROL.setPrefSize(dim.getWidth(), dim.getHeight()); 153 | } else if("minSize".equals(key)) { 154 | Dimension2D dim = ((ObjectProperty) properties.get(key)).get(); 155 | CONTROL.setPrefSize(dim.getWidth(), dim.getHeight()); 156 | } else if("maxSize".equals(key)) { 157 | Dimension2D dim = ((ObjectProperty) properties.get(key)).get(); 158 | CONTROL.setPrefSize(dim.getWidth(), dim.getHeight()); 159 | } else if("prefWidth".equals(key)) { 160 | CONTROL.setPrefWidth(((DoubleProperty) properties.get(key)).get()); 161 | } else if("prefHeight".equals(key)) { 162 | CONTROL.setPrefHeight(((DoubleProperty) properties.get(key)).get()); 163 | } else if("minWidth".equals(key)) { 164 | CONTROL.setMinWidth(((DoubleProperty) properties.get(key)).get()); 165 | } else if("minHeight".equals(key)) { 166 | CONTROL.setMinHeight(((DoubleProperty) properties.get(key)).get()); 167 | } else if("maxWidth".equals(key)) { 168 | CONTROL.setMaxWidth(((DoubleProperty) properties.get(key)).get()); 169 | } else if("maxHeight".equals(key)) { 170 | CONTROL.setMaxHeight(((DoubleProperty) properties.get(key)).get()); 171 | } else if("scaleX".equals(key)) { 172 | CONTROL.setScaleX(((DoubleProperty) properties.get(key)).get()); 173 | } else if("scaleY".equals(key)) { 174 | CONTROL.setScaleY(((DoubleProperty) properties.get(key)).get()); 175 | } else if ("layoutX".equals(key)) { 176 | CONTROL.setLayoutX(((DoubleProperty) properties.get(key)).get()); 177 | } else if ("layoutY".equals(key)) { 178 | CONTROL.setLayoutY(((DoubleProperty) properties.get(key)).get()); 179 | } else if ("translateX".equals(key)) { 180 | CONTROL.setTranslateX(((DoubleProperty) properties.get(key)).get()); 181 | } else if ("translateY".equals(key)) { 182 | CONTROL.setTranslateY(((DoubleProperty) properties.get(key)).get()); 183 | } else if ("foregroundVisible".equals(key)) { 184 | CONTROL.setForegroundVisible(((BooleanProperty) properties.get(key)).get()); 185 | } 186 | } 187 | return CONTROL; 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/Fonts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | import javafx.scene.text.Font; 21 | 22 | 23 | /** 24 | * Created by hansolo on 11.12.15. 25 | */ 26 | public class Fonts { 27 | private static final String DIGITAL_NAME; 28 | private static final String DIGITAL_READOUT_NAME; 29 | private static final String DIGITAL_READOUT_BOLD_NAME; 30 | private static final String ELEKTRA_NAME; 31 | private static final String ROBOTO_THIN_NAME; 32 | private static final String ROBOTO_LIGHT_NAME; 33 | private static final String ROBOTO_REGULAR_NAME; 34 | private static final String ROBOTO_MEDIUM_NAME; 35 | private static final String ROBOTO_BOLD_NAME; 36 | private static final String ROBOTO_LIGHT_CONDENSED_NAME; 37 | private static final String ROBOTO_REGULAR_CONDENSED_NAME; 38 | private static final String ROBOTO_BOLD_CONDENSED_NAME; 39 | private static final String LATO_LIGHT_NAME; 40 | private static final String LATO_REGULAR_NAME; 41 | private static final String LATO_BOLD_NAME; 42 | private static final String ESTRICTA_REGULAR_NAME; 43 | private static final String ESTRICTA_REGULAR_ITALIC_NAME; 44 | private static final String ESTRICTA_MEDIUM_NAME; 45 | private static final String ESTRICTA_MEDIUM_ITALIC_NAME; 46 | 47 | private static String digitalName; 48 | private static String digitalReadoutName; 49 | private static String digitalReadoutBoldName; 50 | private static String elektraName; 51 | 52 | private static String robotoThinName; 53 | private static String robotoLightName; 54 | private static String robotoRegularName; 55 | private static String robotoMediumName; 56 | private static String robotoBoldName; 57 | 58 | private static String robotoLightCondensedName; 59 | private static String robotoRegularCondensedName; 60 | private static String robotoBoldCondensedName; 61 | 62 | private static String latoLightName; 63 | private static String latoRegularName; 64 | private static String latoBoldName; 65 | 66 | private static String estrictaRegularName; 67 | private static String estrictaRegularItalicName; 68 | private static String estrictaMediumName; 69 | private static String estrictaMediumItalicName; 70 | 71 | 72 | static { 73 | try { 74 | digitalName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/digital.ttf"), 10).getName(); 75 | digitalReadoutName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/digitalreadout.ttf"), 10).getName(); 76 | digitalReadoutBoldName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/digitalreadoutb.ttf"), 10).getName(); 77 | elektraName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/elektra.ttf"), 10).getName(); 78 | robotoThinName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Roboto-Thin.ttf"), 10).getName(); 79 | robotoLightName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Roboto-Light.ttf"), 10).getName(); 80 | robotoRegularName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Roboto-Regular.ttf"), 10).getName(); 81 | robotoMediumName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Roboto-Medium.ttf"), 10).getName(); 82 | robotoBoldName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Roboto-Bold.ttf"), 10).getName(); 83 | robotoLightCondensedName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/RobotoCondensed-Light.ttf"), 10).getName(); 84 | robotoRegularCondensedName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/RobotoCondensed-Regular.ttf"), 10).getName(); 85 | robotoBoldCondensedName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/RobotoCondensed-Bold.ttf"), 10).getName(); 86 | latoLightName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Lato-Lig.otf"), 10).getName(); 87 | latoRegularName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Lato-Reg.otf"), 10).getName(); 88 | latoBoldName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Lato-Bol.otf"), 10).getName(); 89 | estrictaRegularName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Estricta-Regular.otf"), 10).getName(); 90 | estrictaRegularItalicName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Estricta-RegularItalic.otf"), 10).getName(); 91 | estrictaMediumName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Estricta-Medium.otf"), 10).getName(); 92 | estrictaMediumItalicName = Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Estricta-MediumItalic.otf"), 10).getName(); 93 | } catch (Exception exception) { } 94 | DIGITAL_NAME = digitalName; 95 | DIGITAL_READOUT_NAME = digitalReadoutName; 96 | DIGITAL_READOUT_BOLD_NAME = digitalReadoutBoldName; 97 | ELEKTRA_NAME = elektraName; 98 | ROBOTO_THIN_NAME = robotoThinName; 99 | ROBOTO_LIGHT_NAME = robotoLightName; 100 | ROBOTO_REGULAR_NAME = robotoRegularName; 101 | ROBOTO_MEDIUM_NAME = robotoMediumName; 102 | ROBOTO_BOLD_NAME = robotoBoldName; 103 | ROBOTO_LIGHT_CONDENSED_NAME = robotoLightCondensedName; 104 | ROBOTO_REGULAR_CONDENSED_NAME = robotoRegularCondensedName; 105 | ROBOTO_BOLD_CONDENSED_NAME = robotoBoldCondensedName; 106 | LATO_LIGHT_NAME = latoLightName; 107 | LATO_REGULAR_NAME = latoRegularName; 108 | LATO_BOLD_NAME = latoBoldName; 109 | ESTRICTA_REGULAR_NAME = estrictaRegularName; 110 | ESTRICTA_REGULAR_ITALIC_NAME = estrictaRegularItalicName; 111 | ESTRICTA_MEDIUM_NAME = estrictaMediumName; 112 | ESTRICTA_MEDIUM_ITALIC_NAME = estrictaMediumItalicName; 113 | } 114 | 115 | 116 | // ******************** Methods ******************************************* 117 | public static Font digital(final double SIZE) { return new Font(DIGITAL_NAME, SIZE); } 118 | 119 | public static Font digitalReadout(final double SIZE) { return new Font(DIGITAL_READOUT_NAME, SIZE); } 120 | public static Font digitalReadoutBold(final double SIZE) { return new Font(DIGITAL_READOUT_BOLD_NAME, SIZE); } 121 | 122 | public static Font elektra(final double SIZE) { return new Font(ELEKTRA_NAME, SIZE); } 123 | 124 | public static Font robotoThin(final double SIZE) { return new Font(ROBOTO_THIN_NAME, SIZE); } 125 | public static Font robotoLight(final double SIZE) { return new Font(ROBOTO_LIGHT_NAME, SIZE); } 126 | public static Font robotoRegular(final double SIZE) { return new Font(ROBOTO_REGULAR_NAME, SIZE); } 127 | public static Font robotoMedium(final double SIZE) { return new Font(ROBOTO_MEDIUM_NAME, SIZE); } 128 | public static Font robotoBold(final double SIZE) { return new Font(ROBOTO_BOLD_NAME, SIZE); } 129 | 130 | public static Font robotoCondensedLight(final double SIZE) { return new Font(ROBOTO_LIGHT_CONDENSED_NAME, SIZE); } 131 | public static Font robotoCondensedRegular(final double SIZE) { return new Font(ROBOTO_REGULAR_CONDENSED_NAME, SIZE); } 132 | public static Font robotoCondensedBold(final double SIZE) { return new Font(ROBOTO_BOLD_CONDENSED_NAME, SIZE); } 133 | 134 | public static Font latoLight(final double SIZE) { return new Font(LATO_LIGHT_NAME, SIZE); } 135 | public static Font latoRegular(final double SIZE) { return new Font(LATO_REGULAR_NAME, SIZE); } 136 | public static Font latoBold(final double SIZE) { return new Font(LATO_BOLD_NAME, SIZE); } 137 | 138 | public static Font estrictaRegular(final double SIZE) { return new Font(ESTRICTA_REGULAR_NAME, SIZE); } 139 | public static Font estrictaRegularItalic(final double SIZE) { return new Font(ESTRICTA_REGULAR_ITALIC_NAME, SIZE); } 140 | public static Font estrictaMedium(final double SIZE) { return new Font(ESTRICTA_MEDIUM_NAME, SIZE); } 141 | public static Font estrictaMediumItalic(final double SIZE) { return new Font(ESTRICTA_MEDIUM_ITALIC_NAME, SIZE); } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/LcdDesign.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | import javafx.scene.paint.Color; 21 | 22 | 23 | /** 24 | * Created by hansolo on 30.12.15. 25 | */ 26 | public enum LcdDesign { 27 | BEIGE(Color.rgb(200, 200, 177), Color.rgb(241, 237, 207), Color.rgb(234, 230, 194), Color.rgb(225, 220, 183), Color.rgb(237, 232, 191), Color.BLACK, Color.rgb(0, 0, 0, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 28 | BLUE(Color.WHITE, Color.rgb(231, 246, 255), Color.rgb(170, 224, 255), Color.rgb(136, 212, 255), Color.rgb(192, 232, 255), Color.rgb(18, 69, 100), Color.rgb(18, 69, 100, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 29 | ORANGE(Color.WHITE, Color.rgb(255, 245, 225), Color.rgb(255, 217, 147), Color.rgb(255, 201, 104), Color.rgb(255, 227, 173), Color.rgb(80, 55, 0), Color.rgb(80, 55, 0, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 30 | RED(Color.WHITE, Color.rgb(255, 225, 225), Color.rgb(252, 114, 115), Color.rgb(252, 114, 115), Color.rgb(254, 178, 178), Color.rgb(79, 12, 14), Color.rgb(79, 12, 14, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 31 | YELLOW(Color.WHITE, Color.rgb(245, 255, 186), Color.rgb(158, 205, 0), Color.rgb(158, 205, 0), Color.rgb(210, 255, 0), Color.rgb(64, 83, 0), Color.rgb(64, 83, 0, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 32 | WHITE(Color.WHITE, Color.WHITE, Color.rgb(241, 246, 242), Color.rgb(229, 239, 244), Color.WHITE, Color.BLACK, Color.rgb(0, 0, 0, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 33 | GRAY(Color.rgb(65, 65, 65), Color.rgb(117, 117, 117), Color.rgb(87, 87, 87), Color.rgb(65, 65, 65), Color.rgb(81, 81, 81), Color.WHITE, Color.rgb(255, 255, 255, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 34 | BLACK(Color.rgb(65, 65, 65), Color.rgb(102, 102, 102), Color.rgb(51, 51, 51), Color.BLACK, Color.rgb(51, 51, 51), Color.rgb(204, 204, 204), Color.rgb(204, 204, 204, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 35 | GREEN(Color.rgb(33, 67, 67), Color.rgb(33, 67, 67), Color.rgb(29, 58, 58), Color.rgb(28, 57, 57), Color.rgb(23, 46, 46), Color.rgb(0, 185, 165), Color.rgb(0, 185, 165, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 36 | GREEN_DARKGREEN(Color.rgb(27, 41, 17), Color.rgb(70, 84, 58), Color.rgb(36, 60, 14), Color.rgb(24, 50, 1), Color.rgb(8, 10, 7), Color.rgb(152, 255, 74), Color.rgb(152, 255, 74, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 37 | BLUE2(Color.rgb(0, 68, 103), Color.rgb(8, 109, 165), Color.rgb(0, 72, 117), Color.rgb(0, 72, 117), Color.rgb(0, 68, 103), Color.rgb(111, 182, 228), Color.rgb(111, 182, 228, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 38 | BLUE_BLACK(Color.rgb(22, 125, 212), Color.rgb(3, 162, 254), Color.rgb(3, 162, 254), Color.rgb(3, 162, 254), Color.rgb(11, 172, 244), Color.BLACK, Color.rgb(0, 0, 0, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 39 | BLUE_DARKBLUE(Color.rgb(18, 33, 88), Color.rgb(18, 33, 88), Color.rgb(19, 30, 90), Color.rgb(17, 31, 94), Color.rgb(21, 25, 90), Color.rgb(23, 99, 221), Color.rgb(23, 99, 221, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 40 | BLUE_LIGHTBLUE(Color.rgb(88, 107, 132), Color.rgb(53, 74, 104), Color.rgb(27, 37, 65), Color.rgb(5, 12, 40), Color.rgb(32, 47, 79), Color.rgb(71, 178, 254), Color.rgb(71, 178, 254, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 41 | BLUE_GRAY(Color.rgb(135, 174, 255), Color.rgb(101, 159, 255), Color.rgb(44, 93, 255), Color.rgb(27, 65, 254), Color.rgb(12, 50, 255), Color.rgb(178, 180, 237), Color.rgb(178, 180, 237, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 42 | STANDARD(Color.rgb(131, 133, 119), Color.rgb(176, 183, 167), Color.rgb(165, 174, 153), Color.rgb(166, 175, 156), Color.rgb(175, 184, 165), Color.rgb(35, 42, 52), Color.rgb(35, 42, 52, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 43 | LIGHTGREEN(Color.rgb(194, 212, 188), Color.rgb(212, 234, 206), Color.rgb(205, 224, 194), Color.rgb(206, 225, 194), Color.rgb(214, 233, 206), Color.rgb(0, 12, 6), Color.rgb(0, 12, 6, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 44 | STANDARD_GREEN(Color.WHITE, Color.rgb(219, 230, 220), Color.rgb(179, 194, 178), Color.rgb(153, 176, 151), Color.rgb(114, 138, 109), Color.rgb(0, 12, 6), Color.rgb(0, 12, 6, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 45 | BLUE_BLUE(Color.rgb(100, 168, 253), Color.rgb(100, 168, 253), Color.rgb(95, 160, 250), Color.rgb(80, 144, 252), Color.rgb(74, 134, 255), Color.rgb(0, 44, 187), Color.rgb(0, 44, 187, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 46 | RED_DARKRED(Color.rgb(72, 36, 50), Color.rgb(185, 111, 110), Color.rgb(148, 66, 72), Color.rgb(83, 19, 20), Color.rgb(7, 6, 14), Color.rgb(254, 139, 146), Color.rgb(254, 139, 146, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 47 | DARKBLUE(Color.rgb(14, 24, 31), Color.rgb(46, 105, 144), Color.rgb(19, 64, 96), Color.rgb(6, 20, 29), Color.rgb(8, 9, 10), Color.rgb(61, 179, 255), Color.rgb(61, 179, 255, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 48 | PURPLE(Color.rgb(175, 164, 255), Color.rgb(188, 168, 253), Color.rgb(176, 159, 255), Color.rgb(174, 147, 252), Color.rgb(168, 136, 233), Color.rgb(7, 97, 72), Color.rgb(7, 97, 72, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 49 | BLACK_RED(Color.rgb(8, 12, 11), Color.rgb(10, 11, 13), Color.rgb(11, 10, 15), Color.rgb(7, 13, 9), Color.rgb(9, 13, 14), Color.rgb(181, 0, 38), Color.rgb(181, 0, 38, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 50 | DARKGREEN(Color.rgb(25, 85, 0), Color.rgb(47, 154, 0), Color.rgb(30, 101, 0), Color.rgb(30, 101, 0), Color.rgb(25, 85, 0), Color.rgb(35, 49, 35), Color.rgb(35, 49, 35, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 51 | AMBER(Color.rgb(182, 71, 0), Color.rgb(236, 155, 25), Color.rgb(212, 93, 5), Color.rgb(212, 93, 5), Color.rgb(182, 71, 0), Color.rgb(89, 58, 10), Color.rgb(89, 58, 10, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 52 | LIGHTBLUE(Color.rgb(125, 146, 184), Color.rgb(197, 212, 231), Color.rgb(138, 155, 194), Color.rgb(138, 155, 194), Color.rgb(125, 146, 184), Color.rgb(9, 0, 81), Color.rgb(9, 0, 81, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 53 | GREEN_BLACK(Color.rgb(1, 47, 0), Color.rgb(20, 106, 61), Color.rgb(33, 125, 84), Color.rgb(33, 125, 84), Color.rgb(33, 109, 63), Color.rgb(3, 15, 11), Color.rgb(3, 15, 11, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 54 | YELLOW_BLACK(Color.rgb(223, 248, 86), Color.rgb(222, 255, 28), Color.rgb(213, 245, 24), Color.rgb(213, 245, 24), Color.rgb(224, 248, 88), Color.rgb(9, 19, 0), Color.rgb(9, 19, 0, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 55 | BLACK_YELLOW(Color.rgb(43, 3, 3), Color.rgb(29, 0, 0), Color.rgb(26, 2, 2), Color.rgb(31, 5, 8), Color.rgb(30, 1, 3), Color.rgb(255, 254, 24), Color.rgb(255, 254, 24, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 56 | LIGHTGREEN_BLACK(Color.rgb(79, 121, 19), Color.rgb(96, 169, 0), Color.rgb(120, 201, 2), Color.rgb(118, 201, 0), Color.rgb(105, 179, 4), Color.rgb(0, 35, 0), Color.rgb(0, 35, 0, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 57 | DARKPURPLE(Color.rgb(35, 24, 75), Color.rgb(42, 20, 111), Color.rgb(40, 22, 103), Color.rgb(40, 22, 103), Color.rgb(41, 21, 111), Color.rgb(158, 167, 210), Color.rgb(158, 167, 210, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 58 | DARKAMBER(Color.rgb(134, 39, 17), Color.rgb(120, 24, 0), Color.rgb(83, 15, 12), Color.rgb(83, 15, 12), Color.rgb(120, 24, 0), Color.rgb(233, 140, 44), Color.rgb(233, 140, 44, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 59 | BLUE_LIGHTBLUE2(Color.rgb(15, 84, 151), Color.rgb(60, 103, 198), Color.rgb(67, 109, 209), Color.rgb(67, 109, 209), Color.rgb(64, 101, 190), Color.rgb(193, 253, 254), Color.rgb(193, 253, 254, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 60 | GRAY_PURPLE(Color.rgb(153, 164, 161), Color.rgb(203, 215, 213), Color.rgb(202, 212, 211), Color.rgb(202, 212, 211), Color.rgb(198, 209, 213), Color.rgb(99, 124, 204), Color.rgb(99, 124, 204, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 61 | YOCTOPUCE(Color.web("#0E181F"), Color.web("#232341"), Color.web("#1E1E3C"), Color.web("#1E1E3C"), Color.web("#191937"), Color.web("#99E5FF"), Color.rgb(153,229,255, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 62 | SECTIONS(Color.web("#B2B2B2"), Color.web("#FFFFFF"), Color.web("#C4C4C4"), Color.web("#C4C4C4"), Color.web("#B2B2B2"), Color.web("#000000"), Color.rgb(0, 0, 0, 0.1)) { @Override public Color[] getColors() { return this.COLORS; } }, 63 | FLAT_CUSTOM(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.WHITE, Color.TRANSPARENT) { @Override public Color[] getColors() { return this.COLORS; } }; 64 | 65 | 66 | protected final Color[] COLORS; 67 | public Color lcdForegroundColor; 68 | public Color lcdBackgroundColor; 69 | 70 | public abstract Color[] getColors(); 71 | 72 | LcdDesign(final Color BG0, final Color BG1, final Color BG2, final Color BG3, final Color BG4, final Color FG, final Color FGT) { 73 | COLORS = new Color[] {BG0, BG1, BG2, BG3, BG4, FG, FGT}; 74 | lcdForegroundColor = FG; 75 | lcdBackgroundColor = FGT; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/LcdFont.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | /** 21 | * Created by hansolo on 28.01.16. 22 | */ 23 | public enum LcdFont { 24 | STANDARD, LCD, DIGITAL, DIGITAL_BOLD, ELEKTRA 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/MarkerBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | import eu.hansolo.medusa.Marker.MarkerType; 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.event.EventHandler; 29 | import javafx.scene.paint.Color; 30 | 31 | import java.util.HashMap; 32 | 33 | 34 | /** 35 | * Created by hansolo on 05.01.16. 36 | */ 37 | public class MarkerBuilder> { 38 | private HashMap properties = new HashMap<>(); 39 | 40 | 41 | // ******************** Constructors ************************************** 42 | protected MarkerBuilder() {} 43 | 44 | 45 | // ******************** Methods ******************************************* 46 | public static final MarkerBuilder create() { 47 | return new MarkerBuilder(); 48 | } 49 | 50 | public final B value(final double VALUE) { 51 | properties.put("value", new SimpleDoubleProperty(VALUE)); 52 | return (B)this; 53 | } 54 | 55 | public final B text(final String TEXT) { 56 | properties.put("text", new SimpleStringProperty(TEXT)); 57 | return (B)this; 58 | } 59 | 60 | public final B color(final Color COLOR) { 61 | properties.put("color", new SimpleObjectProperty<>(COLOR)); 62 | return (B)this; 63 | } 64 | 65 | public final B markerType(final MarkerType TYPE) { 66 | properties.put("markerType", new SimpleObjectProperty<>(TYPE)); 67 | return (B)this; 68 | } 69 | 70 | public final B styleClass(final String STYLE_CLASS) { 71 | properties.put("styleClass", new SimpleStringProperty(STYLE_CLASS)); 72 | return (B)this; 73 | } 74 | 75 | public final B onMarkerPressed(final EventHandler HANDLER) { 76 | properties.put("onMarkerPressed", new SimpleObjectProperty<>(HANDLER)); 77 | return (B)this; 78 | } 79 | 80 | public final B onMarkerReleased(final EventHandler HANDLER) { 81 | properties.put("onMarkerReleased", new SimpleObjectProperty<>(HANDLER)); 82 | return (B)this; 83 | } 84 | 85 | public final B onMarkerExceeded(final EventHandler HANDLER) { 86 | properties.put("onMarkerExceeded", new SimpleObjectProperty<>(HANDLER)); 87 | return (B)this; 88 | } 89 | 90 | public final B onMarkerUnderrun(final EventHandler HANDLER) { 91 | properties.put("onMarkerUnderrun", new SimpleObjectProperty<>(HANDLER)); 92 | return (B)this; 93 | } 94 | 95 | public final Marker build() { 96 | final Marker MARKER = new Marker(); 97 | for (String key : properties.keySet()) { 98 | if ("value".equals(key)) { 99 | MARKER.setValue(((DoubleProperty) properties.get(key)).get()); 100 | } else if("text".equals(key)) { 101 | MARKER.setText(((StringProperty) properties.get(key)).get()); 102 | } else if ("color".equals(key)) { 103 | MARKER.setColor(((ObjectProperty) properties.get(key)).get()); 104 | } else if ("markerType".equals(key)) { 105 | MARKER.setMarkerType(((ObjectProperty) properties.get(key)).get()); 106 | } else if ("onMarkerPressed".equals(key)) { 107 | MARKER.setOnMarkerPressed(((ObjectProperty) properties.get(key)).get()); 108 | } else if ("onMarkerReleased".equals(key)) { 109 | MARKER.setOnMarkerReleased(((ObjectProperty) properties.get(key)).get()); 110 | } else if ("onMarkerExceeded".equals(key)) { 111 | MARKER.setOnMarkerExceeded(((ObjectProperty) properties.get(key)).get()); 112 | } else if ("onMarkerUnderrun".equals(key)) { 113 | MARKER.setOnMarkerUnderrun(((ObjectProperty) properties.get(key)).get()); 114 | } else if ("styleClass".equals(key)) { 115 | MARKER.setStyleClass(((StringProperty) properties.get(key)).get()); 116 | } 117 | } 118 | return MARKER; 119 | } 120 | } 121 | 122 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/SectionBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | import eu.hansolo.medusa.Section.SectionEvent; 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.event.EventHandler; 29 | import javafx.scene.image.Image; 30 | import javafx.scene.paint.Color; 31 | 32 | import java.util.HashMap; 33 | 34 | 35 | /** 36 | * Created by hansolo on 20.12.15. 37 | */ 38 | public class SectionBuilder> { 39 | private HashMap properties = new HashMap<>(); 40 | 41 | 42 | // ******************** Constructors ************************************** 43 | protected SectionBuilder() {} 44 | 45 | 46 | // ******************** Methods ******************************************* 47 | public static final SectionBuilder create() { 48 | return new SectionBuilder(); 49 | } 50 | 51 | public final B start(final double VALUE) { 52 | properties.put("start", new SimpleDoubleProperty(VALUE)); 53 | return (B)this; 54 | } 55 | 56 | public final B stop(final double VALUE) { 57 | properties.put("stop", new SimpleDoubleProperty(VALUE)); 58 | return (B)this; 59 | } 60 | 61 | public final B text(final String TEXT) { 62 | properties.put("text", new SimpleStringProperty(TEXT)); 63 | return (B)this; 64 | } 65 | 66 | public final B icon(final Image IMAGE) { 67 | properties.put("icon", new SimpleObjectProperty<>(IMAGE)); 68 | return (B)this; 69 | } 70 | 71 | public final B color(final Color COLOR) { 72 | properties.put("color", new SimpleObjectProperty<>(COLOR)); 73 | return (B)this; 74 | } 75 | 76 | public final B highlightColor(final Color COLOR) { 77 | properties.put("highlightColor", new SimpleObjectProperty<>(COLOR)); 78 | return (B)this; 79 | } 80 | 81 | public final B textColor(final Color COLOR) { 82 | properties.put("textColor", new SimpleObjectProperty<>(COLOR)); 83 | return (B)this; 84 | } 85 | 86 | public final B styleClass(final String STYLE_CLASS) { 87 | properties.put("styleClass", new SimpleStringProperty(STYLE_CLASS)); 88 | return (B)this; 89 | } 90 | 91 | public final B onSectionEntered(final EventHandler HANDLER) { 92 | properties.put("onSectionEntered", new SimpleObjectProperty<>(HANDLER)); 93 | return (B)this; 94 | } 95 | 96 | public final B onSectionLeft(final EventHandler HANDLER) { 97 | properties.put("onSectionLeft", new SimpleObjectProperty<>(HANDLER)); 98 | return (B)this; 99 | } 100 | 101 | public final Section build() { 102 | final Section SECTION = new Section(); 103 | for (String key : properties.keySet()) { 104 | if ("start".equals(key)) { 105 | SECTION.setStart(((DoubleProperty) properties.get(key)).get()); 106 | } else if("stop".equals(key)) { 107 | SECTION.setStop(((DoubleProperty) properties.get(key)).get()); 108 | } else if("text".equals(key)) { 109 | SECTION.setText(((StringProperty) properties.get(key)).get()); 110 | } else if("icon".equals(key)) { 111 | SECTION.setIcon(((ObjectProperty) properties.get(key)).get()); 112 | } else if ("color".equals(key)) { 113 | SECTION.setColor(((ObjectProperty) properties.get(key)).get()); 114 | } else if ("highlightColor".equals(key)) { 115 | SECTION.setHighlightColor(((ObjectProperty) properties.get(key)).get()); 116 | } else if ("textColor".equals(key)) { 117 | SECTION.setTextColor(((ObjectProperty) properties.get(key)).get()); 118 | } else if ("onSectionEntered".equals(key)) { 119 | SECTION.setOnSectionEntered(((ObjectProperty) properties.get(key)).get()); 120 | } else if ("onSectionLeft".equals(key)) { 121 | SECTION.setOnSectionLeft(((ObjectProperty) properties.get(key)).get()); 122 | } else if ("styleClass".equals(key)) { 123 | SECTION.setStyleClass(((StringProperty) properties.get(key)).get()); 124 | } 125 | } 126 | return SECTION; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | import eu.hansolo.medusa.Clock.ClockSkinType; 21 | import eu.hansolo.medusa.Gauge.SkinType; 22 | import eu.hansolo.medusa.events.UpdateEvent; 23 | import eu.hansolo.medusa.events.UpdateEventListener; 24 | import eu.hansolo.medusa.tools.GradientLookup; 25 | import javafx.animation.AnimationTimer; 26 | import javafx.application.Application; 27 | import javafx.collections.ObservableList; 28 | import javafx.geometry.Insets; 29 | import javafx.geometry.Orientation; 30 | import javafx.scene.Group; 31 | import javafx.scene.Node; 32 | import javafx.scene.Parent; 33 | import javafx.scene.Scene; 34 | import javafx.scene.layout.Background; 35 | import javafx.scene.layout.BackgroundFill; 36 | import javafx.scene.layout.CornerRadii; 37 | import javafx.scene.layout.StackPane; 38 | import javafx.scene.paint.Color; 39 | import javafx.scene.paint.Stop; 40 | import javafx.stage.Stage; 41 | 42 | import java.util.Locale; 43 | import java.util.Random; 44 | 45 | 46 | public class Test extends Application { 47 | private static final Random RND = new Random(); 48 | private static int noOfNodes = 0; 49 | private Gauge gauge; 50 | private long lastTimerCall; 51 | private AnimationTimer timer; 52 | 53 | 54 | @Override public void init() { 55 | gauge = GaugeBuilder.create() 56 | .skinType(SkinType.SIMPLE_DIGITAL) 57 | .prefSize(400, 400) 58 | .foregroundBaseColor(Color.web("#ebeefd")) 59 | .barBackgroundColor(Color.web("#262c49")) 60 | .decimals(2) 61 | .maxValue(200) 62 | .arcExtend(5) 63 | .gradientLookup(new GradientLookup(new Stop(0, Color.web("#8f62cb")), 64 | new Stop(0.25, Color.web("#7367f0")), 65 | new Stop(0.5, Color.web("#ad5ea5")), 66 | new Stop(0.75, Color.web("#e85456")), 67 | new Stop(1.0, Color.web("#e85456").brighter()))) 68 | .gradientBarEnabled(true) 69 | .animated(true) 70 | .build(); 71 | 72 | lastTimerCall = System.nanoTime(); 73 | timer = new AnimationTimer() { 74 | @Override public void handle(final long now) { 75 | if (now > lastTimerCall + 2_000_000_000l) { 76 | double value = RND.nextDouble() * gauge.getRange() + gauge.getMinValue(); 77 | gauge.setValue(value); 78 | lastTimerCall = now; 79 | } 80 | } 81 | }; 82 | } 83 | 84 | @Override public void start(Stage stage) { 85 | StackPane pane = new StackPane(gauge); 86 | pane.setPadding(new Insets(10)); 87 | pane.setBackground(new Background(new BackgroundFill(Color.web("#10163a"), CornerRadii.EMPTY, Insets.EMPTY))); 88 | 89 | Scene scene = new Scene(pane); 90 | 91 | stage.setTitle("Test"); 92 | stage.setScene(scene); 93 | stage.show(); 94 | 95 | // Calculate number of nodes 96 | calcNoOfNodes(pane); 97 | System.out.println(noOfNodes + " Nodes in SceneGraph"); 98 | 99 | timer.start(); 100 | } 101 | 102 | @Override public void stop() { 103 | System.exit(0); 104 | } 105 | 106 | 107 | 108 | // ******************** Misc ********************************************** 109 | private static void calcNoOfNodes(Node node) { 110 | if (node instanceof Parent) { 111 | if (((Parent) node).getChildrenUnmodifiable().size() != 0) { 112 | ObservableList tempChildren = ((Parent) node).getChildrenUnmodifiable(); 113 | noOfNodes += tempChildren.size(); 114 | for (Node n : tempChildren) { calcNoOfNodes(n); } 115 | } 116 | } 117 | } 118 | 119 | public static void main(String[] args) { 120 | launch(args); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/TestLauncher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | public class TestLauncher { 21 | /** 22 | * 23 | * This launcher starts the medusa test pane. 24 | * 25 | * Note: This launcher is required to make sure all openjfx java modules are linked via the classpath. 26 | * 27 | * @param args application arguments 28 | */ 29 | public static void main(String[] args) { 30 | Test.main(args); 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/TickLabelLocation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | /** 21 | * Created by hansolo on 28.01.16. 22 | */ 23 | public enum TickLabelLocation { 24 | INSIDE, OUTSIDE 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/TickLabelOrientation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | /** 21 | * Created by hansolo on 28.01.16. 22 | */ 23 | public enum TickLabelOrientation { 24 | ORTHOGONAL, HORIZONTAL, TANGENT 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/TickMarkType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | /** 21 | * Created by hansolo on 28.01.16. 22 | */ 23 | public enum TickMarkType { 24 | LINE, DOT, TRAPEZOID, TRIANGLE, BOX, TICK_LABEL, PILL 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/TimeSectionBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa; 19 | 20 | import eu.hansolo.medusa.TimeSection.TimeSectionEvent; 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.event.EventHandler; 27 | import javafx.scene.image.Image; 28 | import javafx.scene.paint.Color; 29 | 30 | import java.time.LocalTime; 31 | import java.util.HashMap; 32 | 33 | 34 | /** 35 | * Created by hansolo on 31.01.16. 36 | */ 37 | public class TimeSectionBuilder> { 38 | private HashMap properties = new HashMap<>(); 39 | 40 | 41 | // ******************** Constructors ************************************** 42 | protected TimeSectionBuilder() {} 43 | 44 | 45 | // ******************** Methods ******************************************* 46 | public static final TimeSectionBuilder create() { 47 | return new TimeSectionBuilder(); 48 | } 49 | 50 | public final B start(final LocalTime VALUE) { 51 | properties.put("start", new SimpleObjectProperty<>(VALUE)); 52 | return (B)this; 53 | } 54 | 55 | public final B stop(final LocalTime VALUE) { 56 | properties.put("stop", new SimpleObjectProperty<>(VALUE)); 57 | return (B)this; 58 | } 59 | 60 | public final B text(final String TEXT) { 61 | properties.put("text", new SimpleStringProperty(TEXT)); 62 | return (B)this; 63 | } 64 | 65 | public final B icon(final Image IMAGE) { 66 | properties.put("icon", new SimpleObjectProperty<>(IMAGE)); 67 | return (B)this; 68 | } 69 | 70 | public final B color(final Color COLOR) { 71 | properties.put("color", new SimpleObjectProperty<>(COLOR)); 72 | return (B)this; 73 | } 74 | 75 | public final B highlightColor(final Color COLOR) { 76 | properties.put("highlightColor", new SimpleObjectProperty<>(COLOR)); 77 | return (B)this; 78 | } 79 | 80 | public final B textColor(final Color COLOR) { 81 | properties.put("textColor", new SimpleObjectProperty<>(COLOR)); 82 | return (B)this; 83 | } 84 | 85 | public final B onTimeSectionEntered(final EventHandler HANDLER) { 86 | properties.put("onTimeSectionEntered", new SimpleObjectProperty<>(HANDLER)); 87 | return (B)this; 88 | } 89 | 90 | public final B onTimeSectionLeft(final EventHandler HANDLER) { 91 | properties.put("onTimeSectionLeft", new SimpleObjectProperty<>(HANDLER)); 92 | return (B)this; 93 | } 94 | 95 | public final TimeSection build() { 96 | final TimeSection SECTION = new TimeSection(); 97 | for (String key : properties.keySet()) { 98 | if ("start".equals(key)) { 99 | SECTION.setStart(((ObjectProperty) properties.get(key)).get()); 100 | } else if("stop".equals(key)) { 101 | SECTION.setStop(((ObjectProperty) properties.get(key)).get()); 102 | } else if("text".equals(key)) { 103 | SECTION.setText(((StringProperty) properties.get(key)).get()); 104 | } else if("icon".equals(key)) { 105 | SECTION.setIcon(((ObjectProperty) properties.get(key)).get()); 106 | } else if ("color".equals(key)) { 107 | SECTION.setColor(((ObjectProperty) properties.get(key)).get()); 108 | } else if ("highlightColor".equals(key)) { 109 | SECTION.setHighlightColor(((ObjectProperty) properties.get(key)).get()); 110 | } else if ("textColor".equals(key)) { 111 | SECTION.setTextColor(((ObjectProperty) properties.get(key)).get()); 112 | } else if ("onTimeSectionEntered".equals(key)) { 113 | SECTION.setOnTimeSectionEntered(((ObjectProperty) properties.get(key)).get()); 114 | } else if ("onTimeSectionLeft".equals(key)) { 115 | SECTION.setOnTimeSectionLeft(((ObjectProperty) properties.get(key)).get()); 116 | } 117 | } 118 | return SECTION; 119 | } 120 | } 121 | 122 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/events/AlarmEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.events; 19 | 20 | import eu.hansolo.medusa.Alarm; 21 | 22 | import java.util.EventObject; 23 | 24 | 25 | /** 26 | * Created by hansolo on 28.01.16. 27 | */ 28 | public class AlarmEvent extends EventObject { 29 | public final Alarm ALARM; 30 | 31 | 32 | // ******************** Constructors ************************************** 33 | public AlarmEvent(final Object SRC, final Alarm ALARM) { 34 | super(SRC); 35 | this.ALARM = ALARM; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/events/AlarmEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.events; 19 | 20 | import java.util.EventListener; 21 | 22 | 23 | /** 24 | * Created by hansolo on 28.01.16. 25 | */ 26 | @FunctionalInterface 27 | public interface AlarmEventListener extends EventListener { 28 | public void onAlarmEvent(final AlarmEvent EVENT); 29 | } 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/events/TimeEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.events; 19 | 20 | import java.time.ZonedDateTime; 21 | import java.util.EventObject; 22 | 23 | 24 | /** 25 | * Created by hansolo on 24.02.16. 26 | */ 27 | public class TimeEvent extends EventObject { 28 | public enum TimeEventType { HOUR, MINUTE, SECOND }; 29 | public final ZonedDateTime TIME; 30 | public final TimeEventType TYPE; 31 | 32 | 33 | // ******************** Constructors ************************************** 34 | public TimeEvent(final Object SRC, final ZonedDateTime TIME, final TimeEventType TYPE) { 35 | super(SRC); 36 | this.TIME = TIME; 37 | this.TYPE = TYPE; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/events/TimeEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.events; 19 | 20 | import java.util.EventListener; 21 | 22 | 23 | /** 24 | * Created by hansolo on 24.02.16. 25 | */ 26 | @FunctionalInterface 27 | public interface TimeEventListener extends EventListener { 28 | public void onTimeEvent(final TimeEvent EVENT); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/events/UpdateEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.events; 19 | 20 | import java.util.EventObject; 21 | 22 | 23 | /** 24 | * Created by hansolo on 05.01.16. 25 | */ 26 | public class UpdateEvent extends EventObject { 27 | public enum EventType { RECALC, REDRAW, RESIZE, LED, LCD, VISIBILITY, INTERACTIVITY, FINISHED, SECTION, ALERT, VALUE }; 28 | public final EventType eventType; 29 | 30 | public UpdateEvent(final Object SRC, final EventType EVENT_TYPE) { 31 | super(SRC); 32 | eventType = EVENT_TYPE; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/events/UpdateEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.events; 19 | 20 | import java.util.EventListener; 21 | 22 | 23 | /** 24 | * Created by hansolo on 05.01.16. 25 | */ 26 | @FunctionalInterface 27 | public interface UpdateEventListener extends EventListener { 28 | public void onUpdateEvent(final UpdateEvent EVENT); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/skins/ChargeSkin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.skins; 19 | 20 | import eu.hansolo.medusa.Gauge; 21 | import javafx.application.Platform; 22 | import javafx.beans.InvalidationListener; 23 | import javafx.beans.value.ChangeListener; 24 | import javafx.geometry.Bounds; 25 | import javafx.geometry.Insets; 26 | import javafx.geometry.Pos; 27 | import javafx.scene.layout.Background; 28 | import javafx.scene.layout.BackgroundFill; 29 | import javafx.scene.layout.Border; 30 | import javafx.scene.layout.BorderStroke; 31 | import javafx.scene.layout.BorderStrokeStyle; 32 | import javafx.scene.layout.BorderWidths; 33 | import javafx.scene.layout.CornerRadii; 34 | import javafx.scene.layout.HBox; 35 | import javafx.scene.layout.Region; 36 | import javafx.scene.paint.Color; 37 | import javafx.scene.paint.CycleMethod; 38 | import javafx.scene.paint.LinearGradient; 39 | import javafx.scene.paint.Paint; 40 | import javafx.scene.paint.Stop; 41 | 42 | 43 | /** 44 | * Created by hansolo on 08.07.16. 45 | */ 46 | public class ChargeSkin extends GaugeSkinBase { 47 | private enum BarColor { 48 | GRAY(Color.rgb(243, 243, 243), Color.rgb(143, 143, 143)), 49 | RED(Color.rgb(243, 0, 6), Color.rgb(143, 0, 9)), 50 | ORANGE(Color.rgb(253, 148, 21), Color.rgb(253, 97, 8)), 51 | GREEN(Color.rgb(110, 190, 5), Color.rgb(50, 177, 7)); 52 | 53 | public final Color COLOR_FROM; 54 | public final Color COLOR_TO; 55 | 56 | BarColor(final Color COLOR_FROM, final Color COLOR_TO) { 57 | this.COLOR_FROM = COLOR_FROM; 58 | this.COLOR_TO = COLOR_TO; 59 | } 60 | } 61 | protected static final double PREFERRED_WIDTH = 306; 62 | protected static final double PREFERRED_HEIGHT = 66; 63 | protected static final double MINIMUM_WIDTH = 153; 64 | protected static final double MINIMUM_HEIGHT = 33; 65 | protected static final double MAXIMUM_WIDTH = 918; 66 | protected static final double MAXIMUM_HEIGHT = 198; 67 | private static double aspectRatio = PREFERRED_HEIGHT / PREFERRED_WIDTH; 68 | private Region[] bars; 69 | private Background[] barBackgrounds; 70 | private Border barBorder; 71 | private double width; 72 | private double height; 73 | private HBox pane; 74 | private Paint backgroundPaint; 75 | private Paint borderPaint; 76 | private double borderWidth; 77 | private InvalidationListener currentValueListener; 78 | private ChangeListener paneWidthListener; 79 | 80 | 81 | // ******************** Constructors ************************************** 82 | public ChargeSkin(Gauge gauge) { 83 | super(gauge); 84 | backgroundPaint = Color.TRANSPARENT; 85 | borderPaint = Color.TRANSPARENT; 86 | borderWidth = 0; 87 | bars = new Region[12]; 88 | barBackgrounds = new Background[24]; 89 | currentValueListener = o -> handleEvents("VALUE"); 90 | paneWidthListener = (o, ov, nv) -> { if (ov.intValue() == 0 && nv.intValue() > 0) Platform.runLater(() -> resize()); }; 91 | 92 | initGraphics(); 93 | registerListeners(); 94 | } 95 | 96 | 97 | // ******************** Initialization ************************************ 98 | private void initGraphics() { 99 | // Set initial size 100 | if (Double.compare(gauge.getPrefWidth(), 0.0) <= 0 || Double.compare(gauge.getPrefHeight(), 0.0) <= 0 || 101 | Double.compare(gauge.getWidth(), 0.0) <= 0 || Double.compare(gauge.getHeight(), 0.0) <= 0) { 102 | if (gauge.getPrefWidth() > 0 && gauge.getPrefHeight() > 0) { 103 | gauge.setPrefSize(gauge.getPrefWidth(), gauge.getPrefHeight()); 104 | } else { 105 | gauge.setPrefSize(PREFERRED_WIDTH, PREFERRED_HEIGHT); 106 | } 107 | } 108 | 109 | for (int i = 0 ; i < 12 ; i++) { 110 | Region bar = new Region(); 111 | bar.setPrefSize(20, 20 + (i * 4)); 112 | bars[i] = bar; 113 | } 114 | 115 | pane = new HBox(bars); 116 | pane.setSpacing(PREFERRED_WIDTH * 0.01960784); 117 | pane.setAlignment(Pos.BOTTOM_CENTER); 118 | pane.setFillHeight(false); 119 | pane.setBackground(new Background(new BackgroundFill(backgroundPaint, new CornerRadii(1024), Insets.EMPTY))); 120 | pane.setBorder(new Border(new BorderStroke(borderPaint, BorderStrokeStyle.SOLID, new CornerRadii(1024), new BorderWidths(borderWidth)))); 121 | 122 | getChildren().setAll(pane); 123 | } 124 | 125 | @Override protected void registerListeners() { 126 | super.registerListeners(); 127 | gauge.currentValueProperty().addListener(currentValueListener); 128 | pane.widthProperty().addListener(paneWidthListener); 129 | } 130 | 131 | 132 | // ******************** Methods ******************************************* 133 | @Override public void layoutChildren(double x, double y, double w, double h) { 134 | super.layoutChildren(x, y, w, h); 135 | if(Double.compare(bars[0].getLayoutBounds().getWidth(), 0) == 0) resize(); 136 | } 137 | 138 | @Override protected void handleEvents(final String EVENT_TYPE) { 139 | super.handleEvents(EVENT_TYPE); 140 | if ("VALUE".equals(EVENT_TYPE)) { 141 | redraw(); 142 | } 143 | } 144 | 145 | @Override public void dispose() { 146 | gauge.currentValueProperty().removeListener(currentValueListener); 147 | pane.widthProperty().removeListener(paneWidthListener); 148 | super.dispose(); 149 | } 150 | 151 | 152 | // ******************** Resizing ****************************************** 153 | @Override protected void resize() { 154 | width = gauge.getWidth() - gauge.getInsets().getLeft() - gauge.getInsets().getRight(); 155 | height = gauge.getHeight() - gauge.getInsets().getTop() - gauge.getInsets().getBottom(); 156 | 157 | if (aspectRatio * width > height) { 158 | width = 1 / (aspectRatio / height); 159 | } else if (1 / (aspectRatio / height) > width) { 160 | height = aspectRatio * width; 161 | } 162 | 163 | if (width > 0 && height > 0) { 164 | pane.setMaxSize(width, height); 165 | pane.setPrefSize(width, height); 166 | pane.relocate((gauge.getWidth() - width) * 0.5, (gauge.getHeight() - height) * 0.5); 167 | pane.setSpacing(width * 0.01960784); 168 | 169 | double barWidth = 0; 170 | for (int i = 0 ; i < 12 ; i++) { 171 | bars[i].setPrefSize(0.3030303 * height, (0.3030303 * height + i * 0.06060606 * height)); 172 | Bounds bounds = bars[i].getLayoutBounds(); 173 | barWidth = bounds.getWidth(); 174 | if (barWidth == 0) return; 175 | 176 | BarColor barColor; 177 | if (i < 2) { 178 | barColor = BarColor.RED; 179 | } else if (i < 9) { 180 | barColor = BarColor.ORANGE; 181 | } else { 182 | barColor = BarColor.GREEN; 183 | } 184 | barBackgrounds[i] = new Background(new BackgroundFill[] { 185 | new BackgroundFill(Color.WHITE, new CornerRadii(1024), Insets.EMPTY), 186 | new BackgroundFill(new LinearGradient(0, bounds.getMinY(), 0, bounds.getMaxY(), false, CycleMethod.NO_CYCLE, new Stop(0.0, barColor.COLOR_FROM), new Stop(1.0, barColor.COLOR_TO)), new CornerRadii(1024), new Insets(0.15 * barWidth)) 187 | }); 188 | barBackgrounds[i + 12] = new Background(new BackgroundFill[] { 189 | new BackgroundFill(Color.WHITE, new CornerRadii(1024), Insets.EMPTY), 190 | new BackgroundFill(new LinearGradient(0, bounds.getMinY(), 0, bounds.getMaxY(), false, CycleMethod.NO_CYCLE, new Stop(0.0, BarColor.GRAY.COLOR_FROM), new Stop(1.0, BarColor.GRAY.COLOR_TO)), new CornerRadii(1024), new Insets(0.15 * barWidth)) 191 | }); 192 | } 193 | barBorder = new Border(new BorderStroke(Color.rgb(102, 102, 102), BorderStrokeStyle.SOLID, new CornerRadii(1024), new BorderWidths(0.05 * barWidth))); 194 | } 195 | redraw(); 196 | } 197 | 198 | @Override protected void redraw() { 199 | int chargedBars = (int) (gauge.getCurrentValue() * 13); 200 | for (int i = 0 ; i < 12 ; i++) { 201 | bars[i].setBackground(i < chargedBars ? barBackgrounds[i] : barBackgrounds[i + 12]); 202 | bars[i].setBorder(barBorder); 203 | } 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/skins/ClockSkinBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.skins; 19 | 20 | import eu.hansolo.medusa.Alarm; 21 | import eu.hansolo.medusa.Clock; 22 | import eu.hansolo.medusa.events.UpdateEventListener; 23 | import javafx.beans.InvalidationListener; 24 | import javafx.collections.ListChangeListener; 25 | import javafx.scene.control.Skin; 26 | import javafx.scene.control.SkinBase; 27 | 28 | import java.time.Instant; 29 | import java.time.ZoneId; 30 | import java.time.ZonedDateTime; 31 | 32 | 33 | /** 34 | * Created by hansolo on 20.01.17. 35 | */ 36 | public abstract class ClockSkinBase extends SkinBase implements Skin { 37 | protected static final double PREFERRED_WIDTH = 250; 38 | protected static final double PREFERRED_HEIGHT = 250; 39 | protected static final double MINIMUM_WIDTH = 50; 40 | protected static final double MINIMUM_HEIGHT = 50; 41 | protected static final double MAXIMUM_WIDTH = 1024; 42 | protected static final double MAXIMUM_HEIGHT = 1024; 43 | 44 | protected Clock clock; 45 | protected InvalidationListener sizeListener; 46 | protected UpdateEventListener updateEventListener; 47 | protected InvalidationListener currentTimeListener; 48 | protected InvalidationListener timeListener; 49 | protected ListChangeListener alarmListener; 50 | 51 | 52 | // ******************** Constructors ************************************** 53 | public ClockSkinBase(final Clock CLOCK) { 54 | super(CLOCK); 55 | 56 | clock = CLOCK; 57 | sizeListener = o -> handleEvents("RESIZE"); 58 | updateEventListener = e -> handleEvents(e.eventType.name()); 59 | currentTimeListener = o -> updateTime(ZonedDateTime.ofInstant(Instant.ofEpochSecond(clock.getCurrentTime()), ZoneId.of(ZoneId.systemDefault().getId()))); 60 | timeListener = o -> updateTime(clock.getTime()); 61 | alarmListener = c -> { 62 | updateAlarms(); 63 | redraw(); 64 | }; 65 | } 66 | 67 | 68 | // ******************** Initialization ************************************ 69 | protected abstract void initGraphics(); 70 | 71 | protected void registerListeners() { 72 | clock.widthProperty().addListener(sizeListener); 73 | clock.heightProperty().addListener(sizeListener); 74 | clock.setOnUpdate(updateEventListener); 75 | if (clock.isAnimated()) { 76 | clock.currentTimeProperty().addListener(currentTimeListener); 77 | } else { 78 | clock.timeProperty().addListener(timeListener); 79 | } 80 | clock.getAlarms().addListener(alarmListener); 81 | } 82 | 83 | 84 | // ******************** Methods ******************************************* 85 | @Override protected double computeMinWidth(final double HEIGHT, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return MINIMUM_WIDTH; } 86 | @Override protected double computeMinHeight(final double WIDTH, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return MINIMUM_HEIGHT; } 87 | @Override protected double computePrefWidth(final double HEIGHT, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return super.computePrefWidth(HEIGHT, TOP, RIGHT, BOTTOM, LEFT); } 88 | @Override protected double computePrefHeight(final double WIDTH, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return super.computePrefHeight(WIDTH, TOP, RIGHT, BOTTOM, LEFT); } 89 | @Override protected double computeMaxWidth(final double HEIGHT, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return MAXIMUM_WIDTH; } 90 | @Override protected double computeMaxHeight(final double WIDTH, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return MAXIMUM_HEIGHT; } 91 | 92 | protected void handleEvents(final String EVENT_TYPE) { 93 | if ("RESIZE".equals(EVENT_TYPE)) { 94 | resize(); 95 | redraw(); 96 | } else if ("REDRAW".equals(EVENT_TYPE)) { 97 | redraw(); 98 | } 99 | } 100 | 101 | @Override public void dispose() { 102 | clock.widthProperty().removeListener(sizeListener); 103 | clock.heightProperty().removeListener(sizeListener); 104 | clock.removeUpdateEventListener(updateEventListener); 105 | if (clock.isAnimated()) { 106 | clock.currentTimeProperty().removeListener(currentTimeListener); 107 | } else { 108 | clock.timeProperty().removeListener(timeListener); 109 | } 110 | clock.getAlarms().removeListener(alarmListener); 111 | clock = null; 112 | } 113 | 114 | 115 | // ******************** Graphics ****************************************** 116 | public abstract void updateTime(final ZonedDateTime TIME); 117 | 118 | public abstract void updateAlarms(); 119 | 120 | 121 | // ******************** Resizing ****************************************** 122 | protected abstract void resize(); 123 | 124 | protected abstract void redraw(); 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/skins/DigitalClockSkin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.skins; 19 | 20 | import eu.hansolo.medusa.Clock; 21 | import eu.hansolo.medusa.Fonts; 22 | import eu.hansolo.medusa.tools.Helper; 23 | import javafx.geometry.Insets; 24 | import javafx.geometry.VPos; 25 | import javafx.scene.canvas.Canvas; 26 | import javafx.scene.canvas.GraphicsContext; 27 | import javafx.scene.layout.Background; 28 | import javafx.scene.layout.BackgroundFill; 29 | import javafx.scene.layout.Border; 30 | import javafx.scene.layout.BorderStroke; 31 | import javafx.scene.layout.BorderStrokeStyle; 32 | import javafx.scene.layout.BorderWidths; 33 | import javafx.scene.layout.CornerRadii; 34 | import javafx.scene.layout.Pane; 35 | import javafx.scene.paint.Color; 36 | import javafx.scene.text.TextAlignment; 37 | 38 | import java.time.ZonedDateTime; 39 | import java.time.format.DateTimeFormatter; 40 | import java.util.Locale; 41 | 42 | 43 | /** 44 | * Created by hansolo on 11.08.16. 45 | */ 46 | public class DigitalClockSkin extends ClockSkinBase { 47 | protected static final double PREFERRED_WIDTH = 250; 48 | protected static final double PREFERRED_HEIGHT = 100; 49 | protected static final double MINIMUM_WIDTH = 50; 50 | protected static final double MINIMUM_HEIGHT = 20; 51 | protected static final double MAXIMUM_WIDTH = 1024; 52 | protected static final double MAXIMUM_HEIGHT = 1024; 53 | private static final DateTimeFormatter HHMM_FORMATTER = DateTimeFormatter.ofPattern("HH:mm"); 54 | private static final DateTimeFormatter HHMMSS_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss"); 55 | private static final DateTimeFormatter AMPM_HHMM_FORMATTER = DateTimeFormatter.ofPattern("hh:mm a"); 56 | private static final DateTimeFormatter AMPM_HHMMSS_FORMATTER = DateTimeFormatter.ofPattern("hh:mm:ss a"); 57 | private double aspectRatio = 0.4; 58 | private double width; 59 | private double height; 60 | private double centerX; 61 | private double centerY; 62 | private DateTimeFormatter dateFormat; 63 | private Pane pane; 64 | private Canvas canvas; 65 | private GraphicsContext ctx; 66 | private Color textColor; 67 | private Color dateColor; 68 | private Color alarmColor; 69 | 70 | 71 | // ******************** Constructors ************************************** 72 | public DigitalClockSkin(Clock clock) { 73 | super(clock); 74 | textColor = clock.getTextColor(); 75 | dateColor = clock.getDateColor(); 76 | alarmColor = clock.getAlarmColor(); 77 | dateFormat = Helper.getDateFormat(clock.getLocale()); 78 | 79 | initGraphics(); 80 | registerListeners(); 81 | } 82 | 83 | 84 | // ******************** Initialization ************************************ 85 | @Override protected void initGraphics() { 86 | // Set initial size 87 | if (Double.compare(clock.getPrefWidth(), 0.0) <= 0 || Double.compare(clock.getPrefHeight(), 0.0) <= 0 || 88 | Double.compare(clock.getWidth(), 0.0) <= 0 || Double.compare(clock.getHeight(), 0.0) <= 0) { 89 | if (clock.getPrefWidth() > 0 && clock.getPrefHeight() > 0) { 90 | clock.setPrefSize(clock.getPrefWidth(), clock.getPrefHeight()); 91 | } else { 92 | clock.setPrefSize(PREFERRED_WIDTH, PREFERRED_HEIGHT); 93 | } 94 | } 95 | 96 | canvas = new Canvas(PREFERRED_WIDTH, PREFERRED_HEIGHT); 97 | ctx = canvas.getGraphicsContext2D(); 98 | 99 | pane = new Pane(canvas); 100 | pane.setBorder(new Border(new BorderStroke(clock.getBorderPaint(), BorderStrokeStyle.SOLID, CornerRadii.EMPTY, new BorderWidths(clock.getBorderWidth())))); 101 | pane.setBackground(new Background(new BackgroundFill(clock.getBackgroundPaint(), CornerRadii.EMPTY, Insets.EMPTY))); 102 | 103 | getChildren().setAll(pane); 104 | } 105 | 106 | @Override protected void registerListeners() { 107 | super.registerListeners(); 108 | } 109 | 110 | 111 | // ******************** Methods ******************************************* 112 | @Override protected void handleEvents(final String EVENT_TYPE) { 113 | super.handleEvents(EVENT_TYPE); 114 | if ("VISIBILITY".equals(EVENT_TYPE)) { 115 | 116 | } else if ("SECTION".equals(EVENT_TYPE)) { 117 | redraw(); 118 | } 119 | } 120 | 121 | 122 | // ******************** Canvas ******************************************** 123 | private void drawTime(final ZonedDateTime TIME) { 124 | ctx.clearRect(0, 0, width, height); 125 | 126 | // draw the time 127 | if (clock.isTextVisible()) { 128 | ctx.setFill(textColor); 129 | ctx.setTextBaseline(VPos.CENTER); 130 | ctx.setTextAlign(TextAlignment.CENTER); 131 | if (Locale.US == clock.getLocale()) { 132 | ctx.setFont(Fonts.digital(0.5 * height)); 133 | ctx.fillText(clock.isSecondsVisible() ? AMPM_HHMMSS_FORMATTER.format(TIME) : AMPM_HHMM_FORMATTER.format(TIME), centerX, clock.isDateVisible() ? height * 0.35 : centerY); 134 | } else { 135 | ctx.setFont(Fonts.digital(0.6 * height)); 136 | ctx.fillText(clock.isSecondsVisible() ? HHMMSS_FORMATTER.format(TIME) : HHMM_FORMATTER.format(TIME), centerX, clock.isDateVisible() ? height * 0.3 : centerY); 137 | } 138 | } 139 | 140 | // draw the date 141 | if (clock.isDateVisible()) { 142 | ctx.setFill(dateColor); 143 | ctx.setFont(Fonts.digital(0.34 * height)); 144 | ctx.fillText(dateFormat.format(TIME), centerX, height * 0.77); 145 | } 146 | 147 | // draw the alarmOn icon 148 | if (clock.isAlarmsEnabled() && clock.getAlarms().size() > 0) { ctx.setFill(alarmColor); } 149 | 150 | } 151 | 152 | @Override public void updateTime(final ZonedDateTime TIME) { 153 | drawTime(TIME); 154 | } 155 | 156 | @Override public void updateAlarms() {} 157 | 158 | 159 | // ******************** Resizing ****************************************** 160 | @Override protected void resize() { 161 | width = clock.getWidth() - clock.getInsets().getLeft() - clock.getInsets().getRight(); 162 | height = clock.getHeight() - clock.getInsets().getTop() - clock.getInsets().getBottom(); 163 | 164 | if (aspectRatio * width > height) { 165 | width = 1 / (aspectRatio / height); 166 | } else if (1 / (aspectRatio / height) > width) { 167 | height = aspectRatio * width; 168 | } 169 | 170 | centerX = width * 0.5; 171 | centerY = height * 0.5; 172 | 173 | if (width > 0 && height > 0) { 174 | pane.setMaxSize(width, height); 175 | pane.relocate((clock.getWidth() - height) * 0.5, (clock.getHeight() - height) * 0.5); 176 | 177 | canvas.setWidth(width); 178 | canvas.setHeight(height); 179 | } 180 | } 181 | 182 | @Override protected void redraw() { 183 | pane.setBorder(new Border(new BorderStroke(clock.getBorderPaint(), BorderStrokeStyle.SOLID, CornerRadii.EMPTY, new BorderWidths(clock.getBorderWidth() / PREFERRED_WIDTH * height)))); 184 | pane.setBackground(new Background(new BackgroundFill(clock.getBackgroundPaint(), CornerRadii.EMPTY, Insets.EMPTY))); 185 | ZonedDateTime time = clock.getTime(); 186 | 187 | textColor = clock.getTextColor(); 188 | dateColor = clock.getDateColor(); 189 | alarmColor = clock.getAlarmColor(); 190 | 191 | drawTime(time); 192 | } 193 | } -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/skins/GaugeSkinBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.skins; 19 | 20 | import eu.hansolo.medusa.Gauge; 21 | import eu.hansolo.medusa.events.UpdateEventListener; 22 | import javafx.beans.InvalidationListener; 23 | import javafx.scene.control.Skin; 24 | import javafx.scene.control.SkinBase; 25 | 26 | 27 | /** 28 | * Created by hansolo on 20.01.17. 29 | */ 30 | public abstract class GaugeSkinBase extends SkinBase implements Skin { 31 | protected static final double PREFERRED_WIDTH = 250; 32 | protected static final double PREFERRED_HEIGHT = 250; 33 | protected static final double MINIMUM_WIDTH = 50; 34 | protected static final double MINIMUM_HEIGHT = 50; 35 | protected static final double MAXIMUM_WIDTH = 1024; 36 | protected static final double MAXIMUM_HEIGHT = 1024; 37 | protected Gauge gauge; 38 | protected InvalidationListener sizeListener; 39 | protected UpdateEventListener updateEventListener; 40 | 41 | 42 | protected GaugeSkinBase(final Gauge GAUGE) { 43 | super(GAUGE); 44 | gauge = GAUGE; 45 | sizeListener = o -> handleEvents("RESIZE"); 46 | updateEventListener = e -> handleEvents(e.eventType.name()); 47 | } 48 | 49 | protected void registerListeners() { 50 | getSkinnable().widthProperty().addListener(sizeListener); 51 | getSkinnable().heightProperty().addListener(sizeListener); 52 | getSkinnable().setOnUpdate(updateEventListener); 53 | } 54 | 55 | protected void handleEvents(final String EVENT_TYPE) { 56 | if ("RESIZE".equals(EVENT_TYPE)) { 57 | resize(); 58 | redraw(); 59 | } else if ("REDRAW".equals(EVENT_TYPE)) { 60 | redraw(); 61 | } 62 | } 63 | 64 | 65 | // ******************** Methods ******************************************* 66 | @Override protected double computeMinWidth(final double HEIGHT, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return MINIMUM_WIDTH; } 67 | @Override protected double computeMinHeight(final double WIDTH, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return MINIMUM_HEIGHT; } 68 | @Override protected double computePrefWidth(final double HEIGHT, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return super.computePrefWidth(HEIGHT, TOP, RIGHT, BOTTOM, LEFT); } 69 | @Override protected double computePrefHeight(final double WIDTH, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return super.computePrefHeight(WIDTH, TOP, RIGHT, BOTTOM, LEFT); } 70 | @Override protected double computeMaxWidth(final double HEIGHT, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return MAXIMUM_WIDTH; } 71 | @Override protected double computeMaxHeight(final double WIDTH, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return MAXIMUM_HEIGHT; } 72 | 73 | @Override public void dispose() { 74 | gauge.widthProperty().removeListener(sizeListener); 75 | gauge.heightProperty().removeListener(sizeListener); 76 | gauge.removeUpdateEventListener(updateEventListener); 77 | } 78 | 79 | protected void resize() {} 80 | 81 | protected void redraw() {} 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/skins/SlimClockSkin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.skins; 19 | 20 | import eu.hansolo.medusa.Clock; 21 | import eu.hansolo.medusa.Fonts; 22 | import eu.hansolo.medusa.tools.Helper; 23 | import javafx.geometry.Insets; 24 | import javafx.scene.layout.Background; 25 | import javafx.scene.layout.BackgroundFill; 26 | import javafx.scene.layout.Border; 27 | import javafx.scene.layout.BorderStroke; 28 | import javafx.scene.layout.BorderStrokeStyle; 29 | import javafx.scene.layout.BorderWidths; 30 | import javafx.scene.layout.CornerRadii; 31 | import javafx.scene.layout.Pane; 32 | import javafx.scene.shape.Arc; 33 | import javafx.scene.shape.Circle; 34 | import javafx.scene.shape.StrokeLineCap; 35 | import javafx.scene.shape.StrokeType; 36 | import javafx.scene.text.Text; 37 | 38 | import java.time.ZonedDateTime; 39 | import java.time.format.DateTimeFormatter; 40 | import java.time.temporal.ChronoField; 41 | 42 | 43 | /** 44 | * Created by hansolo on 11.02.16. 45 | */ 46 | public class SlimClockSkin extends ClockSkinBase { 47 | private static final DateTimeFormatter HOUR_FORMATTER = DateTimeFormatter.ofPattern("HH"); 48 | private static final DateTimeFormatter MINUTE_FORMATTER = DateTimeFormatter.ofPattern("mm"); 49 | private DateTimeFormatter dateTextFormatter; 50 | private DateTimeFormatter dateNumberFormatter; 51 | private double size; 52 | private Circle secondBackgroundCircle; 53 | private Text dateText; 54 | private Text dateNumbers; 55 | private Text hour; 56 | private Text minute; 57 | private Arc secondArc; 58 | private Pane pane; 59 | 60 | 61 | // ******************** Constructors ************************************** 62 | public SlimClockSkin(Clock clock) { 63 | super(clock); 64 | 65 | dateTextFormatter = DateTimeFormatter.ofPattern("cccc", clock.getLocale()); 66 | dateNumberFormatter = Helper.getLocalizedDateFormat(clock.getLocale()); 67 | 68 | initGraphics(); 69 | registerListeners(); 70 | } 71 | 72 | 73 | // ******************** Initialization ************************************ 74 | @Override protected void initGraphics() { 75 | // Set initial size 76 | if (Double.compare(clock.getPrefWidth(), 0.0) <= 0 || Double.compare(clock.getPrefHeight(), 0.0) <= 0 || 77 | Double.compare(clock.getWidth(), 0.0) <= 0 || Double.compare(clock.getHeight(), 0.0) <= 0) { 78 | if (clock.getPrefWidth() > 0 && clock.getPrefHeight() > 0) { 79 | clock.setPrefSize(clock.getPrefWidth(), clock.getPrefHeight()); 80 | } else { 81 | clock.setPrefSize(PREFERRED_WIDTH, PREFERRED_HEIGHT); 82 | } 83 | } 84 | 85 | ZonedDateTime time = clock.getTime(); 86 | 87 | secondBackgroundCircle = new Circle(PREFERRED_WIDTH * 0.5, PREFERRED_HEIGHT * 0.5, PREFERRED_WIDTH * 0.48); 88 | secondBackgroundCircle.setStrokeWidth(PREFERRED_WIDTH * 0.008); 89 | secondBackgroundCircle.setStrokeType(StrokeType.CENTERED); 90 | secondBackgroundCircle.setStrokeLineCap(StrokeLineCap.ROUND); 91 | secondBackgroundCircle.setFill(null); 92 | secondBackgroundCircle.setStroke(Helper.getTranslucentColorFrom(clock.getSecondColor(), 0.2)); 93 | secondBackgroundCircle.setVisible(clock.isSecondsVisible()); 94 | secondBackgroundCircle.setManaged(clock.isSecondsVisible()); 95 | 96 | dateText = new Text(dateTextFormatter.format(time)); 97 | dateText.setVisible(clock.isDayVisible()); 98 | dateText.setManaged(clock.isDayVisible()); 99 | 100 | dateNumbers = new Text(dateNumberFormatter.format(time)); 101 | dateNumbers.setVisible(clock.isDateVisible()); 102 | dateNumbers.setManaged(clock.isDateVisible()); 103 | 104 | hour = new Text(HOUR_FORMATTER.format(time)); 105 | hour.setFill(clock.getHourColor()); 106 | 107 | minute = new Text(MINUTE_FORMATTER.format(time)); 108 | minute.setFill(clock.getMinuteColor()); 109 | 110 | secondArc = new Arc(PREFERRED_WIDTH * 0.5, PREFERRED_HEIGHT * 0.5, PREFERRED_WIDTH * 0.96, PREFERRED_WIDTH * 0.48, 90, (-6 * clock.getTime().getSecond())); 111 | secondArc.setStrokeWidth(PREFERRED_WIDTH * 0.008); 112 | secondArc.setStrokeType(StrokeType.CENTERED); 113 | secondArc.setStrokeLineCap(StrokeLineCap.ROUND); 114 | secondArc.setFill(null); 115 | secondArc.setStroke(clock.getSecondColor()); 116 | secondArc.setVisible(clock.isSecondsVisible()); 117 | secondArc.setManaged(clock.isSecondsVisible()); 118 | 119 | pane = new Pane(secondBackgroundCircle, dateText, dateNumbers, hour, minute, secondArc); 120 | pane.setBorder(new Border(new BorderStroke(clock.getBorderPaint(), BorderStrokeStyle.SOLID, new CornerRadii(1024), new BorderWidths(clock.getBorderWidth())))); 121 | pane.setBackground(new Background(new BackgroundFill(clock.getBackgroundPaint(), new CornerRadii(1024), Insets.EMPTY))); 122 | 123 | getChildren().setAll(pane); 124 | } 125 | 126 | @Override protected void registerListeners() { 127 | super.registerListeners(); 128 | } 129 | 130 | 131 | // ******************** Methods ******************************************* 132 | @Override protected void handleEvents(final String EVENT_TYPE) { 133 | super.handleEvents(EVENT_TYPE); 134 | if ("VISIBILITY".equals(EVENT_TYPE)) { 135 | boolean isDateVisible = clock.isDateVisible(); 136 | boolean isDayVisible = clock.isDayVisible(); 137 | dateText.setVisible(isDayVisible); 138 | dateText.setManaged(isDayVisible); 139 | dateNumbers.setVisible(isDateVisible); 140 | dateNumbers.setManaged(isDateVisible); 141 | boolean isSecondsVisible = clock.isSecondsVisible(); 142 | secondBackgroundCircle.setVisible(isSecondsVisible); 143 | secondBackgroundCircle.setManaged(isSecondsVisible); 144 | secondArc.setVisible(isSecondsVisible); 145 | secondArc.setManaged(isSecondsVisible); 146 | } else if ("FINISHED".equals(EVENT_TYPE)) { 147 | 148 | } 149 | } 150 | 151 | 152 | // ******************** Graphics ****************************************** 153 | @Override public void updateTime(final ZonedDateTime TIME) { 154 | if (dateText.isVisible()) { 155 | dateText.setText(dateTextFormatter.format(TIME)); 156 | Helper.adjustTextSize(dateText, 0.6 * size, size * 0.08); 157 | dateText.relocate((size - dateText.getLayoutBounds().getWidth()) * 0.5, size * 0.22180451); 158 | } 159 | if (dateNumbers.isVisible()) { 160 | dateNumbers.setText(dateNumberFormatter.format(TIME)); 161 | Helper.adjustTextSize(dateNumbers, 0.6 * size, size * 0.08); 162 | dateNumbers.relocate((size -dateNumbers.getLayoutBounds().getWidth()) * 0.5, size * 0.68984962); 163 | } 164 | 165 | hour.setText(HOUR_FORMATTER.format(TIME)); 166 | Helper.adjustTextSize(hour, 0.4 * size, 0.328 * size); 167 | hour.relocate(0.136 * size, (size - hour.getLayoutBounds().getHeight()) * 0.5); 168 | 169 | minute.setText(MINUTE_FORMATTER.format(TIME)); 170 | Helper.adjustTextSize(minute, 0.4 * size, 0.328 * size); 171 | minute.relocate(0.544 * size, (size - minute.getLayoutBounds().getHeight()) * 0.5); 172 | 173 | if (secondBackgroundCircle.isVisible()) { 174 | secondArc.setLength((-6 * TIME.getSecond())); 175 | if (clock.isDiscreteSeconds()) { 176 | secondArc.setLength((-6 * TIME.getSecond())); 177 | } else { 178 | secondArc.setLength((-6 * TIME.getSecond() -TIME.get(ChronoField.MILLI_OF_SECOND) * 0.006)); 179 | } 180 | } 181 | } 182 | 183 | @Override public void updateAlarms() { 184 | 185 | } 186 | 187 | 188 | // ******************** Resizing ****************************************** 189 | @Override protected void resize() { 190 | double width = clock.getWidth() - clock.getInsets().getLeft() - clock.getInsets().getRight(); 191 | double height = clock.getHeight() - clock.getInsets().getTop() - clock.getInsets().getBottom(); 192 | size = width < height ? width : height; 193 | 194 | if (size > 0) { 195 | double center = size * 0.5; 196 | 197 | pane.setMaxSize(size, size); 198 | pane.relocate((clock.getWidth() - size) * 0.5, (clock.getHeight() - size) * 0.5); 199 | 200 | secondBackgroundCircle.setCenterX(center); 201 | secondBackgroundCircle.setCenterY(center); 202 | secondBackgroundCircle.setRadius(size * 0.48590226); 203 | secondBackgroundCircle.setStrokeWidth(size * 0.02819549); 204 | 205 | secondArc.setCenterX(center); 206 | secondArc.setCenterY(center); 207 | secondArc.setRadiusX(size * 0.48590226); 208 | secondArc.setRadiusY(size * 0.48590226); 209 | secondArc.setStrokeWidth(size * 0.02819549); 210 | 211 | dateText.setFont(Fonts.robotoLight(size * 0.08082707)); 212 | dateNumbers.setFont(Fonts.robotoLight(size * 0.08082707)); 213 | 214 | hour.setFont(Fonts.robotoMedium(size * 0.328)); 215 | minute.setFont(Fonts.robotoThin(size * 0.328)); 216 | } 217 | } 218 | 219 | @Override protected void redraw() { 220 | pane.setBorder(new Border(new BorderStroke(clock.getBorderPaint(), BorderStrokeStyle.SOLID, new CornerRadii(1024), new BorderWidths(clock.getBorderWidth() / 250 * size)))); 221 | pane.setBackground(new Background(new BackgroundFill(clock.getBackgroundPaint(), new CornerRadii(1024), Insets.EMPTY))); 222 | 223 | secondBackgroundCircle.setStroke(Helper.getTranslucentColorFrom(clock.getSecondColor(), 0.2)); 224 | secondArc.setStroke(clock.getSecondColor()); 225 | 226 | hour.setFill(clock.getHourColor()); 227 | minute.setFill(clock.getMinuteColor()); 228 | 229 | dateText.setFill(clock.getDateColor()); 230 | dateNumbers.setFill(clock.getDateColor()); 231 | 232 | hour.setFill(clock.getHourColor()); 233 | minute.setFill(clock.getMinuteColor()); 234 | 235 | ZonedDateTime time = clock.getTime(); 236 | updateTime(time); 237 | } 238 | } 239 | 240 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/skins/TextClockSkin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.skins; 19 | 20 | import eu.hansolo.medusa.Clock; 21 | import eu.hansolo.medusa.Fonts; 22 | import eu.hansolo.medusa.tools.Helper; 23 | import javafx.geometry.Insets; 24 | import javafx.geometry.VPos; 25 | import javafx.scene.layout.Background; 26 | import javafx.scene.layout.BackgroundFill; 27 | import javafx.scene.layout.Border; 28 | import javafx.scene.layout.BorderStroke; 29 | import javafx.scene.layout.BorderStrokeStyle; 30 | import javafx.scene.layout.BorderWidths; 31 | import javafx.scene.layout.CornerRadii; 32 | import javafx.scene.layout.Pane; 33 | import javafx.scene.paint.Color; 34 | import javafx.scene.text.Font; 35 | import javafx.scene.text.Text; 36 | 37 | import java.time.ZonedDateTime; 38 | import java.time.format.DateTimeFormatter; 39 | import java.util.Locale; 40 | 41 | 42 | /** 43 | * Created by hansolo on 29.09.16. 44 | */ 45 | public class TextClockSkin extends ClockSkinBase { 46 | protected static final double PREFERRED_WIDTH = 250; 47 | protected static final double PREFERRED_HEIGHT = 100; 48 | protected static final double MINIMUM_WIDTH = 50; 49 | protected static final double MINIMUM_HEIGHT = 20; 50 | protected static final double MAXIMUM_WIDTH = 1024; 51 | protected static final double MAXIMUM_HEIGHT = 1024; 52 | private static final DateTimeFormatter HHMM_FORMATTER = DateTimeFormatter.ofPattern("HH:mm"); 53 | private static final DateTimeFormatter HHMMSS_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss"); 54 | private static final DateTimeFormatter AMPM_HHMM_FORMATTER = DateTimeFormatter.ofPattern("hh:mm a"); 55 | private static final DateTimeFormatter AMPM_HHMMSS_FORMATTER = DateTimeFormatter.ofPattern("hh:mm:ss a"); 56 | private double aspectRatio = 0.4; 57 | private double width; 58 | private double height; 59 | private DateTimeFormatter dateFormat; 60 | private Text timeText; 61 | private Text dateText; 62 | private Pane pane; 63 | private Color textColor; 64 | private Color dateColor; 65 | private Font customFont; 66 | 67 | 68 | // ******************** Constructors ************************************** 69 | public TextClockSkin(Clock clock) { 70 | super(clock); 71 | textColor = clock.getTextColor(); 72 | dateColor = clock.getDateColor(); 73 | dateFormat = Helper.getDateFormat(clock.getLocale()); 74 | customFont = clock.getCustomFont(); 75 | 76 | initGraphics(); 77 | registerListeners(); 78 | } 79 | 80 | 81 | // ******************** Initialization ************************************ 82 | @Override protected void initGraphics() { 83 | // Set initial size 84 | if (Double.compare(clock.getPrefWidth(), 0.0) <= 0 || Double.compare(clock.getPrefHeight(), 0.0) <= 0 || 85 | Double.compare(clock.getWidth(), 0.0) <= 0 || Double.compare(clock.getHeight(), 0.0) <= 0) { 86 | if (clock.getPrefWidth() > 0 && clock.getPrefHeight() > 0) { 87 | clock.setPrefSize(clock.getPrefWidth(), clock.getPrefHeight()); 88 | } else { 89 | clock.setPrefSize(PREFERRED_WIDTH, PREFERRED_HEIGHT); 90 | } 91 | } 92 | 93 | timeText = new Text(); 94 | timeText.setTextOrigin(VPos.CENTER); 95 | timeText.setFill(textColor); 96 | 97 | dateText = new Text(); 98 | dateText.setTextOrigin(VPos.CENTER); 99 | dateText.setFill(dateColor); 100 | 101 | pane = new Pane(timeText, dateText); 102 | pane.setBorder(new Border(new BorderStroke(clock.getBorderPaint(), BorderStrokeStyle.SOLID, CornerRadii.EMPTY, new BorderWidths(clock.getBorderWidth())))); 103 | pane.setBackground(new Background(new BackgroundFill(clock.getBackgroundPaint(), CornerRadii.EMPTY, Insets.EMPTY))); 104 | 105 | getChildren().setAll(pane); 106 | } 107 | 108 | @Override protected void registerListeners() { 109 | super.registerListeners(); 110 | } 111 | 112 | 113 | // ******************** Methods ******************************************* 114 | @Override protected void handleEvents(final String EVENT_TYPE) { 115 | super.handleEvents(EVENT_TYPE); 116 | if ("VISIBILITY".equals(EVENT_TYPE)) { 117 | 118 | } else if ("SECTION".equals(EVENT_TYPE)) { 119 | redraw(); 120 | } 121 | } 122 | 123 | 124 | // ******************** Canvas ******************************************** 125 | private void drawTime(final ZonedDateTime TIME) { 126 | // draw the time 127 | if (clock.isTextVisible()) { 128 | if (Locale.US == clock.getLocale()) { 129 | timeText.setText(clock.isSecondsVisible() ? AMPM_HHMMSS_FORMATTER.format(TIME) : AMPM_HHMM_FORMATTER.format(TIME)); 130 | } else { 131 | timeText.setText(clock.isSecondsVisible() ? HHMMSS_FORMATTER.format(TIME) : HHMM_FORMATTER.format(TIME)); 132 | } 133 | timeText.setX((width - timeText.getLayoutBounds().getWidth()) * 0.5); 134 | } 135 | 136 | // draw the date 137 | if (clock.isDateVisible()) { 138 | dateText.setText(dateFormat.format(TIME)); 139 | dateText.setX((width - dateText.getLayoutBounds().getWidth()) * 0.5); 140 | } 141 | } 142 | 143 | @Override public void updateTime(final ZonedDateTime TIME) { 144 | drawTime(TIME); 145 | } 146 | 147 | @Override public void updateAlarms() {} 148 | 149 | 150 | // ******************** Resizing ****************************************** 151 | @Override protected void resize() { 152 | width = clock.getWidth() - clock.getInsets().getLeft() - clock.getInsets().getRight(); 153 | height = clock.getHeight() - clock.getInsets().getTop() - clock.getInsets().getBottom(); 154 | 155 | if (aspectRatio * width > height) { 156 | width = 1 / (aspectRatio / height); 157 | } else if (1 / (aspectRatio / height) > width) { 158 | height = aspectRatio * width; 159 | } 160 | 161 | if (width > 0 && height > 0) { 162 | pane.setMaxSize(width, height); 163 | pane.relocate((clock.getWidth() - height) * 0.5, (clock.getHeight() - height) * 0.5); 164 | 165 | if (clock.isTextVisible()) { 166 | if (null == customFont) { 167 | timeText.setFont(Locale.US == clock.getLocale() ? Fonts.robotoLight(0.5 * height) : Fonts.robotoLight(0.6 * height)); 168 | } else { 169 | timeText.setFont(Locale.US == clock.getLocale() ? new Font(customFont.getName(), 0.5 * height) : new Font(customFont.getName(), 0.6 * height)); 170 | } 171 | timeText.setX((width - timeText.getLayoutBounds().getWidth()) * 0.5); 172 | if (clock.isDateVisible()) { 173 | timeText.setY(height * 0.3); 174 | } else { 175 | timeText.setY(height * 0.5); 176 | } 177 | } 178 | if (clock.isDateVisible()) { 179 | if (null == customFont) { 180 | dateText.setFont(Fonts.robotoLight(0.3 * height)); 181 | } else { 182 | dateText.setFont(new Font(customFont.getName(), 0.3 * height)); 183 | } 184 | dateText.setX((width - dateText.getLayoutBounds().getWidth()) * 0.5); 185 | dateText.setY(height * 0.8); 186 | } 187 | } 188 | } 189 | 190 | @Override protected void redraw() { 191 | pane.setBorder(new Border(new BorderStroke(clock.getBorderPaint(), BorderStrokeStyle.SOLID, CornerRadii.EMPTY, new BorderWidths(clock.getBorderWidth() / PREFERRED_WIDTH * height)))); 192 | pane.setBackground(new Background(new BackgroundFill(clock.getBackgroundPaint(), CornerRadii.EMPTY, Insets.EMPTY))); 193 | ZonedDateTime time = clock.getTime(); 194 | 195 | dateFormat = Helper.getDateFormat(clock.getLocale()); 196 | 197 | textColor = clock.getTextColor(); 198 | timeText.setFill(textColor); 199 | 200 | dateColor = clock.getDateColor(); 201 | dateText.setFill(dateColor); 202 | 203 | drawTime(time); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/tools/AngleConicalGradient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.tools; 19 | 20 | import eu.hansolo.medusa.Gauge.ScaleDirection; 21 | import javafx.geometry.Point2D; 22 | import javafx.scene.image.Image; 23 | import javafx.scene.paint.Color; 24 | import javafx.scene.paint.ImagePattern; 25 | import javafx.scene.paint.Stop; 26 | import javafx.scene.shape.Rectangle; 27 | import javafx.scene.shape.Shape; 28 | 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | import java.util.Map; 32 | 33 | 34 | /** 35 | * Created by hansolo on 21.12.15. 36 | */ 37 | public class AngleConicalGradient { 38 | private ConicalGradient gradient; 39 | 40 | public AngleConicalGradient(final Map ANGLE_STOP_MAP, final ScaleDirection DIRECTION) { 41 | this(0, 0, ANGLE_STOP_MAP, DIRECTION); 42 | } 43 | public AngleConicalGradient(final double CENTER_X, final double CENTER_Y, final Map ANGLE_STOP_MAP, final ScaleDirection DIRECTION) { 44 | this(CENTER_X, CENTER_Y, 0.0, ANGLE_STOP_MAP, DIRECTION); 45 | } 46 | public AngleConicalGradient(final double CENTER_X, final double CENTER_Y, final double OFFSET_ANGLE, final Map ANGLE_STOP_MAP, final ScaleDirection DIRECTION) { 47 | final double ANGLE_FACTOR = 1.0 / 360.0; 48 | double offset = Helper.clamp(0, 1, (OFFSET_ANGLE % 360.0) * ANGLE_FACTOR); 49 | List stops = new ArrayList<>(); 50 | for (double fraction : ANGLE_STOP_MAP.keySet()) { 51 | stops.add(new Stop(Helper.clamp(0, 1, (fraction % 360.0) * ANGLE_FACTOR), ANGLE_STOP_MAP.get(fraction))); 52 | } 53 | gradient = new ConicalGradient(CENTER_X, CENTER_Y, offset, DIRECTION, stops); 54 | } 55 | 56 | public void recalculateWithAngle(final double ANGLE) { gradient.recalculateWithAngle(ANGLE); } 57 | 58 | public List getStops() { return gradient.getStops(); } 59 | 60 | public double[] getCenter() { return gradient.getCenter(); } 61 | public Point2D getCenterPoint() { return gradient.getCenterPoint(); } 62 | 63 | public Image getImage(final double WIDTH, final double HEIGHT) { return gradient.getImage(WIDTH, HEIGHT); } 64 | public Image getRoundImage(final double SIZE) { return gradient.getRoundImage(SIZE); } 65 | 66 | public ImagePattern apply(final Shape SHAPE) { return gradient.apply(SHAPE); } 67 | 68 | public ImagePattern getImagePattern(final Rectangle BOUNDS) { return gradient.getImagePattern(BOUNDS); } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/tools/Data.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.tools; 19 | 20 | import java.time.Instant; 21 | 22 | 23 | /** 24 | * Created by hansolo on 01.11.16. 25 | */ 26 | public class Data { 27 | private final Instant timestamp; 28 | private final double value; 29 | 30 | 31 | // ******************** Constructors ************************************** 32 | public Data(final double VALUE) { 33 | value = VALUE; 34 | timestamp = Instant.now(); 35 | } 36 | 37 | 38 | // ******************** Methods ******************************************* 39 | public double getValue() { return value; } 40 | 41 | public Instant getTimestamp() { return timestamp; } 42 | 43 | @Override public String toString() { 44 | return new StringBuilder().append("{\n") 45 | .append(" \"timestamp\":").append(timestamp.getEpochSecond()).append(",\n") 46 | .append(" \"value\":").append(value).append(",\n") 47 | .append("}") 48 | .toString(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/tools/GradientLookup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.tools; 19 | 20 | import javafx.scene.paint.Color; 21 | import javafx.scene.paint.Stop; 22 | 23 | import java.util.ArrayList; 24 | import java.util.Arrays; 25 | import java.util.Collections; 26 | import java.util.List; 27 | import java.util.Map; 28 | import java.util.TreeMap; 29 | 30 | 31 | /** 32 | * Created by hansolo on 21.12.15. 33 | */ 34 | public class GradientLookup { 35 | private Map stops; 36 | 37 | 38 | // ******************** Constructors ************************************** 39 | public GradientLookup () { 40 | this(new Stop[]{}); 41 | } 42 | public GradientLookup(final Stop... STOPS) { 43 | this(Arrays.asList(STOPS)); 44 | } 45 | public GradientLookup(final List STOPS) { 46 | stops = new TreeMap<>(); 47 | for (Stop stop : STOPS) { stops.put(stop.getOffset(), stop); } 48 | init(); 49 | } 50 | 51 | 52 | // ******************** Initialization ************************************ 53 | private void init() { 54 | if (stops.isEmpty()) return; 55 | 56 | double minFraction = Collections.min(stops.keySet()); 57 | double maxFraction = Collections.max(stops.keySet()); 58 | 59 | if (Double.compare(minFraction, 0) > 0) { stops.put(0.0, new Stop(0.0, stops.get(minFraction).getColor())); } 60 | if (Double.compare(maxFraction, 1) < 0) { stops.put(1.0, new Stop(1.0, stops.get(maxFraction).getColor())); } 61 | } 62 | 63 | 64 | // ******************** Methods ******************************************* 65 | public Color getColorAt(final double POSITION_OF_COLOR) { 66 | if (stops.isEmpty()) return Color.BLACK; 67 | 68 | final double POSITION = Helper.clamp(0.0, 1.0, POSITION_OF_COLOR); 69 | final Color COLOR; 70 | if (stops.size() == 1) { 71 | final Map ONE_ENTRY = (Map) stops.entrySet().iterator().next(); 72 | COLOR = stops.get(ONE_ENTRY.keySet().iterator().next()).getColor(); 73 | } else { 74 | Stop lowerBound = stops.get(0.0); 75 | Stop upperBound = stops.get(1.0); 76 | for (Double fraction : stops.keySet()) { 77 | if (Double.compare(fraction,POSITION) < 0) { 78 | lowerBound = stops.get(fraction); 79 | } 80 | if (Double.compare(fraction, POSITION) > 0) { 81 | upperBound = stops.get(fraction); 82 | break; 83 | } 84 | } 85 | COLOR = interpolateColor(lowerBound, upperBound, POSITION); 86 | } 87 | return COLOR; 88 | } 89 | 90 | public List getStops() { return new ArrayList<>(stops.values()); } 91 | public void setStops(final Stop... STOPS) { setStops(Arrays.asList(STOPS)); } 92 | public void setStops(final List STOPS) { 93 | stops.clear(); 94 | for (Stop stop : STOPS) { stops.put(stop.getOffset(), stop); } 95 | init(); 96 | } 97 | 98 | private Color interpolateColor(final Stop LOWER_BOUND, final Stop UPPER_BOUND, final double POSITION) { 99 | final double POS = (POSITION - LOWER_BOUND.getOffset()) / (UPPER_BOUND.getOffset() - LOWER_BOUND.getOffset()); 100 | 101 | final double DELTA_RED = (UPPER_BOUND.getColor().getRed() - LOWER_BOUND.getColor().getRed()) * POS; 102 | final double DELTA_GREEN = (UPPER_BOUND.getColor().getGreen() - LOWER_BOUND.getColor().getGreen()) * POS; 103 | final double DELTA_BLUE = (UPPER_BOUND.getColor().getBlue() - LOWER_BOUND.getColor().getBlue()) * POS; 104 | final double DELTA_OPACITY = (UPPER_BOUND.getColor().getOpacity() - LOWER_BOUND.getColor().getOpacity()) * POS; 105 | 106 | double red = Helper.clamp(0.0, 1.0, (LOWER_BOUND.getColor().getRed() + DELTA_RED)); 107 | double green = Helper.clamp(0.0, 1.0, (LOWER_BOUND.getColor().getGreen() + DELTA_GREEN)); 108 | double blue = Helper.clamp(0.0, 1.0, (LOWER_BOUND.getColor().getBlue() + DELTA_BLUE)); 109 | double opacity = Helper.clamp(0.0, 1.0, (LOWER_BOUND.getColor().getOpacity() + DELTA_OPACITY)); 110 | 111 | return Color.color(red, green, blue, opacity); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/tools/MarkerComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.tools; 19 | 20 | import eu.hansolo.medusa.Marker; 21 | 22 | import java.io.Serializable; 23 | import java.util.Comparator; 24 | 25 | 26 | /** 27 | * Created by hansolo on 26.01.16. 28 | */ 29 | public class MarkerComparator implements Comparator, Serializable { 30 | @Override public int compare(final Marker MARKER_1, final Marker MARKER_2) { 31 | return MARKER_1.compareTo(MARKER_2); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/tools/MovingAverage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.tools; 19 | 20 | import java.time.Duration; 21 | import java.time.Instant; 22 | import java.util.LinkedList; 23 | import java.util.Queue; 24 | import java.util.concurrent.ConcurrentLinkedQueue; 25 | 26 | 27 | /** 28 | * Created by hansolo on 01.11.16. 29 | */ 30 | public class MovingAverage { 31 | public static final int MAX_PERIOD = 2_073_600; // 24h in seconds 32 | private static final int DEFAULT_PERIOD = 10; 33 | private final Queue window; 34 | private int period; 35 | private double sum; 36 | 37 | 38 | // ******************** Constructors ************************************** 39 | public MovingAverage() { 40 | this(DEFAULT_PERIOD); 41 | } 42 | public MovingAverage(final int PERIOD) { 43 | period = Helper.clamp(0, MAX_PERIOD, PERIOD); 44 | window = new ConcurrentLinkedQueue<>(); 45 | } 46 | 47 | 48 | // ******************** Methods ******************************************* 49 | public void addData(final Data DATA) { 50 | sum += DATA.getValue(); 51 | window.add(DATA); 52 | if (window.size() > period) { 53 | sum -= window.remove().getValue(); 54 | } 55 | } 56 | public void addValue(final double VALUE) { 57 | addData(new Data(VALUE)); 58 | } 59 | 60 | public Queue getWindow() { return new LinkedList<>(window); } 61 | 62 | public double getAverage() { 63 | if (window.isEmpty()) return 0; // technically the average is undefined 64 | return (sum / window.size()); 65 | } 66 | 67 | public double getTimeBasedAverageOf(final Duration DURATION) { 68 | assert !DURATION.isNegative() : "Time period must be positive"; 69 | Instant now = Instant.now(); 70 | return window.stream() 71 | .filter(v -> v.getTimestamp().isAfter(now.minus(DURATION))) 72 | .mapToDouble(Data::getValue) 73 | .average() 74 | .getAsDouble(); 75 | } 76 | 77 | public int getPeriod() { return period; } 78 | public void setPeriod(final int PERIOD) { 79 | period = Helper.clamp(0, MAX_PERIOD, PERIOD); 80 | reset(); 81 | } 82 | 83 | public boolean isFilling() { return window.size() < period; } 84 | 85 | public void reset() { window.clear(); } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/tools/SectionComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.tools; 19 | 20 | import eu.hansolo.medusa.Section; 21 | 22 | import java.io.Serializable; 23 | import java.util.Comparator; 24 | 25 | 26 | /** 27 | * Created by hansolo on 26.01.16. 28 | */ 29 | public class SectionComparator implements Comparator
, Serializable { 30 | @Override public int compare(final Section SECTION_1, final Section SECTION_2) { 31 | return SECTION_1.compareTo(SECTION_2); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/tools/Statistics.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.tools; 19 | 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | 24 | /** 25 | * Created by hansolo on 06.12.16. 26 | */ 27 | public class Statistics { 28 | 29 | 30 | // ******************** Methods ******************************************* 31 | public static double getMean(final List DATA) { return DATA.stream().mapToDouble(v -> v).sum() / DATA.size(); } 32 | 33 | public static double getVariance(final List DATA) { 34 | double mean = getMean(DATA); 35 | double temp = 0; 36 | for (double a : DATA) { temp += ((a - mean) * (a - mean)); } 37 | return temp / DATA.size(); 38 | } 39 | 40 | public static double getStdDev(final List DATA) { return Math.sqrt(getVariance(DATA)); } 41 | 42 | public static double getMedian(final List DATA) { 43 | int size = DATA.size(); 44 | Collections.sort(DATA); 45 | return size % 2 == 0 ? (DATA.get((size / 2) - 1) + DATA.get(size / 2)) / 2.0 : DATA.get(size / 2); 46 | } 47 | 48 | public static double getMin(final List DATA) { return DATA.stream().mapToDouble(v -> v).min().orElse(0); } 49 | 50 | public static double getMax(final List DATA) { return DATA.stream().mapToDouble(v -> v).max().orElse(0); } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/eu/hansolo/medusa/tools/TimeSectionComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | package eu.hansolo.medusa.tools; 19 | 20 | import eu.hansolo.medusa.TimeSection; 21 | 22 | import java.io.Serializable; 23 | import java.util.Comparator; 24 | 25 | 26 | /** 27 | * Created by hansolo on 31.01.16. 28 | */ 29 | public class TimeSectionComparator implements Comparator, Serializable { 30 | @Override public int compare(final TimeSection SECTION_1, final TimeSection SECTION_2) { 31 | return SECTION_1.compareTo(SECTION_2); 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | module eu.hansolo.medusa { 19 | 20 | // Java 21 | requires java.base; 22 | 23 | // Java-FX 24 | requires transitive javafx.base; 25 | requires transitive javafx.graphics; 26 | requires transitive javafx.controls; 27 | 28 | exports eu.hansolo.medusa; 29 | exports eu.hansolo.medusa.skins; 30 | exports eu.hansolo.medusa.events; 31 | exports eu.hansolo.medusa.tools; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/Estricta-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/Estricta-Medium.otf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/Estricta-MediumItalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/Estricta-MediumItalic.otf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/Estricta-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/Estricta-Regular.otf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/Estricta-RegularItalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/Estricta-RegularItalic.otf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/Lato-Bol.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/Lato-Bol.otf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/Lato-Lig.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/Lato-Lig.otf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/Lato-Reg.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/Lato-Reg.otf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/Roboto-Bold.ttf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/Roboto-Light.ttf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/Roboto-Medium.ttf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/Roboto-Regular.ttf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/Roboto-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/Roboto-Thin.ttf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/RobotoCondensed-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/RobotoCondensed-Bold.ttf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/RobotoCondensed-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/RobotoCondensed-Light.ttf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/RobotoCondensed-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/RobotoCondensed-Regular.ttf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/clock.css: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | * CLOCK class * 20 | *****************************************************************************/ 21 | .clock { 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/digital.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/digital.ttf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/digitalreadout.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/digitalreadout.ttf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/digitalreadoutb.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/digitalreadoutb.ttf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/elektra.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanSolo/medusa/51b560b5a11db6bc4835e934f3df2f273561bc6c/src/main/resources/eu/hansolo/medusa/elektra.ttf -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/framed-gauge.css: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | .framed-gauge { 19 | 20 | } 21 | 22 | .steel-series-frame { 23 | -outer-border : rgb(132,132,132); 24 | -inner-border : linear-gradient(to bottom, rgb(254,254,254) 0%, rgb(210,210,210) 7%, rgb(179,179,179) 12%, rgb(213,213,213) 100%); 25 | -body : linear-gradient(to bottom, rgb(0,0,0) 0%, rgb(50,50,50) 39%, rgb(51,51,51) 40%, rgb(153,153,153) 100%); 26 | -fx-background-color : -outer-border, -inner-border, -body; 27 | -fx-background-radius: 1024; 28 | } 29 | 30 | .enzo-frame { 31 | -outer-border : linear-gradient(to bottom, rgb(224,224,224) 0%, rgb(133,133,133) 26%, rgb(84,84,84) 100%); 32 | -highlight-border : linear-gradient(to bottom, rgb(255,255,255) 0%, rgb(146,146,147) 50%, rgb(135,136,138) 100%); 33 | -inner-border : linear-gradient(to bottom, rgb(71,72,72) 0%, rgb(110,106,107) 50%, rgb(186,185,187) 100%); 34 | -body : rgb(240,240,240); 35 | -fx-background-color : -outer-border, -highlight-border, -inner-border, -body; 36 | -fx-background-radius: 1024; 37 | -fx-effect : innershadow(two-pass-box, rgba(0, 0, 0, 0.3), 20, 0.0, 0, 20); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/resources/eu/hansolo/medusa/gauge.css: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2016-2021 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 | * GAUGE class * 20 | *****************************************************************************/ 21 | .gauge { 22 | 23 | } 24 | --------------------------------------------------------------------------------