From 15bb051b2e66118432058203026119f2e489acb9 Mon Sep 17 00:00:00 2001 From: Bruno Salmon Date: Wed, 2 Dec 2020 19:35:27 +0000 Subject: [PATCH] Extracted files from WebFx main repository --- .github/workflows/builds.yml | 439 ++ .gitignore | 80 + pom.xml | 22 + .../pom.xml | 69 + .../src/main/graalvm_conf/reflection.json | 20 + .../src/main/java/module-info.java | 13 + .../src/main/resources/META-INF/webfx.xml | 3 + .../pom.xml | 244 + .../src/main/module.gwt.xml | 239 + .../src/main/resources/META-INF/webfx.xml | 3 + .../src/main/resources/public/index.html | 10 + .../super/java/lang/reflect/Array.java | 17 + .../super/java/util/ServiceLoader.java | 51 + ...eate-distribution-SNAPSHOT-windows-x64.bat | 80 + .../pom.xml | 73 + .../src/main/java/module-info.java | 13 + .../src/main/resources/META-INF/webfx.xml | 3 + webfx-demo-moderngauge-application/pom.xml | 59 + .../main/java/eu/hansolo/medusa/Fonts.java | 143 + .../main/java/eu/hansolo/medusa/Gauge.java | 5930 +++++++++++++++++ .../java/eu/hansolo/medusa/GaugeBuilder.java | 1442 ++++ .../eu/hansolo/medusa/TickLabelLocation.java | 26 + .../hansolo/medusa/TickLabelOrientation.java | 26 + .../java/eu/hansolo/medusa/TickMarkType.java | 26 + .../eu/hansolo/medusa/events/TimeEvent.java | 38 + .../medusa/events/TimeEventListener.java | 28 + .../eu/hansolo/medusa/events/UpdateEvent.java | 33 + .../medusa/events/UpdateEventListener.java | 28 + .../hansolo/medusa/skins/GaugeSkinBase.java | 83 + .../eu/hansolo/medusa/skins/ModernSkin.java | 838 +++ .../java/eu/hansolo/medusa/tools/Helper.java | 1249 ++++ .../src/main/java/module-info.java | 23 + .../moderngauge/ModernGaugeApplication.java | 42 + .../services/javafx.application.Application | 1 + .../src/main/resources/META-INF/webfx.xml | 7 + 35 files changed, 11401 insertions(+) create mode 100644 .github/workflows/builds.yml create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 webfx-demo-moderngauge-application-gluon/pom.xml create mode 100644 webfx-demo-moderngauge-application-gluon/src/main/graalvm_conf/reflection.json create mode 100644 webfx-demo-moderngauge-application-gluon/src/main/java/module-info.java create mode 100644 webfx-demo-moderngauge-application-gluon/src/main/resources/META-INF/webfx.xml create mode 100644 webfx-demo-moderngauge-application-gwt/pom.xml create mode 100644 webfx-demo-moderngauge-application-gwt/src/main/module.gwt.xml create mode 100644 webfx-demo-moderngauge-application-gwt/src/main/resources/META-INF/webfx.xml create mode 100644 webfx-demo-moderngauge-application-gwt/src/main/resources/public/index.html create mode 100644 webfx-demo-moderngauge-application-gwt/src/main/resources/super/java/lang/reflect/Array.java create mode 100644 webfx-demo-moderngauge-application-gwt/src/main/resources/super/java/util/ServiceLoader.java create mode 100644 webfx-demo-moderngauge-application-javafx/create-distribution-SNAPSHOT-windows-x64.bat create mode 100644 webfx-demo-moderngauge-application-javafx/pom.xml create mode 100644 webfx-demo-moderngauge-application-javafx/src/main/java/module-info.java create mode 100644 webfx-demo-moderngauge-application-javafx/src/main/resources/META-INF/webfx.xml create mode 100644 webfx-demo-moderngauge-application/pom.xml create mode 100644 webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/Fonts.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/Gauge.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/GaugeBuilder.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/TickLabelLocation.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/TickLabelOrientation.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/TickMarkType.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/TimeEvent.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/TimeEventListener.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/UpdateEvent.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/UpdateEventListener.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/skins/GaugeSkinBase.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/skins/ModernSkin.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/tools/Helper.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/module-info.java create mode 100644 webfx-demo-moderngauge-application/src/main/java/webfx/demo/moderngauge/ModernGaugeApplication.java create mode 100644 webfx-demo-moderngauge-application/src/main/resources/META-INF/services/javafx.application.Application create mode 100644 webfx-demo-moderngauge-application/src/main/resources/META-INF/webfx.xml diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml new file mode 100644 index 0000000..2099760 --- /dev/null +++ b/.github/workflows/builds.yml @@ -0,0 +1,439 @@ +name: Multi-OS builds +######################################################################################################################## +# This Github workflow will generate the following builds on each push made on the main branch: # +######################################################################################################################## +# Builds generated on Ubuntu: # +# 1) App-Linux-x64.jar : Java archive (fat jar with JavaFx for Linux) # +# 2) App-Web.war : Web app (built with GWT) # +# 3) App-Linux-x64-executable : Linux desktop native app (built with Gluon) # +# 4) App-Android-aarch64.apk : Android native app (built with Gluon) # +# Builds generated on Windows: # +# 5) App-Windows-x64.jar : Java archive (fat jar with JavaFx for Windows) # +# 6) App-Windows-x64.msi : Windows installer (msi) # +# 7) App-Windows-x64.exe : Windows desktop native app (Gluon) # +# Builds generated on MacOS: # +# 8) App-macOS-x64.jar : Java archive (fat jar with JavaFx for MacOS) # +# 9) App-macOS-x64-executable : MacOS desktop native app (Gluon) # +# 10) App-iOS-arm64.ipa : iOS native app (Gluon) # +######################################################################################################################## + +on: + push: + branches: [ main ] + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + app: [{name: 'ModernGauge', module-token: 'moderngauge', bundle-id: 'org.webfx.demo.moderngauge'}] + os-config: [1, 2, 3] + include: + - os-config: 1 + os: ubuntu-latest + web-artifact-suffix: 'Web.war' # Must run on Linux because the Web branch push action runs only on Linux + fatjar-artifact-suffix: 'Linux-x64.jar' + gluon-desktop-arch-token: 'x86_64-linux' + gluon-desktop-artifact-suffix: 'Linux-x64-executable' + gluon-android-arch-token: 'aarch64-android' + gluon-android-artifact-suffix: 'Android-aarch64.apk' + - os-config: 2 + os: windows-latest + fatjar-artifact-suffix: 'Windows-x64.jar' + gluon-desktop-arch-token: 'x86_64-windows' + gluon-desktop-artifact-suffix: 'Windows-x64.exe' + msi-desktop-artifact-suffix: 'Windows-x64.msi' + - os-config: 3 + os: macos-latest + fatjar-artifact-suffix: 'MacOS-x64.jar' + gluon-desktop-arch-token: 'x86_64-darwin' + gluon-desktop-Artifact-suffix: 'MacOS-x64-executable' + # The iOS build needs the Apple certificate in secrets (steps will be skipped otherwise) + gluon-ios-arch-token: 'arm64-ios' + gluon-ios-artifact-suffix: 'iOS-arm64.ipa' + + env: + application-name: ${{ matrix.app.name }} + webfx-module: ./webfx + javafx-module: ./webfx-demo-${{ matrix.app.module-token }}-application-javafx + gwt-module: ./webfx-demo-${{ matrix.app.module-token }}-application-gwt + gwt-build: ./webfx-demo-${{ matrix.app.module-token }}-application-gwt/target/webfx-demo-${{ matrix.app.module-token }}-application-gwt-0.1.0-SNAPSHOT/webfx_demo_${{ matrix.app.module-token }}_application_gwt/ + gluon-module: ./webfx-demo-${{ matrix.app.module-token }}-application-gluon + web-push-repository-name: webfx-demo-${{ matrix.app.module-token }} # This same repository + web-push-repository-owner: ${{ github.repository_owner }} + web-push-branch: 'web-build' + web-push-username: ${{ github.actor }} + web-push-email: ${{ secrets.API_GITHUB_EMAIL }} + jdk-version: '15.0.1' + xcode-version: '11.7.0' + graalvm-version: '20.3.0.java11' + API_GITHUB_TOKEN: ${{ secrets.API_GITHUB_TOKEN }} + GLUON_LICENSE: ${{ secrets.GLUON_LICENSE }} + GLUON_IOS_CERTIFICATES_FILE_BASE64: ${{ secrets.GLUON_IOS_CERTIFICATES_FILE_BASE64 }} + GLUON_IOS_APPSTORE_KEY_ID: ${{ secrets.GLUON_IOS_APPSTORE_KEY_ID }} + + steps: + + ################################################################################################################## + # Preparation # + ################################################################################################################## + + # Configure Git for long filenames on Windows (otherwise the WebFx repository checkout will fail) + - if: runner.os == 'Windows' + name: Configure Git for long filenames (Windows only) + run: git config --global core.longpaths true + + # Checkout this repository (before WebFx repository because this checkout would erase the WebFx folder) + - name: Checkout this repository + uses: actions/checkout@v2 + + # Checkout WebFx repository (we need to build it as a prerequisite because there is no release yet) + - name: Checkout WebFx repository + uses: actions/checkout@v2 + with: + repository: 'webfx-project/webfx' + path: ${{ env.webfx-module }} + + # Set up the JDK (WebFx requires JDK13+ due to javac bugs in prior versions - otherwise JDK11+ should be enough in theory) + - name: Set up JDK ${{ env.jdk-version }} + uses: actions/setup-java@v1 + with: + java-version: ${{ env.jdk-version }} + + # The staging directory will be used to put all artifacts built in this job + - name: Make staging directory + run: mkdir staging + + + ################################################################################################################## + # Clearing SNAPSHOT release assets # + ################################################################################################################## + + # Doing it once (at the beginning of the first job). Assets will then be uploaded at the end of each job. + - if: matrix.os-config == 1 && env.API_GITHUB_TOKEN != '' + name: Delete old release assets + uses: mknejp/delete-release-assets@v1 + with: + tag: SNAPSHOT + assets: '*' + fail-if-no-assets: false + token: ${{ secrets.API_GITHUB_TOKEN }} + + + ################################################################################################################## + # Building WebFx + this repository (jars + javafx fat jar + Web build (GWT) if required) # + ################################################################################################################## + # 1) App-Linux-x64.jar : Java archive (fat jar with JavaFx for Linux) # + # 2) App-Web.war : Web app (built with GWT) # + # 5) App-Windows-x64.jar : Java archive (fat jar with JavaFx for Windows) # + # 8) App-macOS-x64.jar : Java archive (fat jar with JavaFx for MacOS) # + ################################################################################################################## + + # Building the latest WebFx version locally (since there is no public release yet) + - name: Build WebFx with JDK ${{ env.jdk-version }} (Java 11 target) + run: mvn -P '!gwt-compile' install + working-directory: ${{ env.webfx-module }} + + # Building this repository with JDK 13+ (Java 11 target) including a GWT compilation (if required) + - if: matrix.web-artifact-suffix != null + name: Build this repository (JavaFx fat jar + GWT build) + run: mvn -P 'gwt-compile,javafx-fatjar' install + + # Or building this repository with JDK 13+ (Java 11 target) excluding a GWT compilation + - if: matrix.web-artifact-suffix == null + name: Build this repository (JavaFx fat jar - no GWT build) + run: mvn -P '!gwt-compile,javafx-fatjar' install + + + ################################################################################################################## + # Uploading fat jar (with JavaFx) artifacts # + ################################################################################################################## + # 1) App-Linux-x64.jar : Java archive (fat jar with JavaFx for Linux) # + # 5) App-Windows-x64.jar : Java archive (fat jar with JavaFx for Windows) # + # 8) App-macOS-x64.jar : Java archive (fat jar with JavaFx for MacOS) # + ################################################################################################################## + + # Copying the fat jar into the staging directory (will also be used for the final upload in the SNAPSHOT release) + - if: matrix.fatjar-artifact-suffix != null + name: Copy fat jar with JavaFx to staging + run: cp ${{ env.javafx-module }}/target/*-fat.jar staging/${{ env.application-name }}-${{ matrix.fatjar-artifact-suffix }} + + # Uploading it in the assets of this workflow run + - if: matrix.fatjar-artifact-suffix != null + name: Upload this fat jar artifact as asset of this worflow run + uses: actions/upload-artifact@v2 + with: + name: ${{ env.application-name }}-${{ matrix.fatjar-artifact-suffix }} + path: staging/*${{ matrix.fatjar-artifact-suffix }} + + + ################################################################################################################## + # Uploading the Web artifact # + ################################################################################################################## + # 2) App-Web.war : Web app (built with GWT) # + ################################################################################################################## + + # Copying the Web archive into the staging directory (will also be used for the final upload in the SNAPSHOT release) + - if: matrix.web-artifact-suffix != null + name: Copy Web archive to staging + run: cp ${{ env.gwt-module }}/target/*.war staging/${{ env.application-name }}-${{ matrix.web-artifact-suffix }} + + # Uploading it in the assets of this workflow run + - if: matrix.web-artifact-suffix != null + name: Upload GWT build as an artifact of this workflow run + uses: actions/upload-artifact@v2 + with: + name: ${{ env.application-name }}-${{ matrix.web-artifact-suffix }} + path: staging/*${{ matrix.web-artifact-suffix }} + + + ################################################################################################################## + # Updating the Web build branch (will update the live demo) # + ################################################################################################################## + + - if: matrix.web-artifact-suffix != null && env.API_GITHUB_TOKEN != '' + name: Push GWT build to ${{ env.web-push-branch }} branch + uses: cpina/github-action-push-to-another-repository@master + env: + API_TOKEN_GITHUB: ${{ secrets.API_GITHUB_TOKEN }} + with: + source-directory: ${{ env.gwt-build }} + destination-repository-username: ${{ env.web-push-repository-owner }} + destination-repository-name: ${{ env.web-push-repository-name }} + target-branch: ${{ env.web-push-branch }} + destination-github-username: ${{ env.web-push-username }} + user-email: ${{ env.web-push-email }} + + + ################################################################################################################## + # Building the Windows installer (msi) # + ################################################################################################################## + # 6) App-Windows-x64.msi : Windows installer (msi) # + ################################################################################################################## + + # Delegating this task to a batch file (create-distribution-SNAPSHOT-windows-x64.bat) + - if: matrix.msi-desktop-artifact-suffix != null + name: Create Windows Installer (msi) + run: .\create-distribution-SNAPSHOT-windows-x64.bat ${{ env.application-name }} webfx-demo-${{ matrix.app.module-token }}-application-javafx-0.1.0-SNAPSHOT.jar + working-directory: ${{ env.javafx-module }} + + + ################################################################################################################## + # Uploading the Windows installer (msi) # + ################################################################################################################## + # 6) App-Windows-x64.msi : Windows installer (msi) # + ################################################################################################################## + + # Copying the msi file into the staging directory (will also be used for the final upload in the SNAPSHOT release) + - if: matrix.msi-desktop-artifact-suffix != null + name: Copy Windows installer to staging + run: cp ${{ env.javafx-module }}/*.msi staging/${{ env.application-name }}-${{ matrix.msi-desktop-artifact-suffix }} + + # Uploading it in the assets of this workflow run + - if: matrix.msi-desktop-artifact-suffix != null + name: Upload Windows installer + uses: actions/upload-artifact@v2 + with: + name: ${{ env.application-name }}-${{ matrix.msi-desktop-artifact-suffix }} + path: staging/*${{ matrix.msi-desktop-artifact-suffix }} + + + ################################################################################################################## + # Building the native desktop apps using Gluon/GraalVM # + ################################################################################################################## + # 3) App-Linux-x64-executable : Linux desktop native app (built with Gluon) # + # 7) App-Windows-x64.exe : Windows desktop native app (Gluon) # + # 9) App-macOS-x64-executable : MacOS desktop native app (Gluon) # + ################################################################################################################## + + # Windows prerequisite: msbuild + - if: runner.os == 'Windows' + name: Add msbuild to PATH (Windows only) + uses: microsoft/setup-msbuild@v1.0.2 + + # Windows prerequisite: Visual Studio shell + - if: runner.os == 'Windows' + name: Visual Studio shell (Windows only) + uses: egor-tensin/vs-shell@v1 + + # MacOS prerequisite: Xcode + - if: runner.os == 'macOS' + name: Set up Xcode ${{ env.xcode-version }} (MacOS only) + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: ${{ env.xcode-version }} + + # Setting up the GraalVM environment + - name: Set up GraalVM environment ${{ env.graalvm-version }} + uses: DeLaGuardo/setup-graalvm@master + with: + graalvm-version: ${{ env.graalvm-version }} + + # Gluon needs additional libraries on Linux + - if: runner.os == 'Linux' + name: Install libraries required for Gluon on Linux + run: sudo apt install libasound2-dev libavcodec-dev libavformat-dev libavutil-dev libgl-dev libgtk-3-dev libpango1.0-dev libxtst-dev + + # Passing the Gluon License (if set) + - if: env.GLUON_LICENSE != '' + name: Gluon License + uses: gluonhq/gluon-build-license@v1 + with: + gluon-license: ${{ secrets.GLUON_LICENSE }} + + # Invoking the Gluon Client Maven plugin to build the native Desktop app (chaining build & package goals) + - if: matrix.gluon-desktop-artifact-suffix != null + name: Gluon Build for Desktop + run: mvn -P 'gluon-desktop' client:build client:package # May take a while + env: + GRAALVM_HOME: ${{ env.JAVA_HOME }} + working-directory: ${{ env.gluon-module }} + + + ################################################################################################################## + # Uploading the native desktop apps # + ################################################################################################################## + # 3) App-Linux-x64-executable : Linux desktop native app (built with Gluon) # + # 7) App-Windows-x64.exe : Windows desktop native app (Gluon) # + # 9) App-macOS-x64-executable : MacOS desktop native app (Gluon) # + ################################################################################################################## + + # Copying the app into the staging directory (will also be used for the final upload in the SNAPSHOT release) + - if: matrix.gluon-desktop-artifact-suffix != null + name: Copy native Desktop to staging + run: cp ${{ env.gluon-module }}/target/client/${{ matrix.gluon-desktop-arch-token }}/webfx-demo-* staging/${{ env.application-name }}-${{ matrix.gluon-desktop-artifact-suffix }} + + # Uploading it in the assets of this workflow run + - if: matrix.gluon-desktop-artifact-suffix != null + name: Upload native Desktop as an artifact of this workflow run + uses: actions/upload-artifact@v2 + with: + name: ${{ env.application-name }}-${{ matrix.gluon-desktop-artifact-suffix }} + path: staging/*${{ matrix.gluon-desktop-artifact-suffix }} + + + ################################################################################################################## + # Building the native Android app using Gluon/GraalVM # + ################################################################################################################## + # 4) App-Android-aarch64.apk : Android native app (built with Gluon) # + ################################################################################################################## + + # All prerequisite have already be done when building the Desktop qpps + + # Invoking the Gluon Client Maven plugin to build the native Android app (chaining build & package goals) + - if: matrix.gluon-android-arch-token != null + name: Gluon Build for Android + run: mvn -P 'gluon-android' clean client:build client:package # May take a while + env: + GRAALVM_HOME: ${{ env.JAVA_HOME }} + working-directory: ${{ env.gluon-module }} + + + ################################################################################################################## + # Uploading the native Android app # + ################################################################################################################## + # 4) App-Android-aarch64.apk : Android native app (built with Gluon) # + ################################################################################################################## + + # Copying the app into the staging directory (will also be used for the final upload in the SNAPSHOT release) + - if: matrix.gluon-android-arch-token != null + name: Copy Android native application to staging + run: cp ${{ env.gluon-module }}/target/client/${{ matrix.gluon-android-arch-token }}/gvm/*.apk staging/${{ env.application-name }}-${{ matrix.gluon-android-artifact-suffix }} + + # Uploading it in the assets of this workflow run + - if: matrix.gluon-android-arch-token != null + name: Upload Android native application as an artifact of this workflow run + uses: actions/upload-artifact@v2 + with: + name: ${{ env.application-name }}-${{ matrix.gluon-android-artifact-suffix }} + path: staging/*${{ matrix.gluon-android-artifact-suffix }} + + + ################################################################################################################## + # Building the native iOS app using Gluon/GraalVM # + ################################################################################################################## + # 10) App-iOS-arm64.ipa : iOS native app (Gluon) # + ################################################################################################################## + + # Importing the Apple codesign certificates + - if: env.GLUON_IOS_CERTIFICATES_FILE_BASE64 != '' + uses: Apple-Actions/import-codesign-certs@v1 + with: + p12-file-base64: ${{ secrets.GLUON_IOS_CERTIFICATES_FILE_BASE64 }} + p12-password: ${{ secrets.GLUON_IOS_CERTIFICATES_PASSWORD }} + + # Importing the Apple codesign certificates + - if: env.GLUON_IOS_APPSTORE_KEY_ID != '' + uses: Apple-Actions/download-provisioning-profiles@v1 + with: + bundle-id: ${{ matrix.app.bundle-id }} + issuer-id: ${{ secrets.GLUON_IOS_APPSTORE_ISSUER_ID }} + api-key-id: ${{ secrets.GLUON_IOS_APPSTORE_KEY_ID }} + api-private-key: ${{ secrets.GLUON_IOS_APPSTORE_PRIVATE_KEY }} + + # Invoking the Gluon Client Maven plugin to build the native iOS app (chaining build & package goals) + - if: matrix.gluon-ios-arch-token != null && env.GLUON_IOS_CERTIFICATES_FILE_BASE64 != '' + name: Gluon Build for iOS + run: mvn -P 'gluon-ios' clean client:build client:package # May take a while + env: + GRAALVM_HOME: ${{ env.JAVA_HOME }} + working-directory: ${{ env.gluon-module }} + + + ################################################################################################################## + # Uploading the native iOS app # + ################################################################################################################## + # 10) App-iOS-arm64.ipa : iOS native app (Gluon) # + ################################################################################################################## + + # Copying the app into the staging directory (will also be used for the final upload in the SNAPSHOT release) + - if: matrix.gluon-ios-arch-token != null && env.GLUON_IOS_CERTIFICATES_FILE_BASE64 != '' + name: Copy iOS native application to staging + run: cp ${{ env.gluon-module }}/target/client/${{ matrix.gluon-ios-arch-token }}/gvm/*.ipa staging/${{ env.application-name }}-${{ matrix.gluon-ios-artifact-suffix }} + + # Uploading it in the assets of this workflow run + - if: matrix.gluon-ios-arch-token != null && env.GLUON_IOS_CERTIFICATES_FILE_BASE64 != '' + name: Upload iOS native application as an artifact of this workflow run + uses: actions/upload-artifact@v2 + with: + name: ${{ env.application-name }}-${{ matrix.gluon-ios-artifact-suffix }} + path: staging/*${{ matrix.gluon-ios-artifact-suffix }} + + + ################################################################################################################## + # Publishing the native iOS app in the Apple Store # + ################################################################################################################## + # 10) App-iOS-arm64.ipa : iOS native app (Gluon) # + ################################################################################################################## + + - if: env.GLUON_IOS_APPSTORE_KEY_ID != '' + uses: Apple-Actions/upload-testflight-build@master + with: + app-path: staging/${{ env.application-name }}-${{ matrix.gluon-ios-artifact-suffix }} + issuer-id: ${{ secrets.GLUON_IOS_APPSTORE_ISSUER_ID }} + api-key-id: ${{ secrets.GLUON_IOS_APPSTORE_KEY_ID }} + api-private-key: ${{ secrets.GLUON_IOS_APPSTORE_PRIVATE_KEY }} + + + ################################################################################################################## + # Uploading all generated artifacts from staging into the SNAPSHOT release assets # + ################################################################################################################## + # 1) App-Linux-x64.jar : Java archive (fat jar with JavaFx for Linux) # + # 2) App-Web.war : Web app (built with GWT) # + # 3) App-Linux-x64-executable : Linux desktop native app (built with Gluon) # + # 4) App-Android-aarch64.apk : Android native app (built with Gluon) # + # 5) App-Windows-x64.jar : Java archive (fat jar with JavaFx for Windows) # + # 6) App-Windows-x64.msi : Windows installer (msi) # + # 7) App-Windows-x64.exe : Windows desktop native app (Gluon) # + # 8) App-macOS-x64.jar : Java archive (fat jar with JavaFx for MacOS) # + # 9) App-macOS-x64-executable : MacOS desktop native app (Gluon) # + # 10) App-iOS-arm64.ipa : iOS native app (Gluon) # + ################################################################################################################## + + - if: env.API_GITHUB_TOKEN != '' + name: Upload artifacts to the SNAPSHOT release assets + uses: AButler/upload-release-assets@v2.0 + with: + release-tag: SNAPSHOT + files: staging/* + repo-token: ${{ secrets.API_GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fdd88ae --- /dev/null +++ b/.gitignore @@ -0,0 +1,80 @@ +### Maven +target/ + +### Java +*.class + +### JetBrains IntelliJ IDEA + +/out/ + +# User-specific stuff: +.idea/ + +.idea/libraries/ + +## File-based project format: +*.ipr +*.iws +*.iml + +### Eclipse template + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +.classpath +.project diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..36462cc --- /dev/null +++ b/pom.xml @@ -0,0 +1,22 @@ + + + + webfx-demos + org.webfx + 0.1.0-SNAPSHOT + + 4.0.0 + + webfx-demo-moderngauge + pom + + + webfx-demo-moderngauge-application + webfx-demo-moderngauge-application-javafx + webfx-demo-moderngauge-application-gwt + webfx-demo-moderngauge-application-gluon + + + \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-gluon/pom.xml b/webfx-demo-moderngauge-application-gluon/pom.xml new file mode 100644 index 0000000..8c372ba --- /dev/null +++ b/webfx-demo-moderngauge-application-gluon/pom.xml @@ -0,0 +1,69 @@ + + + webfx-demo-moderngauge + org.webfx + 0.1.0-SNAPSHOT + + 4.0.0 + + webfx-demo-moderngauge-application-gluon + + + + + webfx-demo-moderngauge-application + ${webfx.groupId} + ${webfx.version} + + + + webfx-kit-javafx + ${webfx.groupId} + ${webfx.version} + + + + webfx-platform-java-appcontainer-impl + ${webfx.groupId} + ${webfx.version} + + + + webfx-platform-java-scheduler-impl + ${webfx.groupId} + ${webfx.version} + + + + webfx-platform-java-shutdown-impl + ${webfx.groupId} + ${webfx.version} + + + + webfx-platform-shared-log-impl-simple + ${webfx.groupId} + ${webfx.version} + + + + + + + + + com.gluonhq + client-maven-plugin + + + + + + + + gluon-desktop + gluon-android + gluon-ios + + + \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-gluon/src/main/graalvm_conf/reflection.json b/webfx-demo-moderngauge-application-gluon/src/main/graalvm_conf/reflection.json new file mode 100644 index 0000000..4c406ec --- /dev/null +++ b/webfx-demo-moderngauge-application-gluon/src/main/graalvm_conf/reflection.json @@ -0,0 +1,20 @@ +[ + { + "name" : "webfx.kit.launcher.spi.javafx.JavaFxWebFxKitLauncherProvider$FxKitWrapperApplication", + "methods" : [ + { "name" : "", "parameterTypes" : [] } + ] + }, + { + "name" : "webfx.kit.mapper.peers.javafxcontrols.javafx.skin.FxControlPeerSkin", + "methods" : [ + { "name" : "", "parameterTypes" : ["javafx.scene.control.Control"] } + ] + }, + { + "name" : "javafx.scene.control.TableColumnBase", + "methods" : [ + { "name" : "", "parameterTypes" : [] } + ] + } +] \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-gluon/src/main/java/module-info.java b/webfx-demo-moderngauge-application-gluon/src/main/java/module-info.java new file mode 100644 index 0000000..d9907cb --- /dev/null +++ b/webfx-demo-moderngauge-application-gluon/src/main/java/module-info.java @@ -0,0 +1,13 @@ +// Generated by WebFx + +module webfx.demo.moderngauge.application.gluon { + + // Direct dependencies modules + requires webfx.demo.moderngauge.application; + requires webfx.kit.javafx; + requires webfx.platform.java.appcontainer.impl; + requires webfx.platform.java.scheduler.impl; + requires webfx.platform.java.shutdown.impl; + requires webfx.platform.shared.log.impl.simple; + +} \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-gluon/src/main/resources/META-INF/webfx.xml b/webfx-demo-moderngauge-application-gluon/src/main/resources/META-INF/webfx.xml new file mode 100644 index 0000000..0f62346 --- /dev/null +++ b/webfx-demo-moderngauge-application-gluon/src/main/resources/META-INF/webfx.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-gwt/pom.xml b/webfx-demo-moderngauge-application-gwt/pom.xml new file mode 100644 index 0000000..898d8f3 --- /dev/null +++ b/webfx-demo-moderngauge-application-gwt/pom.xml @@ -0,0 +1,244 @@ + + + webfx-demo-moderngauge + org.webfx + 0.1.0-SNAPSHOT + + 4.0.0 + + webfx-demo-moderngauge-application-gwt + gwt-app + + + + + webfx-kit-javafxbase-emul + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-kit-javafxcontrols-emul + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-kit-javafxgraphics-emul + ${webfx.groupId} + ${webfx.version} + sources + + + + elemental2-svg + ${lib.elemental2.groupId} + + + + org.jresearch.gwt.time + org.jresearch.gwt.time + 2.0.1 + + + + gwt-dev + com.google.gwt + + + + webfx-demo-moderngauge-application + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-kit-gwt + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-kit-javafxcontrols-peers-base + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-kit-javafxcontrols-peers-gwt + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-kit-javafxcontrols-registry-gwt + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-kit-javafxgraphics-peers + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-kit-javafxgraphics-peers-base + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-kit-javafxgraphics-peers-gwt + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-kit-javafxgraphics-registry-gwt + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-kit-launcher + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-kit-util + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-platform-client-uischeduler + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-platform-gwt-appcontainer-impl + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-platform-gwt-emul-javabase + ${webfx.groupId} + ${webfx.version} + shaded-sources + + + + webfx-platform-gwt-log-impl + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-platform-gwt-resource-impl + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-platform-gwt-shutdown-impl + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-platform-gwt-uischeduler-impl + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-platform-shared-appcontainer + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-platform-shared-log + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-platform-shared-resource + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-platform-shared-scheduler + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-platform-shared-shutdown + ${webfx.groupId} + ${webfx.version} + sources + + + + webfx-platform-shared-util + ${webfx.groupId} + ${webfx.version} + sources + + + + + + + + + + maven-source-plugin + + + + + net.ltgt.gwt.maven + gwt-maven-plugin + + + + + + + + + gwt-compile + + + \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-gwt/src/main/module.gwt.xml b/webfx-demo-moderngauge-application-gwt/src/main/module.gwt.xml new file mode 100644 index 0000000..b844ea8 --- /dev/null +++ b/webfx-demo-moderngauge-application-gwt/src/main/module.gwt.xml @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-gwt/src/main/resources/META-INF/webfx.xml b/webfx-demo-moderngauge-application-gwt/src/main/resources/META-INF/webfx.xml new file mode 100644 index 0000000..0f62346 --- /dev/null +++ b/webfx-demo-moderngauge-application-gwt/src/main/resources/META-INF/webfx.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-gwt/src/main/resources/public/index.html b/webfx-demo-moderngauge-application-gwt/src/main/resources/public/index.html new file mode 100644 index 0000000..9e1c7d0 --- /dev/null +++ b/webfx-demo-moderngauge-application-gwt/src/main/resources/public/index.html @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-gwt/src/main/resources/super/java/lang/reflect/Array.java b/webfx-demo-moderngauge-application-gwt/src/main/resources/super/java/lang/reflect/Array.java new file mode 100644 index 0000000..a31de33 --- /dev/null +++ b/webfx-demo-moderngauge-application-gwt/src/main/resources/super/java/lang/reflect/Array.java @@ -0,0 +1,17 @@ +// Generated by WebFx +package java.lang.reflect; + +import webfx.platform.shared.services.log.Logger; + +public final class Array { + + public static Object newInstance(Class componentType, int length) throws NegativeArraySizeException { + switch (componentType.getName()) { + // TYPE NOT FOUND + default: + Logger.log("GWT super source Array.newInstance() has no case for type " + componentType + ", so new Object[] is returned but this may cause a ClassCastException."); + return new Object[length]; + } + } + +} \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-gwt/src/main/resources/super/java/util/ServiceLoader.java b/webfx-demo-moderngauge-application-gwt/src/main/resources/super/java/util/ServiceLoader.java new file mode 100644 index 0000000..b11475f --- /dev/null +++ b/webfx-demo-moderngauge-application-gwt/src/main/resources/super/java/util/ServiceLoader.java @@ -0,0 +1,51 @@ +// Generated by WebFx +package java.util; + +import java.util.Iterator; +import java.util.logging.Logger; +import webfx.platform.shared.util.function.Factory; + +public class ServiceLoader implements Iterable { + + public static ServiceLoader load(Class serviceClass) { + switch (serviceClass.getName()) { + case "javafx.application.Application": return new ServiceLoader(webfx.demo.moderngauge.ModernGaugeApplication::new); + case "webfx.kit.launcher.spi.WebFxKitLauncherProvider": return new ServiceLoader(webfx.kit.launcher.spi.gwt.GwtWebFxKitLauncherProvider::new); + case "webfx.kit.mapper.spi.WebFxKitMapperProvider": return new ServiceLoader(webfx.kit.mapper.spi.gwt.GwtWebFxKitHtmlMapperProvider::new); + case "webfx.platform.client.services.uischeduler.spi.UiSchedulerProvider": return new ServiceLoader(webfx.platform.gwt.services.uischeduler.spi.impl.GwtUiSchedulerProvider::new); + case "webfx.platform.gwt.services.resource.spi.impl.GwtResourceBundle": return new ServiceLoader(); + case "webfx.platform.shared.services.appcontainer.spi.ApplicationContainerProvider": return new ServiceLoader(webfx.platform.gwt.services.appcontainer.spi.impl.GwtApplicationContainerProvider::new); + case "webfx.platform.shared.services.appcontainer.spi.ApplicationJob": return new ServiceLoader(); + case "webfx.platform.shared.services.appcontainer.spi.ApplicationModuleInitializer": return new ServiceLoader(webfx.kit.launcher.WebFxKitLauncherModuleInitializer::new, webfx.platform.shared.services.appcontainer.spi.impl.ApplicationJobsStarter::new, webfx.platform.gwt.services.resource.spi.impl.GwtResourceModuleInitializer::new); + case "webfx.platform.shared.services.log.spi.LoggerProvider": return new ServiceLoader(webfx.platform.gwt.services.log.spi.impl.GwtLoggerProvider::new); + case "webfx.platform.shared.services.resource.spi.ResourceServiceProvider": return new ServiceLoader(webfx.platform.gwt.services.resource.spi.impl.GwtResourceServiceProvider::new); + case "webfx.platform.shared.services.scheduler.spi.SchedulerProvider": return new ServiceLoader(webfx.platform.gwt.services.uischeduler.spi.impl.GwtUiSchedulerProvider::new); + case "webfx.platform.shared.services.shutdown.spi.ShutdownProvider": return new ServiceLoader(webfx.platform.gwt.services.shutdown.spi.impl.GwtShutdownProvider::new); + // UNKNOWN SPI + default: + Logger.getLogger(ServiceLoader.class.getName()).warning("Unknown " + serviceClass + " SPI - returning no provider"); + return new ServiceLoader(); + } + } + + private final Factory[] factories; + + public ServiceLoader(Factory... factories) { + this.factories = factories; + } + + public Iterator iterator() { + return new Iterator() { + int index = 0; + @Override + public boolean hasNext() { + return index < factories.length; + } + + @Override + public S next() { + return (S) factories[index++].create(); + } + }; + } +} \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-javafx/create-distribution-SNAPSHOT-windows-x64.bat b/webfx-demo-moderngauge-application-javafx/create-distribution-SNAPSHOT-windows-x64.bat new file mode 100644 index 0000000..1058330 --- /dev/null +++ b/webfx-demo-moderngauge-application-javafx/create-distribution-SNAPSHOT-windows-x64.bat @@ -0,0 +1,80 @@ +@echo off +REM VRL distribution script (creates app bundles and installers). +REM (c) 2020 by Michael Hoffer +REM This script can easily be adapted for other applications as well. + +REM App distribution configuration: +REM - specify app name, jar file and desired app type (msi, app-bundle, etc.) +REM - since jpackage is still in preview, we download a recent JDK installation that +REM is used locally to build the application package +SET APP_NAME=%1 +SET APP_JAR=%2 +SET APP_TYPE="msi" +SET JPACKAGE_JVM="https://download.java.net/java/GA/jdk14/076bab302c7b4508975440c56f6cc26a/36/GPL/openjdk-14_windows-x64_bin.zip" +REM App version is passed as argument by github action workflow +rem SET APP_VERSION=%3 + +REM Please don't change the rest of the script. If something doesn't work +REM then create an issue where we can discuss potential changes. +set DIR="%~dp0" +echo Building distribution in dir: %DIR% +cd %DIR% + +REM Check for 7zip and curl which are used to download and unpack the local Java distribution. +for %%X in (7z.exe) do (set FOUND7Z=%%~$PATH:X) +for %%X in (curl.exe) do (set FOUNDCURL=%%~$PATH:X) +if not defined FOUND7Z ( + echo "ERROR: please make sure that 7Zip is installed and on the path." +) +if not defined FOUNDCURL ( + echo "ERROR: please make sure that Curl is installed and on the path." +) + +REM Do not create the local JDK if it already exists +if exist ".tmp-runtime\jdk-14\" ( + echo "> jdk 14 for package generation already downloaded" +) else ( +REM If it doesn't exist, however, download and unpack the local JDK +REM and create runtime image with the runtime JDK +REM (JAVA_HOME is expected to be set correctly) + mkdir .tmp-runtime\ + cd .tmp-runtime + echo "> downloading jdk 14" + curl -o jdk14.zip %JPACKAGE_JVM% + echo "> unpacking jdk 14" + 7z x jdk14.zip + echo "> creating runtime image" + "%JAVA_HOME%\bin\jlink" -p "%JAVA_HOME%\jmods" ^ + --add-modules java.desktop ^ + --strip-debug ^ + --no-header-files ^ + --no-man-pages ^ + --strip-native-commands ^ + --vm=server ^ + --compress=2 ^ + --output runtime +) + +REM Change to distribution directory (script location) where +REM we will create the final application package +cd %DIR% + +REM Finally, invoke the jpackage CLI program from the local JDK that +REM has been downloaded earlier. +set JPKG_HOME=.tmp-runtime\jdk-14\ +set JPKG_EXECUTABLE=%JPKG_HOME%\bin\jpackage +%JPKG_EXECUTABLE% --input .\target\ ^ + --name %APP_NAME% ^ + --main-jar %APP_JAR% ^ + --type %APP_TYPE% ^ + --runtime-image .tmp-runtime\runtime ^ + --app-version 0.0.0 ^ + --win-per-user-install ^ + --win-menu ^ + --win-menu-group WebFx + +REM Rename the application MSI +rem move %APP_NAME%-0.0.0.msi %APP_NAME%-%APP_VERSION%-windows-x64.msi + +REM Show final MSI package +dir *.msi \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-javafx/pom.xml b/webfx-demo-moderngauge-application-javafx/pom.xml new file mode 100644 index 0000000..6da7127 --- /dev/null +++ b/webfx-demo-moderngauge-application-javafx/pom.xml @@ -0,0 +1,73 @@ + + + webfx-demo-moderngauge + org.webfx + 0.1.0-SNAPSHOT + + 4.0.0 + + webfx-demo-moderngauge-application-javafx + + + + + webfx-demo-moderngauge-application + ${webfx.groupId} + ${webfx.version} + + + + webfx-kit-javafx + ${webfx.groupId} + ${webfx.version} + + + + webfx-platform-java-appcontainer-impl + ${webfx.groupId} + ${webfx.version} + + + + webfx-platform-java-scheduler-impl + ${webfx.groupId} + ${webfx.version} + + + + webfx-platform-java-shutdown-impl + ${webfx.groupId} + ${webfx.version} + + + + webfx-platform-shared-log-impl-simple + ${webfx.groupId} + ${webfx.version} + + + + + + + + javafx-fatjar + + false + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + + + + + + \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-javafx/src/main/java/module-info.java b/webfx-demo-moderngauge-application-javafx/src/main/java/module-info.java new file mode 100644 index 0000000..7824e5e --- /dev/null +++ b/webfx-demo-moderngauge-application-javafx/src/main/java/module-info.java @@ -0,0 +1,13 @@ +// Generated by WebFx + +module webfx.demo.moderngauge.application.javafx { + + // Direct dependencies modules + requires webfx.demo.moderngauge.application; + requires webfx.kit.javafx; + requires webfx.platform.java.appcontainer.impl; + requires webfx.platform.java.scheduler.impl; + requires webfx.platform.java.shutdown.impl; + requires webfx.platform.shared.log.impl.simple; + +} \ No newline at end of file diff --git a/webfx-demo-moderngauge-application-javafx/src/main/resources/META-INF/webfx.xml b/webfx-demo-moderngauge-application-javafx/src/main/resources/META-INF/webfx.xml new file mode 100644 index 0000000..0f62346 --- /dev/null +++ b/webfx-demo-moderngauge-application-javafx/src/main/resources/META-INF/webfx.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/webfx-demo-moderngauge-application/pom.xml b/webfx-demo-moderngauge-application/pom.xml new file mode 100644 index 0000000..b28b4bb --- /dev/null +++ b/webfx-demo-moderngauge-application/pom.xml @@ -0,0 +1,59 @@ + + + webfx-demo-moderngauge + org.webfx + 0.1.0-SNAPSHOT + + 4.0.0 + + webfx-demo-moderngauge-application + + + + + javafx-base + org.openjfx + ${lib.openjfx.version} + provided + + + + javafx-controls + org.openjfx + ${lib.openjfx.version} + provided + + + + javafx-graphics + org.openjfx + ${lib.openjfx.version} + provided + + + + webfx-platform-shared-scheduler + ${webfx.groupId} + ${webfx.version} + + + + webfx-platform-shared-util + ${webfx.groupId} + ${webfx.version} + + + + + + + + + + maven-source-plugin + + + + + + \ No newline at end of file diff --git a/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/Fonts.java b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/Fonts.java new file mode 100644 index 0000000..60c73a5 --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/Fonts.java @@ -0,0 +1,143 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2016-2020 Gerrit Grunwald. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.hansolo.medusa; + +import javafx.scene.text.Font; + + +/** + * Created by hansolo on 11.12.15. + */ +public class Fonts { + private static final String DIGITAL_NAME; + private static final String DIGITAL_READOUT_NAME; + private static final String DIGITAL_READOUT_BOLD_NAME; + private static final String ELEKTRA_NAME; + private static final String ROBOTO_THIN_NAME; + private static final String ROBOTO_LIGHT_NAME; + private static final String ROBOTO_REGULAR_NAME; + private static final String ROBOTO_MEDIUM_NAME; + private static final String ROBOTO_BOLD_NAME; + private static final String ROBOTO_LIGHT_CONDENSED_NAME; + private static final String ROBOTO_REGULAR_CONDENSED_NAME; + private static final String ROBOTO_BOLD_CONDENSED_NAME; + private static final String LATO_LIGHT_NAME; + private static final String LATO_REGULAR_NAME; + private static final String LATO_BOLD_NAME; + private static final String ESTRICTA_REGULAR_NAME; + private static final String ESTRICTA_REGULAR_ITALIC_NAME; + private static final String ESTRICTA_MEDIUM_NAME; + private static final String ESTRICTA_MEDIUM_ITALIC_NAME; + + private static String digitalName; + private static String digitalReadoutName; + private static String digitalReadoutBoldName; + private static String elektraName; + + private static String robotoThinName; + private static String robotoLightName; + private static String robotoRegularName; + private static String robotoMediumName; + private static String robotoBoldName; + + private static String robotoLightCondensedName; + private static String robotoRegularCondensedName; + private static String robotoBoldCondensedName; + + private static String latoLightName; + private static String latoRegularName; + private static String latoBoldName; + + private static String estrictaRegularName; + private static String estrictaRegularItalicName; + private static String estrictaMediumName; + private static String estrictaMediumItalicName; + + + static { + try { + digitalName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/digital.ttf"), 10).getName(); + digitalReadoutName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/digitalreadout.ttf"), 10).getName(); + digitalReadoutBoldName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/digitalreadoutb.ttf"), 10).getName(); + elektraName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/elektra.ttf"), 10).getName(); + robotoThinName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Roboto-Thin.ttf"), 10).getName(); + robotoLightName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Roboto-Light.ttf"), 10).getName(); + robotoRegularName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Roboto-Regular.ttf"), 10).getName(); + robotoMediumName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Roboto-Medium.ttf"), 10).getName(); + robotoBoldName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Roboto-Bold.ttf"), 10).getName(); + robotoLightCondensedName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/RobotoCondensed-Light.ttf"), 10).getName(); + robotoRegularCondensedName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/RobotoCondensed-Regular.ttf"), 10).getName(); + robotoBoldCondensedName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/RobotoCondensed-Bold.ttf"), 10).getName(); + latoLightName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Lato-Lig.otf"), 10).getName(); + latoRegularName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Lato-Reg.otf"), 10).getName(); + latoBoldName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Lato-Bol.otf"), 10).getName(); + estrictaRegularName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Estricta-Regular.otf"), 10).getName(); + estrictaRegularItalicName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Estricta-RegularItalic.otf"), 10).getName(); + estrictaMediumName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Estricta-Medium.otf"), 10).getName(); + estrictaMediumItalicName = "Arial"; //Font.loadFont(Fonts.class.getResourceAsStream("/eu/hansolo/medusa/Estricta-MediumItalic.otf"), 10).getName(); + } catch (Exception exception) { } + DIGITAL_NAME = digitalName; + DIGITAL_READOUT_NAME = digitalReadoutName; + DIGITAL_READOUT_BOLD_NAME = digitalReadoutBoldName; + ELEKTRA_NAME = elektraName; + ROBOTO_THIN_NAME = robotoThinName; + ROBOTO_LIGHT_NAME = robotoLightName; + ROBOTO_REGULAR_NAME = robotoRegularName; + ROBOTO_MEDIUM_NAME = robotoMediumName; + ROBOTO_BOLD_NAME = robotoBoldName; + ROBOTO_LIGHT_CONDENSED_NAME = robotoLightCondensedName; + ROBOTO_REGULAR_CONDENSED_NAME = robotoRegularCondensedName; + ROBOTO_BOLD_CONDENSED_NAME = robotoBoldCondensedName; + LATO_LIGHT_NAME = latoLightName; + LATO_REGULAR_NAME = latoRegularName; + LATO_BOLD_NAME = latoBoldName; + ESTRICTA_REGULAR_NAME = estrictaRegularName; + ESTRICTA_REGULAR_ITALIC_NAME = estrictaRegularItalicName; + ESTRICTA_MEDIUM_NAME = estrictaMediumName; + ESTRICTA_MEDIUM_ITALIC_NAME = estrictaMediumItalicName; + } + + + // ******************** Methods ******************************************* + public static Font digital(final double SIZE) { return new Font(DIGITAL_NAME, SIZE); } + + public static Font digitalReadout(final double SIZE) { return new Font(DIGITAL_READOUT_NAME, SIZE); } + public static Font digitalReadoutBold(final double SIZE) { return new Font(DIGITAL_READOUT_BOLD_NAME, SIZE); } + + public static Font elektra(final double SIZE) { return new Font(ELEKTRA_NAME, SIZE); } + + public static Font robotoThin(final double SIZE) { return new Font(ROBOTO_THIN_NAME, SIZE); } + public static Font robotoLight(final double SIZE) { return new Font(ROBOTO_LIGHT_NAME, SIZE); } + public static Font robotoRegular(final double SIZE) { return new Font(ROBOTO_REGULAR_NAME, SIZE); } + public static Font robotoMedium(final double SIZE) { return new Font(ROBOTO_MEDIUM_NAME, SIZE); } + public static Font robotoBold(final double SIZE) { return new Font(ROBOTO_BOLD_NAME, SIZE); } + + public static Font robotoCondensedLight(final double SIZE) { return new Font(ROBOTO_LIGHT_CONDENSED_NAME, SIZE); } + public static Font robotoCondensedRegular(final double SIZE) { return new Font(ROBOTO_REGULAR_CONDENSED_NAME, SIZE); } + public static Font robotoCondensedBold(final double SIZE) { return new Font(ROBOTO_BOLD_CONDENSED_NAME, SIZE); } + + public static Font latoLight(final double SIZE) { return new Font(LATO_LIGHT_NAME, SIZE); } + public static Font latoRegular(final double SIZE) { return new Font(LATO_REGULAR_NAME, SIZE); } + public static Font latoBold(final double SIZE) { return new Font(LATO_BOLD_NAME, SIZE); } + + public static Font estrictaRegular(final double SIZE) { return new Font(ESTRICTA_REGULAR_NAME, SIZE); } + public static Font estrictaRegularItalic(final double SIZE) { return new Font(ESTRICTA_REGULAR_ITALIC_NAME, SIZE); } + public static Font estrictaMedium(final double SIZE) { return new Font(ESTRICTA_MEDIUM_NAME, SIZE); } + public static Font estrictaMediumItalic(final double SIZE) { return new Font(ESTRICTA_MEDIUM_ITALIC_NAME, SIZE); } +} diff --git a/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/Gauge.java b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/Gauge.java new file mode 100644 index 0000000..26783d0 --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/Gauge.java @@ -0,0 +1,5930 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2016-2020 Gerrit Grunwald. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.hansolo.medusa; + +import eu.hansolo.medusa.events.UpdateEvent; +import eu.hansolo.medusa.events.UpdateEventListener; +import eu.hansolo.medusa.skins.ModernSkin; +import eu.hansolo.medusa.tools.Helper; +import javafx.animation.Animation.Status; +import javafx.animation.Interpolator; +import javafx.animation.KeyFrame; +import javafx.animation.KeyValue; +import javafx.animation.Timeline; +import javafx.beans.NamedArg; +import javafx.beans.binding.Bindings; +import javafx.beans.binding.BooleanBinding; +import javafx.beans.property.*; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.Event; +import javafx.event.EventHandler; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.geometry.Orientation; +import javafx.geometry.Pos; +import javafx.scene.control.Control; +import javafx.scene.control.Skin; +import javafx.scene.paint.Color; +import javafx.scene.paint.Paint; +import javafx.scene.text.Font; +import javafx.util.Duration; +import webfx.platform.shared.util.uuid.Uuid; + +import java.time.Instant; +import java.util.*; + + +/** + * Created by hansolo on 11.12.15. + */ +public class Gauge extends Control { + public enum NeedleType { BIG, FAT, STANDARD, SCIENTIFIC, AVIONIC, VARIOMETER } + + public enum NeedleShape { ANGLED, ROUND, FLAT } + + public enum NeedleSize { + THIN(0.015), + STANDARD(0.025), + THICK(0.05); + + public final double FACTOR; + + NeedleSize(final double FACTOR) { + this.FACTOR = FACTOR; + } + } + + public enum NeedleBehavior { STANDARD, OPTIMIZED } + + public enum KnobType { STANDARD, PLAIN, METAL, FLAT } + + public enum LedType { STANDARD, FLAT } + + public enum ScaleDirection { CLOCKWISE, COUNTER_CLOCKWISE, LEFT_TO_RIGHT, RIGHT_TO_LEFT, BOTTOM_TO_TOP, TOP_TO_BOTTOM } + + public enum SkinType { + AMP, PLAIN_AMP, BULLET_CHART, DASHBOARD, FLAT, GAUGE, INDICATOR, KPI, + MODERN, SIMPLE, SLIM, SPACE_X, QUARTER, HORIZONTAL, VERTICAL, + LCD, TINY, BATTERY, LEVEL, LINEAR, DIGITAL, SIMPLE_DIGITAL, SECTION, + BAR, WHITE, CHARGE, SIMPLE_SECTION, TILE_KPI, TILE_TEXT_KPI, TILE_SPARK_LINE, + NASA + } + + public static final Color DARK_COLOR = Color.rgb(36, 36, 36); // #242424 + public static final Color BRIGHT_COLOR = Color.rgb(223, 223, 223); // #dfdfdf + private static final long LED_BLINK_INTERVAL = 500l; + private static final int MAX_NO_OF_DECIMALS = 3; + + public final ButtonEvent BTN_PRESSED_EVENT = new ButtonEvent(ButtonEvent.BTN_PRESSED); + public final ButtonEvent BTN_RELEASED_EVENT = new ButtonEvent(ButtonEvent.BTN_RELEASED); + private final ThresholdEvent EXCEEDED_EVENT = new ThresholdEvent(ThresholdEvent.THRESHOLD_EXCEEDED); + private final ThresholdEvent UNDERRUN_EVENT = new ThresholdEvent(ThresholdEvent.THRESHOLD_UNDERRUN); + private final UpdateEvent RECALC_EVENT = new UpdateEvent(Gauge.this, UpdateEvent.EventType.RECALC); + private final UpdateEvent REDRAW_EVENT = new UpdateEvent(Gauge.this, UpdateEvent.EventType.REDRAW); + private final UpdateEvent RESIZE_EVENT = new UpdateEvent(Gauge.this, UpdateEvent.EventType.RESIZE); + private final UpdateEvent LED_EVENT = new UpdateEvent(Gauge.this, UpdateEvent.EventType.LED); + //private final UpdateEvent LCD_EVENT = new UpdateEvent(Gauge.this, UpdateEvent.EventType.LCD); + private final UpdateEvent VISIBILITY_EVENT = new UpdateEvent(Gauge.this, UpdateEvent.EventType.VISIBILITY); + private final UpdateEvent INTERACTIVITY_EVENT = new UpdateEvent(Gauge.this, UpdateEvent.EventType.INTERACTIVITY); + private final UpdateEvent FINISHED_EVENT = new UpdateEvent(Gauge.this, UpdateEvent.EventType.FINISHED); + private final UpdateEvent SECTION_EVENT = new UpdateEvent(Gauge.this, UpdateEvent.EventType.SECTION); + private final UpdateEvent ALERT_EVENT = new UpdateEvent(Gauge.this, UpdateEvent.EventType.ALERT); + private final UpdateEvent VALUE_EVENT = new UpdateEvent(Gauge.this, UpdateEvent.EventType.VALUE); + + //private volatile Future blinkFuture; + //private static ScheduledExecutorService blinkService = new ScheduledThreadPoolExecutor(2, Helper.getThreadFactory("BlinkTask", true)); + //private volatile Callable blinkTask; + + //private static String userAgentStyleSheet; + + private BooleanBinding showing; + + // Update events + private List updateEventQueue = new ArrayList<>(); // LinkedBlockingQueue<>(); + private List listenerList = new /*CopyOnWrite*/ArrayList<>(); + + // Data related + private DoubleProperty value; + private DoubleProperty oldValue; // last value + private DoubleProperty currentValue; + private DoubleProperty formerValue; // last current value + private double _minValue; + private DoubleProperty minValue; + private double _maxValue; + private DoubleProperty maxValue; + private double _range; + private DoubleProperty range; + private double _threshold; + private DoubleProperty threshold; + private String _title; + private StringProperty title; + private String _subTitle; + private StringProperty subTitle; + private String _unit; + private StringProperty unit; + //private boolean _averagingEnabled; + //private BooleanProperty averagingEnabled; + //private int _averagingPeriod; + //private IntegerProperty averagingPeriod; + //private MovingAverage movingAverage; +// private ObservableList
sections; +// private ObservableList
areas; +// private ObservableList
tickMarkSections; +// private ObservableList
tickLabelSections; +// private ObservableList markers; + // UI related + private SkinType skinType; + private boolean _startFromZero; + private BooleanProperty startFromZero; + private boolean _returnToZero; + private BooleanProperty returnToZero; + private Color _zeroColor; + private ObjectProperty zeroColor; + private double _minMeasuredValue; + private DoubleProperty minMeasuredValue; + private double _maxMeasuredValue; + private DoubleProperty maxMeasuredValue; + private boolean _minMeasuredValueVisible; + private BooleanProperty minMeasuredValueVisible; + private boolean _maxMeasuredValueVisible; + private BooleanProperty maxMeasuredValueVisible; + private boolean _oldValueVisible; + private BooleanProperty oldValueVisible; + private boolean _valueVisible; + private BooleanProperty valueVisible; + private Paint _backgroundPaint; + private ObjectProperty backgroundPaint; + private Paint _borderPaint; + private ObjectProperty borderPaint; + private double _borderWidth; + private DoubleProperty borderWidth; + private Paint _foregroundPaint; + private ObjectProperty foregroundPaint; + private Color _knobColor; + private ObjectProperty knobColor; + private KnobType _knobType; + private ObjectProperty knobType; + private Pos _knobPosition; + private ObjectProperty knobPosition; + private boolean _knobVisible; + private BooleanProperty knobVisible; + private boolean _animated; + private BooleanProperty animated; + private long animationDuration; + private double _startAngle; + private DoubleProperty startAngle; + private double _angleRange; + private DoubleProperty angleRange; + private double _angleStep; + private DoubleProperty angleStep; + private double _arcExtend; + private DoubleProperty arcExtend; + private boolean _autoScale; + private BooleanProperty autoScale; + private boolean _shadowsEnabled; + private BooleanProperty shadowsEnabled; + private boolean _barEffectEnabled; + private BooleanProperty barEffectEnabled; + private ScaleDirection _scaleDirection; + private ObjectProperty scaleDirection; + private TickLabelLocation _tickLabelLocation; + private ObjectProperty tickLabelLocation; + private TickLabelOrientation _tickLabelOrientation; + private ObjectProperty tickLabelOrientation; + private Color _tickLabelColor; + private ObjectProperty tickLabelColor; + private Color _tickMarkColor; + private ObjectProperty tickMarkColor; + private Color _majorTickMarkColor; + private ObjectProperty majorTickMarkColor; + private double _majorTickMarkLengthFactor; + private DoubleProperty majorTickMarkLengthFactor; + private double _majorTickMarkWidthFactor; + private DoubleProperty majorTickMarkWidthFactor; + private Color _mediumTickMarkColor; + private ObjectProperty mediumTickMarkColor; + private double _mediumTickMarkLengthFactor; + private DoubleProperty mediumTickMarkLengthFactor; + private double _mediumTickMarkWidthFactor; + private DoubleProperty mediumTickMarkWidthFactor; + private Color _minorTickMarkColor; + private ObjectProperty minorTickMarkColor; + private double _minorTickMarkLengthFactor; + private DoubleProperty minorTickMarkLengthFactor; + private double _minorTickMarkWidthFactor; + private DoubleProperty minorTickMarkWidthFactor; + private TickMarkType _majorTickMarkType; + private ObjectProperty majorTickMarkType; + private TickMarkType _mediumTickMarkType; + private ObjectProperty mediumTickMarkType; + private TickMarkType _minorTickMarkType; + private ObjectProperty minorTickMarkType; + private Locale _locale; + private ObjectProperty locale; + private int _decimals; + private IntegerProperty decimals; + private int _tickLabelDecimals; + private IntegerProperty tickLabelDecimals; + private NeedleType _needleType; + private ObjectProperty needleType; + private NeedleShape _needleShape; + private ObjectProperty needleShape; + private NeedleSize _needleSize; + private ObjectProperty needleSize; + private NeedleBehavior _needleBehavior; + private ObjectProperty needleBehavior; + private Color _needleColor; + private ObjectProperty needleColor; + private Color _needleBorderColor; + private ObjectProperty needleBorderColor; + private Color _barColor; + private ObjectProperty barColor; + private Color _barBorderColor; + private ObjectProperty barBorderColor; + private Color _barBackgroundColor; + private ObjectProperty barBackgroundColor; + //private LcdDesign _lcdDesign; + //private ObjectProperty lcdDesign; + //private LcdFont _lcdFont; + //private ObjectProperty lcdFont; + private Color _ledColor; + private ObjectProperty ledColor; + private LedType _ledType; + private ObjectProperty ledType; + private Color _titleColor; + private ObjectProperty titleColor; + private Color _subTitleColor; + private ObjectProperty subTitleColor; + private Color _unitColor; + private ObjectProperty unitColor; + private Color _valueColor; + private ObjectProperty valueColor; + private Color _thresholdColor; + private ObjectProperty thresholdColor; + private Color _averageColor; + private ObjectProperty averageColor; + private boolean _checkSectionsForValue; + private BooleanProperty checkSectionsForValue; + private boolean _checkAreasForValue; + private BooleanProperty checkAreasForValue; + private boolean _checkThreshold; + private BooleanProperty checkThreshold; + private boolean _innerShadowEnabled; + private BooleanProperty innerShadowEnabled; + private boolean _thresholdVisible; + private BooleanProperty thresholdVisible; + private boolean _averageVisible; + private BooleanProperty averageVisible; + private boolean _sectionsVisible; + private BooleanProperty sectionsVisible; + private boolean _sectionsAlwaysVisible; + private BooleanProperty sectionsAlwaysVisible; + private boolean _sectionTextVisible; + private BooleanProperty sectionTextVisible; + private boolean _sectionIconsVisible; + private BooleanProperty sectionIconsVisible; + private boolean _highlightSections; + private BooleanProperty highlightSections; + private boolean _areasVisible; + private BooleanProperty areasVisible; + private boolean _areaTextVisible; + private BooleanProperty areaTextVisible; + private boolean _areaIconsVisible; + private BooleanProperty areaIconsVisible; + private boolean _highlightAreas; + private BooleanProperty highlightAreas; + private boolean _tickMarkSectionsVisible; + private BooleanProperty tickMarkSectionsVisible; + private boolean _tickLabelSectionsVisible; + private BooleanProperty tickLabelSectionsVisible; +// private boolean _markersVisible; +// private BooleanProperty markersVisible; + private boolean _majorTickMarksVisible; + private BooleanProperty majorTickMarksVisible; + private boolean _mediumTickMarksVisible; + private BooleanProperty mediumTickMarksVisible; + private boolean _minorTickMarksVisible; + private BooleanProperty minorTickMarksVisible; + private boolean _tickMarkRingVisible; + private BooleanProperty tickMarkRingVisible; + private boolean _tickLabelsVisible; + private BooleanProperty tickLabelsVisible; + private boolean _onlyFirstAndLastTickLabelVisible; + private BooleanProperty onlyFirstAndLastTickLabelVisible; + private double _majorTickSpace; + private DoubleProperty majorTickSpace; + private double _minorTickSpace; + private DoubleProperty minorTickSpace; + //private boolean _lcdVisible; + //private BooleanProperty lcdVisible; + //private boolean _lcdCrystalEnabled; + //private BooleanProperty lcdCrystalEnabled; + private boolean _ledVisible; + private BooleanProperty ledVisible; + private boolean _ledOn; + private BooleanProperty ledOn; + private boolean _ledBlinking; + private BooleanProperty ledBlinking; + private Orientation _orientation; + private ObjectProperty orientation; + private boolean _gradientBarEnabled; + private BooleanProperty gradientBarEnabled; + //private GradientLookup gradientLookup; + private boolean _customTickLabelsEnabled; + private BooleanProperty customTickLabelsEnabled; + private ObservableList customTickLabels; + private double _customTickLabelFontSize; + private DoubleProperty customTickLabelFontSize; + private boolean _interactive; + private BooleanProperty interactive; + private String _buttonTooltipText; + private StringProperty buttonTooltipText; + private boolean _keepAspect; + private BooleanProperty keepAspect; + private boolean _customFontEnabled; + private BooleanProperty customFontEnabled; + private Font _customFont; + private ObjectProperty customFont; + private boolean _alert; + private BooleanProperty alert; + private String _alertMessage; + private StringProperty alertMessage; + private boolean _smoothing; + private BooleanProperty smoothing; + //private String formatString; + + // others + private double originalMinValue; + private double originalMaxValue; + private double originalThreshold; + private Timeline timeline; + private Instant lastCall; + private boolean withinSpeedLimit; + + + // ******************** Constructors ************************************** + public Gauge() { + this(SkinType.GAUGE); + } + public Gauge(@NamedArg(value="skinType", defaultValue="SkinType.GAUGE") final SkinType SKIN_TYPE) { + //setNodeOrientation(NodeOrientation.LEFT_TO_RIGHT); + skinType = SKIN_TYPE; + getStyleClass().add("gauge"); + + init(); + registerListeners(); + + setSkinType(SKIN_TYPE); + } + /*public Gauge(@NamedArg(value="skinType", defaultValue="SkinType.GAUGE") SkinType skinType, + @NamedArg(value="minValue", defaultValue="0") double minValue, + @NamedArg(value="maxValue", defaultValue="100") double maxValue, + @NamedArg(value="value", defaultValue="0") double value, + @NamedArg(value="threshold", defaultValue="100") double threshold, + @NamedArg(value="title", defaultValue="") String title, + @NamedArg(value="subTitle", defaultValue="") String subTitle, + @NamedArg(value="unit", defaultValue="") String unit, + @NamedArg(value="averagingEnabled", defaultValue="false") boolean averagingEnabled, + @NamedArg(value="startFromZero", defaultValue="false") boolean startFromZero, + @NamedArg(value="returnToZero", defaultValue="false") boolean returnToZero, + @NamedArg(value="zeroColor", defaultValue="#242424") Color zeroColor, + @NamedArg(value="minMeasuredValue", defaultValue="100") double minMeasuredValue, + @NamedArg(value="maxMeasuredValue", defaultValue="0") double maxMeasuredValue, + @NamedArg(value="minMeasuredValueVisible", defaultValue="false") boolean minMeasuredValueVisible, + @NamedArg(value="maxMeasuredValueVisible", defaultValue="false") boolean maxMeasuredValueVisible, + @NamedArg(value="oldValueVisible", defaultValue="false") boolean oldValueVisible, + @NamedArg(value="valueVisible", defaultValue="true") boolean valueVisible, + @NamedArg(value="backgroundPaint", defaultValue="#00000000") Paint backgroundPaint, + @NamedArg(value="borderPaint", defaultValue="#00000000") Paint borderPaint, + @NamedArg(value="foregroundPaint", defaultValue="#00000000") Paint foregroundPaint, + @NamedArg(value="borderWidth", defaultValue="1") double borderWidth, + @NamedArg(value="knobColor", defaultValue="#cccccc") Color knobColor, + @NamedArg(value="knobType", defaultValue="KnobType.STANDARD") KnobType knobType, + @NamedArg(value="knobVisible", defaultValue="true") boolean knobVisible, + @NamedArg(value="animated", defaultValue="false") boolean animated, + @NamedArg(value="animationDuration", defaultValue="800") long animationDuration, + @NamedArg(value="startAngle", defaultValue="320") double startAngle, + @NamedArg(value="angleRange", defaultValue="280") double angleRange, + @NamedArg(value="autoScale", defaultValue="true") boolean autoScale, + @NamedArg(value="shadowsEnabled", defaultValue="false") boolean shadowsEnabled, + @NamedArg(value="barEffectEnabled", defaultValue="false") boolean barEffectEnabled, + @NamedArg(value="scaleDirection", defaultValue="ScaleDiretion.CLOCKWISE") ScaleDirection scaleDirection, + @NamedArg(value="tickLabelLocation", defaultValue="TickLabelLocation.INSIDE") TickLabelLocation tickLabelLocation, + @NamedArg(value="tickLabelOrientation", defaultValue="TickLabelOrientation.HORIZONTAL") TickLabelOrientation tickLabelOrientation, + @NamedArg(value="tickLabelColor", defaultValue="#242424") Color tickLabelColor, + @NamedArg(value="tickMarkColor", defaultValue="#242424") Color tickMarkColor, + @NamedArg(value="majorTickMarkColor", defaultValue="#242424") Color majorTickMarkColor, + @NamedArg(value="mediumTickMarkColor", defaultValue="#242424") Color mediumTickMarkColor, + @NamedArg(value="minorTickMarkColor", defaultValue="#242424") Color minorTickMarkColor, + @NamedArg(value="majorTickMarkType", defaultValue="TickMarkType.LINE") TickMarkType majorTickMarkType, + @NamedArg(value="mediumTickMarkType", defaultValue="TickMarkType.LINE") TickMarkType mediumTickMarkType, + @NamedArg(value="minorTickMarkType", defaultValue="TickMarkType.LINE") TickMarkType minorTickMarkType, + @NamedArg(value="locale", defaultValue="Locale.US") Locale locale, + @NamedArg(value="decimals", defaultValue="1") int decimals, + @NamedArg(value="tickLabelDecimals", defaultValue="0") int tickLabelDecimals, + @NamedArg(value="needleType", defaultValue="NeedleType.STANDARD") NeedleType needleType, + @NamedArg(value="needleShape", defaultValue="NeedleShape.ANGLED") NeedleShape needleShape, + @NamedArg(value="needleSize", defaultValue="NeedleSize.STANDARD") NeedleSize needleSize, + @NamedArg(value="needleBehavior", defaultValue="NeedleBehavior.STANDARD") NeedleBehavior needleBehavior, + @NamedArg(value="needleColor", defaultValue="#c80000") Color needleColor, + @NamedArg(value="needleBorderColor", defaultValue="#00000000") Color needleBorderColor, + @NamedArg(value="barColor", defaultValue="#dfdfdf") Color barColor, + @NamedArg(value="barBorderColor", defaultValue="#00000000") Color barBorderColor, + @NamedArg(value="barBackgroundColor", defaultValue="#242424") Color barBackgroundColor, + @NamedArg(value="lcdDesign", defaultValue="LcdDesign.STANDARD") LcdDesign lcdDesign, + @NamedArg(value="lcdFont", defaultValue="LcdFont.DIGITAL_BOLD") LcdFont lcdFont, + @NamedArg(value="ledColor", defaultValue="#ff0000") Color ledColor, + @NamedArg(value="ledType", defaultValue="LedType.STANDARD") LedType ledType, + @NamedArg(value="titleColor", defaultValue="#242424") Color titleColor, + @NamedArg(value="subTitleColor", defaultValue="#242424") Color subTitleColor, + @NamedArg(value="unitColor", defaultValue="#242424") Color unitColor, + @NamedArg(value="valueColor", defaultValue="#242424") Color valueColor, + @NamedArg(value="thresholdColor", defaultValue="#dc143c") Color thresholdColor, + @NamedArg(value="averageColor", defaultValue="#ff00ff") Color averageColor, + @NamedArg(value="checkSectionsForValue", defaultValue="false") boolean checkSectionsForValue, + @NamedArg(value="checkAreasForValue", defaultValue="false") boolean checkAreasForValue, + @NamedArg(value="checkTreshold", defaultValue="false") boolean checkThreshold, + @NamedArg(value="innerShadowEnabled", defaultValue="false") boolean innerShadowVisible, + @NamedArg(value="thresholdVisible", defaultValue="false") boolean thresholdVisible, + @NamedArg(value="averageVisible", defaultValue="false") boolean averageVisible, + @NamedArg(value="sectionsVisible", defaultValue="false") boolean sectionsVisible, + @NamedArg(value="sectionsAlwaysVisible", defaultValue="false") boolean sectionsAlwaysVisible, + @NamedArg(value="sectionTextVisible", defaultValue="false") boolean sectionTextVisible, + @NamedArg(value="sectionIconsVisible", defaultValue="false") boolean sectionIconsVisible, + @NamedArg(value="highlightSections", defaultValue="false") boolean highlightSections, + @NamedArg(value="areasVisible", defaultValue="false") boolean areasVisible, + @NamedArg(value="areaTextVisible", defaultValue="false") boolean areaTextVisible, + @NamedArg(value="areaIconsVisible", defaultValue="false") boolean areaIconsVisible, + @NamedArg(value="highlightAreas", defaultValue="false") boolean highlightAreas, + @NamedArg(value="tickMarkSectionsVisible", defaultValue="false") boolean tickMarkSectionsVisible, + @NamedArg(value="tickLabelSectionsVisible", defaultValue="false") boolean tickLabelSectionsVisible, + @NamedArg(value="markersVisible", defaultValue="false") boolean markersVisible, + @NamedArg(value="tickLabelsVisible", defaultValue="true") boolean tickLabelsVisible, + @NamedArg(value="onlyFirstAndLastTickLabelVisible", defaultValue="false") boolean onlyFirstAndLastTickLabelVisible, + @NamedArg(value="majorTickMarksVisible", defaultValue="true") boolean majorTickMarksVisible, + @NamedArg(value="mediumTickMarksVisible", defaultValue="true") boolean mediumTickMarksVisible, + @NamedArg(value="minorTickMarksVisible", defaultValue="true") boolean minorTickMarksVisible, + @NamedArg(value="tickMarkRingVisible", defaultValue="false") boolean tickMarkRingVisible, + @NamedArg(value="lcdVisible", defaultValue="false") boolean lcdVisible, + @NamedArg(value="lcdCrystalEnalbed", defaultValue="false") boolean lcdCrystalEnabled, + @NamedArg(value="ledVisible", defaultValue="false") boolean ledVisible, + @NamedArg(value="orientation", defaultValue="Orientation.HORIZONTAL") Orientation orientation, + @NamedArg(value="keepAspect", defaultValue="true") boolean keepAspect, + @NamedArg(value="gradientBarEnabled", defaultValue="false") boolean gradientBarEnabled, + @NamedArg(value="customTickLabelsEnabled", defaultValue="false") boolean customTickLabelsEnabled, + @NamedArg(value="customTickLabelFontSize", defaultValue="18") double customTickLabelFontSize, + @NamedArg(value="interactive", defaultValue="false") boolean interactive, + @NamedArg(value="buttonTooltipText", defaultValue="") String buttonTooltipText, + @NamedArg(value="customFontEnabled", defaultValue="false") boolean customFontEnabled, + @NamedArg(value="customFont", defaultValue="Fonts.robotoRegular(12)") Font customFont, + @NamedArg(value="alert", defaultValue="false") boolean alert, + @NamedArg(value="alertMessage", defaultValue="") String alertMessage, + @NamedArg(value="smoothing", defaultValue="false") boolean smoothing + ) { + setNodeOrientation(NodeOrientation.LEFT_TO_RIGHT); + this.skinType = skinType; + getStyleClass().add("gauge"); + + init(); + registerListeners(); + + setSkinType(skinType); + }*/ + + + // ******************** Initialization ************************************ + private void init() { + _minValue = 0; + _maxValue = 100; + value = new DoublePropertyBase(_minValue) { + @Override protected void invalidated() { + final double VALUE = get(); + withinSpeedLimit = !(Instant.now().minusMillis(getAnimationDuration()).isBefore(lastCall)); + lastCall = Instant.now(); + if (isAnimated() && withinSpeedLimit) { + long animationDuration = isReturnToZero() ? (long) (0.2 * getAnimationDuration()) : getAnimationDuration(); + timeline.stop(); + + final KeyValue KEY_VALUE; + if (NeedleBehavior.STANDARD == getNeedleBehavior()) { + KEY_VALUE = new KeyValue(currentValue, VALUE, Interpolator.SPLINE(0.5, 0.4, 0.4, 1.0)); + } else { // Optimized only useful in a gauge where the angle range is 360 deg and the shorter way has to be calculated. + double ov = getOldValue(); + double min = getMinValue(); + double max = getMaxValue(); + double halfRange = getRange() * 0.5; + double cv = getCurrentValue(); + double delta = VALUE - getCurrentValue(); + + if (delta < -halfRange) { + double kv1 = max - cv; + double kv2 = VALUE; + } else if (delta > halfRange) { + + } + + double tmpValue; + + if (Math.abs(VALUE - ov) > getRange() * 0.5) { + if (ov < VALUE) { + tmpValue = min - max + VALUE; + } else { + tmpValue = ov + max - ov + min + VALUE - getRange(); + } + KEY_VALUE = new KeyValue(currentValue, tmpValue, Interpolator.SPLINE(0.5, 0.4, 0.4, 1.0)); + } else { + if (cv < min) currentValue.set(max + cv); + KEY_VALUE = new KeyValue(currentValue, VALUE, Interpolator.SPLINE(0.5, 0.4, 0.4, 1.0)); + } + } + final KeyFrame KEY_FRAME = new KeyFrame(Duration.millis(animationDuration), KEY_VALUE); + timeline.getKeyFrames().setAll(KEY_FRAME); + timeline.play(); + } else { + currentValue.set(VALUE); + fireUpdateEvent(FINISHED_EVENT); + } + //if (isAveragingEnabled()) { movingAverage.addData(new Data(VALUE)); } + } + @Override public void set(final double VALUE) { + super.set(VALUE); + fireUpdateEvent(VALUE_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "value"; } + }; + oldValue = new SimpleDoubleProperty(Gauge.this, "oldValue", value.get()); + currentValue = new DoublePropertyBase(value.get()) { + @Override protected void invalidated() { + final double VALUE = get(); + if (isCheckThreshold()) { + double thrshld = getThreshold(); + if (formerValue.get() < thrshld && VALUE > thrshld) { + fireEvent(EXCEEDED_EVENT); + } else if (formerValue.get() > thrshld && VALUE < thrshld) { + fireEvent(UNDERRUN_EVENT); + } + } + if (VALUE < getMinMeasuredValue()) { + setMinMeasuredValue(VALUE); + } else if (VALUE > getMaxMeasuredValue()) { + setMaxMeasuredValue(VALUE); + } + formerValue.set(VALUE); + } + @Override public void set(final double VALUE) { super.set(VALUE); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "currentValue";} + }; + formerValue = new SimpleDoubleProperty(Gauge.this, "formerValue", value.get()); + _range = _maxValue - _minValue; + _threshold = _maxValue; + _title = ""; + _subTitle = ""; + _unit = ""; + //_averagingEnabled = false; + //_averagingPeriod = 10; + //movingAverage = new MovingAverage(_averagingPeriod); +// sections = FXCollections.observableArrayList(); +// areas = FXCollections.observableArrayList(); +// tickMarkSections = FXCollections.observableArrayList(); +// tickLabelSections = FXCollections.observableArrayList(); +// markers = FXCollections.observableArrayList(); + + _startFromZero = false; + _returnToZero = false; + _zeroColor = DARK_COLOR; + _minMeasuredValue = _maxValue; + _maxMeasuredValue = _minValue; + _minMeasuredValueVisible = false; + _maxMeasuredValueVisible = false; + _oldValueVisible = false; + _valueVisible = true; + _backgroundPaint = Color.TRANSPARENT; + _borderPaint = Color.TRANSPARENT; + _borderWidth = 1; + _foregroundPaint = Color.TRANSPARENT; + _knobColor = Color.rgb(204, 204, 204); + _knobType = KnobType.STANDARD; + _knobPosition = Pos.CENTER; + _knobVisible = true; + _animated = false; + animationDuration = 800; + _startAngle = 320; + _angleRange = 280; + _angleStep = _angleRange / _range; + _arcExtend = 9.2; + _autoScale = true; + _shadowsEnabled = false; + _barEffectEnabled = false; + _scaleDirection = ScaleDirection.CLOCKWISE; + _tickLabelLocation = TickLabelLocation.INSIDE; + _tickLabelOrientation = TickLabelOrientation.HORIZONTAL; + _tickLabelColor = DARK_COLOR; + _tickMarkColor = DARK_COLOR; + _majorTickMarkColor = DARK_COLOR; + _majorTickMarkLengthFactor = 0.42; + _majorTickMarkWidthFactor = 0.275; + _mediumTickMarkColor = DARK_COLOR; + _mediumTickMarkLengthFactor = 0.41; + _mediumTickMarkWidthFactor = 0.175; + _minorTickMarkColor = DARK_COLOR; + _minorTickMarkLengthFactor = 0.40; + _minorTickMarkWidthFactor = 0.1125; + _majorTickMarkType = TickMarkType.LINE; + _mediumTickMarkType = TickMarkType.LINE; + _minorTickMarkType = TickMarkType.LINE; + _locale = Locale.US; + _decimals = 1; + _tickLabelDecimals = 0; + _needleType = NeedleType.STANDARD; + _needleShape = NeedleShape.ANGLED; + _needleSize = NeedleSize.STANDARD; + _needleBehavior = NeedleBehavior.STANDARD; + _needleColor = Color.rgb(200, 0, 0); + _needleBorderColor = Color.TRANSPARENT; + _barColor = BRIGHT_COLOR; + _barBorderColor = Color.TRANSPARENT; + _barBackgroundColor = DARK_COLOR; + //_lcdDesign = LcdDesign.STANDARD; + //_lcdFont = LcdFont.DIGITAL_BOLD; + _ledColor = Color.RED; + _ledType = LedType.STANDARD; + _titleColor = DARK_COLOR; + _subTitleColor = DARK_COLOR; + _unitColor = DARK_COLOR; + _valueColor = DARK_COLOR; + _thresholdColor = Color.CRIMSON; + _averageColor = Color.MAGENTA; + _checkSectionsForValue = false; + _checkAreasForValue = false; + _checkThreshold = false; + _innerShadowEnabled = false; + _thresholdVisible = false; + _averageVisible = false; + _sectionsVisible = false; + _sectionsAlwaysVisible = false; + _sectionTextVisible = false; + _sectionIconsVisible = false; + _highlightSections = false; + _areasVisible = false; + _areaTextVisible = false; + _areaIconsVisible = false; + _highlightAreas = false; + _tickMarkSectionsVisible = false; + _tickLabelSectionsVisible = false; +// _markersVisible = false; + _tickLabelsVisible = true; + _onlyFirstAndLastTickLabelVisible = false; + _majorTickMarksVisible = true; + _mediumTickMarksVisible = true; + _minorTickMarksVisible = true; + _tickMarkRingVisible = false; + _majorTickSpace = 10; + _minorTickSpace = 1; + //_lcdVisible = false; + //_lcdCrystalEnabled = false; + _ledVisible = false; + _ledOn = false; + _ledBlinking = false; + _orientation = Orientation.HORIZONTAL; + _gradientBarEnabled = false; + _customTickLabelsEnabled = false; + customTickLabels = FXCollections.observableArrayList(); + _customTickLabelFontSize = 18; + _interactive = false; + _buttonTooltipText = ""; + _keepAspect = true; + _customFontEnabled = false; + _customFont = Fonts.robotoRegular(12); + _alert = false; + _alertMessage = ""; + _smoothing = false; + //formatString = "%.2f"; + + originalMinValue = -Double.MAX_VALUE; + originalMaxValue = Double.MAX_VALUE; + originalThreshold = Double.MAX_VALUE; + lastCall = Instant.now(); + timeline = new Timeline(); + timeline.setOnFinished(e -> { + if (isReturnToZero() && Double.compare(currentValue.get(), 0.0) != 0.0) { + final KeyValue KEY_VALUE2 = new KeyValue(value, 0, Interpolator.SPLINE(0.5, 0.4, 0.4, 1.0)); + final KeyFrame KEY_FRAME2 = new KeyFrame(Duration.millis((long) (0.8 * getAnimationDuration())), KEY_VALUE2); + timeline.getKeyFrames().setAll(KEY_FRAME2); + timeline.play(); + } + fireUpdateEvent(FINISHED_EVENT); + }); + } + + public void reInit() { + setZeroColor(DARK_COLOR); + setMinMeasuredValueVisible(false); + setMaxMeasuredValueVisible(false); + setOldValueVisible(false); + setValueVisible(true); + setBackgroundPaint(Color.TRANSPARENT); + setBorderPaint(Color.TRANSPARENT); + setBorderWidth(1); + setForegroundPaint(Color.TRANSPARENT); + setKnobColor(Color.rgb(204, 204, 204)); + setKnobType(KnobType.STANDARD); + setKnobPosition(Pos.CENTER); + setKnobVisible(true); + setShadowsEnabled(false); + setBarEffectEnabled(false); + setTickLabelLocation(TickLabelLocation.INSIDE); + setTickLabelOrientation(TickLabelOrientation.HORIZONTAL); + setTickLabelColor(DARK_COLOR); + setTickMarkColor(DARK_COLOR); + setMajorTickMarkColor(DARK_COLOR); + setMajorTickMarkLengthFactor(0.42); + setMajorTickMarkWidthFactor(0.275); + setMediumTickMarkColor(DARK_COLOR); + setMediumTickMarkLengthFactor(0.41); + setMediumTickMarkWidthFactor(0.175); + setMinorTickMarkColor(DARK_COLOR); + setMinorTickMarkLengthFactor(0.40); + setMinorTickMarkWidthFactor(0.1125); + setMajorTickMarkType(TickMarkType.LINE); + setMediumTickMarkType(TickMarkType.LINE); + setMinorTickMarkType(TickMarkType.LINE); + setNeedleType(NeedleType.STANDARD); + setNeedleShape(NeedleShape.ANGLED); + setNeedleSize(NeedleSize.STANDARD); + setNeedleBehavior(NeedleBehavior.STANDARD); + setNeedleColor(Color.rgb(200, 0, 0)); + setNeedleBorderColor(Color.TRANSPARENT); + setBarColor(BRIGHT_COLOR); + setBarBorderColor(Color.TRANSPARENT); + setBarBackgroundColor(DARK_COLOR); + //setLcdDesign(LcdDesign.STANDARD); + //setLcdFont(LcdFont.DIGITAL_BOLD); + setLedColor(Color.RED); + setLedType(LedType.STANDARD); + setTitleColor(DARK_COLOR); + setSubTitleColor(DARK_COLOR); + setUnitColor(DARK_COLOR); + setValueColor(DARK_COLOR); + setThresholdColor(Color.CRIMSON); + setAverageColor(Color.MAGENTA); + setCheckSectionsForValue(false); + setCheckAreasForValue(false); + setCheckThreshold(false); + setInnerShadowEnabled(false); + setThresholdVisible(false); + setAverageVisible(false); + setSectionsVisible(false); + setSectionsAlwaysVisible(false); + setSectionTextVisible(false); + setSectionIconsVisible(false); + setHighlightSections(false); + setAreasVisible(false); + setAreaTextVisible(false); + setAreaIconsVisible(false); + setHighlightAreas(false); + setTickMarkSectionsVisible(false); + setTickLabelSectionsVisible(false); +// setMarkersVisible(false); + setTickLabelsVisible(true); + setOnlyFirstAndLastTickLabelVisible(false); + setMajorTickMarksVisible(true); + setMediumTickMarksVisible(true); + setMinorTickMarksVisible(true); + setTickMarkRingVisible(false); + //setLcdVisible(false); + //setLcdCrystalEnabled(false); + setLedVisible(false); + setLedOn(false); + //setLedBlinking(false); + setOrientation(Orientation.HORIZONTAL); + setGradientBarEnabled(false); + setCustomTickLabelsEnabled(false); + setCustomTickLabels(FXCollections.observableArrayList()); + setCustomTickLabelFontSize(18); + setInteractive(false); + setButtonTooltipText(""); + setKeepAspect(true); + setCustomFontEnabled(false); + setAlert(false); + setAlertMessage(""); + setSmoothing(false); + } + + private void registerListeners() { + disabledProperty().addListener(o -> setOpacity(isDisabled() ? 0.4 : 1)); + valueProperty().addListener((o, ov, nv) -> oldValue.set(ov.doubleValue())); + if (null != getScene()) { + setupBinding(); + } else { + sceneProperty().addListener((o1, ov1, nv1) -> { + if (null == nv1) { return; } + if (null != getScene().getWindow()) { + setupBinding(); + } else { + sceneProperty().get().windowProperty().addListener((o2, ov2, nv2) -> { + if (null == nv2) { return; } + setupBinding(); + }); + } + }); + } + } + + + // ******************** Data related methods ****************************** + + /** + * Returns the value of the Gauge. If animated == true this value represents + * the value at the end of the animation. Where currentValue represents the + * current value during the animation. + * + * @return the value of the gauge + */ + public double getValue() { return value.get(); } + /** + * Sets the value of the Gauge to the given double. If animated == true this + * value will be the end value after the animation is finished. + * + * @param VALUE + */ + public void setValue(final double VALUE) { value.set(VALUE); } + public DoubleProperty valueProperty() { return value; } + + /** + * Returns the current value of the Gauge. If animated == true this value + * represents the current value during the animation. Otherwise it's returns + * the same value as the getValue() method. + * + * @return the current value of the gauge + */ + public double getCurrentValue() { return currentValue.get(); } + public ReadOnlyDoubleProperty currentValueProperty() { return currentValue; } + + /** + * Returns the last value of the Gauge. This will not be the last value during + * an animation but the final last value after the animation was finished. + * If you need to get the last value during an animation you should use + * formerValue instead. + * + * @return the last value of the gauge + */ + public double getOldValue() { return oldValue.get(); } + public ReadOnlyDoubleProperty oldValueProperty() { return oldValue; } + + /** + * Returns the last value of the Gauge. This will be the last value during + * an animation. + * If you need to get the last value after the animation is finished or if + * you don't use animation at all (when using real values) you should use + * oldValue instead. + * + * @return the last value of the gauge during an animation + */ + public double getFormerValue() { return formerValue.get(); } + public ReadOnlyDoubleProperty formerValueProperty() { return formerValue; } + + /** + * Returns the minimum value of the scale. This value represents the lower + * limit of the visible gauge values. + * + * @return the minimum value of the gauge scale + */ + public double getMinValue() { return null == minValue ? _minValue : minValue.get(); } + /** + * Sets the minimum value of the gauge scale to the given value + * + * @param VALUE + */ + public void setMinValue(final double VALUE) { + if (Status.RUNNING == timeline.getStatus()) { timeline.jumpTo(Duration.ONE); } + if (null == minValue) { + if (VALUE > getMaxValue()) { setMaxValue(VALUE); } + _minValue = Helper.clamp(-Double.MAX_VALUE, getMaxValue(), VALUE); + setRange(getMaxValue() - _minValue); + if (Double.compare(originalMinValue, -Double.MAX_VALUE) == 0) originalMinValue = _minValue; + if (isStartFromZero() && _minValue < 0) setValue(0); + if (Double.compare(originalThreshold, getThreshold()) < 0) { setThreshold(Helper.clamp(_minValue, getMaxValue(), originalThreshold)); } + //updateFormatString(); + fireUpdateEvent(RECALC_EVENT); + if (!valueProperty().isBound()) Gauge.this.setValue(Helper.clamp(getMinValue(), getMaxValue(), Gauge.this.getValue())); + } else { + minValue.set(VALUE); + } + } + public DoubleProperty minValueProperty() { + if (null == minValue) { + minValue = new DoublePropertyBase(_minValue) { + @Override protected void invalidated() { + final double VALUE = get(); + if (VALUE > getMaxValue()) setMaxValue(VALUE); + setRange(getMaxValue() - VALUE); + if (Double.compare(originalMinValue, -Double.MAX_VALUE) == 0) originalMinValue = VALUE; + if (isStartFromZero() && _minValue < 0) Gauge.this.setValue(0); + if (Double.compare(originalThreshold, getThreshold()) < 0) { setThreshold(Helper.clamp(VALUE, getMaxValue(), originalThreshold)); } + //updateFormatString(); + fireUpdateEvent(RECALC_EVENT); + if (!valueProperty().isBound()) Gauge.this.setValue(Helper.clamp(getMinValue(), getMaxValue(), Gauge.this.getValue())); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "minValue";} + }; + } + return minValue; + } + + /** + * Returns the maximum value of the scale. This value represents the upper limit + * of the visible gauge values. + * + * @return the maximum value of the gauge scale + */ + public double getMaxValue() { return null == maxValue ? _maxValue : maxValue.get(); } + /** + * Sets the maximum value of the gauge scale to the given value + * + * @param VALUE + */ + public void setMaxValue(final double VALUE) { + if (Status.RUNNING == timeline.getStatus()) { timeline.jumpTo(Duration.ONE); } + if (null == maxValue) { + if (VALUE < getMinValue()) { setMinValue(VALUE); } + _maxValue = Helper.clamp(getMinValue(), Double.MAX_VALUE, VALUE); + setRange(_maxValue - getMinValue()); + if (Double.compare(originalMaxValue, Double.MAX_VALUE) == 0) originalMaxValue = _maxValue; + if (Double.compare(originalThreshold, getThreshold()) > 0) { setThreshold(Helper.clamp(getMinValue(), _maxValue, originalThreshold)); } + + if (!valueProperty().isBound()) Gauge.this.setValue(Helper.clamp(getMinValue(), getMaxValue(), Gauge.this.getValue())); + //updateFormatString(); + fireUpdateEvent(RECALC_EVENT); + } else { + maxValue.set(VALUE); + } + } + public DoubleProperty maxValueProperty() { + if (null == maxValue) { + maxValue = new DoublePropertyBase(_maxValue) { + @Override protected void invalidated() { + final double VALUE = get(); + if (VALUE < getMinValue()) setMinValue(VALUE); + setRange(VALUE - getMinValue()); + if (Double.compare(originalMaxValue, Double.MAX_VALUE) == 0) originalMaxValue = VALUE; + if (Double.compare(originalThreshold, getThreshold()) > 0) { setThreshold(Helper.clamp(getMinValue(), VALUE, originalThreshold)); } + //updateFormatString(); + fireUpdateEvent(RECALC_EVENT); + if (!valueProperty().isBound()) Gauge.this.setValue(Helper.clamp(getMinValue(), getMaxValue(), Gauge.this.getValue())); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "maxValue"; } + }; + } + return maxValue; + } + + /** + * Always returns the range of the gauge scale (maxValue - minValue). + * This value will be automatically calculated each time + * the min- or maxValue will change. + * + * @return the range of the gauge scale + */ + public double getRange() { return null == range ? _range : range.get(); } + /** + * This is a private method that sets the range to the given value + * which is always (maxValue - minValue). + * + * @param RANGE + */ + private void setRange(final double RANGE) { + if (null == range) { + _range = RANGE; + setAngleStep(getAngleRange() / RANGE); + } else { + range.set(RANGE); + } + } + public ReadOnlyDoubleProperty rangeProperty() { + if (null == range) { + range = new DoublePropertyBase((getMaxValue() - getMinValue())) { + @Override protected void invalidated() { setAngleStep(getAngleRange() / get()); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "range"; } + }; + } + return range; + } + + /** + * Returns the threshold value that can be used to visualize a + * threshold value on the scale. There are also events that will + * be fired if the threshold was exceeded or underrun. + * The value will be clamped to range of the gauge. + * + * @return the threshold value of the gauge + */ + public double getThreshold() { return null == threshold ? _threshold : threshold.get(); } + /** + * Sets the threshold of the gauge to the given value. The value + * will be clamped to the range of the gauge. + * + * @param THRESHOLD + */ + public void setThreshold(final double THRESHOLD) { + originalThreshold = THRESHOLD; + if (null == threshold) { + _threshold = Helper.clamp(getMinValue(), getMaxValue(), THRESHOLD); + fireUpdateEvent(RESIZE_EVENT); + } else { + threshold.set(THRESHOLD); + } + } + public DoubleProperty tresholdProperty() { + if (null == threshold) { + threshold = new DoublePropertyBase(_threshold) { + @Override protected void invalidated() { + final double THRESHOLD = get(); + if (THRESHOLD < getMinValue() || THRESHOLD > getMaxValue()) set(Helper.clamp(getMinValue(), getMaxValue(), THRESHOLD)); + fireUpdateEvent(RESIZE_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "threshold"; } + }; + } + return threshold; + } + + /** + * Returns the title of the gauge. This title will usually + * only be visible if it is not empty. + * + * @return the title of the gauge + */ + public String getTitle() { return null == title ? _title : title.get(); } + /** + * Sets the title of the gauge. This title will only be visible + * if it is not empty. + * + * @param TITLE + */ + public void setTitle(final String TITLE) { + if (null == title) { + _title = TITLE; + fireUpdateEvent(VISIBILITY_EVENT); + fireUpdateEvent(REDRAW_EVENT); + } else { + title.set(TITLE); + } + } + public StringProperty titleProperty() { + if (null == title) { + title = new StringPropertyBase(_title) { + @Override protected void invalidated() { + fireUpdateEvent(VISIBILITY_EVENT); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "title"; } + }; + _title = null; + } + return title; + } + + /** + * Returns the subtitle of the gauge. This subtitle will usually + * only be visible if it is not empty. + * + * @return the subtitle of the gauge + */ + public String getSubTitle() { return null == subTitle ? _subTitle : subTitle.get(); } + /** + * Sets the subtitle of the gauge. This subtitle will usually + * only be visible if it is not empty. + * + * @param SUBTITLE + */ + public void setSubTitle(final String SUBTITLE) { + if (null == subTitle) { + _subTitle = SUBTITLE; + fireUpdateEvent(VISIBILITY_EVENT); + fireUpdateEvent(REDRAW_EVENT); + } else { + subTitle.set(SUBTITLE); + } + } + public StringProperty subTitleProperty() { + if (null == subTitle) { + subTitle = new StringPropertyBase(_subTitle) { + @Override protected void invalidated() { + fireUpdateEvent(VISIBILITY_EVENT); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "subTitle"; } + }; + _subTitle = null; + } + return subTitle; + } + + /** + * Returns the unit of the gauge. This unit will usually only + * be visible if it is not empty. + * + * @return the unit of the gauge + */ + public String getUnit() { return null == unit ? _unit : unit.get(); } + /** + * Sets the unit of the gauge. This unit will usually only be + * visible if it is not empty. + * + * @param UNIT + */ + public void setUnit(final String UNIT) { + if (null == unit) { + _unit = UNIT; + fireUpdateEvent(VISIBILITY_EVENT); + fireUpdateEvent(REDRAW_EVENT); + } else { + unit.set(UNIT); + } + } + public StringProperty unitProperty() { + if (null == unit) { + unit = new StringPropertyBase(_unit) { + @Override protected void invalidated() { + fireUpdateEvent(VISIBILITY_EVENT); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "unit"; } + }; + _unit = null; + } + return unit; + } + + /** + * Returns the moving average object + * @return the moving average object + */ + /*public MovingAverage getMovingAverage() { + if (null == movingAverage) { movingAverage = new MovingAverage(getAveragingPeriod()); } + return movingAverage; + }*/ + + /** + * Returns true if the averaging functionality is enabled. + * @return true if the averaging functionality is enabled + */ + //public boolean isAveragingEnabled() { return null == averagingEnabled ? _averagingEnabled : averagingEnabled.get(); } + /** + * Defines if the averaging functionality will be enabled. + */ + /*public void setAveragingEnabled(final boolean ENABLED) { + if (null == averagingEnabled) { + _averagingEnabled = ENABLED; + fireUpdateEvent(REDRAW_EVENT); + } else { + averagingEnabled.set(ENABLED); + } + } + public BooleanProperty averagingEnabledProperty() { + if (null == averagingEnabled) { + averagingEnabled = new BooleanPropertyBase(_averagingEnabled) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "averagingEnabled"; } + }; + } + return averagingEnabled; + }*/ + + /** + * Returns the number of values that should be used for + * the averaging of values. The value must be in the + * range of 1 - 1000. + * @return the number of values used for averaging + */ + //public int getAveragingPeriod() { return null == averagingPeriod ? _averagingPeriod : averagingPeriod.get(); } + /** + * Defines the number values that should be used for + * the averaging of values. The value must be in the + * range of 1 - 1000. + * @param PERIOD + */ + /*public void setAveragingPeriod(final int PERIOD) { + if (null == averagingPeriod) { + _averagingPeriod = PERIOD; + getMovingAverage().setPeriod(_averagingPeriod); // MAX 1000 values + fireUpdateEvent(REDRAW_EVENT); + } else { + averagingPeriod.set(PERIOD); + } + } + public IntegerProperty averagingPeriodProperty() { + if (null == averagingPeriod) { + averagingPeriod = new IntegerPropertyBase(_averagingPeriod) { + @Override protected void invalidated() { + getMovingAverage().setPeriod(_averagingPeriod); // MAX 1000 values + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "averagingPeriod"; } + }; + } + return averagingPeriod; + }*/ + + /** + * Returns the current list of Data objects that will + * be used to calculate the moving average. + * @return the current list of Data objects used for the moving average + */ + //public Queue getAveragingWindow() { return movingAverage.getWindow(); } + + /** + * Returns the moving average over the number of values + * defined by averagingPeriod. + * @return the moving the average over the number of values defined by averagingPeriod + */ + //public double getAverage() { return movingAverage.getAverage(); } + /** + * Returns the moving average over the given duration. + * @param DURATION + * @return the moving average over the given duration + */ + //public double getTimeBasedAverageOf(final java.time.Duration DURATION) { return movingAverage.getTimeBasedAverageOf(DURATION); } + + /** + * Returns an observable list of Section objects. The sections + * will be used to colorize areas with a special meaning such + * as the red area in a rpm gauge. Sections in the Medusa library + * usually are less eye-catching than Areas. + * + * @return an observable list of Section objects + */ +// public ObservableList
getSections() { return sections; } + /** + * Sets the sections to the given list of Section objects. The + * sections will be used to colorize areas with a special + * meaning such as the red area in a rpm gauge. + * Sections in the Medusa library + * usually are less eye-catching than Areas. + * + * @param SECTIONS + */ +/* + public void setSections(final List
SECTIONS) { + sections.setAll(SECTIONS); + Collections.sort(sections, new SectionComparator()); + fireUpdateEvent(SECTION_EVENT); + } +*/ + /** + * Sets the sections to the given array of Section objects. The + * sections will be used to colorize areas with a special + * meaning such as the red area in a rpm gauge. + * + * @param SECTIONS + */ +// public void setSections(final Section... SECTIONS) { setSections(Arrays.asList(SECTIONS)); } + /** + * Adds the given Section to the list of sections. + * Sections in the Medusa library + * usually are less eye-catching than Areas. + * + * @param SECTION + */ +/* + public void addSection(final Section SECTION) { + if (null == SECTION) return; + sections.add(SECTION); + Collections.sort(sections, new SectionComparator()); + fireUpdateEvent(SECTION_EVENT); + } +*/ + /** + * Removes the given Section from the list of sections. + * Sections in the Medusa library + * usually are less eye-catching than Areas. + * + * @param SECTION + */ +/* + public void removeSection(final Section SECTION) { + if (null == SECTION) return; + sections.remove(SECTION); + Collections.sort(sections, new SectionComparator()); + fireUpdateEvent(SECTION_EVENT); + } +*/ + /** + * Clears the list of sections. + */ +/* + public void clearSections() { + sections.clear(); + fireUpdateEvent(SECTION_EVENT); + } +*/ + + /** + * Returns an observable list of Section objects. The sections + * will be used to colorize areas with a special meaning such + * as the red area in a rpm gauge. Areas in the Medusa library + * usually are more eye-catching than Sections. + * + * @return an observable list of Section objects + */ +// public ObservableList
getAreas() { return areas; } + /** + * Sets the sections to the given list of Section objects. The + * sections will be used to colorize areas with a special + * meaning such as the red area in a rpm gauge. + * Areas in the Medusa library usually are more + * eye-catching than Sections. + * + * @param AREAS + */ +/* + public void setAreas(final List
AREAS) { + areas.setAll(AREAS); + Collections.sort(areas, new SectionComparator()); + fireUpdateEvent(SECTION_EVENT); + } +*/ + /** + * Sets the sections to the given array of Section objects. The + * sections will be used to colorize areas with a special + * meaning such as the red area in a rpm gauge. + * Areas in the Medusa library usually are more + * eye-catching than Sections. + * + * @param AREAS + */ +// public void setAreas(final Section... AREAS) { setAreas(Arrays.asList(AREAS)); } + /** + * Adds the given Section to the list of areas. + * Areas in the Medusa library usually are more + * eye-catching than Sections. + * + * @param AREA + */ +/* + public void addArea(final Section AREA) { + if (null == AREA) return; + areas.add(AREA); + Collections.sort(areas, new SectionComparator()); + fireUpdateEvent(SECTION_EVENT); + } +*/ + /** + * Removes the given Section from the list of areas. + * Areas in the Medusa library usually are more + * eye-catching than Sections. + * + * @param AREA + */ +/* + public void removeArea(final Section AREA) { + if (null == AREA) return; + areas.remove(AREA); + Collections.sort(areas, new SectionComparator()); + fireUpdateEvent(SECTION_EVENT); + } +*/ + /** + * Clears the list of areas. + */ +/* + public void clearAreas() { + areas.clear(); + fireUpdateEvent(SECTION_EVENT); + } +*/ + + /** + * Returns an observable list of Section objects. + * The sections will be used to colorize tickmarks with a + * special meaning such as the red area in a rpm gauge. + * + * @return an observable list of Section objects + */ +// public ObservableList
getTickMarkSections() { return tickMarkSections; } + /** + * Sets the tickmark sections to the given list of Section objects. + * + * @param SECTIONS + */ +/* + public void setTickMarkSections(final List
SECTIONS) { + tickMarkSections.setAll(SECTIONS); + Collections.sort(tickMarkSections, new SectionComparator()); + fireUpdateEvent(REDRAW_EVENT); + } +*/ + /** + * Sets the tickmark sections to the given array of Section objects. + * + * @param SECTIONS + */ +// public void setTickMarkSections(final Section... SECTIONS) { setTickMarkSections(Arrays.asList(SECTIONS)); } + /** + * Adds the given Section to the list of tickmark sections. + * + * @param SECTION + */ +/* + public void addTickMarkSection(final Section SECTION) { + if (null == SECTION) return; + tickMarkSections.add(SECTION); + Collections.sort(tickMarkSections, new SectionComparator()); + fireUpdateEvent(REDRAW_EVENT); + } +*/ + /** + * Removes the given Section from the list of tickmark sections. + * + * @param SECTION + */ +/* + public void removeTickMarkSection(final Section SECTION) { + if (null == SECTION) return; + tickMarkSections.remove(SECTION); + Collections.sort(tickMarkSections, new SectionComparator()); + fireUpdateEvent(REDRAW_EVENT); + } +*/ + /** + * Clears the list of tickmark sections. + */ +/* + public void clearTickMarkSections() { + tickMarkSections.clear(); + fireUpdateEvent(REDRAW_EVENT); + } +*/ + + /** + * Returns an observable list of Section objects. + * The sections will be used to colorize ticklabels with + * a special meaning such as the red area in a rpm gauge. + * + * @return an observable list of Section objects + */ +// public ObservableList
getTickLabelSections() { return tickLabelSections; } + /** + * Sets the ticklabel sections to the given list of Section objects. + * + * @param SECTIONS + */ +/* + public void setTickLabelSections(final List
SECTIONS) { + tickLabelSections.setAll(SECTIONS); + Collections.sort(tickLabelSections, new SectionComparator()); + fireUpdateEvent(REDRAW_EVENT); + } +*/ + /** + * Sets the ticklabel sections to the given array of Section objects. + * + * @param SECTIONS + */ +// public void setTickLabelSections(final Section... SECTIONS) { setTickLabelSections(Arrays.asList(SECTIONS)); } + /** + * Adds the given Section to the list of ticklabel sections. + * + * @param SECTION + */ +/* + public void addTickLabelSection(final Section SECTION) { + if (null == SECTION) return; + tickLabelSections.add(SECTION); + Collections.sort(tickLabelSections, new SectionComparator()); + fireUpdateEvent(REDRAW_EVENT); + } +*/ + /** + * Removes the given Section from the list of ticklabel sections. + * + * @param SECTION + */ +/* + public void removeTickLabelSection(final Section SECTION) { + if (null == SECTION) return; + tickLabelSections.remove(SECTION); + Collections.sort(tickLabelSections, new SectionComparator()); + fireUpdateEvent(REDRAW_EVENT); + } +*/ + /** + * Clears the list of ticklabel sections. + */ +/* + public void clearTickLabelSections() { + tickLabelSections.clear(); + fireUpdateEvent(REDRAW_EVENT); + } +*/ + + /** + * Returns an observable list of Marker objects. + * Like the threshold the markers are used to visualize + * specific values. The markers will be visualized using + * nodes with mouse event support (pressed, released) and + * tooltip. + * + * @return an observable list of Marker objects + */ +// public ObservableList getMarkers() { return markers; } + /** + * Sets the list of markers to the given list of Marker objects. + * The markers will be visualized using nodes with mouse event + * support (pressed, released) and tooltip. + * + * @param MARKERS + */ +/* + public void setMarkers(final List MARKERS) { + markers.setAll(MARKERS); + Collections.sort(markers, new MarkerComparator()); + fireUpdateEvent(REDRAW_EVENT); + } +*/ + /** + * Sets the list of markers to the given array of Marker objects. + * The markers will be visualuzed using nodes with mouse event + * support (pressed, released) and tooltip. + * + * @param MARKERS + */ +// public void setMarkers(final Marker... MARKERS) { setMarkers(Arrays.asList(MARKERS)); } + /** + * Adds the given Marker to the list of markers. + * + * @param MARKER + */ +/* + public void addMarker(final Marker MARKER) { + if (null == MARKER) return; + markers.add(MARKER); + Collections.sort(markers, new MarkerComparator()); + fireUpdateEvent(REDRAW_EVENT); + } +*/ + /** + * Removes the given Marker from the list of markers. + * + * @param MARKER + */ +/* + public void removeMarker(final Marker MARKER) { + if (null == MARKER) return; + markers.remove(MARKER); + Collections.sort(markers, new MarkerComparator()); + fireUpdateEvent(REDRAW_EVENT); + } +*/ + /** + * Clears the list of markers. + */ +/* + public void clearMarkers() { + markers.clear(); + fireUpdateEvent(REDRAW_EVENT); + } +*/ + + + // ******************** UI related methods ******************************** + /** + * A convenient method to set the color of foreground elements like + * title, subTitle, unit, value, tickLabel and tickMark to the given + * Color. + * + * @param COLOR + */ + public void setForegroundBaseColor(final Color COLOR) { + if (null == titleColor) { _titleColor = COLOR; } else { titleColor.set(COLOR); } + if (null == subTitleColor) { _subTitleColor = COLOR; } else { subTitleColor.set(COLOR); } + if (null == unitColor) { _unitColor = COLOR; } else { unitColor.set(COLOR); } + if (null == valueColor) { _valueColor = COLOR; } else { valueColor.set(COLOR); } + if (null == tickLabelColor) { _tickLabelColor = COLOR; } else { tickLabelColor.set(COLOR); } + if (null == zeroColor) { _zeroColor = COLOR; } else { zeroColor.set(COLOR); } + if (null == tickMarkColor) { _tickMarkColor = COLOR; } else { tickMarkColor.set(COLOR); } + if (null == majorTickMarkColor) { _majorTickMarkColor = COLOR; } else { majorTickMarkColor.set(COLOR); } + if (null == mediumTickMarkColor) { _mediumTickMarkColor = COLOR; } else { mediumTickMarkColor.set(COLOR); } + if (null == minorTickMarkColor) { _minorTickMarkColor = COLOR; } else { minorTickMarkColor.set(COLOR); } + fireUpdateEvent(REDRAW_EVENT); + } + + /** + * Returns true if the visualization of the value should start from 0. This + * is especially useful when you work for example with a gauge that has a + * range with a negative minValue + * + * @return true if the visualization of the value should start from 0 + */ + public boolean isStartFromZero() { return null == startFromZero ? _startFromZero : startFromZero.get(); } + /** + * Defines the behavior of the visualization where the needle/bar should + * start from 0 instead of the minValue. This is especially useful when + * working with a gauge that has a range with a negative minValue + * + * @param IS_TRUE + */ + public void setStartFromZero(final boolean IS_TRUE) { + if (null == startFromZero) { + _startFromZero = IS_TRUE; + //setValue(IS_TRUE && getMinValue() < 0 ? 0 : getMinValue()); + fireUpdateEvent(REDRAW_EVENT); + } else { + startFromZero.set(IS_TRUE); + } + } + public BooleanProperty startFromZeroProperty() { + if (null == startFromZero) { + startFromZero = new BooleanPropertyBase(_startFromZero) { + @Override protected void invalidated() { + //Gauge.this.setValue((get() && getMinValue() < 0) ? 0 : getMinValue()); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "startFromZero"; } + }; + } + return startFromZero; + } + + /** + * Returns true if the needle/bar should always return to zero. This setting + * only makes sense if animated == true and the data rate is not too high. + * Set to false when using real measured live data. + * + * @return true if the needle/bar should always return to zero. + */ + public boolean isReturnToZero() { return null == returnToZero ? _returnToZero : returnToZero.get(); } + /** + * Defines the behavior of the visualization where the needle/bar should + * always return to 0 after it reached the final value. This setting only makes + * sense if animated == true and the data rate is not too high. + * Set to false when using real measured live data. + * + * @param IS_TRUE + */ + public void setReturnToZero(final boolean IS_TRUE) { + if (null == returnToZero) { + _returnToZero = Double.compare(getMinValue(), 0.0) <= 0 ? IS_TRUE : false; + fireUpdateEvent(REDRAW_EVENT); + } else { + returnToZero.set(IS_TRUE); + } + } + public BooleanProperty returnToZeroProperty() { + if (null == returnToZero) { + returnToZero = new BooleanPropertyBase(_returnToZero) { + @Override protected void invalidated() { + if (Double.compare(getMaxValue(), 0.0) > 0) set(false); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "returnToZero"; } + }; + } + return returnToZero; + } + + /** + * Returns the color that will be used to colorize the 0 tickmark and ticklabel + * when the gauge range has a negative min- and positive maxValue. + * + * @return the color that will used to visualize the 0 tickmark and ticklabel + */ + public Color getZeroColor() { return null == zeroColor ? _zeroColor : zeroColor.get(); } + /** + * Defines the color that will be used to colorize the 0 tickmark and ticklabel + * when the gauge range has a negative min- and positive maxValue. + * + * @param COLOR + */ + public void setZeroColor(final Color COLOR) { + if (null == zeroColor) { + _zeroColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + zeroColor.set(COLOR); + } + } + public ObjectProperty zeroColorProperty() { + if (null == zeroColor) { + zeroColor = new ObjectPropertyBase(_zeroColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "zeroColor"; } + }; + _zeroColor = null; + } + return zeroColor; + } + + /** + * Returns the smallest value that was measured after the last reset. + * The default value is the maxValue of the gauge. + * + * @return the smallest value that was measured after the last reset + */ + public double getMinMeasuredValue() { return null == minMeasuredValue ? _minMeasuredValue : minMeasuredValue.get(); } + /** + * Sets the minMeasuredValue to the given value. + * + * @param MIN_MEASURED_VALUE + */ + public void setMinMeasuredValue(final double MIN_MEASURED_VALUE) { + if (null == minMeasuredValue) { + _minMeasuredValue = MIN_MEASURED_VALUE; + } else { + minMeasuredValue.set(MIN_MEASURED_VALUE); + } + } + public ReadOnlyDoubleProperty minMeasuredValueProperty() { + if (null == minMeasuredValue) { minMeasuredValue = new SimpleDoubleProperty(this, "minMeasuredValue", _minMeasuredValue); } + return minMeasuredValue; + } + + /** + * Returns the biggest value that was measured after the last reset. + * The default value is the minValue of the gauge. + * + * @return the biggest value that was measured after the last reset + */ + public double getMaxMeasuredValue() { + return null == maxMeasuredValue ? _maxMeasuredValue : maxMeasuredValue.get(); + } + /** + * Sets the maxMeasuredVAlue to the given value. + * + * @param MAX_MEASURED_VALUE + */ + public void setMaxMeasuredValue(final double MAX_MEASURED_VALUE) { + if (null == maxMeasuredValue) { + _maxMeasuredValue = MAX_MEASURED_VALUE; + } else { + maxMeasuredValue.set(MAX_MEASURED_VALUE); + } + } + public ReadOnlyDoubleProperty maxMeasuredValueProperty() { + if (null == maxMeasuredValue) { maxMeasuredValue = new SimpleDoubleProperty(this, "maxMeasuredValue", _maxMeasuredValue); } + return maxMeasuredValue; + } + + /** + * Resets the min- and maxMeasuredValue to the value of the gauge. + */ + public void resetMeasuredValues() { + setMinMeasuredValue(getValue()); + setMaxMeasuredValue(getValue()); + } + + /** + * Returns true if the indicator of the minMeasuredValue is visible. + * + * @return true if the indicator of the minMeasuredValue is visible + */ + public boolean isMinMeasuredValueVisible() { return null == minMeasuredValueVisible ? _minMeasuredValueVisible : minMeasuredValueVisible.get(); } + /** + * Defines if the indicator of the minMeasuredValue should be visible. + * + * @param VISIBLE + */ + public void setMinMeasuredValueVisible(final boolean VISIBLE) { + if (null == minMeasuredValueVisible) { + _minMeasuredValueVisible = VISIBLE; + fireUpdateEvent(VISIBILITY_EVENT); + } else { + minMeasuredValueVisible.set(VISIBLE); + } + } + public BooleanProperty minMeasuredValueVisibleProperty() { + if (null == minMeasuredValueVisible) { + minMeasuredValueVisible = new BooleanPropertyBase(_minMeasuredValueVisible) { + @Override protected void invalidated() { fireUpdateEvent(VISIBILITY_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "minMeasuredValueVisible"; } + }; + } + return minMeasuredValueVisible; + } + + /** + * Returns true if the indicator of the maxMeasuredValue is visible. + * + * @return true if the indicator of the maxMeasuredValue is visible + */ + public boolean isMaxMeasuredValueVisible() { return null == maxMeasuredValueVisible ? _maxMeasuredValueVisible : maxMeasuredValueVisible.get(); } + /** + * Defines if the indicator of the maxMeasuredValue should be visible. + * + * @param VISIBLE + */ + public void setMaxMeasuredValueVisible(final boolean VISIBLE) { + if (null == maxMeasuredValueVisible) { + _maxMeasuredValueVisible = VISIBLE; + fireUpdateEvent(VISIBILITY_EVENT); + } else { + maxMeasuredValueVisible.set(VISIBLE); + } + } + public BooleanProperty maxMeasuredValueVisibleProperty() { + if (null == maxMeasuredValueVisible) { + maxMeasuredValueVisible = new BooleanPropertyBase(_maxMeasuredValueVisible) { + @Override protected void invalidated() { fireUpdateEvent(VISIBILITY_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "maxMeasuredValueVisible"; } + }; + } + return maxMeasuredValueVisible; + } + + /** + * Returns true if the old value of the gauge is visible (not implemented) + * + * @return true if the old value of the gauge is visible (not implemented) + */ + public boolean isOldValueVisible() { return null == oldValueVisible ? _oldValueVisible : oldValueVisible.get(); } + /** + * Defines if the old value of the gauge should be visible (not implemented) + * + * @param VISIBLE + */ + public void setOldValueVisible(final boolean VISIBLE) { + if (null == oldValueVisible) { + _oldValueVisible = VISIBLE; + fireUpdateEvent(VISIBILITY_EVENT); + } else { + oldValueVisible.set(VISIBLE); + } + } + public BooleanProperty oldValueVisibleProperty() { + if (null == oldValueVisible) { + oldValueVisible = new BooleanPropertyBase(_oldValueVisible) { + @Override protected void invalidated() { fireUpdateEvent(VISIBILITY_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "oldValueVisible"; } + }; + } + return oldValueVisible; + } + + /** + * Returns true if the visualization of the gauge value is visible. + * Usually this is a Label or Text node. + * + * @return true if the visualization of the gauge value is visible + */ + public boolean isValueVisible() { return null == valueVisible ? _valueVisible : valueVisible.get(); } + /** + * Defines if the visualization of the gauge value should be visible. + * + * @param VISIBLE + */ + public void setValueVisible(final boolean VISIBLE) { + if (null == valueVisible) { + _valueVisible = VISIBLE; + fireUpdateEvent(VISIBILITY_EVENT); + } else { + valueVisible.set(VISIBLE); + } + } + public BooleanProperty valueVisibleProperty() { + if (null == valueVisible) { + valueVisible = new BooleanPropertyBase(_valueVisible) { + @Override protected void invalidated() { fireUpdateEvent(VISIBILITY_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "valueVisible"; } + }; + } + return valueVisible; + } + + /** + * Returns the Paint object that will be used to fill the gauge background. + * This is usally a Color object. + * + * @return the Paint object that will be used to fill the gauge background + */ + public Paint getBackgroundPaint() { return null == backgroundPaint ? _backgroundPaint : backgroundPaint.get(); } + /** + * Defines the Paint object that will be used to fill the gauge background. + * + * @param PAINT + */ + public void setBackgroundPaint(final Paint PAINT) { + if (null == backgroundPaint) { + _backgroundPaint = PAINT; + fireUpdateEvent(REDRAW_EVENT); + } else { + backgroundPaint.set(PAINT); + } + } + public ObjectProperty backgroundPaintProperty() { + if (null == backgroundPaint) { + backgroundPaint = new ObjectPropertyBase(_backgroundPaint) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "backgroundPaint"; } + }; + _backgroundPaint = null; + } + return backgroundPaint; + } + + /** + * Returns the Paint object that will be used to draw the border of the gauge. + * Usually this is a Color object. + * + * @return the Paint object that will be used to draw the border of the gauge + */ + public Paint getBorderPaint() { return null == borderPaint ? _borderPaint : borderPaint.get(); } + /** + * Defines the Paint object that will be used to draw the border of the gauge. + * + * @param PAINT + */ + public void setBorderPaint(final Paint PAINT) { + if (null == borderPaint) { + _borderPaint = PAINT; + fireUpdateEvent(REDRAW_EVENT); + } else { + borderPaint.set(PAINT); + } + } + public ObjectProperty borderPaintProperty() { + if (null == borderPaint) { + borderPaint = new ObjectPropertyBase(_borderPaint) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "borderPaint"; } + }; + _borderPaint = null; + } + return borderPaint; + } + + /** + * Returns the width in pixels that will be used to draw the border of the gauge. + * The value will be clamped between 0 and 50 pixels. + * + * @return the width in pixels that will be used to draw the border of the gauge + */ + public double getBorderWidth() { return null == borderWidth ? _borderWidth : borderWidth.get(); } + /** + * Defines the width in pixels that will be used to draw the border of the gauge. + * The value will be clamped between 0 and 50 pixels. + * + * @param WIDTH + */ + public void setBorderWidth(final double WIDTH) { + if (null == borderWidth) { + _borderWidth = Helper.clamp(0.0, 50.0, WIDTH); + fireUpdateEvent(REDRAW_EVENT); + } else { + borderWidth.set(WIDTH); + } + } + public DoubleProperty borderWidthProperty() { + if (null == borderWidth) { + borderWidth = new DoublePropertyBase(_borderWidth) { + @Override protected void invalidated() { + final double WIDTH = get(); + if (WIDTH < 0 || WIDTH > 50) set(Helper.clamp(0.0, 50.0, WIDTH)); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "borderWidth"; } + }; + } + return borderWidth; + } + + /** + * Returns the Paint object that will be used to fill the foreground of the gauge. + * This could be used to visualize glass effects etc. and is only rarely used. + * + * @return the Paint object that will be used to fill the foreground of the gauge + */ + public Paint getForegroundPaint() { return null == foregroundPaint ? _foregroundPaint : foregroundPaint.get(); } + /** + * Defines the Paint object that will be used to fill the foreground of the gauge. + * This could be used to visualize glass effects etc. and is only rarely used. + * + * @param PAINT + */ + public void setForegroundPaint(final Paint PAINT) { + if (null == foregroundPaint) { + _foregroundPaint = PAINT; + fireUpdateEvent(REDRAW_EVENT); + } else { + foregroundPaint.set(PAINT); + } + } + public ObjectProperty foregroundPaintProperty() { + if (null == foregroundPaint) { + foregroundPaint = new ObjectPropertyBase(_foregroundPaint) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "foregroundPaint"; } + }; + _foregroundPaint = null; + } + return foregroundPaint; + } + + /** + * Returns the color that will be used to colorize the knob of + * the radial gauges. + * + * @return the color that will be used to colorize the knob of the radial gauges + */ + public Color getKnobColor() { return null == knobColor ? _knobColor : knobColor.get(); } + /** + * Defines the color that will be used to colorize the knob of + * the radial gauges. + * + * @param COLOR + */ + public void setKnobColor(final Color COLOR) { + if (null == knobColor) { + _knobColor = COLOR; + fireUpdateEvent(RESIZE_EVENT); + } else { + knobColor.set(COLOR); + } + } + public ObjectProperty knobColorProperty() { + if (null == knobColor) { + knobColor = new ObjectPropertyBase(_knobColor) { + @Override protected void invalidated() { fireUpdateEvent(RESIZE_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "knobColor"; } + }; + _knobColor = null; + } + return knobColor; + } + + /** + * Returns the type of knob that will be used in the radial + * gauges. The values are STANDARD, PLAIN, METAL and FLAT. + * + * @return the type of knob that will be used in the radial gauges + */ + public KnobType getKnobType() { return null == knobType ? _knobType : knobType.get(); } + /** + * Defines the type of knob that will be used in the radial + * gauges. The values are STANDARD, PLAIN, METAL and FLAT. + * + * @param TYPE + */ + public void setKnobType(final KnobType TYPE) { + if (null == knobType) { + _knobType = null == TYPE ? KnobType.STANDARD : TYPE; + fireUpdateEvent(RESIZE_EVENT); + } else { + knobType.set(TYPE); + } + } + public ObjectProperty knobTypeProperty() { + if (null == knobType) { + knobType = new ObjectPropertyBase(_knobType) { + @Override protected void invalidated() { + if (null == get()) set(KnobType.STANDARD); + fireUpdateEvent(RESIZE_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "knobType"; } + }; + _knobType = null; + } + return knobType; + } + + /** + * Returns the position of the knob in radial gauges. This + * position also defines where the needle will be placed. + * Dependent on the SkinType you can use the following values + * GaugeSkin : CENTER + * HSkin : TOP_CENTER, BOTTOM_CENTER + * VSkin : CENTER_LEFT, CENTER_RIGHT + * QuarterSkin: TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, TOP_LEFT + * + * @return the position of the knob in the radial gauges + */ + public Pos getKnobPosition() { return null == knobPosition ? _knobPosition : knobPosition.get(); } + /** + * Defines the position of the knob in radial gauges. This + * position also defines where the needle will be placed. + * Dependent on the SkinType you can use the following values + * GaugeSkin : CENTER + * HSkin : TOP_CENTER, BOTTOM_CENTER + * VSkin : CENTER_LEFT, CENTER_RIGHT + * QuarterSkin: TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, TOP_LEFT + * + * @param POSITION + */ + public void setKnobPosition(final Pos POSITION) { + if (null == knobPosition) { + _knobPosition = POSITION; + fireUpdateEvent(RESIZE_EVENT); + } else { + knobPosition.set(POSITION); + } + } + public ObjectProperty knobPositionProperty() { + if (null == knobPosition) { + knobPosition = new ObjectPropertyBase(_knobPosition) { + @Override protected void invalidated() { + final Pos POSITION = get(); + if (null == POSITION) { + switch (skinType) { + case HORIZONTAL: super.set(Pos.CENTER_RIGHT); break; + case VERTICAL : super.set(Pos.BOTTOM_CENTER); break; + case QUARTER : super.set(Pos.BOTTOM_RIGHT); break; + default : super.set(Pos.CENTER); + } + } + fireUpdateEvent(RESIZE_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "knobPosition"; } + }; + _knobPosition = null; + } + return knobPosition; + } + + /** + * Returns true if the knob is visible. + * + * @return true if the knob is visible + */ + public boolean isKnobVisible() { return null == knobVisible ? _knobVisible : knobVisible.get(); } + /** + * Defines if the knob is visible. + * + * @param VISIBLE + */ + public void setKnobVisible(final boolean VISIBLE) { + if (null == knobVisible) { + _knobVisible = VISIBLE; + fireUpdateEvent(VISIBILITY_EVENT); + } else { + knobVisible.set(VISIBLE); + } + } + public BooleanProperty knobVisibleProperty() { + if (null == knobVisible) { + knobVisible = new BooleanPropertyBase(_knobVisible) { + @Override protected void invalidated() { fireUpdateEvent(VISIBILITY_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "knobVisible"; } + }; + } + return knobVisible; + } + + /** + * Returns true if setting the value of the gauge will be animated + * using the duration defined in animationDuration [ms]. + * Keep in mind that it only makes sense to animate the setting if + * the data rate is low (more than 1 value per second). If you use real + * live measured data you should set animated to false. + * + * @return true if setting the value of the gauge will be animated + */ + public boolean isAnimated() { return null == animated ? _animated : animated.get(); } + /** + * Defines if setting the value of the gauge should be animated using + * the duration defined in animationDuration [ms]. + * Keep in mind that it only makes sense to animate the setting if + * the data rate is low (more than 1 value per second). If you use real + * live measured data you should set animated to false. + * + * @param ANIMATED + */ + public void setAnimated(final boolean ANIMATED) { + if (null == animated) { + _animated = ANIMATED; + } else { + animated.set(ANIMATED); + } + } + public BooleanProperty animatedProperty() { + if (null == animated) { animated = new SimpleBooleanProperty(Gauge.this, "animated", _animated); } + return animated; + } + + /** + * Returns the duration in milliseconds that will be used to animate + * the needle/bar of the gauge from the last value to the next value. + * This will only be used if animated == true. This value will be + * clamped in the range of 10ms - 10s. + * + * @return the duration in ms that will be used to animate the needle/bar + */ + public long getAnimationDuration() { return animationDuration; } + /** + * Defines the duration in milliseconds that will be used to animate + * the needle/bar of the gauge from the last value to the next value. + * This will only be used if animated == true. This value will be + * clamped in the range of 10ms - 10s. + * + * @param ANIMATION_DURATION + */ + public void setAnimationDuration(final long ANIMATION_DURATION) { animationDuration = Helper.clamp(10, 10000, ANIMATION_DURATION); } + + /** + * Returns the angle in degree that defines the start of the scale with + * it's minValue in a radial gauge. If set to 0 the scale will start at + * the bottom center and the direction of counting is mathematical correct + * counter-clockwise. + * Means if you would like to start the scale on the left side in the + * middle of the gauge height the startAngle should be set to 270 degrees. + * + * @return the angle in degree that defines the start of the scale + */ + public double getStartAngle() { return null == startAngle ? _startAngle : startAngle.get(); } + /** + * Defines the angle in degree that defines the start of the scale with + * it's minValue in a radial gauge. If set to 0 the scale will start at + * the bottom center and the direction of counting is mathematical correct + * counter-clockwise. + * Means if you would like to start the scale on the left side in the + * middle of the gauge height the startAngle should be set to 270 degrees. + * + * @param ANGLE + */ + public void setStartAngle(final double ANGLE) { + if (null == startAngle) { + _startAngle = Helper.clamp(0.0, 360.0, ANGLE); + fireUpdateEvent(RECALC_EVENT); + } else { + startAngle.set(ANGLE); + } + } + public DoubleProperty startAngleProperty() { + if (null == startAngle) { + startAngle = new DoublePropertyBase(_startAngle) { + @Override protected void invalidated() { + final double ANGLE = get(); + if (ANGLE < 0 || ANGLE > 360 ) set(Helper.clamp(0.0, 360.0, ANGLE)); + fireUpdateEvent(RECALC_EVENT); + } + @Override public Object getBean() { return this; } + @Override public String getName() { return "startAngle"; } + }; + } + return startAngle; + } + + /** + * Returns the angle range in degree that will be used to draw the scale + * of the radial gauge. The given range will be clamped in the range of + * 0 - 360 degrees and will be drawn in the direction dependent on the + * scaleDirection. + * + * @return the angle range in degree that will be used to draw the scale + */ + public double getAngleRange() { return null == angleRange ? _angleRange : angleRange.get(); } + /** + * Defines the angle range in degree that will be used to draw the scale + * of the radial gauge. The given range will be clamped in the range of + * 0 - 360 degrees. The range will start at the startAngle and will be + * drawn in the direction dependent on the scaleDirection. + * + * @param RANGE + */ + public void setAngleRange(final double RANGE) { + double tmpAngleRange = Helper.clamp(0.0, 360.0, RANGE); + if (null == angleRange) { + _angleRange = tmpAngleRange; + setAngleStep(tmpAngleRange / getRange()); + if (isAutoScale()) { calcAutoScale(); } + fireUpdateEvent(RECALC_EVENT); + } else { + angleRange.set(tmpAngleRange); + } + } + public DoubleProperty angleRangeProperty() { + if (null == angleRange) { + angleRange = new DoublePropertyBase(_angleRange) { + @Override protected void invalidated() { + final double ANGLE_RANGE = get(); + set(Helper.clamp(0.0, 360.0, ANGLE_RANGE)); + setAngleStep(get() / getRange()); + if (isAutoScale()) { calcAutoScale(); } + fireUpdateEvent(RECALC_EVENT); + } + @Override public Object getBean() { return this; } + @Override public String getName() { return "angleRange"; } + }; + } + return angleRange; + } + + /** + * Returns the value that is calculated by dividing the angleRange + * by the range. The angleStep will always be recalculated when changing + * the min-, maxValue or angleRange. + * E.g. angleRange = 180 degrees, range = 0 - 100 will lead to angleStep = 180/100 = 1.8 + * + * @return the value that is calculated by dividing the angleRange by the range + */ + public double getAngleStep() { return null == angleStep ? _angleStep : angleStep.get(); } + /** + * Private method that will be used to set the angleStep + * + * @param STEP + */ + private void setAngleStep(final double STEP) { + if (null == angleStep) { + _angleStep = STEP; + } else { + angleStep.set(STEP); + } + } + public ReadOnlyDoubleProperty angleStepProperty() { + if (null == angleStep) { angleStep = new SimpleDoubleProperty(Gauge.this, "angleStep", _angleStep); } + return angleStep; + } + + /** + * Returns the distance between the segments in the SIMPLE_DIGITAL skin. + * @return the distance between the segments in the SIMPLE_DIGITAL skin. + */ + public double getArcExtend() { return null == arcExtend ? _arcExtend : arcExtend.get(); } + /** + * Defines the distance between the segments in the SIMPLE_DIGITAL_SKIN + * @param ARC_EXTEND + */ + public void setArcExtend(final double ARC_EXTEND) { + if (null == arcExtend) { + _arcExtend = Helper.clamp(0.1, 10, ARC_EXTEND); + fireUpdateEvent(REDRAW_EVENT); + } else { + arcExtend.set(ARC_EXTEND); + } + } + public DoubleProperty arcExtendProperty() { + if (null == arcExtend) { + arcExtend = new DoublePropertyBase(_arcExtend) { + @Override protected void invalidated() { + set(Helper.clamp(0.1, 10, get())); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "arcExtend"; } + }; + } + return arcExtend; + } + + /** + * Returns true if the scale will be calculated automatically based + * on the defined values for min- and maxValue. + * The autoscaling is on per default because otherwise you will + * run into problems when having very large or very small scales like + * 0 - 10000 or 0 - 1. + * + * @return true if the scale will be calculated automatically + */ + public boolean isAutoScale() { return null == autoScale ? _autoScale : autoScale.get(); } + /** + * Defines if the scale should be calculated automatically based on + * the defined values for min- and maxValue. + * The autoscaling is on per default because otherwise you will + * run into problems when having very large or very small scales like + * 0 - 10000 or 0 - 1. + * + * @param AUTO_SCALE + */ + public void setAutoScale(final boolean AUTO_SCALE) { + if (null == autoScale) { + _autoScale = AUTO_SCALE; + if (_autoScale) { + originalMinValue = getMinValue(); + originalMaxValue = getMaxValue(); + calcAutoScale(); + } else { + setMinValue(Double.compare(-Double.MAX_VALUE, originalMinValue) == 0 ? getMinValue() : originalMinValue); + setMaxValue(Double.compare(Double.MAX_VALUE, originalMaxValue) == 0 ? getMaxValue() : originalMaxValue); + } + fireUpdateEvent(RECALC_EVENT); + } else { + autoScale.set(AUTO_SCALE); + } + } + public BooleanProperty autoScaleProperty() { + if (null == autoScale) { + autoScale = new BooleanPropertyBase(_autoScale) { + @Override protected void invalidated() { + if (get()) { + calcAutoScale(); + } else { + setMinValue(Double.compare(-Double.MAX_VALUE, originalMinValue) == 0 ? getMinValue() : originalMinValue); + setMaxValue(Double.compare(Double.MAX_VALUE, originalMaxValue) == 0 ? getMaxValue() : originalMaxValue); + } + fireUpdateEvent(RECALC_EVENT); + } + @Override public Object getBean() { return this; } + @Override public String getName() { return "autoScale"; } + }; + } + return autoScale; + } + + /** + * Returns true if effects like shadows will be drawn. + * In some gauges inner- and dropshadows will be used which will be + * switched on/off by setting the shadowsEnabled property. + * + * @return true if effects like shadows will be drawn + */ + public boolean isShadowsEnabled() { return null == shadowsEnabled ? _shadowsEnabled : shadowsEnabled.get(); } + /** + * Defines if effects like shadows should be drawn. + * In some gauges inner- and dropshadows will be used which will be + * switched on/off by setting the shadowsEnabled property. + * + * @param ENABLED + */ + public void setShadowsEnabled(final boolean ENABLED) { + if (null == shadowsEnabled) { + _shadowsEnabled = ENABLED; + fireUpdateEvent(REDRAW_EVENT); + } else { + shadowsEnabled.set(ENABLED); + } + } + public BooleanProperty shadowsEnabledProperty() { + if (null == shadowsEnabled) { + shadowsEnabled = new BooleanPropertyBase(_shadowsEnabled) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "shadowsEnabled"; } + }; + } + return shadowsEnabled; + } + + /** + * Returns true if the highlight effect on the gauges like the + * LinearSkin bar will be drawn. If you would like to have a + * more flat style you should set this to false. + * + * @return true if the highlight effect on a bar will be drawn + */ + public boolean isBarEffectEnabled() { return null == barEffectEnabled ? _barEffectEnabled : barEffectEnabled.get(); } + /** + * Defines if the the highlight effect on the gauges like the + * LinearSkin bar will be drawn. If you would like to have a + * more flat style you should set this to false. + * + * @param ENABLED + */ + public void setBarEffectEnabled(final boolean ENABLED) { + if (null == barEffectEnabled) { + _barEffectEnabled = ENABLED; + fireUpdateEvent(VISIBILITY_EVENT); + } else { + barEffectEnabled.set(ENABLED); + } + } + public BooleanProperty barEffectEnabledProperty() { + if (null == barEffectEnabled) { + barEffectEnabled = new BooleanPropertyBase(_barEffectEnabled) { + @Override protected void invalidated() { fireUpdateEvent(VISIBILITY_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "barEffectEnabled"; } + }; + } + return barEffectEnabled; + } + + /** + * Returns the direction of the scale. The values are + * CLOCKWISE and COUNTER_CLOCKWISE. This property is needed + * to realize gauges like in QuarterSkin where the needle + * and knob should be placed on the upper right corner and + * the scale should start at the bottom. Here you need a + * counter-clockwise direction of the scale. + * + * @return the direction of the scale + */ + public ScaleDirection getScaleDirection() { return null == scaleDirection ? _scaleDirection : scaleDirection.get(); } + /** + * Defines the direction of the scale. The values are + * CLOCKWISE and COUNTER_CLOCKWISE. This property is needed + * to realize gauges like in QuarterSkin where the needle + * and knob should be placed on the upper right corner and + * the scale should start at the bottom. Here you need a + * counter-clockwise direction of the scale. + * + * @param DIRECTION + */ + public void setScaleDirection(final ScaleDirection DIRECTION) { + if (null == scaleDirection) { + _scaleDirection = null == DIRECTION ? ScaleDirection.CLOCKWISE : DIRECTION; + fireUpdateEvent(RECALC_EVENT); + } else { + scaleDirection.set(DIRECTION); + } + } + public ObjectProperty scaleDirectionProperty() { + if (null == scaleDirection) { + scaleDirection = new ObjectPropertyBase(_scaleDirection) { + @Override protected void invalidated() { + if (null == get()) set(ScaleDirection.CLOCKWISE); + fireUpdateEvent(RECALC_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "scaleDirection"; } + }; + _scaleDirection = null; + } + return scaleDirection; + } + + /** + * Returns the location of the ticklabels. The values are + * INSIDE and OUTSIDE. The location of the ticklabels has an + * influence on the size of the tickmarks and length of the needle. + * + * @return the location of the ticklabels + */ + public TickLabelLocation getTickLabelLocation() { return null == tickLabelLocation ? _tickLabelLocation : tickLabelLocation.get(); } + /** + * Defines the location of the ticklabels. The values are + * INSIDE and OUTSIDE. The location of the ticklabels has an + * influence on the size of the tickmarks and length of the needle. + * + * @param LOCATION + */ + public void setTickLabelLocation(final TickLabelLocation LOCATION) { + if (null == tickLabelLocation) { + _tickLabelLocation = null == LOCATION ? TickLabelLocation.INSIDE : LOCATION; + fireUpdateEvent(REDRAW_EVENT); + } else { + tickLabelLocation.set(LOCATION); + } + } + public ObjectProperty tickLabelLocationProperty() { + if (null == tickLabelLocation) { + tickLabelLocation = new ObjectPropertyBase(_tickLabelLocation) { + @Override protected void invalidated() { + if(null == get()) set(TickLabelLocation.INSIDE); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "tickLabelLocation"; } + }; + _tickLabelLocation = null; + } + return tickLabelLocation; + } + + /** + * Returns the orientation of the ticklabels. The values are + * HORIZONTAL, ORTHOGONAL and TANGENT. Especially the ORTHOGONAL + * setting can be useful when using scales with big numbers. + * + * @return the orientation of the ticklabels + */ + public TickLabelOrientation getTickLabelOrientation() { return null == tickLabelOrientation ? _tickLabelOrientation : tickLabelOrientation.get(); } + /** + * Defines the orientation of the ticklabels. The values are + * HORIZONTAL, ORTHOGONAL and TANGENT. Especially the ORTHOGONAL + * setting can be useful when using scales with big numbers. + * + * @param ORIENTATION + */ + public void setTickLabelOrientation(final TickLabelOrientation ORIENTATION) { + if (null == tickLabelOrientation) { + _tickLabelOrientation = null == ORIENTATION ? TickLabelOrientation.HORIZONTAL : ORIENTATION; + fireUpdateEvent(REDRAW_EVENT); + } else { + tickLabelOrientation.set(ORIENTATION); + } + } + public ObjectProperty tickLabelOrientationProperty() { + if (null == tickLabelOrientation) { + tickLabelOrientation = new ObjectPropertyBase(_tickLabelOrientation) { + @Override protected void invalidated() { + if(null == get()) set(TickLabelOrientation.HORIZONTAL); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "tickLabelOrientation"; } + }; + _tickLabelOrientation = null; + } + return tickLabelOrientation; + } + + /** + * Returns the color that will be used to colorize the ticklabels. This color + * will only be used if no ticklabel section defines a different color. + * + * @return the color that will be used to colorize the ticklabels + */ + public Color getTickLabelColor() { return null == tickLabelColor ? _tickLabelColor : tickLabelColor.get(); } + /** + * Defines the color that will be used to colorize the ticklabels. This color + * will only be used if no ticklabel section defines a different color. + * + * @param COLOR + */ + public void setTickLabelColor(final Color COLOR) { + if (null == tickLabelColor) { + _tickLabelColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + tickLabelColor.set(COLOR); + } + } + public ObjectProperty tickLabelColorProperty() { + if (null == tickLabelColor) { + tickLabelColor = new ObjectPropertyBase(_tickLabelColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "tickLabelColor"; } + }; + _tickLabelColor = null; + } + return tickLabelColor; + } + + /** + * Returns the color that will be used to colorize the tickmarks. This color + * will only be used if no tickmark section or major-, medium- and minorTickMarkColor + * is defined at the position of the tickmark. + * + * @return the color that will be used to colorize the tickmarks + */ + public Color getTickMarkColor() { return null == tickMarkColor ? _tickMarkColor : tickMarkColor.get(); } + /** + * Defines the color that will be used to colorize the tickmarks. This color + * will only be used if no tickmark section or major-, medium- and minorTickMarkColor + * is defined at the position of the tickmark. + * + * @param COLOR + */ + public void setTickMarkColor(final Color COLOR) { + if (null == tickMarkColor) { + _tickMarkColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + tickMarkColor.set(COLOR); + } + } + public ObjectProperty tickMarkColorProperty() { + if (null == tickMarkColor) { + tickMarkColor = new ObjectPropertyBase(_tickMarkColor) { + @Override protected void invalidated() { fireUpdateEvent( REDRAW_EVENT ); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "tickMarkColor"; } + }; + _tickMarkColor = null; + } + return tickMarkColor; + } + + /** + * Returns the color that will be used to colorize the major + * tickmarks. This color will only be used if no tickmark + * section is defined at the position of the tickmark. + * + * @return the color that will be used to colorize the major tickmarks + */ + public Color getMajorTickMarkColor() { return null == majorTickMarkColor ? _majorTickMarkColor : majorTickMarkColor.get(); } + /** + * Defines the color that will be used to colorize the major + * tickmarks. This color will only be used if no tickmark + * section is defined at the position of the tickmark. + * + * @param COLOR + */ + public void setMajorTickMarkColor(final Color COLOR) { + if (null == majorTickMarkColor) { + _majorTickMarkColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + majorTickMarkColor.set(COLOR); + } + } + public ObjectProperty majorTickMarkColorProperty() { + if (null == majorTickMarkColor) { + majorTickMarkColor = new ObjectPropertyBase(_majorTickMarkColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "majorTickMarkColor"; } + }; + _majorTickMarkColor = null; + } + return majorTickMarkColor; + } + + /** + * Returns the factor that defines the length of the major tick mark. + * The value can be in the range from 0 - 1; + * + * @return the factor that defines the length of the major tick mark + */ + public double getMajorTickMarkLengthFactor() { return null == majorTickMarkLengthFactor ? _majorTickMarkLengthFactor : majorTickMarkLengthFactor.get(); } + /** + * The factor defines the length of the major tick mark. + * It can be in the range from 0 - 1. + * + * @param FACTOR + */ + public void setMajorTickMarkLengthFactor(final double FACTOR) { + if (null == majorTickMarkLengthFactor) { + _majorTickMarkLengthFactor = Helper.clamp(0.0, 1.0, FACTOR); + fireUpdateEvent(REDRAW_EVENT); + } else { + majorTickMarkLengthFactor.set(FACTOR); + } + } + public DoubleProperty majorTickMarkLengthFactorProperty() { + if (null == majorTickMarkLengthFactor) { + majorTickMarkLengthFactor = new DoublePropertyBase(_majorTickMarkLengthFactor) { + @Override protected void invalidated() { + final double VALUE = get(); + if (VALUE < 0 || VALUE > 1) set(Helper.clamp(0.0, 1.0, VALUE)); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "majorTickMarkLengthFactor"; } + }; + } + return majorTickMarkLengthFactor; + } + + /** + * Returns the factor that defines the width of the major tick mark. + * The value can be in the range from 0 - 1. + * + * @return the factor that defines the width of the major tick mark + */ + public double getMajorTickMarkWidthFactor() { return null == majorTickMarkWidthFactor ? _majorTickMarkWidthFactor : majorTickMarkWidthFactor.get(); } + /** + * The factor defines the width of the major tick mark. + * It can be in the range from 0 - 1. + * + * @param FACTOR + */ + public void setMajorTickMarkWidthFactor(final double FACTOR) { + if (null == majorTickMarkWidthFactor) { + _majorTickMarkWidthFactor = Helper.clamp(0.0, 1.0, FACTOR); + fireUpdateEvent(REDRAW_EVENT); + } else { + majorTickMarkWidthFactor.set(FACTOR); + } + } + public DoubleProperty majorTickMarkWidthFactorProperty() { + if (null == majorTickMarkWidthFactor) { + majorTickMarkWidthFactor = new DoublePropertyBase(_majorTickMarkWidthFactor) { + @Override protected void invalidated() { + final double VALUE = get(); + if (VALUE < 0 || VALUE > 1) set(Helper.clamp(0.0, 1.0, VALUE)); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "majorTickMarkWidthFactor"; } + }; + } + return majorTickMarkWidthFactor; + } + + /** + * Returns the color that will be used to colorize the medium + * tickmarks. This color will only be used if no tickmark + * section is defined at the position of the tickmark. + * + * @return the color that will be used to colorize the medium tickmark + */ + public Color getMediumTickMarkColor() { return null == mediumTickMarkColor ? _mediumTickMarkColor : mediumTickMarkColor.get(); } + /** + * Defines the color that will be used to colorize the medium + * tickmarks. This color will only be used if no tickmark + * section is defined at the position of the tickmark. + * + * @param COLOR + */ + public void setMediumTickMarkColor(final Color COLOR) { + if (null == mediumTickMarkColor) { + _mediumTickMarkColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + mediumTickMarkColor.set(COLOR); + } + } + public ObjectProperty mediumTickMarkColorProperty() { + if (null == mediumTickMarkColor) { + mediumTickMarkColor = new ObjectPropertyBase(_mediumTickMarkColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "mediumTickMarkColor"; } + }; + _mediumTickMarkColor = null; + } + return mediumTickMarkColor; + } + + /** + * Returns the factor that defines the length of the medium tick mark. + * The value can be in the range from 0 - 1; + * + * @return the factor that defines the length of the medium tick mark + */ + public double getMediumTickMarkLengthFactor() { return null == mediumTickMarkLengthFactor ? _mediumTickMarkLengthFactor : mediumTickMarkLengthFactor.get(); } + /** + * The factor defines the length of the medium tick mark. + * It can be in the range from 0 - 1. + * + * @param FACTOR + */ + public void setMediumTickMarkLengthFactor(final double FACTOR) { + if (null == mediumTickMarkLengthFactor) { + _mediumTickMarkLengthFactor = Helper.clamp(0.0, 1.0, FACTOR); + fireUpdateEvent(REDRAW_EVENT); + } else { + mediumTickMarkLengthFactor.set(FACTOR); + } + } + public DoubleProperty mediumTickMarkLengthFactorProperty() { + if (null == mediumTickMarkLengthFactor) { + mediumTickMarkLengthFactor = new DoublePropertyBase(_mediumTickMarkLengthFactor) { + @Override protected void invalidated() { + final double VALUE = get(); + if (VALUE < 0 || VALUE > 1) set(Helper.clamp(0.0, 1.0, VALUE)); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "mediumTickMarkLengthFactor"; } + }; + } + return mediumTickMarkLengthFactor; + } + + /** + * Returns the factor that defines the width of the medium tick mark. + * The value can be in the range from 0 - 1. + * + * @return the factor that defines the width of the medium tick mark + */ + public double getMediumTickMarkWidthFactor() { return null == mediumTickMarkWidthFactor ? _mediumTickMarkWidthFactor : mediumTickMarkWidthFactor.get(); } + /** + * The factor defines the width of the medium tick mark. + * It can be in the range from 0 - 1. + * + * @param FACTOR + */ + public void setMediumTickMarkWidthFactor(final double FACTOR) { + if (null == mediumTickMarkWidthFactor) { + _mediumTickMarkWidthFactor = Helper.clamp(0.0, 1.0, FACTOR); + fireUpdateEvent(REDRAW_EVENT); + } else { + mediumTickMarkWidthFactor.set(FACTOR); + } + } + public DoubleProperty mediumTickMarkWidthFactorProperty() { + if (null == mediumTickMarkWidthFactor) { + mediumTickMarkWidthFactor = new DoublePropertyBase(_mediumTickMarkWidthFactor) { + @Override protected void invalidated() { + final double VALUE = get(); + if (VALUE < 0 || VALUE > 1) set(Helper.clamp(0.0, 1.0, VALUE)); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "mediumTickMarkWidthFactor"; } + }; + } + return mediumTickMarkWidthFactor; + } + + /** + * Returns the color that will be used to colorize the minor + * tickmarks. This color will only be used if no tickmark + * section is defined at the position of the tickmark. + * + * @return the color that will be used to colorize the minor tickmark + */ + public Color getMinorTickMarkColor() { return null == minorTickMarkColor ? _minorTickMarkColor : minorTickMarkColor.get(); } + /** + * Defines the color that will be used to colorize the minor + * tickmarks. This color will only be used if no tickmark + * section is defined at the position of the tickmark. + * + * @param COLOR + */ + public void setMinorTickMarkColor(final Color COLOR) { + if (null == minorTickMarkColor) { + _minorTickMarkColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + minorTickMarkColor.set(COLOR); + } + } + public ObjectProperty minorTickMarkColorProperty() { + if (null == minorTickMarkColor) { + minorTickMarkColor = new ObjectPropertyBase(_minorTickMarkColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "minorTickMarkColor"; } + }; + _minorTickMarkColor = null; + } + return minorTickMarkColor; + } + + /** + * Returns the factor that defines the length of the minor tick mark. + * The value can be in the range from 0 - 1; + * + * @return the factor that defines the length of the minor tick mark + */ + public double getMinorTickMarkLengthFactor() { return null == minorTickMarkLengthFactor ? _minorTickMarkLengthFactor : minorTickMarkLengthFactor.get(); } + /** + * The factor defines the length of the minor tick mark. + * It can be in the range from 0 - 1. + * + * @param FACTOR + */ + public void setMinorTickMarkLengthFactor(final double FACTOR) { + if (null == minorTickMarkLengthFactor) { + _minorTickMarkLengthFactor = Helper.clamp(0.0, 1.0, FACTOR); + fireUpdateEvent(REDRAW_EVENT); + } else { + minorTickMarkLengthFactor.set(FACTOR); + } + } + public DoubleProperty minorTickMarkLengthFactorProperty() { + if (null == minorTickMarkLengthFactor) { + minorTickMarkLengthFactor = new DoublePropertyBase(_minorTickMarkLengthFactor) { + @Override protected void invalidated() { + final double VALUE = get(); + if (VALUE < 0 || VALUE > 1) set(Helper.clamp(0.0, 1.0, VALUE)); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "minorTickMarkLengthFactor"; } + }; + } + return minorTickMarkLengthFactor; + } + + /** + * Returns the factor that defines the width of the minor tick mark. + * The value can be in the range from 0 - 1. + * + * @return the factor that defines the width of the minor tick mark + */ + public double getMinorTickMarkWidthFactor() { return null == minorTickMarkWidthFactor ? _minorTickMarkWidthFactor : minorTickMarkWidthFactor.get(); } + /** + * The factor defines the width of the minor tick mark. + * It can be in the range from 0 - 1. + * + * @param FACTOR + */ + public void setMinorTickMarkWidthFactor(final double FACTOR) { + if (null == minorTickMarkWidthFactor) { + _minorTickMarkWidthFactor = Helper.clamp(0.0, 1.0, FACTOR); + fireUpdateEvent(REDRAW_EVENT); + } else { + minorTickMarkWidthFactor.set(FACTOR); + } + } + public DoubleProperty minorTickMarkWidthFactorProperty() { + if (null == minorTickMarkWidthFactor) { + minorTickMarkWidthFactor = new DoublePropertyBase(_minorTickMarkWidthFactor) { + @Override protected void invalidated() { + final double VALUE = get(); + if (VALUE < 0 || VALUE > 1) set(Helper.clamp(0.0, 1.0, VALUE)); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "minorTickMarkWidthFactor"; } + }; + } + return minorTickMarkWidthFactor; + } + + /** + * Returns the shape that will be used to visualize the major tickmark. + * Values are LINE, DOT, TRAPEZOID, BOX, TICK_LABEL and PILL + * + * @return the shape that will be used to visualize the major tickmark + */ + public TickMarkType getMajorTickMarkType() { return null == majorTickMarkType ? _majorTickMarkType : majorTickMarkType.get(); } + /** + * Defines the shape that will be used to visualize the major tickmark. + * Values are LINE, DOT, TRAPEZOID, BOX, TICK_LABEL and PILL + * + * @param TYPE + */ + public void setMajorTickMarkType(final TickMarkType TYPE) { + if (null == majorTickMarkType) { + _majorTickMarkType = null == TYPE ? TickMarkType.LINE : TYPE; + fireUpdateEvent(REDRAW_EVENT); + } else { + majorTickMarkType.set(TYPE); + } + } + public ObjectProperty majorTickMarkTypeProperty() { + if (null == majorTickMarkType) { + majorTickMarkType = new ObjectPropertyBase(_majorTickMarkType) { + @Override protected void invalidated() { + if (null == get()) set(TickMarkType.LINE); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "majorTickMarkType"; } + }; + _majorTickMarkType = null; + } + return majorTickMarkType; + } + + /** + * Returns the shape that will be used to visualize the medium tickmark. + * Values are LINE, DOT, TRAPEZOID, BOX and PILL + * + * @return the shape that will be used to visualize the medium tickmark + */ + public TickMarkType getMediumTickMarkType() { return null == mediumTickMarkType ? _mediumTickMarkType : mediumTickMarkType.get(); } + /** + * Defines the shape that will be used to visualize the medium tickmark. + * Values are LINE, DOT, TRAPEZOID, BOX and PILL + * + * @param TYPE + */ + public void setMediumTickMarkType(final TickMarkType TYPE) { + if (null == mediumTickMarkType) { + _mediumTickMarkType = null == TYPE ? TickMarkType.LINE : TYPE; + fireUpdateEvent(REDRAW_EVENT); + } else { + mediumTickMarkType.set(TYPE); + } + } + public ObjectProperty mediumTickMarkTypeProperty() { + if (null == mediumTickMarkType) { + mediumTickMarkType = new ObjectPropertyBase(_mediumTickMarkType) { + @Override protected void invalidated() { + if (null == get()) set(TickMarkType.LINE); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "mediumTickMarkType"; } + }; + _mediumTickMarkType = null; + } + return mediumTickMarkType; + } + + /** + * Returns the shape that will be used to visualize the minor tickmark. + * Values are LINE, DOT, TRAPEZOID, BOX and PILL + * + * @return the shape that will be used to visualize the minor tickmark + */ + public TickMarkType getMinorTickMarkType() { return null == minorTickMarkType ? _minorTickMarkType : minorTickMarkType.get(); } + /** + * Defines the shape that will be used to visualize the minor tickmark. + * Values are LINE, DOT, TRAPEZOID, BOX and PILL + * + * @param TYPE + */ + public void setMinorTickMarkType(final TickMarkType TYPE) { + if (null == minorTickMarkType) { + _minorTickMarkType = null == TYPE ? TickMarkType.LINE : TYPE; + fireUpdateEvent(REDRAW_EVENT); + } else { + minorTickMarkType.set(TYPE); + } + } + public ObjectProperty minorTickMarkTypeProperty() { + if (null == minorTickMarkType) { + minorTickMarkType = new ObjectPropertyBase(_minorTickMarkType) { + @Override protected void invalidated() { + if (null == get()) set(TickMarkType.LINE); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "minorTickMarkType"; } + }; + _minorTickMarkType = null; + } + return minorTickMarkType; + } + + public Locale getLocale() { return null == locale ? _locale : locale.get(); } + public void setLocale(final Locale LOCALE) { + if (null == locale) { + _locale = null == LOCALE ? Locale.US : LOCALE; + fireUpdateEvent(REDRAW_EVENT); + } else { + locale.set(LOCALE); + } + } + public ObjectProperty localeProperty() { + if (null == locale) { + locale = new ObjectPropertyBase(_locale) { + @Override protected void invalidated() { + if (null == get()) set(Locale.US); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "locale"; } + }; + _locale = null; + } + return locale; + } + + /** + * Returns the number of decimals that will be used to format the + * value of the gauge. The number of decimals will be clamped to + * a value between 0-3. + * + * @return the number of decimals that will be used to format the value + */ + public int getDecimals() { return null == decimals ? _decimals : decimals.get(); } + /** + * Defines the number of decimals that will be used to format the + * value of the gauge. The number of decimals will be clamped to + * a value between 0-3. + * + * @param DECIMALS + */ + public void setDecimals(final int DECIMALS) { + if (null == decimals) { + _decimals = Helper.clamp(0, MAX_NO_OF_DECIMALS, DECIMALS); + //updateFormatString(); + fireUpdateEvent(REDRAW_EVENT); + } else { + decimals.set(DECIMALS); + } + } + public IntegerProperty decimalsProperty() { + if (null == decimals) { + decimals = new IntegerPropertyBase(_decimals) { + @Override protected void invalidated() { + final int VALUE = get(); + if (VALUE < 0 || VALUE > MAX_NO_OF_DECIMALS) set(Helper.clamp(0, MAX_NO_OF_DECIMALS, VALUE)); + //updateFormatString(); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "decimals"; } + }; + } + return decimals; + } + + /** + * Returns the number of decimals that will be used to format the + * value of the ticklabels. The number of decimals will be clamped to + * a value between 0-3. + * + * @return + */ + public int getTickLabelDecimals() { return null == tickLabelDecimals ? _tickLabelDecimals : tickLabelDecimals.get(); } + /** + * Defines the number of decimals that will be used to format the + * value of the gauge. The number of decimals will be clamped to + * a value between 0-3. + * + * @param DECIMALS + */ + public void setTickLabelDecimals(final int DECIMALS) { + if (null == tickLabelDecimals) { + _tickLabelDecimals = Helper.clamp(0, MAX_NO_OF_DECIMALS, DECIMALS); + fireUpdateEvent(REDRAW_EVENT); + } else { + tickLabelDecimals.set(DECIMALS); + } + } + public IntegerProperty tickLabelDecimalsProperty() { + if (null == tickLabelDecimals) { + tickLabelDecimals = new IntegerPropertyBase(_tickLabelDecimals) { + @Override protected void invalidated() { + final int VALUE = get(); + if (VALUE < 0 || VALUE > MAX_NO_OF_DECIMALS) set(Helper.clamp(0, MAX_NO_OF_DECIMALS, VALUE)); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "tickLabelDecimals"; } + }; + } + return tickLabelDecimals; + } + + /** + * Returns the shape of the needle that will be used. This is + * dependent on the used SkinType. Values are + * GaugeSkin : STANDARD, FAT + * HSkin : STANDARD + * VSkin : STANDARD + * QuarterSkin: STANDARD + * + * @return the shape of the needle that will be used + */ + public NeedleType getNeedleType() { return null == needleType ? _needleType : needleType.get(); } + /** + * Defines the shape of the needle that will be used. This is + * dependent on the used SkinType. Values are + * GaugeSkin : STANDARD, FAT + * HSkin : STANDARD + * VSkin : STANDARD + * QuarterSkin: STANDARD + * + * @param TYPE + */ + public void setNeedleType(final NeedleType TYPE) { + if (null == needleType) { + _needleType = TYPE == null ? NeedleType.STANDARD : TYPE; + fireUpdateEvent(RESIZE_EVENT); + } else { + needleType.set(TYPE); + } + } + public ObjectProperty needleTypeProperty() { + if (null == needleType) { + needleType = new ObjectPropertyBase(_needleType) { + @Override protected void invalidated() { + if (null == get()) set(NeedleType.STANDARD); + fireUpdateEvent(RESIZE_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "needleType"; } + }; + _needleType = null; + } + return needleType; + } + + /** + * Returns the graphical representation of the needle that will be used. + * Values are ANGLED, ROUND and FLAT + * In principle it defines how the needle will be filled (gradient, color) + * + * @return the graphical representation of the needle + */ + public NeedleShape getNeedleShape() { return null == needleShape ? _needleShape : needleShape.get(); } + /** + * Defines the graphical representation of the needle that will be used. + * Values are ANGLED, ROUND and FLAT + * In principle it defines how the needle will be filled (gradient, color) + * + * @param SHAPE + */ + public void setNeedleShape(final NeedleShape SHAPE) { + if (null == needleShape) { + _needleShape = null == SHAPE ? NeedleShape.ANGLED : SHAPE; + fireUpdateEvent(REDRAW_EVENT); + } else { + needleShape.set(SHAPE); + } + } + public ObjectProperty needleShapeProperty() { + if (null == needleShape) { + needleShape = new ObjectPropertyBase(_needleShape) { + @Override protected void invalidated() { + if (null == get()) set(NeedleShape.ANGLED); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "needleShape"; } + }; + _needleShape = null; + } + return needleShape; + } + + /** + * Returns the thickness of the needle. + * The values are THIN, STANDARD and THICK + * + * @return the thickness of the needle + */ + public NeedleSize getNeedleSize() { return null == needleSize ? _needleSize : needleSize.get(); } + /** + * Defines the thickness of the needle. + * The values are THIN, STANDARD and THICK + * + * @param SIZE + */ + public void setNeedleSize(final NeedleSize SIZE) { + if (null == needleSize) { + _needleSize = null == SIZE ? NeedleSize.STANDARD : SIZE; + fireUpdateEvent(RESIZE_EVENT); + } else { + needleSize.set(SIZE); + } + } + public ObjectProperty needleSizeProperty() { + if (null == needleSize) { + needleSize = new ObjectPropertyBase(_needleSize) { + @Override protected void invalidated() { + if(null == get()) set(NeedleSize.STANDARD); + fireUpdateEvent(RESIZE_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "needleSize"; } + }; + _needleSize = null; + } + return needleSize; + } + + /** + * Returns the behavior of the needle movement. + * The values are STANDARD and OPTIMIZED + * This is an experimental feature that only makes sense in + * gauges that use an angleRange of 360 degrees and where the + * needle should be able to use the shortest way to the target + * value. As an example one can think of a compass. If the value + * in a compass changes from 20 degrees to 290 degrees the needle + * will take the shortest way to the value, in this case this + * means it will rotate counter-clockwise. + * + * @return the behavior of the needle movement (EXPERIMENTAL) + */ + public NeedleBehavior getNeedleBehavior() { return null == needleBehavior ? _needleBehavior : needleBehavior.get(); } + /** + * Defines the behavior of the needle movement. + * The values are STANDARD and OPTIMIZED + * This is an experimental feature that only makes sense in + * gauges that use an angleRange of 360 degrees and where the + * needle should be able to use the shortest way to the target + * value. As an example one can think of a compass. If the value + * in a compass changes from 20 degrees to 290 degrees the needle + * will take the shortest way to the value, in this case this + * means it will rotate counter-clockwise. + * + * @param BEHAVIOR + */ + public void setNeedleBehavior(final NeedleBehavior BEHAVIOR) { + if (null == needleBehavior) { + _needleBehavior = null == BEHAVIOR ? NeedleBehavior.STANDARD : BEHAVIOR; + } else { + needleBehavior.set(BEHAVIOR); + } + } + public ObjectProperty needleBehaviorProperty() { + if (null == needleBehavior) { + needleBehavior = new ObjectPropertyBase(_needleBehavior) { + @Override protected void invalidated() { if(null == get()) set(NeedleBehavior.STANDARD); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "needleBehavior"; } + }; + _needleBehavior = null; + } + return needleBehavior; + } + + /** + * Returns the color that will be used to colorize the needle of + * the radial gauges. + * + * @return the color that wil be used to colorize the needle + */ + public Color getNeedleColor() { return null == needleColor ? _needleColor : needleColor.get(); } + /** + * Defines the color that will be used to colorize the needle of + * the radial gauges. + * + * @param COLOR + */ + public void setNeedleColor(final Color COLOR) { + if (null == needleColor) { + _needleColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + needleColor.set(COLOR); + } + } + public ObjectProperty needleColorProperty() { + if (null == needleColor) { + needleColor = new ObjectPropertyBase(_needleColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "needleColor"; } + }; + _needleColor = null; + } + return needleColor; + } + + /** + * Returns the color that is used to colorize the border of the needle. + * + * @return the color that is used to colorize the border of the needle + */ + public Color getNeedleBorderColor() { return null == needleBorderColor ? _needleBorderColor : needleBorderColor.get(); } + /** + * Defines the color that will be used to colorize the border of the needle. + * + * @param COLOR + */ + public void setNeedleBorderColor(final Color COLOR) { + if (null == needleBorderColor) { + _needleBorderColor = null == COLOR ? Color.TRANSPARENT : COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + needleBorderColor.set(COLOR); + } + } + public ObjectProperty needleBorderColorProperty() { + if (null == needleBorderColor) { + needleBorderColor = new ObjectPropertyBase(_needleBorderColor) { + @Override protected void invalidated() { + if (null == get()) set(Color.TRANSPARENT); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "needleBorderColor"; } + }; + _needleBorderColor = null; + } + return needleBorderColor; + } + + /** + * Returns the color that will be used to colorize the bar of + * the gauge (if it has a bar). + * + * @return the color that will be used to colorized the bar (if available) + */ + public Color getBarColor() { return null == barColor ? _barColor : barColor.get(); } + /** + * Defines the color that will be used to colorize the bar of + * the gauge (if it has a bar). + * + * @param COLOR + */ + public void setBarColor(final Color COLOR) { + if (null == barColor) { + _barColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + barColor.set(COLOR); + } + } + public ObjectProperty barColorProperty() { + if (null == barColor) { + barColor = new ObjectPropertyBase(_barColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "barColor"; } + }; + _barColor = null; + } + return barColor; + } + + /** + * Returns the color that is used to colorize the border of the bar. + * + * @return the color that is used to colorize the border of the bar + */ + public Color getBarBorderColor() { return null == barBorderColor ? _barBorderColor : barBorderColor.get(); } + /** + * Defines the color that will be used to colorize the border of the bar. + * + * @param COLOR + */ + public void setBarBorderColor(final Color COLOR) { + if (null == barBorderColor) { + _barBorderColor = null == COLOR ? Color.TRANSPARENT : COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + barBorderColor.set(COLOR); + } + } + public ObjectProperty barBorderColorProperty() { + if (null == barBorderColor) { + barBorderColor = new ObjectPropertyBase(_barBorderColor) { + @Override protected void invalidated() { + if(null == get()) set(Color.TRANSPARENT); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "barBorderColor"; } + }; + _barBorderColor = null; + } + return barBorderColor; + } + + /** + * Returns the color that will be used to colorize the bar background of + * the gauge (if it has a bar). + * + * @return the color that will be used to colorize the bar background + */ + public Color getBarBackgroundColor() { return null == barBackgroundColor ? _barBackgroundColor : barBackgroundColor.get(); } + /** + * Returns the color that will be used to colorize the bar background of + * the gauge (if it has a bar). + * + * @param COLOR + */ + public void setBarBackgroundColor(final Color COLOR) { + if (null == barBackgroundColor) { + _barBackgroundColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + barBackgroundColor.set(COLOR); + } + } + public ObjectProperty barBackgroundColorProperty() { + if (null == barBackgroundColor) { + barBackgroundColor = new ObjectPropertyBase(_barBackgroundColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "barBackgroundColor"; } + }; + _barBackgroundColor = null; + } + return barBackgroundColor; + } + + /** + * Returns the design that will be used to visualize the LCD display + * of the gauge (if it has one). The values are + * BEIGE, BLACK, BLUE, ORANGE, RED, YELLOW, WHITE, GRAY, + * BLACK, GREEN, GREEN_DARKGREEN, BLUE2, BLUE_BLACK, + * BLUE_DARKBLUE, BLUE_LIGHTBLUE, BLUE_GRAY, STANDARD, + * LIGHTGREEN, STANDARD_GREEN, BLUE_BLUE, RED_DARKRED, + * DARKBLUE, PURPLE, BLACK_RED, DARKGREEN, AMBER, + * LIGHTBLUE, GREEN_BLACK, YELLOW_BLACK, BLACK_YELLOW, + * LIGHTGREEN_BLACK, DARKPURPLE, DARKAMBER, BLUE_LIGHTBLUE2, + * GRAY_PURPLE, YOCTOPUCE, SECTIONS, FLAT_CUSTOM + * + * @return the design that will be used to visualize the LCD display (if available) + */ + //public LcdDesign getLcdDesign() { return null == lcdDesign ? _lcdDesign : lcdDesign.get(); } + /** + * Defines the design that will be used to visualize the LCD display + * of the gauge (if it has one). The values are + * BEIGE, BLACK, BLUE, ORANGE, RED, YELLOW, WHITE, GRAY, + * BLACK, GREEN, GREEN_DARKGREEN, BLUE2, BLUE_BLACK, + * BLUE_DARKBLUE, BLUE_LIGHTBLUE, BLUE_GRAY, STANDARD, + * LIGHTGREEN, STANDARD_GREEN, BLUE_BLUE, RED_DARKRED, + * DARKBLUE, PURPLE, BLACK_RED, DARKGREEN, AMBER, + * LIGHTBLUE, GREEN_BLACK, YELLOW_BLACK, BLACK_YELLOW, + * LIGHTGREEN_BLACK, DARKPURPLE, DARKAMBER, BLUE_LIGHTBLUE2, + * GRAY_PURPLE, YOCTOPUCE, SECTIONS, FLAT_CUSTOM + * + * @param DESIGN + */ + /*public void setLcdDesign(final LcdDesign DESIGN) { + if (null == lcdDesign) { + _lcdDesign = null == DESIGN ? LcdDesign.STANDARD : DESIGN; + fireUpdateEvent(LCD_EVENT); + } else { + lcdDesign.set(DESIGN); + } + } + public ObjectProperty lcdDesignProperty() { + if (null == lcdDesign) { + lcdDesign = new ObjectPropertyBase(_lcdDesign) { + @Override protected void invalidated() { + if(null == get()) set(LcdDesign.STANDARD); + fireUpdateEvent(LCD_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "lcdDesign"; } + }; + _lcdDesign = null; + } + return lcdDesign; + }*/ + + /** + * Returns the font that will be used to visualize the LCD value + * if the gauge has a LCD display. + * The values are STANDARD, LCD, SLIM, DIGITAL_BOLD, ELEKTRA + * + * @return the font that will be used to visualize the LCD value + */ +// public LcdFont getLcdFont() { return null == lcdFont ? _lcdFont : lcdFont.get(); } + /** + * Defines the font that will be used to visualize the LCD value + * if the gauge has a LCD display. + * The values are STANDARD, LCD, SLIM, DIGITAL_BOLD, ELEKTRA + * + * @param FONT + */ +/* + public void setLcdFont(final LcdFont FONT) { + if (null == lcdFont) { + _lcdFont = null == FONT ? LcdFont.DIGITAL_BOLD : FONT; + fireUpdateEvent(RESIZE_EVENT); + } else { + lcdFont.set(FONT); + } + } + public ObjectProperty lcdFontProperty() { + if (null == lcdFont) { + lcdFont = new ObjectPropertyBase(_lcdFont) { + @Override protected void invalidated() { + if(null == get()) set(LcdFont.DIGITAL_BOLD); + fireUpdateEvent(RESIZE_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "lcdFont"; } + }; + _lcdFont = null; + } + return lcdFont; + } +*/ + + /** + * Returns the color that will be used to visualize the LED of the + * gauge if it has one. + * + * @return the color that will be used to visualize the LED + */ +// public Color getLedColor() { return null == ledColor ? _ledColor : ledColor.get(); } + /** + * Defines the color that will be used to visualize the LED of the + * gauge if it has one. + * + * @param COLOR + */ + public void setLedColor(final Color COLOR) { + if (null == ledColor) { + _ledColor = null == COLOR ? Color.RED : COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + ledColor.set(COLOR); + } + } + public ObjectProperty ledColorProperty() { + if (null == ledColor) { + ledColor = new ObjectPropertyBase(_ledColor) { + @Override protected void invalidated() { + if (null == get()) set(Color.RED); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "ledColor"; } + }; + _ledColor = null; + } + return ledColor; + } + + /** + * Returns the graphical representation of the LED. + * The values are STANDARD and FLAT + * In principle this represents how the LED will be filled (gradient or color). + * + * @return the graphical representation of the LED + */ + public LedType getLedType() { return null == ledType ? _ledType : ledType.get(); } + /** + * Defines the graphical representation of the LED. + * The values are STANDARD and FLAT + * In principle this represents how the LED will be filled (gradient or color). + * + * @param TYPE + */ + public void setLedType(final LedType TYPE) { + if (null == ledType) { + _ledType = null == TYPE ? LedType.STANDARD : TYPE; + fireUpdateEvent(REDRAW_EVENT); + } else { + ledType.set(TYPE); + } + } + public ObjectProperty ledTypeProperty() { + if (null == ledType) { + ledType = new ObjectPropertyBase(_ledType) { + @Override protected void invalidated() { + if(null == get()) set(LedType.STANDARD); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "ledType"; } + }; + _ledType = null; + } + return ledType; + } + + /** + * Returns the color that will be used to colorize the title + * of the gauge. + * + * @return the color that will be used to colorize the title + */ + public Color getTitleColor() { return null == titleColor ? _titleColor : titleColor.get(); } + /** + * Defines the color that will be used to colorize the title + * of the gauge. + * + * @param COLOR + */ + public void setTitleColor(final Color COLOR) { + if (null == titleColor) { + _titleColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + titleColor.set(COLOR); + } + } + public ObjectProperty titleColorProperty() { + if (null == titleColor) { + titleColor = new ObjectPropertyBase(_titleColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "titleColor"; } + }; + _titleColor = null; + } + return titleColor; + } + + /** + * Returns the color that will be used to colorize the subTitle + * of the gauge. + * + * @return the color that will be used to colorize the subTitle + */ + public Color getSubTitleColor() { return null == subTitleColor ? _subTitleColor : subTitleColor.get(); } + /** + * Defines the color that will be used to colorize the subTitle + * of the gauge. + * + * @param COLOR + */ + public void setSubTitleColor(final Color COLOR) { + if (null == subTitleColor) { + _subTitleColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + subTitleColor.set(COLOR); + } + } + public ObjectProperty subTitleColorProperty() { + if (null == subTitleColor) { + subTitleColor = new ObjectPropertyBase(_subTitleColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "subTitleColor"; } + }; + _subTitleColor = null; + } + return subTitleColor; + } + + /** + * Returns the color that will be used to colorize the unit + * of the gauge. + * + * @return the color that will be used to colorize the unit + */ + public Color getUnitColor() { return null == unitColor ? _unitColor : unitColor.get(); } + /** + * Defines the color that will be used to colorize the unit + * of the gauge. + * + * @param COLOR + */ + public void setUnitColor(final Color COLOR) { + if (null == unitColor) { + _unitColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + unitColor.set(COLOR); + } + } + public ObjectProperty unitColorProperty() { + if (null == unitColor) { + unitColor = new ObjectPropertyBase(_unitColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "unitColor"; } + }; + _unitColor = null; + } + return unitColor; + } + + /** + * Returns the color that will be used to colorize the value + * of the gauge. + * + * @return the color that will be used to colorize the value + */ + public Color getValueColor() { return null == valueColor ? _valueColor : valueColor.get(); } + /** + * Defines the color that will be used to colorize the value + * of the gauge. + * + * @param COLOR + */ + public void setValueColor(final Color COLOR) { + if (null == valueColor) { + _valueColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + valueColor.set(COLOR); + } + } + public ObjectProperty valueColorProperty() { + if (null == valueColor) { + valueColor = new ObjectPropertyBase(_valueColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "valueColor"; } + }; + _valueColor = null; + } + return valueColor; + } + + /** + * Returns the color that will be used to colorize the threshold + * indicator of the gauge. + * + * @return the color that will be used to colorize the threshold indicator + */ + public Color getThresholdColor() { return null == thresholdColor ? _thresholdColor : thresholdColor.get(); } + /** + * Defines the color that will be used to colorize the threshold + * indicator of the gauge. + * + * @param COLOR + */ + public void setThresholdColor(final Color COLOR) { + if (null == thresholdColor) { + _thresholdColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + thresholdColor.set(COLOR); + } + } + public ObjectProperty thresholdColorProperty() { + if (null == thresholdColor) { + thresholdColor = new ObjectPropertyBase(_thresholdColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "thresholdColor"; } + }; + _thresholdColor = null; + } + return thresholdColor; + } + + /** + * Returns the color that will be used to colorize the average + * indicator of the gauge. + * + * @return the color that will be used to colorize the average indicator + */ + public Color getAverageColor() { return null == averageColor ? _averageColor : averageColor.get(); } + /** + * Defines the color that will be used to colorize the average + * indicator of the gauge. + * + * @param COLOR + */ + public void setAverageColor(final Color COLOR) { + if (null == averageColor) { + _averageColor = COLOR; + fireUpdateEvent(REDRAW_EVENT); + } else { + averageColor.set(COLOR); + } + } + public ObjectProperty averageColorProperty() { + if (null == averageColor) { + averageColor = new ObjectPropertyBase(_averageColor) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "averageColor"; } + }; + _averageColor = null; + } + return averageColor; + } + + /** + * Returns true if the value of the gauge should be checked against + * all sections (if sections not empty). If a value enters a section + * or leaves a section it will fire an event. The check will be performed + * after the animation is finished (if animated == true). + * + * @return true if the value of the gauge should be checked against all sections + */ + public boolean getCheckSectionsForValue() { return null == checkSectionsForValue ? _checkSectionsForValue : checkSectionsForValue.get(); } + /** + * Defines if the value of the gauge should be checked against + * all sections (if sections not empty). If a value enters a section + * or leaves a section it will fire an event. The check will be performed + * after the animation is finished (if animated == true). + * + * @param CHECK + */ + public void setCheckSectionsForValue(final boolean CHECK) { + if (null == checkSectionsForValue) { _checkSectionsForValue = CHECK; } else { checkSectionsForValue.set(CHECK); } + } + public BooleanProperty checkSectionsForValueProperty() { + if (null == checkSectionsForValue) { checkSectionsForValue = new SimpleBooleanProperty(Gauge.this, "checkSectionsForValue", _checkSectionsForValue); } + return checkSectionsForValue; + } + + /** + * Returns true if the value of the gauge should be checked against + * all areas (if areas not empty). If a value enters an area + * or leaves an area it will fire an event. The check will be performed + * after the animation is finished (if animated == true). + * + * @return true if the the value of the gauge should be checked against all areas + */ + public boolean getCheckAreasForValue() { return null == checkAreasForValue ? _checkAreasForValue : checkAreasForValue.get(); } + /** + * Defines if the value of the gauge should be checked against + * all areas (if areas not empty). If a value enters an area + * or leaves an area it will fire an event. The check will be performed + * after the animation is finished (if animated == true). + * + * @param CHECK + */ + public void setCheckAreasForValue(final boolean CHECK) { + if (null == checkAreasForValue) { _checkAreasForValue = CHECK; } else { checkAreasForValue.set(CHECK); } + } + public BooleanProperty checkAreasForValueProperty() { + if (null == checkAreasForValue) { checkAreasForValue = new SimpleBooleanProperty(Gauge.this, "checkAreasForValue", _checkAreasForValue); } + return checkAreasForValue; + } + + /** + * Returns true if the value of the gauge should be checked against + * the threshold. If a value crosses the threshold it will fire an + * event (EXCEEDED and UNDERRUN. The check will be performed + * after the animation is finished (if animated == true). + * + * @return true if the value of the gauge should be checked against the threshold + */ + public boolean isCheckThreshold() { return null == checkThreshold ? _checkThreshold : checkThreshold.get(); } + /** + * Defines if the value of the gauge should be checked against + * the threshold. If a value crosses the threshold it will fire an + * event (EXCEEDED and UNDERRUN. The check will be performed + * after the animation is finished (if animated == true). + * + * @param CHECK + */ + public void setCheckThreshold(final boolean CHECK) { + if (null == checkThreshold) { + _checkThreshold = CHECK; + } else { + checkThreshold.set(CHECK); + } + } + public BooleanProperty checkThresholdProperty() { + if (null == checkThreshold) { checkThreshold = new SimpleBooleanProperty(Gauge.this, "checkThreshold", _checkThreshold); } + return checkThreshold; + } + + /** + * Returns true if an inner shadow should be drawn on the gauge + * background. + * + * @return true if an inner shadow should be drawn on the gauge background + */ + public boolean isInnerShadowEnabled() { return null == innerShadowEnabled ? _innerShadowEnabled : innerShadowEnabled.get(); } + /** + * Defines if an inner shadow should be drawn on the gauge + * background. + * + * @param ENABLED + */ + public void setInnerShadowEnabled(final boolean ENABLED) { + if (null == innerShadowEnabled) { + _innerShadowEnabled = ENABLED; + fireUpdateEvent(REDRAW_EVENT); + } else { + innerShadowEnabled.set(ENABLED); + } + } + public BooleanProperty innerShadowEnabledProperty() { + if (null == innerShadowEnabled) { + innerShadowEnabled = new BooleanPropertyBase(_innerShadowEnabled) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "innerShadowEnabled"; } + }; + } + return innerShadowEnabled; + } + + /** + * Returns true if the threshold indicator should be drawn. + * + * @return true if the threshold indicator should be drawn + */ + public boolean isThresholdVisible() { return null == thresholdVisible ? _thresholdVisible : thresholdVisible.get(); } + /** + * Defines if the threshold indicator should be drawn + * + * @param VISIBLE + */ + public void setThresholdVisible(final boolean VISIBLE) { + if (null == thresholdVisible) { + _thresholdVisible = VISIBLE; + fireUpdateEvent(VISIBILITY_EVENT); + } else { + thresholdVisible.set(VISIBLE); + } + } + public BooleanProperty thresholdVisibleProperty() { + if (null == thresholdVisible) { + thresholdVisible = new BooleanPropertyBase(_thresholdVisible) { + @Override protected void invalidated() { fireUpdateEvent(VISIBILITY_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "thresholdVisible"; } + }; + } + return thresholdVisible; + } + + /** + * Returns true if the average indicator should be drawn. + * + * @return true if the average indicator should be drawn + */ + public boolean isAverageVisible() { return null == averageVisible ? _averageVisible : averageVisible.get(); } + /** + * Defines if the average indicator should be drawn + * + * @param VISIBLE + */ + public void setAverageVisible(final boolean VISIBLE) { + if (null == averageVisible) { + _averageVisible = VISIBLE; + fireUpdateEvent(VISIBILITY_EVENT); + } else { + averageVisible.set(VISIBLE); + } + } + public BooleanProperty averageVisibleProperty() { + if (null == averageVisible) { + averageVisible = new BooleanPropertyBase() { + @Override protected void invalidated() { fireUpdateEvent(VISIBILITY_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "averageVisible"; } + }; + } + return averageVisible; + } + + /** + * Returns true if the sections will be drawn + * + * @return true if the sections will be drawn + */ + public boolean getSectionsVisible() { return null == sectionsVisible ? _sectionsVisible : sectionsVisible.get(); } + /** + * Defines if the sections will be drawn + * + * @param VISIBLE + */ + public void setSectionsVisible(final boolean VISIBLE) { + if (null == sectionsVisible) { + _sectionsVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + sectionsVisible.set(VISIBLE); + } + } + public BooleanProperty sectionsVisibleProperty() { + if (null == sectionsVisible) { + sectionsVisible = new BooleanPropertyBase(_sectionsVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "sectionsVisible"; } + }; + } + return sectionsVisible; + } + + /** + * Returns true if the sections in the IndicatorSkin + * will always be visible + * @return + */ + public boolean getSectionsAlwaysVisible() { return null == sectionsAlwaysVisible ? _sectionsAlwaysVisible : sectionsAlwaysVisible.get(); } + /** + * Defines if the sections will always be visible. + * This is currently only used in the IndicatorSkin + * @param VISIBLE + */ + public void setSectionsAlwaysVisible(final boolean VISIBLE) { + if (null == sectionsAlwaysVisible) { + _sectionsAlwaysVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + sectionsAlwaysVisible.set(VISIBLE); + } + } + public BooleanProperty sectionsAlwaysVisibleProperty() { + if (null == sectionsAlwaysVisible) { + sectionsAlwaysVisible = new BooleanPropertyBase(_sectionsAlwaysVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "sectionsAlwaysVisible"; } + }; + } + return sectionsAlwaysVisible; + } + + /** + * Returns true if the text of the sections should be drawn inside + * the sections. This is currently only used in the SimpleSkin. + * + * @return true if the text of the sections should be drawn + */ + public boolean isSectionTextVisible() { return null == sectionTextVisible ? _sectionTextVisible : sectionTextVisible.get(); } + /** + * Defines if the text of the sections should be drawn inside + * the sections. This is currently only used in the SimpleSkin. + * + * @param VISIBLE + */ + public void setSectionTextVisible(final boolean VISIBLE) { + if (null == sectionTextVisible) { + _sectionTextVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + sectionTextVisible.set(VISIBLE); + } + } + public BooleanProperty sectionTextVisibleProperty() { + if (null == sectionTextVisible) { + sectionTextVisible = new BooleanPropertyBase(_sectionTextVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "sectionTextVisible"; } + }; + } + return sectionTextVisible; + } + + /** + * Returns true if the icon of the sections should be drawn inside + * the sections. This is currently only used in the SimpleSkin. + * + * @return true if the icon of the sections should be drawn + */ + public boolean getSectionIconsVisible() { return null == sectionIconsVisible ? _sectionIconsVisible : sectionIconsVisible.get(); } + /** + * Defines if the icon of the sections should be drawn inside + * the sections. This is currently only used in the SimpleSkin. + * + * @param VISIBLE + */ + public void setSectionIconsVisible(final boolean VISIBLE) { + if (null == sectionIconsVisible) { + _sectionIconsVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + sectionIconsVisible.set(VISIBLE); + } + } + public BooleanProperty sectionIconsVisibleProperty() { + if (null == sectionIconsVisible) { + sectionIconsVisible = new BooleanPropertyBase(_sectionIconsVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "sectionIconsVisible"; } + }; + } + return sectionIconsVisible; + } + + /** + * Returns true if sections should be highlighted in case they + * contain the current value. + * + * @return true if sections should be highlighted + */ + public boolean isHighlightSections() { return null == highlightSections ? _highlightSections : highlightSections.get(); } + /** + * Defines if sections should be highlighted in case they + * contain the current value + * + * @param HIGHLIGHT + */ + public void setHighlightSections(final boolean HIGHLIGHT) { + if (null == highlightSections) { + _highlightSections = HIGHLIGHT; + fireUpdateEvent(REDRAW_EVENT); + } else { + highlightSections.set(HIGHLIGHT); + } + } + public BooleanProperty highlightSectionsProperty() { + if (null == highlightSections) { + highlightSections = new BooleanPropertyBase(_highlightSections) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "highlightSections"; } + }; + } + return highlightSections; + } + + /** + * Returns true if the areas should be drawn + * + * @return true if the areas should be drawn + */ + public boolean getAreasVisible() { return null == areasVisible ? _areasVisible : areasVisible.get(); } + /** + * Defines if the areas should be drawn + * + * @param VISIBLE + */ + public void setAreasVisible(final boolean VISIBLE) { + if (null == areasVisible) { + _areasVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + areasVisible.set(VISIBLE); + } + } + public BooleanProperty areasVisibleProperty() { + if (null == areasVisible) { + areasVisible = new BooleanPropertyBase(_areasVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "areasVisible"; } + }; + } + return areasVisible; + } + + /** + * Returns true if the text of the areas should be drawn inside + * the areas. This is currently only used in the SimpleSkin. + * + * @return true if the text of the areas should be drawn + */ + public boolean isAreaTextVisible() { return null == areaTextVisible ? _areaTextVisible : areaTextVisible.get(); } + /** + * Defines if the text of the areas should be drawn inside + * the areas. + * + * @param VISIBLE + */ + public void setAreaTextVisible(final boolean VISIBLE) { + if (null == areaTextVisible) { + _areaTextVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + areaTextVisible.set(VISIBLE); + } + } + public BooleanProperty areaTextVisibleProperty() { + if (null == areaTextVisible) { + areaTextVisible = new BooleanPropertyBase(_areaTextVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "areaTextVisible"; } + }; + } + return areaTextVisible; + } + + /** + * Returns true if the icon of the areas should be drawn inside + * the areas. + * + * @return true if the icon of the areas should be drawn + */ + public boolean getAreaIconsVisible() { return null == areaIconsVisible ? _areaIconsVisible : areaIconsVisible.get(); } + /** + * Defines if the icon of the areas should be drawn inside + * the areas. + * + * @param VISIBLE + */ + public void setAreaIconsVisible(final boolean VISIBLE) { + if (null == areaIconsVisible) { + _areaIconsVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + areaIconsVisible.set(VISIBLE); + } + } + public BooleanProperty areaIconsVisibleProperty() { + if (null == areaIconsVisible) { + areaIconsVisible = new BooleanPropertyBase(_areaIconsVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "areaIconsVisible"; } + }; + } + return areaIconsVisible; + } + + /** + * Returns true if areas should be highlighted in case they + * contain the current value. + * + * @return true if areas should be highlighted + */ + public boolean isHighlightAreas() { return null == highlightAreas ? _highlightAreas : highlightAreas.get(); } + /** + * Defines if areas should be highlighted in case they + * contain the current value + * + * @param HIGHLIGHT + */ + public void setHighlightAreas(final boolean HIGHLIGHT) { + if (null == highlightAreas) { + _highlightAreas = HIGHLIGHT; + fireUpdateEvent(REDRAW_EVENT); + } else { + highlightAreas.set(HIGHLIGHT); + } + } + public BooleanProperty highlightAreasProperty() { + if (null == highlightAreas) { + highlightAreas = new BooleanPropertyBase(_highlightAreas) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "highlightAreas"; } + }; + } + return highlightAreas; + } + + /** + * Returns true if the tickmark sections should be used to + * colorize the tickmarks. + * + * @return true if the tickmark sections should be used + */ + public boolean getTickMarkSectionsVisible() { return null == tickMarkSectionsVisible ? _tickMarkSectionsVisible : tickMarkSectionsVisible.get(); } + /** + * Defines if the tickmark sections should be used to + * colorize the tickmarks. + * + * @param VISIBLE + */ + public void setTickMarkSectionsVisible(final boolean VISIBLE) { + if (null == tickMarkSectionsVisible) { + _tickMarkSectionsVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + tickMarkSectionsVisible.set(VISIBLE); + } + } + public BooleanProperty tickMarkSectionsVisibleProperty() { + if (null == tickMarkSectionsVisible) { + tickMarkSectionsVisible = new BooleanPropertyBase(_tickMarkSectionsVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "tickMarkSectionsVisible"; } + }; + } + return tickMarkSectionsVisible; + } + + /** + * Returns true if the ticklabel sections should be used + * to colorize the ticklabels. + * + * @return true if the ticklabel sections should be used + */ + public boolean getTickLabelSectionsVisible() { return null == tickLabelSectionsVisible ? _tickLabelSectionsVisible : tickLabelSectionsVisible.get(); } + /** + * Defines if the ticklabel sections should be used to + * colorize the ticklabels. + * + * @param VISIBLE + */ + public void setTickLabelSectionsVisible(final boolean VISIBLE) { + if (null == tickLabelSectionsVisible) { + _tickLabelSectionsVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + tickLabelSectionsVisible.set(VISIBLE); + } + } + public BooleanProperty tickLabelSectionsVisibleProperty() { + if (null == tickLabelSectionsVisible) { + tickLabelSectionsVisible = new BooleanPropertyBase(_tickLabelSectionsVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "tickLabelSectionsVisible"; } + }; + } + return tickLabelSectionsVisible; + } + + /** + * Returns true if the markers should be drawn + * + * @return true if the markser should be drawn + */ +// public boolean getMarkersVisible() { return null == markersVisible ? _markersVisible : markersVisible.get(); } + /** + * Defines if the markers should be drawn + * + * @param VISIBLE + */ +/* + public void setMarkersVisible(final boolean VISIBLE) { + if (null == markersVisible) { + _markersVisible = VISIBLE; + fireUpdateEvent(VISIBILITY_EVENT); + } else { + markersVisible.set(VISIBLE); + } + } + public BooleanProperty markersVisibleProperty() { + if (null == markersVisible) { + markersVisible = new BooleanPropertyBase(_markersVisible) { + @Override protected void invalidated() { fireUpdateEvent(VISIBILITY_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "markersVisible"; } + }; + } + return markersVisible; + } +*/ + + /** + * Returns true if the ticklabels should be drawn + * + * @return true if the ticklabels should be drawn + */ + public boolean getTickLabelsVisible() { return null == tickLabelsVisible ? _tickLabelsVisible : tickLabelsVisible.get(); } + /** + * Defines if the ticklabels should be drawn + * + * @param VISIBLE + */ + public void setTickLabelsVisible(final boolean VISIBLE) { + if (null == tickLabelsVisible) { + _tickLabelsVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + tickLabelsVisible.set(VISIBLE); + } + } + public BooleanProperty tickLabelsVisibleProperty() { + if (null == tickLabelsVisible) { + tickLabelsVisible = new BooleanPropertyBase(_tickLabelsVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "tickLabelsVisible"; } + }; + } + return tickLabelsVisible; + } + + /** + * Returns true if only the first and the last ticklabel + * will be drawn. Sometimes this could be useful if a gauge + * should for example only should show 0 and 1000. + * + * @return true if only the first and last ticklabel will be drawn + */ + public boolean isOnlyFirstAndLastTickLabelVisible() { + return null == onlyFirstAndLastTickLabelVisible ? _onlyFirstAndLastTickLabelVisible : onlyFirstAndLastTickLabelVisible.get(); + } + /** + * Defines if only the first and the last ticklabel + * will be drawn. Sometimes this could be useful if a gauge + * should for example only should show 0 and 1000. + * + * @param VISIBLE + */ + public void setOnlyFirstAndLastTickLabelVisible(final boolean VISIBLE) { + if (null == onlyFirstAndLastTickLabelVisible) { + _onlyFirstAndLastTickLabelVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + onlyFirstAndLastTickLabelVisible.set(VISIBLE); + } + } + public BooleanProperty onlyFirstAndLastTickLabelVisibleProperty() { + if (null == onlyFirstAndLastTickLabelVisible) { + onlyFirstAndLastTickLabelVisible = new BooleanPropertyBase(_onlyFirstAndLastTickLabelVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "onlyFirstAndLastTickLabelVisible"; } + }; + } + return onlyFirstAndLastTickLabelVisible; + } + + /** + * Returns true if the major tickmarks should be drawn + * If set to false and minorTickmarks == true, a minor tickmark + * will be drawn instead of the major tickmark. + * + * @return true if the major tickmarks should be drawn + */ + public boolean getMajorTickMarksVisible() { return null == majorTickMarksVisible ? _majorTickMarksVisible : majorTickMarksVisible.get(); } + /** + * Defines if the major tickmarks should be drawn + * If set to false and minorTickmarks == true, a minor tickmark + * will be drawn instead of the major tickmark. + * + * @param VISIBLE + */ + public void setMajorTickMarksVisible(final boolean VISIBLE) { + if (null == majorTickMarksVisible) { + _majorTickMarksVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + majorTickMarksVisible.set(VISIBLE); + } + } + public BooleanProperty majorTickMarksVisibleProperty() { + if (null == majorTickMarksVisible) { + majorTickMarksVisible = new BooleanPropertyBase(_majorTickMarksVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "majorTickMarksVisible"; } + }; + } + return majorTickMarksVisible; + } + + /** + * Returns true if the medium tickmarks should be drawn + * If set to false and minorTickmarks == true, a minor tickmark + * will be drawn instead of the medium tickmark. + * + * @return true if the medium tickmarks should be drawn + */ + public boolean getMediumTickMarksVisible() { return null == mediumTickMarksVisible ? _mediumTickMarksVisible : mediumTickMarksVisible.get(); } + public void setMediumTickMarksVisible(final boolean VISIBLE) { + if (null == mediumTickMarksVisible) { + _mediumTickMarksVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + mediumTickMarksVisible.set(VISIBLE); + } + } + public BooleanProperty mediumTickMarksVisibleProperty() { + if (null == mediumTickMarksVisible) { + mediumTickMarksVisible = new BooleanPropertyBase(_mediumTickMarksVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "mediumTickMarksVisible"; } + }; + } + return mediumTickMarksVisible; + } + + /** + * Returns true if the minor tickmarks should be drawn + * + * @return true if the minor tickmarks should be drawn + */ + public boolean getMinorTickMarksVisible() { return null == minorTickMarksVisible ? _minorTickMarksVisible : minorTickMarksVisible.get(); } + /** + * Defines if the minor tickmarks should be drawn + * + * @param VISIBLE + */ + public void setMinorTickMarksVisible(final boolean VISIBLE) { + if (null == minorTickMarksVisible) { + _minorTickMarksVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + minorTickMarksVisible.set(VISIBLE); + } + } + public BooleanProperty minorTickMarksVisibleProperty() { + if (null == minorTickMarksVisible) { + minorTickMarksVisible = new BooleanPropertyBase(_minorTickMarksVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "minorTickMarksVisible"; } + }; + } + return minorTickMarksVisible; + } + + /** + * Returns true when an additional ring will be drawn that "connects" the + * tick marks. + * + * @return true when an additional ring will be drawn that "connects" the tick marks + */ + public boolean isTickMarkRingVisible() { return null == tickMarkRingVisible ? _tickMarkRingVisible : tickMarkRingVisible.get(); } + /** + * Defines if an additional ring should be drawn that "connects" the tick marks. + * + * @param VISIBLE + */ + public void setTickMarkRingVisible(final boolean VISIBLE) { + if (null == tickMarkRingVisible) { + _tickMarkRingVisible = VISIBLE; + fireUpdateEvent(REDRAW_EVENT); + } else { + tickMarkRingVisible.set(VISIBLE); + } + } + public BooleanProperty tickMarkRingVisibleProperty() { + if (null == tickMarkRingVisible) { + tickMarkRingVisible = new BooleanPropertyBase(_tickMarkRingVisible) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "tickMarkRingVisible"; } + }; + } + return tickMarkRingVisible; + } + + /** + * Returns the value that represents the space between major + * tickmarks. This value will be automatically set by the + * autoscale property. Be careful when changing it manually. + * + * @return the value that represents the space between major tickmarks + */ + public double getMajorTickSpace() { return null == majorTickSpace ? _majorTickSpace : majorTickSpace.get(); } + /** + * Defines the value that represents the space between major + * tickmarks. This value will be automatically set by the + * autoscale property. Be careful when changing it manually. + * + * @param SPACE + */ + public void setMajorTickSpace(final double SPACE) { + if (null == majorTickSpace) { + _majorTickSpace = SPACE; + fireUpdateEvent(RECALC_EVENT); + } else { + majorTickSpace.set(SPACE); + } + } + public DoubleProperty majorTickSpaceProperty() { + if (null == majorTickSpace) { + majorTickSpace = new DoublePropertyBase(_majorTickSpace) { + @Override protected void invalidated() { fireUpdateEvent(RECALC_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "majorTickSpace"; } + }; + } + return majorTickSpace; + } + + /** + * Returns the value that represents the space between minor + * tickmarks. This value will be automatically set by the + * autoscale property. Be careful when changing it manually. + * + * @return the value that represents the space between minor tickmarks + */ + public double getMinorTickSpace() { return null == minorTickSpace ? _minorTickSpace : minorTickSpace.get(); } + /** + * Defines the value that represents the space between major + * tickmarks. This value will be automatically set by the + * autoscale property. Be careful when changing it manually. + * + * @param SPACE + */ + public void setMinorTickSpace(final double SPACE) { + if (null == minorTickSpace) { + _minorTickSpace = SPACE; + fireUpdateEvent(RECALC_EVENT); + } else { + minorTickSpace.set(SPACE); + } + } + public DoubleProperty minorTickSpaceProperty() { + if (null == minorTickSpace) { + minorTickSpace = new DoublePropertyBase(_minorTickSpace) { + @Override protected void invalidated() { fireUpdateEvent(RECALC_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "minorTickSpace"; } + }; + } + return minorTickSpace; + } + + /** + * Returns true if the LCD display is visible (if available) + * The LCD display won't be visible if valueVisible == false. + * + * @return true if the LCD display is visible + */ +// public boolean isLcdVisible() { return null == lcdVisible ? _lcdVisible : lcdVisible.get(); } + /** + * Defines if the LCD display is visible (if available) + * The LCD display won't be visible if valueVisible == false. + * + * @param VISIBLE + */ +/* + public void setLcdVisible(final boolean VISIBLE) { + if (null == lcdVisible) { + _lcdVisible = VISIBLE; + fireUpdateEvent(VISIBILITY_EVENT); + } else { + lcdVisible.set(VISIBLE); + } + } + public BooleanProperty lcdVisibleProperty() { + if (null == lcdVisible) { + lcdVisible = new BooleanPropertyBase(_lcdVisible) { + @Override protected void invalidated() { fireUpdateEvent(VISIBILITY_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "lcdVisible"; } + }; + } + return lcdVisible; + } +*/ + + /** + * Returns true if the crystal effect of the LCD display will be drawn. + * This feature could decrease the performance if you run it on + * embedded devices because it will calculate a bitmap image where + * each pixel will be calculated. + * + * @return true if the crystal effect of the LCD display will be drawn + */ +// public boolean isLcdCrystalEnabled() { return null == lcdCrystalEnabled ? _lcdCrystalEnabled : lcdCrystalEnabled.get(); } + /** + * Defines if the crystal effect of the LCD display will be drawn. + * This feature could decrease the performance if you run it on + * embedded devices because it will calculate a bitmap image where + * each pixel will be calculated. + * + * @param ENABLED + */ +/* + public void setLcdCrystalEnabled(final boolean ENABLED) { + if (null == lcdCrystalEnabled) { + _lcdCrystalEnabled = ENABLED; + fireUpdateEvent(VISIBILITY_EVENT); + } else { + lcdCrystalEnabled.set(ENABLED); + } + } + public BooleanProperty lcdCrystalEnabledProperty() { + if (null == lcdCrystalEnabled) { + lcdCrystalEnabled = new BooleanPropertyBase(_lcdCrystalEnabled) { + @Override protected void invalidated() { fireUpdateEvent(VISIBILITY_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "lcdCrystalEnabled"; } + }; + } + return lcdCrystalEnabled; + } +*/ + + /** + * Returns true if the LED will be drawn (if available) + * + * @return true if the LED will be drawn + */ + public boolean isLedVisible() { return null == ledVisible ? _ledVisible : ledVisible.get(); } + /** + * Defines if the LED will be drawn (if available) + * + * @param VISIBLE + */ + public void setLedVisible(final boolean VISIBLE) { + if (null == ledVisible) { + _ledVisible = VISIBLE; + fireUpdateEvent(VISIBILITY_EVENT); + } else { + ledVisible.set(VISIBLE); + } + } + public BooleanProperty ledVisibleProperty() { + if (null == ledVisible) { + ledVisible = new BooleanPropertyBase(_ledVisible) { + @Override protected void invalidated() { fireUpdateEvent(VISIBILITY_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "ledVisible"; } + }; + } + return ledVisible; + } + + /** + * Returns true if the LED is on (if available) + * + * @return true if the LED is on + */ + public boolean isLedOn() { return null == ledOn ? _ledOn : ledOn.get(); } + /** + * Defines if the LED is on (if available) + * + * @param ON + */ + public void setLedOn(final boolean ON) { + if (null == ledOn) { + _ledOn = ON; + fireUpdateEvent(LED_EVENT); + } else { + ledOn.set(ON); + } + } + public BooleanProperty ledOnProperty() { + if (null == ledOn) { + ledOn = new BooleanPropertyBase(_ledOn) { + @Override protected void invalidated() { fireUpdateEvent(LED_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "ledOn"; } + }; + } + return ledOn; + } + + /** + * Returns true if the LED is blinking (if available) + * + * @return true if the LED is blinking + */ + //public boolean isLedBlinking() { return null == ledBlinking ? _ledBlinking : ledBlinking.get(); } + /** + * Defines if the LED is blinking (if available) + * + * @param BLINKING + */ + /*public void setLedBlinking(final boolean BLINKING) { + if (null == ledBlinking) { + _ledBlinking = BLINKING; + if (_ledBlinking) { + startBlinkExecutorService(); + } else { + if (null != blinkFuture) blinkFuture.cancel(true); + setLedOn(false); + } + } else { + ledBlinking.set(BLINKING); + } + } + public BooleanProperty ledBlinkingProperty() { + if (null == ledBlinking) { + ledBlinking = new BooleanPropertyBase(_ledBlinking) { + @Override protected void invalidated() { + if (get()) { + startBlinkExecutorService(); + } else { + if (null != blinkFuture) blinkFuture.cancel(true); + setLedOn(false); + } + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "ledBlinking"; } + }; + } + return ledBlinking; + }*/ + + /** + * Returns the orientation of the control. This feature + * will only be used in the BulletChartSkin and LinearSkin. + * Values are HORIZONTAL and VERTICAL + * + * @return the orientation of the control + */ + public Orientation getOrientation() { return null == orientation ? _orientation : orientation.get(); } + /** + * Defines the orientation of the control. This feature + * will only be used in the BulletChartSkin and LinearSkin. + * Values are HORIZONTAL and VERTICAL + * + * @param ORIENTATION + */ + public void setOrientation(final Orientation ORIENTATION) { + if (null == orientation) { + _orientation = ORIENTATION; + fireUpdateEvent(RESIZE_EVENT); + } else { + orientation.set(ORIENTATION); + } + } + public ObjectProperty orientationProperty() { + if (null == orientation) { + orientation = new ObjectPropertyBase(_orientation) { + @Override protected void invalidated() { fireUpdateEvent(RESIZE_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "orientation"; } + }; + _orientation = null; + } + return orientation; + } + + /** + * Returns true if the gradient defined by the gradient lookup + * will be used to visualize the bar (if available). + * + * @return true if the gradient defined by the gradient lookup will be used to visualize the bar + */ + public boolean isGradientBarEnabled() { return null == gradientBarEnabled ? _gradientBarEnabled : gradientBarEnabled.get(); } + /** + * Defines if the gradient defined by the gradient lookup + * will be used to visualize the bar (if available). + * + * @param ENABLED + */ + public void setGradientBarEnabled(final boolean ENABLED) { + if (null == gradientBarEnabled) { + _gradientBarEnabled = ENABLED; + fireUpdateEvent(REDRAW_EVENT); + } else { + gradientBarEnabled.set(ENABLED); + } + } + public BooleanProperty gradientBarEnabledProperty() { + if (null == gradientBarEnabled) { + gradientBarEnabled = new BooleanPropertyBase(_gradientBarEnabled) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "gradientBarEnabled"; } + }; + } + return gradientBarEnabled; + } + + /** + * Returns the GradientLookup that is used to colorize the bar + * of the gauge (if avaiable) + * + * @return the GradientLookup that is used to colorize the bar + */ +/* + public GradientLookup getGradientLookup() { + if (null == gradientLookup) { gradientLookup = new GradientLookup(); } + return gradientLookup; + } +*/ + /** + * Defines the GradientLookup that is used to colorize the bar + * of the gauge (if avaiable) + * + * @param GRADIENT_LOOKUP + */ +/* + public void setGradientLookup(final GradientLookup GRADIENT_LOOKUP) { + gradientLookup = GRADIENT_LOOKUP; + fireUpdateEvent(REDRAW_EVENT); + } +*/ + /** + * Returns a list of Stops that will be used to calculate the gradient + * in the GradientLookup. + * + * @return a list of Stops that will be used to calculate the gradient in the GradientLookup + */ +// public List getGradientBarStops() { return getGradientLookup().getStops(); } + /** + * Defines a list of Stops that will be used to calculate the gradient + * in the GradientLookup. + * + * @param STOPS + */ +// public void setGradientBarStops(final Stop... STOPS) { setGradientBarStops(Arrays.asList(STOPS)); } + /** + * Defines a list of Stops that will be used to calculate the gradient + * in the GradientLookup. + * + * @param STOPS + */ +/* + public void setGradientBarStops(final List STOPS) { + getGradientLookup().setStops(STOPS); + fireUpdateEvent(REDRAW_EVENT); + } +*/ + + /** + * Returns true if custom ticklabels should be used instead of the + * automatically calculated ones. This could be useful for gauges + * like a compass where you need "N", "E", "S" and "W" instead of + * numbers. + * + * @return true if custom ticklabels should be used + */ + public boolean getCustomTickLabelsEnabled() { return null == customTickLabelsEnabled ? _customTickLabelsEnabled : customTickLabelsEnabled.get(); } + /** + * Defines if custom ticklabels should be used instead of the + * automatically calculated ones. This could be useful for gauges + * like a compass where you need "N", "E", "S" and "W" instead of + * numbers. + * + * @param ENABLED + */ + public void setCustomTickLabelsEnabled(final boolean ENABLED) { + if (null == customTickLabelsEnabled) { + _customTickLabelsEnabled = ENABLED; + fireUpdateEvent(REDRAW_EVENT); + } else { + customTickLabelsEnabled.set(ENABLED); + } + } + public BooleanProperty getCustomTickLabelsEnabledProperty() { + if (null == customTickLabelsEnabled) { + customTickLabelsEnabled = new BooleanPropertyBase(_customTickLabelsEnabled) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "customTickLabelsEnabled"; } + }; + } + return customTickLabelsEnabled; + } + + /** + * Returns a list of Strings that represent the ticklabels that + * will be used for the scale. + * + * @return a list of Strings that represent the ticklabels + */ + public List getCustomTickLabels() { return customTickLabels; } + /** + * Defines a list of Strings that represent the ticklabels that + * will be used for the scale. + * + * @param TICK_LABELS + */ + public void setCustomTickLabels(final List TICK_LABELS) { + customTickLabels.setAll(TICK_LABELS); + fireUpdateEvent(REDRAW_EVENT); + } + /** + * Defines a list of Strings that represent the ticklabels that + * will be used for the scale. + * + * @param TICK_LABELS + */ + public void setCustomTickLabels(final String... TICK_LABELS) { setCustomTickLabels(Arrays.asList(TICK_LABELS)); } + /** + * Adds the given String to the list of custom ticklabels + * + * @param TICK_LABEL + */ + public void addCustomTickLabel(final String TICK_LABEL) { + if (null == TICK_LABEL) return; + if (!customTickLabels.contains(TICK_LABEL)) customTickLabels.add(TICK_LABEL); + fireUpdateEvent(REDRAW_EVENT); + } + /** + * Removes the given String from the list of custom ticklabels + * + * @param TICK_LABEL + */ + public void removeCustomTickLabel(final String TICK_LABEL) { + if (null == TICK_LABEL) return; + if (customTickLabels.contains(TICK_LABEL)) customTickLabels.remove(TICK_LABEL); + fireUpdateEvent(REDRAW_EVENT); + } + /** + * Clears the list of custom ticklabels + */ + public void clearCustomTickLabels() { + customTickLabels.clear(); + fireUpdateEvent(REDRAW_EVENT); + } + + /** + * Returns the custom font size. The default font size is 18px at + * a size of 250px. This value will be used to calculate the current + * font size for the ticklabels when scaling. + * + * @return the custom font size + */ + public double getCustomTickLabelFontSize() { return null == customTickLabelFontSize ? _customTickLabelFontSize : customTickLabelFontSize.get(); } + /** + * Defines the custom font size. The default font size is 18px at + * a size of 250px. This value will be used to calculate the current + * font size for the ticklabels when scaling. + * + * @param SIZE + */ + public void setCustomTickLabelFontSize(final double SIZE) { + if (null == customTickLabelFontSize) { + _customTickLabelFontSize = Helper.clamp(0.0, 72.0, SIZE); + fireUpdateEvent(REDRAW_EVENT); + } else { + customTickLabelFontSize.set(SIZE); + } + } + public DoubleProperty customTickLabelFontSizeProperty() { + if (null == customTickLabelFontSize) { + customTickLabelFontSize = new DoublePropertyBase(_customTickLabelFontSize) { + @Override protected void invalidated() { + final double SIZE = get(); + if (SIZE < 0 || SIZE > 72) set(Helper.clamp(0.0, 72.0, SIZE)); + fireUpdateEvent(REDRAW_EVENT); + } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "customTickLabelFontSize";} + }; + } + return customTickLabelFontSize; + } + + /** + * Returns true if the gauge is in interactive mode. This is currently + * implemented in the radial gauges that have a knob. If interactive == true + * the knob can be pressed to trigger something. + * + * @return true if the gauge is in interactive mode + */ + public boolean isInteractive() { return null == interactive ? _interactive : interactive.get(); } + /** + * Defines if the gauge is in interactive mode. This is currently + * implemented in the radial gauges that have a knob. If interactive == true + * the knob can be pressed to trigger something. + * + * @param INTERACTIVE + */ + public void setInteractive(final boolean INTERACTIVE) { + if (null == interactive) { + _interactive = INTERACTIVE; + fireUpdateEvent(INTERACTIVITY_EVENT); + } else { + interactive.set(INTERACTIVE); + } + } + public BooleanProperty interactiveProperty() { + if (null == interactive) { + interactive = new BooleanPropertyBase(_interactive) { + @Override protected void invalidated() { fireUpdateEvent(INTERACTIVITY_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "interactive"; } + }; + } + return interactive; + } + + /** + * Returns the text that will be shown in the button tooltip. The + * knob in the radial gauges acts as button if interactive == true. + * + * @return the text that will be shown in the button tooltip + */ + public String getButtonTooltipText() { return null == buttonTooltipText ? _buttonTooltipText : buttonTooltipText.get(); } + /** + * Defines the text that will be shown in the button tooltip. The + * knob in the radial gauges acts as button if interactive == true. + * + * @param TEXT + */ + public void setButtonTooltipText(final String TEXT) { + if (null == buttonTooltipText) { + _buttonTooltipText = TEXT; + fireUpdateEvent(REDRAW_EVENT); + } else { + buttonTooltipText.set(TEXT); + } + } + public StringProperty buttonTooltipTextProperty() { + if (null == buttonTooltipText) { + buttonTooltipText = new StringPropertyBase(_buttonTooltipText) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "buttonTooltipText"; } + }; + _buttonTooltipText = null; + } + return buttonTooltipText; + } + + /** + * Returns true if the control should keep it's aspect. This is + * in principle only needed if the control has different width and + * height. + * + * @return true if the control should keep it's aspect + */ + public boolean isKeepAspect() { return null == keepAspect ? _keepAspect : keepAspect.get(); } + /** + * Defines if the control should keep it's aspect. This is + * in principle only needed if the control has different width and + * height. + * + * @param KEEP + */ + public void setKeepAspect(final boolean KEEP) { + if (null == keepAspect) { + _keepAspect = KEEP; + } else { + keepAspect.set(KEEP); + } + } + public BooleanProperty keepAspectProperty() { + if (null == keepAspect) { keepAspect = new SimpleBooleanProperty(Gauge.this, "keepAspect", _keepAspect); } + return keepAspect; + } + + /** + * Returns true if the control uses the given customFont to + * render all text elements. + * @return true if the control uses the given customFont + */ + public boolean isCustomFontEnabled() { return null == customFontEnabled ? _customFontEnabled : customFontEnabled.get(); } + /** + * Defines if the control should use the given customFont + * to render all text elements + * @param ENABLED + */ + public void setCustomFontEnabled(final boolean ENABLED) { + if (null == customFontEnabled) { + _customFontEnabled = ENABLED; + fireUpdateEvent(RESIZE_EVENT); + } else { + customFontEnabled.set(ENABLED); + } + } + public BooleanProperty customFontEnabledProperty() { + if (null == customFontEnabled) { + customFontEnabled = new BooleanPropertyBase(_customFontEnabled) { + @Override protected void invalidated() { fireUpdateEvent(RESIZE_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "customFontEnabled"; } + }; + } + return customFontEnabled; + } + + /** + * Returns the given custom Font that can be used to render + * all text elements. To enable the custom font one has to set + * customFontEnabled = true + * @return the given custom Font + */ + public Font getCustomFont() { return null == customFont ? _customFont : customFont.get(); } + /** + * Defines the custom font that can be used to render all + * text elements. To enable the custom font one has to set + * customFontEnabled = true + * @param FONT + */ + public void setCustomFont(final Font FONT) { + if (null == customFont) { + _customFont = FONT; + fireUpdateEvent(RESIZE_EVENT); + } else { + customFont.set(FONT); + } + } + public ObjectProperty customFontProperty() { + if (null == customFont) { + customFont = new ObjectPropertyBase() { + @Override protected void invalidated() { fireUpdateEvent(RESIZE_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "customFont"; } + }; + _customFont = null; + } + return customFont; + } + + /** + * Returns true if the alert property was set. + * This property can be used to visualize an alert + * situation in a skin. + * @return true if the alert property was set + */ + public boolean isAlert() { return null == alert ? _alert : alert.get(); } + /** + * Defines if the alert property should be set. This + * property can be used to visualize an alert situation + * in the skin. + * @param ALERT + */ + public void setAlert(final boolean ALERT) { + if (null == alert) { + _alert = ALERT; + fireUpdateEvent(ALERT_EVENT); + } else { + alert.set(ALERT); + } + } + public BooleanProperty alertProperty() { + if (null == alert) { + alert = new BooleanPropertyBase(_alert) { + @Override protected void invalidated() { fireUpdateEvent(ALERT_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "alert"; } + }; + } + return alert; + } + + /** + * Returns the alert message text that could be used in a tooltip + * in case of an alert. + * @return the alert message text + */ + public String getAlertMessage() { return null == alertMessage ? _alertMessage : alertMessage.get(); } + /** + * Defines the text that could be used in a tooltip as an + * alert message. + * @param MESSAGE + */ + public void setAlertMessage(final String MESSAGE) { + if (null == alertMessage) { + _alertMessage = MESSAGE; + fireUpdateEvent(ALERT_EVENT); + } else { + alertMessage.set(MESSAGE); + } + } + public StringProperty alertMessageProperty() { + if (null == alertMessage) { + alertMessage = new StringPropertyBase(_alertMessage) { + @Override protected void invalidated() { fireUpdateEvent(ALERT_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "alertMessage"; } + }; + _alertMessage = null; + } + return alertMessage; + } + + /** + * Returns true when smoothing is enabled. This property is only used + * in the TileSparklineSkin to smooth the path. In a custom skin it + * could be also used for other things. + * @return true when smoothing is enabled + */ + public boolean isSmoothing() { return null == smoothing ? _smoothing : smoothing.get(); } + /** + * Defines if the smoothing property should be enabled/disabled. + * At the moment this is only used in the TileSparklineSkin. + * @param SMOOTHING + */ + public void setSmoothing(final boolean SMOOTHING) { + if (null == smoothing) { + _smoothing = SMOOTHING; + fireUpdateEvent(REDRAW_EVENT); + } else { + smoothing.set(SMOOTHING); + } + } + public BooleanProperty smoothingProperty() { + if (null == smoothing) { + smoothing = new BooleanPropertyBase(_smoothing) { + @Override protected void invalidated() { fireUpdateEvent(REDRAW_EVENT); } + @Override public Object getBean() { return Gauge.this; } + @Override public String getName() { return "smoothing"; } + }; + } + return smoothing; + } + + /*public String getFormatString() { return formatString; } + private void updateFormatString() { + StringBuilder formatBuilder = new StringBuilder("%.").append(getDecimals()).append("f"); + String format = formatBuilder.toString(); + int minLength = String.format(Locale.US, format, getMinValue()).length(); + int maxLength = String.format(Locale.US, format, getMaxValue()).length(); + int length = Math.max(minLength, maxLength); + formatBuilder.setLength(0); + //formatBuilder.append("%").append(length).append(".").append(getDecimals()).append("f"); + formatBuilder.append("%").append(".").append(getDecimals()).append("f"); + formatString = formatBuilder.toString(); + fireUpdateEvent(RESIZE_EVENT); + }*/ + + /** + * Calling this method will lead to a recalculation of the scale + */ + public void calcAutoScale() { + double maxNoOfMajorTicks = 10; + double maxNoOfMinorTicks = 10; + double minValue = getMinValue(); + double maxValue = getMaxValue(); + double range = maxValue - minValue; + double niceRange = (Helper.calcNiceNumber(range, false)); + setMajorTickSpace(Helper.calcNiceNumber(niceRange / (maxNoOfMajorTicks - 1), true)); + double niceMinValue = (Math.floor(minValue / getMajorTickSpace()) * getMajorTickSpace()); + double niceMaxValue = (Math.ceil(maxValue / getMajorTickSpace()) * getMajorTickSpace()); + setMinorTickSpace(Helper.calcNiceNumber(getMajorTickSpace() / (maxNoOfMinorTicks - 1), true)); + setMinValue(niceMinValue); + setMaxValue(niceMaxValue); + } + + + // ******************** Misc ********************************************** + /*private synchronized void createBlinkTask() { + blinkTask = new Callable() { + @Override public Void call() throws Exception { + try { + Platform.runLater(() -> setLedOn(!isLedOn())); + } finally { + if (!Thread.currentThread().isInterrupted()) { + // Schedule the same Callable with the current updateInterval + blinkFuture = blinkService.schedule(this, LED_BLINK_INTERVAL, TimeUnit.MILLISECONDS); + } + } + return null; + } + }; + } + private synchronized void startBlinkExecutorService() { + if (null == blinkTask) { createBlinkTask(); } + if (null == blinkService) { blinkService = new ScheduledThreadPoolExecutor(2, Helper.getThreadFactory("BlinkTask", true)); } + blinkFuture = blinkService.schedule(blinkTask, LED_BLINK_INTERVAL, TimeUnit.MILLISECONDS); + }*/ + + /** + * Calling this method will stop all threads. This is needed when using + * JavaFX on mobile devices when the device goes to sleep mode. + */ + public void stop() { + setLedOn(false); + //if (null != blinkFuture) { blinkFuture.cancel(true); } + //if (null != blinkService) { blinkService.shutdownNow(); } + } + + //private void createShutdownHook() { Runtime.getRuntime().addShutdownHook(new Thread(() -> stop())); } + + @Override public String toString() { + return new StringBuilder("{") + .append("\"title\":").append("\"").append(getTitle()).append("\",") + .append("\"subTitle\":").append("\"").append(getTitle()).append("\",") + .append("\"unit\":").append("\"").append(getUnit()).append("\",") + .append("\"value\":").append(getValue()).append(",") + .append("\"minValue\":").append(getMinValue()).append(",") + .append("\"maxValue\":").append(getMaxValue()).append(",") + .append("\"threshold\":").append(getThreshold()).append(",") + .append("\"minMeasuredValue\":").append(getMinMeasuredValue()).append(",") + .append("\"maxMeasuredValue\":").append(getMaxMeasuredValue()) + .append("}").toString(); + } + + private void setupBinding() { + showing = Bindings.createBooleanBinding(() -> { + if (getScene() != null && getScene().getWindow() != null) { + if (getScene().getWindow().isShowing()) { + while(!updateEventQueue/*.peek() != null*/.isEmpty()) { + UpdateEvent event = updateEventQueue.remove(0); //updateEventQueue.poll(); + for (UpdateEventListener listener : listenerList) { listener.onUpdateEvent(event); } + } + } + return getScene().getWindow().isShowing(); + } else { + return false; + } + }, sceneProperty(), getScene().windowProperty(), getScene().getWindow().showingProperty()); + showing.addListener((o, ov, nv) -> { + if (nv) { + while(!updateEventQueue/*.peek() != null*/.isEmpty()) { + UpdateEvent event = updateEventQueue.remove(0); // .poll(); + for (UpdateEventListener listener : listenerList) { listener.onUpdateEvent(event); } + } + } + }); + } + + + // ******************** Style related ************************************* + @Override protected Skin createDefaultSkin() { + switch (skinType) { +/* + case AMP : return new AmpSkin(Gauge.this); + case PLAIN_AMP : return new PlainAmpSkin(Gauge.this); + case BULLET_CHART : return new BulletChartSkin(Gauge.this); + case DASHBOARD : return new DashboardSkin(Gauge.this); + case FLAT : return new FlatSkin(Gauge.this); + case INDICATOR : return new IndicatorSkin(Gauge.this); + case KPI : return new KpiSkin(Gauge.this); +*/ + case MODERN : return new ModernSkin(Gauge.this); +/* + case SIMPLE : return new SimpleSkin(Gauge.this); + case SLIM : return new SlimSkin(Gauge.this); + case SPACE_X : return new SpaceXSkin(Gauge.this); + case QUARTER : return new QuarterSkin(Gauge.this); + case HORIZONTAL : return new HSkin(Gauge.this); + case VERTICAL : return new VSkin(Gauge.this); + case LCD : return new LcdSkin(Gauge.this); + case TINY : return new TinySkin(Gauge.this); + case BATTERY : return new BatterySkin(Gauge.this); + case LEVEL : return new LevelSkin(Gauge.this); + case LINEAR : return new LinearSkin(Gauge.this); + case DIGITAL : return new DigitalSkin(Gauge.this); + case SIMPLE_DIGITAL : return new SimpleDigitalSkin(Gauge.this); + case SECTION : return new SectionSkin(Gauge.this); + case BAR : return new BarSkin(Gauge.this); + case WHITE : return new WhiteSkin(Gauge.this); + case CHARGE : return new ChargeSkin(Gauge.this); + case SIMPLE_SECTION : return new SimpleSectionSkin(Gauge.this); + case TILE_KPI : return new TileKpiSkin(Gauge.this); + case TILE_TEXT_KPI : return new TileTextKpiSkin(Gauge.this); + case TILE_SPARK_LINE: return new TileSparklineSkin(Gauge.this); + case NASA : return new NasaSkin(Gauge.this); + case GAUGE : + default : return new GaugeSkin(Gauge.this); +*/ + default: return null; + } + } + + /*@Override public String getUserAgentStylesheet() { + if (null == userAgentStyleSheet) { userAgentStyleSheet = getClass().getResource("gauge.css").toExternalForm(); } + return userAgentStyleSheet; + }*/ + + public SkinType getSkinType() { return skinType; } + public void setSkinType(final SkinType SKIN_TYPE) { + skinType = SKIN_TYPE; + presetGaugeParameters(skinType); + switch (SKIN_TYPE) { +/* + case AMP : super.setSkin(new AmpSkin(Gauge.this)); break; + case PLAIN_AMP : super.setSkin(new PlainAmpSkin(Gauge.this)); break; + case BULLET_CHART : super.setSkin(new BulletChartSkin(Gauge.this)); break; + case DASHBOARD : super.setSkin(new DashboardSkin(Gauge.this)); break; + case FLAT : super.setSkin(new FlatSkin(Gauge.this)); break; + case INDICATOR : super.setSkin(new IndicatorSkin(Gauge.this)); break; + case KPI : super.setSkin(new KpiSkin(Gauge.this)); break; +*/ + case MODERN : super.setSkin(new ModernSkin(Gauge.this)); break; +/* + case SIMPLE : super.setSkin(new SimpleSkin(Gauge.this)); break; + case SLIM : super.setSkin(new SlimSkin(Gauge.this)); break; + case SPACE_X : super.setSkin(new SpaceXSkin(Gauge.this)); break; + case QUARTER : super.setSkin(new QuarterSkin(Gauge.this)); break; + case HORIZONTAL : super.setSkin(new HSkin(Gauge.this)); break; + case VERTICAL : super.setSkin(new VSkin(Gauge.this)); break; + case LCD : super.setSkin(new LcdSkin(Gauge.this)); break; + case TINY : super.setSkin(new TinySkin(Gauge.this)); break; + case BATTERY : super.setSkin(new BatterySkin(Gauge.this)); break; + case LEVEL : super.setSkin(new LevelSkin(Gauge.this)); break; + case LINEAR : super.setSkin(new LinearSkin(Gauge.this)); break; + case DIGITAL : super.setSkin(new DigitalSkin(Gauge.this)); break; + case SIMPLE_DIGITAL : super.setSkin(new SimpleDigitalSkin(Gauge.this)); break; + case SECTION : super.setSkin(new SectionSkin(Gauge.this)); break; + case BAR : super.setSkin(new BarSkin(Gauge.this)); break; + case WHITE : super.setSkin(new WhiteSkin(Gauge.this)); break; + case CHARGE : super.setSkin(new ChargeSkin(Gauge.this)); break; + case SIMPLE_SECTION : super.setSkin(new SimpleSectionSkin(Gauge.this)); break; + case TILE_KPI : super.setSkin(new TileKpiSkin(Gauge.this)); break; + case TILE_TEXT_KPI : super.setSkin(new TileTextKpiSkin(Gauge.this)); break; + case TILE_SPARK_LINE: super.setSkin(new TileSparklineSkin(Gauge.this)); break; + case NASA : super.setSkin(new NasaSkin(Gauge.this)); break; + case GAUGE : + default : super.setSkin(new GaugeSkin(Gauge.this)); break; +*/ + } + fireUpdateEvent(RESIZE_EVENT); + } + + public void presetGaugeParameters(final SkinType SKIN_TYPE) { + reInit(); + switch (SKIN_TYPE) { +/* + case AMP: + setKnobPosition(Pos.BOTTOM_CENTER); + setTitleColor(Color.WHITE); + setLedVisible(isLedVisible()); + setBackgroundPaint(Color.WHITE); + setForegroundPaint(Color.BLACK); + setLcdVisible(isLcdVisible()); + setShadowsEnabled(isShadowsEnabled()); + break; + case PLAIN_AMP: + setKnobPosition(Pos.BOTTOM_CENTER); + setTitleColor(Color.WHITE); + setLedVisible(isLedVisible()); + setBackgroundPaint(Color.WHITE); + setForegroundPaint(Color.BLACK); + setLcdVisible(isLcdVisible()); + setShadowsEnabled(isShadowsEnabled()); + break; + case BULLET_CHART: + setKnobPosition(Pos.CENTER); + setBarColor(Color.BLACK); + setThresholdColor(Color.BLACK); + break; + case DASHBOARD: + setKnobPosition(Pos.BOTTOM_CENTER); + setDecimals(0); + setBarBackgroundColor(Color.LIGHTGRAY); + setBarColor(Color.rgb(93, 190, 205)); + break; + case FLAT: + setKnobPosition(Pos.CENTER); + setBarColor(Color.CYAN); + setBackgroundPaint(Color.TRANSPARENT); + setTitleColor(Gauge.DARK_COLOR); + setValueColor(Gauge.DARK_COLOR); + setUnitColor(Gauge.DARK_COLOR); + setBorderPaint(Color.rgb(208, 208, 208)); + setDecimals(0); + break; + case INDICATOR: + setKnobPosition(Pos.BOTTOM_CENTER); + setValueVisible(false); + setGradientBarEnabled(false); + setGradientBarStops(new Stop(0.0, Color.rgb(34, 180, 11)), + new Stop(0.5, Color.rgb(255, 146, 0)), + new Stop(1.0, Color.rgb(255, 0, 39))); + setTickLabelsVisible(false); + setNeedleColor(Color.rgb(71, 71, 71)); + setBarBackgroundColor(Color.rgb(232, 231, 223)); + setBarColor(Color.rgb(255, 0, 39)); + setAngleRange(180); + break; + case KPI: + setKnobPosition(Pos.BOTTOM_CENTER); + setDecimals(0); + setForegroundBaseColor(Color.rgb(126, 126, 127)); + setBarColor(Color.rgb(168, 204, 254)); + setThresholdVisible(true); + setThresholdColor(Color.rgb(45, 86, 184)); + setNeedleColor(Color.rgb(74, 74, 74)); + setAngleRange(128); + break;*/ + case MODERN: + setKnobPosition(Pos.CENTER); + setDecimals(0); + setValueColor(Color.WHITE); + setTitleColor(Color.WHITE); + setSubTitleColor(Color.WHITE); + setUnitColor(Color.WHITE); + setBarColor(Color.rgb(0, 214, 215)); + setNeedleColor(Color.WHITE); + setThresholdColor(Color.rgb(204, 0, 0)); + setTickLabelColor(Color.rgb(151, 151, 151)); + setTickMarkColor(Color.BLACK); + setTickLabelOrientation(TickLabelOrientation.ORTHOGONAL); + break;/* + case SIMPLE: + setKnobPosition(Pos.CENTER); + setBorderPaint(Color.WHITE); + setNeedleBorderColor(Color.WHITE); + setBackgroundPaint(Color.DARKGRAY); + setDecimals(0); + setTickLabelColor(Color.WHITE); + setNeedleColor(Color.web("#5a615f")); + setValueColor(Color.WHITE); + setTitleColor(Color.WHITE); + setSubTitleColor(Color.WHITE); + setSectionsVisible(true); + break; + case SLIM: + setKnobPosition(Pos.CENTER); + setDecimals(2); + setBarBackgroundColor(Color.rgb(62, 67, 73)); + setBarColor(Color.rgb(93, 190, 205)); + setTitleColor(Color.rgb(142, 147, 151)); + setValueColor(Color.rgb(228, 231, 238)); + setUnitColor(Color.rgb(142, 147, 151)); + break; + case SPACE_X: + setKnobPosition(Pos.CENTER); + setDecimals(0); + setThresholdColor(Color.rgb(180, 0, 0)); + setBarBackgroundColor(Color.rgb(169, 169, 169, 0.25)); + setBarColor(Color.rgb(169, 169, 169)); + setTitleColor(Color.WHITE); + setValueColor(Color.WHITE); + setUnitColor(Color.WHITE); + break; + case QUARTER: + setKnobPosition(Pos.BOTTOM_RIGHT); + setAngleRange(90); + break; + case HORIZONTAL: + setKnobPosition(Pos.BOTTOM_CENTER); + setAngleRange(180); + break; + case VERTICAL: + setKnobPosition(Pos.CENTER_RIGHT); + setAngleRange(180); + break; + case LCD: + setDecimals(1); + setTickLabelDecimals(1); + setMinMeasuredValueVisible(isMinMeasuredValueVisible()); + setMaxMeasuredValueVisible(isMaxMeasuredValueVisible()); + setOldValueVisible(isOldValueVisible()); + setBorderPaint(Color.WHITE); + setForegroundPaint(Color.WHITE); + break; + case TINY: + setBorderWidth(24); + setBackgroundPaint(Color.rgb(216, 216, 216)); + setBorderPaint(Color.rgb(76, 76, 76)); + setBarBackgroundColor(Color.rgb(76, 76, 76, 0.2)); + setNeedleColor(Color.rgb(76, 76, 76)); + setSectionsVisible(true); + setMajorTickMarksVisible(true); + setMajorTickMarkColor(Color.WHITE); + break; + case BATTERY: + setBarBackgroundColor(Color.BLACK); + setBarColor(Color.BLACK); + setValueColor(Color.WHITE); + break; + case LEVEL: + setValueColor(Color.WHITE); + setBarColor(Color.CYAN); + break; + case LINEAR: + setOrientation(Orientation.VERTICAL); + setBarColor(DARK_COLOR); + setBarEffectEnabled(true); + break; + case DIGITAL: + setBarColor(DARK_COLOR); + break; + case SIMPLE_DIGITAL: + setBarBackgroundColor(Helper.getTranslucentColorFrom(DARK_COLOR, 0.1)); + setBarColor(DARK_COLOR); + break; + case SECTION: + setBackgroundPaint(Gauge.DARK_COLOR); + setAutoScale(false); + setValueVisible(false); + setKnobColor(Color.rgb(82, 82, 84)); + setSectionsVisible(true); + setSectionTextVisible(true); + break; + case BAR: + Color barColor = getBarColor(); + setAnimated(true); + setAnimationDuration(1000); + setMinValue(0); + setMaxValue(100); + setGradientBarEnabled(true); + setGradientBarStops(new Stop(0.0, barColor), + new Stop(0.01, barColor), + new Stop(0.75, barColor.deriveColor(-10, 1, 1, 1)), + new Stop(1.0, barColor.deriveColor(-20, 1, 1, 1))); + break; + case WHITE: + setAnimated(true); + setAnimationDuration(1000); + setAngleRange(360); + setMinValue(0); + setMaxValue(100); + setBarColor(Color.WHITE); + setValueColor(Color.WHITE); + setUnitColor(Color.WHITE); + break; + case CHARGE: + setAnimated(true); + setMinValue(0.0); + setMaxValue(1.0); + break; + case SIMPLE_SECTION: + setAnimated(true); + setStartAngle(150); + setAngleRange(300); + setSectionsVisible(true); + setBarBackgroundColor(Color.rgb(150, 150, 150, 0.25)); + setBarColor(Color.rgb(69, 106, 207)); + setTitleColor(Color.rgb(90, 90, 90)); + setUnitColor(Color.rgb(90, 90, 90)); + setValueColor(Color.rgb(90, 90, 90)); + break; + case TILE_KPI: + setKnobPosition(Pos.BOTTOM_CENTER); + setDecimals(0); + setValueColor(Color.rgb(238, 238, 238)); + setBackgroundPaint(Color.rgb(42,42,42)); + setForegroundBaseColor(Color.rgb(238,238,238)); + setBarColor(Color.rgb(238,238,238)); + setThresholdVisible(false); + setThresholdColor(Color.rgb(41,177,255)); + setNeedleColor(Color.rgb(238,238,238)); + setAngleRange(180); + break; + case TILE_TEXT_KPI: + setDecimals(0); + setBackgroundPaint(Color.rgb(42,42,42)); + setForegroundBaseColor(Color.rgb(238,238,238)); + setBarColor(Color.rgb(41,177,255)); + setValueColor(Color.rgb(238, 238, 238)); + setUnitColor(Color.rgb(238, 238, 238)); + setThresholdVisible(false); + setThresholdColor(Color.rgb(139,144,146)); + break; + case TILE_SPARK_LINE: + setDecimals(0); + setBackgroundPaint(Color.rgb(42,42,42)); + setForegroundBaseColor(Color.rgb(238,238,238)); + setBarColor(Color.rgb(41,177,255)); + setValueColor(Color.rgb(238, 238, 238)); + setUnitColor(Color.rgb(238, 238, 238)); + setAveragingEnabled(true); + setAveragingPeriod(10); + setAverageColor(Color.rgb(238, 238, 238, 0.5)); + setAnimated(false); + break; + case NASA: + setBarBackgroundColor(Color.TRANSPARENT); + setForegroundBaseColor(Color.WHITE); + setStartAngle(108); + setAngleRange(216); + setTickLabelsVisible(false); + setMediumTickMarksVisible(false); + setMajorTickMarksVisible(false); + break; + case GAUGE: + setStartAngle(320); + setAngleRange(280); +*/ + default: + break; + } + } + + + // ******************** Event handling ************************************ + public void setOnUpdate(final UpdateEventListener LISTENER) { addUpdateEventListener(LISTENER); } + public void addUpdateEventListener(final UpdateEventListener LISTENER) { if (!listenerList.contains(LISTENER)) listenerList.add(LISTENER); } + public void removeUpdateEventListener(final UpdateEventListener LISTENER) { if (listenerList.contains(LISTENER)) listenerList.remove(LISTENER); } + + public void fireUpdateEvent(final UpdateEvent EVENT) { + if (null != showing && showing.get()) { + for (UpdateEventListener listener : listenerList) { listener.onUpdateEvent(EVENT); } + } else { + updateEventQueue.add(EVENT); + } + } + + + public void setOnButtonPressed(final EventHandler HANDLER) { addEventHandler(ButtonEvent.BTN_PRESSED, HANDLER); } + public void removeOnButtonPressed(final EventHandler HANDLER) { removeEventHandler(ButtonEvent.BTN_PRESSED, HANDLER); } + + public void setOnButtonReleased(final EventHandler HANDLER) { addEventHandler(ButtonEvent.BTN_RELEASED, HANDLER); } + public void removeOnButtonReleased(final EventHandler HANDLER) { removeEventHandler(ButtonEvent.BTN_RELEASED, HANDLER); } + + + public void setOnThresholdExceeded(final EventHandler HANDLER) { addEventHandler(ThresholdEvent.THRESHOLD_EXCEEDED, HANDLER); } + public void removeOnThresholdExceeded(final EventHandler HANDLER) { removeEventHandler(ThresholdEvent.THRESHOLD_EXCEEDED, HANDLER); } + + public void setOnThresholdUnderrun(final EventHandler HANDLER) { addEventHandler(ThresholdEvent.THRESHOLD_UNDERRUN, HANDLER); } + public void removeOnThresholdUnderrun(final EventHandler HANDLER) { removeEventHandler(ThresholdEvent.THRESHOLD_UNDERRUN, HANDLER); } + + + // ******************** Inner Classes ************************************* + public static class ButtonEvent extends Event { + public static final EventType BTN_PRESSED = new EventType<>(ANY, "BTN_PRESSED" + Uuid.randomUuid().toString()); + public static final EventType BTN_RELEASED = new EventType<>(ANY, "BTN_RELEASED" + Uuid.randomUuid().toString()); + + + // ******************** Constructors ************************************** + public ButtonEvent(final EventType TYPE) { super(TYPE); } + public ButtonEvent(final Object SOURCE, final EventTarget TARGET, EventType TYPE) { super(SOURCE, TARGET, TYPE); } + } + + public static class ThresholdEvent extends Event { + public static final EventType THRESHOLD_EXCEEDED = new EventType<>(ANY, "THRESHOLD_EXCEEDED" + Uuid.randomUuid().toString()); + public static final EventType THRESHOLD_UNDERRUN = new EventType<>(ANY, "THRESHOLD_UNDERRUN" + Uuid.randomUuid().toString()); + + + // ******************** Constructors ************************************** + public ThresholdEvent(final EventType TYPE) { super(TYPE); } + public ThresholdEvent(final Object SOURCE, final EventTarget TARGET, EventType TYPE) { super(SOURCE, TARGET, TYPE); } + } +} diff --git a/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/GaugeBuilder.java b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/GaugeBuilder.java new file mode 100644 index 0000000..2ed2b2e --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/GaugeBuilder.java @@ -0,0 +1,1442 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2016-2020 Gerrit Grunwald. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.hansolo.medusa; + +import eu.hansolo.medusa.Gauge.*; +import javafx.beans.InvalidationListener; +import javafx.beans.property.*; +import javafx.event.EventHandler; +import javafx.geometry.Dimension2D; +import javafx.geometry.Insets; +import javafx.geometry.Orientation; +import javafx.geometry.Pos; +import javafx.scene.paint.Color; +import javafx.scene.paint.Paint; +import javafx.scene.paint.Stop; +import javafx.scene.text.Font; + +import java.util.HashMap; +import java.util.List; +import java.util.Locale; + + +/** + * Created by hansolo on 13.12.15. + */ +public class GaugeBuilder> { + private HashMap properties = new HashMap<>(); + + + // ******************** Constructors ************************************** + protected GaugeBuilder() {} + + + // ******************** Methods ******************************************* + public static final GaugeBuilder create() { + return new GaugeBuilder(); + } + + public final B skinType(final SkinType TYPE) { + properties.put("skinType", new SimpleObjectProperty<>(TYPE)); + return (B)this; + } + + public final B value(final double VALUE) { + properties.put("value", new SimpleDoubleProperty(VALUE)); + return (B) this; + } + + public final B minValue(final double VALUE) { + properties.put("minValue", new SimpleDoubleProperty(VALUE)); + return (B) this; + } + + public final B maxValue(final double VALUE) { + properties.put("maxValue", new SimpleDoubleProperty(VALUE)); + return (B) this; + } + + public final B threshold(final double VALUE) { + properties.put("threshold", new SimpleDoubleProperty(VALUE)); + return (B)this; + } + + public final B decimals(final int DECIMALS) { + properties.put("decimals", new SimpleIntegerProperty(DECIMALS)); + return (B) this; + } + + public final B tickLabelDecimals(final int DECIMALS) { + properties.put("tickLabelDecimals", new SimpleIntegerProperty(DECIMALS)); + return (B)this; + } + + public final B title(final String TITLE) { + properties.put("title", new SimpleStringProperty(TITLE)); + return (B)this; + } + + public final B subTitle(final String SUBTITLE) { + properties.put("subTitle", new SimpleStringProperty(SUBTITLE)); + return (B)this; + } + + public final B unit(final String UNIT) { + properties.put("unit", new SimpleStringProperty(UNIT)); + return (B)this; + } + + public final B averagingEnabled(final boolean ENABLED) { + properties.put("averagingEnabled", new SimpleBooleanProperty(ENABLED)); + return (B)this; + } + + public final B averagingPeriod(final int PERIOD) { + properties.put("averagingPeriod", new SimpleIntegerProperty(PERIOD)); + return (B)this; + } + + public final B foregroundBaseColor(final Color COLOR) { + properties.put("foregroundBaseColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B startFromZero(final boolean START) { + properties.put("startFromZero", new SimpleBooleanProperty(START)); + return (B)this; + } + + public final B returnToZero(final boolean RETURN) { + properties.put("returnToZero", new SimpleBooleanProperty(RETURN)); + return (B)this; + } + + public final B zeroColor(final Color COLOR) { + properties.put("zeroColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B minMeasuredValueVisible(final boolean VISIBLE) { + properties.put("minMeasuredValueVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B maxMeasuredValueVisible(final boolean VISIBLE) { + properties.put("maxMeasuredValueVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B oldValueVisible(final boolean VISIBLE) { + properties.put("oldValueVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B valueVisible(final boolean VISIBLE) { + properties.put("valueVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B backgroundPaint(final Paint PAINT) { + properties.put("backgroundPaint", new SimpleObjectProperty<>(PAINT)); + return (B)this; + } + + public final B borderPaint(final Paint PAINT) { + properties.put("borderPaint", new SimpleObjectProperty<>(PAINT)); + return (B)this; + } + + public final B borderWidth(final double WIDTH) { + properties.put("borderWidth", new SimpleDoubleProperty(WIDTH)); + return (B)this; + } + + public final B foregroundPaint(final Paint PAINT) { + properties.put("foregroundPaint", new SimpleObjectProperty<>(PAINT)); + return (B)this; + } + + public final B knobColor(final Color COLOR) { + properties.put("knobColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B knobType(final KnobType TYPE) { + properties.put("knobType", new SimpleObjectProperty<>(TYPE)); + return (B)this; + } + + public final B knobVisible(final boolean VISIBLE) { + properties.put("knobVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B knobPosition(final Pos POSITION) { + properties.put("knobPosition", new SimpleObjectProperty<>(POSITION)); + return (B)this; + } + + public final B animated(final boolean ANIMATED) { + properties.put("animated", new SimpleBooleanProperty(ANIMATED)); + return (B)this; + } + + public final B animationDuration(final long DURATION) { + properties.put("animationDuration", new SimpleLongProperty(DURATION)); + return (B)this; + } + + public final B startAngle(final double ANGLE) { + properties.put("startAngle", new SimpleDoubleProperty(ANGLE)); + return (B)this; + } + + public final B angleRange(final double RANGE) { + properties.put("angleRange", new SimpleDoubleProperty(RANGE)); + return (B)this; + } + + public final B arcExtend(final double ARC_EXTEND) { + properties.put("arcExtend", new SimpleDoubleProperty(ARC_EXTEND)); + return (B)this; + } + + public final B autoScale(final boolean AUTO_SCALE) { + properties.put("autoScale", new SimpleBooleanProperty(AUTO_SCALE)); + return (B)this; + } + + public final B needleType(final NeedleType TYPE) { + properties.put("needleType", new SimpleObjectProperty<>(TYPE)); + return (B)this; + } + + public final B needleShape(final NeedleShape SHAPE) { + properties.put("needleShape", new SimpleObjectProperty<>(SHAPE)); + return (B)this; + } + + public final B needleSize(final NeedleSize SIZE) { + properties.put("needleSize", new SimpleObjectProperty<>(SIZE)); + return (B)this; + } + + public final B needleBehavior(final NeedleBehavior BEHAVIOR) { + properties.put("needleBehavior", new SimpleObjectProperty<>(BEHAVIOR)); + return (B)this; + } + + public final B needleColor(final Color COLOR) { + properties.put("needleColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B needleBorderColor(final Color COLOR) { + properties.put("needleBorderColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B barColor(final Color COLOR) { + properties.put("barColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B barBorderColor(final Color COLOR) { + properties.put("barBorderColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B barBackgroundColor(final Color COLOR) { + properties.put("barBackgroundColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B tickLabelOrientation(final TickLabelOrientation ORIENTATION) { + properties.put("tickLabelOrientation", new SimpleObjectProperty<>(ORIENTATION)); + return (B)this; + } + + public final B tickLabelLocation(final TickLabelLocation LOCATION) { + properties.put("tickLabelLocation", new SimpleObjectProperty<>(LOCATION)); + return (B)this; + } + + public final B locale(final Locale LOCALE) { + properties.put("locale", new SimpleObjectProperty<>(LOCALE)); + return (B)this; + } + + public final B majorTickSpace(final double SPACE) { + properties.put("majorTickSpace", new SimpleDoubleProperty(SPACE)); + return (B)this; + } + + public final B minorTickSpace(final double SPACE) { + properties.put("minorTickSpace", new SimpleDoubleProperty(SPACE)); + return (B)this; + } + + public final B shadowsEnabled(final boolean ENABLED) { + properties.put("shadowsEnabled", new SimpleBooleanProperty(ENABLED)); + return (B)this; + } + + public final B barEffectEnabled(final boolean ENABLED) { + properties.put("barEffectEnabled", new SimpleBooleanProperty(ENABLED)); + return (B)this; + } + + public final B scaleDirection(final ScaleDirection DIRECTION) { + properties.put("scaleDirection", new SimpleObjectProperty<>(DIRECTION)); + return (B)this; + } + + public final B tickLabelColor(final Color COLOR) { + properties.put("tickLabelColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B tickMarkColor(final Color COLOR) { + properties.put("tickMarkColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B majorTickMarkColor(final Color COLOR) { + properties.put("majorTickMarkColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B majorTickMarkLengthFactor(final double FACTOR) { + properties.put("majorTickMarkLengthFactor", new SimpleDoubleProperty(FACTOR)); + return (B)this; + } + + public final B majorTickMarkWidthFactor(final double FACTOR) { + properties.put("majorTickMarkWidthFactor", new SimpleDoubleProperty(FACTOR)); + return (B)this; + } + + public final B mediumTickMarkColor(final Color COLOR) { + properties.put("mediumTickMarkColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B mediumTickMarkLengthFactor(final double FACTOR) { + properties.put("mediumTickMarkLengthFactor", new SimpleDoubleProperty(FACTOR)); + return (B)this; + } + + public final B mediumTickMarkWidthFactor(final double FACTOR) { + properties.put("mediumTickMarkWidthFactor", new SimpleDoubleProperty(FACTOR)); + return (B)this; + } + + public final B minorTickMarkColor(final Color COLOR) { + properties.put("minorTickMarkColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B minorTickMarkLengthFactor(final double FACTOR) { + properties.put("minorTickMarkLengthFactor", new SimpleDoubleProperty(FACTOR)); + return (B)this; + } + + public final B minorTickMarkWidthFactor(final double FACTOR) { + properties.put("minorTickMarkWidthFactor", new SimpleDoubleProperty(FACTOR)); + return (B)this; + } + + public final B majorTickMarkType(final TickMarkType TYPE) { + properties.put("majorTickMarkType", new SimpleObjectProperty<>(TYPE)); + return (B)this; + } + + public final B mediumTickMarkType(final TickMarkType TYPE) { + properties.put("mediumTickMarkType", new SimpleObjectProperty<>(TYPE)); + return (B)this; + } + + public final B minorTickMarkType(final TickMarkType TYPE) { + properties.put("minorTickMarkType", new SimpleObjectProperty<>(TYPE)); + return (B)this; + } + + public final B style(final String STYLE) { + properties.put("style", new SimpleStringProperty(STYLE)); + return (B)this; + } + + public final B styleClass(final String... STYLES) { + properties.put("styleClass", new SimpleObjectProperty<>(STYLES)); + return (B)this; + } + + public final B ledColor(final Color COLOR) { + properties.put("ledColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B ledType(final LedType TYPE) { + properties.put("ledType", new SimpleObjectProperty<>(TYPE)); + return (B)this; + } + + public final B ledVisible(final boolean VISIBLE) { + properties.put("ledVisible", new SimpleBooleanProperty(VISIBLE)); + return (B) this; + } + +/* + public final B lcdVisible(final boolean VISIBLE) { + properties.put("lcdVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B lcdCrystalEnabled(final boolean ENABLED) { + properties.put("lcdCrystalEnabled", new SimpleBooleanProperty(ENABLED)); + return (B)this; + } + + public final B lcdDesign(final LcdDesign DESIGN) { + properties.put("lcdDesign", new SimpleObjectProperty<>(DESIGN)); + return (B)this; + } + + public final B lcdFont(final LcdFont FONT) { + properties.put("lcdFont", new SimpleObjectProperty<>(FONT)); + return (B)this; + } +*/ + +/* + public final B sections(final Section... SECTIONS) { + properties.put("sectionsArray", new SimpleObjectProperty<>(SECTIONS)); + return (B)this; + } + + public final B sections(final List
SECTIONS) { + properties.put("sectionsList", new SimpleObjectProperty<>(SECTIONS)); + return (B)this; + } + + public final B areas(final Section... AREAS) { + properties.put("areasArray", new SimpleObjectProperty<>(AREAS)); + return (B)this; + } + + public final B areas(final List
AREAS) { + properties.put("areasList", new SimpleObjectProperty<>(AREAS)); + return (B)this; + } + + public final B tickMarkSections(final Section... SECTIONS) { + properties.put("tickMarkSectionsArray", new SimpleObjectProperty<>(SECTIONS)); + return (B)this; + } + + public final B tickMarkSections(final List
SECTIONS) { + properties.put("tickMarkSectionsList", new SimpleObjectProperty<>(SECTIONS)); + return (B)this; + } + + public final B tickLabelSections(final Section... SECTIONS) { + properties.put("tickLabelSectionsArray", new SimpleObjectProperty<>(SECTIONS)); + return (B)this; + } + + public final B tickLabelSections(final List
SECTIONS) { + properties.put("tickLabelSectionsList", new SimpleObjectProperty<>(SECTIONS)); + return (B)this; + } +*/ + +/* + public final B markers(final Marker... MARKERS) { + properties.put("markersArray", new SimpleObjectProperty<>(MARKERS)); + return (B)this; + } + + public final B markers(final List MARKERS) { + properties.put("markersList", new SimpleObjectProperty<>(MARKERS)); + return (B)this; + } +*/ + + public final B titleColor(final Color COLOR) { + properties.put("titleColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B subTitleColor(final Color COLOR) { + properties.put("subTitleColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public B unitColor(final Color COLOR) { + properties.put("unitColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public B valueColor(final Color COLOR) { + properties.put("valueColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public B thresholdColor(final Color COLOR) { + properties.put("thresholdColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public B averageColor(final Color COLOR) { + properties.put("averageColor", new SimpleObjectProperty<>(COLOR)); + return (B)this; + } + + public final B checkSectionsForValue(final boolean CHECK) { + properties.put("checkSectionsForValue", new SimpleBooleanProperty(CHECK)); + return (B)this; + } + + public final B checkAreasForValue(final boolean CHECK) { + properties.put("checkAreasForValue", new SimpleBooleanProperty(CHECK)); + return (B)this; + } + + public final B checkThreshold(final boolean CHECK) { + properties.put("checkThreshold", new SimpleBooleanProperty(CHECK)); + return (B)this; + } + + public final B innerShadowEnabled(final boolean ENABLED) { + properties.put("innerShadowEnabled", new SimpleBooleanProperty(ENABLED)); + return (B)this; + } + + public final B thresholdVisible(final boolean VISIBLE) { + properties.put("thresholdVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B averageVisible(final boolean VISIBLE) { + properties.put("averageVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B sectionsVisible(final boolean VISIBLE) { + properties.put("sectionsVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B sectionsAlwaysVisible(final boolean VISIBLE) { + properties.put("sectionsAlwaysVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B sectionTextVisible(final boolean VISIBLE) { + properties.put("sectionTextVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B sectionIconsVisible(final boolean VISIBLE) { + properties.put("sectionIconsVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B highlightSections(final boolean HIGHLIGHT) { + properties.put("highlightSections", new SimpleBooleanProperty(HIGHLIGHT)); + return (B)this; + } + + public final B areasVisible(final boolean VISIBLE) { + properties.put("areasVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B areaTextVisible(final boolean VISIBLE) { + properties.put("areaTextVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B areaIconsVisible(final boolean VISIBLE) { + properties.put("areaIconsVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B highlightAreas(final boolean HIGHLIGHT) { + properties.put("highlightAreas", new SimpleBooleanProperty(HIGHLIGHT)); + return (B)this; + } + + public final B tickMarkSectionsVisible(final boolean VISIBLE) { + properties.put("tickMarkSectionsVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B tickLabelSectionsVisible(final boolean VISIBLE) { + properties.put("tickLabelSectionsVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B markersVisible(final boolean VISIBLE) { + properties.put("markersVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B tickLabelsVisible(final boolean VISIBLE) { + properties.put("tickLabelsVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B onlyFirstAndLastTickLabelVisible(final boolean VISIBLE) { + properties.put("onlyFirstAndLastTickLabelVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B majorTickMarksVisible(final boolean VISIBLE) { + properties.put("majorTickMarksVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B mediumTickMarksVisible(final boolean VISIBLE) { + properties.put("mediumTickMarksVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B minorTickMarksVisible(final boolean VISIBLE) { + properties.put("minorTickMarksVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B tickMarkRingVisible(final boolean VISIBLE) { + properties.put("tickMarkRingVisible", new SimpleBooleanProperty(VISIBLE)); + return (B)this; + } + + public final B ledOn(final boolean ON) { + properties.put("ledOn", new SimpleBooleanProperty(ON)); + return (B)this; + } + + public final B ledBlinking(final boolean BLINKING) { + properties.put("ledBlinking", new SimpleBooleanProperty(BLINKING)); + return (B)this; + } + + public final B orientation(final Orientation ORIENTATION) { + properties.put("orientation", new SimpleObjectProperty<>(ORIENTATION)); + return (B)this; + } + + public final B gradientBarEnabled(final boolean ENABLED) { + properties.put("gradientBarEnabled", new SimpleBooleanProperty(ENABLED)); + return (B)this; + } + +/* + public final B gradientLookup(final GradientLookup GRADIENT_LOOKUP) { + properties.put("gradientLookup", new SimpleObjectProperty<>(GRADIENT_LOOKUP)); + return (B)this; + } +*/ + + public final B gradientBarStops(final Stop... STOPS) { + properties.put("gradientBarStopsArray", new SimpleObjectProperty<>(STOPS)); + return (B)this; + } + + public final B gradientBarStops(final List STOPS) { + properties.put("gradientBarStopsList", new SimpleObjectProperty<>(STOPS)); + return (B)this; + } + + public final B customTickLabelsEnabled(final boolean ENABLED) { + properties.put("customTickLabelsEnabled", new SimpleBooleanProperty(ENABLED)); + return (B)this; + } + + public final B customTickLabels(final String... TICK_LABELS) { + properties.put("customTickLabelsArray", new SimpleObjectProperty<>(TICK_LABELS)); + return (B)this; + } + + public final B customTickLabels(final List TICK_LABELS) { + properties.put("customTickLabelsList", new SimpleObjectProperty<>(TICK_LABELS)); + return (B)this; + } + + public final B customTickLabelFontSize(final double SIZE) { + properties.put("customTickLabelFontSize", new SimpleDoubleProperty(SIZE)); + return (B)this; + } + + public final B interactive(final boolean INTERACTIVE) { + properties.put("interactive", new SimpleBooleanProperty(INTERACTIVE)); + return (B)this; + } + + public final B buttonTooltipText(final String TEXT) { + properties.put("buttonTooltipText", new SimpleStringProperty(TEXT)); + return (B)this; + } + + public final B keepAspect(final boolean KEEP) { + properties.put("keepAspect", new SimpleBooleanProperty(KEEP)); + return (B)this; + } + + public final B customFontEnabled(final boolean ENABLED) { + properties.put("customFontEnabled", new SimpleBooleanProperty(ENABLED)); + return (B)this; + } + + public final B customFont(final Font FONT) { + properties.put("customFont", new SimpleObjectProperty(FONT)); + return (B)this; + } + + public final B alertMessage(final String MESSAGE) { + properties.put("alertMessage", new SimpleStringProperty(MESSAGE)); + return (B)this; + } + + public final B smoothing(final boolean SMOOTHING) { + properties.put("smoothing", new SimpleBooleanProperty(SMOOTHING)); + return (B)this; + } + + public final B onValueChanged(final InvalidationListener LISTENER) { + properties.put("onValueChanged", new SimpleObjectProperty<>(LISTENER)); + return (B)this; + } + + public final B onButtonPressed(final EventHandler HANDLER) { + properties.put("onButtonPressed", new SimpleObjectProperty<>(HANDLER)); + return (B)this; + } + + public final B onButtonReleased(final EventHandler HANDLER) { + properties.put("onButtonReleased", new SimpleObjectProperty<>(HANDLER)); + return (B)this; + } + + public final B onThresholdExceeded(final EventHandler HANDLER) { + properties.put("onThresholdExceeded", new SimpleObjectProperty<>(HANDLER)); + return (B)this; + } + + public final B onThresholdUnderrun(final EventHandler HANDLER) { + properties.put("onThresholdUnderrun", new SimpleObjectProperty<>(HANDLER)); + return (B)this; + } + + public final B prefSize(final double WIDTH, final double HEIGHT) { + properties.put("prefSize", new SimpleObjectProperty<>(new Dimension2D(WIDTH, HEIGHT))); + return (B)this; + } + public final B minSize(final double WIDTH, final double HEIGHT) { + properties.put("minSize", new SimpleObjectProperty<>(new Dimension2D(WIDTH, HEIGHT))); + return (B)this; + } + public final B maxSize(final double WIDTH, final double HEIGHT) { + properties.put("maxSize", new SimpleObjectProperty<>(new Dimension2D(WIDTH, HEIGHT))); + return (B)this; + } + + public final B prefWidth(final double PREF_WIDTH) { + properties.put("prefWidth", new SimpleDoubleProperty(PREF_WIDTH)); + return (B)this; + } + public final B prefHeight(final double PREF_HEIGHT) { + properties.put("prefHeight", new SimpleDoubleProperty(PREF_HEIGHT)); + return (B)this; + } + + public final B minWidth(final double MIN_WIDTH) { + properties.put("minWidth", new SimpleDoubleProperty(MIN_WIDTH)); + return (B)this; + } + public final B minHeight(final double MIN_HEIGHT) { + properties.put("minHeight", new SimpleDoubleProperty(MIN_HEIGHT)); + return (B)this; + } + + public final B maxWidth(final double MAX_WIDTH) { + properties.put("maxWidth", new SimpleDoubleProperty(MAX_WIDTH)); + return (B)this; + } + public final B maxHeight(final double MAX_HEIGHT) { + properties.put("maxHeight", new SimpleDoubleProperty(MAX_HEIGHT)); + return (B)this; + } + + public final B scaleX(final double SCALE_X) { + properties.put("scaleX", new SimpleDoubleProperty(SCALE_X)); + return (B)this; + } + public final B scaleY(final double SCALE_Y) { + properties.put("scaleY", new SimpleDoubleProperty(SCALE_Y)); + return (B)this; + } + + public final B layoutX(final double LAYOUT_X) { + properties.put("layoutX", new SimpleDoubleProperty(LAYOUT_X)); + return (B)this; + } + public final B layoutY(final double LAYOUT_Y) { + properties.put("layoutY", new SimpleDoubleProperty(LAYOUT_Y)); + return (B)this; + } + + public final B translateX(final double TRANSLATE_X) { + properties.put("translateX", new SimpleDoubleProperty(TRANSLATE_X)); + return (B)this; + } + public final B translateY(final double TRANSLATE_Y) { + properties.put("translateY", new SimpleDoubleProperty(TRANSLATE_Y)); + return (B)this; + } + + public final B padding(final Insets INSETS) { + properties.put("padding", new SimpleObjectProperty<>(INSETS)); + return (B)this; + } + + public final Gauge build() { + final Gauge CONTROL; + if (properties.containsKey("skinType")) { + SkinType skinType = ((ObjectProperty) properties.get("skinType")).get(); + CONTROL = new Gauge(skinType); + switch(skinType) { +/* + case AMP: + CONTROL.setKnobPosition(Pos.BOTTOM_CENTER); + CONTROL.setTitleColor(Color.WHITE); + CONTROL.setLedVisible(true); + CONTROL.setBackgroundPaint(Color.WHITE); + CONTROL.setForegroundPaint(Color.BLACK); + CONTROL.setLcdVisible(true); + CONTROL.setShadowsEnabled(true); + break; + case PLAIN_AMP: + CONTROL.setKnobPosition(Pos.BOTTOM_CENTER); + CONTROL.setTitleColor(Color.WHITE); + CONTROL.setLedVisible(true); + CONTROL.setBackgroundPaint(Color.WHITE); + CONTROL.setForegroundPaint(Color.BLACK); + CONTROL.setLcdVisible(true); + CONTROL.setShadowsEnabled(true); + break; + case BULLET_CHART: + CONTROL.setKnobPosition(Pos.CENTER); + CONTROL.setBarColor(Color.BLACK); + CONTROL.setThresholdColor(Color.BLACK); + break; + case DASHBOARD: + CONTROL.setKnobPosition(Pos.BOTTOM_CENTER); + CONTROL.setDecimals(0); + CONTROL.setBarBackgroundColor(Color.LIGHTGRAY); + CONTROL.setBarColor(Color.rgb(93,190,205)); + CONTROL.setStartFromZero(false); + break; + case FLAT: + CONTROL.setKnobPosition(Pos.CENTER); + CONTROL.setBarColor(Color.CYAN); + CONTROL.setBackgroundPaint(Color.TRANSPARENT); + CONTROL.setTitleColor(Gauge.DARK_COLOR); + CONTROL.setValueColor(Gauge.DARK_COLOR); + CONTROL.setUnitColor(Gauge.DARK_COLOR); + CONTROL.setBorderPaint(Color.rgb(208, 208, 208)); + CONTROL.setDecimals(0); + CONTROL.setStartFromZero(true); + break; + case INDICATOR: + CONTROL.setKnobPosition(Pos.BOTTOM_CENTER); + CONTROL.setValueVisible(false); + CONTROL.setGradientBarEnabled(false); + CONTROL.setGradientBarStops(new Stop(0.0, Color.rgb(34,180,11)), + new Stop(0.5, Color.rgb(255,146,0)), + new Stop(1.0, Color.rgb(255,0,39))); + CONTROL.setTickLabelsVisible(false); + CONTROL.setNeedleColor(Color.rgb(71,71,71)); + CONTROL.setBarBackgroundColor(Color.rgb(232,231,223)); + CONTROL.setBarColor(Color.rgb(255,0,39)); + CONTROL.setAngleRange(180); + break; + case KPI: + CONTROL.setKnobPosition(Pos.BOTTOM_CENTER); + CONTROL.setDecimals(0); + CONTROL.setForegroundBaseColor(Color.rgb(126,126,127)); + CONTROL.setBarColor(Color.rgb(168,204,254)); + CONTROL.setThresholdVisible(true); + CONTROL.setThresholdColor(Color.rgb(45,86,184)); + CONTROL.setNeedleColor(Color.rgb(74,74,74)); + CONTROL.setAngleRange(128); + break;*/ + case MODERN: + CONTROL.setKnobPosition(Pos.CENTER); + CONTROL.setDecimals(0); + CONTROL.setValueColor(Color.WHITE); + CONTROL.setTitleColor(Color.WHITE); + CONTROL.setSubTitleColor(Color.WHITE); + CONTROL.setUnitColor(Color.WHITE); + CONTROL.setBarColor(Color.rgb(0, 214, 215)); + CONTROL.setNeedleColor(Color.WHITE); + CONTROL.setThresholdColor(Color.rgb(204, 0, 0)); + CONTROL.setTickLabelColor(Color.rgb(151, 151, 151)); + CONTROL.setTickMarkColor(Color.BLACK); + CONTROL.setTickLabelOrientation(TickLabelOrientation.ORTHOGONAL); + break;/* + case SIMPLE: + CONTROL.setKnobPosition(Pos.CENTER); + CONTROL.setBorderPaint(Color.WHITE); + CONTROL.setNeedleBorderColor(Color.WHITE); + CONTROL.setBackgroundPaint(Color.DARKGRAY); + CONTROL.setDecimals(0); + CONTROL.setTickLabelColor(Color.WHITE); + CONTROL.setNeedleColor(Color.web("#5a615f")); + CONTROL.setValueColor(Color.WHITE); + CONTROL.setTitleColor(Color.WHITE); + CONTROL.setSubTitleColor(Color.WHITE); + CONTROL.setSectionsVisible(true); + break; + case SLIM: + CONTROL.setKnobPosition(Pos.CENTER); + CONTROL.setDecimals(2); + CONTROL.setStartFromZero(true); + CONTROL.setBarBackgroundColor(Color.rgb(62, 67, 73)); + CONTROL.setBarColor(Color.rgb(93,190,205)); + CONTROL.setTitleColor(Color.rgb(142,147,151)); + CONTROL.setValueColor(Color.rgb(228,231,238)); + CONTROL.setUnitColor(Color.rgb(142,147,151)); + break; + case SPACE_X: + CONTROL.setKnobPosition(Pos.CENTER); + CONTROL.setDecimals(0); + CONTROL.setThresholdColor(Color.rgb(180, 0, 0)); + CONTROL.setBarBackgroundColor(Color.rgb(169, 169, 169, 0.25)); + CONTROL.setBarColor(Color.rgb(169, 169, 169)); + CONTROL.setTitleColor(Color.WHITE); + CONTROL.setValueColor(Color.WHITE); + CONTROL.setUnitColor(Color.WHITE); + break; + case QUARTER: + CONTROL.setKnobPosition(Pos.BOTTOM_RIGHT); + CONTROL.setAngleRange(90); + break; + case HORIZONTAL: + CONTROL.setKnobPosition(Pos.BOTTOM_CENTER); + CONTROL.setAngleRange(180); + break; + case VERTICAL: + CONTROL.setKnobPosition(Pos.CENTER_RIGHT); + CONTROL.setAngleRange(180); + break; + case LCD: + CONTROL.setDecimals(1); + CONTROL.setTickLabelDecimals(1); + CONTROL.setMinMeasuredValueVisible(true); + CONTROL.setMaxMeasuredValueVisible(true); + CONTROL.setOldValueVisible(true); + CONTROL.setBorderPaint(Color.WHITE); + CONTROL.setForegroundPaint(Color.WHITE); + break; + case TINY: + CONTROL.setBorderWidth(24); + CONTROL.setBackgroundPaint(Color.rgb(216,216,216)); + CONTROL.setBorderPaint(Color.rgb(76,76,76)); + CONTROL.setBarBackgroundColor(Color.rgb(76, 76, 76, 0.2)); + CONTROL.setNeedleColor(Color.rgb(76, 76, 76)); + CONTROL.setSectionsVisible(true); + CONTROL.setMajorTickMarksVisible(true); + CONTROL.setMajorTickMarkColor(Color.WHITE); + break; + case BATTERY: + CONTROL.setBarBackgroundColor(Color.BLACK); + CONTROL.setBarColor(Color.BLACK); + CONTROL.setValueColor(Color.WHITE); + break; + case LEVEL: + CONTROL.setValueColor(Color.WHITE); + CONTROL.setBarColor(Color.CYAN); + break; + case LINEAR: + CONTROL.setOrientation(Orientation.VERTICAL); + CONTROL.setBarColor(Gauge.DARK_COLOR); + CONTROL.setBarEffectEnabled(true); + break; + case DIGITAL: + CONTROL.setBarColor(Gauge.DARK_COLOR); + CONTROL.setShadowsEnabled(true); + break; + case SIMPLE_DIGITAL: + CONTROL.setBarBackgroundColor(Helper.getTranslucentColorFrom(Gauge.DARK_COLOR, 0.1)); + CONTROL.setBarColor(Gauge.DARK_COLOR); + break; + case SECTION: + CONTROL.setBackgroundPaint(Gauge.DARK_COLOR); + CONTROL.setAutoScale(false); + CONTROL.setValueVisible(false); + CONTROL.setKnobColor(Color.rgb(82,82,84)); + CONTROL.setSectionsVisible(true); + CONTROL.setSectionTextVisible(true); + break; + case BAR: + Color barColor = CONTROL.getBarColor(); + CONTROL.setAnimated(true); + CONTROL.setAnimationDuration(1000); + CONTROL.setMinValue(0); + CONTROL.setMaxValue(100); + CONTROL.setGradientBarEnabled(true); + CONTROL.setGradientBarStops(new Stop(0.0, barColor), + new Stop(0.01, barColor), + new Stop(0.75, barColor.deriveColor(-10, 1, 1, 1)), + new Stop(1.0, barColor.deriveColor(-20, 1, 1, 1))); + CONTROL.setBarColor(barColor); + CONTROL.setBarEffectEnabled(true); + break; + case WHITE: + CONTROL.setAnimated(true); + CONTROL.setAnimationDuration(1000); + CONTROL.setAngleRange(360); + CONTROL.setMinValue(0); + CONTROL.setMaxValue(100); + CONTROL.setBarColor(Color.WHITE); + CONTROL.setValueColor(Color.WHITE); + CONTROL.setUnitColor(Color.WHITE); + break; + case CHARGE: + CONTROL.setMinValue(0); + CONTROL.setMaxValue(1.0); + CONTROL.setAnimated(true); + break; + case SIMPLE_SECTION: + CONTROL.setAnimated(true); + CONTROL.setStartAngle(150); + CONTROL.setAngleRange(300); + CONTROL.setStartFromZero(true); + CONTROL.setSectionsVisible(true); + CONTROL.setBarBackgroundColor(Color.rgb(150, 150, 150, 0.25)); + CONTROL.setBarColor(Color.rgb(69, 106, 207)); + CONTROL.setTitleColor(Color.rgb(90, 90, 90)); + CONTROL.setUnitColor(Color.rgb(90, 90, 90)); + CONTROL.setValueColor(Color.rgb(90, 90, 90)); + break; + case TILE_KPI: + CONTROL.setKnobPosition(Pos.BOTTOM_CENTER); + CONTROL.setDecimals(0); + CONTROL.setBackgroundPaint(Color.rgb(42,42,42)); + CONTROL.setForegroundBaseColor(Color.rgb(238,238,238)); + CONTROL.setBarColor(Color.rgb(238,238,238)); + CONTROL.setThresholdVisible(false); + CONTROL.setThresholdColor(Color.rgb(41,177,255)); + CONTROL.setNeedleColor(Color.rgb(238,238,238)); + CONTROL.setAngleRange(180); + break; + case TILE_TEXT_KPI: + CONTROL.setDecimals(0); + CONTROL.setBackgroundPaint(Color.rgb(42,42,42)); + CONTROL.setForegroundBaseColor(Color.rgb(238,238,238)); + CONTROL.setBarColor(Color.rgb(41,177,255)); + CONTROL.setValueColor(Color.rgb(238, 238, 238)); + CONTROL.setUnitColor(Color.rgb(238, 238, 238)); + CONTROL.setThresholdVisible(false); + CONTROL.setThresholdColor(Color.rgb(139,144,146)); + break; + case TILE_SPARK_LINE: + CONTROL.setDecimals(0); + CONTROL.setBackgroundPaint(Color.rgb(42,42,42)); + CONTROL.setForegroundBaseColor(Color.rgb(238,238,238)); + CONTROL.setBarColor(Color.rgb(41,177,255)); + CONTROL.setValueColor(Color.rgb(238, 238, 238)); + CONTROL.setUnitColor(Color.rgb(238, 238, 238)); + CONTROL.setAveragingEnabled(true); + CONTROL.setAveragingPeriod(10); + CONTROL.setAverageColor(Color.rgb(238, 238, 238, 0.5)); + CONTROL.setAnimated(false); + break; + case NASA: + CONTROL.setBarBackgroundColor(Color.TRANSPARENT); + CONTROL.setForegroundBaseColor(Color.WHITE); + CONTROL.setStartAngle(108); + CONTROL.setAngleRange(216); + CONTROL.setTickLabelsVisible(false); + CONTROL.setMediumTickMarksVisible(false); + CONTROL.setMajorTickMarksVisible(false); + break; + case GAUGE: + CONTROL.setStartAngle(320); + CONTROL.setAngleRange(280); + break; +*/ + } + } else { + CONTROL = new Gauge(); + } + + // Make sure that sections, areas and markers will be added first + /*if (properties.keySet().contains("sectionsArray")) { + CONTROL.setSections(((ObjectProperty) properties.get("sectionsArray")).get()); + } + if(properties.keySet().contains("sectionsList")) { + CONTROL.setSections(((ObjectProperty>) properties.get("sectionsList")).get()); + } + + if (properties.keySet().contains("areasArray")) { + CONTROL.setAreas(((ObjectProperty) properties.get("areasArray")).get()); + } + if(properties.keySet().contains("areasList")) { + CONTROL.setAreas(((ObjectProperty>) properties.get("areasList")).get()); + } + + if (properties.keySet().contains("tickMarkSectionsArray")) { + CONTROL.setTickMarkSections(((ObjectProperty) properties.get("tickMarkSectionsArray")).get()); + } + if(properties.keySet().contains("tickMarkSectionsList")) { + CONTROL.setTickMarkSections(((ObjectProperty>) properties.get("tickMarkSectionsList")).get()); + } + + if (properties.keySet().contains("tickLabelSectionsArray")) { + CONTROL.setTickLabelSections(((ObjectProperty) properties.get("tickLabelSectionsArray")).get()); + } + if(properties.keySet().contains("tickLabelSectionsList")) { + CONTROL.setTickLabelSections(((ObjectProperty>) properties.get("tickLabelSectionsList")).get()); + }*/ + + /*if (properties.keySet().contains("markersArray")) { + CONTROL.setMarkers(((ObjectProperty) properties.get("markersArray")).get()); + } + if (properties.keySet().contains("markersList")) { + CONTROL.setMarkers(((ObjectProperty>) properties.get("markersList")).get()); + }*/ + + /*if (properties.keySet().contains("gradientBarStopsArray")) { + CONTROL.setGradientBarStops(((ObjectProperty) properties.get("gradientBarStopsArray")).get()); + } + if (properties.keySet().contains("gradientBarStopsList")) { + CONTROL.setGradientBarStops(((ObjectProperty>) properties.get("gradientBarStopsList")).get()); + }*/ + + if (properties.keySet().contains("customTickLabelsArray")) { + CONTROL.setCustomTickLabels(((ObjectProperty) properties.get("customTickLabelsArray")).get()); + } + if (properties.keySet().contains("customTickLabelsList")) { + CONTROL.setCustomTickLabels(((ObjectProperty>) properties.get("customTickLabelsList")).get()); + } + + if(properties.keySet().contains("foregroundBaseColor")) { + CONTROL.setForegroundBaseColor(((ObjectProperty) properties.get("foregroundBaseColor")).get()); + } + + setMinMaxValues(CONTROL); + + for (String key : properties.keySet()) { + if ("prefSize".equals(key)) { + Dimension2D dim = ((ObjectProperty) properties.get(key)).get(); + CONTROL.setPrefSize(dim.getWidth(), dim.getHeight()); + } else if("minSize".equals(key)) { + Dimension2D dim = ((ObjectProperty) properties.get(key)).get(); + CONTROL.setMinSize(dim.getWidth(), dim.getHeight()); + } else if("maxSize".equals(key)) { + Dimension2D dim = ((ObjectProperty) properties.get(key)).get(); + CONTROL.setMaxSize(dim.getWidth(), dim.getHeight()); + } else if("prefWidth".equals(key)) { + CONTROL.setPrefWidth(((DoubleProperty) properties.get(key)).get()); + } else if("prefHeight".equals(key)) { + CONTROL.setPrefHeight(((DoubleProperty) properties.get(key)).get()); + } else if("minWidth".equals(key)) { + CONTROL.setMinWidth(((DoubleProperty) properties.get(key)).get()); + } else if("minHeight".equals(key)) { + CONTROL.setMinHeight(((DoubleProperty) properties.get(key)).get()); + } else if("maxWidth".equals(key)) { + CONTROL.setMaxWidth(((DoubleProperty) properties.get(key)).get()); + } else if("maxHeight".equals(key)) { + CONTROL.setMaxHeight(((DoubleProperty) properties.get(key)).get()); + } else if("scaleX".equals(key)) { + //CONTROL.setScaleX(((DoubleProperty) properties.get(key)).get()); + } else if("scaleY".equals(key)) { + //CONTROL.setScaleY(((DoubleProperty) properties.get(key)).get()); + } else if ("layoutX".equals(key)) { + CONTROL.setLayoutX(((DoubleProperty) properties.get(key)).get()); + } else if ("layoutY".equals(key)) { + CONTROL.setLayoutY(((DoubleProperty) properties.get(key)).get()); + } else if ("translateX".equals(key)) { + //CONTROL.setTranslateX(((DoubleProperty) properties.get(key)).get()); + } else if ("translateY".equals(key)) { + //CONTROL.setTranslateY(((DoubleProperty) properties.get(key)).get()); + } else if ("padding".equals(key)) { + CONTROL.setPadding(((ObjectProperty) properties.get(key)).get()); + } else if("styleClass".equals(key)) { + CONTROL.getStyleClass().setAll("gauge"); + CONTROL.getStyleClass().addAll(((ObjectProperty) properties.get(key)).get()); + } else if("decimals".equals(key)) { + CONTROL.setDecimals(((IntegerProperty) properties.get(key)).get()); + } else if ("tickLabelDecimals".equals(key)) { + CONTROL.setTickLabelDecimals(((IntegerProperty) properties.get(key)).get()); + } else if("title".equals(key)) { + CONTROL.setTitle(((StringProperty) properties.get(key)).get()); + } else if("subTitle".equals(key)) { + CONTROL.setSubTitle(((StringProperty) properties.get(key)).get()); + } else if("unit".equals(key)) { + CONTROL.setUnit(((StringProperty) properties.get(key)).get()); + }/* else if("averagingEnabled".equals(key)) { + CONTROL.setAveragingEnabled(((BooleanProperty) properties.get(key)).get()); + } else if("averagingPeriod".equals(key)) { + CONTROL.setAveragingPeriod(((IntegerProperty) properties.get(key)).get()); + }*/ else if("startFromZero".equals(key)) { + CONTROL.setStartFromZero(((BooleanProperty) properties.get(key)).get()); + } else if("returnToZero".equals(key)) { + CONTROL.setReturnToZero(((BooleanProperty) properties.get(key)).get()); + } else if("zeroColor".equals(key)) { + CONTROL.setZeroColor(((ObjectProperty) properties.get(key)).get()); + } else if ("minMeasuredValueVisible".equals(key)) { + CONTROL.setMinMeasuredValueVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("maxMeasuredValueVisible".equals(key)) { + CONTROL.setMaxMeasuredValueVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("oldValueVisible".equals(key)) { + CONTROL.setOldValueVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("valueVisible".equals(key)) { + CONTROL.setValueVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("backgroundPaint".equals(key)) { + CONTROL.setBackgroundPaint(((ObjectProperty) properties.get(key)).get()); + } else if ("borderPaint".equals(key)) { + CONTROL.setBorderPaint(((ObjectProperty) properties.get(key)).get()); + } else if ("borderWidth".equals(key)) { + CONTROL.setBorderWidth(((DoubleProperty) properties.get(key)).get()); + } else if ("foregroundPaint".equals(key)) { + CONTROL.setForegroundPaint(((ObjectProperty) properties.get(key)).get()); + } else if ("knobColor".equals(key)) { + CONTROL.setKnobColor(((ObjectProperty) properties.get(key)).get()); + } else if ("knobType".equals(key)) { + CONTROL.setKnobType(((ObjectProperty) properties.get(key)).get()); + } else if ("knobPosition".equals(key)) { + CONTROL.setKnobPosition(((ObjectProperty) properties.get(key)).get()); + } else if ("knobVisible".equals(key)) { + CONTROL.setKnobVisible(((BooleanProperty) properties.get(key)).get()); + } else if("animated".equals(key)) { + CONTROL.setAnimated(((BooleanProperty) properties.get(key)).get()); + } else if("animationDuration".equals(key)) { + CONTROL.setAnimationDuration(((LongProperty) properties.get(key)).get()); + } else if("startAngle".equals(key)) { + CONTROL.setStartAngle(((DoubleProperty) properties.get(key)).get()); + } else if("angleRange".equals(key)) { + CONTROL.setAngleRange(((DoubleProperty) properties.get(key)).get()); + } else if ("arcExtend".equals(key)) { + CONTROL.setArcExtend(((DoubleProperty) properties.get(key)).get()); + } else if("needleType".equals(key)) { + CONTROL.setNeedleType(((ObjectProperty) properties.get(key)).get()); + } else if("needleShape".equals(key)) { + CONTROL.setNeedleShape(((ObjectProperty) properties.get(key)).get()); + } else if("needleSize".equals(key)) { + CONTROL.setNeedleSize(((ObjectProperty) properties.get(key)).get()); + } else if("needleBehavior".equals(key)) { + CONTROL.setNeedleBehavior(((ObjectProperty) properties.get(key)).get()); + } else if("needleColor".equals(key)) { + CONTROL.setNeedleColor(((ObjectProperty) properties.get(key)).get()); + } else if("needleBorderColor".equals(key)) { + CONTROL.setNeedleBorderColor(((ObjectProperty) properties.get(key)).get()); + } else if("barColor".equals(key)) { + CONTROL.setBarColor(((ObjectProperty) properties.get(key)).get()); + } else if("barBorderColor".equals(key)) { + CONTROL.setBarBorderColor(((ObjectProperty) properties.get(key)).get()); + } else if ("barBackgroundColor".equals(key)) { + CONTROL.setBarBackgroundColor(((ObjectProperty) properties.get(key)).get()); + } else if("tickLabelOrientation".equals(key)) { + CONTROL.setTickLabelOrientation(((ObjectProperty) properties.get(key)).get()); + } else if("tickLabelLocation".equals(key)) { + CONTROL.setTickLabelLocation(((ObjectProperty) properties.get(key)).get()); + } else if("locale".equals(key)) { + CONTROL.setLocale(((ObjectProperty) properties.get(key)).get()); + } else if("majorTickSpace".equals(key)) { + CONTROL.setMajorTickSpace(((DoubleProperty) properties.get(key)).get()); + } else if("minorTickSpace".equals(key)) { + CONTROL.setMinorTickSpace(((DoubleProperty) properties.get(key)).get()); + } else if("shadowsEnabled".equals(key)) { + CONTROL.setShadowsEnabled(((BooleanProperty) properties.get(key)).get()); + } else if ("barEffectEnabled".equals(key)) { + CONTROL.setBarEffectEnabled(((BooleanProperty) properties.get(key)).get()); + } else if ("scaleDirection".equals(key)) { + CONTROL.setScaleDirection(((ObjectProperty) properties.get(key)).get()); + } else if("tickLabelColor".equals(key)) { + CONTROL.setTickLabelColor(((ObjectProperty) properties.get(key)).get()); + } else if ("tickMarkColor".equals(key)) { + CONTROL.setTickMarkColor(((ObjectProperty) properties.get(key)).get()); + } else if ("majorTickMarkColor".equals(key)) { + CONTROL.setMajorTickMarkColor(((ObjectProperty) properties.get(key)).get()); + } else if ("majorTickMarkLengthFactor".equals(key)) { + CONTROL.setMajorTickMarkLengthFactor(((DoubleProperty) properties.get(key)).get()); + } else if ("majorTickMarkWidthFactor".equals(key)) { + CONTROL.setMajorTickMarkWidthFactor(((DoubleProperty) properties.get(key)).get()); + } else if ("mediumTickMarkColor".equals(key)) { + CONTROL.setMediumTickMarkColor(((ObjectProperty) properties.get(key)).get()); + } else if ("mediumTickMarkLengthFactor".equals(key)) { + CONTROL.setMediumTickMarkLengthFactor(((DoubleProperty) properties.get(key)).get()); + } else if ("mediumTickMarkWidthFactor".equals(key)) { + CONTROL.setMediumTickMarkWidthFactor(((DoubleProperty) properties.get(key)).get()); + } else if ("minorTickMarkColor".equals(key)) { + CONTROL.setMinorTickMarkColor(((ObjectProperty) properties.get(key)).get()); + } else if ("minorTickMarkLengthFactor".equals(key)) { + CONTROL.setMinorTickMarkLengthFactor(((DoubleProperty) properties.get(key)).get()); + } else if ("minorTickMarkWidthFactor".equals(key)) { + CONTROL.setMinorTickMarkWidthFactor(((DoubleProperty) properties.get(key)).get()); + } else if ("style".equals(key)) { + CONTROL.setStyle(((StringProperty) properties.get(key)).get()); + } else if("ledColor".equals(key)) { + CONTROL.setLedColor(((ObjectProperty) properties.get(key)).get()); + } else if("ledType".equals(key)) { + CONTROL.setLedType(((ObjectProperty) properties.get(key)).get()); + } else if ("ledVisible".equals(key)) { + CONTROL.setLedVisible(((BooleanProperty) properties.get(key)).get()); + }/* else if ("lcdVisible".equals(key)) { + CONTROL.setLcdVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("lcdCrystalEnabled".equals(key)) { + CONTROL.setLcdCrystalEnabled(((BooleanProperty) properties.get(key)).get()); + } else if ("lcdDesign".equals(key)) { + CONTROL.setLcdDesign(((ObjectProperty) properties.get(key)).get()); + } else if ("lcdFont".equals(key)) { + CONTROL.setLcdFont(((ObjectProperty) properties.get(key)).get()); + }*/ else if ("innerShadowEnabled".equals(key)) { + CONTROL.setInnerShadowEnabled(((BooleanProperty) properties.get(key)).get()); + } else if ("thresholdVisible".equals(key)) { + CONTROL.setThresholdVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("averageVisible".equals(key)) { + CONTROL.setAverageVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("sectionsVisible".equals(key)) { + CONTROL.setSectionsVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("sectionsAlwaysVisible".equals(key)) { + CONTROL.setSectionsAlwaysVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("sectionTextVisible".equals(key)) { + CONTROL.setSectionTextVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("sectionIconsVisible".equals(key)) { + CONTROL.setSectionIconsVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("highlightSections".equals(key)) { + CONTROL.setHighlightSections(((BooleanProperty) properties.get(key)).get()); + } else if ("areasVisible".equals(key)) { + CONTROL.setAreasVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("areaTextVisible".equals(key)) { + CONTROL.setAreaTextVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("areaIconsVisible".equals(key)) { + CONTROL.setAreaIconsVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("highlightAreas".equals(key)) { + CONTROL.setHighlightAreas(((BooleanProperty) properties.get(key)).get()); + } else if ("tickMarkSectionsVisible".equals(key)) { + CONTROL.setTickMarkSectionsVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("tickLabelSectionsVisible".equals(key)) { + CONTROL.setTickLabelSectionsVisible(((BooleanProperty) properties.get(key)).get()); + }/* else if ("markersVisible".equals(key)) { + CONTROL.setMarkersVisible(((BooleanProperty) properties.get(key)).get()); + }*/ else if ("majorTickMarkType".equals(key)) { + CONTROL.setMajorTickMarkType(((ObjectProperty) properties.get(key)).get()); + } else if ("mediumTickMarkType".equals(key)) { + CONTROL.setMediumTickMarkType(((ObjectProperty) properties.get(key)).get()); + } else if ("minorTickMarkType".equals(key)) { + CONTROL.setMinorTickMarkType(((ObjectProperty) properties.get(key)).get()); + } else if ("titleColor".equals(key)) { + CONTROL.setTitleColor(((ObjectProperty) properties.get(key)).get()); + } else if ("subTitleColor".equals(key)) { + CONTROL.setSubTitleColor(((ObjectProperty) properties.get(key)).get()); + } else if ("unitColor".equals(key)) { + CONTROL.setUnitColor(((ObjectProperty) properties.get(key)).get()); + } else if ("valueColor".equals(key)) { + CONTROL.setValueColor(((ObjectProperty) properties.get(key)).get()); + } else if ("thresholdColor".equals(key)) { + CONTROL.setThresholdColor(((ObjectProperty) properties.get(key)).get()); + } else if ("averageColor".equals(key)) { + CONTROL.setAverageColor(((ObjectProperty) properties.get(key)).get()); + } else if ("tickLabelsVisible".equals(key)) { + CONTROL.setTickLabelsVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("onlyFirstAndLastTickLabelVisible".equals(key)) { + CONTROL.setOnlyFirstAndLastTickLabelVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("majorTickMarksVisible".equals(key)) { + CONTROL.setMajorTickMarksVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("mediumTickMarksVisible".equals(key)) { + CONTROL.setMediumTickMarksVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("minorTickMarksVisible".equals(key)) { + CONTROL.setMinorTickMarksVisible(((BooleanProperty) properties.get(key)).get()); + } else if ("tickMarkRingVisible".equals(key)) { + CONTROL.setTickMarkRingVisible(((BooleanProperty) properties.get(key)).get()); + }/* else if ("ledBlinking".equals(key)) { + CONTROL.setLedBlinking(((BooleanProperty) properties.get(key)).get()); + }*/ else if ("ledOn".equals(key)) { + CONTROL.setLedOn(((BooleanProperty) properties.get(key)).get()); + } else if ("orientation".equals(key)) { + CONTROL.setOrientation(((ObjectProperty) properties.get(key)).get()); + } else if("gradientBarEnabled".equals(key)) { + CONTROL.setGradientBarEnabled(((BooleanProperty) properties.get(key)).get()); + }/* else if ("gradientLookup".equals(key)) { + CONTROL.setGradientLookup(((ObjectProperty) properties.get(key)).get()); + }*/ else if ("customTickLabelsEnabled".equals(key)) { + CONTROL.setCustomTickLabelsEnabled(((BooleanProperty) properties.get(key)).get()); + } else if ("customTickLabelFontSize".equals(key)) { + CONTROL.setCustomTickLabelFontSize(((DoubleProperty) properties.get(key)).get()); + } else if ("interactive".equals(key)) { + CONTROL.setInteractive(((BooleanProperty) properties.get(key)).get()); + } else if ("checkSectionsForValue".equals(key)) { + CONTROL.setCheckSectionsForValue(((BooleanProperty) properties.get(key)).get()); + } else if ("checkAreasForValue".equals(key)) { + CONTROL.setCheckAreasForValue(((BooleanProperty) properties.get(key)).get()); + } else if ("checkThreshold".equals(key)) { + CONTROL.setCheckThreshold(((BooleanProperty) properties.get(key)).get()); + } else if ("onValueChanged".equals(key)) { + CONTROL.currentValueProperty().addListener(((ObjectProperty) properties.get(key)).get()); + } else if ("onButtonPressed".equals(key)) { + CONTROL.setOnButtonPressed(((ObjectProperty) properties.get(key)).get()); + } else if ("onButtonReleased".equals(key)) { + CONTROL.setOnButtonReleased(((ObjectProperty) properties.get(key)).get()); + } else if ("onThresholdExceeded".equals(key)) { + CONTROL.setOnThresholdExceeded(((ObjectProperty) properties.get(key)).get()); + } else if ("onThresholdUnderrun".equals(key)) { + CONTROL.setOnThresholdUnderrun(((ObjectProperty) properties.get(key)).get()); + } else if ("buttonTooltipText".equals(key)) { + CONTROL.setButtonTooltipText(((StringProperty) properties.get(key)).get()); + } else if ("keepAspect".equals(key)) { + CONTROL.setKeepAspect(((BooleanProperty) properties.get(key)).get()); + } else if ("threshold".equals(key)) { + CONTROL.setThreshold(((DoubleProperty) properties.get(key)).get()); + } else if ("customFontEnabled".equals(key)) { + CONTROL.setCustomFontEnabled(((BooleanProperty) properties.get(key)).get()); + } else if ("customFont".equals(key)) { + CONTROL.setCustomFont(((ObjectProperty) properties.get(key)).get()); + } else if ("alertMessage".equals(key)) { + CONTROL.setAlertMessage(((StringProperty) properties.get(key)).get()); + } else if ("smoothing".equals(key)) { + CONTROL.setSmoothing(((BooleanProperty) properties.get(key)).get()); + } else if ("autoScale".equals(key)) { + CONTROL.setAutoScale(((BooleanProperty) properties.get(key)).get()); + setMinMaxValues(CONTROL); + } else if("value".equals(key)) { + CONTROL.setValue(((DoubleProperty) properties.get(key)).get()); + } + } + + // Adjust tick mark colors + if (properties.containsKey("tickMarkColor")) { + Color tickMarkColor = ((ObjectProperty) properties.get("tickMarkColor")).get(); + if (!properties.containsKey("majorTickMarkColor")) CONTROL.setMajorTickMarkColor(tickMarkColor); + if (!properties.containsKey("mediumTickMarkColor")) CONTROL.setMediumTickMarkColor(tickMarkColor); + if (!properties.containsKey("minorTickMarkColor")) CONTROL.setMinorTickMarkColor(tickMarkColor); + } + + return CONTROL; + } + + private void setMinMaxValues(final Gauge CONTROL) { + if (properties.keySet().contains("minValue")) { CONTROL.setMinValue(((DoubleProperty) properties.get("minValue")).get()); } + if (properties.keySet().contains("maxValue")) { CONTROL.setMaxValue(((DoubleProperty) properties.get("maxValue")).get()); } + } +} diff --git a/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/TickLabelLocation.java b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/TickLabelLocation.java new file mode 100644 index 0000000..62fd6ff --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/TickLabelLocation.java @@ -0,0 +1,26 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2016-2020 Gerrit Grunwald. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.hansolo.medusa; + +/** + * Created by hansolo on 28.01.16. + */ +public enum TickLabelLocation { + INSIDE, OUTSIDE +} diff --git a/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/TickLabelOrientation.java b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/TickLabelOrientation.java new file mode 100644 index 0000000..d23d3db --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/TickLabelOrientation.java @@ -0,0 +1,26 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2016-2020 Gerrit Grunwald. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.hansolo.medusa; + +/** + * Created by hansolo on 28.01.16. + */ +public enum TickLabelOrientation { + ORTHOGONAL, HORIZONTAL, TANGENT +} diff --git a/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/TickMarkType.java b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/TickMarkType.java new file mode 100644 index 0000000..f1e0d19 --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/TickMarkType.java @@ -0,0 +1,26 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2016-2020 Gerrit Grunwald. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.hansolo.medusa; + +/** + * Created by hansolo on 28.01.16. + */ +public enum TickMarkType { + LINE, DOT, TRAPEZOID, TRIANGLE, BOX, TICK_LABEL, PILL +} diff --git a/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/TimeEvent.java b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/TimeEvent.java new file mode 100644 index 0000000..c4ccbc3 --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/TimeEvent.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 by Gerrit Grunwald + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.hansolo.medusa.events; + +import java.time.ZonedDateTime; +import java.util.EventObject; + + +/** + * Created by hansolo on 24.02.16. + */ +public class TimeEvent extends EventObject { + public enum TimeEventType { HOUR, MINUTE, SECOND }; + public final ZonedDateTime TIME; + public final TimeEventType TYPE; + + + // ******************** Constructors ************************************** + public TimeEvent(final Object SRC, final ZonedDateTime TIME, final TimeEventType TYPE) { + super(SRC); + this.TIME = TIME; + this.TYPE = TYPE; + } +} diff --git a/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/TimeEventListener.java b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/TimeEventListener.java new file mode 100644 index 0000000..65c5549 --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/TimeEventListener.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016 by Gerrit Grunwald + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.hansolo.medusa.events; + +import java.util.EventListener; + + +/** + * Created by hansolo on 24.02.16. + */ +@FunctionalInterface +public interface TimeEventListener extends EventListener { + public void onTimeEvent(final TimeEvent EVENT); +} diff --git a/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/UpdateEvent.java b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/UpdateEvent.java new file mode 100644 index 0000000..aa2b61d --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/UpdateEvent.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016 by Gerrit Grunwald + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.hansolo.medusa.events; + +import java.util.EventObject; + + +/** + * Created by hansolo on 05.01.16. + */ +public class UpdateEvent extends EventObject { + public enum EventType { RECALC, REDRAW, RESIZE, LED, LCD, VISIBILITY, INTERACTIVITY, FINISHED, SECTION, ALERT, VALUE }; + public final EventType eventType; + + public UpdateEvent(final Object SRC, final EventType EVENT_TYPE) { + super(SRC); + eventType = EVENT_TYPE; + } +} diff --git a/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/UpdateEventListener.java b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/UpdateEventListener.java new file mode 100644 index 0000000..4e8bfe8 --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/events/UpdateEventListener.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016 by Gerrit Grunwald + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.hansolo.medusa.events; + +import java.util.EventListener; + + +/** + * Created by hansolo on 05.01.16. + */ +@FunctionalInterface +public interface UpdateEventListener extends EventListener { + public void onUpdateEvent(final UpdateEvent EVENT); +} diff --git a/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/skins/GaugeSkinBase.java b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/skins/GaugeSkinBase.java new file mode 100644 index 0000000..619c649 --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/skins/GaugeSkinBase.java @@ -0,0 +1,83 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2016-2020 Gerrit Grunwald. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.hansolo.medusa.skins; + +import eu.hansolo.medusa.Gauge; +import eu.hansolo.medusa.events.UpdateEventListener; +import javafx.beans.InvalidationListener; +import javafx.scene.control.Skin; +import javafx.scene.control.SkinBase; + + +/** + * Created by hansolo on 20.01.17. + */ +public abstract class GaugeSkinBase extends SkinBase implements Skin { + protected static final double PREFERRED_WIDTH = 250; + protected static final double PREFERRED_HEIGHT = 250; + protected static final double MINIMUM_WIDTH = 50; + protected static final double MINIMUM_HEIGHT = 50; + protected static final double MAXIMUM_WIDTH = 1024; + protected static final double MAXIMUM_HEIGHT = 1024; + protected Gauge gauge; + protected InvalidationListener sizeListener; + protected UpdateEventListener updateEventListener; + + + protected GaugeSkinBase(final Gauge GAUGE) { + super(GAUGE); + gauge = GAUGE; + sizeListener = o -> handleEvents("RESIZE"); + updateEventListener = e -> handleEvents(e.eventType.name()); + } + + protected void registerListeners() { + getSkinnable().widthProperty().addListener(sizeListener); + getSkinnable().heightProperty().addListener(sizeListener); + getSkinnable().setOnUpdate(e -> handleEvents(e.eventType.name())); + } + + protected void handleEvents(final String EVENT_TYPE) { + if ("RESIZE".equals(EVENT_TYPE)) { + resize(); + redraw(); + } else if ("REDRAW".equals(EVENT_TYPE)) { + redraw(); + } + } + + + // ******************** Methods ******************************************* + @Override protected double computeMinWidth(final double HEIGHT, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return MINIMUM_WIDTH; } + @Override protected double computeMinHeight(final double WIDTH, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return MINIMUM_HEIGHT; } + @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); } + @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); } + @Override protected double computeMaxWidth(final double HEIGHT, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return MAXIMUM_WIDTH; } + @Override protected double computeMaxHeight(final double WIDTH, final double TOP, final double RIGHT, final double BOTTOM, final double LEFT) { return MAXIMUM_HEIGHT; } + + @Override public void dispose() { + gauge.widthProperty().removeListener(sizeListener); + gauge.heightProperty().removeListener(sizeListener); + gauge.removeUpdateEventListener(updateEventListener); + } + + protected void resize() {} + + protected void redraw() {} +} diff --git a/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/skins/ModernSkin.java b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/skins/ModernSkin.java new file mode 100644 index 0000000..a2a1768 --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/skins/ModernSkin.java @@ -0,0 +1,838 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2016-2020 Gerrit Grunwald. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.hansolo.medusa.skins; + +import eu.hansolo.medusa.Fonts; +import eu.hansolo.medusa.Gauge; +import eu.hansolo.medusa.TickLabelOrientation; +import eu.hansolo.medusa.tools.Helper; +import javafx.beans.InvalidationListener; +import javafx.event.EventHandler; +import javafx.event.EventType; +import javafx.geometry.VPos; +import javafx.scene.CacheHint; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.effect.BlurType; +import javafx.scene.effect.DropShadow; +import javafx.scene.effect.InnerShadow; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.paint.CycleMethod; +import javafx.scene.paint.LinearGradient; +import javafx.scene.paint.Stop; +import javafx.scene.shape.*; +import javafx.scene.text.Font; +import javafx.scene.text.Text; +import javafx.scene.text.TextAlignment; +import javafx.scene.transform.Rotate; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import static eu.hansolo.medusa.tools.Helper.formatNumber; + + +/** + * Created by hansolo on 01.01.16. + */ +public class ModernSkin extends GaugeSkinBase { + private double START_ANGLE = 300; + private double ANGLE_RANGE = 240; + private double BAR_START_ANGLE = -150; + private double size; + private Pane pane; + private Circle background; + private Path mask; + private Circle centerKnob; + private Path needle; + private MoveTo needleMoveTo1; + private CubicCurveTo needleCubicCurveTo2; + private CubicCurveTo needleCubicCurveTo3; + private CubicCurveTo needleCubicCurveTo4; + private LineTo needleLineTo5; + private LineTo needleLineTo6; + private LineTo needleLineTo7; + private LineTo needleLineTo8; + private ClosePath needleClosePath9; + private Rotate needleRotate; + private Canvas mainCanvas; + private GraphicsContext mainCtx; + private Canvas tickMarkCanvas; + private GraphicsContext tickMarkCtx; + private InnerShadow innerShadow0; + private InnerShadow innerShadow1; + private InnerShadow innerShadow2; + private InnerShadow innerShadow3; + private DropShadow dropShadow4; + private DropShadow glow1; + private DropShadow glow2; + private DropShadow bigGlow; + private Text valueText; + private Text titleText; + private Text subTitleText; + private Text unitText; + private double angleStep; + private EventHandler mouseHandler; + //private Tooltip buttonTooltip; + private Locale locale; + //private boolean sectionsVisible; + //private List
sections; + private Color barColor; + private Color thresholdColor; + private InvalidationListener animatedListener; +// private ListChangeListener
sectionListener; + private InvalidationListener currentValueListener; + private int titleLength; + private int subTitleLength; + private int unitLength; + private int valueLength; + + // ******************** Constructors ************************************** + public ModernSkin(Gauge gauge) { + super(gauge); + if (gauge.isAutoScale()) gauge.calcAutoScale(); + angleStep = ANGLE_RANGE / (gauge.getRange()); + mouseHandler = event -> handleMouseEvent(event); + //buttonTooltip = new Tooltip(); + locale = gauge.getLocale(); +// sectionsVisible = gauge.getSectionsVisible(); +// sections = gauge.getSections(); + barColor = gauge.getBarColor(); + thresholdColor = gauge.getThresholdColor(); + animatedListener = o -> handleEvents("ANIMATED"); +// sectionListener = c -> handleEvents("RESIZE"); + currentValueListener = o -> rotateNeedle(gauge.getCurrentValue()); + titleLength = 0; + subTitleLength = 0; + unitLength = 0; + + initGraphics(); + registerListeners(); + } + + + // ******************** Initialization ************************************ + private void initGraphics() { + // Set initial size + if (Double.compare(gauge.getPrefWidth(), 0.0) <= 0 || Double.compare(gauge.getPrefHeight(), 0.0) <= 0 || + Double.compare(gauge.getWidth(), 0.0) <= 0 || Double.compare(gauge.getHeight(), 0.0) <= 0) { + if (gauge.getPrefWidth() > 0 && gauge.getPrefHeight() > 0) { + gauge.setPrefSize(gauge.getPrefWidth(), gauge.getPrefHeight()); + } else { + gauge.setPrefSize(PREFERRED_WIDTH, PREFERRED_HEIGHT); + } + } + + innerShadow0 = new InnerShadow(BlurType.TWO_PASS_BOX, Color.rgb(0, 0, 0, 0.65), 1, 0, 0, 1); + + innerShadow1 = new InnerShadow(BlurType.TWO_PASS_BOX, Color.rgb(255, 255, 255, 0.65), 1, 0, 0, -1); + innerShadow1.setInput(innerShadow0); + + background = new Circle(PREFERRED_WIDTH * 0.5, PREFERRED_HEIGHT * 0.5, PREFERRED_WIDTH * 0.5); + background.setFill(Color.rgb(32, 32, 32)); + background.setStroke(null); + background.setEffect(innerShadow1); + + innerShadow2 = new InnerShadow(BlurType.TWO_PASS_BOX, Color.rgb(255, 255, 255, 0.65), 1, 0, 0, 1); + + innerShadow3 = new InnerShadow(BlurType.TWO_PASS_BOX, Color.rgb(0, 0, 0, 0.65), 1, 0, 0, -1); + innerShadow3.setInput(innerShadow2); + + dropShadow4 = new DropShadow(); + dropShadow4.setBlurType(BlurType.TWO_PASS_BOX); + dropShadow4.setColor(Color.rgb(0, 0, 0, 0.65)); + dropShadow4.setOffsetX(0); + dropShadow4.setInput(innerShadow3); + + mask = new Path(); + mask.setFillRule(FillRule.EVEN_ODD); + mask.setFill(Color.rgb(32, 32, 32)); + mask.setStroke(null); + mask.setEffect(dropShadow4); + + needleRotate = new Rotate(180 - START_ANGLE); + + double targetAngle = 180 - START_ANGLE + (gauge.getCurrentValue() - gauge.getMinValue()) * angleStep; + needleRotate.setAngle(Helper.clamp(180 - START_ANGLE, 180 - START_ANGLE + ANGLE_RANGE, targetAngle)); + + glow1 = new DropShadow(BlurType.TWO_PASS_BOX, barColor, 0.085 * PREFERRED_WIDTH, 0, 0, 0); + glow2 = new DropShadow(BlurType.TWO_PASS_BOX, barColor, 0.085 * PREFERRED_WIDTH, 0, 0, 0); + bigGlow = new DropShadow(BlurType.TWO_PASS_BOX, barColor, 0.25 * PREFERRED_WIDTH, 0, 0, 0); + + needleMoveTo1 = new MoveTo(); + needleCubicCurveTo2 = new CubicCurveTo(); + needleCubicCurveTo3 = new CubicCurveTo(); + needleCubicCurveTo4 = new CubicCurveTo(); + needleLineTo5 = new LineTo(); + needleLineTo6 = new LineTo(); + needleLineTo7 = new LineTo(); + needleLineTo8 = new LineTo(); + needleClosePath9 = new ClosePath(); + needle = new Path(needleMoveTo1, needleCubicCurveTo2, needleCubicCurveTo3, needleCubicCurveTo4, + needleLineTo5, needleLineTo6, needleLineTo7, needleLineTo8, needleClosePath9); + needle.setFillRule(FillRule.EVEN_ODD); + needle.setEffect(glow1); + + needle.getTransforms().setAll(needleRotate); + needle.setFill(gauge.getNeedleColor()); + needle.setStroke(null); + needle.setStrokeLineCap(StrokeLineCap.ROUND); + needle.setStrokeLineJoin(StrokeLineJoin.BEVEL); + + mainCanvas = new Canvas(PREFERRED_WIDTH, PREFERRED_HEIGHT); + mainCtx = mainCanvas.getGraphicsContext2D(); + + tickMarkCanvas = new Canvas(PREFERRED_WIDTH, PREFERRED_HEIGHT); + tickMarkCtx = tickMarkCanvas.getGraphicsContext2D(); + + centerKnob = new Circle(0.5 * PREFERRED_WIDTH, 0.5 * PREFERRED_HEIGHT, 0.22916667 * PREFERRED_WIDTH); + //centerKnob.setPickOnBounds(false); + + titleText = new Text(gauge.getTitle()); + titleText.setTextOrigin(VPos.CENTER); + titleText.setFill(gauge.getTitleColor()); + titleText.setEffect(glow1); + titleText.setMouseTransparent(true); + Helper.enableNode(titleText, !gauge.getTitle().isEmpty()); + + subTitleText = new Text(gauge.getSubTitle()); + subTitleText.setTextOrigin(VPos.CENTER); + subTitleText.setFill(gauge.getSubTitleColor()); + subTitleText.setEffect(glow1); + subTitleText.setMouseTransparent(true); + Helper.enableNode(subTitleText, !gauge.getSubTitle().isEmpty()); + + unitText = new Text(gauge.getUnit()); + unitText.setTextOrigin(VPos.CENTER); + unitText.setFill(gauge.getUnitColor()); + unitText.setEffect(glow1); + unitText.setMouseTransparent(true); + Helper.enableNode(unitText, !gauge.getUnit().isEmpty()); + + valueText = new Text(formatNumber(gauge.getLocale(), null/*gauge.getFormatString()*/, gauge.getDecimals(), gauge.getCurrentValue())); + valueText.setMouseTransparent(true); + valueText.setTextOrigin(VPos.CENTER); + valueText.setFill(gauge.getValueColor()); + valueText.setEffect(bigGlow); + Helper.enableNode(valueText, gauge.isValueVisible()); + + // Add all nodes + pane = new Pane(background, + mainCanvas, + tickMarkCanvas, + mask, + needle, + centerKnob, + titleText, + subTitleText, + unitText, + valueText); + + getChildren().setAll(pane); + } + + @Override protected void registerListeners() { + super.registerListeners(); + gauge.animatedProperty().addListener(animatedListener); +// gauge.getSections().addListener(sectionListener); + gauge.currentValueProperty().addListener(currentValueListener); + + handleEvents("INTERACTIVITY"); + } + + + // ******************** Methods ******************************************* + @Override protected void handleEvents(final String EVENT_TYPE) { + super.handleEvents(EVENT_TYPE); + if ("VISIBILITY".equals(EVENT_TYPE)) { + Helper.enableNode(titleText, !gauge.getTitle().isEmpty()); + Helper.enableNode(subTitleText, !gauge.getSubTitle().isEmpty()); + Helper.enableNode(unitText, !gauge.getUnit().isEmpty()); + Helper.enableNode(valueText, gauge.isValueVisible()); +// sectionsVisible = gauge.getSectionsVisible(); + redraw(); + } else if ("RECALC".equals(EVENT_TYPE)) { + angleStep = ANGLE_RANGE / gauge.getRange(); + redraw(); + rotateNeedle(gauge.getCurrentValue()); + } else if ("INTERACTIVITY".equals(EVENT_TYPE)) { + if (gauge.isInteractive()) { + centerKnob.setOnMousePressed(mouseHandler); + centerKnob.setOnMouseReleased(mouseHandler); + /*buttonTooltip.setText(gauge.getButtonTooltipText()); + Tooltip.install(centerKnob, buttonTooltip);*/ + } else { + centerKnob.removeEventHandler(MouseEvent.MOUSE_PRESSED, mouseHandler); + centerKnob.removeEventHandler(MouseEvent.MOUSE_RELEASED, mouseHandler); + //Tooltip.uninstall(centerKnob, buttonTooltip); + } + }/* else if ("SECTIONS".equals(EVENT_TYPE)) { + sectionsVisible = gauge.getSectionsVisible(); + sections = gauge.getSections(); + }*/ + } + + public void handleMouseEvent(final MouseEvent EVENT) { + if (gauge.isDisabled()) return; + final EventType TYPE = EVENT.getEventType(); + if (MouseEvent.MOUSE_PRESSED.equals(TYPE)) { + gauge.fireEvent(gauge.BTN_PRESSED_EVENT); + centerKnob.setFill(new LinearGradient(0.5 * size, 0.2708333333333333 * size, + 0.5 * size, 0.7291666666666666 * size, + false, CycleMethod.NO_CYCLE, + new Stop(0.0, Color.rgb(31, 31, 31)), + new Stop(1.0, Color.rgb(69, 70, 73)))); + valueText.setLayoutY(size * 0.501); + subTitleText.setLayoutY(size * 0.3525); + unitText.setLayoutY(size * 0.6675); + } else if (MouseEvent.MOUSE_RELEASED.equals(TYPE)) { + gauge.fireEvent(gauge.BTN_RELEASED_EVENT); + centerKnob.setFill(new LinearGradient(0.5 * size, 0.2708333333333333 * size, + 0.5 * size, 0.7291666666666666 * size, + false, CycleMethod.NO_CYCLE, + new Stop(0.0, Color.rgb(69, 70, 73)), + new Stop(1.0, Color.rgb(31, 31, 31)))); + valueText.setLayoutY(size * 0.5); + subTitleText.setLayoutY(size * 0.35); + unitText.setLayoutY(size * 0.67); + } + } + + @Override public void dispose() { + gauge.animatedProperty().removeListener(animatedListener); +// gauge.getSections().removeListener(sectionListener); + gauge.currentValueProperty().removeListener(currentValueListener); + if (gauge.isInteractive()) { + centerKnob.removeEventHandler(MouseEvent.MOUSE_PRESSED, mouseHandler); + centerKnob.removeEventHandler(MouseEvent.MOUSE_RELEASED, mouseHandler); + } + super.dispose(); + } + + + // ******************** Private Methods *********************************** + private void rotateNeedle(final double VALUE) { + angleStep = ANGLE_RANGE / gauge.getRange(); + double targetAngle = 180 - START_ANGLE + (VALUE - gauge.getMinValue()) * angleStep; + needleRotate.setAngle(Helper.clamp(180 - START_ANGLE, 180 - START_ANGLE + ANGLE_RANGE, targetAngle)); + valueText.setText(formatNumber(gauge.getLocale(), null/*gauge.getFormatString()*/, gauge.getDecimals(), VALUE)); + + if (valueText.getText().length() != valueLength) // Only needed in this case + resizeText(); + +/* Commented as doesn't seem necessary + placeTextVerticaly(); +*/ + + if ( gauge.isThresholdVisible() && VALUE > gauge.getThreshold() ) { + glow2.setColor(thresholdColor); + bigGlow.setColor(thresholdColor); + } else { + glow2.setColor(barColor); + bigGlow.setColor(barColor); + } + highlightValue(tickMarkCtx, VALUE); + } + + private void highlightValue( final GraphicsContext CTX, final double CURRENT_VALUE ) { + + CTX.clearRect(0, 0, size, size); + + // highlight tickmarks + double centerX = size * 0.5; + double centerY = size * 0.5; + double minorTickSpace = gauge.getMinorTickSpace(); + double minValue = gauge.getMinValue(); + double maxValue = gauge.getMaxValue(); + double tmpAngleStep = angleStep * minorTickSpace; + BigDecimal minorTickSpaceBD = BigDecimal.valueOf(minorTickSpace); + BigDecimal majorTickSpaceBD = BigDecimal.valueOf(gauge.getMajorTickSpace()); + BigDecimal mediumCheck2 = BigDecimal.valueOf(2 * minorTickSpace); + BigDecimal mediumCheck5 = BigDecimal.valueOf(5 * minorTickSpace); + BigDecimal counterBD = BigDecimal.valueOf(minValue); + double counter = minValue; + boolean majorTickMarksVisible = gauge.getMajorTickMarksVisible(); + boolean mediumTickMarksVisible = gauge.getMediumTickMarksVisible(); + double threshold = gauge.getThreshold(); + Color tickMarkColor = Color.TRANSPARENT; + Color highlightColor = ( !gauge.isThresholdVisible() || CURRENT_VALUE <= gauge.getThreshold() ) ? barColor : thresholdColor; + boolean startFromZero = gauge.isStartFromZero(); + + CTX.setLineCap(StrokeLineCap.BUTT); + CTX.setLineWidth(size * 0.0035); + + for (double angle = 0 ; Double.compare(-ANGLE_RANGE - tmpAngleStep, angle) < 0 ; angle -= tmpAngleStep) { + + double sinValue = Math.sin(Math.toRadians(angle + START_ANGLE)); + double cosValue = Math.cos(Math.toRadians(angle + START_ANGLE)); + double innerPointX = centerX + size * 0.375 * sinValue; + double innerPointY = centerY + size * 0.375 * cosValue; + double outerPointX = centerX + size * 0.425 * sinValue; + double outerPointY = centerY + size * 0.425 * cosValue; + double innerMediumPointX = centerX + size * 0.35 * sinValue; + double innerMediumPointY = centerY + size * 0.35 * cosValue; + double outerMediumPointX = centerX + size * 0.4 * sinValue; + double outerMediumPointY = centerY + size * 0.4 * cosValue; + boolean shouldHighlight = false; + + if ( startFromZero ) { + if ( ( CURRENT_VALUE > minValue || minValue < 0 ) && ( CURRENT_VALUE < maxValue || maxValue > 0 ) ) { + if ( maxValue < 0 ) { + shouldHighlight = counter >= CURRENT_VALUE; + } else if ( minValue > 0 ) { + shouldHighlight = counter <= CURRENT_VALUE; + } else if ( CURRENT_VALUE > 0 ) { + shouldHighlight = counter >= 0 && counter <= CURRENT_VALUE; + } else { + shouldHighlight = counter <= 0 && counter >= CURRENT_VALUE; + } + } + } else { + shouldHighlight = counter <= CURRENT_VALUE; + } + + if (Double.compare(counterBD.remainder(majorTickSpaceBD).doubleValue(), 0.0) == 0) { + // Draw major tick mark + if (majorTickMarksVisible) { + CTX.setStroke(shouldHighlight ? highlightColor : tickMarkColor); + CTX.strokeLine(innerPointX, innerPointY, outerPointX, outerPointY); + } + } else if (mediumTickMarksVisible && + Double.compare(minorTickSpaceBD.remainder(mediumCheck2).doubleValue(), 0.0) != 0.0 && + Double.compare(counterBD.remainder(mediumCheck5).doubleValue(), 0.0) == 0.0) { + // Draw medium tick mark + CTX.setStroke(shouldHighlight ? highlightColor : tickMarkColor); + CTX.strokeLine(innerMediumPointX, innerMediumPointY, outerMediumPointX, outerMediumPointY); + } + + counterBD = counterBD.add(minorTickSpaceBD); + counter = counterBD.doubleValue(); + + } + + // highlight bar + double barXY = ( size - 0.75 * size ) * 0.5; + double barWH = size * 0.75; + + CTX.save(); + CTX.setEffect(glow2); + CTX.setStroke(highlightColor); + CTX.setLineWidth(size * 0.01666667); + CTX.setLineCap(StrokeLineCap.BUTT); + + double barLength = 0; + double barStart = 0; + double clampedValue = Helper.clamp(minValue, maxValue, CURRENT_VALUE); + + if ( startFromZero ) { + if ( ( CURRENT_VALUE > minValue || minValue < 0 ) && ( CURRENT_VALUE < maxValue || maxValue > 0 ) ) { + if ( maxValue < 0 ) { + barStart = BAR_START_ANGLE - ANGLE_RANGE; + barLength = ( maxValue - clampedValue ) * angleStep; + } else if ( minValue > 0 ) { + barStart = BAR_START_ANGLE; + barLength = ( minValue - clampedValue ) * angleStep; + } else { + barStart = BAR_START_ANGLE + minValue * angleStep; + barLength = - clampedValue * angleStep; + } + } + } else { + barStart = BAR_START_ANGLE; + barLength = ( minValue - clampedValue ) * angleStep; + } + + CTX.strokeArc(barXY, barXY, barWH, barWH, barStart, barLength, ArcType.OPEN); + CTX.restore(); + + valueText.setText(formatNumber(gauge.getLocale(), null/*gauge.getFormatString()*/, gauge.getDecimals(), CURRENT_VALUE)); + + } + + private void drawMainCanvas() { + mainCtx.clearRect(0, 0, size, size); + //mainCtx.setFillRule(FillRule.EVEN_ODD); + + // Draw sections if available + final double sectionsXY = (size - 0.75 * size) * 0.5; + final double sectionsWH = size * 0.75; + double minValue = gauge.getMinValue(); + double maxValue = gauge.getMaxValue(); + double offset = 90 - START_ANGLE; + double sectionWidth = size * 0.06; +/* + if (sectionsVisible) { + int listSize = sections.size(); + for (int i = 0; i < listSize; i++) { + final Section SECTION = sections.get(i); + final double SECTION_START_ANGLE; + if (Double.compare(SECTION.getStart(), maxValue) <= 0 && Double.compare(SECTION.getStop(), minValue) >= 0) { + if (Double.compare(SECTION.getStart(), minValue) < 0 && Double.compare(SECTION.getStop(), maxValue) < 0) { + SECTION_START_ANGLE = 0; + } else { + SECTION_START_ANGLE = (SECTION.getStart() - minValue) * angleStep; + } + final double SECTION_ANGLE_EXTEND; + if (Double.compare(SECTION.getStop(), maxValue) > 0) { + SECTION_ANGLE_EXTEND = (maxValue - SECTION.getStart()) * angleStep; + } else { + SECTION_ANGLE_EXTEND = (SECTION.getStop() - SECTION.getStart()) * angleStep; + } + mainCtx.save(); + mainCtx.setStroke(SECTION.getColor()); + mainCtx.setLineWidth(sectionWidth); + mainCtx.setLineCap(StrokeLineCap.BUTT); + mainCtx.strokeArc(sectionsXY, sectionsXY, sectionsWH, sectionsWH, -(offset + SECTION_START_ANGLE), -SECTION_ANGLE_EXTEND, ArcType.OPEN); + mainCtx.restore(); + } + } + } +*/ + + // Draw tickmarks + mainCtx.save(); + drawTickMarks(mainCtx); + mainCtx.restore(); + + // Draw black bar overlay + mainCtx.save(); + mainCtx.setStroke(Color.rgb(23, 23, 23)); + mainCtx.setLineWidth(size * 0.025); + mainCtx.setLineCap(StrokeLineCap.BUTT); + mainCtx.strokeArc(sectionsXY, sectionsXY, sectionsWH, sectionsWH, BAR_START_ANGLE, -ANGLE_RANGE, ArcType.OPEN); + mainCtx.restore(); + + // Draw databar background + double barXY = (size - 0.75 * size) * 0.5; + double barWH = size * 0.75; + mainCtx.save(); + mainCtx.setStroke(Color.rgb(57, 57, 57, 0.75)); + mainCtx.setLineWidth(size * 0.01666667); + mainCtx.setLineCap(StrokeLineCap.BUTT); + mainCtx.strokeArc(barXY, barXY, barWH, barWH, BAR_START_ANGLE, -ANGLE_RANGE, ArcType.OPEN); + mainCtx.restore(); + + // Draw threshold + if (gauge.isThresholdVisible()) { + mainCtx.save(); + mainCtx.translate(size * 0.5, size * 0.5); + mainCtx.rotate(((gauge.getThreshold() - minValue ) * angleStep) - 120); + mainCtx.beginPath(); + mainCtx.moveTo(0, -size * 0.33); + mainCtx.lineTo(-size * 0.0125, -size * 0.30833333); + mainCtx.lineTo(size * 0.0125, -size * 0.30833333); + mainCtx.closePath(); + mainCtx.setFill(gauge.getNeedleColor()); + mainCtx.fill(); + mainCtx.restore(); + } + } + + private void drawTickMarks(final GraphicsContext CTX) { + double sinValue; + double cosValue; + double centerX = size * 0.5; + double centerY = size * 0.5; + double minorTickSpace = gauge.getMinorTickSpace(); + double minValue = gauge.getMinValue(); + double maxValue = gauge.getMaxValue(); + double tmpAngleStep = angleStep * minorTickSpace; + int decimals = gauge.getTickLabelDecimals(); + BigDecimal minorTickSpaceBD = BigDecimal.valueOf(minorTickSpace); + BigDecimal majorTickSpaceBD = BigDecimal.valueOf(gauge.getMajorTickSpace()); + BigDecimal mediumCheck2 = BigDecimal.valueOf(2 * minorTickSpace); + BigDecimal mediumCheck5 = BigDecimal.valueOf(5 * minorTickSpace); + BigDecimal counterBD = BigDecimal.valueOf(minValue); + double counter = minValue; + boolean majorTickMarksVisible = gauge.getMajorTickMarksVisible(); + boolean mediumTickMarksVisible = gauge.getMediumTickMarksVisible(); + boolean tickLabelsVisible = gauge.getTickLabelsVisible(); + TickLabelOrientation tickLabelOrientation = gauge.getTickLabelOrientation(); + Color tickMarkColor = gauge.getTickMarkColor(); + Color majorTickMarkColor = tickMarkColor; + Color mediumTickMarkColor = tickMarkColor; + Color tickLabelColor = gauge.getTickLabelColor(); + + double innerPointX; + double innerPointY; + double outerPointX; + double outerPointY; + double innerMediumPointX; + double innerMediumPointY; + double outerMediumPointX; + double outerMediumPointY; + double textPointX; + double textPointY; + + double orthTextFactor = 0.46; //TickLabelOrientation.ORTHOGONAL == gauge.getTickLabelOrientation() ? 0.46 : 0.46; + + Font tickLabelFont = Fonts.robotoCondensedLight((decimals == 0 ? 0.047 : 0.040) * size); + CTX.setFont(tickLabelFont); + CTX.setTextAlign(TextAlignment.CENTER); + CTX.setTextBaseline(VPos.CENTER); + + CTX.setLineCap(StrokeLineCap.BUTT); + CTX.setLineWidth(size * 0.0035); + for (double angle = 0 ; Double.compare(-ANGLE_RANGE - tmpAngleStep, angle) < 0 ; angle -= tmpAngleStep) { + sinValue = Math.sin(Math.toRadians(angle + START_ANGLE)); + cosValue = Math.cos(Math.toRadians(angle + START_ANGLE)); + + innerPointX = centerX + size * 0.375 * sinValue; + innerPointY = centerY + size * 0.375 * cosValue; + outerPointX = centerX + size * 0.425 * sinValue; + outerPointY = centerY + size * 0.425 * cosValue; + innerMediumPointX = centerX + size * 0.35 * sinValue; + innerMediumPointY = centerY + size * 0.35 * cosValue; + outerMediumPointX = centerX + size * 0.4 * sinValue; + outerMediumPointY = centerY + size * 0.4 * cosValue; + textPointX = centerX + size * orthTextFactor * sinValue; + textPointY = centerY + size * orthTextFactor * cosValue; + + // Set the general tickmark color + CTX.setStroke(tickMarkColor); + + if (Double.compare(counterBD.remainder(majorTickSpaceBD).doubleValue(), 0.0) == 0) { + // Draw major tick mark + if (majorTickMarksVisible) { + CTX.setFill(majorTickMarkColor); + CTX.setStroke(majorTickMarkColor); + CTX.strokeLine(innerPointX, innerPointY, outerPointX, outerPointY); + } + // Draw tick label text + if (tickLabelsVisible) { + CTX.save(); + CTX.translate(textPointX, textPointY); + + Helper.rotateContextForText(CTX, START_ANGLE, angle, tickLabelOrientation); + + CTX.setFill(tickLabelColor); + if (TickLabelOrientation.HORIZONTAL == tickLabelOrientation && + (Double.compare(counter, minValue) == 0 || + Double.compare(counter, maxValue) == 0)) { + CTX.setFill(Color.TRANSPARENT); + } + CTX.fillText(Helper.formatNumber(locale, null, decimals, counter) /*String.format(locale, "%." + decimals + "f", counter)*/, 0, 0); + CTX.restore(); + } + } else if (mediumTickMarksVisible && + Double.compare(minorTickSpaceBD.remainder(mediumCheck2).doubleValue(), 0.0) != 0.0 && + Double.compare(counterBD.remainder(mediumCheck5).doubleValue(), 0.0) == 0.0) { + // Draw medium tick mark + CTX.setFill(mediumTickMarkColor); + CTX.setStroke(mediumTickMarkColor); + CTX.strokeLine(innerMediumPointX, innerMediumPointY, outerMediumPointX, outerMediumPointY); + } + counterBD = counterBD.add(minorTickSpaceBD); + counter = counterBD.doubleValue(); + } + } + + private void resizeText() { + double maxWidth = 0.405 * size; + + titleText.setText(gauge.getTitle()); + double titleWidth = titleText.getLayoutBounds().getWidth(); + if (titleText.getText().length() > titleLength) { + if (titleWidth > maxWidth) { Helper.adjustTextSize(titleText, maxWidth, size * 0.062); } + } + titleText.setLayoutX((size - titleWidth) * 0.5); + + //maxWidth = centerKnob.getRadius() * 1.8; + double fontSize = centerKnob.getRadius() * 0.65; + valueText.setFont(Fonts.latoRegular(fontSize)); + //if (valueText.getBoundsInLocal().getWidth() > maxWidth) { Helper.adjustTextSize(valueText, maxWidth, fontSize); } + valueText.setLayoutX((size - valueText.getLayoutBounds().getWidth()) * 0.5); + + maxWidth = 0.28 * size; + subTitleText.setText(gauge.getSubTitle()); + if (subTitleText.getText().length() > subTitleLength) { + if (subTitleText.getLayoutBounds().getWidth() > maxWidth) { Helper.adjustTextSize(subTitleText, maxWidth, size * 0.047); } + } + subTitleText.setLayoutX((size - subTitleText.getLayoutBounds().getWidth()) * 0.5); + + unitText.setText(gauge.getUnit()); + if (unitText.getText().length() > unitLength) { + if (unitText.getLayoutBounds().getWidth() > maxWidth) { Helper.adjustTextSize(unitText, maxWidth, size * 0.047); } + } + unitText.setLayoutX((size - unitText.getLayoutBounds().getWidth()) * 0.5); + + titleLength = titleText.getText().length(); + subTitleLength = subTitleText.getText().length(); + unitLength = unitText.getText().length(); + valueLength = valueText.getText().length(); + } + + private void placeTextVerticaly() { + valueText.setLayoutY(size * 0.5); + + titleText.setLayoutY(size * 0.83); + + subTitleText.setLayoutY(size * 0.35); + + unitText.setLayoutY(size * 0.67); + } + + @Override protected void resize() { + double width = gauge.getWidth() - gauge.getInsets().getLeft() - gauge.getInsets().getRight(); + double height = gauge.getHeight() - gauge.getInsets().getTop() - gauge.getInsets().getBottom(); + size = width < height ? width : height; + + if (size > 0) { + pane.setMaxSize(size, size); + pane.relocate((gauge.getWidth() - size) * 0.5, (gauge.getHeight() - size) * 0.5); + + background.setRadius(size * 0.5); + background.setCenterX(size * 0.5); + background.setCenterY(size * 0.5); + + mask.getElements().clear(); + mask.getElements().add(new MoveTo(0.23333333333333334 * size, 0.5 * size)); + mask.getElements().add(new CubicCurveTo(0.23333333333333334 * size, 0.3525 * size, + 0.3525 * size, 0.23333333333333334 * size, + 0.5 * size, 0.23333333333333334 * size)); + mask.getElements().add(new CubicCurveTo(0.6475 * size, 0.23333333333333334 * size, + 0.7666666666666667 * size, 0.3525 * size, + 0.7666666666666667 * size, 0.5 * size)); + mask.getElements().add(new CubicCurveTo(0.7666666666666667 * size, 0.6475 * size, + 0.6475 * size, 0.7666666666666667 * size, + 0.5 * size, 0.7666666666666667 * size)); + mask.getElements().add(new CubicCurveTo(0.3525 * size, 0.7666666666666667 * size, + 0.23333333333333334 * size, 0.6475 * size, + 0.23333333333333334 * size, 0.5 * size)); + mask.getElements().add(new ClosePath()); + mask.getElements().add(new MoveTo(0.2 * size, 0.5 * size)); + mask.getElements().add(new CubicCurveTo(0.2 * size, 0.555 * size, + 0.215 * size, 0.6058333333333333 * size, + 0.24 * size, 0.65 * size)); + mask.getElements().add(new CubicCurveTo(0.24 * size, 0.65 * size, + 0.12583333333333332 * size, 0.7166666666666667 * size, + 0.12583333333333332 * size, 0.7166666666666667 * size)); + mask.getElements().add(new CubicCurveTo(0.205 * size, 0.8541666666666666 * size, + 0.3408333333333333 * size, 0.9333333333333333 * size, + 0.5 * size, 0.9333333333333333 * size)); + mask.getElements().add(new CubicCurveTo(0.6591666666666667 * size, 0.9333333333333333 * size, + 0.795 * size, 0.8541666666666666 * size, + 0.8741666666666666 * size, 0.7166666666666667 * size)); + mask.getElements().add(new CubicCurveTo(0.8741666666666666 * size, 0.7166666666666667 * size, + 0.76 * size, 0.65 * size, + 0.76 * size, 0.65 * size)); + mask.getElements().add(new CubicCurveTo(0.785 * size, 0.6058333333333333 * size, + 0.8 * size, 0.555 * size, + 0.8 * size, 0.5 * size)); + mask.getElements().add(new CubicCurveTo(0.8 * size, 0.33416666666666667 * size, + 0.6658333333333334 * size, 0.2 * size, + 0.5 * size, 0.2 * size)); + mask.getElements().add(new CubicCurveTo(0.33416666666666667 * size, 0.2 * size, + 0.2 * size, 0.33416666666666667 * size, + 0.2 * size, 0.5 * size)); + mask.getElements().add(new ClosePath()); + + dropShadow4.setOffsetY(0.014 * size); + dropShadow4.setRadius(0.014 * size); + + needleMoveTo1.setX(0.5008333333333334 * size); needleMoveTo1.setY(0.0775 * size); + + needleCubicCurveTo2.setControlX1(0.5008333333333334 * size); needleCubicCurveTo2.setControlY1(0.0775 * size); + needleCubicCurveTo2.setControlX2(0.5416666666666666 * size); needleCubicCurveTo2.setControlY2(0.0025 * size); + needleCubicCurveTo2.setX(0.5416666666666666 * size); needleCubicCurveTo2.setY(0.0025 * size); + + needleCubicCurveTo3.setControlX1(0.5125 * size); needleCubicCurveTo3.setControlY1(0); + needleCubicCurveTo3.setControlX2(0.4875 * size); needleCubicCurveTo3.setControlY2(0); + needleCubicCurveTo3.setX(0.4583333333333333 * size); needleCubicCurveTo3.setY(0.0025 * size); + + needleCubicCurveTo4.setControlX1(0.4583333333333333 * size); needleCubicCurveTo4.setControlY1(0.0025 * size); + needleCubicCurveTo4.setControlX2(0.49833333333333335 * size); needleCubicCurveTo4.setControlY2(0.0775 * size); + needleCubicCurveTo4.setX(0.49833333333333335 * size); needleCubicCurveTo4.setY(0.0775 * size); + + needleLineTo5.setX(0.49833333333333335 * size); needleLineTo5.setY(0.0775 * size); + + needleLineTo6.setX(0.49833333333333335 * size); needleLineTo6.setY(0.17916666666666667 * size); + + needleLineTo7.setX(0.5008333333333334 * size); needleLineTo7.setY(0.17916666666666667 * size); + + needleLineTo8.setX(0.5008333333333334 * size); needleLineTo8.setY(0.0775 * size); + + needle.relocate(needle.getLayoutBounds().getMinX(), needle.getLayoutBounds().getMinY()); + needleRotate.setPivotX(size * 0.5); + needleRotate.setPivotY(size * 0.5); + // Added these 3 lines of code to make WebFx react to the above changes (as not auto-reacting yet) + List elements = new ArrayList<>(needle.getElements()); + needle.getElements().clear(); + needle.getElements().setAll(elements); + + mainCanvas.setCache(false); + mainCanvas.setWidth(size); + mainCanvas.setHeight(size); + drawMainCanvas(); + mainCanvas.setCache(true); + mainCanvas.setCacheHint(CacheHint.QUALITY); + + tickMarkCanvas.setWidth(size); + tickMarkCanvas.setHeight(size); + highlightValue(tickMarkCtx, gauge.getValue()); + + centerKnob.setRadius(0.22916667 * size); + centerKnob.setCenterX(0.5 * size); + centerKnob.setCenterY(0.5 * size); + centerKnob.setFill(new LinearGradient(0.5 * size, 0.2708333333333333 * size, + 0.5 * size, 0.7291666666666666 * size, + false, CycleMethod.NO_CYCLE, + new Stop(0.0, Color.rgb(69,70,73)), + new Stop(1.0, Color.rgb(31,31,31)))); + centerKnob.setEffect(dropShadow4); + + glow1.setRadius(0.085 * size); + glow2.setRadius(0.085 * size); + bigGlow.setRadius(0.25 * size); + + titleText.setFont(Fonts.robotoCondensedRegular(size * 0.062)); + subTitleText.setFont(Fonts.robotoCondensedLight(size * 0.047)); + valueText.setFont(Fonts.latoRegular(size * 0.22)); + unitText.setFont(Fonts.robotoCondensedRegular(size * 0.047)); + + resizeText(); + placeTextVerticaly(); + } + } + + @Override protected void redraw() { +// sectionsVisible = gauge.getSectionsVisible(); + locale = gauge.getLocale(); + barColor = gauge.getBarColor(); + thresholdColor = gauge.getThresholdColor(); + needle.setFill(gauge.getNeedleColor()); + titleText.setFill(gauge.getTitleColor()); + subTitleText.setFill(gauge.getSubTitleColor()); + unitText.setFill(gauge.getUnitColor()); + valueText.setFill(gauge.getValueColor()); + //buttonTooltip.setText(gauge.getButtonTooltipText()); + + mainCanvas.setCache(false); + mainCanvas.setWidth(size); + mainCanvas.setHeight(size); + drawMainCanvas(); + mainCanvas.setCache(true); + mainCanvas.setCacheHint(CacheHint.QUALITY); + resizeText(); + } +} diff --git a/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/tools/Helper.java b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/tools/Helper.java new file mode 100644 index 0000000..45d3486 --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/eu/hansolo/medusa/tools/Helper.java @@ -0,0 +1,1249 @@ +/* + * Copyright (c) 2015 by Gerrit Grunwald + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.hansolo.medusa.tools; + +import eu.hansolo.medusa.*; +import javafx.geometry.VPos; +import javafx.scene.Node; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; +import javafx.scene.shape.ArcType; +import javafx.scene.shape.StrokeLineCap; +import javafx.scene.text.Font; +import javafx.scene.text.Text; +import javafx.scene.text.TextAlignment; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +//import javafx.scene.canvas.Canvas; +//import javafx.scene.canvas.GraphicsContext; + + +/** + * Created by hansolo on 11.12.15. + */ +public class Helper { + public static final double MAX_TICK_MARK_LENGTH = 0.125; + public static final double MAX_TICK_MARK_WIDTH = 0.02; + public static final Color INACTIVE_ALARM_COLOR = Color.rgb(90, 90, 90, 0.5); + + + public static final T clamp(final T MIN, final T MAX, final T VALUE) { + if (VALUE.doubleValue() < MIN.doubleValue()) return MIN; + if (VALUE.doubleValue() > MAX.doubleValue()) return MAX; + return VALUE; + } + + public static final int clamp(final int MIN, final int MAX, final int VALUE) { + if (VALUE < MIN) return MIN; + if (VALUE > MAX) return MAX; + return VALUE; + } + public static final long clamp(final long MIN, final long MAX, final long VALUE) { + if (VALUE < MIN) return MIN; + if (VALUE > MAX) return MAX; + return VALUE; + } + public static final double clamp(final double MIN, final double MAX, final double VALUE) { + if (Double.compare(VALUE, MIN) < 0) return MIN; + if (Double.compare(VALUE, MAX) > 0) return MAX; + return VALUE; + } + + public static final double clampMin(final double MIN, final double VALUE) { + if (VALUE < MIN) return MIN; + return VALUE; + } + public static final double clampMax(final double MAX, final double VALUE) { + if (VALUE > MAX) return MAX; + return VALUE; + } + + public static final double round(final double VALUE, final int PRECISION) { + final int SCALE = (int) Math.pow(10, PRECISION); + return (double) Math.round(VALUE * SCALE) / SCALE; + } + + public static final double roundTo(final double VALUE, final double TARGET) { return TARGET * (Math.round(VALUE / TARGET)); } + + public static final double roundToHalf(final double VALUE) { return Math.round(VALUE * 2) / 2.0; } + + + public static final double nearest(final double SMALLER, final double VALUE, final double LARGER) { + return (VALUE - SMALLER) < (LARGER - VALUE) ? SMALLER : LARGER; + } + + public static final int roundDoubleToInt(final double VALUE){ + double dAbs = Math.abs(VALUE); + int i = (int) dAbs; + double result = dAbs - (double) i; + if (result < 0.5) { + return VALUE < 0 ? -i : i; + } else { + return VALUE < 0 ? -(i + 1) : i + 1; + } + } + + public static final double[] calcAutoScale(final double MIN_VALUE, final double MAX_VALUE) { + double maxNoOfMajorTicks = 10; + double maxNoOfMinorTicks = 10; + double niceMinValue; + double niceMaxValue; + double niceRange; + double majorTickSpace; + double minorTickSpace; + niceRange = (calcNiceNumber((MAX_VALUE - MIN_VALUE), false)); + majorTickSpace = calcNiceNumber(niceRange / (maxNoOfMajorTicks - 1), true); + niceMinValue = (Math.floor(MIN_VALUE / majorTickSpace) * majorTickSpace); + niceMaxValue = (Math.ceil(MAX_VALUE / majorTickSpace) * majorTickSpace); + minorTickSpace = calcNiceNumber(majorTickSpace / (maxNoOfMinorTicks - 1), true); + return new double[]{ niceMinValue, niceMaxValue, majorTickSpace, minorTickSpace }; + } + + /** + * Calculates nice minValue, maxValue and stepSize for given MIN and MAX values + * @param MIN + * @param MAX + * @return array of doubles with [niceMin, niceMax, niceRange, niceStep] + */ + public static final double[] getNiceScale(final double MIN, final double MAX) { + return getNiceScale(MIN, MAX, 20); + } + /** + * Calculates nice minValue, maxValue and stepSize for given MIN and MAX values + * @param MIN + * @param MAX + * @param MAX_NO_OF_TICKS + * @return array of doubles with [niceMin, niceMax, niceRange, niceStep] + */ + public static final double[] getNiceScale(final double MIN, final double MAX, final int MAX_NO_OF_TICKS) { + // Minimal increment to avoid round extreme values to be on the edge of the chart + double minimum = MIN; + double maximum = MAX; + double epsilon = (MAX - MIN) / 1e6; + maximum += epsilon; + minimum -= epsilon; + double range = maximum - minimum; + + // Target number of values to be displayed on the Y axis (it may be less) + int stepCount = MAX_NO_OF_TICKS; + // First approximation + double roughStep = range / (stepCount - 1); + + // Set best niceStep for the range + //double[] goodNormalizedSteps = { 1, 1.5, 2, 2.5, 5, 7.5, 10 }; // keep the 10 at the end + double[] goodNormalizedSteps = { 1, 2, 5, 10 }; + + // Normalize rough niceStep to find the normalized one that fits best + double stepPower = Math.pow(10, -Math.floor(Math.log10(Math.abs(roughStep)))); + double normalizedStep = roughStep * stepPower; + double goodNormalizedStep = Arrays.stream(goodNormalizedSteps).filter(n -> Double.compare(n, normalizedStep) >= 0).findFirst().getAsDouble(); + double niceStep = goodNormalizedStep / stepPower; + + // Determine the scale limits based on the chosen niceStep. + double niceMin = minimum < 0 ? Math.floor(minimum / niceStep) * niceStep : Math.ceil(minimum / niceStep) * niceStep; + double niceMax = maximum < 0 ? Math.floor(maximum / niceStep) * niceStep : Math.ceil(maximum / niceStep) * niceStep; + + if (MIN % niceStep == 0) { niceMin = MIN; } + if (MAX % niceStep == 0) { niceMax = MAX; } + + double niceRange = niceMax - niceMin; + + return new double[] { niceMin, niceMax, niceRange, niceStep }; + } + + /** + * Can be used to implement discrete steps e.g. on a slider. + * @param MIN_VALUE The min value of the range + * @param MAX_VALUE The max value of the range + * @param VALUE The value to snap + * @param MINOR_TICK_COUNT The number of ticks between 2 major tick marks + * @param MAJOR_TICK_UNIT The distance between 2 major tick marks + * @return The value snapped to the next tick mark defined by the given parameters + */ + public static final double snapToTicks(final double MIN_VALUE, final double MAX_VALUE, final double VALUE, final int MINOR_TICK_COUNT, final double MAJOR_TICK_UNIT) { + double v = VALUE; + int minorTickCount = clamp(0, 10, MINOR_TICK_COUNT); + double majorTickUnit = Double.compare(MAJOR_TICK_UNIT, 0.0) <= 0 ? 0.25 : MAJOR_TICK_UNIT; + double tickSpacing; + + if (minorTickCount != 0) { + tickSpacing = majorTickUnit / (Math.max(minorTickCount, 0) + 1); + } else { + tickSpacing = majorTickUnit; + } + + int prevTick = (int) ((v - MIN_VALUE) / tickSpacing); + double prevTickValue = prevTick * tickSpacing + MIN_VALUE; + double nextTickValue = (prevTick + 1) * tickSpacing + MIN_VALUE; + + v = nearest(prevTickValue, v, nextTickValue); + + return clamp(MIN_VALUE, MAX_VALUE, v); + } + + /** + * Returns a "niceScaling" number approximately equal to the range. + * Rounds the number if ROUND == true. + * Takes the ceiling if ROUND = false. + * + * @param RANGE the value range (maxValue - minValue) + * @param ROUND whether to round the result or ceil + * @return a "niceScaling" number to be used for the value range + */ + public static final double calcNiceNumber(final double RANGE, final boolean ROUND) { + double niceFraction; + double exponent = Math.floor(Math.log10(RANGE)); // exponent of range + double fraction = RANGE / Math.pow(10, exponent); // fractional part of range + + if (ROUND) { + if (fraction < 1.5) { + niceFraction = 1; + } else if (fraction < 3) { + niceFraction = 2; + } else if (fraction < 7) { + niceFraction = 5; + } else { + niceFraction = 10; + } + } else { + if (fraction <= 1) { + niceFraction = 1; + } else if (fraction <= 2) { + niceFraction = 2; + } else if (fraction <= 5) { + niceFraction = 5; + } else { + niceFraction = 10; + } + } + return niceFraction * Math.pow(10, exponent); + } + +/* + public static final Color getColorOfSection(final List
SECTIONS, final double VALUE, final Color DEFAULT_COLOR) { + for (Section section : SECTIONS) { + if (section.contains(VALUE)) return section.getColor(); + } + return DEFAULT_COLOR; + } +*/ + + public static final void rotateContextForText(final GraphicsContext CTX, final double START_ANGLE, final double ANGLE, final TickLabelOrientation ORIENTATION) { + switch (ORIENTATION) { + case ORTHOGONAL: + if ((360 - START_ANGLE - ANGLE) % 360 > 90 && (360 - START_ANGLE - ANGLE) % 360 < 270) { + CTX.rotate((180 - START_ANGLE - ANGLE) % 360); + } else { + CTX.rotate((360 - START_ANGLE - ANGLE) % 360); + } + break; + case TANGENT: + if ((360 - START_ANGLE - ANGLE - 90) % 360 > 90 && (360 - START_ANGLE - ANGLE - 90) % 360 < 270) { + CTX.rotate((90 - START_ANGLE - ANGLE) % 360); + } else { + CTX.rotate((270 - START_ANGLE - ANGLE) % 360); + } + break; + case HORIZONTAL: + default: + break; + } + } + + public static final void adjustTextSize(final Text TEXT, final double MAX_WIDTH, final double FONT_SIZE) { +/* + final String FONT_NAME = TEXT.getFont().getName(); + double adjustableFontSize = FONT_SIZE; + + while (TEXT.getBoundsInLocal().getWidth() > MAX_WIDTH && adjustableFontSize > 0) { + adjustableFontSize -= 0.05; + TEXT.setFont(new Font(FONT_NAME, adjustableFontSize)); + } +*/ + } +/* + public static final void adjustTextSize(final Label TEXT, final double MAX_WIDTH, final double FONT_SIZE) { + final String FONT_NAME = TEXT.getFont().getName(); + double adjustableFontSize = FONT_SIZE; + + while (TEXT.getBoundsInLocal().getWidth() > MAX_WIDTH && adjustableFontSize > 0) { + adjustableFontSize -= 0.05; + TEXT.setFont(new Font(FONT_NAME, adjustableFontSize)); + } + } + + public static final DateTimeFormatter getDateFormat(final Locale LOCALE) { + if (Locale.US == LOCALE) { + return DateTimeFormatter.ofPattern("MM/dd/YYYY"); + } else if (Locale.CHINA == LOCALE) { + return DateTimeFormatter.ofPattern("YYYY.MM.dd"); + } else { + return DateTimeFormatter.ofPattern("dd.MM.YYYY"); + } + } + public static final DateTimeFormatter getLocalizedDateFormat(final Locale LOCALE) { + return DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withLocale(LOCALE); + }*/ + + public static final void enableNode(final Node NODE, final boolean ENABLE) { + NODE.setManaged(ENABLE); + NODE.setVisible(ENABLE); + } + + /*public static final String colorToCss(final Color COLOR) { + return COLOR.toString().replace("0x", "#"); + } + + public static final ThreadFactory getThreadFactory(final String THREAD_NAME, final boolean IS_DAEMON) { + return runnable -> { + Thread thread = new Thread(runnable, THREAD_NAME); + thread.setDaemon(IS_DAEMON); + return thread; + }; + } + + public static final void stopTask(ScheduledFuture task) { + if (null == task) return; + task.cancel(true); + task = null; + } + + public static final ImagePattern createCarbonPattern() { + final double SIZE = 12; + final Canvas CANVAS = new Canvas(SIZE, SIZE); + final GraphicsContext CTX = CANVAS.getGraphicsContext2D(); + + CTX.setFill(new LinearGradient(0, 0, 0, 0.5 * SIZE, + false, CycleMethod.NO_CYCLE, + new Stop(0, Color.rgb(35, 35, 35)), + new Stop(1, Color.rgb(23, 23, 23)))); + CTX.fillRect(0, 0, SIZE * 0.5, SIZE * 0.5); + + CTX.setFill(new LinearGradient(0, 0, 0, 0.416666 * SIZE, + false, CycleMethod.NO_CYCLE, + new Stop(0, Color.rgb(38, 38, 38)), + new Stop(1, Color.rgb(30, 30, 30)))); + CTX.fillRect(SIZE * 0.083333, 0, SIZE * 0.333333, SIZE * 0.416666); + + CTX.setFill(new LinearGradient(0, 0.5 * SIZE, 0, SIZE, + false, CycleMethod.NO_CYCLE, + new Stop(0, Color.rgb(35, 35, 35)), + new Stop(1, Color.rgb(23, 23, 23)))); + CTX.fillRect(SIZE * 0.5, SIZE * 0.5, SIZE * 0.5, SIZE * 0.5); + + CTX.setFill(new LinearGradient(0, 0.5 * SIZE, 0, 0.916666 * SIZE, + false, CycleMethod.NO_CYCLE, + new Stop(0, Color.rgb(38, 38, 38)), + new Stop(1, Color.rgb(30, 30, 30)))); + CTX.fillRect(SIZE * 0.583333, SIZE * 0.5, SIZE * 0.333333, SIZE * 0.416666); + + CTX.setFill(new LinearGradient(0, 0, 0, 0.5 * SIZE, + false, CycleMethod.NO_CYCLE, + new Stop(0, Color.rgb(48, 48, 48)), + new Stop(1, Color.rgb(40, 40, 40)))); + CTX.fillRect(SIZE * 0.5, 0, SIZE * 0.5, SIZE * 0.5); + + CTX.setFill(new LinearGradient(0, 0.083333 * SIZE, 0, 0.5 * SIZE, + false, CycleMethod.NO_CYCLE, + new Stop(0, Color.rgb(53, 53, 53)), + new Stop(1, Color.rgb(45, 45, 45)))); + CTX.fillRect(SIZE * 0.583333, SIZE * 0.083333, SIZE * 0.333333, SIZE * 0.416666); + + CTX.setFill(new LinearGradient(0, 0.5 * SIZE, 0, SIZE, + false, CycleMethod.NO_CYCLE, + new Stop(0, Color.rgb(48, 48, 48)), + new Stop(1, Color.rgb(40, 40, 40)))); + CTX.fillRect(0, SIZE * 0.5, SIZE * 0.5, SIZE * 0.5); + + CTX.setFill(new LinearGradient(0, 0.583333 * SIZE, 0, SIZE, + false, CycleMethod.NO_CYCLE, + new Stop(0, Color.rgb(53, 53, 53)), + new Stop(1, Color.rgb(45, 45, 45)))); + CTX.fillRect(SIZE * 0.083333, SIZE * 0.583333, SIZE * 0.333333, SIZE * 0.416666); + + final Image PATTERN_IMAGE = CANVAS.snapshot(new SnapshotParameters(), null); + final ImagePattern PATTERN = new ImagePattern(PATTERN_IMAGE, 0, 0, SIZE, SIZE, false); + + return PATTERN; + } +*/ + public static final void drawTrapezoid(final GraphicsContext CTX, + final double PI1X, final double PI1Y, final double PI2X, final double PI2Y, + final double PO1X, final double PO1Y, final double PO2X, final double PO2Y) { + CTX.beginPath(); + CTX.moveTo(PI2X, PI2Y); + CTX.lineTo(PI1X, PI1Y); + CTX.lineTo(PO1X, PO1Y); + CTX.lineTo(PO2X, PO2Y); + CTX.closePath(); + CTX.fill(); + } + public static final void drawTriangle(final GraphicsContext CTX, + final double PIX, final double PIY, final double PO1X, final double PO1Y, final double PO2X, final double PO2Y) { + CTX.beginPath(); + CTX.moveTo(PIX, PIY); + CTX.lineTo(PO1X, PO1Y); + CTX.lineTo(PO2X, PO2Y); + CTX.closePath(); + CTX.fill(); + } + public static final void drawDot(final GraphicsContext CTX, final double CENTER_X, final double CENTER_Y, final double SIZE) { + CTX.fillOval(CENTER_X, CENTER_Y, SIZE, SIZE); + } + public static final void drawLine(final GraphicsContext CTX, final double P1X, final double P1Y, final double P2X, final double P2Y) { + CTX.strokeLine(P1X, P1Y, P2X, P2Y); + } + + public static final boolean isMonochrome(final Color COLOR) { + return Double.compare(COLOR.getRed(), COLOR.getGreen()) == 0 && Double.compare(COLOR.getGreen(), COLOR.getBlue()) == 0; + } + + public static final double colorDistance(final Color COLOR_1, final Color COLOR_2) { + final double DELTA_R = (COLOR_2.getRed() - COLOR_1.getRed()); + final double DELTA_G = (COLOR_2.getGreen() - COLOR_1.getGreen()); + final double DELTA_B = (COLOR_2.getBlue() - COLOR_1.getBlue()); + + return Math.sqrt(DELTA_R * DELTA_R + DELTA_G * DELTA_G + DELTA_B * DELTA_B); + } + + public static final boolean isBright(final Color COLOR) { return !isDark(COLOR); } + public static final boolean isDark(final Color COLOR) { + final double DISTANCE_TO_WHITE = colorDistance(COLOR, Color.WHITE); + final double DISTANCE_TO_BLACK = colorDistance(COLOR, Color.BLACK); + return DISTANCE_TO_BLACK < DISTANCE_TO_WHITE; + } + + public static final Color getTranslucentColorFrom(final Color COLOR, final double FACTOR) { + return Color.color(COLOR.getRed(), COLOR.getGreen(), COLOR.getBlue(), Helper.clamp(0.0, 1.0, FACTOR)); + } + + public static final void drawRadialTickMarks(final Gauge GAUGE, final GraphicsContext CTX, + final double MIN_VALUE, final double MAX_VALUE, + final double START_ANGLE, final double ANGLE_RANGE, final double ANGLE_STEP, + final double CENTER_X, final double CENTER_Y, final double SIZE) { + double sinValue; + double cosValue; + double centerX = CENTER_X; + double centerY = CENTER_Y; + int tickLabelDecimals = GAUGE.getTickLabelDecimals(); + String tickLabelFormatString = "%." + tickLabelDecimals + "f"; + double minorTickSpace = GAUGE.getMinorTickSpace(); + double tmpAngleStep = ANGLE_STEP * minorTickSpace; + TickLabelOrientation tickLabelOrientation = GAUGE.getTickLabelOrientation(); + TickLabelLocation tickLabelLocation = GAUGE.getTickLabelLocation(); + BigDecimal minorTickSpaceBD = BigDecimal.valueOf(minorTickSpace); + BigDecimal majorTickSpaceBD = BigDecimal.valueOf(GAUGE.getMajorTickSpace()); + BigDecimal mediumCheck2 = BigDecimal.valueOf(2 * minorTickSpace); + BigDecimal mediumCheck5 = BigDecimal.valueOf(5 * minorTickSpace); + BigDecimal counterBD = BigDecimal.valueOf(MIN_VALUE); + double counter = MIN_VALUE; + +// List
tickMarkSections = GAUGE.getTickMarkSections(); +// List
tickLabelSections = GAUGE.getTickLabelSections(); + Color tickMarkColor = GAUGE.getTickMarkColor(); + Color majorTickMarkColor = GAUGE.getMajorTickMarkColor().equals(tickMarkColor) ? tickMarkColor : GAUGE.getMajorTickMarkColor(); + Color mediumTickMarkColor = GAUGE.getMediumTickMarkColor().equals(tickMarkColor) ? tickMarkColor : GAUGE.getMediumTickMarkColor(); + Color minorTickMarkColor = GAUGE.getMinorTickMarkColor().equals(tickMarkColor) ? tickMarkColor : GAUGE.getMinorTickMarkColor(); + double majorTickMarkLengthFactor = GAUGE.getMajorTickMarkLengthFactor(); + double majorTickMarkWidthFactor = GAUGE.getMajorTickMarkWidthFactor(); + double mediumTickMarkLengthFactor = GAUGE.getMediumTickMarkLengthFactor(); + double mediumTickMarkWidthFactor = GAUGE.getMediumTickMarkWidthFactor(); + double minorTickMarkLengthFactor = GAUGE.getMinorTickMarkLengthFactor(); + double minorTickMarkWidthFactor = GAUGE.getMinorTickMarkWidthFactor(); + Color tickLabelColor = GAUGE.getTickLabelColor(); + Color zeroColor = GAUGE.getZeroColor(); + boolean isNotZero = true; + TickMarkType majorTickMarkType = GAUGE.getMajorTickMarkType(); + TickMarkType mediumTickMarkType = GAUGE.getMediumTickMarkType(); + TickMarkType minorTickMarkType = GAUGE.getMinorTickMarkType(); + boolean tickMarkSectionsVisible = GAUGE.getTickMarkSectionsVisible(); + boolean tickLabelSectionsVisible = GAUGE.getTickLabelSectionsVisible(); + boolean majorTickMarksVisible = GAUGE.getMajorTickMarksVisible(); + boolean mediumTickMarksVisible = GAUGE.getMediumTickMarksVisible(); + boolean minorTickMarksVisible = GAUGE.getMinorTickMarksVisible(); + boolean tickLabelsVisible = GAUGE.getTickLabelsVisible(); + boolean onlyFirstAndLastLabelVisible = GAUGE.isOnlyFirstAndLastTickLabelVisible(); + boolean customTickLabelsEnabled = GAUGE.getCustomTickLabelsEnabled(); + Locale locale = GAUGE.getLocale(); + List customTickLabels = customTickLabelsEnabled ? GAUGE.getCustomTickLabels() : null; + double textDisplacementFactor = majorTickMarkType == TickMarkType.DOT ? (TickLabelLocation.OUTSIDE == tickLabelLocation ? 0.95 : 1.05) : 1.0; + double majorDotSize; + double majorHalfDotSize; + double mediumDotSize; + double mediumHalfDotSize; + double minorDotSize; + double minorHalfDotSize; + + double orthTextFactor; + if (TickLabelLocation.OUTSIDE == tickLabelLocation) { + orthTextFactor = 0.45 * textDisplacementFactor;//TickLabelOrientation.ORTHOGONAL == tickLabelOrientation ? 0.45 * textDisplacementFactor : 0.45 * textDisplacementFactor; + majorDotSize = 0.02 * SIZE; + majorHalfDotSize = majorDotSize * 0.5; + mediumDotSize = 0.01375 * SIZE; + mediumHalfDotSize = mediumDotSize * 0.5; + minorDotSize = 0.0075 * SIZE; + minorHalfDotSize = minorDotSize * 0.5; + } else { + orthTextFactor = TickLabelOrientation.ORTHOGONAL == tickLabelOrientation ? 0.38 * textDisplacementFactor : 0.37 * textDisplacementFactor; + majorDotSize = 0.025 * SIZE; + majorHalfDotSize = majorDotSize * 0.5; + mediumDotSize = 0.01875 * SIZE; + mediumHalfDotSize = mediumDotSize * 0.5; + minorDotSize = 0.0125 * SIZE; + minorHalfDotSize = minorDotSize * 0.5; + }; + + double customFontSizeFactor = GAUGE.getCustomTickLabelFontSize() / 400; + boolean fullRange = (MIN_VALUE < 0 && MAX_VALUE > 0); + double tickLabelFontSize = tickLabelDecimals == 0 ? 0.054 * SIZE : 0.051 * SIZE; + tickLabelFontSize = GAUGE.getCustomTickLabelsEnabled() ? customFontSizeFactor * SIZE : tickLabelFontSize; + double tickMarkFontSize = tickLabelDecimals == 0 ? 0.047 * SIZE: 0.044 * SIZE; + double tickLabelOrientationFactor = TickLabelOrientation.HORIZONTAL == tickLabelOrientation ? 0.9 : 1.0; + + Font tickLabelFont = Fonts.robotoCondensedRegular(tickLabelFontSize * tickLabelOrientationFactor); + Font tickMarkFont = Fonts.robotoCondensedRegular(tickMarkFontSize * tickLabelOrientationFactor); + Font tickLabelZeroFont = fullRange ? Fonts.robotoCondensedBold(tickLabelFontSize * tickLabelOrientationFactor) : tickLabelFont; + Font tickMarkZeroFont = fullRange ? Fonts.robotoCondensedBold(tickMarkFontSize * tickLabelOrientationFactor) : tickMarkFont; + + // Variables needed for tickmarks + double innerPointX; + double innerPointY; + double innerMediumPointX; + double innerMediumPointY; + double innerMinorPointX; + double innerMinorPointY; + double outerPointX; + double outerPointY; + double outerMediumPointX; + double outerMediumPointY; + double outerMinorPointX; + double outerMinorPointY; + double textPointX; + double textPointY; + double dotCenterX; + double dotCenterY; + double dotMediumCenterX; + double dotMediumCenterY; + double dotMinorCenterX; + double dotMinorCenterY; + double tickLabelTickMarkX; + double tickLabelTickMarkY; + + double trapezoidMajorInnerAngle1; + double trapezoidMajorInnerAngle2; + double trapezoidMajorOuterAngle1; + double trapezoidMajorOuterAngle2; + double trapezoidMajorInnerPoint1X; + double trapezoidMajorInnerPoint1Y; + double trapezoidMajorInnerPoint2X; + double trapezoidMajorInnerPoint2Y; + double trapezoidMajorOuterPoint1X; + double trapezoidMajorOuterPoint1Y; + double trapezoidMajorOuterPoint2X; + double trapezoidMajorOuterPoint2Y; + + double trapezoidMediumInnerAngle1; + double trapezoidMediumInnerAngle2; + double trapezoidMediumOuterAngle1; + double trapezoidMediumOuterAngle2; + double trapezoidMediumInnerPoint1X; + double trapezoidMediumInnerPoint1Y; + double trapezoidMediumInnerPoint2X; + double trapezoidMediumInnerPoint2Y; + double trapezoidMediumOuterPoint1X; + double trapezoidMediumOuterPoint1Y; + double trapezoidMediumOuterPoint2X; + double trapezoidMediumOuterPoint2Y; + + double trapezoidMinorInnerAngle1; + double trapezoidMinorInnerAngle2; + double trapezoidMinorOuterAngle1; + double trapezoidMinorOuterAngle2; + double trapezoidMinorInnerPoint1X; + double trapezoidMinorInnerPoint1Y; + double trapezoidMinorInnerPoint2X; + double trapezoidMinorInnerPoint2Y; + double trapezoidMinorOuterPoint1X; + double trapezoidMinorOuterPoint1Y; + double trapezoidMinorOuterPoint2X; + double trapezoidMinorOuterPoint2Y; + + double triangleMajorInnerPointX; + double triangleMajorInnerPointY; + double triangleMajorOuterPointX; + double triangleMajorOuterPointY; + + double triangleMediumInnerPointX; + double triangleMediumInnerPointY; + double triangleMediumOuterPointX; + double triangleMediumOuterPointY; + + double triangleMinorInnerPointX; + double triangleMinorInnerPointY; + double triangleMinorOuterPointX; + double triangleMinorOuterPointY; + + Gauge.ScaleDirection scaleDirection = GAUGE.getScaleDirection(); + + // Draw tickmark ring + if (GAUGE.isTickMarkRingVisible()) { + Gauge.SkinType skinType = GAUGE.getSkinType(); + double xy = TickLabelLocation.INSIDE == tickLabelLocation ? SIZE * 0.026 : SIZE * 0.14; + double wh = TickLabelLocation.INSIDE == tickLabelLocation ? SIZE * 0.948 : SIZE * 0.72; + double offset = -90 + START_ANGLE; + double horVerOffset = SIZE * 0.055555555; + CTX.setLineWidth(SIZE * 0.004); + CTX.setLineCap(StrokeLineCap.SQUARE); + CTX.save(); + CTX.setStroke(tickMarkColor); + switch(skinType) { + case HORIZONTAL: CTX.strokeArc(xy + horVerOffset, xy, wh, wh, offset, -ANGLE_RANGE, ArcType.OPEN); break; + case VERTICAL : CTX.strokeArc(xy, xy + horVerOffset, wh, wh, offset, -ANGLE_RANGE, ArcType.OPEN); break; + default : CTX.strokeArc(xy, xy, wh, wh, offset, -ANGLE_RANGE, ArcType.OPEN); break; + } + + CTX.restore(); + /*if (tickMarkSections.size() > 0) { + int listSize = tickMarkSections.size(); + double sectionStartAngle; + for (int i = 0; i < listSize; i++) { + Section section = tickMarkSections.get(i); + if (Double.compare(section.getStart(), MIN_VALUE) < 0 && Double.compare(section.getStop(), MAX_VALUE) < 0) { + sectionStartAngle = 0; + } else { + sectionStartAngle = Gauge.ScaleDirection.CLOCKWISE == scaleDirection ? (section.getStart() - MIN_VALUE) * ANGLE_STEP : -(section.getStart() - MIN_VALUE) * ANGLE_STEP; + } + double sectionAngleExtend; + if (Double.compare(section.getStop(), MAX_VALUE) > 0) { + sectionAngleExtend = Gauge.ScaleDirection.CLOCKWISE == scaleDirection ? (MAX_VALUE - section.getStart()) * ANGLE_STEP : -(MAX_VALUE - section.getStart()) * ANGLE_STEP; + } else { + sectionAngleExtend = Gauge.ScaleDirection.CLOCKWISE == scaleDirection ? (section.getStop() - section.getStart()) * ANGLE_STEP : -(section.getStop() - section.getStart()) * ANGLE_STEP; + } + CTX.save(); + CTX.setStroke(section.getColor()); + switch(skinType) { + case HORIZONTAL: CTX.strokeArc(xy + horVerOffset, xy, wh, wh, offset - sectionStartAngle, -sectionAngleExtend, ArcType.OPEN); break; + case VERTICAL : CTX.strokeArc(xy, xy + horVerOffset, wh, wh, offset - sectionStartAngle, -sectionAngleExtend, ArcType.OPEN); break; + default : CTX.strokeArc(xy, xy, wh, wh, offset - sectionStartAngle, -sectionAngleExtend, ArcType.OPEN); break; + } + CTX.restore(); + } + }*/ + } + + // Main loop + BigDecimal tmpStepBD = new BigDecimal(tmpAngleStep); + tmpStepBD = tmpStepBD.setScale(3, BigDecimal.ROUND_HALF_UP); + double tmpStep = tmpStepBD.doubleValue(); + double angle = 0; + int customTickLabelCounter = 0; + for (double i = 0; Double.compare(-ANGLE_RANGE - tmpStep, i) <= 0 ; i -= tmpStep) { + sinValue = Math.sin(Math.toRadians(angle + START_ANGLE)); + cosValue = Math.cos(Math.toRadians(angle + START_ANGLE)); + + switch(tickLabelLocation) { + case OUTSIDE: + innerPointX = centerX + SIZE * 0.3585 * sinValue; + innerPointY = centerY + SIZE * 0.3585 * cosValue; + innerMediumPointX = innerPointX; + innerMediumPointY = innerPointY; + innerMinorPointX = innerPointX; + innerMinorPointY = innerPointY; + outerPointX = centerX + SIZE * (0.3585 + MAX_TICK_MARK_LENGTH * majorTickMarkLengthFactor) * sinValue; + outerPointY = centerY + SIZE * (0.3585 + MAX_TICK_MARK_LENGTH * majorTickMarkLengthFactor) * cosValue; + outerMediumPointX = centerX + SIZE * (0.3585 + MAX_TICK_MARK_LENGTH * mediumTickMarkLengthFactor) * sinValue; + outerMediumPointY = centerY + SIZE * (0.3585 + MAX_TICK_MARK_LENGTH * mediumTickMarkLengthFactor) * cosValue; + outerMinorPointX = centerX + SIZE * (0.3585 + MAX_TICK_MARK_LENGTH * minorTickMarkLengthFactor) * sinValue; + outerMinorPointY = centerY + SIZE * (0.3585 + MAX_TICK_MARK_LENGTH * minorTickMarkLengthFactor) * cosValue; + textPointX = centerX + SIZE * orthTextFactor * sinValue; + textPointY = centerY + SIZE * orthTextFactor * cosValue; + dotCenterX = centerX + SIZE * 0.3685 * sinValue; + dotCenterY = centerY + SIZE * 0.3685 * cosValue; + dotMediumCenterX = centerX + SIZE * 0.365375 * sinValue; + dotMediumCenterY = centerY + SIZE * 0.365375 * cosValue; + dotMinorCenterX = centerX + SIZE * 0.36225 * sinValue; + dotMinorCenterY = centerY + SIZE * 0.36225 * cosValue; + tickLabelTickMarkX = centerX + SIZE * 0.3805 * sinValue; + tickLabelTickMarkY = centerY + SIZE * 0.3805 * cosValue; + + trapezoidMajorInnerAngle1 = Math.toRadians(angle - 1.2 + START_ANGLE); + trapezoidMajorInnerAngle2 = Math.toRadians(angle + 1.2 + START_ANGLE); + trapezoidMajorOuterAngle1 = Math.toRadians(angle - 0.8 + START_ANGLE); + trapezoidMajorOuterAngle2 = Math.toRadians(angle + 0.8 + START_ANGLE); + trapezoidMajorInnerPoint1X = centerX + SIZE * 0.3585 * Math.sin(trapezoidMajorInnerAngle1); + trapezoidMajorInnerPoint1Y = centerY + SIZE * 0.3585 * Math.cos(trapezoidMajorInnerAngle1); + trapezoidMajorInnerPoint2X = centerX + SIZE * 0.3585 * Math.sin(trapezoidMajorInnerAngle2); + trapezoidMajorInnerPoint2Y = centerY + SIZE * 0.3585 * Math.cos(trapezoidMajorInnerAngle2); + trapezoidMajorOuterPoint1X = centerX + SIZE * 0.4105 * Math.sin(trapezoidMajorOuterAngle1); + trapezoidMajorOuterPoint1Y = centerY + SIZE * 0.4105 * Math.cos(trapezoidMajorOuterAngle1); + trapezoidMajorOuterPoint2X = centerX + SIZE * 0.4105 * Math.sin(trapezoidMajorOuterAngle2); + trapezoidMajorOuterPoint2Y = centerY + SIZE * 0.4105 * Math.cos(trapezoidMajorOuterAngle2); + + trapezoidMediumInnerAngle1 = Math.toRadians(angle - 1.0 + START_ANGLE); + trapezoidMediumInnerAngle2 = Math.toRadians(angle + 1.0 + START_ANGLE); + trapezoidMediumOuterAngle1 = Math.toRadians(angle - 0.7 + START_ANGLE); + trapezoidMediumOuterAngle2 = Math.toRadians(angle + 0.7 + START_ANGLE); + trapezoidMediumInnerPoint1X = centerX + SIZE * 0.3585 * Math.sin(trapezoidMediumInnerAngle1); + trapezoidMediumInnerPoint1Y = centerY + SIZE * 0.3585 * Math.cos(trapezoidMediumInnerAngle1); + trapezoidMediumInnerPoint2X = centerX + SIZE * 0.3585 * Math.sin(trapezoidMediumInnerAngle2); + trapezoidMediumInnerPoint2Y = centerY + SIZE * 0.3585 * Math.cos(trapezoidMediumInnerAngle2); + trapezoidMediumOuterPoint1X = centerX + SIZE * 0.3985 * Math.sin(trapezoidMajorOuterAngle1); + trapezoidMediumOuterPoint1Y = centerY + SIZE * 0.3985 * Math.cos(trapezoidMediumOuterAngle1); + trapezoidMediumOuterPoint2X = centerX + SIZE * 0.3985 * Math.sin(trapezoidMediumOuterAngle2); + trapezoidMediumOuterPoint2Y = centerY + SIZE * 0.3985 * Math.cos(trapezoidMediumOuterAngle2); + + trapezoidMinorInnerAngle1 = Math.toRadians(angle - 0.8 + START_ANGLE); + trapezoidMinorInnerAngle2 = Math.toRadians(angle + 0.8 + START_ANGLE); + trapezoidMinorOuterAngle1 = Math.toRadians(angle - 0.6 + START_ANGLE); + trapezoidMinorOuterAngle2 = Math.toRadians(angle + 0.6 + START_ANGLE); + trapezoidMinorInnerPoint1X = centerX + SIZE * 0.3585 * Math.sin(trapezoidMinorInnerAngle1); + trapezoidMinorInnerPoint1Y = centerY + SIZE * 0.3585 * Math.cos(trapezoidMinorInnerAngle1); + trapezoidMinorInnerPoint2X = centerX + SIZE * 0.3585 * Math.sin(trapezoidMinorInnerAngle2); + trapezoidMinorInnerPoint2Y = centerY + SIZE * 0.3585 * Math.cos(trapezoidMinorInnerAngle2); + trapezoidMinorOuterPoint1X = centerX + SIZE * 0.3975 * Math.sin(trapezoidMinorOuterAngle1); + trapezoidMinorOuterPoint1Y = centerY + SIZE * 0.3975 * Math.cos(trapezoidMinorOuterAngle1); + trapezoidMinorOuterPoint2X = centerX + SIZE * 0.3975 * Math.sin(trapezoidMinorOuterAngle2); + trapezoidMinorOuterPoint2Y = centerY + SIZE * 0.3975 * Math.cos(trapezoidMinorOuterAngle2); + + triangleMajorInnerPointX = centerX + SIZE * 0.3585 * sinValue; + triangleMajorInnerPointY = centerY + SIZE * 0.3585 * cosValue; + triangleMajorOuterPointX = centerX + SIZE * 0.4105 * sinValue; + triangleMajorOuterPointY = centerY + SIZE * 0.4105 * cosValue; + + triangleMediumInnerPointX = triangleMajorInnerPointX; + triangleMediumInnerPointY = triangleMajorInnerPointY; + triangleMediumOuterPointX = centerX + SIZE * 0.4045 * sinValue; + triangleMediumOuterPointY = centerY + SIZE * 0.4045 * cosValue; + + triangleMinorInnerPointX = triangleMajorInnerPointX; + triangleMinorInnerPointY = triangleMajorInnerPointY; + triangleMinorOuterPointX = centerX + SIZE * 0.3975 * sinValue; + triangleMinorOuterPointY = centerY + SIZE * 0.3975 * cosValue; + break; + case INSIDE: + default: + innerPointX = centerX + SIZE * (0.475 - MAX_TICK_MARK_LENGTH * majorTickMarkLengthFactor) * sinValue; + innerPointY = centerY + SIZE * (0.475 - MAX_TICK_MARK_LENGTH * majorTickMarkLengthFactor) * cosValue; + innerMediumPointX = centerX + SIZE * (0.475 - MAX_TICK_MARK_LENGTH * mediumTickMarkLengthFactor) * sinValue; + innerMediumPointY = centerY + SIZE * (0.475 - MAX_TICK_MARK_LENGTH * mediumTickMarkLengthFactor) * cosValue; + innerMinorPointX = centerX + SIZE * (0.475 - MAX_TICK_MARK_LENGTH * minorTickMarkLengthFactor) * sinValue; + innerMinorPointY = centerY + SIZE * (0.475 - MAX_TICK_MARK_LENGTH * minorTickMarkLengthFactor) * cosValue; + outerPointX = centerX + SIZE * 0.475 * sinValue; + outerPointY = centerY + SIZE * 0.475 * cosValue; + outerMediumPointX = outerPointX; + outerMediumPointY = outerPointY; + outerMinorPointX = outerPointX; + outerMinorPointY = outerPointY; + textPointX = centerX + SIZE * orthTextFactor * sinValue; + textPointY = centerY + SIZE * orthTextFactor * cosValue; + dotCenterX = centerX + SIZE * 0.4625 * sinValue; + dotCenterY = centerY + SIZE * 0.4625 * cosValue; + dotMediumCenterX = centerX + SIZE * 0.465625 * sinValue; + dotMediumCenterY = centerY + SIZE * 0.465625 * cosValue; + dotMinorCenterX = centerX + SIZE * 0.46875 * sinValue; + dotMinorCenterY = centerY + SIZE * 0.46875 * cosValue; + tickLabelTickMarkX = centerX + SIZE * 0.445 * sinValue; + tickLabelTickMarkY = centerY + SIZE * 0.445 * cosValue; + + trapezoidMajorInnerAngle1 = Math.toRadians(angle - 0.8 + START_ANGLE); + trapezoidMajorInnerAngle2 = Math.toRadians(angle + 0.8 + START_ANGLE); + trapezoidMajorOuterAngle1 = Math.toRadians(angle - 1.2 + START_ANGLE); + trapezoidMajorOuterAngle2 = Math.toRadians(angle + 1.2 + START_ANGLE); + trapezoidMajorInnerPoint1X = centerX + SIZE * 0.423 * Math.sin(trapezoidMajorInnerAngle1); + trapezoidMajorInnerPoint1Y = centerY + SIZE * 0.423 * Math.cos(trapezoidMajorInnerAngle1); + trapezoidMajorInnerPoint2X = centerX + SIZE * 0.423 * Math.sin(trapezoidMajorInnerAngle2); + trapezoidMajorInnerPoint2Y = centerY + SIZE * 0.423 * Math.cos(trapezoidMajorInnerAngle2); + trapezoidMajorOuterPoint1X = centerX + SIZE * 0.475 * Math.sin(trapezoidMajorOuterAngle1); + trapezoidMajorOuterPoint1Y = centerY + SIZE * 0.475 * Math.cos(trapezoidMajorOuterAngle1); + trapezoidMajorOuterPoint2X = centerX + SIZE * 0.475 * Math.sin(trapezoidMajorOuterAngle2); + trapezoidMajorOuterPoint2Y = centerY + SIZE * 0.475 * Math.cos(trapezoidMajorOuterAngle2); + + trapezoidMediumInnerAngle1 = Math.toRadians(angle - 0.7 + START_ANGLE); + trapezoidMediumInnerAngle2 = Math.toRadians(angle + 0.7 + START_ANGLE); + trapezoidMediumOuterAngle1 = Math.toRadians(angle - 1.0 + START_ANGLE); + trapezoidMediumOuterAngle2 = Math.toRadians(angle + 1.0 + START_ANGLE); + trapezoidMediumInnerPoint1X = centerX + SIZE * 0.435 * Math.sin(trapezoidMediumInnerAngle1); + trapezoidMediumInnerPoint1Y = centerY + SIZE * 0.435 * Math.cos(trapezoidMediumInnerAngle1); + trapezoidMediumInnerPoint2X = centerX + SIZE * 0.435 * Math.sin(trapezoidMediumInnerAngle2); + trapezoidMediumInnerPoint2Y = centerY + SIZE * 0.435 * Math.cos(trapezoidMediumInnerAngle2); + trapezoidMediumOuterPoint1X = centerX + SIZE * 0.475 * Math.sin(trapezoidMajorOuterAngle1); + trapezoidMediumOuterPoint1Y = centerY + SIZE * 0.475 * Math.cos(trapezoidMediumOuterAngle1); + trapezoidMediumOuterPoint2X = centerX + SIZE * 0.475 * Math.sin(trapezoidMediumOuterAngle2); + trapezoidMediumOuterPoint2Y = centerY + SIZE * 0.475 * Math.cos(trapezoidMediumOuterAngle2); + + trapezoidMinorInnerAngle1 = Math.toRadians(angle - 0.6 + START_ANGLE); + trapezoidMinorInnerAngle2 = Math.toRadians(angle + 0.6 + START_ANGLE); + trapezoidMinorOuterAngle1 = Math.toRadians(angle - 0.8 + START_ANGLE); + trapezoidMinorOuterAngle2 = Math.toRadians(angle + 0.8 + START_ANGLE); + trapezoidMinorInnerPoint1X = centerX + SIZE * 0.440 * Math.sin(trapezoidMinorInnerAngle1); + trapezoidMinorInnerPoint1Y = centerY + SIZE * 0.440 * Math.cos(trapezoidMinorInnerAngle1); + trapezoidMinorInnerPoint2X = centerX + SIZE * 0.440 * Math.sin(trapezoidMinorInnerAngle2); + trapezoidMinorInnerPoint2Y = centerY + SIZE * 0.440 * Math.cos(trapezoidMinorInnerAngle2); + trapezoidMinorOuterPoint1X = centerX + SIZE * 0.475 * Math.sin(trapezoidMinorOuterAngle1); + trapezoidMinorOuterPoint1Y = centerY + SIZE * 0.475 * Math.cos(trapezoidMinorOuterAngle1); + trapezoidMinorOuterPoint2X = centerX + SIZE * 0.475 * Math.sin(trapezoidMinorOuterAngle2); + trapezoidMinorOuterPoint2Y = centerY + SIZE * 0.475 * Math.cos(trapezoidMinorOuterAngle2); + + triangleMajorInnerPointX = centerX + SIZE * 0.423 * sinValue; + triangleMajorInnerPointY = centerY + SIZE * 0.423 * cosValue; + triangleMajorOuterPointX = centerX + SIZE * 0.475 * sinValue; + triangleMajorOuterPointY = centerY + SIZE * 0.475 * cosValue; + + triangleMediumInnerPointX = centerX + SIZE * 0.43 * sinValue; + triangleMediumInnerPointY = centerY + SIZE * 0.43 * cosValue; + triangleMediumOuterPointX = triangleMajorOuterPointX; + triangleMediumOuterPointY = triangleMajorOuterPointY; + + triangleMinorInnerPointX = centerX + SIZE * 0.436 * sinValue; + triangleMinorInnerPointY = centerY + SIZE * 0.436 * cosValue; + triangleMinorOuterPointX = triangleMajorOuterPointX; + triangleMinorOuterPointY = triangleMajorOuterPointY; + break; + } + + // Set the general tickmark color + CTX.setStroke(tickMarkColor); + CTX.setFill(tickMarkColor); + CTX.setLineCap(StrokeLineCap.BUTT); + + if (Double.compare(counterBD.remainder(majorTickSpaceBD).doubleValue(), 0.0) == 0) { + // Draw major tick mark + isNotZero = Double.compare(0.0, counter) != 0; + TickMarkType tickMarkType = null; + if (majorTickMarksVisible) { + tickMarkType = majorTickMarkType; + CTX.setFill(tickMarkSectionsVisible ? /*Helper.getColorOfSection(tickMarkSections, counter,*/ majorTickMarkColor/*)*/ : majorTickMarkColor); + CTX.setStroke(tickMarkSectionsVisible ? /*Helper.getColorOfSection(tickMarkSections, counter,*/ majorTickMarkColor/*)*/ : majorTickMarkColor); + CTX.setLineWidth(SIZE * (TickMarkType.BOX == tickMarkType || TickMarkType.PILL == tickMarkType ? 0.016 : MAX_TICK_MARK_WIDTH * majorTickMarkWidthFactor)); + CTX.setLineCap(TickMarkType.PILL == tickMarkType ? StrokeLineCap.ROUND : StrokeLineCap.BUTT); + } else if (minorTickMarksVisible) { + tickMarkType = minorTickMarkType; + CTX.setFill(tickMarkSectionsVisible ? /*Helper.getColorOfSection(tickMarkSections, counter, */minorTickMarkColor/*)*/ : minorTickMarkColor); + CTX.setStroke(tickMarkSectionsVisible ? /*Helper.getColorOfSection(tickMarkSections, counter,*/ minorTickMarkColor/*)*/ : minorTickMarkColor); + CTX.setLineWidth(SIZE * (TickMarkType.BOX == tickMarkType || TickMarkType.PILL == tickMarkType ? 0.007 : MAX_TICK_MARK_WIDTH * minorTickMarkWidthFactor)); + CTX.setLineCap(TickMarkType.PILL == tickMarkType ? StrokeLineCap.ROUND : StrokeLineCap.BUTT); + } + if (fullRange && !isNotZero) { + CTX.setFill(zeroColor); + CTX.setStroke(zeroColor); + } + if (null != tickMarkType) { + switch (tickMarkType) { + case TRAPEZOID: + if (majorTickMarksVisible) { + Helper.drawTrapezoid(CTX, trapezoidMajorInnerPoint1X, trapezoidMajorInnerPoint1Y, trapezoidMajorInnerPoint2X, trapezoidMajorInnerPoint2Y, + trapezoidMajorOuterPoint1X, trapezoidMajorOuterPoint1Y, trapezoidMajorOuterPoint2X, trapezoidMajorOuterPoint2Y); + } else if (minorTickMarksVisible) { + Helper.drawTrapezoid(CTX, trapezoidMinorInnerPoint1X, trapezoidMinorInnerPoint1Y, trapezoidMinorInnerPoint2X, trapezoidMinorInnerPoint2Y, + trapezoidMinorOuterPoint1X, trapezoidMinorOuterPoint1Y, trapezoidMinorOuterPoint2X, trapezoidMinorOuterPoint2Y); + } + break; + case TRIANGLE: + if (majorTickMarksVisible) { + if (TickLabelLocation.INSIDE == tickLabelLocation) { + Helper.drawTriangle(CTX, triangleMajorInnerPointX, triangleMajorInnerPointY, trapezoidMajorOuterPoint1X, trapezoidMajorOuterPoint1Y, trapezoidMajorOuterPoint2X, trapezoidMajorOuterPoint2Y); + } else { + Helper.drawTriangle(CTX, triangleMajorOuterPointX, triangleMajorOuterPointY, trapezoidMajorInnerPoint1X, trapezoidMajorInnerPoint1Y, trapezoidMajorInnerPoint2X, trapezoidMajorInnerPoint2Y); + } + } else if (minorTickMarksVisible) { + if (TickLabelLocation.INSIDE == tickLabelLocation) { + Helper.drawTriangle(CTX, triangleMinorInnerPointX, triangleMinorInnerPointY, trapezoidMinorOuterPoint1X, trapezoidMinorOuterPoint1Y, trapezoidMinorOuterPoint2X, trapezoidMinorOuterPoint2Y); + } else { + Helper.drawTriangle(CTX, triangleMinorOuterPointX, triangleMinorOuterPointY, trapezoidMinorInnerPoint1X, trapezoidMinorInnerPoint1Y, trapezoidMinorInnerPoint2X, trapezoidMinorInnerPoint2Y); + } + } + break; + case DOT: + if (majorTickMarksVisible) { + Helper.drawDot(CTX, dotCenterX - majorHalfDotSize, dotCenterY - majorHalfDotSize, majorDotSize); + } else if (minorTickMarksVisible) { + Helper.drawDot(CTX, dotMinorCenterX - minorHalfDotSize, dotMinorCenterY - minorHalfDotSize, minorDotSize); + } + break; + case TICK_LABEL: + if (majorTickMarksVisible) { + CTX.save(); + CTX.translate(tickLabelTickMarkX, tickLabelTickMarkY); + + Helper.rotateContextForText(CTX, START_ANGLE, angle, tickLabelOrientation); + + CTX.setFont(isNotZero ? tickMarkFont : tickMarkZeroFont); + CTX.setTextAlign(TextAlignment.CENTER); + CTX.setTextBaseline(VPos.CENTER); + CTX.fillText(formatNumber(locale, tickLabelFormatString, 0, counter) /*String.format(locale, tickLabelFormatString, counter)*/, 0, 0); + CTX.restore(); + } + break; + case LINE: + default: + if (majorTickMarksVisible) { + Helper.drawLine(CTX, innerPointX, innerPointY, outerPointX, outerPointY); + } else if (minorTickMarksVisible) { + if (TickLabelLocation.OUTSIDE == tickLabelLocation) { + Helper.drawLine(CTX, innerPointX, innerPointY, outerMinorPointX, outerMinorPointY); + } else { + Helper.drawLine(CTX, innerMinorPointX, innerMinorPointY, outerPointX, outerPointY); + } + } + break; + } + } + + // Draw tick label text + if (tickLabelsVisible) { + CTX.save(); + CTX.translate(textPointX, textPointY); + + Helper.rotateContextForText(CTX, START_ANGLE, angle, tickLabelOrientation); + CTX.setFont(isNotZero ? tickLabelFont : tickLabelZeroFont); + CTX.setTextAlign(TextAlignment.CENTER); + CTX.setTextBaseline(VPos.CENTER); + + if (!onlyFirstAndLastLabelVisible) { + if (isNotZero) { + CTX.setFill(tickLabelSectionsVisible ? /*Helper.getColorOfSection(tickLabelSections, counter,*/ tickLabelColor/*)*/ : tickLabelColor); + } else { + CTX.setFill(tickLabelSectionsVisible ? /*Helper.getColorOfSection(tickLabelSections, counter,*/ tickLabelColor/*)*/ : fullRange ? zeroColor : tickLabelColor); + } + } else { + if ((Double.compare(counter, MIN_VALUE) == 0 || Double.compare(counter, MAX_VALUE) == 0)) { + if (isNotZero) { + CTX.setFill(tickLabelSectionsVisible ? /*Helper.getColorOfSection(tickLabelSections, counter,*/ tickLabelColor/*)*/ : tickLabelColor); + } else { + CTX.setFill(tickLabelSectionsVisible ? /*Helper.getColorOfSection(tickLabelSections, counter,*/ tickLabelColor/*)*/ : fullRange ? zeroColor : tickLabelColor); + } + } else { + CTX.setFill(Color.TRANSPARENT); + } + } + + if (customTickLabelsEnabled) { + if (customTickLabelCounter >= 0) { + CTX.fillText(customTickLabels.get(customTickLabelCounter), 0, 0); + customTickLabelCounter++; + } + if (customTickLabelCounter > customTickLabels.size() - 1) customTickLabelCounter = -1; + } else { + CTX.fillText(formatNumber(locale, tickLabelFormatString, 0, counter)/*String.format(locale, tickLabelFormatString, counter)*/, 0, 0); + } + CTX.restore(); + } + } else if (mediumTickMarksVisible && + Double.compare(minorTickSpaceBD.remainder(mediumCheck2).doubleValue(), 0.0) != 0.0 && + Double.compare(counterBD.remainder(mediumCheck5).doubleValue(), 0.0) == 0.0) { + // Draw medium tick mark + CTX.setFill(tickMarkSectionsVisible ? /*Helper.getColorOfSection(tickMarkSections, counter, */mediumTickMarkColor/*)*/ : mediumTickMarkColor); + CTX.setStroke(tickMarkSectionsVisible ? /*Helper.getColorOfSection(tickMarkSections, counter, */mediumTickMarkColor/*)*/ : mediumTickMarkColor); + switch(mediumTickMarkType) { + case TRAPEZOID: + Helper.drawTrapezoid(CTX, trapezoidMediumInnerPoint1X, trapezoidMediumInnerPoint1Y, trapezoidMediumInnerPoint2X, trapezoidMediumInnerPoint2Y, + trapezoidMediumOuterPoint1X, trapezoidMediumOuterPoint1Y, trapezoidMediumOuterPoint2X, trapezoidMediumOuterPoint2Y); + break; + case TRIANGLE: + if (TickLabelLocation.INSIDE == tickLabelLocation) { + Helper.drawTriangle(CTX, triangleMediumInnerPointX, triangleMediumInnerPointY, trapezoidMediumOuterPoint1X, trapezoidMediumOuterPoint1Y, trapezoidMediumOuterPoint2X, trapezoidMediumOuterPoint2Y); + } else { + Helper.drawTriangle(CTX, triangleMediumOuterPointX, triangleMediumOuterPointY, trapezoidMediumInnerPoint1X, trapezoidMediumInnerPoint1Y, trapezoidMediumInnerPoint2X, trapezoidMediumInnerPoint2Y); + } + break; + case DOT: + Helper.drawDot(CTX, dotMediumCenterX - mediumHalfDotSize, dotMediumCenterY - mediumHalfDotSize, mediumDotSize); + break; + case BOX: + CTX.setLineWidth(SIZE * 0.009); + if (TickLabelLocation.OUTSIDE == tickLabelLocation) { + Helper.drawLine(CTX, innerPointX, innerPointY, outerMediumPointX, outerMediumPointY); + } else { + Helper.drawLine(CTX, innerMediumPointX, innerMediumPointY, outerPointX, outerPointY); + } + break; + case PILL: + CTX.setLineCap(StrokeLineCap.ROUND); + CTX.setLineWidth(SIZE * 0.009); + if (TickLabelLocation.OUTSIDE == tickLabelLocation) { + Helper.drawLine(CTX, innerPointX, innerPointY, outerMediumPointX, outerMediumPointY); + } else { + Helper.drawLine(CTX, innerMediumPointX, innerMediumPointY, outerPointX, outerPointY); + } + break; + case LINE: + default: + CTX.setLineWidth(SIZE * MAX_TICK_MARK_WIDTH * mediumTickMarkWidthFactor); + if (TickLabelLocation.OUTSIDE == tickLabelLocation) { + Helper.drawLine(CTX, innerPointX, innerPointY, outerMediumPointX, outerMediumPointY); + } else { + Helper.drawLine(CTX, innerMediumPointX, innerMediumPointY, outerPointX, outerPointY); + } + break; + } + } else if (minorTickMarksVisible) { + boolean drawMinorTicks = false; + if (minorTickSpaceBD.stripTrailingZeros().scale() <= 0) { + if (Double.compare(counterBD.remainder(minorTickSpaceBD).doubleValue(), 0.0) == 0) { + drawMinorTicks = true; + } + } else { + drawMinorTicks = true; + } + + // Draw minor tick mark + if (drawMinorTicks && TickMarkType.TICK_LABEL != majorTickMarkType) { + CTX.setFill(tickMarkSectionsVisible ? /*Helper.getColorOfSection(tickMarkSections, counter,*/ minorTickMarkColor/*)*/ : minorTickMarkColor); + CTX.setStroke(tickMarkSectionsVisible ? /*Helper.getColorOfSection(tickMarkSections, counter,*/ minorTickMarkColor/*)*/ : minorTickMarkColor); + switch (minorTickMarkType) { + case TRAPEZOID: + Helper.drawTrapezoid(CTX, trapezoidMinorInnerPoint1X, trapezoidMinorInnerPoint1Y, trapezoidMinorInnerPoint2X, trapezoidMinorInnerPoint2Y, + trapezoidMinorOuterPoint1X, trapezoidMinorOuterPoint1Y, trapezoidMinorOuterPoint2X, trapezoidMinorOuterPoint2Y); + break; + case TRIANGLE: + if (TickLabelLocation.INSIDE == tickLabelLocation) { + Helper.drawTriangle(CTX, triangleMinorInnerPointX, triangleMinorInnerPointY, trapezoidMinorOuterPoint1X, trapezoidMinorOuterPoint1Y, trapezoidMinorOuterPoint2X, trapezoidMinorOuterPoint2Y); + } else { + Helper.drawTriangle(CTX, triangleMinorOuterPointX, triangleMinorOuterPointY, trapezoidMinorInnerPoint1X, trapezoidMinorInnerPoint1Y, trapezoidMinorInnerPoint2X, trapezoidMinorInnerPoint2Y); + } + break; + case DOT: + Helper.drawDot(CTX, dotMinorCenterX - minorHalfDotSize, dotMinorCenterY - minorHalfDotSize, minorDotSize); + break; + case BOX: + CTX.setLineWidth(SIZE * 0.007); + if (TickLabelLocation.OUTSIDE == tickLabelLocation) { + Helper.drawLine(CTX, innerPointX, innerPointY, outerMinorPointX, outerMinorPointY); + } else { + Helper.drawLine(CTX, innerMinorPointX, innerMinorPointY, outerPointX, outerPointY); + } + break; + case PILL: + CTX.setLineCap(StrokeLineCap.ROUND); + CTX.setLineWidth(SIZE * 0.007); + if (TickLabelLocation.OUTSIDE == tickLabelLocation) { + Helper.drawLine(CTX, innerPointX, innerPointY, outerMinorPointX, outerMinorPointY); + } else { + Helper.drawLine(CTX, innerMinorPointX, innerMinorPointY, outerPointX, outerPointY); + } + break; + case LINE: + default: + CTX.setLineWidth(SIZE * MAX_TICK_MARK_WIDTH * minorTickMarkWidthFactor); + if (TickLabelLocation.OUTSIDE == tickLabelLocation) { + Helper.drawLine(CTX, innerPointX, innerPointY, outerMinorPointX, outerMinorPointY); + } else { + Helper.drawLine(CTX, innerMinorPointX, innerMinorPointY, outerPointX, outerPointY); + } + break; + } + } + } + counterBD = counterBD.add(minorTickSpaceBD); + counter = counterBD.doubleValue(); + if (counter > MAX_VALUE) break; + angle = Gauge.ScaleDirection.CLOCKWISE == scaleDirection ? (angle - tmpAngleStep) : (angle + tmpAngleStep); + } + } +/* + + public static final Image createNoiseImage(final double WIDTH, final double HEIGHT, final Color DARK_COLOR, final Color BRIGHT_COLOR, final double ALPHA_VARIATION_IN_PERCENT) { + if (Double.compare(WIDTH, 0) <= 0 || Double.compare(HEIGHT, 0) <= 0) return null; + int width = (int) WIDTH; + int height = (int) HEIGHT; + double alphaVariationInPercent = Helper.clamp(0.0, 100.0, ALPHA_VARIATION_IN_PERCENT); + final WritableImage IMAGE = new WritableImage(width, height); + final PixelWriter PIXEL_WRITER = IMAGE.getPixelWriter(); + final Random BW_RND = new Random(); + final Random ALPHA_RND = new Random(); + final double ALPHA_START = alphaVariationInPercent / 100 / 2; + final double ALPHA_VARIATION = alphaVariationInPercent / 100; + for (int y = 0 ; y < height ; y++) { + for (int x = 0 ; x < width ; x++) { + final Color NOISE_COLOR = BW_RND.nextBoolean() ? BRIGHT_COLOR : DARK_COLOR; + final double NOISE_ALPHA = Helper.clamp(0.0, 1.0, ALPHA_START + ALPHA_RND.nextDouble() * ALPHA_VARIATION); + PIXEL_WRITER.setColor(x, y, Color.color(NOISE_COLOR.getRed(), NOISE_COLOR.getGreen(), NOISE_COLOR.getBlue(), NOISE_ALPHA)); + } + } + return IMAGE; + } +*/ + +/* + public static final void drawTimeSections(final Clock CLOCK, final GraphicsContext CTX, final List SECTIONS, final double SIZE, + final double XY_INSIDE, final double XY_OUTSIDE, final double WH_INSIDE, final double WH_OUTSIDE, + final double LINE_WIDTH) { + if (SECTIONS.isEmpty()) return; + TickLabelLocation tickLabelLocation = CLOCK.getTickLabelLocation(); + ZonedDateTime time = CLOCK.getTime(); + boolean isAM = time.get(ChronoField.AMPM_OF_DAY) == 0; + double xy = TickLabelLocation.INSIDE == tickLabelLocation ? XY_INSIDE * SIZE : XY_OUTSIDE * SIZE; + double wh = TickLabelLocation.INSIDE == tickLabelLocation ? WH_INSIDE * SIZE : WH_OUTSIDE * SIZE; + double offset = 90; + int listSize = SECTIONS.size(); + double angleStep = 360.0 / 60.0; + boolean highlightSections = CLOCK.isHighlightSections(); + for (int i = 0 ; i < listSize ; i++) { + TimeSection section = SECTIONS.get(i); + LocalTime start = section.getStart(); + LocalTime stop = section.getStop(); + boolean isStartAM = start.get(ChronoField.AMPM_OF_DAY) == 0; + boolean isStopAM = stop.get(ChronoField.AMPM_OF_DAY) == 0; + boolean draw = isAM ? (isStartAM || isStopAM) :(!isStartAM || !isStopAM); + if (draw) { + double sectionStartAngle = (start.getHour() % 12 * 5.0 + start.getMinute() / 12.0 + start.getSecond() / 300.0) * angleStep + 180; + double sectionAngleExtend = ((stop.getHour() - start.getHour()) % 12 * 5.0 + (stop.getMinute() - start.getMinute()) / 12.0 + (stop.getSecond() - start.getSecond()) / 300.0) * angleStep; + //TODO: Add an indicator to the section like -1 or similar + // check if start was already yesterday + if (start.getHour() > stop.getHour()) { sectionAngleExtend = (360.0 - Math.abs(sectionAngleExtend)); } + CTX.save(); + */ +/*if (highlightSections) { + CTX.setStroke(section.contains(time.toLocalTime()) ? section.getHighlightColor() : section.getColor()); + } else*//* + { + CTX.setStroke(section.getColor()); + } + CTX.setLineWidth(SIZE * LINE_WIDTH); + CTX.setLineCap(StrokeLineCap.BUTT); + CTX.strokeArc(xy, xy, wh, wh, -(offset + sectionStartAngle), -sectionAngleExtend, ArcType.OPEN); + CTX.restore(); + } + } + } + + public static final void drawTimeAreas(final Clock CLOCK, final GraphicsContext CTX, final List AREAS, final double SIZE, + final double XY_INSIDE, final double XY_OUTSIDE, final double WH_INSIDE, final double WH_OUTSIDE) { + if (AREAS.isEmpty()) return; + TickLabelLocation tickLabelLocation = CLOCK.getTickLabelLocation(); + ZonedDateTime time = CLOCK.getTime(); + boolean isAM = time.get(ChronoField.AMPM_OF_DAY) == 0; + double xy = TickLabelLocation.OUTSIDE == tickLabelLocation ? XY_OUTSIDE * SIZE : XY_INSIDE * SIZE; + double wh = TickLabelLocation.OUTSIDE == tickLabelLocation ? WH_OUTSIDE * SIZE : WH_INSIDE * SIZE; + double offset = 90; + double angleStep = 360.0 / 60.0; + int listSize = AREAS.size(); + boolean highlightAreas = CLOCK.isHighlightAreas(); + for (int i = 0; i < listSize ; i++) { + TimeSection area = AREAS.get(i); + LocalTime start = area.getStart(); + LocalTime stop = area.getStop(); + boolean isStartAM = start.get(ChronoField.AMPM_OF_DAY) == 0; + boolean isStopAM = stop.get(ChronoField.AMPM_OF_DAY) == 0; + boolean draw = isAM ? (isStartAM || isStopAM) :(!isStartAM || !isStopAM); + if (draw) { + double areaStartAngle = (start.getHour() % 12 * 5.0 + start.getMinute() / 12.0 + start.getSecond() / 300.0) * angleStep + 180;; + double areaAngleExtend = ((stop.getHour() - start.getHour()) % 12 * 5.0 + (stop.getMinute() - start.getMinute()) / 12.0 + (stop.getSecond() - start.getSecond()) / 300.0) * angleStep; + //TODO: Add an indicator to the area like -1 or similar + // check if start was already yesterday + if (start.getHour() > stop.getHour()) { areaAngleExtend = (360.0 - Math.abs(areaAngleExtend)); } + CTX.save(); + */ +/*if (highlightAreas) { + CTX.setFill(area.contains(time.toLocalTime()) ? area.getHighlightColor() : area.getColor()); + } else*//* + { + CTX.setFill(area.getColor()); + } + CTX.fillArc(xy, xy, wh, wh, -(offset + areaStartAngle), -areaAngleExtend, ArcType.ROUND); + CTX.restore(); + } + } + } + + public static final void drawAlarms(final Clock CLOCK, final double SIZE, final double ALARM_MARKER_SIZE, final double ALARM_MARKER_RADIUS, final Map ALARM_MAP, final DateTimeFormatter DATE_TIME_FORMATTER, final ZonedDateTime TIME) { + if (CLOCK.isAlarmsVisible()) { + double alarmSize = ALARM_MARKER_SIZE * SIZE; + double center = SIZE * 0.5; + double angleStep = 360.0 / 60.0; + for (Map.Entry entry : ALARM_MAP.entrySet()) { + Alarm alarm = entry.getKey(); + ZonedDateTime alarmTime = alarm.getTime(); + double alarmAngle = (alarmTime.getMinute() + alarmTime.getSecond() / 60.0) * angleStep + 180; + double sinValue = Math.sin(Math.toRadians((-alarmAngle))); + double cosValue = Math.cos(Math.toRadians((-alarmAngle))); + Color alarmColor = alarm.isArmed() ? alarm.getColor() : INACTIVE_ALARM_COLOR; + Circle dot = entry.getValue(); + dot.setRadius(alarmSize); + dot.setCenterX(center + SIZE * ALARM_MARKER_RADIUS * sinValue); + dot.setCenterY(center + SIZE * ALARM_MARKER_RADIUS * cosValue); + dot.setFill(alarmColor); + dot.setStroke(alarmColor.darker()); + //dot.setPickOnBounds(false); + //dot.setOnMousePressed(e -> alarm.fireAlarmMarkerEvent(alarm.ALARM_MARKER_PRESSED_EVENT)); + //dot.setOnMouseReleased(e -> alarm.fireAlarmMarkerEvent(alarm.ALARM_MARKER_RELEASED_EVENT)); + if (alarmTime.getDayOfMonth() == TIME.getDayOfMonth() && + alarmTime.getMonthValue() == TIME.getMonthValue() && + alarmTime.getYear() == TIME.getYear() && + alarmTime.getHour() == TIME.getHour() && + alarmTime.getMinute() >= TIME.getMinute()) { + dot.setManaged(true); + dot.setVisible(true); + } else { + dot.setManaged(false); + dot.setVisible(false); + } + */ +/*Tooltip alarmTooltip; + if (alarm.getText().isEmpty()) { + alarmTooltip = new Tooltip(DATE_TIME_FORMATTER.format(alarm.getTime())); + } else { + alarmTooltip = new Tooltip(new StringBuilder(alarm.getText()).append("\n").append(DATE_TIME_FORMATTER.format(alarm.getTime())).toString()); + } + alarmTooltip.setTextAlignment(TextAlignment.CENTER); + Tooltip.install(dot, alarmTooltip);*//* + + } + } + } +*/ + + public static final String formatNumber(final Gauge GAUGE, final double VALUE) { + return formatNumber(GAUGE.getLocale(), null/*GAUGE.getFormatString()*/, GAUGE.getDecimals(), VALUE); + } + + public static final String formatNumber(final Locale LOCALE, final String FORMAT_STRING, final int DECIMALS, final double VALUE) { + double value = VALUE; + if (value > 0) { + value = Math.floor(value * Math.pow(10, DECIMALS)) / Math.pow(10, DECIMALS); + } else if (value < 0) { + value = Math.ceil(value * Math.pow(10, DECIMALS)) / Math.pow(10, DECIMALS); + } + //return String.format(LOCALE, FORMAT_STRING, value); + return Integer.toString((int) value); + } + + public static final String formatNumber(final Locale LOCALE, final double MIN_VALUE, final double MAX_VALUE, final int DECIMALS, final double VALUE) { + //StringBuilder sb = new StringBuilder("%.").append(DECIMALS).append("f"); + //String f = sb.toString(); + //int minLength = String.format(Locale.US, f, MIN_VALUE).length(); + //int maxLength = String.format(Locale.US, f, MAX_VALUE).length(); + //int length = Math.max(minLength, maxLength); + + //StringBuilder formatStringBuilder = new StringBuilder("%").append(length).append(".").append(DECIMALS).append("f"); + //String formatString = formatStringBuilder.toString(); + + double value = VALUE; + if (value > 0) { + value = Math.floor(VALUE * Math.pow(10, DECIMALS)) / Math.pow(10, DECIMALS); + } else if (value < 0) { + value = Math.ceil(VALUE * Math.pow(10, DECIMALS)) / Math.pow(10, DECIMALS); + } + + //return String.format(LOCALE, formatString, value); + return Integer.toString((int) value); + } +} diff --git a/webfx-demo-moderngauge-application/src/main/java/module-info.java b/webfx-demo-moderngauge-application/src/main/java/module-info.java new file mode 100644 index 0000000..bb0ca32 --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/module-info.java @@ -0,0 +1,23 @@ +// Generated by WebFx + +module webfx.demo.moderngauge.application { + + // Direct dependencies modules + requires java.base; + requires javafx.base; + requires javafx.controls; + requires javafx.graphics; + requires webfx.platform.shared.scheduler; + requires webfx.platform.shared.util; + + // Exported packages + exports eu.hansolo.medusa; + exports eu.hansolo.medusa.events; + exports eu.hansolo.medusa.skins; + exports eu.hansolo.medusa.tools; + exports webfx.demo.moderngauge; + + // Provided services + provides javafx.application.Application with webfx.demo.moderngauge.ModernGaugeApplication; + +} \ No newline at end of file diff --git a/webfx-demo-moderngauge-application/src/main/java/webfx/demo/moderngauge/ModernGaugeApplication.java b/webfx-demo-moderngauge-application/src/main/java/webfx/demo/moderngauge/ModernGaugeApplication.java new file mode 100644 index 0000000..4a395ce --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/java/webfx/demo/moderngauge/ModernGaugeApplication.java @@ -0,0 +1,42 @@ +package webfx.demo.moderngauge; + +import eu.hansolo.medusa.Gauge; +import eu.hansolo.medusa.GaugeBuilder; +import javafx.application.Application; +import javafx.geometry.Insets; +import javafx.scene.Scene; +import javafx.scene.layout.Background; +import javafx.scene.layout.BackgroundFill; +import javafx.scene.layout.CornerRadii; +import javafx.scene.layout.StackPane; +import javafx.scene.paint.Color; +import javafx.stage.Stage; +import webfx.platform.shared.services.scheduler.Scheduler; + +/** + * @author Bruno Salmon + */ +public final class ModernGaugeApplication extends Application { + + @Override + public void start(Stage stage) { + Gauge gauge = GaugeBuilder.create() + .skinType(Gauge.SkinType.MODERN) + .prefSize(400, 400) + .sectionTextVisible(true) + .title("MODERN") + .unit("UNIT") + .threshold(85) + .thresholdVisible(true) + .animated(true) + .build(); + StackPane root = new StackPane(gauge); + root.setBackground(new Background(new BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY))); + Scene scene = new Scene(root,800, 600); + stage.setScene(scene); + stage.setTitle("Modern Gauge"); + stage.show(); + Scheduler.schedulePeriodic(1500, () -> gauge.setValue(Math.random() * gauge.getRange() + gauge.getMinValue())); + } + +} diff --git a/webfx-demo-moderngauge-application/src/main/resources/META-INF/services/javafx.application.Application b/webfx-demo-moderngauge-application/src/main/resources/META-INF/services/javafx.application.Application new file mode 100644 index 0000000..86160b4 --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/resources/META-INF/services/javafx.application.Application @@ -0,0 +1 @@ +webfx.demo.moderngauge.ModernGaugeApplication diff --git a/webfx-demo-moderngauge-application/src/main/resources/META-INF/webfx.xml b/webfx-demo-moderngauge-application/src/main/resources/META-INF/webfx.xml new file mode 100644 index 0000000..09e7cb1 --- /dev/null +++ b/webfx-demo-moderngauge-application/src/main/resources/META-INF/webfx.xml @@ -0,0 +1,7 @@ + + + + webfx.demo.moderngauge.ModernGaugeApplication + + + \ No newline at end of file