commit 5b8021007c74d766de8b611fb97b76a9f6609db0 Author: liwen Date: Wed Oct 28 16:36:50 2020 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e66c587 --- /dev/null +++ b/.gitignore @@ -0,0 +1,65 @@ +# Compiled source # +################### +*.com +*.class +*.dll +*.exe +*.o +*.so + +# Packages # +############ +# it's better to unpack these files and commit the raw source +# git has its own built in compression methods +*.7z +*.dmg +*.gz +*.iso +*.rar +*.tar +*.zip + +# Logs and databases # +###################### +*.log + +# OS generated files # +###################### +.DS_Store* +ehthumbs.db +Thumbs.db + +# Editor Files # +################ +*~ +*.swp + +# Build output directies +/target +**/test-output +**/target +**/bin +build +*/build +.m2 + +# IntelliJ specific files/directories +out +.idea +*.ipr +*.iws +*.iml +atlassian-ide-plugin.xml + +# Eclipse specific files/directories +.classpath +.project +.settings +.metadata +.factorypath +.generated + +#font +*.ttc + + diff --git a/.gradle/6.4.1/executionHistory/executionHistory.bin b/.gradle/6.4.1/executionHistory/executionHistory.bin new file mode 100644 index 0000000..0740d30 Binary files /dev/null and b/.gradle/6.4.1/executionHistory/executionHistory.bin differ diff --git a/.gradle/6.4.1/executionHistory/executionHistory.lock b/.gradle/6.4.1/executionHistory/executionHistory.lock new file mode 100644 index 0000000..e2ee71f Binary files /dev/null and b/.gradle/6.4.1/executionHistory/executionHistory.lock differ diff --git a/.gradle/6.4.1/fileChanges/last-build.bin b/.gradle/6.4.1/fileChanges/last-build.bin new file mode 100644 index 0000000..f76dd23 Binary files /dev/null and b/.gradle/6.4.1/fileChanges/last-build.bin differ diff --git a/.gradle/6.4.1/fileContent/fileContent.lock b/.gradle/6.4.1/fileContent/fileContent.lock new file mode 100644 index 0000000..c05ed79 Binary files /dev/null and b/.gradle/6.4.1/fileContent/fileContent.lock differ diff --git a/.gradle/6.4.1/fileHashes/fileHashes.bin b/.gradle/6.4.1/fileHashes/fileHashes.bin new file mode 100644 index 0000000..62f5832 Binary files /dev/null and b/.gradle/6.4.1/fileHashes/fileHashes.bin differ diff --git a/.gradle/6.4.1/fileHashes/fileHashes.lock b/.gradle/6.4.1/fileHashes/fileHashes.lock new file mode 100644 index 0000000..2275e6d Binary files /dev/null and b/.gradle/6.4.1/fileHashes/fileHashes.lock differ diff --git a/.gradle/6.4.1/fileHashes/resourceHashesCache.bin b/.gradle/6.4.1/fileHashes/resourceHashesCache.bin new file mode 100644 index 0000000..80ff8d4 Binary files /dev/null and b/.gradle/6.4.1/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/6.4.1/gc.properties b/.gradle/6.4.1/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.gradle/6.4.1/javaCompile/classAnalysis.bin b/.gradle/6.4.1/javaCompile/classAnalysis.bin new file mode 100644 index 0000000..875133e Binary files /dev/null and b/.gradle/6.4.1/javaCompile/classAnalysis.bin differ diff --git a/.gradle/6.4.1/javaCompile/jarAnalysis.bin b/.gradle/6.4.1/javaCompile/jarAnalysis.bin new file mode 100644 index 0000000..c7e934c Binary files /dev/null and b/.gradle/6.4.1/javaCompile/jarAnalysis.bin differ diff --git a/.gradle/6.4.1/javaCompile/javaCompile.lock b/.gradle/6.4.1/javaCompile/javaCompile.lock new file mode 100644 index 0000000..64b772b Binary files /dev/null and b/.gradle/6.4.1/javaCompile/javaCompile.lock differ diff --git a/.gradle/6.4.1/javaCompile/taskHistory.bin b/.gradle/6.4.1/javaCompile/taskHistory.bin new file mode 100644 index 0000000..10d4d24 Binary files /dev/null and b/.gradle/6.4.1/javaCompile/taskHistory.bin differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 0000000..78ba1fa Binary files /dev/null and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/buildOutputCleanup/cache.properties b/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 0000000..4c4b339 --- /dev/null +++ b/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Sat Jul 11 23:56:44 CST 2020 +gradle.version=6.4.1 diff --git a/.gradle/buildOutputCleanup/outputFiles.bin b/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 0000000..18ece09 Binary files /dev/null and b/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/.gradle/checksums/checksums.lock b/.gradle/checksums/checksums.lock new file mode 100644 index 0000000..660369c Binary files /dev/null and b/.gradle/checksums/checksums.lock differ diff --git a/.gradle/checksums/md5-checksums.bin b/.gradle/checksums/md5-checksums.bin new file mode 100644 index 0000000..d4d662e Binary files /dev/null and b/.gradle/checksums/md5-checksums.bin differ diff --git a/.gradle/checksums/sha1-checksums.bin b/.gradle/checksums/sha1-checksums.bin new file mode 100644 index 0000000..d575525 Binary files /dev/null and b/.gradle/checksums/sha1-checksums.bin differ diff --git a/.gradle/vcs-1/gc.properties b/.gradle/vcs-1/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..05f0b38 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +<<<<<<< HEAD +#ipsm-sced +======= +# fx-falsework +基于javafx、spring boot 开发的客户端与服务端系统开发脚手架 +>>>>>>> 81a2173cfca6f001994b84cf6f6997432fea415d diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..faac005 --- /dev/null +++ b/build.gradle @@ -0,0 +1,16 @@ +plugins { + id 'java' +} + +group 'org.example' +version '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + testCompile group: 'junit', name: 'junit', version: '4.12' + + +} diff --git a/client/build.gradle b/client/build.gradle new file mode 100644 index 0000000..1c15c06 --- /dev/null +++ b/client/build.gradle @@ -0,0 +1,50 @@ +plugins { + id 'java' +} + +group 'org.epri.fx.client' +version '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + implementation project(':server') +// implementation 'com.jfoenix:jfoenix:8.0.10' +// compile 'com.airhacks:afterburner.fx:1.7.0' + compile 'de.jensd:fontawesomefx:8.9' + compile 'org.apache.lucene:lucene-core:7.4.0' + compile 'org.apache.lucene:lucene-grouping:7.4.0' + compile 'org.apache.lucene:lucene-queryparser:7.4.0' + compile 'dom4j:dom4j:1.6.1' + + + compile 'org.controlsfx:controlsfx:8.40.17' + compile group: 'org.javassist', name: 'javassist', version: '3.18.1-GA' + compile group: 'com.guigarage', name: 'observable-toogles', version: '0.1' + compile group: 'javax.inject', name: 'javax.inject', version: '1' + compile files('libs/datafx-injection-8.0.2-SNAPSHOT.jar') + compile files('libs/datafx-eventsystem-8.0.2-SNAPSHOT.jar') + compile files('libs/datafx-core-8.0.2-SNAPSHOT.jar') + compile files('libs/datafx-flow-8.0.2-SNAPSHOT.jar') + compile files('libs/jfoenix-8.0.10.jar') + compile files('libs/pinyin4j-2.5.0.jar') + compile files('libs/tilesfx-1.6.8.jar') + + + compile 'org.kordamp.ikonli:ikonli-javafx:2.4.0' + compile 'org.kordamp.ikonli:ikonli-fontawesome5-pack:2.4.0' + compile 'io.github.openfeign:feign-core:10.9' + compile 'io.github.openfeign:feign-okhttp:10.9' + compile 'io.github.openfeign:feign-jackson:10.9' + compile 'io.github.openfeign:feign-hystrix:10.9' + compile 'io.github.openfeign:feign-ribbon:10.9' + compile 'io.github.openfeign:feign-slf4j:10.9' + compile 'com.netflix.ribbon:ribbon-httpclient:2.2.0' + + testCompile group: 'junit', name: 'junit', version: '4.12' + implementation 'org.apache.commons:commons-lang3:3.4' + + +} diff --git a/client/libs/datafx-core-8.0.2-SNAPSHOT-javadoc.jar b/client/libs/datafx-core-8.0.2-SNAPSHOT-javadoc.jar new file mode 100644 index 0000000..3208707 Binary files /dev/null and b/client/libs/datafx-core-8.0.2-SNAPSHOT-javadoc.jar differ diff --git a/client/libs/datafx-core-8.0.2-SNAPSHOT-sources.jar b/client/libs/datafx-core-8.0.2-SNAPSHOT-sources.jar new file mode 100644 index 0000000..a13c07c Binary files /dev/null and b/client/libs/datafx-core-8.0.2-SNAPSHOT-sources.jar differ diff --git a/client/libs/datafx-core-8.0.2-SNAPSHOT.jar b/client/libs/datafx-core-8.0.2-SNAPSHOT.jar new file mode 100644 index 0000000..f957cbf Binary files /dev/null and b/client/libs/datafx-core-8.0.2-SNAPSHOT.jar differ diff --git a/client/libs/datafx-eventsystem-8.0.2-SNAPSHOT-javadoc.jar b/client/libs/datafx-eventsystem-8.0.2-SNAPSHOT-javadoc.jar new file mode 100644 index 0000000..7d5d666 Binary files /dev/null and b/client/libs/datafx-eventsystem-8.0.2-SNAPSHOT-javadoc.jar differ diff --git a/client/libs/datafx-eventsystem-8.0.2-SNAPSHOT-sources.jar b/client/libs/datafx-eventsystem-8.0.2-SNAPSHOT-sources.jar new file mode 100644 index 0000000..68b967b Binary files /dev/null and b/client/libs/datafx-eventsystem-8.0.2-SNAPSHOT-sources.jar differ diff --git a/client/libs/datafx-eventsystem-8.0.2-SNAPSHOT.jar b/client/libs/datafx-eventsystem-8.0.2-SNAPSHOT.jar new file mode 100644 index 0000000..effb74f Binary files /dev/null and b/client/libs/datafx-eventsystem-8.0.2-SNAPSHOT.jar differ diff --git a/client/libs/datafx-featuretoggle-8.0.2-SNAPSHOT.jar b/client/libs/datafx-featuretoggle-8.0.2-SNAPSHOT.jar new file mode 100644 index 0000000..7109ba9 Binary files /dev/null and b/client/libs/datafx-featuretoggle-8.0.2-SNAPSHOT.jar differ diff --git a/client/libs/datafx-flow-8.0.2-SNAPSHOT-javadoc.jar b/client/libs/datafx-flow-8.0.2-SNAPSHOT-javadoc.jar new file mode 100644 index 0000000..7f1f9ee Binary files /dev/null and b/client/libs/datafx-flow-8.0.2-SNAPSHOT-javadoc.jar differ diff --git a/client/libs/datafx-flow-8.0.2-SNAPSHOT-sources.jar b/client/libs/datafx-flow-8.0.2-SNAPSHOT-sources.jar new file mode 100644 index 0000000..0135e16 Binary files /dev/null and b/client/libs/datafx-flow-8.0.2-SNAPSHOT-sources.jar differ diff --git a/client/libs/datafx-flow-8.0.2-SNAPSHOT.jar b/client/libs/datafx-flow-8.0.2-SNAPSHOT.jar new file mode 100644 index 0000000..6ae7a9a Binary files /dev/null and b/client/libs/datafx-flow-8.0.2-SNAPSHOT.jar differ diff --git a/client/libs/datafx-injection-8.0.2-SNAPSHOT-javadoc.jar b/client/libs/datafx-injection-8.0.2-SNAPSHOT-javadoc.jar new file mode 100644 index 0000000..dbacca1 Binary files /dev/null and b/client/libs/datafx-injection-8.0.2-SNAPSHOT-javadoc.jar differ diff --git a/client/libs/datafx-injection-8.0.2-SNAPSHOT-sources.jar b/client/libs/datafx-injection-8.0.2-SNAPSHOT-sources.jar new file mode 100644 index 0000000..8e2fced Binary files /dev/null and b/client/libs/datafx-injection-8.0.2-SNAPSHOT-sources.jar differ diff --git a/client/libs/datafx-injection-8.0.2-SNAPSHOT.jar b/client/libs/datafx-injection-8.0.2-SNAPSHOT.jar new file mode 100644 index 0000000..c7a86fb Binary files /dev/null and b/client/libs/datafx-injection-8.0.2-SNAPSHOT.jar differ diff --git a/client/libs/jfoenix-8.0.10.jar b/client/libs/jfoenix-8.0.10.jar new file mode 100644 index 0000000..12f08cf Binary files /dev/null and b/client/libs/jfoenix-8.0.10.jar differ diff --git a/client/libs/pinyin4j-2.5.0.jar b/client/libs/pinyin4j-2.5.0.jar new file mode 100644 index 0000000..e8ede13 Binary files /dev/null and b/client/libs/pinyin4j-2.5.0.jar differ diff --git a/client/libs/tilesfx-1.6.8.jar b/client/libs/tilesfx-1.6.8.jar new file mode 100644 index 0000000..b99eab4 Binary files /dev/null and b/client/libs/tilesfx-1.6.8.jar differ diff --git a/client/src/main/java/com/epri/fx/client/AppStartup.java b/client/src/main/java/com/epri/fx/client/AppStartup.java new file mode 100644 index 0000000..19b8318 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/AppStartup.java @@ -0,0 +1,99 @@ +package com.epri.fx.client; + +import com.epri.fx.client.gui.uicomponents.control.LFXDecorator; +import com.epri.fx.client.gui.uicomponents.login.LoginController; +import com.epri.fx.client.store.ApplicatonStore; +import com.jfoenix.assets.JFoenixResources; +import com.jfoenix.svg.SVGGlyph; +import com.jfoenix.svg.SVGGlyphLoader; +import com.netflix.config.ConfigurationManager; +import io.datafx.controller.context.ApplicationContext; +import io.datafx.controller.flow.Flow; +import io.datafx.controller.flow.FlowHandler; +import io.datafx.controller.flow.container.AnimatedFlowContainer; +import io.datafx.controller.flow.container.ContainerAnimations; +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.layout.StackPane; +import javafx.scene.paint.Color; +import javafx.scene.text.Font; +import javafx.stage.Stage; +import javafx.util.Duration; + +import java.io.IOException; +import java.io.InputStream; + + +/** + * @description: + * @className: AppStartup + * @author: liwen + * @date: 2019-08-26 16:24 + */ +public class AppStartup extends Application { + + + + @Override + public void init() throws Exception { + + InputStream in = AppStartup.class.getClassLoader().getResourceAsStream("fonts/msyh.ttf"); + Font font1 = Font.loadFont(in, 12); + + System.err.println(font1.getName()+"\t"+font1.getFamily()); + ConfigurationManager.loadPropertiesFromResources("sample-client.properties"); +// + + + } + + @Override + public void start(Stage stage) throws Exception { + + String keyPrefix = ""; +// //全局样式 +// setUserAgentStylesheet(null); +// StyleManager.getInstance().addUserAgentStylesheet("css/app.css"); + + new Thread(() -> { + try { + SVGGlyphLoader.loadGlyphsFont(AppStartup.class.getResourceAsStream("/fonts/icon_font/iconfont.svg"), + ApplicatonStore.ICON_FONT_KEY); +// SVGGlyphLoader.loadGlyphsFont(AppStartup.class.getResourceAsStream("/fonts/icon_font/icon-font-solid.svg"), +// "IconFontSolid.svg"); + } catch (IOException ioExc) { + ioExc.printStackTrace(); + } + }).start(); + + + ApplicationContext.getInstance().register(stage, Stage.class); + + Flow flow = new Flow(LoginController.class); + FlowHandler flowHandler = flow.createHandler(); + StackPane rootPane = flowHandler.start(new AnimatedFlowContainer(Duration.millis(320), ContainerAnimations.SWIPE_LEFT)); + + ApplicationContext.getInstance().register("mainFlowHandler", flowHandler); + ApplicationContext.getInstance().register(rootPane, StackPane.class); + + LFXDecorator wfxDecorator = new LFXDecorator(stage, rootPane, false, true, true); + wfxDecorator.setCustomMaximize(true); + wfxDecorator.setGraphic(new SVGGlyph("")); + + Scene scene = new Scene(wfxDecorator, 1000, 700); + stage.setTitle("JavaFX Welcome"); + scene.setFill(Color.TRANSPARENT); + stage.setScene(scene); + stage.show(); + + + scene.getStylesheets().addAll(JFoenixResources.load("/css/app-fonts.css").toExternalForm(),AppStartup.class.getResource("/css/app.css").toExternalForm()); + + } + + @Override + public void stop() throws Exception { + + System.err.println(Font.getFontNames()); + } +} diff --git a/client/src/main/java/com/epri/fx/client/bean/CountryPath.java b/client/src/main/java/com/epri/fx/client/bean/CountryPath.java new file mode 100644 index 0000000..f76c003 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/bean/CountryPath.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017 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 com.epri.fx.client.bean; + +import javafx.scene.control.Tooltip; +import javafx.scene.shape.SVGPath; + +import java.util.Locale; + + +/** + * Created by hansolo on 21.12.16. + */ +public class CountryPath extends SVGPath { + private String name; + private Locale locale; + private Tooltip tooltip; + + + // ******************** Constructors ************************************** + public CountryPath() { + this("", null); + } + + public CountryPath(final String NAME) { + this(NAME, null); + } + + public CountryPath(final String NAME, final String CONTENT) { + super(); + name = NAME; + locale = new Locale("", NAME); + tooltip = new Tooltip(locale.getDisplayCountry()); + + Tooltip.install(this, tooltip); + if (null == CONTENT) return; + setContent(CONTENT); + } + + + // ******************** Methods ******************************************* + public String getName() { + return name; + } + + public void setName(final String NAME) { + this.name = NAME; + } + + public Locale getLocale() { + return locale; + } + + public void setLocale(final Locale LOCALE) { + locale = LOCALE; + } + + public Tooltip getTooltip() { + return tooltip; + } + + public void setTooltip(final Tooltip TOOLTIP) { + tooltip = TOOLTIP; + Tooltip.install(this, tooltip); + } + + @Override + public String toString() { + return new StringBuilder("{\n").append(" name :\"").append(name).append("\"\n") + .append(" locale :\"").append(locale).append("\"\n") + .append(" tooltip:\"").append(tooltip.getText()).append("\"\n") + .append(" content:\"").append(getContent()).append("\"\n") + .append("}\n") + .toString(); + } +} diff --git a/client/src/main/java/com/epri/fx/client/bean/MenuVoCell.java b/client/src/main/java/com/epri/fx/client/bean/MenuVoCell.java new file mode 100644 index 0000000..fe553f9 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/bean/MenuVoCell.java @@ -0,0 +1,50 @@ +package com.epri.fx.client.bean; + +import com.epri.fx.server.entity.Menu; +import com.epri.fx.server.vo.MenuVO; +import javafx.beans.property.ListProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleListProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +import java.util.List; + +/** + * @description: + * @className: MenuVoCell + * @author: liwen + * @date: 2020/8/17 20:08 + */ + +public class MenuVoCell { + private ObjectProperty menuVO; + private ObservableList childrenMenus; + + public MenuVoCell(MenuVO menuVO, List childrenMenus) { + this.menuVO = new SimpleObjectProperty<>(menuVO); + if (childrenMenus != null) { + getChildrenMenus().addAll(childrenMenus); + } + + } + + + public MenuVO getMenuVO() { + return menuVO.get(); + } + + public ObjectProperty menuVOProperty() { + return menuVO; + } + + public ObservableList getChildrenMenus() { + if (childrenMenus == null) { + ObservableList innerList = FXCollections.observableArrayList(); + childrenMenus = new SimpleListProperty<>(innerList); + } + + return childrenMenus; + } +} \ No newline at end of file diff --git a/client/src/main/java/com/epri/fx/client/exception/AppRunException.java b/client/src/main/java/com/epri/fx/client/exception/AppRunException.java new file mode 100644 index 0000000..6ca762f --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/exception/AppRunException.java @@ -0,0 +1,43 @@ +package com.epri.fx.client.exception; + +import javafx.application.Platform; + +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * @description: + * @className: AppRunException + * @author: liwen + * @date: 2020/8/5 23:58 + */ +public class AppRunException { + + public static void showError(Thread t, Throwable e) { + System.err.println("***Default exception handler***"); + if (Platform.isFxApplicationThread()) { + showErrorDialog(e); + } else { + System.err.println("An unexpected error occurred in " + t); + + } + } + + private static void showErrorDialog(Throwable e) { + StringWriter errorMsg = new StringWriter(); + e.printStackTrace(); +// e.printStackTrace(new PrintWriter(errorMsg)); + +// Stage dialog = new Stage(); +// dialog.initModality(Modality.APPLICATION_MODAL); +// FXMLLoader loader = new FXMLLoader(Main.class.getResource("Error.fxml")); +// try { +// Parent root = loader.load(); +// ((ErrorController)loader.getController()).setErrorText(errorMsg.toString()); +// dialog.setScene(new Scene(root, 250, 400)); +// dialog.show(); +// } catch (IOException exc) { +// exc.printStackTrace(); +// } + } +} diff --git a/client/src/main/java/com/epri/fx/client/gui/feature/DisabledByFeature.java b/client/src/main/java/com/epri/fx/client/gui/feature/DisabledByFeature.java new file mode 100644 index 0000000..e271497 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/feature/DisabledByFeature.java @@ -0,0 +1,12 @@ +package com.epri.fx.client.gui.feature; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface DisabledByFeature { + String value(); +} diff --git a/client/src/main/java/com/epri/fx/client/gui/feature/FeatureHandler.java b/client/src/main/java/com/epri/fx/client/gui/feature/FeatureHandler.java new file mode 100644 index 0000000..5599322 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/feature/FeatureHandler.java @@ -0,0 +1,37 @@ +package com.epri.fx.client.gui.feature; + +import com.epri.fx.client.store.ApplicatonStore; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.scene.Node; + +import java.util.Map; + +public class FeatureHandler { + + private static FeatureHandler instance; + + private Map permissionInfoMap; + + private FeatureHandler() { + } + + public static synchronized FeatureHandler getInstance() { + if (instance == null) { + instance = new FeatureHandler(); + } + return instance; + } + + + + + public void hideByFeature(Node node, String featureName) { + node.visibleProperty().bind(new SimpleBooleanProperty(ApplicatonStore.getFeatureMap().get(featureName)!=null)); + node.managedProperty().bind(node.visibleProperty()); + } + + public void disableByFeature(Node node, String featureName) { + node.disableProperty().bind(new SimpleBooleanProperty(ApplicatonStore.getFeatureMap().get(featureName)!=null)); + } + +} diff --git a/client/src/main/java/com/epri/fx/client/gui/feature/FeatureResourceConsumer.java b/client/src/main/java/com/epri/fx/client/gui/feature/FeatureResourceConsumer.java new file mode 100644 index 0000000..a08d0c3 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/feature/FeatureResourceConsumer.java @@ -0,0 +1,37 @@ +package com.epri.fx.client.gui.feature; + +import io.datafx.controller.ViewNode; +import io.datafx.controller.injection.scopes.ApplicationScoped; +import io.datafx.core.DataFXUtils; +import javafx.fxml.FXML; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; + +@ApplicationScoped +public class FeatureResourceConsumer { + + public void consumeResource(Object object) { + + Class cls = object.getClass(); + for (final Field field : DataFXUtils.getInheritedDeclaredFields(cls)) { + + if (field.getAnnotation(FXML.class) != null || field.getAnnotation(ViewNode.class) != null) { + + List fieldAnnotations = Arrays.asList(field.getAnnotations()); + + for (Annotation annotation : fieldAnnotations) { + if (annotation instanceof DisabledByFeature) { + FeatureHandler.getInstance().disableByFeature(DataFXUtils.getPrivileged(field, object), ((DisabledByFeature) annotation).value()); + } else if (annotation instanceof HideByFeature) { + FeatureHandler.getInstance().hideByFeature(DataFXUtils.getPrivileged(field, object), ((HideByFeature) annotation).value()); + } + } + } + } + } + + +} diff --git a/client/src/main/java/com/epri/fx/client/gui/feature/HideByFeature.java b/client/src/main/java/com/epri/fx/client/gui/feature/HideByFeature.java new file mode 100644 index 0000000..55763b8 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/feature/HideByFeature.java @@ -0,0 +1,12 @@ +package com.epri.fx.client.gui.feature; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface HideByFeature { + String value(); +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/group/GroupManagementController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/group/GroupManagementController.java new file mode 100644 index 0000000..c599d56 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/group/GroupManagementController.java @@ -0,0 +1,81 @@ +package com.epri.fx.client.gui.uicomponents.admin.group; + +import com.epri.fx.client.gui.uicomponents.admin.group.components.GroupDetailController; +import com.epri.fx.client.model.GroupDataModel; +import com.epri.fx.client.request.Request; +import com.epri.fx.client.request.feign.admin.GroupTypeFeign; +import com.epri.fx.server.vo.GroupTypeVO; +import com.jfoenix.controls.JFXTabPane; +import io.datafx.controller.ViewController; +import io.datafx.controller.flow.Flow; +import io.datafx.controller.flow.FlowException; +import io.datafx.controller.flow.context.ViewFlowContext; +import io.datafx.core.concurrent.ProcessChain; +import io.datafx.eventsystem.Event; +import io.datafx.eventsystem.OnEvent; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.fxml.FXML; +import javafx.scene.control.Tab; +import javafx.scene.control.TextField; +import javafx.scene.layout.StackPane; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; + +/** + * @description: + * @className: GroupManagementController + * @author: liwen + * @date: 2020/7/22 15:09 + */ +@ViewController(value = "/fxml/admin/group/group_management.fxml", title = "角色权限管理") +public class GroupManagementController { + + + @FXML + private JFXTabPane tabPane; + + @FXML + private StackPane rootPane; + @Inject + private GroupDataModel groupDataModel; + + @PostConstruct + private void init() { + + TextField textField = new TextField(); + textField.setStyle(""); + + tabPane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Tab oldValue, Tab newValue) { +// groupDataModel.setSelectedGroupType(newValue.); + } + }); + ProcessChain.create() + .addSupplierInExecutor(() -> Request.connector(GroupTypeFeign.class).getAllGroupTypes()) + .addConsumerInPlatformThread(rel -> { + for (GroupTypeVO groupType : rel) { + + Tab tab = new Tab(groupType.getName()); + Flow flow = new Flow(GroupDetailController.class); + ViewFlowContext viewFlowContext = new ViewFlowContext(); + viewFlowContext.register("groupType", groupType.getId()); + viewFlowContext.register("rootPane", rootPane); + try { + tab.setContent(flow.createHandler(viewFlowContext).start()); + } catch (FlowException e) { + e.printStackTrace(); + } + tabPane.getTabs().add(tab); + } + }).onException(e -> e.printStackTrace()) + .run(); + } + + @OnEvent("test-message") + private void onNewChatMessage(Event e) { + System.err.println(this.getClass() + "\t" + e.getContent()); + } +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/group/components/GroupDetailController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/group/components/GroupDetailController.java new file mode 100644 index 0000000..a03bbe4 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/group/components/GroupDetailController.java @@ -0,0 +1,703 @@ +package com.epri.fx.client.gui.uicomponents.admin.group.components; + +import com.epri.fx.client.gui.uicomponents.control.FilterableCheckBoxTreeItem; +import com.epri.fx.client.gui.uicomponents.control.FilterableTreeItem; +import com.epri.fx.client.gui.uicomponents.control.TreeItemPredicate; +import com.epri.fx.client.model.GroupDataModel; +import com.epri.fx.client.request.Request; +import com.epri.fx.client.request.feign.admin.GroupFeign; +import com.epri.fx.client.request.feign.admin.MenuFeign; +import com.epri.fx.client.store.ApplicatonStore; +import com.epri.fx.client.utils.Pinyin4jUtil; +import com.epri.fx.server.entity.User; +import com.epri.fx.server.vo.ElementVO; +import com.epri.fx.server.vo.GroupVO; +import com.epri.fx.server.vo.MenuVO; +import com.jfoenix.controls.*; +import com.jfoenix.svg.SVGGlyphLoader; +import io.datafx.controller.ViewController; +import io.datafx.controller.flow.FlowException; +import io.datafx.controller.flow.action.ActionMethod; +import io.datafx.controller.flow.action.ActionTrigger; +import io.datafx.controller.flow.context.FXMLViewFlowContext; +import io.datafx.controller.flow.context.ViewFlowContext; +import io.datafx.core.concurrent.ProcessChain; +import io.datafx.eventsystem.Event; +import io.datafx.eventsystem.OnEvent; +import javafx.beans.binding.Bindings; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.fxml.FXML; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.*; +import javafx.scene.control.cell.CheckBoxTableCell; +import javafx.scene.control.cell.CheckBoxTreeCell; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.util.Callback; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @description: + * @className: GroupDetail + * @author: liwen + * @date: 2020/7/22 16:17 + */ +@ViewController(value = "/fxml/admin/group/components/group_detail.fxml", title = "test") +public class GroupDetailController { + + + @FXML + private VBox contentPane; + @FXML + private JFXChipView leaderChipView; + @FXML + private JFXChipView memberChipView; + @FXML + private JFXDialog groupAuthorityDialog; + @FXML + private JFXDialog groupUserDialog; + @FXML + private JFXProgressBar progressBar; + @FXML + @ActionTrigger("saveAuthority") + private JFXButton saveAuthorityButton; + @FXML + @ActionTrigger("selectAllElement") + private JFXCheckBox selectAllCheckBox; + @FXML + @ActionTrigger("handlerAuthority") + private ToggleButton handlerAuthorityButton; + @FXML + @ActionTrigger("handlerUser") + private ToggleButton handlerUserButton; + @FXML + @ActionTrigger("addGroup") + private ToggleButton addButton; + @FXML + @ActionTrigger("editGroup") + private ToggleButton editButton; + @FXML + @ActionTrigger("deleteGroup") + private ToggleButton deleteButton; + @FXML + @ActionTrigger("cancelGroup") + private JFXButton cancelButton; + @FXML + @ActionTrigger("createGroup") + private JFXButton defineButton; + @FXML + @ActionTrigger("updateGroup") + private JFXButton updateButton; + @FXML + @ActionTrigger("cancelAuthority") + private JFXButton cancelAuthorityButton; + @FXML + @ActionTrigger("cancelUser") + private JFXButton cancelUserButton; + @FXML + @ActionTrigger("modifiyUsers") + private JFXButton saveUserButton; + @FXML + private JFXTextField treeSearchTextField; + @FXML + private JFXTextField nameTextField; + @FXML + private JFXTextField codeTextField; + @FXML + private JFXTextArea descTextArea; + @FXML + private ButtonBar buttonBar; + @FXML + private JFXTreeView treeView; + @Inject + private GroupDataModel groupDataModel; + + @FXMLViewFlowContext + private ViewFlowContext viewFlowContext; + + + @FXML + private JFXTextField menuTreeSearchTextField; + @FXML + private JFXTreeView menuTreeView; + @FXML + private TableView elementTableView; + @FXML + private TableColumn selColumn; + @FXML + private TableColumn serialNumberColumn; + @FXML + private TableColumn codeColumn; + @FXML + private TableColumn typeColumn; + @FXML + private TableColumn nameColumn; + @FXML + private TableColumn addressColumn; + @FXML + private TableColumn requestTypeColumn; + + private Integer groupType; + private Integer groupId = -1; + + @PostConstruct + private void init() { + final ToggleGroup group = new ToggleGroup(); + + addButton.setToggleGroup(group); + editButton.setToggleGroup(group); + deleteButton.setToggleGroup(group); + handlerAuthorityButton.setToggleGroup(group); + handlerUserButton.setToggleGroup(group); + try { + addButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".add-circle-outline")); + editButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".create-outline")); + deleteButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".trash-outline")); + handlerAuthorityButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".quanxianfenpei")); + handlerUserButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".yonghugl")); + } catch (Exception e) { + e.printStackTrace(); + } + + buttonBar.managedProperty().bind(buttonBar.visibleProperty()); + contentPane.disableProperty().bind(buttonBar.visibleProperty().not()); + defineButton.managedProperty().bind(defineButton.visibleProperty()); + updateButton.visibleProperty().bind(defineButton.visibleProperty().not()); + updateButton.managedProperty().bind(updateButton.visibleProperty()); + progressBar.visibleProperty().bind(buttonBar.disableProperty().and(buttonBar.visibleProperty())); + progressBar.managedProperty().bind(progressBar.visibleProperty()); + groupType = (Integer) viewFlowContext.getRegisteredObject("groupType"); + + serialNumberColumn.setCellFactory((col) -> { + TableCell cell = new TableCell() { + @Override + public void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + this.setText(null); + this.setGraphic(null); + + if (!empty) { + int rowIndex = this.getIndex() + 1; + this.setText(String.valueOf(rowIndex)); + } + } + }; + return cell; + }); + selColumn.setCellValueFactory(new PropertyValueFactory<>("sel")); + selColumn.setCellFactory(new Callback, // + TableCell>() { + @Override + public TableCell call(TableColumn p) { + CheckBoxTableCell cell = new CheckBoxTableCell() { + @Override + public void updateItem(Boolean item, boolean empty) { + super.updateItem(item, empty); + if (empty) { + setGraphic(null); + } else { + CheckBox cb = (CheckBox) getGraphic(); + JFXCheckBox checkBox = new JFXCheckBox(); + checkBox.indeterminateProperty().bindBidirectional(cb.indeterminateProperty()); + checkBox.selectedProperty().bindBidirectional(cb.selectedProperty()); + setGraphic(checkBox); + } + } + }; + cell.setAlignment(Pos.CENTER); + return cell; + } + + }); + codeColumn.setCellValueFactory(cellData -> cellData.getValue().codeProperty()); + nameColumn.setCellValueFactory(new PropertyValueFactory<>("name")); + typeColumn.setCellValueFactory(new PropertyValueFactory<>("type")); + addressColumn.setCellValueFactory(new PropertyValueFactory<>("uri")); + requestTypeColumn.setCellValueFactory(new PropertyValueFactory<>("method")); + + treeView.setCellFactory(new Callback() { + @Override + public TreeCell call(TreeView param) { + return new TreeCell() { + @Override + protected void updateItem(GroupVO menu, boolean empty) { + super.updateItem(menu, empty); + if (!empty && menu != null) { + setText(menu.getName()); + } else { + setText(null); + } + } + }; + } + }); + menuTreeView.setCellFactory(new Callback() { + @Override + public CheckBoxTreeCell call(TreeView param) { + return new CheckBoxTreeCell() { + @Override + public void updateItem(MenuVO item, boolean empty) { + super.updateItem(item, empty); + if (!empty && item != null) { + + setText(item.getTitle()); + CheckBox cb = (CheckBox) getGraphic(); + JFXCheckBox checkBox = new JFXCheckBox(); + checkBox.indeterminateProperty().bindBidirectional(cb.indeterminateProperty()); + checkBox.selectedProperty().bindBidirectional(cb.selectedProperty()); + setGraphic(checkBox); + } else { + setText(null); + } + } + + }; + } + }); + menuTreeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener>() { + @Override + public void changed(ObservableValue> observable, TreeItem oldValue, TreeItem newValue) { + + if (newValue.isLeaf()) { + MenuVO menuVO = newValue.getValue(); + groupDataModel.setSelectedMenuVO(menuVO); + elementTableView.setItems(groupDataModel.getElementVOS()); + } else { + groupDataModel.getElementVOS().clear(); + } + + int sel = 0; + if (groupDataModel.getElementVOS().isEmpty()) { + sel=-1; + } + for (ElementVO elementVO : groupDataModel.getElementVOS()) { + + if (elementVO.isSel() == false) { + sel = -1; + break; + } else { + sel += 1; + } + } + + + selectAllCheckBox.setSelected(sel==groupDataModel.getElementVOS().size()); + + } + }); + treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener>() { + @Override + public void changed(ObservableValue> observable, TreeItem oldValue, TreeItem newValue) { + + updateMenuInfo(newValue); + } + }); + + + leaderChipView.setChipFactory((emailJFXChipView, email) -> new JFXDefaultChip(emailJFXChipView, email) { + { + if (getItem() != null) { + try { + Node image = SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".user-tie"); + image.getStyleClass().add("chip-icon"); + root.getChildren().add(0, image); + } catch (Exception e) { + e.printStackTrace(); + } + + } + } + }); + + leaderChipView.setPredicate((user, val) -> { + + val = Pinyin4jUtil.toPinYinLowercase(val); + return Pinyin4jUtil.toPinYinLowercase(user.getName()).contains(val); + }); + + memberChipView.setPredicate((user, val) -> { + + val = Pinyin4jUtil.toPinYinLowercase(val); + return Pinyin4jUtil.toPinYinLowercase(user.getName()).contains(val); + }); + + + memberChipView.setChipFactory((emailJFXChipView, email) -> new JFXDefaultChip(emailJFXChipView, email) { + { + if (getItem() != null) { + try { + Node image = SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".user"); + image.getStyleClass().add("chip-icon"); + root.getChildren().add(0, image); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + }); + leaderChipView.setSuggestionsCellFactory(param -> new JFXListCell<>()); + memberChipView.setSuggestionsCellFactory(param -> new JFXListCell<>()); + + initLoadData(); + + } + + private void initLoadData() { + + loadingTreeData(); + + } + + private void loadingTreeData() { + ProcessChain.create() + .addSupplierInExecutor(() -> Request.connector(GroupFeign.class).getGroupList(groupType)) + .addConsumerInPlatformThread(rel -> buildGroupTree(rel)).onException(e -> e.printStackTrace()).run(); + } + + private void updateMenuInfo(TreeItem newValue) { + buttonBar.setVisible(false); + if (newValue == null) { + groupId = -1; + groupDataModel.setSelectedGroup(null); + return; + } + + GroupVO groupVO = newValue.getValue(); + groupDataModel.setSelectedGroup(groupVO); + groupId = groupVO.getId(); + codeTextField.textProperty().unbind(); + codeTextField.textProperty().bind(groupVO.codeProperty()); + nameTextField.textProperty().unbind(); + nameTextField.textProperty().bind(groupVO.nameProperty()); + descTextArea.textProperty().unbind(); + descTextArea.textProperty().bind(groupVO.descriptionProperty()); + + } + + private void buildMenuTree(List menuVOList) { + + + if (menuVOList.isEmpty()) { + menuTreeView.setRoot(null); + return; + } + groupDataModel.getMenuVOS().clear(); + for (MenuVO menuVO : menuVOList) { + groupDataModel.getMenuVOS().add(menuVO); + } + + MenuVO root = menuVOList.stream().min(Comparator.comparing(MenuVO::getParentId)).get(); + Map> map = menuVOList.stream().collect(Collectors.groupingBy(MenuVO::getParentId)); + map.remove(root.getParentId()); + + FilterableCheckBoxTreeItem rootNode = new FilterableCheckBoxTreeItem(root); + groupDataModel.setSelectedMenuVO(root); + menuTreeView.setRoot(rootNode); + menuTreeView.setShowRoot(false); + addMenuChildrenNode(rootNode, map); + rootNode.predicateProperty().bind(Bindings.createObjectBinding(() -> { + if (menuTreeSearchTextField.getText() == null || menuTreeSearchTextField.getText().isEmpty()) { + return null; + } + return TreeItemPredicate.create(actor -> { + String searchText = Pinyin4jUtil.toPinYinLowercase(menuTreeSearchTextField.getText()); + String itemText = Pinyin4jUtil.toPinYinLowercase(actor.getTitle()); + return itemText.contains(searchText); + }); + }, menuTreeSearchTextField.textProperty())); + menuTreeView.getSelectionModel().select(1); + + rootNode.setExpanded(true); + } + + private void addMenuChildrenNode(FilterableCheckBoxTreeItem parentNode, Map> map) { + + List childrenList = map.get(parentNode.getValue().getId()); + + if (childrenList != null) { + + for (MenuVO menu : childrenList) { + + FilterableCheckBoxTreeItem clildrenNode = new FilterableCheckBoxTreeItem<>(menu); + clildrenNode.selectedProperty().bindBidirectional(menu.selProperty()); + parentNode.getInternalChildren().add(clildrenNode); + addMenuChildrenNode(clildrenNode, map); + } + parentNode.setExpanded(true); + + } + + } + + private void buildGroupTree(List groupVOList) { + + if (groupVOList.isEmpty()) { + treeView.setRoot(null); + return; + } + Map> map = groupVOList.stream().collect(Collectors.groupingBy(GroupVO::getParentId)); + GroupVO root = new GroupVO(); + root.setId(-1); + + FilterableTreeItem rootNode = new FilterableTreeItem(root); + treeView.setRoot(rootNode); + treeView.setShowRoot(false); + addChildrenNode(rootNode, map); + rootNode.predicateProperty().bind(Bindings.createObjectBinding(() -> { + if (treeSearchTextField.getText() == null || treeSearchTextField.getText().isEmpty()) { + return null; + } + return TreeItemPredicate.create(actor -> { + String searchText = Pinyin4jUtil.toPinYinLowercase(treeSearchTextField.getText()); + String itemText = Pinyin4jUtil.toPinYinLowercase(actor.getName()); + return itemText.contains(searchText); + }); + }, treeSearchTextField.textProperty())); + rootNode.setExpanded(true); + treeView.getSelectionModel().select(rootNode); + } + + private void addChildrenNode(FilterableTreeItem parentNode, Map> map) { + + List childrenList = map.get(parentNode.getValue().getId()); + + if (childrenList != null) { + + for (GroupVO menu : childrenList) { + + FilterableTreeItem clildrenNode = new FilterableTreeItem<>(menu); + parentNode.getInternalChildren().add(clildrenNode); + parentNode.setExpanded(true); + addChildrenNode(clildrenNode, map); + } + } + + } + + @ActionMethod("addGroup") + private void addGroup() { + codeTextField.textProperty().unbind(); + codeTextField.setText(""); + nameTextField.textProperty().unbind(); + nameTextField.setText(""); + descTextArea.textProperty().unbind(); + descTextArea.setText(""); + buttonBar.setVisible(true); + defineButton.setVisible(true); + + } + + @ActionMethod("editGroup") + private void editGroup() { + codeTextField.textProperty().unbind(); + nameTextField.textProperty().unbind(); + descTextArea.textProperty().unbind(); + buttonBar.setVisible(true); + defineButton.setVisible(false); + } + + @ActionMethod("cancelGroup") + private void cancelGroup() { + buttonBar.setVisible(false); + } + + @ActionMethod("createGroup") + private void createGroup() { + GroupVO groupVO = new GroupVO(); + groupVO.setParentId(groupId); + groupVO.setGroupType(groupType); + groupVO.setCode(codeTextField.getText()); + groupVO.setName(nameTextField.getText()); + groupVO.setDescription(descTextArea.getText()); + + ProcessChain.create() + .addRunnableInPlatformThread(() -> buttonBar.setDisable(true)).addSupplierInExecutor(() -> Request.connector(GroupFeign.class).addGroup(groupVO)) + .addConsumerInPlatformThread(rel -> { + if (rel >= 0) { + loadingTreeData(); + } + }) + .withFinal(() -> { + buttonBar.setDisable(false); + buttonBar.setVisible(false); + }) + .run(); + + + } + + @ActionMethod("updateGroup") + private void updateGroup() { + GroupVO groupVO = new GroupVO(); + groupVO.setId(groupDataModel.getSelectedGroup().getId()); + groupVO.setParentId(groupDataModel.getSelectedGroup().getParentId()); + groupVO.setGroupType(groupType); + groupVO.setCode(codeTextField.getText()); + groupVO.setName(nameTextField.getText()); + groupVO.setDescription(descTextArea.getText()); + + ProcessChain.create() + .addRunnableInPlatformThread(() -> buttonBar.setDisable(true)).addSupplierInExecutor(() -> Request.connector(GroupFeign.class).updateGroup(groupVO)) + .addConsumerInPlatformThread(rel -> { + if (rel >= 0) { + loadingTreeData(); + } + }) + .withFinal(() -> { + buttonBar.setDisable(false); + buttonBar.setVisible(false); + }) + .run(); + + + } + + @ActionMethod("deleteGroup") + private void deleteGroup() { + GroupVO groupVO = groupDataModel.getSelectedGroup(); + + JFXAlert alert = new JFXAlert((Stage) contentPane.getScene().getWindow()); + alert.initModality(Modality.APPLICATION_MODAL); + alert.setOverlayClose(false); + JFXDialogLayout layout = new JFXDialogLayout(); + layout.setHeading(new Label("消息提示")); + layout.setBody(new Label("确实删除【" + groupVO.getName() + "】吗?")); + JFXButton closeButton = new JFXButton("取消"); + closeButton.setOnAction(event -> alert.hideWithAnimation()); + JFXButton determineButton = new JFXButton("确定"); + determineButton.setOnAction(event -> { + alert.hideWithAnimation(); + ProcessChain.create() + .addSupplierInExecutor(() -> Request.connector(GroupFeign.class).deleteGroup(groupVO)) + .addConsumerInPlatformThread(rel -> { + if (rel >= 0) { + loadingTreeData(); + } + }).onException(e -> e.printStackTrace()) + + .run(); + }); + layout.setActions(closeButton, determineButton); + alert.setContent(layout); + alert.show(); + + + + + } + + @ActionMethod("saveAuthority") + private void saveAuthority() { + + List saveMenuList = new ArrayList<>(); + + for (MenuVO menuVO : groupDataModel.getMenuVOS()) { + if (menuVO.isSel()) { + saveMenuList.add(menuVO); + List elementList = menuVO.getElementVOS().stream().filter(elementVO -> elementVO.isSel()).collect(Collectors.toList()); + menuVO.getElementVOS().clear(); + menuVO.getElementVOS().addAll(elementList); + } + } + + ProcessChain.create() + .addSupplierInExecutor(() -> Request.connector(GroupFeign.class).modifyMenuAuthority(groupId, saveMenuList)) + .addConsumerInPlatformThread(rel -> { + if (rel >= 0) { + groupDataModel.setSelectedMenuVO(new MenuVO()); + } + }).onException(e -> e.printStackTrace()) + .withFinal(() -> groupAuthorityDialog.close()) + + .run(); + } + + @ActionMethod("cancelAuthority") + private void cancelAuthorityButton() { + groupAuthorityDialog.close(); + } + + @ActionMethod("selectAllElement") + private void selectAllElement() { + + List elementVOS = groupDataModel.getElementVOS(); + for (ElementVO elementVO : elementVOS) { + elementVO.setSel(selectAllCheckBox.isSelected()); + } + } + + @ActionMethod("handlerAuthority") + private void handlerAuthority() throws FlowException { + groupAuthorityDialog.show((StackPane) viewFlowContext.getRegisteredObject("rootPane")); + ProcessChain.create() + .addSupplierInExecutor(() -> Request.connector(GroupFeign.class).getAuthorityMenuElementAll(groupId)) + .addConsumerInPlatformThread(rel -> buildMenuTree(rel)).onException(e -> e.printStackTrace()) + .run(); + } + + @ActionMethod("cancelUser") + private void cancelUser() throws FlowException { + groupUserDialog.close(); + } + + @ActionMethod("modifiyUsers") + private void modifiyUsers() throws FlowException { + + Set ls = new HashSet<>(); + Set ms = new HashSet<>(); + + for (User user : memberChipView.getChips()) { + ms.add(user.getId()); + } + for (User user : leaderChipView.getChips()) { + ls.add(user.getId()); + } + + Map parmMap = new HashMap<>(); + parmMap.put("members", ms.toString()); + parmMap.put("leaders", ls.toString()); + + ProcessChain.create() + .addSupplierInExecutor(() -> Request.connector(GroupFeign.class).modifiyUsers(groupId, parmMap)) + .addConsumerInPlatformThread(rel -> { + if (rel >= 0) { + groupUserDialog.close(); + } + }).onException(e -> e.printStackTrace()) + .run(); + } + + @ActionMethod("handlerUser") + private void handlerUser() { + ProcessChain.create() + .addRunnableInPlatformThread(() -> { + leaderChipView.getChips().clear(); + leaderChipView.getSuggestions().clear(); + memberChipView.getChips().clear(); + memberChipView.getSuggestions().clear(); + }) + .addSupplierInExecutor(() -> Request.connector(GroupFeign.class).getUsers(groupId)) + .addConsumerInPlatformThread(rel -> { + leaderChipView.getChips().addAll(rel.getLeaders()); + leaderChipView.getSuggestions().addAll(rel.getUsers()); + memberChipView.getChips().addAll(rel.getMembers()); + memberChipView.getSuggestions().addAll(rel.getUsers()); + }).withFinal(() -> groupUserDialog.show((StackPane) viewFlowContext.getRegisteredObject("rootPane"))) + .onException(e -> e.printStackTrace()).run(); + + } + @OnEvent("test-message") + private void onNewChatMessage(Event e) { + System.err.println(this.getClass() + "\t" + e.getContent()); + } + +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/grouptype/GroupTypeManagementController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/grouptype/GroupTypeManagementController.java new file mode 100644 index 0000000..e9ea7d6 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/grouptype/GroupTypeManagementController.java @@ -0,0 +1,309 @@ +package com.epri.fx.client.gui.uicomponents.admin.grouptype; + +import com.epri.fx.client.model.GroupTypeDataModel; +import com.epri.fx.client.request.Request; +import com.epri.fx.client.request.feign.admin.GroupTypeFeign; +import com.epri.fx.client.request.feign.admin.UserFeign; +import com.epri.fx.client.store.ApplicatonStore; +import com.epri.fx.client.utils.Pinyin4jUtil; +import com.epri.fx.server.vo.GroupTypeVO; +import com.jfoenix.controls.*; +import com.jfoenix.svg.SVGGlyphLoader; +import io.datafx.controller.ViewController; +import io.datafx.controller.flow.action.ActionMethod; +import io.datafx.controller.flow.action.ActionTrigger; +import io.datafx.controller.flow.context.FXMLViewFlowContext; +import io.datafx.controller.flow.context.ViewFlowContext; +import io.datafx.core.concurrent.ProcessChain; +import javafx.collections.transformation.FilteredList; +import javafx.fxml.FXML; +import javafx.geometry.Pos; +import javafx.scene.control.*; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.layout.HBox; +import javafx.scene.layout.StackPane; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.util.Callback; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import java.util.Date; + + +/** + * @description: + * @className: RoleRightsManagement + * @author: liwen + * @date: 2020/7/12 01:23 + */ +@ViewController(value = "/fxml/admin/groupType/group_type_management.fxml", title = "角色类型管理") +public class GroupTypeManagementController { + + + @FXMLViewFlowContext + private ViewFlowContext viewFlowContext; + + @FXML + private StackPane rootPane; + @FXML + private JFXProgressBar progressBar; + @FXML + private JFXDialog dialog; + @FXML + private Label title; + @FXML + private JFXButton searchButton; + @FXML + @ActionTrigger("createDialog") + private JFXButton addButton; + @FXML + @ActionTrigger("closeDialog") + private JFXButton cancelButton; + @FXML + @ActionTrigger("createGroupType") + private JFXButton saveButton; + @FXML + @ActionTrigger("updateGroupType") + private JFXButton updateButton; + @FXML + private JFXTextField searchField; + @FXML + private JFXTextField nameTextField; + @FXML + private JFXTextField codeTextField; + @FXML + private JFXTextArea descriptionTextArea; + @FXML + private TableView tableView; + @FXML + private TableColumn serialNumberColumn; + @FXML + private TableColumn codeColumn; + @FXML + private TableColumn nameColumn; + @FXML + private TableColumn descriptionColumn; + @FXML + private TableColumn updTimeColumn; + @FXML + private TableColumn updHostColumn; + @FXML + private TableColumn operatingColumn; + @Inject + private GroupTypeDataModel groupTypeDataModel; + + @PostConstruct + private void init() { + + progressBar.visibleProperty().bind(dialog.disableProperty()); + progressBar.managedProperty().bind(progressBar.visibleProperty()); + updateButton.visibleProperty().bind(saveButton.visibleProperty().not()); + updateButton.managedProperty().bind(updateButton.visibleProperty()); + cancelButton.disableProperty().bind(saveButton.disableProperty().or(updateButton.disableProperty())); + + serialNumberColumn.setCellFactory((col) -> { + TableCell cell = new TableCell() { + @Override + public void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + this.setText(null); + this.setGraphic(null); + + if (!empty) { + int rowIndex = this.getIndex() + 1; + this.setText(String.valueOf(rowIndex)); + } + } + }; + return cell; + }); + + nameColumn.setCellValueFactory(new PropertyValueFactory<>("name")); + codeColumn.setCellValueFactory(new PropertyValueFactory<>("code")); + descriptionColumn.setCellValueFactory(new PropertyValueFactory<>("description")); + updTimeColumn.setCellValueFactory(new PropertyValueFactory<>("updTime")); + updHostColumn.setCellValueFactory(new PropertyValueFactory<>("updHost")); + + Callback, TableCell> cellFactory = new Callback, TableCell>() { + @Override + public TableCell call(TableColumn param) { + + final TableCell cell = new TableCell() { + + private final ToggleButton editBut = new ToggleButton(); + private final ToggleButton delBut = new ToggleButton(); + + { + + + editBut.getStyleClass().add("left-pill"); + delBut.getStyleClass().add("right-pill"); + + try { + editBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".create-outline")); + delBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".trash-outline")); + } catch (Exception e) { + e.printStackTrace(); + } + + editBut.setOnMouseClicked(event -> { + + tableView.getSelectionModel().select(getIndex()); + updateDialog(); + }); + delBut.setOnMouseClicked(event -> { + tableView.getSelectionModel().select(getIndex()); + delete(); + }); + } + + @Override + protected void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + if (empty) { + setGraphic(null); + } else { + HBox hBox = new HBox(editBut, delBut); + hBox.setAlignment(Pos.CENTER); + hBox.setSpacing(0); + setGraphic(hBox); + } + } + }; + return cell; + } + }; + + operatingColumn.setCellFactory(cellFactory); + + FilteredList filteredData = new FilteredList<>(groupTypeDataModel.getGroupTypes(), p -> true); + tableView.setItems(filteredData); + searchField.textProperty().addListener((o, oldVal, newVal) -> { + filteredData.setPredicate(elementProp -> { + if (newVal == null || newVal.isEmpty()) { + return true; + } + String val = Pinyin4jUtil.toPinYinLowercase(newVal); + return Pinyin4jUtil.toPinYinLowercase(elementProp.getName()).contains(val) + || Pinyin4jUtil.toPinYinLowercase(elementProp.getCode()).contains(val); + }); + }); + + groupTypeDataModel.selectedIndexProperty().bind(tableView.getSelectionModel().selectedIndexProperty()); + + initData(); + } + + private void initData() { + loadingTableData(); + } + + private void loadingTableData() { + ProcessChain.create() + .addSupplierInExecutor(() -> Request.connector(GroupTypeFeign.class).getAllGroupTypes()) + .addConsumerInPlatformThread(rel -> { + groupTypeDataModel.getGroupTypes().clear(); + groupTypeDataModel.getGroupTypes().addAll(rel);}) + .run(); + } + + @ActionMethod("closeDialog") + private void closeDialog() { + dialog.close(); + } + + @ActionMethod("createDialog") + private void createDialog() { + title.setText("新建"); + codeTextField.setText(""); + nameTextField.setText(""); + descriptionTextArea.setText(""); + saveButton.setVisible(true); + dialog.show(rootPane); + } + + @ActionMethod("createGroupType") + private void createGroupType() { + + GroupTypeVO groupTypeVO = new GroupTypeVO(); + groupTypeVO.setCode(codeTextField.getText()); + groupTypeVO.setName(nameTextField.getText()); + groupTypeVO.setDescription(descriptionTextArea.getText()); + + ProcessChain.create().addRunnableInPlatformThread(() -> dialog.setDisable(true)) + .addSupplierInExecutor(() -> Request.connector(GroupTypeFeign.class).addGroupType(groupTypeVO)) + .addConsumerInPlatformThread(rel -> { + if (rel >=0) { + loadingTableData(); + } + }).withFinal(() -> { + dialog.setDisable(false); + dialog.close(); + }) + .run(); + + } + + @ActionMethod("updateGroupType") + private void updateGroupType() { + GroupTypeVO groupTypeVO = new GroupTypeVO(); + groupTypeVO.setId((groupTypeDataModel.getGroupTypes().get(groupTypeDataModel.getSelectedIndex())).getId()); + groupTypeVO.setCode(codeTextField.getText()); + groupTypeVO.setName(nameTextField.getText()); + groupTypeVO.setDescription(descriptionTextArea.getText()); + + ProcessChain.create() + .addRunnableInPlatformThread(() -> dialog.setDisable(true)) + .addSupplierInExecutor(() -> Request.connector(GroupTypeFeign.class).updateGroupType(groupTypeVO)) + .addConsumerInPlatformThread(rel -> { + if (rel > -0) { + loadingTableData(); + } + }).withFinal(() -> { + dialog.setDisable(false); + dialog.close(); + }) + .run(); + } + + private void delete() { + GroupTypeVO groupTypeVO = groupTypeDataModel.getGroupTypes().get(groupTypeDataModel.getSelectedIndex()); + + JFXAlert alert = new JFXAlert((Stage) rootPane.getScene().getWindow()); + alert.initModality(Modality.APPLICATION_MODAL); + alert.setOverlayClose(false); + JFXDialogLayout layout = new JFXDialogLayout(); + layout.setHeading(new Label("消息提示")); + layout.setBody(new Label("确实删除【" + groupTypeVO.getName() + "】吗?")); + JFXButton closeButton = new JFXButton("取消"); + closeButton.setOnAction(event -> alert.hideWithAnimation()); + JFXButton determineButton = new JFXButton("确定"); + determineButton.setOnAction(event -> { + alert.hideWithAnimation(); + ProcessChain.create() + .addSupplierInExecutor(() -> Request.connector(GroupTypeFeign.class).deleteGroupTypes(groupTypeVO.getId())) + .addConsumerInPlatformThread(result -> { + if (result >= 0) { + groupTypeDataModel.getGroupTypes().remove(groupTypeDataModel.getSelectedIndex()); + } + }).onException(e -> e.printStackTrace()).run(); + }); + layout.setActions(closeButton, determineButton); + alert.setContent(layout); + alert.show(); + + } + + private void updateDialog() { + title.setText("编辑"); + saveButton.setVisible(false); + GroupTypeVO groupTypeVO = groupTypeDataModel.getGroupTypes().get(groupTypeDataModel.getSelectedIndex()); + codeTextField.setText(groupTypeVO.getCode()); + nameTextField.setText(groupTypeVO.getName()); + descriptionTextArea.setText(groupTypeVO.getDescription()); + dialog.show(rootPane); + } + + +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/menu/MenuManagementController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/menu/MenuManagementController.java new file mode 100644 index 0000000..59c68ff --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/menu/MenuManagementController.java @@ -0,0 +1,693 @@ +package com.epri.fx.client.gui.uicomponents.admin.menu; + +import com.epri.fx.client.gui.uicomponents.control.FilterableTreeItem; +import com.epri.fx.client.gui.uicomponents.control.TreeItemPredicate; +import com.epri.fx.client.model.MenuDataModel; +import com.epri.fx.client.request.Request; +import com.epri.fx.client.request.feign.admin.ElementFeign; +import com.epri.fx.client.request.feign.admin.MenuFeign; +import com.epri.fx.client.request.feign.admin.UserFeign; +import com.epri.fx.client.store.ApplicatonStore; +import com.epri.fx.client.utils.Pinyin4jUtil; +import com.epri.fx.server.entity.Element; +import com.epri.fx.server.msg.TableResultResponse; +import com.epri.fx.server.vo.ElementVO; +import com.epri.fx.server.vo.MenuVO; +import com.jfoenix.controls.*; +import com.jfoenix.svg.SVGGlyphLoader; +import io.datafx.controller.ViewController; +import io.datafx.controller.flow.action.ActionMethod; +import io.datafx.controller.flow.action.ActionTrigger; +import io.datafx.core.concurrent.ProcessChain; +import io.datafx.eventsystem.Event; +import io.datafx.eventsystem.OnEvent; +import javafx.beans.binding.Bindings; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.collections.transformation.FilteredList; +import javafx.fxml.FXML; +import javafx.geometry.Pos; +import javafx.scene.control.*; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.util.Callback; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @description: + * @className: UserManagement + * @author: liwen + * @date: 2020/6/30 22:37 + */ +@ViewController(value = "/fxml/admin/menu/menu_management.fxml", title = "菜单管理") +public class MenuManagementController { + + private static final String[] METHOD_OPTIONS = {"GET", "POST", "PUT", "DELETE"}; + private static final String[] TYPE_OPTIONS = {"uri", "button"}; + + @FXML + private StackPane rootPane; + @FXML + private VBox infoPane; + @FXML + private TableView tableView; + @FXML + private TreeView treeView; + @FXML + private VBox treePane; + @FXML + private JFXSpinner treeViewSpinner; + @FXML + private JFXTextField treeSearchTextField; + @FXML + private JFXProgressBar elementProgressBar; + //menu + @FXML + private JFXTextField titleTextField; + @FXML + private JFXTextField codeTextField; + @FXML + private JFXTextField orderNumTextField; + @FXML + private JFXTextField parentIdTextField; + @FXML + private JFXTextField iconTextField; + @FXML + private JFXTextArea descriptionTextAre; + @FXML + private JFXTextField hrefTextFeild; + + //element + @FXML + private VBox elementPane; + @FXML + private JFXTextField elementCodeTextField; + @FXML + private JFXComboBox elementTypeComboBox; + @FXML + private JFXTextField elementNameTextField; + @FXML + private JFXTextField elementUriTextField; + @FXML + private JFXComboBox elementMethodComBox; + @FXML + private JFXTextArea elementDesTextAre; + + + @FXML + @ActionTrigger("updateMenu") + private JFXButton updateButton; + @FXML + @ActionTrigger("saveMenu") + private JFXButton saveButton; + @FXML + private JFXButton cancelButton; + @FXML + @ActionTrigger("addElement") + private JFXButton addElement; + @FXML + @ActionTrigger("addMenu") + private ToggleButton addButton; + @FXML + @ActionTrigger("editMenu") + private ToggleButton editButton; + @FXML + @ActionTrigger("deleteMenu") + private ToggleButton deleteButton; + @FXML + private ButtonBar buttonBar; + @FXML + private GridPane gridPane; + + @FXML + @ActionTrigger("cancelElementDialog") + private JFXButton cancelElementButton; + @FXML + @ActionTrigger("upeateElement") + private JFXButton updateElementButton; + @FXML + @ActionTrigger("createElement") + private JFXButton saveElementButton; + @FXML + private JFXTextField elementfilterField; + + @FXML + private TableColumn serialNumberColumn; + @FXML + private TableColumn codeColumn; + @FXML + private TableColumn typeColumn; + @FXML + private TableColumn nameColumn; + @FXML + private TableColumn addressColumn; + @FXML + private TableColumn requestTypeColumn; + @FXML + private TableColumn descriptionColumn; + @FXML + private TableColumn operateColumn; + @FXML + private JFXDialog dialog; + + + @Inject + private MenuDataModel menuDataModel; + + + @PostConstruct + private void init() { + final ToggleGroup group = new ToggleGroup(); + addButton.setToggleGroup(group); + editButton.setToggleGroup(group); + deleteButton.setToggleGroup(group); + + try { + addButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".add-circle-outline")); + editButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".create-outline")); + deleteButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".trash-outline")); + } catch (Exception e) { + e.printStackTrace(); + } + + elementTypeComboBox.getItems().addAll(TYPE_OPTIONS); + elementMethodComBox.getItems().addAll(METHOD_OPTIONS); + + elementProgressBar.visibleProperty().bind(updateElementButton.disableProperty().or(saveElementButton.disableProperty())); + elementProgressBar.managedProperty().bind(elementProgressBar.visibleProperty()); + + updateElementButton.visibleProperty().bind(saveElementButton.visibleProperty().not()); + updateElementButton.managedProperty().bind(updateElementButton.visibleProperty()); + cancelElementButton.disableProperty().bind(saveElementButton.disableProperty().or(updateElementButton.disableProperty())); + + buttonBar.visibleProperty().bind(infoPane.disableProperty().not()); + buttonBar.managedProperty().bind(buttonBar.visibleProperty()); + saveButton.managedProperty().bind(saveButton.visibleProperty()); + updateButton.visibleProperty().bind(saveButton.visibleProperty().not()); + updateButton.managedProperty().bind(updateButton.visibleProperty()); + + serialNumberColumn.setCellFactory((col) -> { + TableCell cell = new TableCell() { + @Override + public void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + this.setText(null); + this.setGraphic(null); + + if (!empty) { + int rowIndex = this.getIndex() + 1; + this.setText(String.valueOf(rowIndex)); + } + } + }; + return cell; + }); + codeColumn.setCellValueFactory(new PropertyValueFactory<>("code")); + nameColumn.setCellValueFactory(new PropertyValueFactory<>("name")); + typeColumn.setCellValueFactory(new PropertyValueFactory<>("type")); + addressColumn.setCellValueFactory(new PropertyValueFactory<>("uri")); + requestTypeColumn.setCellValueFactory(new PropertyValueFactory<>("method")); + descriptionColumn.setCellValueFactory(new PropertyValueFactory<>("description")); + addOperateButtonToTable(); + menuDataModel.selectedElementIndexProperty().bind(tableView.getSelectionModel().selectedIndexProperty()); + FilteredList filteredData = new FilteredList<>(menuDataModel.getElementVOS(), p -> true); + tableView.setItems(filteredData); + elementfilterField.textProperty().addListener((o, oldVal, newVal) -> { + filteredData.setPredicate(elementProp -> { + if (newVal == null || newVal.isEmpty()) { + return true; + } + String val = Pinyin4jUtil.toPinYinLowercase(newVal); + return Pinyin4jUtil.toPinYinLowercase(elementProp.getName()).contains(val) + || elementProp.getMethod().toLowerCase().contains(val) + || elementProp.getType().toLowerCase().contains(val); + }); + }); + + + treeViewSpinner.visibleProperty().bind(treePane.disableProperty()); + gridPane.disableProperty().bind(buttonBar.visibleProperty().not()); + treeView.setCellFactory(new Callback() { + @Override + public TreeCell call(TreeView param) { + return new TreeCell() { + @Override + protected void updateItem(MenuVO menu, boolean empty) { + super.updateItem(menu, empty); + if (!empty && menu != null) { + setText(menu.getTitle()); + } else { + setText(null); + } + } + }; + } + }); + + parentIdTextField.setDisable(true); + + cancelButton.setOnAction(event -> { + infoPane.setDisable(true); + }); + + + treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener>() { + @Override + public void changed(ObservableValue> observable, TreeItem oldValue, TreeItem newValue) { + + updateMenuInfo(newValue); + } + }); + + + initTreeData(); + + + } + + private void updateMenuInfo(TreeItem newValue) { + infoPane.setDisable(true); + + if (newValue == null) { + return; + } + MenuVO menuVO = newValue.getValue(); + menuDataModel.setSelectMenuVO(menuVO); + + if (newValue.isLeaf()) { + elementPane.setVisible(true); + elementPane.setManaged(true); + updateMenuElement(); + } else { + elementPane.setVisible(false); + elementPane.setManaged(false); + menuDataModel.getElementVOS().clear(); + } + + codeTextField.setText(menuVO.getCode()); + orderNumTextField.setText(menuVO.getOrderNum() + ""); + titleTextField.setText(menuVO.getTitle()); + parentIdTextField.setText(menuVO.getParentId() + ""); + iconTextField.setText(menuVO.getIcon()); + hrefTextFeild.setText(menuVO.getHref()); + descriptionTextAre.setText(menuVO.getDescription()); + } + + private void updateMenuElement() { + MenuVO menuVO = menuDataModel.getSelectMenuVO(); + ProcessChain.create() + .addSupplierInExecutor(() -> { + TableResultResponse tableResultResponse = Request.connector(ElementFeign.class).getMenuElementList(menuVO.getId()); + List elementList = tableResultResponse.getDatas(); + List elementVOList = new ArrayList<>(); + + elementList.forEach(element -> { + elementVOList.add(new ElementVO(element.getId(), element.getCode(), element.getType(), element.getName(), element.getUri(), element.getMenuId(), element.getParentId(), element.getPath(), element.getMethod(), element.getDescription())); + }); + return elementVOList; + }) + .addConsumerInPlatformThread(rel -> { + menuVO.getElementVOS().clear(); + menuVO.getElementVOS().addAll(rel); + menuDataModel.getElementVOS().clear(); + menuDataModel.getElementVOS().addAll(rel); + }).onException(e -> e.printStackTrace()) + .run(); + } + + + private void setupCellValueFactory(JFXTreeTableColumn column, Function> mapper) { + column.setCellValueFactory((TreeTableColumn.CellDataFeatures param) -> { + if (column.validateValue(param)) { + return mapper.apply(param.getValue().getValue()); + } else { + return column.getComputedValue(param); + } + }); + } + + private void initTreeData() { + ProcessChain.create().addRunnableInPlatformThread(() -> treePane.setDisable(true)) + .addSupplierInExecutor(() -> Request.connector(MenuFeign.class).getMenuAll()) + .addConsumerInPlatformThread(rel -> { + buildMenuTree(rel); + }).onException(e -> e.printStackTrace()).withFinal(() -> treePane.setDisable(false)).run(); + } + + + private void buildMenuTree(List menuList) { + + MenuVO rootMenu = menuList.stream().min(Comparator.comparing(MenuVO::getParentId)).get(); + Map> map = menuList.stream().collect(Collectors.groupingBy(MenuVO::getParentId)); + map.remove(rootMenu.getParentId()); + + FilterableTreeItem rootNode = new FilterableTreeItem(rootMenu); + treeView.setRoot(rootNode); + treeView.setShowRoot(false); + addChildrenNode(rootNode, map); + rootNode.predicateProperty().bind(Bindings.createObjectBinding(() -> { + if (treeSearchTextField.getText() == null || treeSearchTextField.getText().isEmpty()) { + return null; + } + return TreeItemPredicate.create(actor -> { + String searchText = Pinyin4jUtil.toPinYinLowercase(treeSearchTextField.getText()); + String itemText = Pinyin4jUtil.toPinYinLowercase(actor.toString()); + return itemText.contains(searchText); + }); + }, treeSearchTextField.textProperty())); + rootNode.setExpanded(true); + treeView.getSelectionModel().select(rootNode); + + + } + + private void addChildrenNode(FilterableTreeItem parentNode, Map> map) { + + List childrenList = map.get(parentNode.getValue().getId()); + + if (childrenList != null) { + + for (MenuVO menu : childrenList) { + + FilterableTreeItem clildrenNode = new FilterableTreeItem<>(menu); + parentNode.getInternalChildren().add(clildrenNode); + + addChildrenNode(clildrenNode, map); + } + } + + } + + + private void addOperateButtonToTable() { + + Callback, TableCell> cellFactory = new Callback, TableCell>() { + @Override + public TableCell call(TableColumn param) { + + final TableCell cell = new TableCell() { + + private final ToggleButton editBut = new ToggleButton(); + private final ToggleButton delBut = new ToggleButton(); + + { + + + editBut.getStyleClass().add("left-pill"); + delBut.getStyleClass().add("right-pill"); + + try { + editBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".create-outline")); + delBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".trash-outline")); + } catch (Exception e) { + e.printStackTrace(); + } + + editBut.setOnMouseClicked(event -> { + tableView.getSelectionModel().select(getIndex()); + editElement(); + }); + delBut.setOnMouseClicked(event -> { + tableView.getSelectionModel().select(getIndex()); + deleteElement(); + }); + } + + @Override + protected void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + if (empty) { + setGraphic(null); + } else { + HBox hBox = new HBox(editBut, delBut); + hBox.setAlignment(Pos.CENTER); + hBox.setSpacing(0); + setGraphic(hBox); + } + } + }; + return cell; + } + }; + + operateColumn.setCellFactory(cellFactory); + + + } + + @ActionMethod("addMenu") + private void addMenu() { + + infoPane.setDisable(false); + saveButton.setVisible(true); + + codeTextField.setText(""); + orderNumTextField.setText(""); + titleTextField.setText(""); + parentIdTextField.setText(menuDataModel.getSelectMenuVO().getId() + ""); + iconTextField.setText(""); + hrefTextFeild.setText(""); + descriptionTextAre.setText(""); + } + + @ActionMethod("saveMenu") + private void saveMenu() { + + MenuVO menuVO = new MenuVO(); + menuVO.setTitle(titleTextField.getText()); + menuVO.setCode(codeTextField.getText()); + menuVO.setIcon(iconTextField.getText()); + menuVO.setHref(hrefTextFeild.getText()); + menuVO.setOrderNum(Integer.parseInt(orderNumTextField.getText())); + menuVO.setParentId(Integer.parseInt(parentIdTextField.getText())); + menuVO.setDescription(descriptionTextAre.getText()); + + ProcessChain.create() + .addRunnableInPlatformThread(() -> infoPane.setDisable(true)) + .addSupplierInExecutor(() -> Request.connector(MenuFeign.class).addMenu(menuVO)) + .addConsumerInPlatformThread(rel -> { + if (rel == 1) { + initTreeData(); + } + }) + .withFinal(() -> { + infoPane.setDisable(false); + treeView.getRoot().setExpanded(true); + + }).onException(e -> e.printStackTrace()) + .run(); + } + + @ActionMethod("editMenu") + private void editMenu() { + + infoPane.setDisable(false); + saveButton.setVisible(false); + + } + + @ActionMethod("updateMenu") + private void updateMenu() { + + MenuVO menuVO = menuDataModel.getSelectMenuVO(); + menuVO.setTitle(titleTextField.getText()); + menuVO.setCode(codeTextField.getText()); + menuVO.setIcon(iconTextField.getText()); + menuVO.setHref(hrefTextFeild.getText()); + menuVO.setOrderNum(Integer.parseInt(orderNumTextField.getText())); + menuVO.setParentId(Integer.parseInt(parentIdTextField.getText())); + menuVO.setDescription(descriptionTextAre.getText()); + + ProcessChain.create() + .addRunnableInPlatformThread(() -> infoPane.setDisable(true)) + .addSupplierInExecutor(() -> Request.connector(MenuFeign.class).updateMenu(menuVO)) + .addConsumerInPlatformThread(rel -> { + if (rel >= 0) { + initTreeData(); + } + }).withFinal(() -> { + infoPane.setDisable(false); + treeView.getRoot().setExpanded(true); + + }).onException(e -> e.printStackTrace()) + .run(); + } + + @ActionMethod("deleteMenu") + private void deleteMenu() { + + JFXAlert alert = new JFXAlert((Stage) rootPane.getScene().getWindow()); + alert.initModality(Modality.APPLICATION_MODAL); + alert.setOverlayClose(false); + JFXDialogLayout layout = new JFXDialogLayout(); + layout.setHeading(new Label("消息提示")); + layout.setBody(new Label("确实删除【" + menuDataModel.getSelectMenuVO().getTitle() + "】吗?")); + JFXButton closeButton = new JFXButton("取消"); + closeButton.setOnAction(event -> alert.hideWithAnimation()); + JFXButton determineButton = new JFXButton("确定"); + determineButton.setOnAction(event -> { + alert.hideWithAnimation(); + ProcessChain.create() + .addSupplierInExecutor(() -> Request.connector(MenuFeign.class).deleteMenu(menuDataModel.getSelectMenuVO())) + .addConsumerInPlatformThread(rel -> { + if (rel >= 0) { + initTreeData(); + } + }).withFinal(() -> { + treeView.getRoot().setExpanded(true); + + }).onException(e -> e.printStackTrace()) + .run(); + }); + layout.setActions(closeButton, determineButton); + alert.setContent(layout); + alert.show(); + + } + + + @ActionMethod("addElement") + private void addElement() { + + elementCodeTextField.setText(""); + elementTypeComboBox.getSelectionModel().select(null); + elementMethodComBox.getSelectionModel().select(null); + elementNameTextField.setText(""); + elementUriTextField.setText(""); + elementCodeTextField.setText(""); + elementDesTextAre.setText(""); + + + saveElementButton.setManaged(true); + saveElementButton.setVisible(true); + dialog.setTransitionType(JFXDialog.DialogTransition.TOP); + dialog.show(rootPane); + } + + @ActionMethod("createElement") + private void createElement() { + + MenuVO menuVO = menuDataModel.getSelectMenuVO(); + Element newElect = new Element(); + + newElect.setCode(elementCodeTextField.getText()); + newElect.setMenuId(menuVO.getId() + ""); + newElect.setName(elementNameTextField.getText()); + newElect.setUri(elementUriTextField.getText()); + newElect.setType(elementTypeComboBox.getSelectionModel().getSelectedItem()); + newElect.setMethod(elementMethodComBox.getSelectionModel().getSelectedItem()); + newElect.setDescription(elementDesTextAre.getText()); + + ProcessChain.create() + .addRunnableInPlatformThread(() -> { + saveElementButton.setDisable(true); + }) + .addSupplierInExecutor(() -> Request.connector(ElementFeign.class).addElement(newElect)) + .addConsumerInPlatformThread(rel -> { + if (rel >= 0) { + updateMenuElement(); + } + }) + .withFinal(() -> { + saveElementButton.setDisable(false); + dialog.close(); + }).onException(e -> e.printStackTrace()) + .run(); + + } + + @ActionMethod("upeateElement") + private void updateElement() { + + MenuVO menuVO = menuDataModel.getSelectMenuVO(); + Element newElect = new Element(); + newElect.setId(menuDataModel.getElementVOS().get(menuDataModel.getSelectedElementIndex()).getId()); + newElect.setCode(elementCodeTextField.getText()); + newElect.setMenuId(menuVO.getId() + ""); + newElect.setName(elementNameTextField.getText()); + newElect.setUri(elementUriTextField.getText()); + newElect.setType(elementTypeComboBox.getSelectionModel().getSelectedItem()); + newElect.setMethod(elementMethodComBox.getSelectionModel().getSelectedItem()); + newElect.setDescription(elementDesTextAre.getText()); + + ProcessChain.create() + .addRunnableInPlatformThread(() -> { + updateElementButton.setDisable(true); + }) + .addSupplierInExecutor(() -> Request.connector(ElementFeign.class).updateElement(newElect)) + .addConsumerInPlatformThread(rel -> { + if (rel >= 0) { + updateMenuElement(); + + } + }) + .withFinal(() -> { + updateElementButton.setDisable(false); + dialog.close(); + }).onException(e -> e.printStackTrace()) + .run(); + + } + + + private void editElement() { + + ElementVO elementVO = menuDataModel.getElementVOS().get(menuDataModel.getSelectedElementIndex()); + elementCodeTextField.setText(elementVO.getCode()); + elementTypeComboBox.getSelectionModel().select(elementVO.getType()); + elementMethodComBox.getSelectionModel().select(elementVO.getMethod()); + elementNameTextField.setText(elementVO.getName()); + elementUriTextField.setText(elementVO.getUri()); + elementDesTextAre.setText(elementVO.getDescription()); + + saveElementButton.setManaged(false); + saveElementButton.setVisible(false); + dialog.setTransitionType(JFXDialog.DialogTransition.TOP); + dialog.show(rootPane); + } + + private void deleteElement() { + + ElementVO elementVO = menuDataModel.getElementVOS().get(menuDataModel.getSelectedElementIndex()); + + ProcessChain.create() + .addRunnableInPlatformThread(() -> { + }) + .addSupplierInExecutor(() -> Request.connector(ElementFeign.class).deleteElement(elementVO.getId())) + .addConsumerInPlatformThread(rel -> { + + if (rel >= 0) { + updateMenuElement(); + } + }) + .withFinal(() -> { + + }).onException(e -> e.printStackTrace()) + .run(); + + } + + + @ActionMethod("cancelElementDialog") + private void cancelElementDialog() { + dialog.close(); + } + + @OnEvent("test-message") + private void onNewChatMessage(Event e) { + System.err.println(this.getClass() + "\t" + e.getContent()); + } +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/user/UserManagementController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/user/UserManagementController.java new file mode 100644 index 0000000..8b85c88 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/user/UserManagementController.java @@ -0,0 +1,380 @@ +package com.epri.fx.client.gui.uicomponents.admin.user; + +import com.epri.fx.client.gui.feature.FeatureResourceConsumer; +import com.epri.fx.client.gui.feature.HideByFeature; +import com.epri.fx.client.gui.uicomponents.admin.user.components.UserAddController; +import com.epri.fx.client.gui.uicomponents.admin.user.components.UserEditController; +import com.epri.fx.client.model.UserDataModel; +import com.epri.fx.client.request.Request; +import com.epri.fx.client.request.feign.admin.UserFeign; +import com.epri.fx.client.store.ApplicatonStore; +import com.epri.fx.client.utils.Pinyin4jUtil; +import com.epri.fx.server.entity.User; +import com.epri.fx.server.util.DateUtils; +import com.epri.fx.server.vo.UserVO; +import com.jfoenix.controls.JFXAlert; +import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXDialogLayout; +import com.jfoenix.svg.SVGGlyph; +import com.jfoenix.svg.SVGGlyphLoader; +import io.datafx.controller.ViewController; +import io.datafx.controller.flow.FlowException; +import io.datafx.controller.flow.action.ActionMethod; +import io.datafx.controller.flow.action.ActionTrigger; +import io.datafx.controller.flow.context.ActionHandler; +import io.datafx.controller.flow.context.FlowActionHandler; +import io.datafx.controller.util.VetoException; +import io.datafx.core.concurrent.ProcessChain; +import javafx.collections.transformation.FilteredList; +import javafx.fxml.FXML; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.*; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.layout.HBox; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.util.Callback; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.inject.Inject; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @description: + * @className: UserManagementController + * @author: liwen + * @date: 2020/3/4 21:05 + */ +@ViewController(value = "/fxml/admin/user/user_management.fxml", title = "用户管理") +public class UserManagementController { + + public static final String CONTENT_PANE = "ContentPane"; + + + @FXML + private StackPane root; + @FXML + private VBox centPane; + @FXML + private StackPane spinnerPane; + @FXML + private TextField searchField; + @FXML + private TextField userNameTextField; + @FXML + private TextField accountTextField; + @FXML + private TextField pwdTextField; + @FXML + private TextArea descTextArea; + @FXML + private ComboBox genderCombobox; + @FXML + @ActionTrigger("createUser") + @HideByFeature("userManager:btn_add") + private Button addBut; + @FXML + @ActionTrigger("accept") + private Button acceptButton; + @FXML + @ActionTrigger("cancel") + private Button cancelButton; + @FXML + @ActionTrigger("search") + private Button searchBut; + + + @FXML + private Pagination pagination; + + + @FXML + private TableView tableView; + @FXML + private TableColumn serialNumberColumn; + @FXML + private TableColumn nameColumn; + @FXML + private TableColumn accountColumn; + @FXML + private TableColumn remarksColumn; + @FXML + private TableColumn lastUpdateTimeColumn; + @FXML + private TableColumn lastUpdatedByColumn; + @FXML + private TableColumn operateColumn; + + @ActionHandler + private FlowActionHandler actionHandler; + + @Inject + private UserDataModel dataModel; + + @Inject + private FeatureResourceConsumer featureResourceConsumer; + @PostConstruct + public void init() { + featureResourceConsumer.consumeResource(this); + spinnerPane.setVisible(false); + serialNumberColumn.setCellFactory((col) -> { + TableCell cell = new TableCell() { + @Override + public void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + this.setText(null); + this.setGraphic(null); + + if (!empty) { + int rowIndex = this.getIndex() + 1; + this.setText(String.valueOf(rowIndex)); + } + } + }; + return cell; + }); + + nameColumn.setCellValueFactory(new PropertyValueFactory<>("name")); + accountColumn.setCellValueFactory(new PropertyValueFactory<>("userName")); + remarksColumn.setCellValueFactory(new PropertyValueFactory<>("description")); + lastUpdateTimeColumn.setCellValueFactory(new PropertyValueFactory<>("updTime")); + lastUpdatedByColumn.setCellValueFactory(new PropertyValueFactory<>("updUser")); + Callback, TableCell> cellFactory = new Callback, TableCell>() { + @Override + public TableCell call(TableColumn param) { + + final TableCell cell = new TableCell() { + + private final ToggleButton resetBut = new ToggleButton(); + private final ToggleButton editBut = new ToggleButton(); + private final ToggleButton delBut = new ToggleButton(); + + { + + + resetBut.setTooltip(new Tooltip("重置密码")); + resetBut.getStyleClass().add("left-pill"); + editBut.getStyleClass().add("center-pill"); + delBut.getStyleClass().add("right-pill"); + + try { + editBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".create-outline")); + resetBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".history")); + delBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".trash-outline")); + } catch (Exception e) { + e.printStackTrace(); + } + + editBut.setOnMouseClicked(event -> { + + try { + tableView.getSelectionModel().select(getIndex()); + actionHandler.navigate(UserEditController.class); + } catch (VetoException e) { + e.printStackTrace(); + } catch (FlowException e) { + e.printStackTrace(); + } + }); + delBut.setOnMouseClicked(event -> { + tableView.getSelectionModel().select(getIndex()); + delete(); + }); + resetBut.setOnMouseClicked(event -> { + tableView.getSelectionModel().select(getIndex()); + restPassword(); + }); + } + + @Override + protected void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + if (empty) { + setGraphic(null); + } else { + HBox hBox = new HBox(resetBut, editBut, delBut); + hBox.setSpacing(0); + hBox.setAlignment(Pos.CENTER); + setGraphic(hBox); + } + } + }; + return cell; + } + }; + + operateColumn.setCellFactory(cellFactory); + + FilteredList filteredData = new FilteredList<>(dataModel.getUsers(), p -> true); + tableView.setItems(filteredData); + searchField.textProperty().addListener((o, oldVal, newVal) -> { + filteredData.setPredicate(elementProp -> { + if (newVal == null || newVal.isEmpty()) { + return true; + } + String val = Pinyin4jUtil.toPinYinLowercase(newVal); + return Pinyin4jUtil.toPinYinLowercase(elementProp.getName()).contains(val) + || elementProp.getName().toLowerCase().contains(val) + || elementProp.getUserName().toLowerCase().contains(val); + }); + }); + + dataModel.selectedPersonIndexProperty().bind(tableView.getSelectionModel().selectedIndexProperty()); + pagination.pageCountProperty().bind(dataModel.pageCountProperty()); + pagination.setPageFactory(new Callback() { + @Override + public Node call(Integer param) { + showPage(param + 1); + return tableView; + } + }); + + + } + + + @ActionMethod("createUser") + private void createUser() { + + try { + actionHandler.navigate(UserAddController.class); + } catch (VetoException e) { + e.printStackTrace(); + } catch (FlowException e) { + e.printStackTrace(); + } + } + + @ActionMethod("cancel") + private void cancel() { + + } + + @ActionMethod("accept") + private void accept() { + + JFXAlert alert = new JFXAlert((Stage) root.getScene().getWindow()); + alert.initModality(Modality.APPLICATION_MODAL); + alert.setOverlayClose(false); + JFXDialogLayout layout = new JFXDialogLayout(); + + layout.setBody(new Label(userNameTextField.getText() + "\t" + accountTextField.getText() + "\t" + genderCombobox.getSelectionModel().getSelectedItem() + "\t" + descTextArea.getText())); + + alert.setContent(layout); + alert.show(); + } + + private void restPassword() { + UserVO userVO = dataModel.getUsers().get(dataModel.getSelectedPersonIndex()); + + JFXAlert alert = new JFXAlert((Stage) root.getScene().getWindow()); + alert.initModality(Modality.APPLICATION_MODAL); + alert.setOverlayClose(false); + JFXDialogLayout layout = new JFXDialogLayout(); + layout.setHeading(new Label("消息提示")); + layout.setBody(new Label("确定要重置【" + userVO.getUserName() + "】登录密码吗?")); + JFXButton closeButton = new JFXButton("取消"); + closeButton.setOnAction(event -> alert.hideWithAnimation()); + JFXButton determineButton = new JFXButton("确定"); + determineButton.setOnAction(event -> { + alert.hideWithAnimation(); + ProcessChain.create() + .addSupplierInExecutor(() -> Request.connector(UserFeign.class).restPassword(userVO.getId())) + .addConsumerInPlatformThread(result -> { + + }).onException(e -> e.printStackTrace()).run(); + }); + layout.setActions(closeButton, determineButton); + alert.setContent(layout); + alert.show(); + } + + private void delete() { + UserVO userVO = dataModel.getUsers().get(dataModel.getSelectedPersonIndex()); + + JFXAlert alert = new JFXAlert((Stage) root.getScene().getWindow()); + alert.initModality(Modality.APPLICATION_MODAL); + alert.setOverlayClose(false); + JFXDialogLayout layout = new JFXDialogLayout(); + layout.setHeading(new Label("消息提示")); + layout.setBody(new Label("确实删除【" + userVO.getUserName() + "】吗?")); + JFXButton closeButton = new JFXButton("取消"); + closeButton.setOnAction(event -> alert.hideWithAnimation()); + JFXButton determineButton = new JFXButton("确定"); + determineButton.setOnAction(event -> { + alert.hideWithAnimation(); + ProcessChain.create() + .addSupplierInExecutor(() -> Request.connector(UserFeign.class).delete(userVO.getId())) + .addConsumerInPlatformThread(result -> { + if (result.isRel()) { + dataModel.getUsers().remove(dataModel.getSelectedPersonIndex()); + } + }).onException(e -> e.printStackTrace()).run(); + }); + layout.setActions(closeButton, determineButton); + alert.setContent(layout); + alert.show(); + + } + + + private void showPage(Integer page) { + Map queryMap = new HashMap<>(); + queryMap.put("keyId", searchField.getText()); + queryMap.put("page", page); + query(queryMap); + + } + + @ActionMethod("search") + private void search() { + Map queryMap = new HashMap<>(); + queryMap.put("keyId", searchField.getText()); + query(queryMap); + + } + + private void query(Map queryMap) { + + ProcessChain.create() + .addRunnableInPlatformThread(() -> { + spinnerPane.setVisible(true); + centPane.setDisable(true); + }) + .addSupplierInExecutor(() -> Request.connector(UserFeign.class).getPageList(queryMap) + ) + .addConsumerInPlatformThread(result -> { + dataModel.getUsers().clear(); + List userList = result.getDatas(); + dataModel.setPageCount((int) result.getTotal()); + + for (User user : userList) { + dataModel.getUsers().add(new UserVO(user.getId(), user.getName(), user.getUsername(), DateUtils.format(user.getUpdTime(), DateUtils.DATE_TIME_PATTERN), user.getUpdUser(), user.getSex(), user.getDescription())); + } + }) + .withFinal(() -> { + spinnerPane.setVisible(false); + centPane.setDisable(false); + }) + .onException(e -> e.printStackTrace()) + .run(); + } + + + @PreDestroy + private void destroy() { + System.err.println("destroy " + this); + } + + + @FXML + private void test() { + System.err.println(); + } +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/user/components/UserAddController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/user/components/UserAddController.java new file mode 100644 index 0000000..1202f15 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/user/components/UserAddController.java @@ -0,0 +1,96 @@ +package com.epri.fx.client.gui.uicomponents.admin.user.components; + +import com.epri.fx.client.gui.uicomponents.admin.user.UserManagementController; +import com.epri.fx.client.model.UserDataModel; +import com.epri.fx.client.request.Request; +import com.epri.fx.client.request.feign.admin.UserFeign; +import com.epri.fx.server.entity.User; +import com.jfoenix.controls.*; +import io.datafx.controller.ViewController; +import io.datafx.controller.flow.FlowException; +import io.datafx.controller.flow.action.ActionMethod; +import io.datafx.controller.flow.action.ActionTrigger; +import io.datafx.controller.flow.action.BackAction; +import io.datafx.controller.flow.context.ActionHandler; +import io.datafx.controller.flow.context.FlowActionHandler; +import io.datafx.controller.util.VetoException; +import io.datafx.core.concurrent.ProcessChain; +import javafx.fxml.FXML; +import javafx.scene.control.Label; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; + +/** + * @description: + * @className: UserAddController + * @author: liwen + * @date: 2020/7/3 17:04 + */ + +@ViewController(value = "/fxml/admin/user/user_detailed.fxml", title = "添加用户") +public class UserAddController { + @ActionHandler + private FlowActionHandler actionHandler; + + @FXML + @BackAction + private JFXButton cancelBut; + @FXML + private Label title; + @FXML + @ActionTrigger("save") + private JFXButton saveBut; + @FXML + @ActionTrigger("update") + private JFXButton updateBut; + @FXML + private JFXTextField nameTextField; + @FXML + private JFXTextField userNameTextField; + @FXML + private JFXPasswordField pwdTextField; + @FXML + private JFXTextArea descTextArea; + @FXML + private JFXComboBox genderCombobox; + + @Inject + private UserDataModel dataModel; + + @PostConstruct + private void init() { + + + title.setText("添加用户"); + updateBut.setVisible(false); + updateBut.managedProperty().bind(updateBut.visibleProperty()); + } + + + @ActionMethod("save") + private void save() { + + User user = new User(); + user.setName(nameTextField.getText()); + user.setDescription(descTextArea.getText()); + user.setUsername(userNameTextField.getText()); + user.setPassword(pwdTextField.getText()); + user.setSex(genderCombobox.getSelectionModel().getSelectedIndex() == 0 ? "男" : "女"); + + ProcessChain.create() + .addSupplierInExecutor(() -> Request.connector(UserFeign.class).add(user)) + .addConsumerInPlatformThread(rel -> { + if (rel.isRel()) { + try { + actionHandler.navigate(UserManagementController.class); + } catch (VetoException e) { + e.printStackTrace(); + } catch (FlowException e) { + e.printStackTrace(); + } + } + }).run(); + + } +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/user/components/UserEditController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/user/components/UserEditController.java new file mode 100644 index 0000000..db9fa27 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/admin/user/components/UserEditController.java @@ -0,0 +1,115 @@ +package com.epri.fx.client.gui.uicomponents.admin.user.components; + +import com.epri.fx.client.gui.uicomponents.admin.user.UserManagementController; +import com.epri.fx.client.model.UserDataModel; +import com.epri.fx.client.request.Request; +import com.epri.fx.client.request.feign.admin.UserFeign; +import com.epri.fx.server.entity.User; +import com.epri.fx.server.vo.UserVO; +import com.jfoenix.controls.*; +import io.datafx.controller.ViewController; +import io.datafx.controller.flow.FlowException; +import io.datafx.controller.flow.action.ActionMethod; +import io.datafx.controller.flow.action.ActionTrigger; +import io.datafx.controller.flow.action.BackAction; +import io.datafx.controller.flow.context.ActionHandler; +import io.datafx.controller.flow.context.FlowActionHandler; +import io.datafx.controller.util.VetoException; +import io.datafx.core.concurrent.ProcessChain; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.fxml.FXML; +import javafx.scene.control.Label; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; + +/** + * @description: + * @className: UserAddController + * @author: liwen + * @date: 2020/7/3 17:04 + */ + +@ViewController(value = "/fxml/admin/user/user_detailed.fxml", title = "编辑用户") +public class UserEditController { + + @ActionHandler + private FlowActionHandler actionHandler; + + @FXML + @BackAction + private JFXButton cancelBut; + + @FXML + private Label title; + @FXML + private JFXButton saveBut; + @FXML + @ActionTrigger("update") + private JFXButton updateBut; + @FXML + private JFXTextField nameTextField; + @FXML + private JFXTextField userNameTextField; + @FXML + private JFXPasswordField pwdTextField; + @FXML + private JFXTextArea descTextArea; + @FXML + private JFXComboBox genderCombobox; + + @Inject + private UserDataModel dataModel; + + + @PostConstruct + private void init() { + title.setText("编辑用户"); + saveBut.managedProperty().bind(saveBut.visibleProperty()); + pwdTextField.setDisable(true); + saveBut.setVisible(false); + genderCombobox.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Number oldValue, Number newValue) { + UserVO userVO = dataModel.getUsers().get(dataModel.getSelectedPersonIndex()); + userVO.setSex(newValue.intValue() == 0 ? "男" : "女"); + } + }); + UserVO userVO = dataModel.getUsers().get(dataModel.getSelectedPersonIndex()); + + nameTextField.textProperty().bindBidirectional(userVO.nameProperty()); + userNameTextField.textProperty().bindBidirectional(userVO.userNameProperty()); + pwdTextField.textProperty().bindBidirectional(userVO.userNameProperty()); + descTextArea.textProperty().bindBidirectional(userVO.descriptionProperty()); + String sex = userVO.sexProperty().getValue(); + genderCombobox.getSelectionModel().select("男".equals(sex) ? 0 : 1); + } + + @ActionMethod("update") + private void update() { + + UserVO userVO = dataModel.getUsers().get(dataModel.getSelectedPersonIndex()); + + User user = new User(); + user.setId(userVO.getId()); + user.setName(userVO.getName()); + user.setDescription(userVO.getDescription()); + user.setUsername(userVO.getUserName()); + user.setSex(userVO.getSex()); + ProcessChain.create() + .addSupplierInExecutor(() -> Request.connector(UserFeign.class).update(user.getId(), user)) + .addConsumerInPlatformThread((rel) -> { + if (rel.isRel()) { + try { + actionHandler.navigate(UserManagementController.class); + } catch (VetoException e) { + e.printStackTrace(); + } catch (FlowException e) { + e.printStackTrace(); + } + } + }) + .run(); + } +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/BasicDataSetController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/BasicDataSetController.java new file mode 100644 index 0000000..b43b2be --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/BasicDataSetController.java @@ -0,0 +1,13 @@ +package com.epri.fx.client.gui.uicomponents.basicInfo; + +import io.datafx.controller.ViewController; + +/** + * @description: + * @className: BasicDataSetController + * @author: liwen + * @date: 2020/10/14 16:55 + */ +@ViewController(value = "/fxml/basicInfo/basic_data_set.fxml", title = "基础数据", iconPath = "") +public class BasicDataSetController { +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/CoalPriceDiffController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/CoalPriceDiffController.java new file mode 100644 index 0000000..de621da --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/CoalPriceDiffController.java @@ -0,0 +1,13 @@ +package com.epri.fx.client.gui.uicomponents.basicInfo; + +import io.datafx.controller.ViewController; + +/** + * @description: + * @className: BasicDataSetController + * @author: liwen + * @date: 2020/10/14 16:55 + */ +@ViewController(value = "/fxml/basicInfo/coal_price_difference.fxml", title = "煤价差", iconPath = "") +public class CoalPriceDiffController { +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/CurrentFreightController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/CurrentFreightController.java new file mode 100644 index 0000000..2448246 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/CurrentFreightController.java @@ -0,0 +1,13 @@ +package com.epri.fx.client.gui.uicomponents.basicInfo; + +import io.datafx.controller.ViewController; + +/** + * @description: + * @className: BasicDataSetController + * @author: liwen + * @date: 2020/10/14 16:55 + */ +@ViewController(value = "/fxml/basicInfo/current_freight.fxml", title = "现行运价", iconPath = "") +public class CurrentFreightController { +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/MainConclusionController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/MainConclusionController.java new file mode 100644 index 0000000..a947f27 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/MainConclusionController.java @@ -0,0 +1,13 @@ +package com.epri.fx.client.gui.uicomponents.basicInfo; + +import io.datafx.controller.ViewController; + +/** + * @description: + * @className: BasicDataSetController + * @author: liwen + * @date: 2020/10/14 16:55 + */ +@ViewController(value = "/fxml/basicInfo/main_conclusion.fxml", title = "主要结论", iconPath = "") +public class MainConclusionController { +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/RailwayCostController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/RailwayCostController.java new file mode 100644 index 0000000..32883d5 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/basicInfo/RailwayCostController.java @@ -0,0 +1,13 @@ +package com.epri.fx.client.gui.uicomponents.basicInfo; + +import io.datafx.controller.ViewController; + +/** + * @description: + * @className: BasicDataSetController + * @author: liwen + * @date: 2020/10/14 16:55 + */ +@ViewController(value = "/fxml/basicInfo/railway_cost.fxml", title = "铁路成本", iconPath = "") +public class RailwayCostController { +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/container/TabPaneFlowContainer.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/container/TabPaneFlowContainer.java new file mode 100644 index 0000000..ebd8d22 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/container/TabPaneFlowContainer.java @@ -0,0 +1,73 @@ +package com.epri.fx.client.gui.uicomponents.container; + +import com.jfoenix.controls.JFXTabPane; +import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; +import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView; +import io.datafx.controller.context.ViewContext; +import io.datafx.controller.flow.FlowContainer; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; + +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; + +/** + * @description: + * @className: TabPaneFlowContainer + * @author: liwen + * @date: 2020/6/24 18:09 + */ +public class TabPaneFlowContainer implements FlowContainer { + + private final JFXTabPane tabPane; + private final HashMap tabsMap = new HashMap<>(); + + + public TabPaneFlowContainer() { + this(new JFXTabPane()); + } + + public TabPaneFlowContainer(JFXTabPane tabPane) { + this.tabPane = tabPane; + this.tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.ALL_TABS); + + + } + + @Override + public void setViewContext(ViewContext context) { + + String title = context.getMetadata().getTitle(); + Class controller = context.getController().getClass(); + Tab tab = tabsMap.get(controller.getName()); + if (tab == null ) { + tab = new Tab(title); + tab.setUserData(context.getController()); + tab.setContent(context.getRootNode()); + tabPane.getTabs().add(tab); + tabsMap.put(controller.getName(), tab); + tab.setGraphic(new MaterialDesignIconView(MaterialDesignIcon.HOME)); + tab.setOnClosed(event -> { + tabsMap.remove(controller.getName()); + try { + context.destroy(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + }); + + + } + + + tabPane.getSelectionModel().select(tab); + + } + + @Override + public JFXTabPane getView() { + return tabPane; + } +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/control/FilterableCheckBoxTreeItem.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/control/FilterableCheckBoxTreeItem.java new file mode 100644 index 0000000..aae2588 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/control/FilterableCheckBoxTreeItem.java @@ -0,0 +1,76 @@ +package com.epri.fx.client.gui.uicomponents.control; + +import javafx.beans.binding.Bindings; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.collections.transformation.FilteredList; +import javafx.scene.control.CheckBoxTreeItem; +import javafx.scene.control.TreeItem; + +import java.lang.reflect.Field; + +public class FilterableCheckBoxTreeItem extends CheckBoxTreeItem { + final private ObservableList> sourceList; + private FilteredList> filteredList; + private ObjectProperty> predicate = new SimpleObjectProperty<>(); + + + public FilterableCheckBoxTreeItem(T value) { + super(value); + this.sourceList = FXCollections.observableArrayList(); + this.filteredList = new FilteredList<>(this.sourceList); + this.filteredList.predicateProperty().bind(Bindings.createObjectBinding(() -> { + return child -> { + // Set the predicate of child items to force filtering + if (child instanceof FilterableCheckBoxTreeItem) { + FilterableCheckBoxTreeItem filterableChild = (FilterableCheckBoxTreeItem) child; + filterableChild.setPredicate(this.predicate.get()); + } + // If there is no predicate, keep this tree item + if (this.predicate.get() == null) { + return true; + } + // If there are children, keep this tree item + if (child.getChildren().size() > 0) { + return true; + } + // Otherwise ask the TreeItemPredicate + return this.predicate.get().test(this, child.getValue()); + }; + }, this.predicate)); + setHiddenFieldChildren(this.filteredList); + } + + protected void setHiddenFieldChildren(ObservableList> list) { + try { + Field childrenField = TreeItem.class.getDeclaredField("children"); //$NON-NLS-1$ + childrenField.setAccessible(true); + childrenField.set(this, list); + + Field declaredField = TreeItem.class.getDeclaredField("childrenListener"); //$NON-NLS-1$ + declaredField.setAccessible(true); + list.addListener((ListChangeListener>) declaredField.get(this)); + } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException("Could not set TreeItem.children", e); //$NON-NLS-1$ + } + } + + public ObservableList> getInternalChildren() { + return this.sourceList; + } + + public void setPredicate(TreeItemPredicate predicate) { + this.predicate.set(predicate); + } + + public TreeItemPredicate getPredicate() { + return predicate.get(); + } + + public ObjectProperty> predicateProperty() { + return predicate; + } +} \ No newline at end of file diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/control/FilterableTreeItem.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/control/FilterableTreeItem.java new file mode 100644 index 0000000..e8c3e11 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/control/FilterableTreeItem.java @@ -0,0 +1,75 @@ +package com.epri.fx.client.gui.uicomponents.control; + +import javafx.beans.binding.Bindings; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.collections.transformation.FilteredList; +import javafx.scene.control.TreeItem; + +import java.lang.reflect.Field; + +public class FilterableTreeItem extends TreeItem { + final private ObservableList> sourceList; + private FilteredList> filteredList; + private ObjectProperty> predicate = new SimpleObjectProperty<>(); + + + public FilterableTreeItem(T value) { + super(value); + this.sourceList = FXCollections.observableArrayList(); + this.filteredList = new FilteredList<>(this.sourceList); + this.filteredList.predicateProperty().bind(Bindings.createObjectBinding(() -> { + return child -> { + // Set the predicate of child items to force filtering + if (child instanceof FilterableTreeItem) { + FilterableTreeItem filterableChild = (FilterableTreeItem) child; + filterableChild.setPredicate(this.predicate.get()); + } + // If there is no predicate, keep this tree item + if (this.predicate.get() == null) { + return true; + } + // If there are children, keep this tree item + if (child.getChildren().size() > 0) { + return true; + } + // Otherwise ask the TreeItemPredicate + return this.predicate.get().test(this, child.getValue()); + }; + }, this.predicate)); + setHiddenFieldChildren(this.filteredList); + } + + protected void setHiddenFieldChildren(ObservableList> list) { + try { + Field childrenField = TreeItem.class.getDeclaredField("children"); //$NON-NLS-1$ + childrenField.setAccessible(true); + childrenField.set(this, list); + + Field declaredField = TreeItem.class.getDeclaredField("childrenListener"); //$NON-NLS-1$ + declaredField.setAccessible(true); + list.addListener((ListChangeListener>) declaredField.get(this)); + } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException("Could not set TreeItem.children", e); //$NON-NLS-1$ + } + } + + public ObservableList> getInternalChildren() { + return this.sourceList; + } + + public void setPredicate(TreeItemPredicate predicate) { + this.predicate.set(predicate); + } + + public TreeItemPredicate getPredicate() { + return predicate.get(); + } + + public ObjectProperty> predicateProperty() { + return predicate; + } +} \ No newline at end of file diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/control/LFXDecorator.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/control/LFXDecorator.java new file mode 100644 index 0000000..2914d1b --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/control/LFXDecorator.java @@ -0,0 +1,653 @@ +package com.epri.fx.client.gui.uicomponents.control; + +import com.jfoenix.controls.JFXButton; +import com.jfoenix.svg.SVGGlyph; +import javafx.animation.Animation; +import javafx.animation.Interpolator; +import javafx.animation.KeyFrame; +import javafx.animation.KeyValue; +import javafx.animation.Timeline; +import javafx.application.Platform; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.geometry.BoundingBox; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.geometry.Rectangle2D; +import javafx.scene.Cursor; +import javafx.scene.Node; +import javafx.scene.control.Tooltip; +import javafx.scene.effect.DropShadow; +import javafx.scene.effect.Shadow; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.Background; +import javafx.scene.layout.BackgroundFill; +import javafx.scene.layout.Border; +import javafx.scene.layout.BorderStroke; +import javafx.scene.layout.BorderStrokeStyle; +import javafx.scene.layout.BorderWidths; +import javafx.scene.layout.CornerRadii; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import javafx.scene.text.Text; +import javafx.stage.Screen; +import javafx.stage.Stage; +import javafx.stage.StageStyle; +import javafx.stage.WindowEvent; +import javafx.util.Duration; + +import java.util.ArrayList; +import java.util.List; + + +/** + * Window Decorator allow to resize/move its content Note: the default close button will call stage.close() which will + * only close the current stage. it will not close the java application, however it can be customized by calling {@link + * #setOnCloseButtonAction(Runnable)} + * + * @author Shadi Shaheen + * @version 1.0 + * @since 2016-03-09 + */ +public class LFXDecorator extends StackPane { + + private Stage primaryStage; + private VBox contentPane = new VBox(); + + private double snapped_inset = 6; + private double xOffset = 0; + private double yOffset = 0; + private double newX, newY, initX, initY, initWidth = -1, initHeight = -1, + initStageX = -1, initStageY = -1; + + private boolean allowMove = false; + private boolean isDragging = false; + private Timeline windowDecoratorAnimation; + private StackPane contentPlaceHolder = new StackPane(); + private HBox buttonsContainer; + + private ObjectProperty onCloseButtonAction = new SimpleObjectProperty<>(() -> + primaryStage.fireEvent(new WindowEvent(primaryStage, WindowEvent.WINDOW_CLOSE_REQUEST))); + + private BooleanProperty customMaximize = new SimpleBooleanProperty(false); + private boolean maximized = false; + private BoundingBox originalBox; + private BoundingBox maximizedBox; + + protected JFXButton btnMax; + protected JFXButton btnFull; + protected JFXButton btnClose; + protected JFXButton btnMin; + + protected StringProperty title = new SimpleStringProperty(); + protected Text text; + protected Node graphic; + protected HBox graphicContainer; + + /** + * Create a window decorator for the specified node with the options: + * - full screen + * - maximize + * - minimize + * + * @param stage the primary stage used by the application + * @param node the node to be decorated + */ + public LFXDecorator(Stage stage, Node node) { + this(stage, node, true, true, true); + } + + /** + * Create a window decorator for the specified node with the options: + * - full screen + * - maximize + * - minimize + * + * @param stage the primary stage used by the application + * @param node the node to be decorated + * @param fullScreen indicates whether to show full screen option or not + * @param max indicates whether to show maximize option or not + * @param min indicates whether to show minimize option or not + */ + public LFXDecorator(Stage stage, Node node, boolean fullScreen, boolean max, boolean min) { + primaryStage = stage; + // Note that setting the style to TRANSPARENT is causing performance + // degradation, as an alternative we set it to UNDECORATED instead. + primaryStage.initStyle(StageStyle.TRANSPARENT); + + setPickOnBounds(false); + getStyleClass().add("lfx-decorator"); + + initializeButtons(); + initializeContainers(node, fullScreen, max, min); + + primaryStage.fullScreenProperty().addListener((o, oldVal, newVal) -> { + if (newVal) { + // remove border + contentPlaceHolder.getStyleClass().remove("resize-border"); + /* + * note the border property MUST NOT be bound to another property + * when going full screen mode, thus the binding will be lost if exisited + */ + contentPlaceHolder.borderProperty().unbind(); + contentPlaceHolder.setBorder(Border.EMPTY); + if (windowDecoratorAnimation != null) { + windowDecoratorAnimation.stop(); + } + windowDecoratorAnimation = new Timeline(new KeyFrame(Duration.millis(320), + new KeyValue(this.translateYProperty(), + -buttonsContainer.getHeight(), + Interpolator.EASE_BOTH))); + windowDecoratorAnimation.setOnFinished((finish) -> { + this.getChildren().remove(buttonsContainer); + this.setTranslateY(0); + }); + windowDecoratorAnimation.play(); + } else { + // add border + if (windowDecoratorAnimation != null) { + if (windowDecoratorAnimation.getStatus() == Animation.Status.RUNNING) { + windowDecoratorAnimation.stop(); + } else { + this.getChildren().add(0, buttonsContainer); + } + } + this.setTranslateY(-buttonsContainer.getHeight()); + windowDecoratorAnimation = new Timeline(new KeyFrame(Duration.millis(320), + new KeyValue(this.translateYProperty(), + 0, + Interpolator.EASE_BOTH))); + windowDecoratorAnimation.setOnFinished((finish) -> { + contentPlaceHolder.setBorder(new Border(new BorderStroke(Color.BLACK, + BorderStrokeStyle.SOLID, + CornerRadii.EMPTY, + new BorderWidths(0, 4, 4, 4)))); + contentPlaceHolder.getStyleClass().add("resize-border"); + }); + windowDecoratorAnimation.play(); + } + }); + + this.addEventHandler(MouseEvent.MOUSE_PRESSED, (mouseEvent) -> + updateInitMouseValues(mouseEvent)); + this.addEventHandler(MouseEvent.MOUSE_PRESSED, (mouseEvent) -> + updateInitMouseValues(mouseEvent)); + + // show the drag cursor on the borders + addEventFilter(MouseEvent.MOUSE_MOVED, (mouseEvent) -> showDragCursorOnBorders(mouseEvent)); + + + // handle drag events on the decorator pane + addEventFilter(MouseEvent.MOUSE_RELEASED, (mouseEvent) -> isDragging = false); + this.setOnMouseDragged((mouseEvent) -> handleDragEventOnDecoratorPane(mouseEvent)); + } + + private void initializeButtons() { + + SVGGlyph full = new SVGGlyph(0, + "FULLSCREEN", + "M598 214h212v212h-84v-128h-128v-84zM726 726v-128h84v212h-212v-84h128zM214 426v-212h212v84h-128v128h-84zM298 598v128h128v84h-212v-212h84z", + Color.WHITE); + full.setSize(16, 16); + SVGGlyph minus = new SVGGlyph(0, + "MINUS", + "M804.571 420.571v109.714q0 22.857-16 38.857t-38.857 16h-694.857q-22.857 0-38.857-16t-16-38.857v-109.714q0-22.857 16-38.857t38.857-16h694.857q22.857 0 38.857 16t16 38.857z", + Color.WHITE); + minus.setSize(12, 2); + minus.setTranslateY(4); + SVGGlyph resizeMax = new SVGGlyph(0, + "RESIZE_MAX", + "M726 810v-596h-428v596h428zM726 44q34 0 59 25t25 59v768q0 34-25 60t-59 26h-428q-34 0-59-26t-25-60v-768q0-34 25-60t59-26z", + Color.WHITE); + resizeMax.setSize(12, 12); + SVGGlyph resizeMin = new SVGGlyph(0, + "RESIZE_MIN", + "M80.842 943.158v-377.264h565.894v377.264h-565.894zM0 404.21v619.79h727.578v-619.79h-727.578zM377.264 161.684h565.894v377.264h-134.736v80.842h215.578v-619.79h-727.578v323.37h80.842v-161.686z", + Color.WHITE); + resizeMin.setSize(12, 12); + SVGGlyph close = new SVGGlyph(0, + "CLOSE", + "M810 274l-238 238 238 238-60 60-238-238-238 238-60-60 238-238-238-238 60-60 238 238 238-238z", + Color.WHITE); + close.setSize(12, 12); + btnFull = new JFXButton(); + btnFull.getStyleClass().add("lfx-decorator-button"); + btnFull.setCursor(Cursor.HAND); + btnFull.setOnAction((action) -> primaryStage.setFullScreen(!primaryStage.isFullScreen())); + btnFull.setGraphic(full); + btnFull.setTranslateX(-30); + btnFull.setRipplerFill(Color.WHITE); + + btnClose = new JFXButton(); + btnClose.getStyleClass().add("lfx-decorator-button"); + btnClose.setCursor(Cursor.HAND); + btnClose.setOnAction((action) -> onCloseButtonAction.get().run()); + btnClose.setGraphic(close); + btnClose.setRipplerFill(Color.WHITE); + + btnMin = new JFXButton(); + btnMin.getStyleClass().add("lfx-decorator-button"); + btnMin.setCursor(Cursor.HAND); + btnMin.setOnAction((action) -> primaryStage.setIconified(true)); + btnMin.setGraphic(minus); + btnMin.setRipplerFill(Color.WHITE); + + btnMax = new JFXButton(); + btnMax.getStyleClass().add("lfx-decorator-button"); + btnMax.setCursor(Cursor.HAND); + btnMax.setRipplerFill(Color.WHITE); + btnMax.setOnAction((action) -> maximize(resizeMin, resizeMax)); + btnMax.setGraphic(resizeMax); + } + + private void maximize(SVGGlyph resizeMin, SVGGlyph resizeMax) { + if (!isCustomMaximize()) { + primaryStage.setMaximized(!primaryStage.isMaximized()); + maximized = primaryStage.isMaximized(); + if (primaryStage.isMaximized()) { + btnMax.setGraphic(resizeMin); + btnMax.setTooltip(new Tooltip("Restore Down")); + } else { + btnMax.setGraphic(resizeMax); + btnMax.setTooltip(new Tooltip("Maximize")); + } + } else { + if (!maximized) { + // store original bounds + originalBox = new BoundingBox(primaryStage.getX(), primaryStage.getY(), primaryStage.getWidth(), primaryStage.getHeight()); + // get the max stage bounds + Screen screen = Screen.getScreensForRectangle(primaryStage.getX(), + primaryStage.getY(), + primaryStage.getWidth(), + primaryStage.getHeight()).get(0); + Rectangle2D bounds = screen.getVisualBounds(); + maximizedBox = new BoundingBox(bounds.getMinX(), + bounds.getMinY(), + bounds.getWidth(), + bounds.getHeight()); + // maximized the stage + primaryStage.setX(maximizedBox.getMinX()); + primaryStage.setY(maximizedBox.getMinY()); + primaryStage.setWidth(maximizedBox.getWidth()); + primaryStage.setHeight(maximizedBox.getHeight()); + btnMax.setGraphic(resizeMin); + btnMax.setTooltip(new Tooltip("Restore Down")); + this.setPadding(new Insets(0,0,0,0)); + } else { + // restore stage to its original size + primaryStage.setX(originalBox.getMinX()); + primaryStage.setY(originalBox.getMinY()); + primaryStage.setWidth(originalBox.getWidth()); + primaryStage.setHeight(originalBox.getHeight()); + originalBox = null; + btnMax.setGraphic(resizeMax); + btnMax.setTooltip(new Tooltip("Maximize")); + this.setPadding(new Insets(3,3,3,3)); + } + maximized = !maximized; + } + } + + private void initializeContainers(Node node, boolean fullScreen, boolean max, boolean min) { + buttonsContainer = new HBox(); + buttonsContainer.getStyleClass().add("lfx-decorator-buttons-container"); + buttonsContainer.setBackground(new Background(new BackgroundFill(Color.BLACK, + CornerRadii.EMPTY, + Insets.EMPTY))); + // BINDING + buttonsContainer.setPadding(new Insets(4)); + buttonsContainer.setAlignment(Pos.CENTER_RIGHT); + + // customize decorator buttons + List btns = new ArrayList<>(); + if (fullScreen) { + btns.add(btnFull); + } + if (min) { + btns.add(btnMin); + } + if (max) { + btns.add(btnMax); + // maximize/restore the window on header double click + buttonsContainer.addEventHandler(MouseEvent.MOUSE_CLICKED, (mouseEvent) -> { + if (mouseEvent.getClickCount() == 2) { + btnMax.fire(); + } + }); + } + btns.add(btnClose); + + text = new Text(); + text.getStyleClass().addAll("lfx-decorator-text", "title", "lfx-decorator-title"); + text.setFill(Color.WHITE); + text.textProperty().bind(title); //binds the Text's text to title + title.bind(primaryStage.titleProperty()); //binds title to the primaryStage's title + + graphicContainer = new HBox(); + graphicContainer.setPickOnBounds(false); + graphicContainer.setAlignment(Pos.CENTER_LEFT); + graphicContainer.getChildren().setAll(text); + + HBox graphicTextContainer = new HBox(graphicContainer, text); + graphicTextContainer.getStyleClass().add("lfx-decorator-title-container"); + graphicTextContainer.setAlignment(Pos.CENTER_LEFT); + graphicTextContainer.setPickOnBounds(false); + HBox.setHgrow(graphicTextContainer, Priority.ALWAYS); + HBox.setMargin(graphicContainer, new Insets(0, 8, 0, 8)); + + buttonsContainer.getChildren().setAll(graphicTextContainer); + buttonsContainer.getChildren().addAll(btns); + buttonsContainer.addEventHandler(MouseEvent.MOUSE_ENTERED, (enter) -> allowMove = true); + buttonsContainer.addEventHandler(MouseEvent.MOUSE_EXITED, (enter) -> { + if (!isDragging) { + allowMove = false; + } + }); + buttonsContainer.setMinWidth(180); + contentPlaceHolder.getStyleClass().add("lfx-decorator-content-container"); + contentPlaceHolder.setMinSize(0, 0); + StackPane clippedContainer = new StackPane(node); + contentPlaceHolder.getChildren().add(clippedContainer); + ((Region) node).setMinSize(0, 0); + + contentPlaceHolder.getStyleClass().add("resize-border"); + + // BINDING + + Rectangle clip = new Rectangle(); + clip.setArcWidth(20); + clip.setArcHeight(20); + clip.widthProperty().bind(contentPane.widthProperty()); + clip.heightProperty().bind(contentPane.heightProperty()); + + VBox.setVgrow(contentPlaceHolder, Priority.ALWAYS); + contentPane.getChildren().addAll(buttonsContainer, contentPlaceHolder); + contentPane.setClip(clip); + + this.setPadding(new Insets(3,3,3,3)); + this.getChildren().addAll(contentPane); + } + + private void showDragCursorOnBorders(MouseEvent mouseEvent) { + if (primaryStage.isFullScreen() || maximized) { + this.setCursor(Cursor.DEFAULT); + return; // maximized mode does not support resize + } + if (!primaryStage.isResizable()) { + return; + } + double x = mouseEvent.getX(); + double y = mouseEvent.getY(); + double borderWidth = 20; + if (isRightEdge(x)) { + if (y < borderWidth) { + this.setCursor(Cursor.NE_RESIZE); + } else if (y > this.getHeight() - borderWidth) { + this.setCursor(Cursor.SE_RESIZE); + } else { + this.setCursor(Cursor.E_RESIZE); + } + } else if (isLeftEdge(x)) { + if (y < borderWidth) { + this.setCursor(Cursor.NW_RESIZE); + } else if (y > this.getHeight() - borderWidth) { + this.setCursor(Cursor.SW_RESIZE); + } else { + this.setCursor(Cursor.W_RESIZE); + } + } else if (isTopEdge(y)) { + this.setCursor(Cursor.N_RESIZE); + } else if (isBottomEdge(y)) { + this.setCursor(Cursor.S_RESIZE); + } else { + this.setCursor(Cursor.DEFAULT); + } + + + } + + private void handleDragEventOnDecoratorPane(MouseEvent mouseEvent) { + isDragging = true; + if (!mouseEvent.isPrimaryButtonDown() || (xOffset == -1 && yOffset == -1)) { + return; + } + /* + * Long press generates drag event! + */ + if (primaryStage.isFullScreen() || maximized) { + return; + } + + newX = mouseEvent.getScreenX(); + newY = mouseEvent.getScreenY(); + + + double deltax = newX - initX; + double deltay = newY - initY; + Cursor cursor = this.getCursor(); + + if (Cursor.E_RESIZE.equals(cursor)) { + setStageWidth(initWidth + deltax); + mouseEvent.consume(); + } else if (Cursor.NE_RESIZE.equals(cursor)) { + if (setStageHeight(initHeight - deltay)) { + primaryStage.setY(initStageY + deltay); + } + setStageWidth(initWidth + deltax); + mouseEvent.consume(); + } else if (Cursor.SE_RESIZE.equals(cursor)) { + setStageWidth(initWidth + deltax); + setStageHeight(initHeight + deltay); + mouseEvent.consume(); + } else if (Cursor.S_RESIZE.equals(cursor)) { + setStageHeight(initHeight + deltay); + mouseEvent.consume(); + } else if (Cursor.W_RESIZE.equals(cursor)) { + if (setStageWidth(initWidth - deltax)) { + primaryStage.setX(initStageX + deltax); + } + mouseEvent.consume(); + } else if (Cursor.SW_RESIZE.equals(cursor)) { + if (setStageWidth(initWidth - deltax)) { + primaryStage.setX(initStageX + deltax); + } + setStageHeight(initHeight + deltay); + mouseEvent.consume(); + } else if (Cursor.NW_RESIZE.equals(cursor)) { + if (setStageWidth(initWidth - deltax)) { + primaryStage.setX(initStageX + deltax); + } + if (setStageHeight(initHeight - deltay)) { + primaryStage.setY(initStageY + deltay); + } + mouseEvent.consume(); + } else if (Cursor.N_RESIZE.equals(cursor)) { + if (setStageHeight(initHeight - deltay)) { + primaryStage.setY(initStageY + deltay); + } + mouseEvent.consume(); + } else if (allowMove) { + primaryStage.setX(mouseEvent.getScreenX() - xOffset); + primaryStage.setY(mouseEvent.getScreenY() - yOffset); + mouseEvent.consume(); + } + } + + private void updateInitMouseValues(MouseEvent mouseEvent) { + initStageX = primaryStage.getX(); + initStageY = primaryStage.getY(); + initWidth = primaryStage.getWidth(); + initHeight = primaryStage.getHeight(); + initX = mouseEvent.getScreenX(); + initY = mouseEvent.getScreenY(); + xOffset = mouseEvent.getSceneX(); + yOffset = mouseEvent.getSceneY(); + } + + + private boolean isRightEdge(double x) { + final double width = this.getWidth(); + return x < width && x > width - snapped_inset; + } + + private boolean isTopEdge(double y) { + return y >= 0 && y < snapped_inset; + } + + private boolean isBottomEdge(double y) { + final double height = this.getHeight(); + return y < height && y > height - snapped_inset; + } + + private boolean isLeftEdge(double x) { + return x >= 0 && x < snapped_inset; + } + + boolean setStageWidth(double width) { + if (width >= primaryStage.getMinWidth() && width >= buttonsContainer.getMinWidth()) { + primaryStage.setWidth(width); +// initX = newX; + return true; + } else if (width >= primaryStage.getMinWidth() && width <= buttonsContainer.getMinWidth()) { + width = buttonsContainer.getMinWidth(); + primaryStage.setWidth(width); + } + return false; + } + + boolean setStageHeight(double height) { + if (height >= primaryStage.getMinHeight() && height >= buttonsContainer.getHeight()) { + primaryStage.setHeight(height); +// initY = newY; + return true; + } else if (height >= primaryStage.getMinHeight() && height <= buttonsContainer.getHeight()) { + height = buttonsContainer.getHeight(); + primaryStage.setHeight(height); + } + return false; + } + + /** + * set a speficed runnable when clicking on the close button + * + * @param onCloseButtonAction runnable to be executed + */ + public void setOnCloseButtonAction(Runnable onCloseButtonAction) { + this.onCloseButtonAction.set(onCloseButtonAction); + } + + /** + * this property is used to replace JavaFX maximization + * with a custom one that prevents hiding windows taskbar when + * the JFXDecorator is maximized. + * + * @return customMaximizeProperty whether to use custom maximization or not. + */ + public final BooleanProperty customMaximizeProperty() { + return this.customMaximize; + } + + /** + * @return whether customMaximizeProperty is active or not + */ + public final boolean isCustomMaximize() { + return this.customMaximizeProperty().get(); + } + + /** + * set customMaximize property + * + * @param customMaximize + */ + public final void setCustomMaximize(final boolean customMaximize) { + this.customMaximizeProperty().set(customMaximize); + } + + /** + * @param maximized + */ + public void setMaximized(boolean maximized) { + if (this.maximized != maximized) { + Platform.runLater(() -> { + btnMax.fire(); + }); + } + } + + /** + * will change the decorator content + * + * @param content + */ + public void setContent(Node content) { + this.contentPlaceHolder.getChildren().setAll(content); + } + + /** + * will set the title + * + * @param text + * @deprecated Use {@link LFXDecorator#setTitle(String)} instead. + */ + public void setText(String text) { + setTitle(text); + } + + /** + * will get the title + * + * @deprecated Use {@link LFXDecorator#setTitle(String)} instead. + */ + public String getText() { + return getTitle(); + } + + public String getTitle() { + return title.get(); + } + + /** + * By default this title property is bound to the primaryStage's title property. + *

+ * To change it to something else, use

+     *     {@code jfxDecorator.titleProperty().unbind();}
first. + */ + public StringProperty titleProperty() { + return title; + } + + /** + * If you want the {@code primaryStage}'s title and the {@code JFXDecorator}'s title to be different, then + * go ahead and use this method. + *

+ * By default, this title property is bound to the {@code primaryStage}'s title property-so merely setting the + * {@code primaryStage}'s title, will set the {@code JFXDecorator}'s title. + */ + public void setTitle(String title) { + this.title.unbind(); + this.title.set(title); + } + + public void setGraphic(Node node) { + if (graphic != null) { + graphicContainer.getChildren().remove(graphic); + } + if (node != null) { + graphicContainer.getChildren().add(0, node); + } + graphic = node; + } + + public Node getGraphic() { + return graphic; + } +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/control/TreeItemPredicate.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/control/TreeItemPredicate.java new file mode 100644 index 0000000..ccf7a5d --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/control/TreeItemPredicate.java @@ -0,0 +1,16 @@ +package com.epri.fx.client.gui.uicomponents.control; + +import javafx.scene.control.TreeItem; + +import java.util.function.Predicate; + +@FunctionalInterface +public interface TreeItemPredicate { + + boolean test(TreeItem parent, T value); + + static TreeItemPredicate create(Predicate predicate) { + return (parent, value) -> predicate.test(value); + } + +} \ No newline at end of file diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/home/HomeController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/home/HomeController.java new file mode 100644 index 0000000..d2219d9 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/home/HomeController.java @@ -0,0 +1,447 @@ +package com.epri.fx.client.gui.uicomponents.home; + +import com.epri.fx.client.bean.CountryPath; +import eu.hansolo.tilesfx.Tile; +import eu.hansolo.tilesfx.TileBuilder; +import eu.hansolo.tilesfx.TimeSection; +import eu.hansolo.tilesfx.TimeSectionBuilder; +import eu.hansolo.tilesfx.addons.Indicator; +import eu.hansolo.tilesfx.chart.ChartData; +import eu.hansolo.tilesfx.chart.RadarChart; +import eu.hansolo.tilesfx.chart.TilesFXSeries; +import eu.hansolo.tilesfx.colors.Bright; +import eu.hansolo.tilesfx.colors.Dark; +import eu.hansolo.tilesfx.skins.BarChartItem; +import eu.hansolo.tilesfx.skins.LeaderBoardItem; +import eu.hansolo.tilesfx.tools.Country; +import eu.hansolo.tilesfx.tools.FlowGridPane; +import eu.hansolo.tilesfx.tools.Helper; +import eu.hansolo.tilesfx.tools.Location; +import eu.hansolo.tilesfx.weather.DarkSky; +import io.datafx.controller.ViewController; +import io.datafx.controller.flow.context.ActionHandler; +import io.datafx.controller.flow.context.FlowActionHandler; +import javafx.animation.AnimationTimer; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.Parent; +import javafx.scene.chart.XYChart; +import javafx.scene.layout.*; +import javafx.scene.paint.Color; +import javafx.scene.paint.CycleMethod; +import javafx.scene.paint.LinearGradient; +import javafx.scene.paint.Stop; +import javafx.scene.text.TextAlignment; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import java.time.LocalTime; +import java.time.ZonedDateTime; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +import static javafx.scene.layout.Region.USE_COMPUTED_SIZE; +import static javafx.scene.layout.Region.USE_PREF_SIZE; + +/** + * @description: + * @className: HomeController + * @author: liwen + * @date: 2020/6/24 18:16 + */ +@ViewController(value = "/fxml/home/home.fxml", title = "主页", iconPath = "") +public class HomeController { + + @ActionHandler + private FlowActionHandler actionHandler; + + public static final Color BACKGROUND = Color.rgb(39, 49, 66); // #2a2a2a + public static final Color BORDERCOLOR = Color.rgb(49, 61, 79); // #2a2a2a + + + private static final Random RND = new Random(); + private int noOfNodes = 0; + + private BarChartItem barChartItem1; + private BarChartItem barChartItem2; + private BarChartItem barChartItem3; + private BarChartItem barChartItem4; + + private LeaderBoardItem leaderBoardItem1; + private LeaderBoardItem leaderBoardItem2; + private LeaderBoardItem leaderBoardItem3; + private LeaderBoardItem leaderBoardItem4; + + private ChartData chartData1; + private ChartData chartData2; + private ChartData chartData3; + private ChartData chartData4; + private ChartData chartData5; + private ChartData chartData6; + private ChartData chartData7; + private ChartData chartData8; + + private ChartData smoothChartData1; + private ChartData smoothChartData2; + private ChartData smoothChartData3; + private ChartData smoothChartData4; + + private Tile radialChartTile; + private Tile donutChartTile; + private Tile circularProgressTile; + private Tile radarChartTile1; + + private Tile worldTile; + private Tile ephemerisTile; + private Tile statusTile; + + private Tile sparkLineTile; + private Tile areaChartTile; + private Tile lineChartTile; + + + private long lastTimerCall; + private AnimationTimer timer; + private DoubleProperty value; + + + private Map> hiresCountryPaths = new ConcurrentHashMap<>(); + + @FXML + private GridPane centerPane; + + @PostConstruct + private void init() { + long start = System.currentTimeMillis(); + + + value = new SimpleDoubleProperty(0); + + // AreaChart Data + XYChart.Series series1 = new XYChart.Series(); + series1.setName("Whatever"); + series1.getData().add(new XYChart.Data("MO", 23)); + series1.getData().add(new XYChart.Data("TU", 21)); + series1.getData().add(new XYChart.Data("WE", 20)); + series1.getData().add(new XYChart.Data("TH", 22)); + series1.getData().add(new XYChart.Data("FR", 24)); + series1.getData().add(new XYChart.Data("SA", 22)); + series1.getData().add(new XYChart.Data("SU", 20)); + + // LineChart Data + XYChart.Series series2 = new XYChart.Series(); + series2.setName("Inside"); + series2.getData().add(new XYChart.Data("MO", 8)); + series2.getData().add(new XYChart.Data("TU", 5)); + series2.getData().add(new XYChart.Data("WE", 0)); + series2.getData().add(new XYChart.Data("TH", 2)); + series2.getData().add(new XYChart.Data("FR", 4)); + series2.getData().add(new XYChart.Data("SA", 3)); + series2.getData().add(new XYChart.Data("SU", 5)); + + XYChart.Series series3 = new XYChart.Series(); + series3.setName("Outside"); + series3.getData().add(new XYChart.Data("MO", 8)); + series3.getData().add(new XYChart.Data("TU", 5)); + series3.getData().add(new XYChart.Data("WE", 0)); + series3.getData().add(new XYChart.Data("TH", 2)); + series3.getData().add(new XYChart.Data("FR", 4)); + series3.getData().add(new XYChart.Data("SA", 3)); + series3.getData().add(new XYChart.Data("SU", 5)); + + // WorldMap Data + for (int i = 0; i < Country.values().length; i++) { + double value = RND.nextInt(10); + Color color; + if (value > 8) { + color = Tile.RED; + } else if (value > 6) { + color = Tile.ORANGE; + } else if (value > 4) { + color = Tile.YELLOW_ORANGE; + } else if (value > 2) { + color = Tile.GREEN; + } else { + color = Tile.BLUE; + } + Country.values()[i].setColor(color); + } + + // TimeControl Data + TimeSection timeSection = TimeSectionBuilder.create() + .start(LocalTime.now().plusSeconds(20)) + .stop(LocalTime.now().plusHours(1)) + //.days(DayOfWeek.MONDAY, DayOfWeek.FRIDAY) + .color(Tile.GRAY) + .highlightColor(Tile.RED) + .build(); + + timeSection.setOnTimeSectionEntered(e -> System.out.println("Section ACTIVE")); + timeSection.setOnTimeSectionLeft(e -> System.out.println("Section INACTIVE")); + + // Weather (You can get a DarkSky API key here: https://darksky.net/dev/ ) + DarkSky darkSky = new DarkSky("YOUR DARKSKY API KEY", DarkSky.Unit.CA, DarkSky.Language.ENGLISH, 51.911858, 7.632815); + //darkSky.update(); + + // BarChart Items + barChartItem1 = new BarChartItem("Gerrit", 47, Tile.BLUE); + barChartItem2 = new BarChartItem("Sandra", 43, Tile.RED); + barChartItem3 = new BarChartItem("Lilli", 12, Tile.GREEN); + barChartItem4 = new BarChartItem("Anton", 8, Tile.ORANGE); + + barChartItem1.setFormatString("%.1f kWh"); + + // LeaderBoard Items + leaderBoardItem1 = new LeaderBoardItem("Gerrit", 47); + leaderBoardItem2 = new LeaderBoardItem("Sandra", 43); + leaderBoardItem3 = new LeaderBoardItem("Lilli", 12); + leaderBoardItem4 = new LeaderBoardItem("Anton", 8); + + // Chart Data + chartData1 = new ChartData("Item 1", 24.0, Tile.GREEN); + chartData2 = new ChartData("Item 2", 10.0, Tile.BLUE); + chartData3 = new ChartData("Item 3", 12.0, Tile.RED); + chartData4 = new ChartData("Item 4", 13.0, Tile.YELLOW_ORANGE); + chartData5 = new ChartData("Item 5", 13.0, Tile.BLUE); + chartData6 = new ChartData("Item 6", 13.0, Tile.BLUE); + chartData7 = new ChartData("Item 7", 13.0, Tile.BLUE); + chartData8 = new ChartData("Item 8", 13.0, Tile.BLUE); + //ChartData.animated = false; + + smoothChartData1 = new ChartData("Item 1", RND.nextDouble() * 25, Tile.BLUE); + smoothChartData2 = new ChartData("Item 2", RND.nextDouble() * 25, Tile.BLUE); + smoothChartData3 = new ChartData("Item 3", RND.nextDouble() * 25, Tile.BLUE); + smoothChartData4 = new ChartData("Item 4", RND.nextDouble() * 25, Tile.BLUE); + + + sparkLineTile = TileBuilder.create() + .skinType(Tile.SkinType.SPARK_LINE) + .title("SparkLine Tile") + .unit("mb").borderRadius(14) + .gradientStops(new Stop(0, Tile.GREEN), + new Stop(0.5, Tile.YELLOW), + new Stop(1.0, Tile.RED)) + .strokeWithGradient(true) + .backgroundColor(BACKGROUND).borderColor(BORDERCOLOR).borderWidth(0.8d) + //.smoothing(true) + .build(); + + + areaChartTile = TileBuilder.create() + .skinType(Tile.SkinType.SMOOTHED_CHART).backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d) + .title("SmoothedChart Tile") + .chartType(Tile.ChartType.AREA) + //.animated(true) + .smoothing(true) + .tooltipTimeout(1000) + .tilesFxSeries(new TilesFXSeries<>(series1, + Tile.BLUE, + new LinearGradient(0, 0, 0, 1, + true, CycleMethod.NO_CYCLE, + new Stop(0, Tile.BLUE), + new Stop(1, Color.TRANSPARENT)))) + .build(); + + lineChartTile = TileBuilder.create() + .skinType(Tile.SkinType.SMOOTHED_CHART).backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d) + .title("SmoothedChart Tile") + //.animated(true) + .smoothing(false) + .series(series2, series3) + .build(); + + + worldTile = TileBuilder.create() + .skinType(Tile.SkinType.WORLDMAP).backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d) + .title("WorldMap Tile") + .text("Whatever text") + .textVisible(false) + .build(); + + + radialChartTile = TileBuilder.create() + .skinType(Tile.SkinType.RADIAL_CHART).backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d) + .title("RadialChart") + .text("Some text") + .textVisible(false) + .chartData(chartData1, chartData2, chartData3, chartData4) + .build(); + + donutChartTile = TileBuilder.create() + .skinType(Tile.SkinType.DONUT_CHART) + .title("DonutChart").backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d) + .text("Some text") + .textVisible(false) + .chartData(chartData1, chartData2, chartData3, chartData4) + .build(); + + circularProgressTile = TileBuilder.create() + .skinType(Tile.SkinType.CIRCULAR_PROGRESS) + .title("CircularProgress").backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d) + .text("Some text") + .unit("\u0025") + //.graphic(new WeatherSymbol(ConditionAndIcon.CLEAR_DAY, 48, Color.WHITE)) + .build(); + + + radarChartTile1 = TileBuilder.create().skinType(Tile.SkinType.RADAR_CHART) + .minValue(0) + .maxValue(50).backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d) + .title("RadarChart Sector") + .unit("Unit") + .radarChartMode(RadarChart.Mode.SECTOR) + .gradientStops(new Stop(0.00000, Color.TRANSPARENT), + new Stop(0.00001, Color.web("#3552a0")), + new Stop(0.09090, Color.web("#456acf")), + new Stop(0.27272, Color.web("#45a1cf")), + new Stop(0.36363, Color.web("#30c8c9")), + new Stop(0.45454, Color.web("#30c9af")), + new Stop(0.50909, Color.web("#56d483")), + new Stop(0.72727, Color.web("#9adb49")), + new Stop(0.81818, Color.web("#efd750")), + new Stop(0.90909, Color.web("#ef9850")), + new Stop(1.00000, Color.web("#ef6050"))) + .text("Test") + .chartData(chartData1, chartData2, chartData3, chartData4, + chartData5, chartData6, chartData7, chartData8) + .tooltipText("") + .animated(true) + .build(); + + + ephemerisTile = TileBuilder.create().skinType(Tile.SkinType.EPHEMERIS) + .title("Ephemeris").backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d) + .currentLocation(new Location(51.911515, 7.6340026, "Hiltrup")) + .text("Hiltrup") + .build(); + + + Indicator leftGraphics = new Indicator(Tile.RED); + leftGraphics.setOn(true); + + Indicator middleGraphics = new Indicator(Tile.YELLOW); + middleGraphics.setOn(true); + + Indicator rightGraphics = new Indicator(Tile.GREEN); + rightGraphics.setOn(true); + + statusTile = TileBuilder.create() + .skinType(Tile.SkinType.STATUS) + .title("Status Tile").borderWidth(0.8d).backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d) + .description("Notifications") + .leftText("CRITICAL") + .middleText("WARNING") + .rightText("INFORMATION") + .leftGraphics(leftGraphics) + .middleGraphics(middleGraphics) + .rightGraphics(rightGraphics) + .text("Text") + .build(); + + + lastTimerCall = System.nanoTime(); + timer = new AnimationTimer() { + @Override + public void handle(long now) { + if (now > lastTimerCall + 3_500_000_000L) { + + sparkLineTile.setValue(RND.nextDouble() * sparkLineTile.getRange() * 1.5 + sparkLineTile.getMinValue()); + //value.set(RND.nextDouble() * sparkLineTile.getRange() * 1.5 + sparkLineTile.getMinValue()); + //sparkLineTile.setValue(20); + + for (XYChart.Data stringNumberData : series1.getData()) { + stringNumberData.setYValue(RND.nextInt(100)); + } + for (XYChart.Data stringNumberData : series2.getData()) { + stringNumberData.setYValue(RND.nextInt(30)); + } + for (XYChart.Data data : series3.getData()) { + data.setYValue(RND.nextInt(10)); + } + + chartData1.setValue(RND.nextDouble() * 50); + chartData2.setValue(RND.nextDouble() * 50); + chartData3.setValue(RND.nextDouble() * 50); + chartData4.setValue(RND.nextDouble() * 50); + chartData5.setValue(RND.nextDouble() * 50); + chartData6.setValue(RND.nextDouble() * 50); + chartData7.setValue(RND.nextDouble() * 50); + chartData8.setValue(RND.nextDouble() * 50); + + + circularProgressTile.setValue(RND.nextDouble() * 120); + + + smoothChartData1.setValue(smoothChartData2.getValue()); + smoothChartData2.setValue(smoothChartData3.getValue()); + smoothChartData3.setValue(smoothChartData4.getValue()); + smoothChartData4.setValue(RND.nextDouble() * 25); + + + if (statusTile.getLeftValue() > 1000) { + statusTile.setLeftValue(0); + } + if (statusTile.getMiddleValue() > 1000) { + statusTile.setMiddleValue(0); + } + if (statusTile.getRightValue() > 1000) { + statusTile.setRightValue(0); + } + statusTile.setLeftValue(statusTile.getLeftValue() + RND.nextInt(4)); + statusTile.setMiddleValue(statusTile.getMiddleValue() + RND.nextInt(3)); + statusTile.setRightValue(statusTile.getRightValue() + RND.nextInt(3)); + + + lastTimerCall = now; + } + } + }; + + System.out.println("Initialization: " + (System.currentTimeMillis() - start) + "ms"); + + + centerPane.add(radialChartTile, 0, 0); + centerPane.add(donutChartTile, 1, 0); + centerPane.add(circularProgressTile, 2, 0); + centerPane.add(radarChartTile1, 3, 0); + + centerPane.add(worldTile, 0, 1, 2, 1); + centerPane.add(ephemerisTile, 2, 1); + centerPane.add(statusTile, 3, 1); + + centerPane.add(sparkLineTile, 0, 2); + centerPane.add(areaChartTile, 1, 2); + centerPane.add(lineChartTile, 2, 2, 2, 1); + + System.out.println("Nodes in Scene: " + noOfNodes); + + timer.start(); + + } + + @PreDestroy + private void destroy() { + // useful for jpro + timer.stop(); + System.err.println("destroy " + this + actionHandler.getExceptionHandler()); + } + + // ******************** Misc ********************************************** + private void calcNoOfNodes(Node node) { + if (node instanceof Parent) { + if (((Parent) node).getChildrenUnmodifiable().size() != 0) { + ObservableList tempChildren = ((Parent) node).getChildrenUnmodifiable(); + noOfNodes += tempChildren.size(); + for (Node n : tempChildren) { + calcNoOfNodes(n); + } + } + } + } + +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/login/LoadingController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/login/LoadingController.java new file mode 100644 index 0000000..41110d4 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/login/LoadingController.java @@ -0,0 +1,17 @@ +package com.epri.fx.client.gui.uicomponents.login; + +import io.datafx.controller.ViewController; + +/** + * @description: + * @className: ConversationItemPresenter + * @author: liwen + * @date: 2019-09-25 16:51 + */ +@ViewController("/fxml/login/loading.fxml") +public class LoadingController { + + +} + + diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/login/LoginController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/login/LoginController.java new file mode 100644 index 0000000..eb72fda --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/login/LoginController.java @@ -0,0 +1,352 @@ +package com.epri.fx.client.gui.uicomponents.login; + +import com.epri.fx.client.bean.MenuVoCell; +import com.epri.fx.client.gui.uicomponents.main.MainController; +import com.epri.fx.client.request.feign.admin.MenuFeign; +import com.epri.fx.client.store.ApplicatonStore; +import com.epri.fx.client.request.feign.login.LoginFeign; +import com.epri.fx.client.request.Request; +import com.epri.fx.client.utils.AlertUtil; +import com.epri.fx.client.websocket.Session; +import com.epri.fx.server.util.DynamicEnumUtils; +import com.epri.fx.server.util.EncryptUtil; +import com.epri.fx.server.util.user.JwtAuthenticationRequest; +import com.epri.fx.server.vo.FrontUser; +import com.epri.fx.server.vo.MenuVO; +import com.epri.fx.server.vo.PermissionInfo; +import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXPasswordField; +import com.jfoenix.controls.JFXProgressBar; +import com.jfoenix.controls.JFXTextField; +import io.datafx.controller.ViewController; +import io.datafx.controller.flow.FlowException; +import io.datafx.controller.flow.action.ActionMethod; +import io.datafx.controller.flow.action.ActionTrigger; +import io.datafx.controller.flow.context.ActionHandler; +import io.datafx.controller.flow.context.FXMLViewFlowContext; +import io.datafx.controller.flow.context.FlowActionHandler; +import io.datafx.controller.flow.context.ViewFlowContext; +import io.datafx.controller.util.VetoException; +import io.datafx.core.concurrent.ProcessChain; +import javafx.animation.*; +import javafx.beans.binding.Bindings; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.event.EventType; +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.image.ImageView; +import javafx.scene.input.KeyCode; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.Pane; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import javafx.util.Duration; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.inject.Inject; +import java.io.File; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @description: + * @className: ConversationItemPresenter + * @author: liwen + * @date: 2019-09-25 16:51 + */ +@ViewController("/fxml/login/login.fxml") +public class LoginController { + + + @FXML + + private Pane imagePane; + @FXML + private GridPane enterPane; + @FXML + private StackPane rootPane; + @FXML + private JFXTextField userNameTextField; + @FXML + private JFXPasswordField passWordTextField; + @FXML + private Label errorLabel; + @FXML + @ActionTrigger("login") + private JFXButton loginBut; + @FXML + private VBox signCredsPane; + + @FXML + private JFXProgressBar lodingBar; + + @ActionHandler + private FlowActionHandler actionHandler; + + private SequentialTransition sequentialTransition = new SequentialTransition(); + + private DoubleProperty imageWidth = new SimpleDoubleProperty(); + private DoubleProperty imageHeiht = new SimpleDoubleProperty(); + private Stage stage; + + + @Inject + private Session session; + + + @FXMLViewFlowContext + private ViewFlowContext flowContext; + + @PostConstruct + public void init() { + errorLabel.visibleProperty().bind(errorLabel.textProperty().isNotEmpty()); + errorLabel.managedProperty().bind(errorLabel.visibleProperty()); + + lodingBar.visibleProperty().bind(enterPane.disableProperty()); + lodingBar.managedProperty().bind(lodingBar.visibleProperty()); + + userNameTextField.focusedProperty().addListener((o, oldVal, newVal) -> { + if (!newVal) { + userNameTextField.validate(); + } + }); + passWordTextField.focusedProperty().addListener((o, oldVal, newVal) -> { + if (!newVal) { + passWordTextField.validate(); + } + }); + + loginBut.disableProperty().bind(Bindings.or( + userNameTextField.textProperty().isEqualTo(""), + passWordTextField.textProperty().isEqualTo(""))); + + rootPane.setOnKeyPressed(event -> { + if (event.getCode() == KeyCode.ENTER) { + if (loginBut.isDisable() == false) { + login(); + } + } + + }); + imagePane.widthProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Number oldValue, Number newValue) { + imageWidth.setValue(newValue); + } + }); + imagePane.heightProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Number oldValue, Number newValue) { + imageHeiht.setValue(newValue); + } + }); + + + + FadeTransition fadeTransition = new FadeTransition(Duration.millis(500), signCredsPane); + fadeTransition.setFromValue(0f); + fadeTransition.setToValue(1f); + + TranslateTransition translateTransition = new TranslateTransition(Duration.millis(500), signCredsPane); + translateTransition.setInterpolator(Interpolator.EASE_BOTH); + translateTransition.setFromY(400); + translateTransition.setToY(signCredsPane.getLayoutY()); + + ParallelTransition parallelTransition = new ParallelTransition(); + parallelTransition.setDelay(Duration.millis(1500)); + parallelTransition.getChildren().addAll( + fadeTransition, + translateTransition + ); + parallelTransition.setCycleCount(1); + parallelTransition.play(); + + ImageView logBack = new ImageView("/images/loginBack.jpg"); + logBack.fitHeightProperty().bind(imageHeiht); + logBack.fitWidthProperty().bind(imageWidth); + imagePane.getChildren().add(new Label("", logBack)); + + List files = Arrays.asList(new File(this.getClass().getResource("/images/login/").getPath()).listFiles()); + + sequentialTransition.setAutoReverse(true); + sequentialTransition.setCycleCount(Timeline.INDEFINITE); + + ProcessChain.create().addPublishingTask(() -> imagePane.getChildren(), p -> { + for (int i = 0; i < files.size(); i++) { + + File file = files.get(i); + if (!file.isDirectory()) { + String url = "/images/login/" + file.getName(); + ImageView imageView = new ImageView(url); + imageView.fitHeightProperty().bind(imageHeiht); + imageView.fitWidthProperty().bind(imageWidth); + Label label = new Label("", imageView); + + label.setOpacity(0d); + FadeTransition fadeT = new FadeTransition(Duration.millis(500), label); + fadeT.setDelay(Duration.millis(1500)); + fadeT.setFromValue(0f); + fadeT.setToValue(1f); + fadeT.setCycleCount(1); + sequentialTransition.getChildren().add(fadeT); + + p.publish(label); + + } + + } + }).withFinal(() -> sequentialTransition.play()).run(); + + + } + + + @ActionMethod("login") + private void login() { + + JwtAuthenticationRequest jwtAuthenticationRequest = new JwtAuthenticationRequest(); + jwtAuthenticationRequest.setUsername(userNameTextField.getText()); + jwtAuthenticationRequest.setPassword(EncryptUtil.getInstance().Base64Encode(passWordTextField.getText())); + ProcessChain.create() + .addRunnableInPlatformThread(() -> { + enterPane.setDisable(true); + loginBut.setText("正在登录..."); + }) + .addSupplierInExecutor(() -> Request.connector(LoginFeign.class).login(jwtAuthenticationRequest)) + .addConsumerInPlatformThread(rel -> { + + if (rel.getStatus() == 200) { + errorLabel.setText(""); + ApplicatonStore.setToken(rel.getData()); + loadApplicatonStore(); + } else { + lodingBar.requestFocus(); + errorLabel.setText(rel.getMessage()); + } + + }) + .onException(e -> { + e.printStackTrace(); + errorLabel.setText("无法连接服务器,请检查服务器是否启动。"); + lodingBar.requestFocus(); + }) + .withFinal(() -> { + enterPane.setDisable(false); + loginBut.setText("登录"); + }).run(); + + + } + + public void loadApplicatonStore() { + ProcessChain.create() + .addRunnableInPlatformThread(() -> { + try { + actionHandler.navigate(LoadingController.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + ApplicatonStore.setName(""); + ApplicatonStore.getAllMenu().clear(); + ApplicatonStore.getMenus().clear(); + ApplicatonStore.getElements().clear(); + ApplicatonStore.getPermissionMenus().clear(); + ApplicatonStore.getRoles().clear(); + }) + .addSupplierInExecutor(() -> Request.connector(MenuFeign.class).getMenuAll()) + .addConsumerInPlatformThread(rel -> ApplicatonStore.getAllMenu().addAll(rel)) + .addSupplierInExecutor(() -> + Request.connector(LoginFeign.class).getInfo(ApplicatonStore.getToken()) + ) + .addConsumerInPlatformThread(rel -> { + if (rel.getStatus() == 200) { + FrontUser frontUser = rel.getData(); + ApplicatonStore.setName(frontUser.name); + ApplicatonStore.getMenus().addAll(frontUser.getMenus()); + ApplicatonStore.getRoles().addAll(frontUser.getRoles()); + ApplicatonStore.getElements().addAll(frontUser.getElements()); + ApplicatonStore.setIntroduction(frontUser.getDescription()); + + for (PermissionInfo permissionInfo : frontUser.getElements()) { + ApplicatonStore.getFeatureMap().put(permissionInfo.getCode(), permissionInfo.getName()); + } + + + } else { + AlertUtil.show(rel); + } + }) + .addSupplierInExecutor(() -> + Request.connector(LoginFeign.class).getMenus(ApplicatonStore.getToken()) + ) + .addConsumerInPlatformThread(rel -> { + ApplicatonStore.getPermissionMenus().addAll(rel); + + }) + .addSupplierInExecutor(() -> { + + List allMenuList = ApplicatonStore.getAllMenu(); + Map> allMap = allMenuList.stream().collect(Collectors.groupingBy(MenuVO::getParentId)); + MenuVO rootMenu = allMenuList.stream().min(Comparator.comparing(MenuVO::getParentId)).get(); + + + List permissionInfoList = ApplicatonStore.getPermissionMenus(); + Map> permissionInfoMap = permissionInfoList.stream().collect(Collectors.groupingBy(MenuVO::getParentId)); + Map> permissonTitleMap = permissionInfoList.stream().collect(Collectors.groupingBy(MenuVO::getTitle)); + + for (MenuVO menu : allMap.get(rootMenu.getId())) { + + List childrenMenus = permissionInfoMap.get(menu.getId()); + + List partMenus = permissonTitleMap.get(menu.getTitle()); + if (childrenMenus == null && partMenus == null) { + + continue; + } + + MenuVoCell menuVoCell=new MenuVoCell(menu,childrenMenus); + + ApplicatonStore.getMenuVoCells().add(menuVoCell); + + } + return 0; + + }) + .addConsumerInPlatformThread(rel -> { + + try { + actionHandler.navigate(MainController.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + }) + .onException(e -> { + e.printStackTrace(); + try { + actionHandler.navigate(LoginController.class); + } catch (VetoException vetoException) { + vetoException.printStackTrace(); + } catch (FlowException flowException) { + flowException.printStackTrace(); + } + }) + .run(); + } + + @PreDestroy + private void destroy() { + sequentialTransition.stop(); + } + + +} + + diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/main/MainController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/main/MainController.java new file mode 100644 index 0000000..69d6d06 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/main/MainController.java @@ -0,0 +1,406 @@ +package com.epri.fx.client.gui.uicomponents.main; + +import com.epri.fx.client.bean.MenuVoCell; +import com.epri.fx.client.gui.feature.FeatureResourceConsumer; +import com.epri.fx.client.gui.uicomponents.home.HomeController; +import com.epri.fx.client.gui.uicomponents.login.LoginController; +import com.epri.fx.client.gui.uicomponents.main.components.UserInfoController; +import com.epri.fx.client.store.ApplicatonStore; +import com.epri.fx.server.vo.MenuVO; +import com.jfoenix.controls.*; +import com.jfoenix.svg.SVGGlyphLoader; +import io.datafx.controller.ViewController; +import io.datafx.controller.context.ApplicationContext; +import io.datafx.controller.context.FXMLApplicationContext; +import io.datafx.controller.flow.Flow; +import io.datafx.controller.flow.FlowException; +import io.datafx.controller.flow.FlowHandler; +import io.datafx.controller.flow.action.ActionMethod; +import io.datafx.controller.flow.action.ActionTrigger; +import io.datafx.controller.flow.container.AnimatedFlowContainer; +import io.datafx.controller.flow.container.ContainerAnimations; +import io.datafx.controller.flow.context.ActionHandler; +import io.datafx.controller.flow.context.FlowActionHandler; +import io.datafx.controller.util.VetoException; +import io.datafx.eventsystem.Event; +import io.datafx.eventsystem.EventProducer; +import io.datafx.eventsystem.EventTrigger; +import io.datafx.eventsystem.OnEvent; +import javafx.animation.Transition; +import javafx.beans.property.ListProperty; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.geometry.Insets; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.StackPane; +import javafx.scene.text.TextAlignment; +import javafx.util.Duration; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.inject.Inject; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; + +/** + * @description: + * @className: MainPresenter + * @author: liwen + * @date: 2019-09-02 15:33 + */ + +@ViewController("/fxml/main/main.fxml") +public class MainController { + + @FXMLApplicationContext + private ApplicationContext context; + + @ActionHandler + private FlowActionHandler actionHandler; + + @FXML + private JFXToolbar toolBar; //工具栏 + @FXML + private StackPane rootPane; + @FXML + private JFXListView navigationList; + @FXML + private Pane backgroundPicturePane; + @FXML + private HBox leftHbox; + @FXML + private HBox rightHbox; + //导航按钮 + @FXML + private JFXHamburger navigationButton; + //主页按钮 + @FXML + @ActionTrigger("goHome") + private JFXButton homeButton; + @FXML + @ActionTrigger("showSkinPane") + private JFXButton skinButton; + //刷新按钮 + @FXML + @EventTrigger("test-message1") + private JFXButton refreshButton; + + //内容面板tabPane + @FXML + private JFXTabPane tabPane; + + + private JFXPopup popOver; + + @FXML + @ActionTrigger("userInfo") + private JFXButton userButton; + @FXML + private JFXButton rolesBut; + + + @FXML + private Label userLabel; + + @FXML + private Label roleLabel; + + + @FXML + private JFXDrawersStack drawersStack; + + @FXML + private JFXDrawer leftDrawer; + + @FXML + private JFXDatePicker datePicker; + @Inject + private FeatureResourceConsumer featureResourceConsumer; + + + private final HashMap tabsMap = new HashMap<>(); + + @PostConstruct + public void init() throws FlowException { + userLabel.textProperty().bind(ApplicatonStore.nameProperty()); + roleLabel.textProperty().bind(ApplicatonStore.getRoles().asString()); + userButton.textProperty().bind(ApplicatonStore.nameProperty()); + try { + skinButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".skin")); + homeButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".home-outline")); + refreshButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".shuaxin")); + rolesBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".admin")); + userButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".ChevronDownCircle")); + } catch (Exception e) { + e.printStackTrace(); + } + datePicker.setEditable(false); + leftDrawer.setSidePane(navigationList); + leftDrawer.setOverLayVisible(false); + leftDrawer.setResizeContent(true); + leftDrawer.setResizableOnDrag(true); + + // create and setup search popover + backgroundPicturePane.setMouseTransparent(true); + + leftDrawer.setOnDrawerOpening(e -> { + final Transition animation = navigationButton.getAnimation(); + animation.setRate(1); + animation.play(); + }); + leftDrawer.setOnDrawerClosing(e -> { + final Transition animation = navigationButton.getAnimation(); + animation.setRate(-1); + animation.play(); + }); + navigationButton.setOnMouseClicked(e -> { + drawersStack.toggle(leftDrawer); + }); + + tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.ALL_TABS); + drawersStack.setContent(tabPane); + drawersStack.toggle(leftDrawer); + try { + addTab("主页", SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".home-outline"), HomeController.class); + } catch (Exception e) { + e.printStackTrace(); + } + + featureResourceConsumer.consumeResource(this); + + navigationList.setCellFactory(listView -> new JFXListCell() { + @Override + public void updateItem(Object item, boolean empty) { + super.updateItem(item, empty); + if (item != null) { + if (item instanceof MenuVO) { + MenuVO menuVO = (MenuVO) item; + try { + Label label = new Label(menuVO.getTitle(), SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + "." + menuVO.getIcon())); + setGraphic(label); + setText(""); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else { + setGraphic(null); + } + } + }); + navigationList.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + if (newValue instanceof MenuVO) { + try { + addTab(((MenuVO) newValue).getTitle(), SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + "." + ((MenuVO) newValue).getIcon()), Class.forName(((MenuVO) newValue).getHref())); + } catch (Exception e) { + e.printStackTrace(); + } + + } + }); + navigationList.depthProperty().setValue(1); + navigationList.expandedProperty().set(true); + initData(); + } + + private JFXPopup getPopOver() { + if (popOver == null) { + try { + popOver = new JFXPopup(new Flow(UserInfoController.class).start()); + } catch (FlowException e) { + e.printStackTrace(); + } + } + return popOver; + } + + @EventProducer("test-message") + private String getMessage() { + return "--------=================-----------"; + } + + @EventProducer("test-message1") + private String getMessage1() { + return "--------=================-----------"; + } + + private void initData() { + + ListProperty listProperty = ApplicatonStore.getMenuVoCells(); + listProperty.sort((o1, o2) -> o1.getMenuVO().getOrderNum().compareTo(o2.getMenuVO().getOrderNum())); + + for (MenuVoCell menuVoCell : listProperty) { + if (menuVoCell.getChildrenMenus().isEmpty()) { + navigationList.getItems().add(menuVoCell.getMenuVO()); + + } else { + JFXListView listView = new JFXListView(); + listView.getStyleClass().add("sublist"); + Label label = null; + try { + label = new Label(menuVoCell.getMenuVO().getTitle(), SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + "." + menuVoCell.getMenuVO().getIcon())); + label.getStyleClass().add("sublist-label"); + } catch (Exception e) { + e.printStackTrace(); + } + label.setTextAlignment(TextAlignment.LEFT); + listView.setGroupnode(label); + listView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + if (newValue instanceof MenuVO) { + try { + addTab(newValue.getTitle(), SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + "." + newValue.getIcon()), Class.forName(newValue.getHref())); + } catch (Exception e) { + e.printStackTrace(); + } + + } + }); + listView.setCellFactory(lv -> new JFXListCell() { + @Override + public void updateItem(MenuVO item, boolean empty) { + super.updateItem(item, empty); + if (item != null) { + if (item instanceof MenuVO) { + MenuVO menuVO = (MenuVO) item; + try { + Label label = new Label(menuVO.getTitle(), SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + "." + menuVO.getIcon())); + setText(""); + setGraphic(label); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else { + setGraphic(null); + } + } + }); + ObservableList childrenMenus = menuVoCell.getChildrenMenus(); + childrenMenus.sort((o1, o2) -> o1.getOrderNum().compareTo(o2.getOrderNum())); + for (MenuVO menuVO : childrenMenus) { + listView.getItems().add(menuVO); + } + navigationList.getItems().add(listView); + + } + } + + } + + + /** + * @Description: + * @param: [controllerClass] + * @return: void + * @auther: liwen + * @date: 2020/6/28 9:57 上午 + */ + private void addTab(String title, Node icon, Class controllerClass) { + addTab(title, icon, new Flow(controllerClass)); + } + + /** + * @Description:添加tab页 + * @param: [flow] + * @return: void + * @auther: liwen + * @date: 2020/6/28 9:57 上午 + */ + private void addTab(String title, Node icon, Flow flow) { + FlowHandler flowHandler = flow.createHandler(); + Tab tab = tabsMap.get(title); + + if (tab == null) { + + tab = new Tab(title); + tab.setGraphic(icon); + + try { + StackPane node = flowHandler.start(new AnimatedFlowContainer(Duration.millis(320), ContainerAnimations.SWIPE_LEFT)); + node.getStyleClass().addAll("tab-content"); + node.setPadding(new Insets(15, 20, 15, 20)); + tab.setContent(node); + featureResourceConsumer.consumeResource(flowHandler.getCurrentViewContext().getController()); + + } catch (FlowException e) { + e.printStackTrace(); + } + tabPane.getTabs().add(tab); + tabsMap.put(title, tab); + tab.setOnClosed(event -> { + tabsMap.remove(title); + try { + flowHandler.getCurrentViewContext().destroy(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + }); + } + + if ("主页".equals(title)) { + tab.setClosable(false); + } + tabPane.getSelectionModel().select(tab); + + } + + @ActionMethod("goHome") + private void goHome() { + try { + addTab("主页", SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".home-outline"), HomeController.class); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + @ActionMethod("userInfo") + private void userInfo() throws VetoException, FlowException { + getPopOver().show(userButton, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.RIGHT, 0, userButton.getHeight()); + } + + @ActionMethod("showSkinPane") + private void showSkinPane() throws VetoException, FlowException { + + getPopOver().show(skinButton); + } + + + @PreDestroy + public void destroy() { + + } + + /** + * @Description:退出登录 + * @param: [event] + * @return: void + * @auther: liwen + * @date: 2020/8/20 6:33 下午 + */ + @OnEvent("dropOut") + private void signOut(Event event) { + getPopOver().hide(); + ApplicatonStore.clearPermissionInfo(); + try { + actionHandler.navigate(LoginController.class); + } catch (VetoException e) { + e.printStackTrace(); + } catch (FlowException e) { + e.printStackTrace(); + } + + + } + +} + + + diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/main/components/SkinInfoController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/main/components/SkinInfoController.java new file mode 100644 index 0000000..1a9b03d --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/main/components/SkinInfoController.java @@ -0,0 +1,24 @@ +package com.epri.fx.client.gui.uicomponents.main.components; + +import io.datafx.controller.ViewController; + +import javax.annotation.PostConstruct; + +/** + * @description: + * @className: UserInfoController + * @author: liwen + * @date: 2020/8/16 10:52 + */ +@ViewController("/fxml/main/components/skin_info.fxml") +public class SkinInfoController { + + + + @PostConstruct + private void init() { + + } + + +} diff --git a/client/src/main/java/com/epri/fx/client/gui/uicomponents/main/components/UserInfoController.java b/client/src/main/java/com/epri/fx/client/gui/uicomponents/main/components/UserInfoController.java new file mode 100644 index 0000000..48a9406 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/gui/uicomponents/main/components/UserInfoController.java @@ -0,0 +1,51 @@ +package com.epri.fx.client.gui.uicomponents.main.components; + +import com.epri.fx.client.store.ApplicatonStore; +import com.jfoenix.controls.JFXListView; +import io.datafx.controller.ViewController; +import io.datafx.eventsystem.EventProducer; +import io.datafx.eventsystem.EventTrigger; +import javafx.fxml.FXML; +import javafx.scene.control.Label; + +import javax.annotation.PostConstruct; + +/** + * @description: + * @className: UserInfoController + * @author: liwen + * @date: 2020/8/16 10:52 + */ +@ViewController("/fxml/main/components/user_info.fxml") +public class UserInfoController { + + @FXML + private JFXListView listView; + + @FXML + private Label userLabel; + @FXML + private Label personalCenterLabel; + @FXML + @EventTrigger("dropOut") + private Label dropOutLabel; + + @FXML + private Label roleLabel; + + @PostConstruct + private void init() { + userLabel.textProperty().bind(ApplicatonStore.nameProperty()); + roleLabel.textProperty().bind(ApplicatonStore.getRoles().asString()); + listView.expandedProperty().bind(listView.visibleProperty()); + + } + + @EventProducer("dropOut") + private String listViewListener() { + + + return "退出"; + + } +} diff --git a/client/src/main/java/com/epri/fx/client/model/GroupDataModel.java b/client/src/main/java/com/epri/fx/client/model/GroupDataModel.java new file mode 100644 index 0000000..4b039ea --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/model/GroupDataModel.java @@ -0,0 +1,65 @@ +package com.epri.fx.client.model; + +import com.epri.fx.server.vo.ElementVO; +import com.epri.fx.server.vo.GroupVO; +import com.epri.fx.server.vo.MenuVO; +import io.datafx.controller.FxmlLoadException; +import io.datafx.controller.injection.scopes.ViewScoped; +import javafx.beans.property.ListProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleListProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +/** + * @description: + * @className: GroupDataModel + * @author: liwen + * @date: 2020/7/22 16:42 + */ +@ViewScoped +public class GroupDataModel { + + + private ListProperty menuVOS; + private SimpleObjectProperty selectedGroupVO = new SimpleObjectProperty<>(new GroupVO()); + private SimpleObjectProperty selectedMenuVO = new SimpleObjectProperty<>(new MenuVO()); + + + public ObservableList getElementVOS() { + return FXCollections.observableArrayList(getSelectedMenuVO().getElementVOS()); + } + + public ListProperty getMenuVOS() { + if (menuVOS == null) { + ObservableList innerList = FXCollections.observableArrayList(); + menuVOS = new SimpleListProperty<>(innerList); + } + return menuVOS; + } + + public GroupVO getSelectedGroup() { + return selectedGroupVO.get(); + } + + public ObjectProperty selectedGroupProperty() { + return selectedGroupVO; + } + + public void setSelectedGroup(GroupVO group) { + this.selectedGroupVO.set(group); + } + + public MenuVO getSelectedMenuVO() { + return selectedMenuVO.get(); + } + + public SimpleObjectProperty selectedMenuVOProperty() { + return selectedMenuVO; + } + + public void setSelectedMenuVO(MenuVO selectedMenuVO) { + this.selectedMenuVO.set(selectedMenuVO); + } +} diff --git a/client/src/main/java/com/epri/fx/client/model/GroupTypeDataModel.java b/client/src/main/java/com/epri/fx/client/model/GroupTypeDataModel.java new file mode 100644 index 0000000..a1418ca --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/model/GroupTypeDataModel.java @@ -0,0 +1,42 @@ +package com.epri.fx.client.model; + +import com.epri.fx.server.vo.GroupTypeVO; +import io.datafx.controller.injection.scopes.FlowScoped; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ListProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleListProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +@FlowScoped +public class GroupTypeDataModel { + private int counter = 0; + private ListProperty groupTypes; + private IntegerProperty selectedIndex; + + public ListProperty getGroupTypes() { + if (groupTypes == null) { + ObservableList innerList = FXCollections.observableArrayList(); + groupTypes = new SimpleListProperty<>(innerList); + } + return groupTypes; + } + + public int getSelectedIndex() { + return selectedIndexProperty().get(); + } + + public void setSelectedIndex(int selectedPersonIndex) { + this.selectedIndex.set(selectedPersonIndex); + } + + public IntegerProperty selectedIndexProperty() { + if (selectedIndex == null) { + selectedIndex = new SimpleIntegerProperty(); + } + return selectedIndex; + } + + +} \ No newline at end of file diff --git a/client/src/main/java/com/epri/fx/client/model/MenuDataModel.java b/client/src/main/java/com/epri/fx/client/model/MenuDataModel.java new file mode 100644 index 0000000..b37b120 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/model/MenuDataModel.java @@ -0,0 +1,60 @@ +package com.epri.fx.client.model; + +import com.epri.fx.server.vo.ElementVO; +import com.epri.fx.server.vo.MenuVO; +import io.datafx.controller.injection.scopes.ViewScoped; +import javafx.beans.property.*; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +@ViewScoped +public class MenuDataModel { + + private ObjectProperty selectMenuVOProperty; + + private ListProperty elementVOS; + + private IntegerProperty selectedElementIndex; + + public ListProperty getElementVOS() { + + if (elementVOS == null) { + ObservableList innerList = FXCollections.observableArrayList(); + elementVOS = new SimpleListProperty<>(innerList); + } + return elementVOS; + } + + + public MenuVO getSelectMenuVO() { + return selectMenuVOPropertyProperty().get(); + } + + public ObjectProperty selectMenuVOPropertyProperty() { + if (selectMenuVOProperty == null) { + selectMenuVOProperty = new SimpleObjectProperty<>(new MenuVO()); + } + return selectMenuVOProperty; + } + + public void setSelectMenuVO(MenuVO selectMenuVOProperty) { + this.selectMenuVOPropertyProperty().set(selectMenuVOProperty); + } + + + public int getSelectedElementIndex() { + return selectedElementIndexProperty().get(); + } + + public IntegerProperty selectedElementIndexProperty() { + + if (selectedElementIndex == null) { + selectedElementIndex = new SimpleIntegerProperty(); + } + return selectedElementIndex; + } + + +} + + diff --git a/client/src/main/java/com/epri/fx/client/model/UserDataModel.java b/client/src/main/java/com/epri/fx/client/model/UserDataModel.java new file mode 100644 index 0000000..73a2238 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/model/UserDataModel.java @@ -0,0 +1,58 @@ +package com.epri.fx.client.model; + +import com.epri.fx.server.vo.UserVO; +import io.datafx.controller.injection.scopes.FlowScoped; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ListProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleListProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +@FlowScoped +public class UserDataModel { + private int counter = 0; + private ListProperty users; + + private IntegerProperty pageCount; + private IntegerProperty selectedPersonIndex; + + + public ListProperty getUsers() { + if (users == null) { + ObservableList innerList = FXCollections.observableArrayList(); + users = new SimpleListProperty<>(innerList); + } + return users; + } + + public int getSelectedPersonIndex() { + return selectedPersonIndexProperty().get(); + } + + public void setSelectedPersonIndex(int selectedPersonIndex) { + this.selectedPersonIndex.set(selectedPersonIndex); + } + + public IntegerProperty selectedPersonIndexProperty() { + if (selectedPersonIndex == null) { + selectedPersonIndex = new SimpleIntegerProperty(); + } + return selectedPersonIndex; + } + + public int getPageCount() { + return pageCount.get(); + } + + public IntegerProperty pageCountProperty() { + if (pageCount == null) { + pageCount = new SimpleIntegerProperty(); + } + return pageCount; + } + + public void setPageCount(int pageCount) { + this.pageCount.set(pageCount); + } +} \ No newline at end of file diff --git a/client/src/main/java/com/epri/fx/client/request/Request.java b/client/src/main/java/com/epri/fx/client/request/Request.java new file mode 100644 index 0000000..6253995 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/request/Request.java @@ -0,0 +1,137 @@ +package com.epri.fx.client.request; + +import com.epri.fx.client.request.feign.AppRequestErrorDecoder; +import com.epri.fx.client.request.feign.AppRequestInterceptor; +import com.epri.fx.client.request.feign.FeignAPI; +import com.netflix.client.ClientFactory; +import com.netflix.client.config.IClientConfig; +import com.netflix.loadbalancer.BestAvailableRule; +import com.netflix.loadbalancer.ILoadBalancer; +import com.netflix.loadbalancer.ZoneAwareLoadBalancer; +import feign.Feign; +import feign.Logger; +import feign.Retryer; +import feign.jackson.JacksonDecoder; +import feign.jackson.JacksonEncoder; +import feign.okhttp.OkHttpClient; +import feign.ribbon.LBClient; +import feign.ribbon.LBClientFactory; +import feign.ribbon.LoadBalancingTarget; +import feign.ribbon.RibbonClient; +import feign.slf4j.Slf4jLogger; +import okhttp3.ConnectionPool; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + + +public class Request { + + private static final Map CONNECTORS = new ConcurrentHashMap<>(); + private static RibbonClient ribbonClient; + + private static String API_URL = "http://sample-client"; + private final static int CONNECT_TIME_OUT_MILLIS = 1000; + private final static int READ_TIME_OUT_MILLIS = 60000; + private static JacksonDecoder jacksonDecoder; + private static JacksonEncoder jacksonEncoder; + private static AppRequestInterceptor requestInterceptor; + private static AppRequestErrorDecoder requestErrorDecoder; + private static Slf4jLogger slf4jLogger; + + /** + * @Description: + * @param: [connectorClass, readTimeOut->设置超时时间] + * @return: T + * @auther: liwen + * @date: 2019-06-05 14:33 + */ + public static T connector(Class connectorClass, int readTimeOut) { + final String commandConfigKey = connectorClass.getSimpleName() + readTimeOut; + + return (T) CONNECTORS.computeIfAbsent(commandConfigKey, k -> { + return Feign.builder() + .client(ribbonClient()) + .decoder(getJacksonDecoder()) + .encoder(getJacksonEncoder()) + .errorDecoder(getRequestErrorDecoder()) + .requestInterceptor(getRequestInterceptor()) + .logger(getSlf4jLogger()) + .logLevel(Logger.Level.FULL) + .retryer(Retryer.NEVER_RETRY) + .options(new feign.Request.Options(CONNECT_TIME_OUT_MILLIS, readTimeOut)) + .target(connectorClass, API_URL); + + }); + + } + + + public static T connector(Class connectorClass) { + return connector(connectorClass, READ_TIME_OUT_MILLIS); + + } + + + private static JacksonDecoder getJacksonDecoder() { + if (jacksonDecoder == null) { + jacksonDecoder = new JacksonDecoder(); + } + return jacksonDecoder; + } + + + private static JacksonEncoder getJacksonEncoder() { + if (jacksonEncoder == null) { + jacksonEncoder = new JacksonEncoder(); + } + return jacksonEncoder; + } + + private static AppRequestInterceptor getRequestInterceptor() { + if (requestInterceptor == null) { + requestInterceptor = new AppRequestInterceptor(); + } + return requestInterceptor; + } + + private static AppRequestErrorDecoder getRequestErrorDecoder() { + if (requestErrorDecoder == null) { + requestErrorDecoder = new AppRequestErrorDecoder(); + } + return requestErrorDecoder; + } + + private static Slf4jLogger getSlf4jLogger() { + if (slf4jLogger == null) { + slf4jLogger = new Slf4jLogger(); + } + return slf4jLogger; + } + + private static RibbonClient ribbonClient() { + + if (ribbonClient == null) { + ribbonClient = RibbonClient.builder().delegate(new OkHttpClient(createOkHttpClient())).lbClientFactory(new LBClientFactory() { + + @Override + public LBClient create(String clientName) { + IClientConfig config = ClientFactory.getNamedConfig(clientName); + ILoadBalancer lb = ClientFactory.getNamedLoadBalancer(clientName); + ZoneAwareLoadBalancer zb = (ZoneAwareLoadBalancer) lb; + zb.setRule(new BestAvailableRule()); + LBClient lbClient = LBClient.create(lb, config); + return lbClient; + } + + + }).build(); + } + return ribbonClient; + } + + private static okhttp3.OkHttpClient createOkHttpClient() { + return new okhttp3.OkHttpClient.Builder().connectionPool(new ConnectionPool()) + .build(); + } +} diff --git a/client/src/main/java/com/epri/fx/client/request/feign/AppRequestErrorDecoder.java b/client/src/main/java/com/epri/fx/client/request/feign/AppRequestErrorDecoder.java new file mode 100644 index 0000000..e41300f --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/request/feign/AppRequestErrorDecoder.java @@ -0,0 +1,20 @@ +package com.epri.fx.client.request.feign; + +import com.epri.fx.client.store.ApplicatonStore; +import com.epri.fx.client.utils.AlertUtil; +import feign.Response; +import feign.codec.ErrorDecoder; + +/** + * @description: + * @className: RequestErrorDecoder + * @author: liwen + * @date: 2020/8/13 09:36 + */ +public class AppRequestErrorDecoder implements ErrorDecoder { + @Override + public Exception decode(String methodKey, Response response) { + AlertUtil.show(response); + return null; + } +} diff --git a/client/src/main/java/com/epri/fx/client/request/feign/AppRequestInterceptor.java b/client/src/main/java/com/epri/fx/client/request/feign/AppRequestInterceptor.java new file mode 100644 index 0000000..16a0ea9 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/request/feign/AppRequestInterceptor.java @@ -0,0 +1,15 @@ +package com.epri.fx.client.request.feign; + +import com.epri.fx.client.store.ApplicatonStore; +import feign.RequestInterceptor; +import feign.RequestTemplate; + +public class AppRequestInterceptor implements RequestInterceptor { + + + @Override + public void apply(RequestTemplate template) { + + template.header("Authorization", ApplicatonStore.getToken()); + } +} \ No newline at end of file diff --git a/client/src/main/java/com/epri/fx/client/request/feign/FeignAPI.java b/client/src/main/java/com/epri/fx/client/request/feign/FeignAPI.java new file mode 100644 index 0000000..b642dda --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/request/feign/FeignAPI.java @@ -0,0 +1,9 @@ +package com.epri.fx.client.request.feign; + +import feign.Headers; + +@Headers("Content-Type: application/json") +public interface FeignAPI { + + +} diff --git a/client/src/main/java/com/epri/fx/client/request/feign/admin/ElementFeign.java b/client/src/main/java/com/epri/fx/client/request/feign/admin/ElementFeign.java new file mode 100644 index 0000000..887eb98 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/request/feign/admin/ElementFeign.java @@ -0,0 +1,29 @@ +package com.epri.fx.client.request.feign.admin; + +import com.epri.fx.client.request.feign.FeignAPI; +import com.epri.fx.server.entity.Element; +import com.epri.fx.server.msg.TableResultResponse; +import feign.Param; +import feign.RequestLine; + +/** + * @description: + * @className: ElementFeign + * @author: liwen + * @date: 2020/7/19 18:55 + */ +public interface ElementFeign extends FeignAPI { + + @RequestLine("GET /element/list/{menuId}") + TableResultResponse getMenuElementList(@Param("menuId") Integer menuId); + + @RequestLine("POST /element") + Integer addElement(Element element); + + @RequestLine("PUT /element") + Integer updateElement(Element element); + + @RequestLine("DELETE /element/{id}") + Integer deleteElement(@Param("id") Integer id); + +} diff --git a/client/src/main/java/com/epri/fx/client/request/feign/admin/GroupFeign.java b/client/src/main/java/com/epri/fx/client/request/feign/admin/GroupFeign.java new file mode 100644 index 0000000..c408c5e --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/request/feign/admin/GroupFeign.java @@ -0,0 +1,46 @@ +package com.epri.fx.client.request.feign.admin; + +import com.epri.fx.client.request.feign.FeignAPI; +import com.epri.fx.server.vo.GroupUsers; +import com.epri.fx.server.vo.GroupVO; +import com.epri.fx.server.vo.MenuVO; +import feign.Param; +import feign.QueryMap; +import feign.RequestLine; + +import java.util.List; +import java.util.Map; + +/** + * @description: + * @className: TestFeign + * @author: liwen + * @date: 2020/4/1 17:31 + */ +public interface GroupFeign extends FeignAPI { + @RequestLine("GET /group/treeList/{groupTypeId}") + List getGroupList(@Param("groupTypeId") Integer groupTypeId); + + @RequestLine("GET /group/{groupId}/authority/menu") + List getAuthorityMenuElementAll(@Param("groupId") Integer groupId); + + @RequestLine("PUT /group/{groupId}/authority/menu") + Integer modifyMenuAuthority(@Param("groupId") int id, List menuVOList); + + @RequestLine("POST /group") + Integer addGroup(GroupVO groupVO); + + @RequestLine("PUT /group") + Integer updateGroup(GroupVO groupVO); + + @RequestLine("DELETE /group") + Integer deleteGroup(GroupVO groupVO); + + + @RequestLine(value = "GET /group/{id}/user") + public GroupUsers getUsers(@Param("id") int id); + + @RequestLine(value = "PUT /group/{id}/user") + public Integer modifiyUsers(@Param("id") int id, @QueryMap Map map); + +} diff --git a/client/src/main/java/com/epri/fx/client/request/feign/admin/GroupTypeFeign.java b/client/src/main/java/com/epri/fx/client/request/feign/admin/GroupTypeFeign.java new file mode 100644 index 0000000..bd7602d --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/request/feign/admin/GroupTypeFeign.java @@ -0,0 +1,29 @@ +package com.epri.fx.client.request.feign.admin; + +import com.epri.fx.client.request.feign.FeignAPI; +import com.epri.fx.server.vo.GroupTypeVO; +import feign.Param; +import feign.RequestLine; + +import java.util.List; + +/** + * @description: + * @className: TestFeign + * @author: liwen + * @date: 2020/4/1 17:31 + */ +public interface GroupTypeFeign extends FeignAPI { + @RequestLine("GET /groupType/all") + List getAllGroupTypes(); + + @RequestLine("POST /groupType") + Integer addGroupType(GroupTypeVO groupTypeVO); + + @RequestLine("PUT /groupType") + Integer updateGroupType(GroupTypeVO groupTypeVO); + + @RequestLine("DELETE /groupType/{groupTypeId}") + Integer deleteGroupTypes(@Param("groupTypeId") int groupTypeId); + +} diff --git a/client/src/main/java/com/epri/fx/client/request/feign/admin/MenuFeign.java b/client/src/main/java/com/epri/fx/client/request/feign/admin/MenuFeign.java new file mode 100644 index 0000000..2ec5694 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/request/feign/admin/MenuFeign.java @@ -0,0 +1,32 @@ +package com.epri.fx.client.request.feign.admin; + +import com.epri.fx.client.request.feign.FeignAPI; +import com.epri.fx.server.vo.MenuVO; +import feign.Headers; +import feign.RequestLine; + +import java.util.List; + +/** + * @description: + * @className: TestFeign + * @author: liwen + * @date: 2020/4/1 17:31 + */ +@Headers("Content-Type: application/json") +public interface MenuFeign extends FeignAPI { + @RequestLine("GET /menu/all") + List getMenuAll(); + @RequestLine("GET /menu/element/all") + List getMenuElementAll(); + + @RequestLine("POST /menu") + Integer addMenu(MenuVO menuVO); + + @RequestLine("PUT /menu") + Integer updateMenu(MenuVO menuVO); + + @RequestLine("DELETE /menu") + Integer deleteMenu(MenuVO menuVO); + +} diff --git a/client/src/main/java/com/epri/fx/client/request/feign/admin/UserFeign.java b/client/src/main/java/com/epri/fx/client/request/feign/admin/UserFeign.java new file mode 100644 index 0000000..06c56d1 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/request/feign/admin/UserFeign.java @@ -0,0 +1,35 @@ +package com.epri.fx.client.request.feign.admin; + +import com.epri.fx.client.request.feign.FeignAPI; +import com.epri.fx.server.entity.User; +import com.epri.fx.server.msg.ObjectRestResponse; +import com.epri.fx.server.msg.TableResultResponse; +import com.epri.fx.server.vo.UserVO; +import feign.Param; +import feign.QueryMap; +import feign.RequestLine; + +import java.util.Map; + +/** + * @description: + * @className: TestFeign + * @author: liwen + * @date: 2020/4/1 17:31 + */ +public interface UserFeign extends FeignAPI { + @RequestLine("GET /user/page") + TableResultResponse getPageList(@QueryMap Map map); + + @RequestLine("PUT /user/{id}") + ObjectRestResponse update(@Param("id") Integer id, User user); + + @RequestLine("DELETE /user/{id}") + ObjectRestResponse delete(@Param("id") Integer id); + + @RequestLine("PUT /user/password/{id}") + ObjectRestResponse restPassword(@Param("id")Integer id); + + @RequestLine("POST /user") + ObjectRestResponse add(User user); +} diff --git a/client/src/main/java/com/epri/fx/client/request/feign/login/LoginFeign.java b/client/src/main/java/com/epri/fx/client/request/feign/login/LoginFeign.java new file mode 100644 index 0000000..69284ac --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/request/feign/login/LoginFeign.java @@ -0,0 +1,36 @@ +package com.epri.fx.client.request.feign.login; + +import com.epri.fx.client.request.feign.FeignAPI; +import com.epri.fx.server.msg.ObjectRestResponse; +import com.epri.fx.server.util.user.JwtAuthenticationRequest; +import com.epri.fx.server.vo.FrontUser; +import com.epri.fx.server.vo.MenuVO; +import feign.Param; +import feign.RequestLine; + +import java.util.List; + +/** + * @description: + * @className: LoginFeign + * @author: liwen + * @date: 2020/8/2 09:47 + */ +public interface LoginFeign extends FeignAPI { + + @RequestLine("POST /jwt/token") + ObjectRestResponse login(JwtAuthenticationRequest request); + + @RequestLine("GET /jwt/invalid") + ObjectRestResponse logout(JwtAuthenticationRequest request); + + @RequestLine("GET /user/front/info/{token}") + ObjectRestResponse getInfo(@Param("token") String token); + + @RequestLine("GET /user/front/menus/{token}") + List getMenus(@Param("token") String token); + + @RequestLine("GET /user/front/menus/all/{token}") + List getMenuAll(@Param("token") String token); + +} diff --git a/client/src/main/java/com/epri/fx/client/store/ApplicatonStore.java b/client/src/main/java/com/epri/fx/client/store/ApplicatonStore.java new file mode 100644 index 0000000..abf3c9f --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/store/ApplicatonStore.java @@ -0,0 +1,187 @@ +package com.epri.fx.client.store; + +import com.epri.fx.client.bean.MenuVoCell; +import com.epri.fx.server.vo.GroupVO; +import com.epri.fx.server.vo.MenuVO; +import com.epri.fx.server.vo.PermissionInfo; +import javafx.beans.property.*; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.collections.ObservableMap; + +import java.util.HashMap; +import java.util.Map; + +/** + * @description: + * @className: User + * @author: liwen + * @date: 2020/8/2 10:17 + */ + +public class ApplicatonStore { + + public static String ICON_FONT_KEY = "icon.svg"; + private static SimpleIntegerProperty status = new SimpleIntegerProperty(); + private static SimpleStringProperty code = new SimpleStringProperty(); + private static SimpleStringProperty token = new SimpleStringProperty(); + private static SimpleStringProperty name = new SimpleStringProperty(); + private static SimpleStringProperty avatar = new SimpleStringProperty(); + private static SimpleStringProperty introduction = new SimpleStringProperty(); + private static ListProperty roles; + private static ListProperty menus; + private static ListProperty permissionMenus; + private static ListProperty allMenu; + private static ListProperty menuVoCells; + private static ListProperty elements; + private static MapProperty featureMap; + + + public static int getStatus() { + return status.get(); + } + + public static SimpleIntegerProperty statusProperty() { + return status; + } + + public static void setStatus(int status) { + ApplicatonStore.status.set(status); + } + + public static String getCode() { + return code.get(); + } + + public static SimpleStringProperty codeProperty() { + return code; + } + + public static void setCode(String code) { + ApplicatonStore.code.set(code); + } + + public static String getToken() { + return token.get(); + } + + public static SimpleStringProperty tokenProperty() { + return token; + } + + public static void setToken(String token) { + ApplicatonStore.token.set(token); + } + + public static String getName() { + return name.get(); + } + + public static SimpleStringProperty nameProperty() { + return name; + } + + public static void setName(String name) { + ApplicatonStore.name.set(name); + } + + public static String getAvatar() { + return avatar.get(); + } + + public static SimpleStringProperty avatarProperty() { + return avatar; + } + + public static void setAvatar(String avatar) { + ApplicatonStore.avatar.set(avatar); + } + + public static String getIntroduction() { + return introduction.get(); + } + + public static SimpleStringProperty introductionProperty() { + return introduction; + } + + public static void setIntroduction(String introduction) { + ApplicatonStore.introduction.set(introduction); + } + + + public static ListProperty getRoles() { + if (roles == null) { + ObservableList innerList = FXCollections.observableArrayList(); + roles = new SimpleListProperty<>(innerList); + } + return roles; + } + + + public static ListProperty getMenus() { + if (menus == null) { + ObservableList innerList = FXCollections.observableArrayList(); + menus = new SimpleListProperty<>(innerList); + } + return menus; + } + + + public static ListProperty getAllMenu() { + if (allMenu == null) { + ObservableList innerList = FXCollections.observableArrayList(); + allMenu = new SimpleListProperty<>(innerList); + } + return allMenu; + } + + public static ListProperty getMenuVoCells() { + if (menuVoCells == null) { + ObservableList innerList = FXCollections.observableArrayList(); + menuVoCells = new SimpleListProperty<>(innerList); + } + + return menuVoCells; + } + + + public static ListProperty getElements() { + if (elements == null) { + ObservableList innerList = FXCollections.observableArrayList(); + elements = new SimpleListProperty<>(innerList); + } + return elements; + } + + public static MapProperty getFeatureMap() { + if (featureMap == null) { + ObservableMap map = FXCollections.observableMap(new HashMap<>()); + featureMap = new SimpleMapProperty<>(map); + } + return featureMap; + } + + public static ListProperty getPermissionMenus() { + if (permissionMenus == null) { + ObservableList innerList = FXCollections.observableArrayList(); + permissionMenus = new SimpleListProperty<>(innerList); + } + return permissionMenus; + } + + public static void clearPermissionInfo() { + setName(""); + getAllMenu().clear(); + getMenuVoCells().clear(); + getMenus().clear(); + ApplicatonStore.getElements().clear(); + getPermissionMenus().clear(); + getRoles().clear(); + getFeatureMap().clear(); + } + + +} + + diff --git a/client/src/main/java/com/epri/fx/client/utils/AlertUtil.java b/client/src/main/java/com/epri/fx/client/utils/AlertUtil.java new file mode 100644 index 0000000..bbaec03 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/utils/AlertUtil.java @@ -0,0 +1,48 @@ +package com.epri.fx.client.utils; + +import com.epri.fx.server.msg.BaseResponse; +import com.jfoenix.controls.JFXAlert; +import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXDialogLayout; +import feign.Response; +import io.datafx.controller.context.ApplicationContext; +import javafx.scene.control.Label; +import javafx.stage.Modality; +import javafx.stage.Stage; + +/** + * @description: + * @className: AlerUtil + * @author: liwen + * @date: 2020/8/2 13:39 + */ +public class AlertUtil { + + public static void show(BaseResponse response) { + JFXAlert alert = new JFXAlert(ApplicationContext.getInstance().getRegisteredObject(Stage.class)); + alert.initModality(Modality.APPLICATION_MODAL); + alert.setOverlayClose(false); + JFXDialogLayout layout = new JFXDialogLayout(); + layout.setHeading(new Label("提示")); + layout.setBody(new Label(response.getStatus() + "\t" + response.getMessage())); + JFXButton closeButton = new JFXButton("确定"); + closeButton.setOnAction(event -> alert.hideWithAnimation()); + layout.setActions(closeButton); + alert.setContent(layout); + alert.show(); + } + + public static void show(Response response) { + JFXAlert alert = new JFXAlert(ApplicationContext.getInstance().getRegisteredObject(Stage.class)); + alert.initModality(Modality.APPLICATION_MODAL); + alert.setOverlayClose(false); + JFXDialogLayout layout = new JFXDialogLayout(); + layout.setHeading(new Label("提示")); + layout.setBody(new Label(response.status() + "\t" + response.reason())); + JFXButton closeButton = new JFXButton("确定"); + closeButton.setOnAction(event -> alert.hideWithAnimation()); + layout.setActions(closeButton); + alert.setContent(layout); + alert.show(); + } +} diff --git a/client/src/main/java/com/epri/fx/client/utils/Helper.java b/client/src/main/java/com/epri/fx/client/utils/Helper.java new file mode 100644 index 0000000..ba35a49 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/utils/Helper.java @@ -0,0 +1,12 @@ +package com.epri.fx.client.utils; + +/** + * @description: + * @className: Helper + * @author: liwen + * @date: 2020/9/22 16:05 + */ +public class Helper { + private static final String COUNTRY_PROPERTIES = "resources/country/中国.svg"; + +} diff --git a/client/src/main/java/com/epri/fx/client/utils/Pinyin4jUtil.java b/client/src/main/java/com/epri/fx/client/utils/Pinyin4jUtil.java new file mode 100644 index 0000000..f4e6ae2 --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/utils/Pinyin4jUtil.java @@ -0,0 +1,161 @@ +package com.epri.fx.client.utils; + +import net.sourceforge.pinyin4j.PinyinHelper; +import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; +import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; +import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; +import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; + +/** + * 汉字转换成拼音方法 + * + * @author 蔡龙 + */ + +public class Pinyin4jUtil { + + static HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat(); + + public static enum Type { + UPPERCASE, //全部大写 + LOWERCASE, //全部小写 + FIRSTUPPER //首字母大写 + } + + static { + + format.setCaseType(HanyuPinyinCaseType.UPPERCASE); + format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); + } + + /** + * 转换全部大写 + * + * @param str 字符串 + * @return str为颐和园 ,return获取到的是YHY + */ + public static String toPinYinUppercase(String str) { + return toPinYin(str, "", Type.UPPERCASE); + } + + /** + * 转换全部大写 + * + * @param str 字符串 + * @param spera 转换字母间隔加的字符串,如果不需要为"" + * @return str为颐和园 ,spera为** return获取到的是Y**H**Y + */ + public static String toPinYinUppercase(String str, String spera) { + return toPinYin(str, spera, Type.UPPERCASE); + } + + /** + * 转换全部小写 + * + * @param str 字符串 + * @return str为颐和园 ,return获取到的是yhy + * @ + */ + public static String toPinYinLowercase(String str) { + return toPinYin(str, "", Type.LOWERCASE); + } + + /** + * 转换全部小写 + * + * @param str 字符串 + * @param spera 转换字母间隔加的字符串,如果不需要为"" + * @return str为颐和园 ,spera为** return获取到的是y**h**y + * @ + */ + public static String toPinYinLowercase(String str, String spera) { + return toPinYin(str, spera, Type.LOWERCASE); + } + + /** + * 获取拼音首字母(大写) + * + * @param str 字符串 + * @return str为颐和园 ,return获取到的是Y + * @ 异常信息 + */ + public static String toPinYinUppercaseInitials(String str) { + String initials = null; + String py = toPinYinUppercase(str); + if (py.length() > 1) { + initials = py.substring(0, 1); + } + if (py.length() <= 1) { + initials = py; + } + return initials.trim(); + } + + /** + * 获取拼音首字母(小写) + * + * @param str 字符串 + * @return str为颐和园 ,return获取到的是y + * @ 异常信息 + */ + public static String toPinYinLowercaseInitials(String str) { + String initials = null; + String py = toPinYinLowercase(str); + if (py.length() > 1) { + initials = py.substring(0, 1); + } + if (py.length() <= 1) { + initials = py; + } + return initials.trim(); + } + + /** + * 将str转换成拼音,如果不是汉字或者没有对应的拼音,则不作转换 + * + * @param str 字符串 + * @param spera 默认,可为"" + * @param type 转换格式 + * @return 按照转换格式转换成字符串 + */ + public static String toPinYin(String str, String spera, Type type) { + if (str == null || str.trim().length() == 0) { + return ""; + } + if (type == Type.UPPERCASE) { + format.setCaseType(HanyuPinyinCaseType.UPPERCASE); + } else { + format.setCaseType(HanyuPinyinCaseType.LOWERCASE); + } + String py = ""; + String temp = ""; + String[] t = null; + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if ((int) c <= 128) { + py += c; + } else { + try { + t = PinyinHelper.toHanyuPinyinStringArray(c, format); + } catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) { + badHanyuPinyinOutputFormatCombination.printStackTrace(); + } + if (t == null) { + py += c; + } else { + temp = t[0]; + if (type == Type.FIRSTUPPER) { + temp = t[0].toUpperCase().charAt(0) + temp.substring(1); + } + if (temp.length() >= 1) { + temp = temp.substring(0, 1); + } + py += temp + (i == str.length() - 1 ? "" : spera); + } + } + } + return py.trim(); + } +} + + diff --git a/client/src/main/java/com/epri/fx/client/websocket/Session.java b/client/src/main/java/com/epri/fx/client/websocket/Session.java new file mode 100644 index 0000000..19cebbc --- /dev/null +++ b/client/src/main/java/com/epri/fx/client/websocket/Session.java @@ -0,0 +1,24 @@ +package com.epri.fx.client.websocket; + +import io.datafx.controller.injection.scopes.ApplicationScoped; +import io.datafx.controller.injection.scopes.FlowScoped; + +/** + * @description: + * @className: Session + * @author: liwen + * @date: 2020/6/24 16:17 + */ +@ApplicationScoped +public class Session { + + private int counter = 0; + + public Session() { + + } + + public void print(String from) { + System.out.println(from + ": counter = " + counter++); + } +} diff --git a/client/src/main/resources/META-INF/datafx.xml b/client/src/main/resources/META-INF/datafx.xml new file mode 100644 index 0000000..1c0aa57 --- /dev/null +++ b/client/src/main/resources/META-INF/datafx.xml @@ -0,0 +1,7 @@ + + + + com.epri.fx.client.gui.uicomponents.feature.UserGroupFeatures + + + \ No newline at end of file diff --git a/client/src/main/resources/country/中国.svg b/client/src/main/resources/country/中国.svg new file mode 100644 index 0000000..369e394 --- /dev/null +++ b/client/src/main/resources/country/中国.svg @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/client/src/main/resources/css/app-fonts.css b/client/src/main/resources/css/app-fonts.css new file mode 100644 index 0000000..bb58148 --- /dev/null +++ b/client/src/main/resources/css/app-fonts.css @@ -0,0 +1,15 @@ +@font-face { + font-family: 'Microsoft YaHei'; + src: url("../fonts/msyh.ttf"); +} + +@font-face { + font-family: 'Microsoft YaHei Light'; + src: url("../fonts/msyhl.ttf"); +} + +@font-face { + font-family: 'Microsoft YaHei Bold'; + src: url("../fonts/msyhbd.ttf"); +} + diff --git a/client/src/main/resources/css/app.css b/client/src/main/resources/css/app.css new file mode 100644 index 0000000..c5b531e --- /dev/null +++ b/client/src/main/resources/css/app.css @@ -0,0 +1,918 @@ + +.root { + /**全局定义主题颜色变量 默认*/ + -fx-main-base: #1B2431; + -fx-card-base: #273142; + -fx-bar-base: #323D4E; + + /* 用于突出显示/突出显示对象。例如:selected *文本;菜单,列表,树和表中的选定项目;进度条*/ + -fx-accent-color: #4880ff; + -fx-accent-suspension-color: rgba(72, 128, 255, 0.13); + /*边框颜色*/ + -fx-border-base: #313D4F;; + -fx-cell-border-base: rgba(151, 151, 151, .4); + + -fx-font-base14: 14px; + -fx-font-base16: 16px; + + /**字体颜色*/ + -fx-dark-text-color: #ffffff; + -fx-light-text-color: #404040; + -fx-text-color: ladder(-fx-main-base, -fx-dark-text-color 29%, -fx-light-text-color 30%); + + +} + +.backgroundPane { + -fx-background-color: -fx-main-base; +} + +.jfx-svg-glyph { + -fx-background-color: -fx-text-color; +} + +.glyph-icon { + -fx-fill: -fx-text-color; +} + +.card-pane { + -fx-background-color: -fx-card-base; + -fx-padding: 10; + -fx-background-radius: 14; + -fx-border-color: #313D4F; + -fx-border-width: 1px; + -fx-border-radius: 14px; +} + + +/******************************************************************************* +* * +* text和label * +* * +*******************************************************************************/ +.text, .label { + -fx-text-fill: -fx-text-color; + -fx-font-family: "Microsoft YaHei"; + -fx-font-weight: 100; + -fx-font-size: -fx-font-base14; +} + +/******************************************************************************* + * * + * JFX Pop Up * + * * + ******************************************************************************/ + +.jfx-popup-overlay-pane { + -fx-background-color: transparent; +} + +.jfx-popup-container { + -fx-background-color: -fx-card-base; + -fx-background-radius: 14; + -fx-border-color: #313D4F; + -fx-border-width: 1px; + -fx-border-radius: 14px; +} + + +.jfx-snackbar-content { + -fx-background-color: #323232; +} + +.jfx-snackbar-toast { + -fx-text-fill: WHITE; +} + +.jfx-snackbar-action { + -fx-text-fill: #ff4081; +} + + +/******************************************************************************* +* * +* JFX Button * +* * +*******************************************************************************/ + +.jfx-button { + -fx-padding: 0.47em 0.47em; + -fx-background-color: -fx-accent-color; + -fx-text-fill: -fx-text-color; + -jfx-button-type: RAISED; +} + +.jfx-button > MaterialDesignIconView, .toggle-button > MaterialDesignIconView { + -fx-fill: -fx-text-color; + -fx-text-fill: -fx-text-color; + -fx-prompt-text-fill: -fx-text-color; + -jfx-size: 16px; +} + + +.left-pill { + -fx-text-fill: -fx-text-color; + -fx-background-insets: 0; + -fx-background-color: -fx-bar-base; + -fx-border-color: rgba(207, 207, 207, 0.11); + -fx-background-radius: 14 0 0 14; + -fx-border-radius: 14 0 0 14; + -fx-padding: 0.333333em 0.666667em 0.333333em 0.75em; /* 4 8 4 9 */ +} + +.center-pill { + -fx-text-fill: -fx-text-color; + -fx-background-color: -fx-bar-base; + -fx-border-color: rgba(207, 207, 207, 0.11); + -fx-border-width: 1 1 1 0; + -fx-background-radius: 0; + -fx-background-insets: 0; +} + +.right-pill { + -fx-text-fill: -fx-text-color; + -fx-background-color: -fx-bar-base; + -fx-border-color: rgba(207, 207, 207, 0.11); + -fx-background-radius: 0 14 14 0; + -fx-border-radius: 0 14 14 0; + -fx-border-width: 1 1 1 0; + -fx-background-insets: 0; + +} + +.left-pill:hover { + -fx-background-color: derive(-fx-bar-base, 20%) +} + +.left-pill:focused { + -fx-background-insets: 0; + -fx-background-radius: 14 0 0 14; +} + +.left-pill:pressed { + -fx-background-color: derive(-fx-bar-base, 30%) +} + +.center-pill:focused { + -fx-background-insets: 0; + -fx-background-radius: 0, 0, 0, 0, 0; +} + +.center-pill:hover { + -fx-background-color: derive(-fx-bar-base, 20%) +} + +.center-pill:pressed { + -fx-background-color: derive(-fx-bar-base, 30%) +} + +.right-pill:focused { + -fx-background-insets: 0; + -fx-background-radius: 0 14 14 0; +} + +.right-pill:hover { + -fx-background-color: derive(-fx-bar-base, 20%) +} + +.right-pill:pressed { + -fx-background-color: derive(-fx-bar-base, 30%) +} + +.toggle-button:selected .left-pill:focused { + -fx-background-insets: 0; + -fx-background-radius: 14 0 0 14; +} + +.toggle-button:selected .center-pill:focused { + -fx-background-insets: 0; + -fx-background-radius: 0, 0, 0, 0; +} + +.toggle-button:selected .right-pill:focused { + -fx-background-insets: 0; + -fx-background-radius: 0 14 14 0 +} + + +/******************************************************************************* +* * +* JFX Decorator * +* * +*******************************************************************************/ + +.lfx-decorator { + -fx-decorator-color: -fx-card-base; + -fx-background-color: transparent; + +} + +.lfx-decorator .lfx-decorator-buttons-container { + -fx-background-color: -fx-decorator-color; +} + +.lfx-decorator .resize-border { + -fx-border-color: -fx-decorator-color; + -fx-border-width: 0; +} + +.lfx-decorator .lfx-decorator-title-container .lfx-decorator-text { + -fx-fill: -fx-text-color; + -fx-font-size: 16; +} + +.lfx-decorator .lfx-decorator-title-container .jfx-svg-glyph { + /*-fx-shape: "M223.3 179.2l-6.9-6.9-5.9 6.6-41 42.3-6.4 6.4 7.2 6.5 43.6 41.3 7.4 7.4 7.6-8-1-0.8 38.1-39.3 1.4 1.3 7.8-8m-54.3 39.3L178 226.5l38.1-39.3 43 40.8-38.2 39.3z M188.9 222.7l-5.6 5.4 7.1 6.9 5.2-5.8 8.1-8.4 6.3 6-6.4 6.7-5.6 5.5 7.1 6.6 5.3-5.7 6.4-6.7 8.8 8.3-8.7 9-5.8 5.6 7 6.6 5.4-5.9 24.6-25.4 6-5.9-7-6.6-4.5 5.1c-0.2-2.3-0.2-4.3-0.4-6.2l-3.1 0.1-4.3 0.3c-0.8 0-1.8 0-3.1-0.1l4.9-4.6-7.2-6.8-3.9 4.3-7.8 8.1-6.5-6 8.3-8.5 5.8-5.4-7.2-6.9-5.7 6.3-23.5 24.1z m39.9-1.8c0.1 2.4-0.1 4.6-0.5 6.5 4.1-0.5 6.8-0.6 7.9-0.5 1.2 0.1 2.4 0.2 3.2 0.4l-6.1 6.3-8.7-8.3 4.2-4.4zM346.9 144.6c1.8-3.3 3.9-7.1 6.4-11.4-4.5-0.6-7.3-1.1-8.3-1.4-1-0.3-2.2-0.7-3.5-1.3l-2.1 5.7c-0.5 1.6-2.8 6-6.9 13.5l-2.7-1.3c-0.9-0.5-3.1-0.9-6.4-1.4 1.9-2.9 3.9-5.9 5.9-9-1.6-0.2-3.1-0.4-4.6-0.7l11.9-6.1 7.8-3.8-4.4-8.4-7.7 4.1-33.5 17.3-7.1 3.4 4.5 8.5 6.8-3.8 11.8-6.1c-5 6.9-9.6 11.9-13.8 14.9-4.1 2.9-7.3 5.3-9.8 6.9 3.5 1.9 5.7 3.1 6.6 3.8 0.8 0.6 1.9 1.4 2.9 2.4 4-3.7 7-6.3 8.8-8.1 1.8-1.6 4.2-4.3 7.5-7.8l1.3 0.3c-2.1 3.7-4.5 7.2-7.1 10.6-2.7 3.2-5 5.8-7 7.8-2 1.9-4.4 3.9-7.4 6.1 3 1.6 5 2.7 6.1 3.5 0.9 0.6 2 1.4 3.2 2.4 5.7-5.6 9.9-10.3 12.4-14 2.7-3.6 5.5-7.8 8.5-12.8 0.5 0.3 1.2 0.8 1.7 1.3-2 4.1-5.2 9.4-9.5 15.6-4.3 6.3-10.6 12.7-18.7 19l4.4 2.2c1.3 0.6 3.1 1.9 5.6 3.8l8.5-9.4c2.5-2.6 5.3-6.2 8.5-10.6 3.1-4.5 5.6-8.5 7.5-12l0.4 1c0.5 0.9 1.1 2.3 1.7 4 0.7 1.6 0.7 3.1-0.1 4.3-0.6 1.3-3.3 2.6-7.8 4.1l3.4 2.7c0.9 0.6 2.6 2.5 5.2 5.6 6.3-3.4 9.9-6.3 10.8-8.7 0.9-2.5 0.9-4.9 0.4-7.2-0.7-2.1-1.8-4.8-3.5-8-1.8-3.1-2.9-5.3-3.7-6.4-0.7-1-1.5-2.2-2.4-3.5l2.1-3.1c3.5 3.5 6.7 6.2 9.6 8.3 2.9 1.9 6.2 3.5 10 4.9 3.8 1.4 9.1 2.2 16 2.7 0.3-3.3 0.6-5.6 0.9-7 0.3-1.4 0.7-3.1 1.3-5.3-4.8 0.5-9.7 0.2-14.7-1-4.8-1-8.7-2.8-11.6-5.3-2.7-2.4-4.7-4.4-6.1-5.8z M280.2 150.5l2 4.4 10.3-5.3-2.4-4.2-2.8-5.5 52-26.9 3 5.8 2.2 4.5 10.3-5.2-2.6-4.4-4.6-8.7-2.8-5.9-8.3 4.6-23.1 11.9c0.3-0.8 0.7-1.8 1.3-2.8-2.5-0.7-6.3-1.7-11.4-2.8-2 3.1-3.3 5.2-3.9 6-0.6 0.9-1.5 1.9-2.4 3 2.7 0.6 4.8 1.2 6.4 1.8l-21.6 11.1-9.2 4.3 3.1 5.6 4.5 8.7zM415.5 124.3l1.2 9.3 11.3-1.8-0.3-1.3 17.2-2.7 2 13c0.3 2 0.7 3.6 1.4 4.8 0.7 1.1 1.9 2.1 3.8 2.8 1.9 0.7 4.5 0.9 8 0.3 3.5-0.5 7.9-1.1 13.5-1.8 5.8-0.7 10-1.4 12.8-1.9 2.8-0.6 4.8-1.3 6.1-2 1.3-0.8 2.4-1.9 3.4-3.4s1.9-5.4 2.8-11.8c-3.3-0.6-7.2-1.8-11.6-3.5v3.6c0.1 2.3-0.4 4-1.4 5.1-1 1.1-2.4 1.8-4.1 2.3-1.8 0.5-4.8 0.9-9.1 1.5l-9.8 1.3c-2.1 0.3-3.5 0.1-4.1-0.4-0.6-0.7-0.9-1.3-1.1-2.1l-1.5-9.4 19.5-3.1 0.3 1.7 11.2-1.7-1.6-8.7-5.5-35.2-1-7.9-7.3 1.4-23.5 3.6-0.8-5-0.9-7.1-11.6 1.8 1.4 7 0.7 5.1-19.8 3.1-8.6 1 1.6 7.9 5.4 34.2z m56.6-21.1l1.6 10.1-19.5 3.1-1.6-10.2 19.5-3z m-3.2-19.8l1.6 10.3-19.5 3-1.6-10.3 19.5-3z m-25.6 34.7l-17.1 2.6-1.6-10.2 17-2.6 1.7 10.2z m-4.8-30l1.7 10.4-17.1 2.6-1.6-10.3 17-2.7zM616.3 76.1l-51.8-9-10.9-2.3-1.7 10.9-9.5 53.4-2.2 11.7 11.7 2.1 2-11.8 1.9-10.9c1.9 2.7 3.1 4.6 3.7 5.6 0.5 1.1 1.2 2.2 1.7 3.3 4-3.8 6.5-6.4 7.6-7.7 1.1-1.3 2-2.4 2.7-3.5l0.8 2.6c0.2 0.5 0.3 1.7 0.5 3.9l2.4-1.6c1.5-0.9 4-2 7.7-3.3-1.4-4.6-2.9-9-4.6-13.2l1.5-2.9c0.5-1 1.5-3.3 3-6.8 2.3 3.9 3.7 6.5 4.2 7.6 0.4 1 1.4 3.5 2.6 7.1l-2 3.5c-1.4 2.5-3.3 4.9-5.4 7.3-2.1 2.3-5 4.6-8.5 7 2.7 2.2 4.5 3.7 5.3 4.7 0.8 0.9 1.7 2 2.6 3.1 2-1.4 3.7-2.8 4.9-4.1 1.3-1.3 4-4.3 8-9.1l1.4 5.3c0.2 0.5 0.5 2.1 1 4.8 3.6-2.5 6.9-4.6 9.8-6.2l-1-3.2c-0.1-0.3-1.7-4.5-4.7-12.4l2.3-5.4c0.8-2 1.8-4.7 3.1-8.1l1.8-5.2c0.1-0.5 0.4-1.5 0.9-2.6-3.6-0.9-7.2-2-10.9-3.5l-0.5 2.8c-0.3 1.5-1.1 4.4-2.5 8.7-1.2-2.4-2.2-4.7-3.3-6.6l-2.2 1.4c-1.3 0.8-3.5 1.6-6.5 2.3l1.8-4.5c0-0.1 0.3-0.8 0.7-2.2 0.5-1.3 0.9-2.5 1.3-3.4-4.3-1.1-7.8-2.4-10.6-3.9l-0.8 3.7c-0.3 1.5-0.7 2.9-1.1 4.3-0.4 1.2-0.9 2.7-1.6 4.1-1.3-2.8-2.5-5.3-3.4-7.6-2.7 1.5-4.5 2.4-5.4 2.6-0.9 0.3-1.8 0.6-2.8 0.8l2.2-12.3 50.8 8.8-9.3 52.5c-0.2 1.1-0.5 1.8-1 2.3-0.5 0.6-1.9 0.6-4.1 0.1-1.9-0.4-3.9-0.9-5.9-1.6l0.9 3.1c0.8 3 1.1 5.2 1 6.6 0 1.5-0.2 2.6-0.2 3.5 5.8 0.7 10.1 0.7 12.8 0.3 2.7-0.5 4.5-1.4 5.2-2.9 0.7-1.6 1.2-3.3 1.6-5.1l10-56.6 2.2-10.8-11.2-1.5zM562.5 95c0.4 0.9 2 4.4 4.5 10.4-1.8 3.5-3.5 6.1-5.1 7.9-1.6 1.8-3.6 3.7-6 5.6l4.9-27.3 1.7 3.4zM731.6 161.2c1.8 4.6 4.5 9.1 7.7 13.4 4.5-3 7.2-4.8 8.3-5.4 1.1-0.6 2.3-1.1 3.5-1.5-2.6-2.5-4.3-4.4-5.2-5.5-0.7-1.1-1.7-2.6-2.6-4.3-1-1.8-2-4.3-3.2-7.7-1.2-3.4-1.5-7.1-0.9-11 0.5-4 1.1-6.6 1.6-8.2 0.5-1.4 0.9-2.6 1.5-3.5 0.5-1 1-2 1.8-3-4-1.9-7.5-4-10.6-6.3-1.9 5-3.1 8.5-3.7 10.6-0.6 2.2-1 5.1-1.5 8.5-0.4 3.6-0.5 7.2 0 11 0.3 4.1 1.5 8.3 3.3 12.9zM676.6 139.4c5-1 10.6-2.4 16.8-4.3 6.2-1.9 11.3-4 15.3-6.3 4-2.2 8.9-5 14.7-8.3-2.8-3-5.3-6.3-7.6-10.1l-2.2 1.9c-3.5 3-7.5 5.6-12.1 7.8-4.7 2.1-9.5 3.9-14.6 5.2-5.2 1.3-9.7 1.8-13.6 1.3l1.2 2.8c0.5 1.7 1.3 5.1 2.1 10zM673.8 174.3c2.3 1 8.2 3.4 18 7.7 9.8 4.2 17.2 7.5 22.4 9.9 0.2 3 0.3 5 0.2 6.1-0.1 1.1-0.1 2.3-0.3 3.7l3.4-0.8c0.2-0.1 3.4-0.5 9.9-1.4-0.9-8.5-2.3-19.5-4.2-33l-2.4 0.3c-1.4 0.2-4.5 0.1-9.3-0.5l1.2 5.8c0.3 1.5 0.7 4.6 1.2 9.5-10.1-5-20.4-9.9-30.7-15.1 5-1.5 9.2-2.9 12.7-4.2 3.5-1.4 6.9-2.8 10.4-4.4l7.3-3.5c0.9-0.4 2.2-1 4-1.9-2.6-3.7-5-7.7-7.1-11.9l-1.8 1.7c-0.9 0.7-2.9 2.3-6.3 4.5-3.3 2.3-6.6 4.1-9.9 5.7-3.3 1.5-6.5 2.8-9.5 3.9-3.1 1.1-5.6 1.8-7.4 2.1-1.8 0.3-4.6 0.5-8.3 0.7l0.1 3.1c0.1 2-0.3 5.2-1.3 9.6 2.8 0.7 5.4 1.6 7.7 2.4zM821.3 234l-18.7-20-5.9-6.8-5.8 5.8-11.5 10.7-6.7 5.6 6.4 6.4 18.8 19.9 6.6 7.4 6.2-6.2 11.5-10.7 6.3-5.2-7.2-6.9z m-17 14l-16.5-17.5 9-8.3 16.5 17.4-9 8.4z M829.4 233.1l7.5 8.4 7.9-7.3-8.1-7.9-26.3-28-6.8-7.6-7.8 7.2 7.3 7.3z M855 233.2l-40.8 37.7c-1.3 1.2-2.2 1.7-2.9 1.8-0.7 0-1.7-0.6-3-1.9-0.5-0.4-1.3-1.3-2.3-2.4-1.1-1.2-2.1-2.4-3-3.4l-1.4 3.3c-0.8 1.8-1.6 3.3-2.6 4.5-0.9 1.2-1.8 2.3-2.6 3.3 5.4 5 9.2 7.9 11.7 8.8 2.4 0.9 4.1 1.2 5.2 0.8 1-0.3 2.6-1.4 4.5-3.3l45.4-41.8 7.2-6.1-7.2-7.3-36.2-38.5-7.9-8.7-8 7.3 8.4 8.4 35.5 37.5zM120.2 359.2c4.7 2.2 8.9 2.7 12.7 1.6 3.8-1.2 8-4.3 12.7-9.8 0.5-0.5 1.2-1.3 2.2-2.4 6.4-7.7 11.2-10.7 14.2-9.3 1.7 0.8 2.8 2.2 3.3 4.2 0.4 2 0 4.1-1.1 6.4-1.5 3.1-4.1 5.6-7.6 7.4-3.6 1.8-7.7 2.6-12.5 2.6l-0.5 6.4 19.4 4 2.4-4.9-2.4-2.5c2.2-1.2 4.2-2.6 5.8-4.3 1.6-1.7 3-3.7 4.1-5.8 2.6-5.3 3-10.5 1.3-15.7-1.8-5.2-5.3-9-10.6-11.5-2.7-1.3-5.4-1.9-8.1-2-2.7-0.1-5.3 0.5-7.6 1.6-1.1 0.6-2.7 1.7-4.5 3.5-1.8 1.8-4.2 4.2-7.2 7.3-0.4 0.5-0.9 1.1-1.7 2-5.8 6.5-10.3 9-13.3 7.5-2-1-3.4-2.7-4-5.3-0.6-2.4-0.3-5 1-7.6 1.8-3.8 5-6.6 9.4-8.6 4.5-2 9.8-2.9 16.1-2.7l0.6-7.1-24.5-4.2-2.3 4.7 3.2 2.6c-2.4 1.6-4.7 3.3-6.5 5.4-1.9 2.1-3.5 4.3-4.7 6.9-3 5.9-3.4 11.5-1.4 17 1.9 5.3 6 9.5 12.1 12.6zM96.8 396.5c1.6-0.4 4.8 0 9.5 1.5l34.2 10.9-0.2 0.9c-1.2 3.5-3 6.2-5.8 7.9-2.7 1.7-6.7 2.9-12.1 3.6l0.6 6 20.8-0.3 14.7-45-16.7-12.2-4 4.5c4.1 3.6 6.6 6.9 7.7 9.8 1.2 3 1.2 6.2-0.1 9.8l-0.2 0.9-34.2-10.9c-4.8-1.6-7.7-2.9-8.7-4.3-1-1.4-1.1-3.2-0.4-5.8l-7.5-2.4-8.8 27.2 7.6 2.3c0.8-2.4 2-4 3.6-4.4zM89.1 469l0.4-0.1 49.7-6.9 2.5-12.9-41.4-24.4c-0.3-0.1-0.6-0.3-1.1-0.6-5.4-3.1-8.1-6.8-7.9-10.9l-7.8-1.4-4.5 23.5 7.6 1.5c0.5-2.4 1.2-3.9 2-4.7 0.9-0.7 2.2-1 3.7-0.6 0.2 0 0.5 0.1 0.8 0.2 0.3 0.1 0.6 0.2 1 0.3l8.2 4-3.3 17.3-9.3 1.3c-0.4 0.1-0.8 0.1-1.3 0.1-0.5-0.1-1-0.1-1.6-0.2-1.3-0.2-2.2-0.8-2.6-1.7-0.4-0.9-0.4-2.4 0-4.4l0.1-0.7-7.6-1.4-5.3 27.4 7.8 1.4c1.4-3.3 4.6-5.3 9.9-6.1z m20.5-28.6l17 9.5-19.1 1.9 2.1-11.4zM81.1 510c1.4-0.9 4.6-1.2 9.7-1l35.8 1.6v0.9c-0.1 3.7-1.3 6.7-3.5 9.2-2.1 2.3-5.6 4.5-10.7 6.5l2.2 5.6 20-5.6 2.1-47.3-19.3-7.4-2.7 5.3c4.8 2.5 8.1 5 10.1 7.5 1.8 2.6 2.7 5.7 2.5 9.4l-0.1 0.9-35.8-1.7c-5.1-0.2-8.3-0.8-9.5-1.9-1.4-0.9-2-2.8-1.9-5.5l-7.9-0.3-1.4 28.4 7.9 0.4c0.3-2.4 1.2-4 2.5-5zM103.2 590.2c-5.9-2.4-10.6-5.4-14.2-9.3-3.6-3.8-5.7-7.8-6.3-12.1-0.3-2.6 0-4.3 0.9-5.3s3-1.8 6.4-2.2l14.9-1.8 0.3 2.8c0.3 2.2-0.3 4.1-1.9 5.5-1.6 1.4-4.2 2.6-7.9 3.5l0.7 6 28.9-3.4-0.7-6c-4.1 0.3-6.9 0-8.3-0.9-1.3-0.8-2.2-2.7-2.6-5.6l-0.4-2.8 9.2-1c3.4-0.5 5.7-0.3 6.8 0.5 1 0.8 1.8 2.4 2.1 4.9 0.5 4.3-0.2 8.4-2.2 12.3-2 3.9-5.3 7.7-9.8 11.2l3.8 4.9 18.3-9.9-5.8-47.1-7.8 0.9c0.2 2.5-0.2 4.3-1.4 5.4-1.3 1.1-4.3 1.8-9.6 2.4L92.2 546c-5.2 0.6-8.5 0.6-10-0.1-1.4-0.8-2.3-2.4-2.6-5l-7.9 0.9 5.9 48.3 22.9 6 2.7-5.9zM126.5 677.5c1.5 0.3 3 1.6 4.5 3.9l6.9-2.7-9.6-24.8-7 2.7c0.8 2.4 1 4.3 0.3 5.7-0.5 1.4-1.9 2.5-4.1 3.3-3.1 1.3-6 1.3-8.6-0.1-2.7-1.2-4.6-3.5-5.9-6.8-1.6-4.1-0.9-8.1 2-11.7 3-3.7 8.1-6.9 15.3-9.6 7.5-2.9 13.6-3.9 18.4-3.3 4.9 0.8 8 3.2 9.7 7.3 1.3 3.3 1.2 6.8-0.2 10.2-1.4 3.5-4.4 7.6-8.8 12.2l5 5.2 18.4-12.7-1.9-5.1-2.9-0.2c0.3-2.5 0.3-4.8 0.1-6.9-0.3-2-0.8-4.1-1.5-6.1-3.1-7.9-8.5-13.3-16.3-16.2-7.8-2.9-16.1-2.6-25.1 0.8-9.7 3.8-16.5 9-20.7 15.6-4.1 6.7-4.7 13.7-1.8 21.1 1.2 3.1 2.8 5.8 4.6 7.9 1.9 2.1 4.2 4.1 7.1 5.7l-4.1 4.1 3.1 7.9 15.9-6.1c3.4-1.3 5.8-1.7 7.2-1.3zM183.4 696.3l-15.9-28.8-6.9 3.8c1.2 2.5 1.5 4.4 0.8 5.8-0.8 1.5-3.3 3.5-7.8 6l-21.8 11.7c-4.5 2.4-7.5 3.5-9.2 3.4-1.6-0.2-3.1-1.5-4.6-3.9l-6.9 3.8 13.9 25.2 7-3.7c-1.3-2.5-1.5-4.4-0.8-5.9s3.4-3.4 7.9-5.8l7.1-3.9 2.7 5-15.6 29.2 8.9 16.1 6.8-3.7c-0.9-1.9-1.2-3.7-1.1-5.4 0-1.6 0.6-3.5 1.7-5.7l8.5-17.8c3.5 3.3 6.9 5.2 10.4 5.8 3.5 0.5 7.1-0.2 11-2.2 5.2-2.8 8-6.6 8.6-11.5 0.7-4.6-0.8-10.5-4.7-17.5z m-6.8 9.5c-0.5 2.8-2.1 4.8-4.7 6.3-3 1.6-5.8 1.6-8.6 0.1-2.7-1.6-5.5-4.8-8-9.5-0.4-0.7-0.8-1.3-1-1.7-0.2-0.4-0.4-0.8-0.5-1.2l10.4-5.5c3-1.6 5.1-2.2 6.4-2 1.3 0.3 2.6 1.7 3.9 4.1 1.9 3.4 2.5 6.6 2.1 9.4zM168 772.7c0.5-1.6 2.9-3.9 6.9-6.8l20.1-14.3c4-2.9 6.9-4.5 8.6-4.4 1.7 0 3.4 1.1 5.2 3.3l6.4-4.7-17.2-23.5-6.4 4.6c1.6 2.4 2 4.3 1.5 5.8-0.5 1.6-2.8 3.8-6.9 6.8l-20.1 14.4c-4 2.8-7 4.4-8.6 4.3-1.7 0-3.4-1.1-5.1-3.3l-6.5 4.6 17.2 23.5 6.4-4.5c-1.6-2.3-2.1-4.2-1.5-5.8zM236.8 771.1L219 749.4l-6.2 4.9c1.6 2 2.2 3.7 1.7 5.2-0.5 1.6-2.7 3.9-6.9 7.2l-19 15.3c-4.1 3.2-7 4.9-8.5 5-1.6 0.2-3.2-0.7-4.9-2.7l-6.2 4.9 17.8 21.9c6.9 8.3 14.1 13 22.1 13.9 7.9 1 15.9-1.7 23.9-8.2 8.1-6.5 12.5-13.6 13.2-21.4 0.5-7.8-2.5-15.9-9.2-24.3z m-3.2 18.7c-1.4 5.1-5 10.1-10.9 14.8-5.8 4.6-11.5 7.1-16.8 7.3-5.4 0.2-9.7-1.9-13.2-6.1-1.5-1.9-2.3-3.5-2.1-4.7 0.2-1.2 1.6-2.9 4.4-5.1l25.2-20.1c2.8-2.2 4.8-3.3 6-3.2 1.2 0.1 2.6 1.1 4.2 3 3.4 4.3 4.5 9 3.2 14.1zM307.3 862l8.3-23.2-3.7-2.7-3.2 2.5c-1.1-2.6-2.3-4.8-3.7-6.7-1.4-1.9-3.1-3.5-4.8-5-6.9-5.1-14.4-7-22.7-5.5-8.3 1.5-15.3 6.1-21.2 13.8-6.2 8.1-9 16.3-8.3 24.5 0.7 8.2 4.7 15.1 12.1 20.7 5.1 3.9 10.6 5.9 16.4 6.2 5.9 0.3 12-1.5 18.6-4.9l-3.6-6.9c-4.4 2.1-8.8 3.1-13.2 2.9-4.4 0-8-1.1-10.8-3.3-4.1-3.1-6.1-7.3-5.8-12.5 0.3-5.3 2.7-10.9 7.4-16.9 4.5-6 9.4-10 14.4-11.7 4.9-1.8 9.3-1.3 13.2 1.6 3 2.3 4.7 5.7 5.6 10.1 0.8 4.6 0.5 9.6-1 15.2l6 1.8zM366.7 873.4c-2.6-8-8-14-16.5-17.9-8.4-4-16.5-4.4-24.4-1.4-7.8 3.1-13.9 9.1-18.2 18.1-4.3 9-5.2 17.5-2.6 25.4 2.6 8 8 13.9 16.4 17.9 8.4 3.9 16.5 4.4 24.4 1.3 7.9-3.1 14-9.1 18.3-18 4.3-9 5.2-17.5 2.6-25.4z m-17.1 18.5c-3.4 7.2-7.3 12.1-11.6 15.1-4.3 2.8-8.7 3.3-12.9 1.2-4.4-2-6.8-5.6-7.3-10.7s1-11.2 4.4-18.5c3.5-7.2 7.4-12.2 11.7-15.1 4.3-2.8 8.7-3.3 13-1.3 4.3 2.1 6.6 5.6 7.1 10.8 0.5 5.2-1 11.3-4.4 18.5zM429.2 903c1.7-5.5 1-10.3-1.9-14.1-3-3.9-8.3-6.9-15.9-9.2l-31.8-9.4-2.2 7.4c2.6 0.9 4.2 2.2 4.7 3.7s0 4.7-1.4 9.6l-7.1 23.5c-1.5 4.8-2.8 7.7-4.1 8.7-1.2 0.9-3.3 1.2-6 0.5l-2.3 7.6 27.9 8.3 2.2-7.6c-2.6-0.8-4.2-2.1-4.7-3.6-0.5-1.6 0-4.8 1.4-9.6l2.4-7.7 5.5 1.7 9.7 31.6 17.8 5.2 2.3-7.3c-1.9-0.9-3.5-1.8-4.6-3-1.2-1.3-2.2-3-2.9-5.4l-6.6-18.6c4.9-0.1 8.6-1.1 11.6-3.1 2.7-1.9 4.7-5 6-9.2z m-14.9-4.1c-1 3.2-2.9 5.2-6 6-3.1 0.9-7.2 0.5-12.5-1.2-0.9-0.3-1.5-0.4-2-0.5-0.4-0.1-0.8-0.3-1.1-0.4l3.4-11.2c0.9-3.2 2-5.2 3.2-5.8 1.2-0.7 3.1-0.6 5.6 0.1 3.8 1.1 6.6 2.8 8.2 5.1 1.7 2.4 2.1 5 1.2 7.9zM471.7 891.8l-30.4-3.8-1 7.7c2.5 0.4 4.2 1.3 4.9 2.7 0.7 1.4 0.7 4.7 0.1 9.9l-3.1 24.2c-0.7 5.2-1.5 8.2-2.6 9.4-1.1 1.2-2.8 1.6-5.4 1.4l-1 7.8 28 3.5 0.9-7.7c-2.6-0.5-4.2-1.3-4.9-2.8-0.7-1.4-0.8-4.6-0.1-9.7l0.9-6.5 9.9 1.3c7 0.9 12.6 0.1 16.5-2.6 3.9-2.5 6.2-6.9 7.1-13 0.8-6.2-0.4-11.2-3.8-14.9-3.4-3.8-8.7-6-16-6.9z m4.7 19.2c-0.4 3.6-1.9 6.3-4.4 7.9-2.4 1.6-5.9 2.1-10.3 1.6-0.6-0.1-1.2-0.2-1.6-0.3-0.4-0.1-0.7-0.1-1.2-0.2l1.8-13.6c0.4-3.3 1.1-5.4 2-6.3 0.8-0.9 2.3-1.3 4.5-1 3.3 0.4 5.8 1.7 7.3 3.9 1.7 2 2.3 4.7 1.9 8zM556.7 925.4c-0.3-9.9-3.6-17.9-9.6-23.7-6-5.9-13.7-8.7-23-8.4-9.2 0.5-16.7 3.7-22.2 10-5.6 6.4-8.1 14.4-7.8 24.3s3.5 17.9 9.6 23.8c6 5.9 13.5 8.7 23 8.3 9.2-0.3 16.6-3.6 22.2-10 5.5-6.3 8.1-14.4 7.8-24.3z m-19.5 19.2c-2.4 4.5-6.1 6.9-10.9 7-4.8 0.2-8.6-1.9-11.5-6.2-2.8-4.3-4.3-10.4-4.6-18.3-0.3-7.9 0.8-14.2 3.3-18.7s6.1-6.8 10.9-7c4.8-0.1 8.5 1.9 11.4 6.2 2.8 4.4 4.5 10.5 4.7 18.4 0.4 7.9-0.7 14-3.3 18.6zM622.3 936.9c-1.6-0.6-3.3-1.7-4.9-3.5l-14.2-13.8c4.3-2.1 7.3-4.7 9-7.7 1.7-3.1 2.2-6.7 1.6-11.1-1-5.7-3.7-9.6-8-11.9-4.4-2.2-10.5-2.6-18.4-1.3l-32.7 5.3 1.3 7.8c2.7-0.4 4.7 0 5.8 1.2 1.2 1.2 2.2 4.2 3 9.2l4 24.2c0.8 5 0.9 8.3 0.1 9.6-0.7 1.5-2.4 2.5-5.1 3l1.3 7.7 28.6-4.6-1.3-7.7c-2.8 0.4-4.6-0.1-5.8-1.2-1.2-1.2-2.1-4.3-2.9-9.3l-1.3-7.9 5.7-0.9 22.7 24.3 18.3-3.1-1.2-7.5c-2.2 0.1-4-0.1-5.6-0.8z m-26.5-25.3c-2.4 2.1-6.2 3.5-11.7 4.4-0.9 0.1-1.6 0.3-2 0.4-0.5 0-0.9 0.1-1.3 0.1l-2-11.6c-0.5-3.3-0.4-5.5 0.3-6.7 0.8-1 2.5-1.9 5.2-2.2 3.9-0.6 7.1-0.3 9.5 1 2.5 1.4 4 3.6 4.5 6.6 0.8 3.2-0.1 6-2.5 8zM681.3 908.2l-0.3-0.3-32.3-38.2-12.3 4.7 1 47.7v1.2c0.1 6.2-1.6 10.4-5.2 12.5l2.9 7.3 22.5-8.6-2.8-7.1c-2.2 0.7-3.9 1-5.1 0.8-1.2-0.4-2-1.3-2.6-2.8-0.1-0.2-0.2-0.5-0.3-0.8-0.1-0.4-0.1-0.7-0.2-1l-0.9-9.1 16.6-6.3 6 7.1c0.3 0.3 0.5 0.7 0.7 1 0.3 0.5 0.4 0.9 0.7 1.4 0.4 1.2 0.4 2.2-0.2 3.1-0.5 0.8-1.8 1.6-3.6 2.3l-0.7 0.3 2.8 7.2 26.2-10-2.8-7.4c-3.2 0.8-6.7-0.9-10.1-5z m-35.4-2.1l-0.9-19.3 11.8 15.1-10.9 4.2zM722.1 896.2c-1.5-0.8-3.5-3.4-5.8-7.8L699.6 857l0.9-0.4c3.3-1.8 6.6-2.3 9.7-1.7 3.2 0.6 6.9 2.4 11.2 5.8l3.8-4.7-15.2-14.1-42.2 22 3.3 20.3 6-0.4c-0.3-5.4 0.2-9.6 1.5-12.5 1.2-2.9 3.5-5.2 6.9-7l0.8-0.4 16.7 31.5c2.4 4.4 3.5 7.4 3.3 9s-1.5 3.1-3.8 4.4l3.7 6.9 25.5-13.3-3.7-7c-2.5 1.4-4.5 1.5-5.9 0.8zM767.3 868.2c-1.7-0.5-3.9-2.9-6.7-7l-14-20.2c-2.8-4.1-4.2-7-4.2-8.7 0.1-1.6 1.2-3.3 3.5-5l-4.5-6.4-24.2 16.5 4.5 6.4c2.4-1.4 4.4-1.9 5.9-1.4 1.6 0.6 3.8 2.9 6.7 7l14 20.2c2.9 4.1 4.3 7 4.3 8.7-0.1 1.6-1.2 3.3-3.5 5l4.4 6.4 24.3-16.5-4.5-6.5c-2.4 1.6-4.5 2-6 1.5zM811.5 808.1c-5.9-7.9-13.1-12.8-21.4-14.2-8.3-1.5-16.2 0.5-23.7 6-7.5 5.6-11.7 12.5-12.6 20.8-0.9 8.3 1.6 16.3 7.6 24.3s13.2 12.7 21.5 14.2 16.2-0.5 23.7-6c7.4-5.5 11.6-12.4 12.6-20.8 0.9-8.2-1.6-16.4-7.7-24.3z m-9.8 38.6c-3.9 2.8-8.2 3.2-13 1.2-4.8-2-9.6-6.1-14.4-12.5-4.8-6.4-7.5-12.1-8-17.2s1.2-9.1 5-12c3.8-2.8 8.1-3.2 12.9-1.2 4.8 2 9.6 6.2 14.5 12.5 4.7 6.4 7.4 12.1 7.9 17.2 0.5 5.2-1.2 9.1-4.9 12zM914.6 695.8c-3.1-7.9-9.1-13.9-18.2-18.2-9.2-4.2-17.7-5.1-25.7-2.5-8.1 2.6-14 8.1-18 16.4-4 8.3-4.4 16.4-1.3 24.2 3.1 7.7 9.2 13.8 18.3 18 9 4.2 17.6 5.1 25.6 2.5 8.1-2.5 14.2-8 18.1-16.3 3.9-8.4 4.4-16.4 1.2-24.1z m-8.6 20.5c-2.1 4.3-5.7 6.7-10.8 7.2-5.2 0.5-11.4-0.9-18.7-4.3-7.3-3.4-12.4-7.3-15.3-11.5-3-4.3-3.3-8.5-1.3-12.8 2-4.2 5.6-6.6 10.7-7.1 5.3-0.5 11.5 0.9 18.8 4.3 7.3 3.4 12.3 7.2 15.2 11.4 3 4.3 3.4 8.6 1.4 12.8zM926.4 657.2c-1.6 0.5-4.7-0.1-9.5-1.8l-10.2-3.5 0.9-2.5c0.9-2.5 2.4-4.1 4.5-4.9 2.2-0.7 5-0.7 8.7 0.1l1.8-5.1-28.3-9.6-1.8 5.1c3.6 1.4 6 3 6.9 4.5 0.8 1.5 0.7 3.9-0.3 7.1l-0.9 2.5-8.4-2.9c-3.3-1.1-5.2-2.2-5.8-3.5-0.5-1.2-0.4-3.3 0.5-5.9 1.5-4.2 3.9-7.6 7.2-10.3 3.4-2.7 7.7-4.7 12.9-6l-1-5.8-20.2 1.9-15.8 45.4 7.4 2.5c1.1-2.5 2.5-4 4.1-4.5 1.5-0.6 4.6 0.1 9.4 1.8l23.5 7.9c4.8 1.7 7.7 3.2 8.6 4.5 0.9 1.4 0.9 3.3 0.2 6l7.5 2.6 9.6-27.6-7.5-2.6c-1 2.6-2.3 4.1-4 4.6zM957.1 551.7c-2.6-5.1-7.1-9.6-13.4-13.6l-4.4 6.5c4 2.8 7.1 6.2 9.1 10 2.2 3.9 3 7.5 2.5 11-0.7 5.2-3.4 8.8-8.1 11.2-4.8 2.3-10.9 3-18.6 1.9-7.5-1-13.3-3.2-17.4-6.6-4.1-3.4-5.8-7.5-5.1-12.2 0.5-3.6 2.4-6.9 6-9.8 3.6-3 8.2-5.2 13.8-6.6l-1.3-6.3-24.5 4.3-0.6 4.5 3.8 1.6c-1.8 2.2-3.1 4.4-4.1 6.5-1 2.1-1.7 4.3-2 6.5-1.2 8.5 1 15.9 6.4 22.3 5.4 6.3 13 10.2 22.6 11.4 10.2 1.4 18.6-0.3 25.6-4.9 6.9-4.7 11-11.6 12.2-20.6 1.2-6.2 0.2-11.9-2.5-17.1zM947.4 473.6c-1.4 1-4.5 1.6-9.7 1.8l-24.6 1c-5.2 0.3-8.5-0.1-9.9-1-1.3-0.9-2.1-2.6-2.3-5.3l-7.9 0.3 1.2 28.6 7.6-0.4c0-2.6 0.6-4.4 2-5.4 1.3-1.1 4.5-1.6 9.7-1.8l6.5-0.3 0.9 21.7-6.4 0.3c-5.1 0.1-8.3-0.2-9.8-1-1.5-0.9-2.3-2.7-2.5-5.3l-7.6 0.3 1.2 28.5 7.9-0.3c0-2.6 0.6-4.4 2-5.4s4.5-1.6 9.7-1.8l24.7-1c5-0.1 8.3 0.1 9.7 1 1.4 0.9 2.2 2.6 2.4 5.3l7.9-0.3-1.2-28.4-7.7 0.3c0.1 2.7-0.6 4.5-1.8 5.4-1.3 0.9-4.5 1.6-9.7 1.8l-10.8 0.4-0.9-21.7 10.8-0.4c5.1-0.2 8.4 0.1 9.8 1 1.5 0.9 2.2 2.7 2.4 5.3l7.6-0.3-1.2-28.5-7.9 0.3c-0.2 2.5-0.9 4.3-2.1 5.3zM941.9 434.6c-1.2 1.2-4.2 2.3-9.1 3.1l-24.4 4.3c-4.9 0.9-8.2 1-9.7 0.3-1.5-0.8-2.6-2.4-3.3-5.2l-7.8 1.4s0.8 3.4 2.4 13 2.8 15.6 2.8 15.6l7.8-1.4c-0.3-2.8 0-4.7 1.2-5.9 1.2-1.2 4.2-2.3 9.3-3.2l24.3-4.3c4.9-0.9 8.2-1 9.7-0.2 1.5 0.7 2.6 2.4 3.2 5.1l7.8-1.4-5.2-28.6-7.8 1.4c0.3 2.9 0 4.8-1.2 6zM882.4 381.1c-1.6-0.5-2.8-2-3.6-4.6l-7.6 2.2 5.8 20.4 7.4-2.1c-0.6-2.6-0.4-4.5 0.7-5.8 1-1.1 4-2.4 8.9-3.8l16.6-4.7-29.9 29.1 6.6 23.4 7.8-2.1c-0.7-2.6-0.5-4.5 0.5-5.8 1.1-1.3 4.1-2.6 9-3.9l23.7-6.6c5-1.4 8.1-1.8 9.7-1.3 1.6 0.5 2.8 2.1 3.6 4.5l7.6-2-5.9-20.7-7.4 2.1c0.6 2.6 0.4 4.6-0.6 5.7-1.1 1.3-4.1 2.6-9 3.9l-28.7 8.1 40.2-39.4-2.9-10-42.8 11.9c-4.9 1.6-8.2 2.1-9.7 1.5zM863.9 363.8l48.2-3.5c0.3 0 0.7-0.1 1.2-0.1 6.3-0.5 10.6 1.1 12.8 4.3l7.3-3.2-9.9-21.8-7.1 3.2c0.9 2.2 1.4 3.9 1.1 5-0.3 1.2-1.1 2-2.6 2.7-0.2 0.1-0.5 0.2-0.9 0.3-0.3 0.1-0.7 0.2-0.9 0.3l-9.2 1.4-7.3-16.1 6.9-6.3c0.3-0.2 0.6-0.5 1-0.7 0.4-0.3 0.9-0.5 1.4-0.7 1.2-0.5 2.2-0.6 3.2 0 0.8 0.5 1.6 1.8 2.5 3.5l0.2 0.6 7.2-3.1-11.6-25.4-7.3 3.2c1 3.2-0.4 6.7-4.3 10.4l-0.3 0.1-36.8 34 5.2 11.9z m26.6-21.7l4.8 10.6-19.4 2M830.5 748.1c-0.5-1.6 0.1-3.5 1.8-5.6l-6.1-5-13.8 16.3 5.9 4.9c1.8-1.9 3.5-2.8 5.2-2.6 1.6 0.2 4.3 2 8.2 5.2l13.2 10.9-41.1-8.1-15.8 18.6 6 5.1c1.8-2 3.5-2.9 5.1-2.8 1.7 0.1 4.5 1.9 8.3 5.1l18.9 15.6c3.9 3.3 6.1 5.7 6.5 7.3 0.5 1.5-0.1 3.4-1.8 5.5l6.1 5.1 13.9-16.4-6-4.9c-1.8 1.9-3.6 2.8-5.2 2.7-1.7-0.2-4.4-1.9-8.3-5.1l-22.8-19 55.4 10.7 6.7-8-34-28.3c-3.7-3.3-5.9-5.7-6.3-7.2zM320.9 587.9c18.7 6.1 38.5 11.1 59.1 14.9-4.3-27.3-6.7-56.1-6.7-85.8 0.1-140.7 52.6-260.5 126-305.7-57.9 63.3-95.4 164.7-95.5 279 0 41.4 4.9 81.2 14 118.1 27.5 3.1 56.1 4.2 85.5 3 154.3-6 283.2-71.8 328.4-158.2-27.4-153-161-269.2-322-269.3h-0.3C400 214 317.1 355.3 317 525.2c0 21.5 1.4 42.4 3.9 62.7zM403.2 679.4c-5.2-15.7-9.6-32.2-13.1-49.4-21.5-4.8-41.8-10.8-60.5-17.8 2.8 16.9 6.4 33.3 10.9 49.2 19.7 7.1 40.7 13.2 62.7 18zM416.9 715.3c-21.6-2.8-42.4-6.7-62.1-11.5 16.1 40.8 37.7 76.3 63.3 104.4-35.3-21.8-65.7-60.8-87.8-111-48.6-14.7-89.6-35.5-118.9-60.6 48.2 120.5 166 205.6 303.8 205.7 7.6 0 15.2-0.3 22.7-0.8-49.5-14.2-92.3-60.6-121-126.2z M537.3 642.3c-37.2 1.5-73.2-0.4-106.8-5.1 5.4 17.5 11.7 34.3 18.9 50.2 24.2 3.1 49.3 4.8 75 4.9 118 0.1 222.7-34.5 288-87.8-46.7 67.6-170.2 116.1-315.4 116-10.4 0-20.7-0.3-30.9-0.8 32.4 55.9 76.6 96.4 127 113.3 142.6-34.7 248.6-162.7 249.6-315.7-45.2 67.9-164.1 119.5-305.4 125zM190.2 553c25 39.1 68 72.8 122.9 97.3-4.8-16-8.8-32.9-12.1-50.3-34.8-16.8-62.3-37.7-80-61.6 21.8 16.7 47.8 31.1 76.9 42.9-3.7-25.3-5.6-51.7-5.6-79 0.1-130.5 45.2-243 110.4-294.7C277.5 253.5 188.1 373.7 188 514.9c0 12.9 0.8 25.6 2.2 38.1z M167 515c0 192.3 155.9 348.2 348.3 348.2 192.3 0 348.2-155.9 348.2-348.2 0-192.4-155.9-348.3-348.2-348.3-192.4 0-348.3 156-348.3 348.3z m348.3-340.2c187.9 0 340.2 152.3 340.2 340.2 0 187.9-152.3 340.2-340.2 340.2-187.9 0-340.2-152.3-340.2-340.2 0-187.9 152.3-340.2 340.2-340.2z";*/ + -fx-shape: "M890.76 623.29c-2 6.51-3.27 13.14-5.63 19.59-35.77 97.63-107.49 175.65-201.95 219.7C630.8 887 575.23 899.39 518 899.39c-52.2 0-102.23-11.87-148.7-31.51-24.5 4.26-48.84 7.94-72.52 9.95-13.34 1.13-24.97 1.8-35.96 2.25 75.15 52.43 164.79 81.55 257.19 81.55 64.17 0 129.43-13.7 191.48-42.64 152.06-70.9 245.13-215.38 258.67-370.84-7.63 8.57-15.03 17.15-23.44 25.72-16.65 16.94-35.05 33.29-53.96 49.42z M1012.01 264.62c-21.89-46.94-71.87-76.62-139.28-89.83 12.48 13.42 24.72 28.02 36.84 44.2 17.23 23.01 30.18 44.14 41.49 65.21 1.87 3.49 3.92 7.02 5.68 10.52 7.92 20.48 5.44 47.02-6.6 77.12-9.44 23.6-24.75 49.25-45.42 75.79-3.07 3.94-5.86 7.83-9.16 11.8-7.04 8.46-14.73 16.83-22.58 25.18-67.75 72.09-164.54 139.45-276.75 191.77-111.82 52.15-225.4 82.97-324.02 88.67-10.97 0.63-21.89 1.19-32.46 1.19-4.83 0-9.29-0.33-13.97-0.47-0.44-0.01-0.8-0.09-1.24-0.11-32.83-1.07-61.8-5.43-85.74-12.87-0.5-0.16-0.89-0.37-1.38-0.53-0.03-0.01-0.04-0.02-0.07-0.03-31.33-9.98-53.77-25.05-64.74-44.32-1.84-4.18-3.41-8.49-5.13-12.73-9.72-23.88-18.18-48.41-24.06-73.78-4.18-18.02-7.14-36.65-9.16-55.62-33.24 60.14-42.6 117.5-20.71 164.44 26.62 57.09 94.17 89.3 184.9 96.61 13.3 1.07 27.06 1.64 41.3 1.64 17.18 0 35.2-1.06 53.57-2.62 99.04-8.41 213.76-39.22 329.21-93.06 117.2-54.65 215.79-123.97 286.1-195.56 23.56-23.99 44.05-48.2 60.81-72.24 50.88-73.02 68.78-144.15 42.57-200.37z M67.66 514.54c0.14 32.84 3.51 65.9 11.11 98.67 0.09 0.4 0.25 0.79 0.34 1.19 4.43 18.91 10.57 37.63 17.55 56.21 0.25 0.69 0.18 1.28 0.46 1.98 0.18 0.6 2.05 6.08 2.22 6.71 0.13 0.23 0.94 0.61 1.17 0.86 5.07 5.53 32.28 16.2 52.62 22.67l13.75 4.37c5.38 1.23 11.94 1.76 17.87 2.69 0.02 0 0.04 0.01 0.06 0.01-6.74-11.16-13.55-22.3-19.13-34.27-21.03-45.1-32.74-92.86-35.53-141.12-1.88-32.47 0.6-65.1 7.05-97.37 3.93-19.66 8.94-39.21 15.98-58.41 3.32-9.08 7.27-17.8 11.21-26.53 3.68 4.86 7.78 9.66 12.85 14.19 24.08 21.52 57.43 30.67 99.21 27.42 45.3-3.62 59.03 6.03 62.09 9.07 1.98 1.95 2.3 3.75 2.46 3.75 0 0 0.03 0 0.03-0.03l-0.84 4 0.46 4.08c1.11 10.18 12.81 61.89 136.87 80.73 0.38 0.03 0.99 0.03 1.8 0.03 9.09 0 44.39-1.72 64.8-27.45 9.34-11.78 18.64-32.69 9.83-65.56l-2.38-5.87c-11.93-21.5-30.92-72.75-13.55-94.02 37.17-45.48 30.39-116.66 29.55-123.95-0.13-1.55-2.92-28.48-20.06-54.51 57.04 4.22 111.61 20.64 160.45 47.6 28.58 15.78 55.01 34.93 78.83 57.33 35.09 33 64.84 72.04 85.8 117 5.47 11.73 9.53 23.82 13.72 35.87 0.11 0.32 0.19 0.64 0.3 0.96l0.03-0.06c6.38-10.56 11.56-20.74 15.36-30.21 7.53-18.81 17.08-45.55 16.17-52.79-0.04-0.3 0.18-1.07 0.1-1.3l-1.1-2-1.59-1.54c-0.04-0.09-0.12-0.13-0.16-0.21-10.66-18.87-22.17-36.99-34.9-53.98-11.23-15-23.3-29.12-35.93-42.58-0.31-0.37-0.47-0.93-0.79-1.28l-3.01-2.41c-8.91-9.25-17.86-18.46-27.57-26.72-26.13-22.22-54.76-40.89-84.89-56.51-14.65-7.6-29.7-14.36-45.07-20.28-30.74-11.83-62.76-20.25-95.49-25.16a462.045 462.045 0 0 0-49.55-4.71c-5.97-0.24-11.87-1.1-17.87-1.1h-0.02c-64.17 0-129.43 13.7-191.48 42.64l-0.01 0.01c-0.01 0.01-0.02 0.01-0.03 0.01-131.67 61.37-218.68 178.06-248.77 309.07-2.64 11.51-4.42 23.2-6.31 34.87l0.02 0.14c-3.58 22.07-6.2 44.31-6.14 66.88-0.01 0.31 0.05 0.61 0.05 0.92z m287.45-355.49c33.42-15.58 68.25-25.7 103.89-31.38 12.41 0.92 22.91 4.35 31.38 10.28 22.23 15.55 25.5 45.02 25.58 45.71 1.7 15.73 1.75 61.79-18.11 86.07-40.87 50.09-3.24 129.93 6.66 148.82 1.22 5.52 2.13 13.19-0.99 17.17-4.51 5.77-18.21 7.98-21.25 8.18-63.26-9.72-85.69-28.54-89.59-34.06 0.46-11.85-3.09-27.5-14.74-40.72-19.4-21.95-54.98-31.02-105.65-26.99-26.61 2.25-46.97-2.53-60.09-14.03-11.97-10.44-15.82-24.7-17-31.46 39.29-59.11 93.86-106.79 159.91-137.59z"; + -jfx-size: 20px; + -fx-background-color: -fx-text-color; +} + +.lfx-decorator-button { + -fx-fill: -fx-text-color; + -fx-text-fill: -fx-text-color; + -fx-prompt-text-fill: -fx-text-color; + -jfx-button-type: FLAT; + -fx-background-color: TRANSPARENT +} + +/******************************************************************************* +* * +* JFX Hamburger Icon * +* * +*******************************************************************************/ + +.jfx-hamburger { + -fx-padding: 10.0; + -fx-spacing: 4px; + -fx-cursor: hand; +} + +.jfx-hamburger StackPane { + -fx-pref-width: 40px; + -fx-pref-height: 4px; + -fx-background-color: -fx-text-color; + -fx-background-radius: 5px; +} + +/******************************************************************************* +* * +* JFX 滚动条 * +* * +*******************************************************************************/ +.corner, .track, .increment-arrow, .decrement-arrow, .increment-button, .decrement-button, .scroll-bar:vertical, .scroll-bar:horizontal { + -fx-background-color: TRANSPARENT; +} + + +.thumb { + -fx-background-color: ladder(-fx-main-base, rgba(255, 255, 255, .3) 29%, rgba(0, 0, 0, 0.3) 30%); + -fx-border-color: TRANSPARENT; + -fx-background-radius: 14; + -fx-border-radius: 14; + -fx-border-width: 0.5; +} + + +/******************************************************************************* + * * + * JFX Tool Bar * + * * + ******************************************************************************/ + +.jfx-tool-bar { + -fx-background-color: -fx-card-base; + -fx-border-color: -fx-border-base; + -fx-border-width: 0 0 0 0; + -fx-pref-width: 100.0%; + -fx-pref-height: 48.0px; +} + +.jfx-tool-bar HBox { + -fx-alignment: center; + -fx-spacing: 7.0; + -fx-padding: 0 0 0 0; +} + + +.tool-bar-button { + -fx-fill: -fx-text-color; + -fx-text-fill: -fx-text-color; + -fx-prompt-text-fill: -fx-text-color; + -fx-pref-height: 40; + -fx-pref-width: 40; + -fx-background-radius: 20; + -jfx-button-type: FLAT; + -fx-background-color: TRANSPARENT +} + +.tool-bar-button > .jfx-svg-glyph { + -fx-fill: -fx-text-color; + -fx-text-fill: -fx-text-color; + -fx-prompt-text-fill: -fx-text-color; + -jfx-size: 20px; +} + +.tool-bar-button:hover { + -fx-background-color: ladder(-fx-main-base, rgba(255, 255, 255, .2) 29%, rgba(0, 0, 0, .2) 30%); +} + +.tool-bar-button:focused { + -fx-background-color: TRANSPARENT +} + +/******************************************************************************* +* * +* JFX TabPane * +* * +*******************************************************************************/ + + +.jfx-tab-pane .tab-header-background { + -fx-background-color: -fx-main-base; +} + +.jfx-tab-pane .headers-region .tab-selected-line { + -fx-background-color: -fx-accent-color; + -fx-pref-height: 3px; +} + +.jfx-tab-pane .headers-region .tab .tab-container .tab-label { + -fx-text-fill: -fx-text-color; + -fx-font-family: "Microsoft YaHei"; + -fx-font-size: 14px; + -fx-font-weight: 600; + -fx-graphic-text-gap: 10; + -fx-padding: 6 10 6 10; +} + +.jfx-tab-pane .headers-region .tab:selected .tab-container .tab-label { + -fx-text-fill: -fx-text-color; + +} + +.jfx-tab-pane .headers-region .tab .tab-container .tab-close-button > .jfx-svg-glyph { + -fx-background-color: -fx-text-color; + -jfx-size: 10px; + + +} + +.jfx-tab-pane .headers-region .tab { + -fx-pref-height: 50px; + +} + +.jfx-tab-pane .headers-region .tab:closable { + -fx-border-color: rgba(0, 0, 0, 0); +} + +.jfx-tab-pane .headers-region .tab .tab-container .tab-close-button { + -fx-background-color: TRANSPARENT; + -fx-background-radius: 20; +} + +.jfx-tab-pane .headers-region .tab .tab-container .tab-close-button:hover { + -fx-background-color: derive(-fx-text-color, -20%) + +} + +.jfx-tab-pane .headers-region .tab .tab-container .tab-close-button:focused { + -fx-background-color: TRANSPARENT; +} + +.jfx-tab-pane .headers-region .tab:hover .tab-container .tab-close-button > .jfx-svg-glyph { + -fx-background-color: derive(-fx-text-color, -30%); +} + +.jfx-tab-pane .headers-region .tab .tab-container .jfx-svg-glyph { + -fx-background-color: derive(-fx-text-color, -20%); + -jfx-size: 20; +} + + +.jfx-tab-pane .headers-region > .tab:hover { + -fx-background-color: derive(-fx-accent-suspension-color, 20%) +} + +.jfx-tab-pane .headers-region > .tab:selected { + -fx-background-color: -fx-accent-suspension-color; +} + +/*.tab-content {*/ +/* -fx-background-color: -fx-card-base;*/ +/*}*/ + +/******************************************************************************* +* * +* JFX List View * +* * +*******************************************************************************/ + + +.jfx-list-cell { + -fx-background-insets: 0.0; + -fx-text-fill: -fx-text-color; +} + +.jfx-list-cell:odd, +.jfx-list-cell:even { + -fx-background-color: transparent; +} + +.jfx-list-cell:filled:hover, +.jfx-list-cell:selected .label { + -fx-text-fill: -fx-text-color; +} + +.jfx-list-cell .jfx-rippler { + -jfx-rippler-fill: #5264AE; +} + +.jfx-list-cell:odd:selected > .jfx-rippler > StackPane, +.jfx-list-cell:even:selected > .jfx-rippler > StackPane { + -fx-background-color: -fx-accent-color; + -fx-background-radius: 6; + -fx-border-color: -fx-accent-color; +} + +.jfx-list-view { + -fx-background-color: transparent; +} + + +.navigation-list .jfx-list-cell { + -fx-background-color: transparent; + -fx-background-insets: 0; + -fx-padding: 0; +} + + +.navigation-list .jfx-list-cell .label { + -fx-graphic-text-gap: 15; + -fx-pref-height: 45; + -fx-padding: 0 0 0 25; +} + + +.navigation-list .jfx-list-cell .label > .jfx-svg-glyph { + -jfx-size: 20px; + -fx-alignment: center; +} + +.navigation-list .jfx-list-cell:odd:selected > .jfx-rippler > StackPane, +.navigation-list .jfx-list-cell:even:selected > .jfx-rippler > StackPane { + -fx-background-color: -fx-accent-color; + -fx-background-insets: 0 20 0 20; + -fx-background-radius: 6; + -fx-border-color: -fx-accent-color; + -fx-border-width: 0 0 0 4; +} + +.navigation-list { + -fx-background-radius: 0; + -fx-background-insets: 0.0; + -fx-background-color: -fx-card-base; + -jfx-cell-horizontal-margin: 0.0; + -jfx-cell-vertical-margin: 0.0; + -jfx-expanded: true; + +} + +.navigation-list .jfx-rippler { + -jfx-rippler-fill: derive(-fx-accent-color, -20%); +} + + +/******************************************************************************* +* * +* JFX SUBLIST IMPORTANT * +* * +*******************************************************************************/ +.sublist .scroll-bar:vertical .increment-arrow, +.sublist .scroll-bar:vertical .decrement-arrow, +.sublist .scroll-bar:vertical .increment-button, +.sublist .scroll-bar:vertical .decrement-button { + -fx-padding: 0; +} + +.sublist .scroll-bar:vertical .track, +.sublist .scroll-bar:vertical .thumb { + -fx-background-color: -fx-text-color; +} + +.sublist { + + /* important to hide the list change of height */ + -fx-background-radius: 0; + -fx-background-insets: 0.0; + -jfx-cell-horizontal-margin: 0.0; + -jfx-cell-vertical-margin: 0.0; + -jfx-expanded: true; + -fx-padding: 0; + -fx-background-color: TRANSPARENT; +} + + +.sublist .jfx-list-cell { + -fx-background-insets: 0.0; + -fx-padding: 0 0 0 35; + -fx-text-fill: -fx-text-color; + -fx-border-color: #e0e0e0; + -fx-border-width: 0 0 0 0; +} + + +.sublist-header { + -fx-alignment: center-left; + -fx-padding: 0; +} + +.sublist-header .sub-label { + -fx-padding: 0 0 0 0; +} + +/******************************************************************************* + * * + * TableView * + * * + ******************************************************************************/ +.table-view, .tree-table-view { + /* Constants used throughout the tableview. */ + -fx-background-color: -fx-card-base; + -fx-table-header-border-color: #700128; + -fx-table-cell-border-color: -fx-cell-border-base; + -fx-background-radius: 14px; + -fx-border-radius: 14px; + -fx-border-width: 0.6; + -fx-border-color: -fx-border-base; + -fx-background-insets: 0; + -fx-padding: -0.9; +} + +.table-view:focused { + -fx-background-insets: 0; +} + +.table-view .column-header-background { + -fx-background-color: -fx-border-base; + /*-fx-background-insets: 10 10 0 0;*/ + -fx-background-radius: 14px 14px 0 0; + -fx-border-radius: 14px 14px 0 0; + -fx-pref-height: 49; +} + +/**列头行设置背景*/ +.table-view .column-header, +.table-view .filler { + -fx-background-color: transparent; +} + +/**TableView列头文本标签*/ +.table-view .column-header .label { + -fx-alignment: center; + -fx-font-family: "Microsoft YaHei"; + -fx-font-weight: BOLD; + -fx-text-fill: -fx-text-color; + -fx-font-size: -fx-font-base16; +} + +/**TableView列头展示隐藏列按钮*/ +.table-view > .column-header-background > .show-hide-columns-button { + -fx-background-color: transparent; +} + +/*表格内容区域*/ +.table-view .placeholder { + -fx-background-color: transparent; +} + + +.table-column { + -fx-pref-height: 49; + -fx-background-color: transparent; + -fx-alignment: center; + -fx-border-width: 0.4; +} + +/*表格内容区域每行的样式*/ +.table-view .table-row-cell { + -fx-border-color: -fx-cell-border-base; + -fx-border-width: 0 0 0.4 0; + -fx-background-color: transparent; +} + +.table-view .table-row-cell .table-cell { + -fx-pref-height: 52; + -fx-alignment: center; + -fx-border-width: 0.4; +} + +.table-row-cell:odd { + -fx-background-color: transparent; +} + +.table-row-cell .text { + -fx-fill: -fx-text-color; +} + +/*TableView的单元之间去掉没有数据的竖线 */ +.table-view .table-row-cell:empty, .table-view .table-row-cell:empty .table-cell { + -fx-border-width: 0px; +} + +.table-view .table-row-cell:selected { + -fx-background-color: -fx-accent-suspension-color; + +} + +.table-view .table-row-cell:selected .table-cell { + -fx-border-color: -fx-cell-border-base; +} + +/******************************************************************************* +* * +* splitPane * +* * +*******************************************************************************/ +.split-pane { + -fx-border-width: 0 0 0 0; + -fx-background-color: transparent; +} + +.split-pane *.split-pane-divider { + -fx-background-color: transparent; + -fx-padding: 0 5 0 5; /* 0 3 0 3 */ +} + +/******************************************************************************* + * * + * TreeView and TreeCell * + * * + ******************************************************************************/ +.tree-view { + -fx-background-color: transparent; +} + + +.tree-cell { + -fx-padding: 0.25em; /* 3 */ + -fx-indent: 1em; + -fx-text-fill: -fx-text-color; + -fx-background-color: transparent; +} + +.tree-cell:selected { + -fx-background-color: -fx-accent-suspension-color; + -fx-text-fill: -fx-accent-color; +} + + +.tree-cell > .tree-disclosure-node, +.tree-table-row-cell > .tree-disclosure-node { + -fx-padding: 4 6 4 8; + -fx-background-color: transparent; +} + +.tree-cell > .tree-disclosure-node > .arrow, +.tree-table-row-cell > .tree-disclosure-node > .arrow { + -fx-background-color: -fx-text-color; + -fx-padding: 0.333333em 0.229em 0.333333em 0.229em; /* 4 */ + -fx-shape: "M 0 -3.5 L 4 0 L 0 3.5 z"; +} + +.tree-cell:expanded > .tree-disclosure-node > .arrow, +.tree-table-row-cell:expanded > .tree-disclosure-node > .arrow { + -fx-rotate: 90; +} + +/******************************************************************************* + * * + * JFXTextField * + * * + ******************************************************************************/ + + +.jfx-text-field, .jfx-password-field, .jfx-text-area, .jfx-combo-box { + -fx-background-color: transparent; + -fx-font-family: "Microsoft YaHei"; + -fx-font-weight: BOLD; + -fx-text-fill: -fx-text-color; + -fx-prompt-text-fill: #c7c7c7; + -fx-alignment: top-left; + -jfx-focus-color: #ffffff; + -jfx-unfocus-color: #e8e8e8; +} + +.jfx-text-field > .input-line, +.jfx-password-fieldxt-field > .input-line, +.jfx-text-area > .input-line, +.jfx-combo-box > .input-line { + -fx-background-color: -jfx-unfocus-color; + -fx-pref-height: .45; + -fx-translate-y: 1px; +} + +.jfx-text-field > .input-focused-line, +.jfx-password-fieldxt-field > .input-focused-line, +.jfx-text-area > .input-focused-line, +.jfx-tejfx-combo-box > .input-focused-line { + -fx-background-color: -jfx-focus-color; + -fx-pref-height: 1px; +} + +.login-text { + -fx-background-color: transparent; + -fx-font-family: "Microsoft YaHei"; + -fx-font-weight: 100; + -fx-text-fill: -fx-light-text-color; + -fx-prompt-text-fill: #70665e; + -fx-alignment: top-left; + -jfx-focus-color: #70665e; + -jfx-unfocus-color: -fx-light-text-color; +} + +#login-glyph-icon { + -fx-fill: #70665e; +} + + +/******************************************************************************* + * * + * JFX Dialog Layout * + * * + ******************************************************************************/ + + +.jfx-dialog, .jfx-dialog-layout { + -fx-background-color: -fx-card-base; + -fx-background-radius: 14; +} + +.jfx-dialog-overlay-pane, .jfx-alert-overlay { + -fx-background-color: rgba(0.0, 0.0, 0.0, 0.2); +} + +.jfx-dialog-content, .jfx-alert-content-container { + -fx-background-color: transparent; + + -fx-border-color: #313D4F; + -fx-border-width: 1px; + -fx-border-radius: 14px; +} + + +.jfx-layout-heading .label { + -fx-font-size: 20px; +} + + +/******************************************************************************* +* * +* JFX Spinner * +* * +*******************************************************************************/ + +.jfx-spinner .arc { + -fx-stroke-width: 3.0; +} + +.first-spinner { + -jfx-radius: 20; +} + +.first-spinner .arc { + -fx-stroke-width: 5.0; +} + +.second-spinner { + -jfx-radius: 30; +} + +.second-spinner .arc { + -fx-stroke-width: 5.0; +} + +.third-spinner { + -jfx-radius: 40; +} + +.third-spinner .arc { + -fx-stroke-width: 5.0; +} + +.fourth-spinner { + -jfx-radius: 50; +} + +.fourth-spinner .arc { + -fx-stroke-width: 5.0; +} + +.fifth-spinner { + -jfx-radius: 60; +} + +.fifth-spinner .arc { + -fx-stroke-width: 5.0; +} + +.sixth-spinner { + -jfx-radius: 70; +} + +.sixth-spinner .arc { + -fx-stroke-width: 5.0; +} + +.seventh-spinner { + -jfx-radius: 80; +} + +.seventh-spinner .arc { + -fx-stroke-width: 5.0; +} + +.blue-spinner .arc { + -fx-stroke: #4285f4; +} + +.blue-spinner .track { + -fx-stroke: #d0d0d0; +} + +.red-spinner .arc { + -fx-stroke: #db4437; +} + +.green-spinner .arc { + -fx-stroke: #0F9D58; +} + +.yellow-spinner .arc { + -fx-stroke: #f4b400; +} + +.materialDesign-purple:indeterminate .arc { + -fx-stroke: #ab47bc; +} + +.materialDesign-blue .arc { + -fx-stroke: #2962ff; +} + +.materialDesign-blue .percentage { + -fx-fill: #ab47bc; +} + +.materialDesign-cyan .arc { + -fx-stroke: #00b8d4; +} + +.materialDesign-green .arc { + -fx-stroke: #00c853; +} + +.materialDesign-green .text { + visibility: false; +} + +.materialDesign-yellow .arc { + -fx-stroke: #ffd600; +} + +.materialDesign-orange .arc { + -fx-stroke: #ff6d00; +} + +.materialDesign-red .arc { + -fx-stroke: #d50000; +} + + +.tile { + -BACKGROUND: rgb(42, 42, 42); + -FOREGROUND: rgb(223, 223, 223); + -GRAY: rgb(139, 144, 146); + -RED: rgb(229, 80, 76); + -LIGHT_RED: rgb(255, 84, 56); + -GREEN: rgb(143, 198, 94); + -LIGHT_GREEN: rgb(132, 228, 50); + -BLUE: rgb(55, 179, 252); + -DARK_BLUE: rgb(55, 94, 252); + -ORANGE: rgb(237, 162, 57); + -YELLOW_ORANGE: rgb(229, 198, 76); + -YELLOW: rgb(229, 229, 76); + -MAGENTA: rgb(198, 75, 232); + -PINK: rgb(233, 14, 139); + + -foreground-color: -FOREGROUND; +} + + + + + + + + diff --git a/client/src/main/resources/css/app.test.css b/client/src/main/resources/css/app.test.css new file mode 100644 index 0000000..2918887 --- /dev/null +++ b/client/src/main/resources/css/app.test.css @@ -0,0 +1,714 @@ +@font-face { + font-family: 'Microsoft YaHei'; + src: url('../fonts/msyh.ttf'); +} + +.root { + /**全局定义主题颜色变量 默认*/ + -fx-base: #f15353; + /*用于窗口背景的非常浅的灰色*/ + -fx-background: derive(-fx-base, 26.4%); + /*将根据使用背景颜色的亮度的梯形计算*选择这些颜色之一*/ + -fx-dark-text-color: black; + -fx-mid-text-color: #333; + -fx-light-text-color: white; + + /* 亮蓝色,用于突出显示/突出显示对象。例如:selected *文本;菜单,列表,树和表中的选定项目;进度条* */ + -fx-accent: #0096C9; + + /* 默认按钮颜色,类似于重音符号,但更细微 */ + -fx-default-button: #ABD8ED; + + /* 物体的聚焦指示器为亮蓝色。通常用作“聚焦”伪类的-fx-background-color中的*第一颜色。也*通常与-1.4的插图一起使用以提供发光效果。 + */ + -fx-focus-color: #039ED3; + -fx-faint-focus-color: #039ED322; + + /*样式控件中使用的颜色。*/ + -fx-color: -fx-base; + + /**全局定义主题字体变量 默认*/ + -fx-font-family-base: 'Microsoft YaHei'; + /**全局定义主题字体大小变量 默认*/ + -fx-font-size-base: 12px; +} + + +/******************************************************************************* +* * +* text和label * +* * +*******************************************************************************/ +.text, .label { + -fx-text-fill: ladder(-fx-base, white 29%, black 30%); + -fx-font-size: 14px; + -fx-font-family: -fx-theme-font-family; +} + +/******************************************************************************* +* * +* splitPane * +* * +*******************************************************************************/ +.split-pane { + -fx-border-width: 0 0 0 0; +} + +.split-pane *.split-pane-divider { + -fx-padding: 0 1 0 1; /* 0 3 0 3 */ +} + +/******************************************************************************* +* * +* JFX Button * +* * +*******************************************************************************/ + +.jfx-button .jfx-rippler { + -jfx-rippler-fill: -fx-theme-rippler-color; +} + +.jfx-button { + -fx-padding: 0.47em 0.47em; + -fx-font-size: 14.0px; + -fx-background-color: -fx-theme-color; + /*-fx-pref-width: 200.0;*/ + -fx-text-fill: WHITE; +} + +/*.jfx-button:hover {*/ +/* -fx-background-color: derive(-fx-theme-color, 20%)*/ +/*}*/ + +/*.jfx-button:focused {*/ +/* -fx-background-color: -fx-theme-color;*/ +/*}*/ + + +/******************************************************************************* +* * +* JFX Decorator * +* * +*******************************************************************************/ + +.jfx-decorator { + -fx-decorator-color: derive(-fx-theme-color, -20%); + +} + +.jfx-decorator-button { + -fx-background-color: TRANSPARENT; + -jfx-button-type: FLAT; +} + +.jfx-decorator-button .jfx-rippler { + -jfx-rippler-fill: -fx-theme-rippler-color; +} + +.jfx-decorator .jfx-decorator-buttons-container { + -fx-background-color: -fx-decorator-color; +} + +.jfx-decorator .resize-border { + -fx-border-color: -fx-decorator-color; + -fx-border-width: 0 4 4 4; +} + +.jfx-decorator .jfx-decorator-title-container .jfx-decorator-text { + -fx-fill: WHITE; + -fx-font-size: 16; +} + +.jfx-decorator .jfx-decorator-title-container .jfx-svg-glyph { + -fx-shape: "M223.3 179.2l-6.9-6.9-5.9 6.6-41 42.3-6.4 6.4 7.2 6.5 43.6 41.3 7.4 7.4 7.6-8-1-0.8 38.1-39.3 1.4 1.3 7.8-8m-54.3 39.3L178 226.5l38.1-39.3 43 40.8-38.2 39.3z M188.9 222.7l-5.6 5.4 7.1 6.9 5.2-5.8 8.1-8.4 6.3 6-6.4 6.7-5.6 5.5 7.1 6.6 5.3-5.7 6.4-6.7 8.8 8.3-8.7 9-5.8 5.6 7 6.6 5.4-5.9 24.6-25.4 6-5.9-7-6.6-4.5 5.1c-0.2-2.3-0.2-4.3-0.4-6.2l-3.1 0.1-4.3 0.3c-0.8 0-1.8 0-3.1-0.1l4.9-4.6-7.2-6.8-3.9 4.3-7.8 8.1-6.5-6 8.3-8.5 5.8-5.4-7.2-6.9-5.7 6.3-23.5 24.1z m39.9-1.8c0.1 2.4-0.1 4.6-0.5 6.5 4.1-0.5 6.8-0.6 7.9-0.5 1.2 0.1 2.4 0.2 3.2 0.4l-6.1 6.3-8.7-8.3 4.2-4.4zM346.9 144.6c1.8-3.3 3.9-7.1 6.4-11.4-4.5-0.6-7.3-1.1-8.3-1.4-1-0.3-2.2-0.7-3.5-1.3l-2.1 5.7c-0.5 1.6-2.8 6-6.9 13.5l-2.7-1.3c-0.9-0.5-3.1-0.9-6.4-1.4 1.9-2.9 3.9-5.9 5.9-9-1.6-0.2-3.1-0.4-4.6-0.7l11.9-6.1 7.8-3.8-4.4-8.4-7.7 4.1-33.5 17.3-7.1 3.4 4.5 8.5 6.8-3.8 11.8-6.1c-5 6.9-9.6 11.9-13.8 14.9-4.1 2.9-7.3 5.3-9.8 6.9 3.5 1.9 5.7 3.1 6.6 3.8 0.8 0.6 1.9 1.4 2.9 2.4 4-3.7 7-6.3 8.8-8.1 1.8-1.6 4.2-4.3 7.5-7.8l1.3 0.3c-2.1 3.7-4.5 7.2-7.1 10.6-2.7 3.2-5 5.8-7 7.8-2 1.9-4.4 3.9-7.4 6.1 3 1.6 5 2.7 6.1 3.5 0.9 0.6 2 1.4 3.2 2.4 5.7-5.6 9.9-10.3 12.4-14 2.7-3.6 5.5-7.8 8.5-12.8 0.5 0.3 1.2 0.8 1.7 1.3-2 4.1-5.2 9.4-9.5 15.6-4.3 6.3-10.6 12.7-18.7 19l4.4 2.2c1.3 0.6 3.1 1.9 5.6 3.8l8.5-9.4c2.5-2.6 5.3-6.2 8.5-10.6 3.1-4.5 5.6-8.5 7.5-12l0.4 1c0.5 0.9 1.1 2.3 1.7 4 0.7 1.6 0.7 3.1-0.1 4.3-0.6 1.3-3.3 2.6-7.8 4.1l3.4 2.7c0.9 0.6 2.6 2.5 5.2 5.6 6.3-3.4 9.9-6.3 10.8-8.7 0.9-2.5 0.9-4.9 0.4-7.2-0.7-2.1-1.8-4.8-3.5-8-1.8-3.1-2.9-5.3-3.7-6.4-0.7-1-1.5-2.2-2.4-3.5l2.1-3.1c3.5 3.5 6.7 6.2 9.6 8.3 2.9 1.9 6.2 3.5 10 4.9 3.8 1.4 9.1 2.2 16 2.7 0.3-3.3 0.6-5.6 0.9-7 0.3-1.4 0.7-3.1 1.3-5.3-4.8 0.5-9.7 0.2-14.7-1-4.8-1-8.7-2.8-11.6-5.3-2.7-2.4-4.7-4.4-6.1-5.8z M280.2 150.5l2 4.4 10.3-5.3-2.4-4.2-2.8-5.5 52-26.9 3 5.8 2.2 4.5 10.3-5.2-2.6-4.4-4.6-8.7-2.8-5.9-8.3 4.6-23.1 11.9c0.3-0.8 0.7-1.8 1.3-2.8-2.5-0.7-6.3-1.7-11.4-2.8-2 3.1-3.3 5.2-3.9 6-0.6 0.9-1.5 1.9-2.4 3 2.7 0.6 4.8 1.2 6.4 1.8l-21.6 11.1-9.2 4.3 3.1 5.6 4.5 8.7zM415.5 124.3l1.2 9.3 11.3-1.8-0.3-1.3 17.2-2.7 2 13c0.3 2 0.7 3.6 1.4 4.8 0.7 1.1 1.9 2.1 3.8 2.8 1.9 0.7 4.5 0.9 8 0.3 3.5-0.5 7.9-1.1 13.5-1.8 5.8-0.7 10-1.4 12.8-1.9 2.8-0.6 4.8-1.3 6.1-2 1.3-0.8 2.4-1.9 3.4-3.4s1.9-5.4 2.8-11.8c-3.3-0.6-7.2-1.8-11.6-3.5v3.6c0.1 2.3-0.4 4-1.4 5.1-1 1.1-2.4 1.8-4.1 2.3-1.8 0.5-4.8 0.9-9.1 1.5l-9.8 1.3c-2.1 0.3-3.5 0.1-4.1-0.4-0.6-0.7-0.9-1.3-1.1-2.1l-1.5-9.4 19.5-3.1 0.3 1.7 11.2-1.7-1.6-8.7-5.5-35.2-1-7.9-7.3 1.4-23.5 3.6-0.8-5-0.9-7.1-11.6 1.8 1.4 7 0.7 5.1-19.8 3.1-8.6 1 1.6 7.9 5.4 34.2z m56.6-21.1l1.6 10.1-19.5 3.1-1.6-10.2 19.5-3z m-3.2-19.8l1.6 10.3-19.5 3-1.6-10.3 19.5-3z m-25.6 34.7l-17.1 2.6-1.6-10.2 17-2.6 1.7 10.2z m-4.8-30l1.7 10.4-17.1 2.6-1.6-10.3 17-2.7zM616.3 76.1l-51.8-9-10.9-2.3-1.7 10.9-9.5 53.4-2.2 11.7 11.7 2.1 2-11.8 1.9-10.9c1.9 2.7 3.1 4.6 3.7 5.6 0.5 1.1 1.2 2.2 1.7 3.3 4-3.8 6.5-6.4 7.6-7.7 1.1-1.3 2-2.4 2.7-3.5l0.8 2.6c0.2 0.5 0.3 1.7 0.5 3.9l2.4-1.6c1.5-0.9 4-2 7.7-3.3-1.4-4.6-2.9-9-4.6-13.2l1.5-2.9c0.5-1 1.5-3.3 3-6.8 2.3 3.9 3.7 6.5 4.2 7.6 0.4 1 1.4 3.5 2.6 7.1l-2 3.5c-1.4 2.5-3.3 4.9-5.4 7.3-2.1 2.3-5 4.6-8.5 7 2.7 2.2 4.5 3.7 5.3 4.7 0.8 0.9 1.7 2 2.6 3.1 2-1.4 3.7-2.8 4.9-4.1 1.3-1.3 4-4.3 8-9.1l1.4 5.3c0.2 0.5 0.5 2.1 1 4.8 3.6-2.5 6.9-4.6 9.8-6.2l-1-3.2c-0.1-0.3-1.7-4.5-4.7-12.4l2.3-5.4c0.8-2 1.8-4.7 3.1-8.1l1.8-5.2c0.1-0.5 0.4-1.5 0.9-2.6-3.6-0.9-7.2-2-10.9-3.5l-0.5 2.8c-0.3 1.5-1.1 4.4-2.5 8.7-1.2-2.4-2.2-4.7-3.3-6.6l-2.2 1.4c-1.3 0.8-3.5 1.6-6.5 2.3l1.8-4.5c0-0.1 0.3-0.8 0.7-2.2 0.5-1.3 0.9-2.5 1.3-3.4-4.3-1.1-7.8-2.4-10.6-3.9l-0.8 3.7c-0.3 1.5-0.7 2.9-1.1 4.3-0.4 1.2-0.9 2.7-1.6 4.1-1.3-2.8-2.5-5.3-3.4-7.6-2.7 1.5-4.5 2.4-5.4 2.6-0.9 0.3-1.8 0.6-2.8 0.8l2.2-12.3 50.8 8.8-9.3 52.5c-0.2 1.1-0.5 1.8-1 2.3-0.5 0.6-1.9 0.6-4.1 0.1-1.9-0.4-3.9-0.9-5.9-1.6l0.9 3.1c0.8 3 1.1 5.2 1 6.6 0 1.5-0.2 2.6-0.2 3.5 5.8 0.7 10.1 0.7 12.8 0.3 2.7-0.5 4.5-1.4 5.2-2.9 0.7-1.6 1.2-3.3 1.6-5.1l10-56.6 2.2-10.8-11.2-1.5zM562.5 95c0.4 0.9 2 4.4 4.5 10.4-1.8 3.5-3.5 6.1-5.1 7.9-1.6 1.8-3.6 3.7-6 5.6l4.9-27.3 1.7 3.4zM731.6 161.2c1.8 4.6 4.5 9.1 7.7 13.4 4.5-3 7.2-4.8 8.3-5.4 1.1-0.6 2.3-1.1 3.5-1.5-2.6-2.5-4.3-4.4-5.2-5.5-0.7-1.1-1.7-2.6-2.6-4.3-1-1.8-2-4.3-3.2-7.7-1.2-3.4-1.5-7.1-0.9-11 0.5-4 1.1-6.6 1.6-8.2 0.5-1.4 0.9-2.6 1.5-3.5 0.5-1 1-2 1.8-3-4-1.9-7.5-4-10.6-6.3-1.9 5-3.1 8.5-3.7 10.6-0.6 2.2-1 5.1-1.5 8.5-0.4 3.6-0.5 7.2 0 11 0.3 4.1 1.5 8.3 3.3 12.9zM676.6 139.4c5-1 10.6-2.4 16.8-4.3 6.2-1.9 11.3-4 15.3-6.3 4-2.2 8.9-5 14.7-8.3-2.8-3-5.3-6.3-7.6-10.1l-2.2 1.9c-3.5 3-7.5 5.6-12.1 7.8-4.7 2.1-9.5 3.9-14.6 5.2-5.2 1.3-9.7 1.8-13.6 1.3l1.2 2.8c0.5 1.7 1.3 5.1 2.1 10zM673.8 174.3c2.3 1 8.2 3.4 18 7.7 9.8 4.2 17.2 7.5 22.4 9.9 0.2 3 0.3 5 0.2 6.1-0.1 1.1-0.1 2.3-0.3 3.7l3.4-0.8c0.2-0.1 3.4-0.5 9.9-1.4-0.9-8.5-2.3-19.5-4.2-33l-2.4 0.3c-1.4 0.2-4.5 0.1-9.3-0.5l1.2 5.8c0.3 1.5 0.7 4.6 1.2 9.5-10.1-5-20.4-9.9-30.7-15.1 5-1.5 9.2-2.9 12.7-4.2 3.5-1.4 6.9-2.8 10.4-4.4l7.3-3.5c0.9-0.4 2.2-1 4-1.9-2.6-3.7-5-7.7-7.1-11.9l-1.8 1.7c-0.9 0.7-2.9 2.3-6.3 4.5-3.3 2.3-6.6 4.1-9.9 5.7-3.3 1.5-6.5 2.8-9.5 3.9-3.1 1.1-5.6 1.8-7.4 2.1-1.8 0.3-4.6 0.5-8.3 0.7l0.1 3.1c0.1 2-0.3 5.2-1.3 9.6 2.8 0.7 5.4 1.6 7.7 2.4zM821.3 234l-18.7-20-5.9-6.8-5.8 5.8-11.5 10.7-6.7 5.6 6.4 6.4 18.8 19.9 6.6 7.4 6.2-6.2 11.5-10.7 6.3-5.2-7.2-6.9z m-17 14l-16.5-17.5 9-8.3 16.5 17.4-9 8.4z M829.4 233.1l7.5 8.4 7.9-7.3-8.1-7.9-26.3-28-6.8-7.6-7.8 7.2 7.3 7.3z M855 233.2l-40.8 37.7c-1.3 1.2-2.2 1.7-2.9 1.8-0.7 0-1.7-0.6-3-1.9-0.5-0.4-1.3-1.3-2.3-2.4-1.1-1.2-2.1-2.4-3-3.4l-1.4 3.3c-0.8 1.8-1.6 3.3-2.6 4.5-0.9 1.2-1.8 2.3-2.6 3.3 5.4 5 9.2 7.9 11.7 8.8 2.4 0.9 4.1 1.2 5.2 0.8 1-0.3 2.6-1.4 4.5-3.3l45.4-41.8 7.2-6.1-7.2-7.3-36.2-38.5-7.9-8.7-8 7.3 8.4 8.4 35.5 37.5zM120.2 359.2c4.7 2.2 8.9 2.7 12.7 1.6 3.8-1.2 8-4.3 12.7-9.8 0.5-0.5 1.2-1.3 2.2-2.4 6.4-7.7 11.2-10.7 14.2-9.3 1.7 0.8 2.8 2.2 3.3 4.2 0.4 2 0 4.1-1.1 6.4-1.5 3.1-4.1 5.6-7.6 7.4-3.6 1.8-7.7 2.6-12.5 2.6l-0.5 6.4 19.4 4 2.4-4.9-2.4-2.5c2.2-1.2 4.2-2.6 5.8-4.3 1.6-1.7 3-3.7 4.1-5.8 2.6-5.3 3-10.5 1.3-15.7-1.8-5.2-5.3-9-10.6-11.5-2.7-1.3-5.4-1.9-8.1-2-2.7-0.1-5.3 0.5-7.6 1.6-1.1 0.6-2.7 1.7-4.5 3.5-1.8 1.8-4.2 4.2-7.2 7.3-0.4 0.5-0.9 1.1-1.7 2-5.8 6.5-10.3 9-13.3 7.5-2-1-3.4-2.7-4-5.3-0.6-2.4-0.3-5 1-7.6 1.8-3.8 5-6.6 9.4-8.6 4.5-2 9.8-2.9 16.1-2.7l0.6-7.1-24.5-4.2-2.3 4.7 3.2 2.6c-2.4 1.6-4.7 3.3-6.5 5.4-1.9 2.1-3.5 4.3-4.7 6.9-3 5.9-3.4 11.5-1.4 17 1.9 5.3 6 9.5 12.1 12.6zM96.8 396.5c1.6-0.4 4.8 0 9.5 1.5l34.2 10.9-0.2 0.9c-1.2 3.5-3 6.2-5.8 7.9-2.7 1.7-6.7 2.9-12.1 3.6l0.6 6 20.8-0.3 14.7-45-16.7-12.2-4 4.5c4.1 3.6 6.6 6.9 7.7 9.8 1.2 3 1.2 6.2-0.1 9.8l-0.2 0.9-34.2-10.9c-4.8-1.6-7.7-2.9-8.7-4.3-1-1.4-1.1-3.2-0.4-5.8l-7.5-2.4-8.8 27.2 7.6 2.3c0.8-2.4 2-4 3.6-4.4zM89.1 469l0.4-0.1 49.7-6.9 2.5-12.9-41.4-24.4c-0.3-0.1-0.6-0.3-1.1-0.6-5.4-3.1-8.1-6.8-7.9-10.9l-7.8-1.4-4.5 23.5 7.6 1.5c0.5-2.4 1.2-3.9 2-4.7 0.9-0.7 2.2-1 3.7-0.6 0.2 0 0.5 0.1 0.8 0.2 0.3 0.1 0.6 0.2 1 0.3l8.2 4-3.3 17.3-9.3 1.3c-0.4 0.1-0.8 0.1-1.3 0.1-0.5-0.1-1-0.1-1.6-0.2-1.3-0.2-2.2-0.8-2.6-1.7-0.4-0.9-0.4-2.4 0-4.4l0.1-0.7-7.6-1.4-5.3 27.4 7.8 1.4c1.4-3.3 4.6-5.3 9.9-6.1z m20.5-28.6l17 9.5-19.1 1.9 2.1-11.4zM81.1 510c1.4-0.9 4.6-1.2 9.7-1l35.8 1.6v0.9c-0.1 3.7-1.3 6.7-3.5 9.2-2.1 2.3-5.6 4.5-10.7 6.5l2.2 5.6 20-5.6 2.1-47.3-19.3-7.4-2.7 5.3c4.8 2.5 8.1 5 10.1 7.5 1.8 2.6 2.7 5.7 2.5 9.4l-0.1 0.9-35.8-1.7c-5.1-0.2-8.3-0.8-9.5-1.9-1.4-0.9-2-2.8-1.9-5.5l-7.9-0.3-1.4 28.4 7.9 0.4c0.3-2.4 1.2-4 2.5-5zM103.2 590.2c-5.9-2.4-10.6-5.4-14.2-9.3-3.6-3.8-5.7-7.8-6.3-12.1-0.3-2.6 0-4.3 0.9-5.3s3-1.8 6.4-2.2l14.9-1.8 0.3 2.8c0.3 2.2-0.3 4.1-1.9 5.5-1.6 1.4-4.2 2.6-7.9 3.5l0.7 6 28.9-3.4-0.7-6c-4.1 0.3-6.9 0-8.3-0.9-1.3-0.8-2.2-2.7-2.6-5.6l-0.4-2.8 9.2-1c3.4-0.5 5.7-0.3 6.8 0.5 1 0.8 1.8 2.4 2.1 4.9 0.5 4.3-0.2 8.4-2.2 12.3-2 3.9-5.3 7.7-9.8 11.2l3.8 4.9 18.3-9.9-5.8-47.1-7.8 0.9c0.2 2.5-0.2 4.3-1.4 5.4-1.3 1.1-4.3 1.8-9.6 2.4L92.2 546c-5.2 0.6-8.5 0.6-10-0.1-1.4-0.8-2.3-2.4-2.6-5l-7.9 0.9 5.9 48.3 22.9 6 2.7-5.9zM126.5 677.5c1.5 0.3 3 1.6 4.5 3.9l6.9-2.7-9.6-24.8-7 2.7c0.8 2.4 1 4.3 0.3 5.7-0.5 1.4-1.9 2.5-4.1 3.3-3.1 1.3-6 1.3-8.6-0.1-2.7-1.2-4.6-3.5-5.9-6.8-1.6-4.1-0.9-8.1 2-11.7 3-3.7 8.1-6.9 15.3-9.6 7.5-2.9 13.6-3.9 18.4-3.3 4.9 0.8 8 3.2 9.7 7.3 1.3 3.3 1.2 6.8-0.2 10.2-1.4 3.5-4.4 7.6-8.8 12.2l5 5.2 18.4-12.7-1.9-5.1-2.9-0.2c0.3-2.5 0.3-4.8 0.1-6.9-0.3-2-0.8-4.1-1.5-6.1-3.1-7.9-8.5-13.3-16.3-16.2-7.8-2.9-16.1-2.6-25.1 0.8-9.7 3.8-16.5 9-20.7 15.6-4.1 6.7-4.7 13.7-1.8 21.1 1.2 3.1 2.8 5.8 4.6 7.9 1.9 2.1 4.2 4.1 7.1 5.7l-4.1 4.1 3.1 7.9 15.9-6.1c3.4-1.3 5.8-1.7 7.2-1.3zM183.4 696.3l-15.9-28.8-6.9 3.8c1.2 2.5 1.5 4.4 0.8 5.8-0.8 1.5-3.3 3.5-7.8 6l-21.8 11.7c-4.5 2.4-7.5 3.5-9.2 3.4-1.6-0.2-3.1-1.5-4.6-3.9l-6.9 3.8 13.9 25.2 7-3.7c-1.3-2.5-1.5-4.4-0.8-5.9s3.4-3.4 7.9-5.8l7.1-3.9 2.7 5-15.6 29.2 8.9 16.1 6.8-3.7c-0.9-1.9-1.2-3.7-1.1-5.4 0-1.6 0.6-3.5 1.7-5.7l8.5-17.8c3.5 3.3 6.9 5.2 10.4 5.8 3.5 0.5 7.1-0.2 11-2.2 5.2-2.8 8-6.6 8.6-11.5 0.7-4.6-0.8-10.5-4.7-17.5z m-6.8 9.5c-0.5 2.8-2.1 4.8-4.7 6.3-3 1.6-5.8 1.6-8.6 0.1-2.7-1.6-5.5-4.8-8-9.5-0.4-0.7-0.8-1.3-1-1.7-0.2-0.4-0.4-0.8-0.5-1.2l10.4-5.5c3-1.6 5.1-2.2 6.4-2 1.3 0.3 2.6 1.7 3.9 4.1 1.9 3.4 2.5 6.6 2.1 9.4zM168 772.7c0.5-1.6 2.9-3.9 6.9-6.8l20.1-14.3c4-2.9 6.9-4.5 8.6-4.4 1.7 0 3.4 1.1 5.2 3.3l6.4-4.7-17.2-23.5-6.4 4.6c1.6 2.4 2 4.3 1.5 5.8-0.5 1.6-2.8 3.8-6.9 6.8l-20.1 14.4c-4 2.8-7 4.4-8.6 4.3-1.7 0-3.4-1.1-5.1-3.3l-6.5 4.6 17.2 23.5 6.4-4.5c-1.6-2.3-2.1-4.2-1.5-5.8zM236.8 771.1L219 749.4l-6.2 4.9c1.6 2 2.2 3.7 1.7 5.2-0.5 1.6-2.7 3.9-6.9 7.2l-19 15.3c-4.1 3.2-7 4.9-8.5 5-1.6 0.2-3.2-0.7-4.9-2.7l-6.2 4.9 17.8 21.9c6.9 8.3 14.1 13 22.1 13.9 7.9 1 15.9-1.7 23.9-8.2 8.1-6.5 12.5-13.6 13.2-21.4 0.5-7.8-2.5-15.9-9.2-24.3z m-3.2 18.7c-1.4 5.1-5 10.1-10.9 14.8-5.8 4.6-11.5 7.1-16.8 7.3-5.4 0.2-9.7-1.9-13.2-6.1-1.5-1.9-2.3-3.5-2.1-4.7 0.2-1.2 1.6-2.9 4.4-5.1l25.2-20.1c2.8-2.2 4.8-3.3 6-3.2 1.2 0.1 2.6 1.1 4.2 3 3.4 4.3 4.5 9 3.2 14.1zM307.3 862l8.3-23.2-3.7-2.7-3.2 2.5c-1.1-2.6-2.3-4.8-3.7-6.7-1.4-1.9-3.1-3.5-4.8-5-6.9-5.1-14.4-7-22.7-5.5-8.3 1.5-15.3 6.1-21.2 13.8-6.2 8.1-9 16.3-8.3 24.5 0.7 8.2 4.7 15.1 12.1 20.7 5.1 3.9 10.6 5.9 16.4 6.2 5.9 0.3 12-1.5 18.6-4.9l-3.6-6.9c-4.4 2.1-8.8 3.1-13.2 2.9-4.4 0-8-1.1-10.8-3.3-4.1-3.1-6.1-7.3-5.8-12.5 0.3-5.3 2.7-10.9 7.4-16.9 4.5-6 9.4-10 14.4-11.7 4.9-1.8 9.3-1.3 13.2 1.6 3 2.3 4.7 5.7 5.6 10.1 0.8 4.6 0.5 9.6-1 15.2l6 1.8zM366.7 873.4c-2.6-8-8-14-16.5-17.9-8.4-4-16.5-4.4-24.4-1.4-7.8 3.1-13.9 9.1-18.2 18.1-4.3 9-5.2 17.5-2.6 25.4 2.6 8 8 13.9 16.4 17.9 8.4 3.9 16.5 4.4 24.4 1.3 7.9-3.1 14-9.1 18.3-18 4.3-9 5.2-17.5 2.6-25.4z m-17.1 18.5c-3.4 7.2-7.3 12.1-11.6 15.1-4.3 2.8-8.7 3.3-12.9 1.2-4.4-2-6.8-5.6-7.3-10.7s1-11.2 4.4-18.5c3.5-7.2 7.4-12.2 11.7-15.1 4.3-2.8 8.7-3.3 13-1.3 4.3 2.1 6.6 5.6 7.1 10.8 0.5 5.2-1 11.3-4.4 18.5zM429.2 903c1.7-5.5 1-10.3-1.9-14.1-3-3.9-8.3-6.9-15.9-9.2l-31.8-9.4-2.2 7.4c2.6 0.9 4.2 2.2 4.7 3.7s0 4.7-1.4 9.6l-7.1 23.5c-1.5 4.8-2.8 7.7-4.1 8.7-1.2 0.9-3.3 1.2-6 0.5l-2.3 7.6 27.9 8.3 2.2-7.6c-2.6-0.8-4.2-2.1-4.7-3.6-0.5-1.6 0-4.8 1.4-9.6l2.4-7.7 5.5 1.7 9.7 31.6 17.8 5.2 2.3-7.3c-1.9-0.9-3.5-1.8-4.6-3-1.2-1.3-2.2-3-2.9-5.4l-6.6-18.6c4.9-0.1 8.6-1.1 11.6-3.1 2.7-1.9 4.7-5 6-9.2z m-14.9-4.1c-1 3.2-2.9 5.2-6 6-3.1 0.9-7.2 0.5-12.5-1.2-0.9-0.3-1.5-0.4-2-0.5-0.4-0.1-0.8-0.3-1.1-0.4l3.4-11.2c0.9-3.2 2-5.2 3.2-5.8 1.2-0.7 3.1-0.6 5.6 0.1 3.8 1.1 6.6 2.8 8.2 5.1 1.7 2.4 2.1 5 1.2 7.9zM471.7 891.8l-30.4-3.8-1 7.7c2.5 0.4 4.2 1.3 4.9 2.7 0.7 1.4 0.7 4.7 0.1 9.9l-3.1 24.2c-0.7 5.2-1.5 8.2-2.6 9.4-1.1 1.2-2.8 1.6-5.4 1.4l-1 7.8 28 3.5 0.9-7.7c-2.6-0.5-4.2-1.3-4.9-2.8-0.7-1.4-0.8-4.6-0.1-9.7l0.9-6.5 9.9 1.3c7 0.9 12.6 0.1 16.5-2.6 3.9-2.5 6.2-6.9 7.1-13 0.8-6.2-0.4-11.2-3.8-14.9-3.4-3.8-8.7-6-16-6.9z m4.7 19.2c-0.4 3.6-1.9 6.3-4.4 7.9-2.4 1.6-5.9 2.1-10.3 1.6-0.6-0.1-1.2-0.2-1.6-0.3-0.4-0.1-0.7-0.1-1.2-0.2l1.8-13.6c0.4-3.3 1.1-5.4 2-6.3 0.8-0.9 2.3-1.3 4.5-1 3.3 0.4 5.8 1.7 7.3 3.9 1.7 2 2.3 4.7 1.9 8zM556.7 925.4c-0.3-9.9-3.6-17.9-9.6-23.7-6-5.9-13.7-8.7-23-8.4-9.2 0.5-16.7 3.7-22.2 10-5.6 6.4-8.1 14.4-7.8 24.3s3.5 17.9 9.6 23.8c6 5.9 13.5 8.7 23 8.3 9.2-0.3 16.6-3.6 22.2-10 5.5-6.3 8.1-14.4 7.8-24.3z m-19.5 19.2c-2.4 4.5-6.1 6.9-10.9 7-4.8 0.2-8.6-1.9-11.5-6.2-2.8-4.3-4.3-10.4-4.6-18.3-0.3-7.9 0.8-14.2 3.3-18.7s6.1-6.8 10.9-7c4.8-0.1 8.5 1.9 11.4 6.2 2.8 4.4 4.5 10.5 4.7 18.4 0.4 7.9-0.7 14-3.3 18.6zM622.3 936.9c-1.6-0.6-3.3-1.7-4.9-3.5l-14.2-13.8c4.3-2.1 7.3-4.7 9-7.7 1.7-3.1 2.2-6.7 1.6-11.1-1-5.7-3.7-9.6-8-11.9-4.4-2.2-10.5-2.6-18.4-1.3l-32.7 5.3 1.3 7.8c2.7-0.4 4.7 0 5.8 1.2 1.2 1.2 2.2 4.2 3 9.2l4 24.2c0.8 5 0.9 8.3 0.1 9.6-0.7 1.5-2.4 2.5-5.1 3l1.3 7.7 28.6-4.6-1.3-7.7c-2.8 0.4-4.6-0.1-5.8-1.2-1.2-1.2-2.1-4.3-2.9-9.3l-1.3-7.9 5.7-0.9 22.7 24.3 18.3-3.1-1.2-7.5c-2.2 0.1-4-0.1-5.6-0.8z m-26.5-25.3c-2.4 2.1-6.2 3.5-11.7 4.4-0.9 0.1-1.6 0.3-2 0.4-0.5 0-0.9 0.1-1.3 0.1l-2-11.6c-0.5-3.3-0.4-5.5 0.3-6.7 0.8-1 2.5-1.9 5.2-2.2 3.9-0.6 7.1-0.3 9.5 1 2.5 1.4 4 3.6 4.5 6.6 0.8 3.2-0.1 6-2.5 8zM681.3 908.2l-0.3-0.3-32.3-38.2-12.3 4.7 1 47.7v1.2c0.1 6.2-1.6 10.4-5.2 12.5l2.9 7.3 22.5-8.6-2.8-7.1c-2.2 0.7-3.9 1-5.1 0.8-1.2-0.4-2-1.3-2.6-2.8-0.1-0.2-0.2-0.5-0.3-0.8-0.1-0.4-0.1-0.7-0.2-1l-0.9-9.1 16.6-6.3 6 7.1c0.3 0.3 0.5 0.7 0.7 1 0.3 0.5 0.4 0.9 0.7 1.4 0.4 1.2 0.4 2.2-0.2 3.1-0.5 0.8-1.8 1.6-3.6 2.3l-0.7 0.3 2.8 7.2 26.2-10-2.8-7.4c-3.2 0.8-6.7-0.9-10.1-5z m-35.4-2.1l-0.9-19.3 11.8 15.1-10.9 4.2zM722.1 896.2c-1.5-0.8-3.5-3.4-5.8-7.8L699.6 857l0.9-0.4c3.3-1.8 6.6-2.3 9.7-1.7 3.2 0.6 6.9 2.4 11.2 5.8l3.8-4.7-15.2-14.1-42.2 22 3.3 20.3 6-0.4c-0.3-5.4 0.2-9.6 1.5-12.5 1.2-2.9 3.5-5.2 6.9-7l0.8-0.4 16.7 31.5c2.4 4.4 3.5 7.4 3.3 9s-1.5 3.1-3.8 4.4l3.7 6.9 25.5-13.3-3.7-7c-2.5 1.4-4.5 1.5-5.9 0.8zM767.3 868.2c-1.7-0.5-3.9-2.9-6.7-7l-14-20.2c-2.8-4.1-4.2-7-4.2-8.7 0.1-1.6 1.2-3.3 3.5-5l-4.5-6.4-24.2 16.5 4.5 6.4c2.4-1.4 4.4-1.9 5.9-1.4 1.6 0.6 3.8 2.9 6.7 7l14 20.2c2.9 4.1 4.3 7 4.3 8.7-0.1 1.6-1.2 3.3-3.5 5l4.4 6.4 24.3-16.5-4.5-6.5c-2.4 1.6-4.5 2-6 1.5zM811.5 808.1c-5.9-7.9-13.1-12.8-21.4-14.2-8.3-1.5-16.2 0.5-23.7 6-7.5 5.6-11.7 12.5-12.6 20.8-0.9 8.3 1.6 16.3 7.6 24.3s13.2 12.7 21.5 14.2 16.2-0.5 23.7-6c7.4-5.5 11.6-12.4 12.6-20.8 0.9-8.2-1.6-16.4-7.7-24.3z m-9.8 38.6c-3.9 2.8-8.2 3.2-13 1.2-4.8-2-9.6-6.1-14.4-12.5-4.8-6.4-7.5-12.1-8-17.2s1.2-9.1 5-12c3.8-2.8 8.1-3.2 12.9-1.2 4.8 2 9.6 6.2 14.5 12.5 4.7 6.4 7.4 12.1 7.9 17.2 0.5 5.2-1.2 9.1-4.9 12zM914.6 695.8c-3.1-7.9-9.1-13.9-18.2-18.2-9.2-4.2-17.7-5.1-25.7-2.5-8.1 2.6-14 8.1-18 16.4-4 8.3-4.4 16.4-1.3 24.2 3.1 7.7 9.2 13.8 18.3 18 9 4.2 17.6 5.1 25.6 2.5 8.1-2.5 14.2-8 18.1-16.3 3.9-8.4 4.4-16.4 1.2-24.1z m-8.6 20.5c-2.1 4.3-5.7 6.7-10.8 7.2-5.2 0.5-11.4-0.9-18.7-4.3-7.3-3.4-12.4-7.3-15.3-11.5-3-4.3-3.3-8.5-1.3-12.8 2-4.2 5.6-6.6 10.7-7.1 5.3-0.5 11.5 0.9 18.8 4.3 7.3 3.4 12.3 7.2 15.2 11.4 3 4.3 3.4 8.6 1.4 12.8zM926.4 657.2c-1.6 0.5-4.7-0.1-9.5-1.8l-10.2-3.5 0.9-2.5c0.9-2.5 2.4-4.1 4.5-4.9 2.2-0.7 5-0.7 8.7 0.1l1.8-5.1-28.3-9.6-1.8 5.1c3.6 1.4 6 3 6.9 4.5 0.8 1.5 0.7 3.9-0.3 7.1l-0.9 2.5-8.4-2.9c-3.3-1.1-5.2-2.2-5.8-3.5-0.5-1.2-0.4-3.3 0.5-5.9 1.5-4.2 3.9-7.6 7.2-10.3 3.4-2.7 7.7-4.7 12.9-6l-1-5.8-20.2 1.9-15.8 45.4 7.4 2.5c1.1-2.5 2.5-4 4.1-4.5 1.5-0.6 4.6 0.1 9.4 1.8l23.5 7.9c4.8 1.7 7.7 3.2 8.6 4.5 0.9 1.4 0.9 3.3 0.2 6l7.5 2.6 9.6-27.6-7.5-2.6c-1 2.6-2.3 4.1-4 4.6zM957.1 551.7c-2.6-5.1-7.1-9.6-13.4-13.6l-4.4 6.5c4 2.8 7.1 6.2 9.1 10 2.2 3.9 3 7.5 2.5 11-0.7 5.2-3.4 8.8-8.1 11.2-4.8 2.3-10.9 3-18.6 1.9-7.5-1-13.3-3.2-17.4-6.6-4.1-3.4-5.8-7.5-5.1-12.2 0.5-3.6 2.4-6.9 6-9.8 3.6-3 8.2-5.2 13.8-6.6l-1.3-6.3-24.5 4.3-0.6 4.5 3.8 1.6c-1.8 2.2-3.1 4.4-4.1 6.5-1 2.1-1.7 4.3-2 6.5-1.2 8.5 1 15.9 6.4 22.3 5.4 6.3 13 10.2 22.6 11.4 10.2 1.4 18.6-0.3 25.6-4.9 6.9-4.7 11-11.6 12.2-20.6 1.2-6.2 0.2-11.9-2.5-17.1zM947.4 473.6c-1.4 1-4.5 1.6-9.7 1.8l-24.6 1c-5.2 0.3-8.5-0.1-9.9-1-1.3-0.9-2.1-2.6-2.3-5.3l-7.9 0.3 1.2 28.6 7.6-0.4c0-2.6 0.6-4.4 2-5.4 1.3-1.1 4.5-1.6 9.7-1.8l6.5-0.3 0.9 21.7-6.4 0.3c-5.1 0.1-8.3-0.2-9.8-1-1.5-0.9-2.3-2.7-2.5-5.3l-7.6 0.3 1.2 28.5 7.9-0.3c0-2.6 0.6-4.4 2-5.4s4.5-1.6 9.7-1.8l24.7-1c5-0.1 8.3 0.1 9.7 1 1.4 0.9 2.2 2.6 2.4 5.3l7.9-0.3-1.2-28.4-7.7 0.3c0.1 2.7-0.6 4.5-1.8 5.4-1.3 0.9-4.5 1.6-9.7 1.8l-10.8 0.4-0.9-21.7 10.8-0.4c5.1-0.2 8.4 0.1 9.8 1 1.5 0.9 2.2 2.7 2.4 5.3l7.6-0.3-1.2-28.5-7.9 0.3c-0.2 2.5-0.9 4.3-2.1 5.3zM941.9 434.6c-1.2 1.2-4.2 2.3-9.1 3.1l-24.4 4.3c-4.9 0.9-8.2 1-9.7 0.3-1.5-0.8-2.6-2.4-3.3-5.2l-7.8 1.4s0.8 3.4 2.4 13 2.8 15.6 2.8 15.6l7.8-1.4c-0.3-2.8 0-4.7 1.2-5.9 1.2-1.2 4.2-2.3 9.3-3.2l24.3-4.3c4.9-0.9 8.2-1 9.7-0.2 1.5 0.7 2.6 2.4 3.2 5.1l7.8-1.4-5.2-28.6-7.8 1.4c0.3 2.9 0 4.8-1.2 6zM882.4 381.1c-1.6-0.5-2.8-2-3.6-4.6l-7.6 2.2 5.8 20.4 7.4-2.1c-0.6-2.6-0.4-4.5 0.7-5.8 1-1.1 4-2.4 8.9-3.8l16.6-4.7-29.9 29.1 6.6 23.4 7.8-2.1c-0.7-2.6-0.5-4.5 0.5-5.8 1.1-1.3 4.1-2.6 9-3.9l23.7-6.6c5-1.4 8.1-1.8 9.7-1.3 1.6 0.5 2.8 2.1 3.6 4.5l7.6-2-5.9-20.7-7.4 2.1c0.6 2.6 0.4 4.6-0.6 5.7-1.1 1.3-4.1 2.6-9 3.9l-28.7 8.1 40.2-39.4-2.9-10-42.8 11.9c-4.9 1.6-8.2 2.1-9.7 1.5zM863.9 363.8l48.2-3.5c0.3 0 0.7-0.1 1.2-0.1 6.3-0.5 10.6 1.1 12.8 4.3l7.3-3.2-9.9-21.8-7.1 3.2c0.9 2.2 1.4 3.9 1.1 5-0.3 1.2-1.1 2-2.6 2.7-0.2 0.1-0.5 0.2-0.9 0.3-0.3 0.1-0.7 0.2-0.9 0.3l-9.2 1.4-7.3-16.1 6.9-6.3c0.3-0.2 0.6-0.5 1-0.7 0.4-0.3 0.9-0.5 1.4-0.7 1.2-0.5 2.2-0.6 3.2 0 0.8 0.5 1.6 1.8 2.5 3.5l0.2 0.6 7.2-3.1-11.6-25.4-7.3 3.2c1 3.2-0.4 6.7-4.3 10.4l-0.3 0.1-36.8 34 5.2 11.9z m26.6-21.7l4.8 10.6-19.4 2M830.5 748.1c-0.5-1.6 0.1-3.5 1.8-5.6l-6.1-5-13.8 16.3 5.9 4.9c1.8-1.9 3.5-2.8 5.2-2.6 1.6 0.2 4.3 2 8.2 5.2l13.2 10.9-41.1-8.1-15.8 18.6 6 5.1c1.8-2 3.5-2.9 5.1-2.8 1.7 0.1 4.5 1.9 8.3 5.1l18.9 15.6c3.9 3.3 6.1 5.7 6.5 7.3 0.5 1.5-0.1 3.4-1.8 5.5l6.1 5.1 13.9-16.4-6-4.9c-1.8 1.9-3.6 2.8-5.2 2.7-1.7-0.2-4.4-1.9-8.3-5.1l-22.8-19 55.4 10.7 6.7-8-34-28.3c-3.7-3.3-5.9-5.7-6.3-7.2zM320.9 587.9c18.7 6.1 38.5 11.1 59.1 14.9-4.3-27.3-6.7-56.1-6.7-85.8 0.1-140.7 52.6-260.5 126-305.7-57.9 63.3-95.4 164.7-95.5 279 0 41.4 4.9 81.2 14 118.1 27.5 3.1 56.1 4.2 85.5 3 154.3-6 283.2-71.8 328.4-158.2-27.4-153-161-269.2-322-269.3h-0.3C400 214 317.1 355.3 317 525.2c0 21.5 1.4 42.4 3.9 62.7zM403.2 679.4c-5.2-15.7-9.6-32.2-13.1-49.4-21.5-4.8-41.8-10.8-60.5-17.8 2.8 16.9 6.4 33.3 10.9 49.2 19.7 7.1 40.7 13.2 62.7 18zM416.9 715.3c-21.6-2.8-42.4-6.7-62.1-11.5 16.1 40.8 37.7 76.3 63.3 104.4-35.3-21.8-65.7-60.8-87.8-111-48.6-14.7-89.6-35.5-118.9-60.6 48.2 120.5 166 205.6 303.8 205.7 7.6 0 15.2-0.3 22.7-0.8-49.5-14.2-92.3-60.6-121-126.2z M537.3 642.3c-37.2 1.5-73.2-0.4-106.8-5.1 5.4 17.5 11.7 34.3 18.9 50.2 24.2 3.1 49.3 4.8 75 4.9 118 0.1 222.7-34.5 288-87.8-46.7 67.6-170.2 116.1-315.4 116-10.4 0-20.7-0.3-30.9-0.8 32.4 55.9 76.6 96.4 127 113.3 142.6-34.7 248.6-162.7 249.6-315.7-45.2 67.9-164.1 119.5-305.4 125zM190.2 553c25 39.1 68 72.8 122.9 97.3-4.8-16-8.8-32.9-12.1-50.3-34.8-16.8-62.3-37.7-80-61.6 21.8 16.7 47.8 31.1 76.9 42.9-3.7-25.3-5.6-51.7-5.6-79 0.1-130.5 45.2-243 110.4-294.7C277.5 253.5 188.1 373.7 188 514.9c0 12.9 0.8 25.6 2.2 38.1z M167 515c0 192.3 155.9 348.2 348.3 348.2 192.3 0 348.2-155.9 348.2-348.2 0-192.4-155.9-348.3-348.2-348.3-192.4 0-348.3 156-348.3 348.3z m348.3-340.2c187.9 0 340.2 152.3 340.2 340.2 0 187.9-152.3 340.2-340.2 340.2-187.9 0-340.2-152.3-340.2-340.2 0-187.9 152.3-340.2 340.2-340.2z"; + -jfx-size: 20; + -fx-background-color: WHITE; +} + +/******************************************************************************* +* * +* JFX Hamburger Icon * +* * +*******************************************************************************/ + +.jfx-hamburger { + -fx-padding: 10.0; + -fx-spacing: 4px; + -fx-cursor: hand; +} + +.jfx-hamburger StackPane { + -fx-pref-width: 40px; + -fx-pref-height: 4px; + -fx-background-color: #FFF; + -fx-background-radius: 5px; +} + +/******************************************************************************* +* * +* JFX TabPane * +* * +*******************************************************************************/ + + +.jfx-tab-pane .tab-header-background { + -fx-background-color: #ffffff; +} + +.jfx-tab-pane .headers-region .tab-selected-line { + -fx-background-color: -fx-decorator-color; + -fx-pref-height: 3px; +} + +.jfx-tab-pane .headers-region .tab .tab-container .tab-label { + -fx-text-fill: rgba(0, 0, 0, .87); + -fx-font-weight: BOLD; + -fx-padding: 6 10 6 10; + -fx-font-size: 16; +} + +.jfx-tab-pane .headers-region .tab:selected .tab-container .tab-label { + -fx-text-fill: #030304; + +} + +.jfx-tab-pane .headers-region .tab .tab-container .tab-close-button > .jfx-svg-glyph { + -fx-background-color: rgba(3, 3, 4, 0.46); + -jfx-size: 14; + + +} + +.jfx-tab-pane .headers-region .tab { + -fx-pref-height: 50px; + +} + +.jfx-tab-pane .headers-region .tab MaterialDesignIconView { + -glyph-size: 25; + +} + +.jfx-tab-pane .headers-region .tab:closable { + -fx-border-color: rgba(0, 0, 0, 0); +} + +.jfx-tab-pane .headers-region .tab .tab-container .tab-close-button { + -fx-background-color: TRANSPARENT; + -fx-background-radius: 20; +} + +.jfx-tab-pane .headers-region .tab .tab-container .tab-close-button:hover { + -fx-background-color: rgba(0, 0, 0, .3) + +} + +.jfx-tab-pane .headers-region .tab .tab-container .tab-close-button:focused { + -fx-background-color: TRANSPARENT; +} + +.jfx-tab-pane .headers-region .tab:hover .tab-container .tab-close-button > .jfx-svg-glyph { + -fx-background-color: rgba(3, 3, 4, 1); + -jfx-size: 14; +} + +.jfx-tab-pane .headers-region .tab .tab-container .jfx-svg-glyph { + -fx-background-color: rgb(17, 17, 17); + -jfx-size: 20; +} + + +.jfx-tab-pane .headers-region > .tab:hover { + -fx-background-color: rgba(82, 100, 174, .3) +} + +.jfx-tab-pane .headers-region > .tab:selected { + -fx-background-color: rgba(82, 100, 174, .5) +} + + +/******************************************************************************* + * * + * JFX Tool Bar * + * * + ******************************************************************************/ + +.jfx-tool-bar { + -fx-background-color: -fx-theme-color; + -fx-pref-width: 100.0%; + -fx-pref-height: 45.0px; +} + +.jfx-tool-bar HBox { + -fx-alignment: center; + -fx-spacing: 3.0; + -fx-padding: 0.0 10.0; +} + + +.jfx-tool-bar MaterialDesignIconView { + -fx-fill: -fx-theme-rippler-color; + -fx-text-fill: -fx-theme-rippler-color; + -fx-prompt-text-fill: -fx-theme-rippler-color; + -glyph-size: 24; + -fx-background-color: -fx-theme-rippler-color; + -jfx-size: 20; +} + +.tool-bar-button { + -fx-fill: -fx-theme-rippler-color; + -fx-text-fill: -fx-theme-rippler-color; + -fx-prompt-text-fill: -fx-theme-rippler-color; + -fx-background-radius: 20; + -jfx-button-type: FLAT; +} + +.tool-bar-button:hover { + -fx-background-color: rgba(255, 255, 255, .2) +} + +.tool-bar-button:focused { + -fx-background-color: TRANSPARENT +} + +.tool-bar-button > .jfx-rippler { + -jfx-rippler-fill: -fx-theme-rippler-color; +} + +/******************************************************************************* +* * +* JFX Rippler * +* * +*******************************************************************************/ + + +.jfx-rippler:hover { + -fx-cursor: hand; +} + + +/* ***************************************************************************** + * 24px ICONS + ****************************************************************************/ +.samples-icon { + -fx-shape: "M12,0C5.373,0,0,5.373,0,12s5.373,12,12,12c6.627,0,12-5.373,12-12S18.627,0,12,0z M7.5,18V6l12.006,6L7.5,18z"; + -fx-scale-shape: false; + -fx-background-color: #515151; +} + +.documentation-icon { + -fx-shape: "M12,3c0,0-3-3-12-3v18c9.094,0,12,3,12,3s2.906-3,12-3V0C15,0,12,3,12,3z M3,3c3.813,0.319,6.152,1.201,7.5,1.916v12.082c-1.348-0.712-3.687-1.594-7.5-1.916V3z M21,15.082c-3.814,0.322-6.154,1.203-7.5,1.916V4.916C14.846,4.201,17.186,3.319,21,3V15.082z"; + -fx-scale-shape: false; + -fx-background-color: #515151; +} + +.folder-icon { + -fx-shape: "M4.141,4.039h15.82c0,0-0.268-2.004-0.936-2.004S9.214,2.034,8.346,2.034C7.479,2.034,7.143,0,6.409,0C5.675,0,1.672,0.001,0.805,0.001c-0.868,0-0.801,0.867-0.801,0.867s0,11.513,0,11.779S4.141,4.039,4.141,4.039z M5.28,5L0.07,16.009l19.756,0.033L23.996,5H5.28z"; + -fx-scale-shape: false; + -fx-background-color: #515151; +} + + +/*!* #3 *!*/ +/*.titled-pane > .title > MaterialDesignIconView {*/ +/* -glyph-size: 24;*/ + +/*}*/ + +/*!* #3 *!*/ +/*.titled-pane > .title > {*/ +/* -fx-alignment: center_left;*/ +/* -fx-padding: 10 10 10 0;*/ +/* -fx-background-color: rgba(0, 0, 0, 0);*/ +/* -fx-border-color: #445566;*/ +/* -fx-border-width: 0 0 1 0;*/ +/*}*/ + +/*!* #3 *!*/ +/*.titled-pane:hover .title {*/ +/* -fx-background-color: #5264AE;*/ +/*}*/ + +/*!* #3 *!*/ +/*.titled-pane:hover {*/ +/* -fx-text-fill: #ffffff;*/ +/*}*/ + +/*.titled-pane:hover MaterialDesignIconView {*/ +/* -fx-fill: #ffffff;*/ +/*}*/ + +/*!* #3 *!*/ +/*.titled-pane > .title > .arrow-button > .arrow {*/ +/* -fx-shape: "M472.064 751.552 72.832 352.32c-22.08-22.08-22.08-57.792 0-79.872 22.016-22.016 57.792-22.08 79.872 0L512 631.744l359.296-359.296c22.016-22.016 57.792-22.08 79.872 0 22.08 22.08 22.016 57.792 0 79.872l-399.232 399.232C529.856 773.568 494.144 773.568 472.064 751.552z";*/ +/* -fx-background-color: rgba(0, 0, 0, 0.8);*/ +/* -fx-translate-x: 220;*/ +/*}*/ + +/*.titled-pane-menu > .title > .arrow-button > .arrow {*/ +/* -fx-shape: " ";*/ +/* !*-fx-padding: 0;*!*/ +/* !*-fx-translate-x: 220;*!*/ +/*}*/ + +/*!* #3 *!*/ +/*.titled-pane:hover > .title > .arrow-button > .arrow {*/ +/* -fx-background-color: #ffffff;*/ +/*}*/ + + +/*.accordion .titled-pane > *.content {*/ +/* -fx-background-color: rgba(0, 0, 0, 0);*/ +/* -fx-border-width: 0 0 0 0;*/ +/*}*/ + +.jfx-drawer > .jfx-drawer-side-pane { + -fx-background-color: rgba(0, 0, 0, 0); +} + +.title-label { + -fx-font-size: 16.0px; + -fx-padding: 14.0px; + -fx-text-fill: rgba(0.0, 0.0, 0.0, 0.87); +} + +/******************************************************************************* +* * +* JFX Spinner * +* * +*******************************************************************************/ + +.jfx-spinner .arc { + -fx-stroke-width: 3.0; +} + +.first-spinner { + -jfx-radius: 20; +} + +.first-spinner .arc { + -fx-stroke-width: 5.0; +} + +.second-spinner { + -jfx-radius: 30; +} + +.second-spinner .arc { + -fx-stroke-width: 5.0; +} + +.third-spinner { + -jfx-radius: 40; +} + +.third-spinner .arc { + -fx-stroke-width: 5.0; +} + +.fourth-spinner { + -jfx-radius: 50; +} + +.fourth-spinner .arc { + -fx-stroke-width: 5.0; +} + +.fifth-spinner { + -jfx-radius: 60; +} + +.fifth-spinner .arc { + -fx-stroke-width: 5.0; +} + +.sixth-spinner { + -jfx-radius: 70; +} + +.sixth-spinner .arc { + -fx-stroke-width: 5.0; +} + +.seventh-spinner { + -jfx-radius: 80; +} + +.seventh-spinner .arc { + -fx-stroke-width: 5.0; +} + +.blue-spinner .arc { + -fx-stroke: #4285f4; +} + +.blue-spinner .track { + -fx-stroke: #d0d0d0; +} + +.red-spinner .arc { + -fx-stroke: #db4437; +} + +.green-spinner .arc { + -fx-stroke: #0F9D58; +} + +.yellow-spinner .arc { + -fx-stroke: #f4b400; +} + +.materialDesign-purple:indeterminate .arc { + -fx-stroke: #ab47bc; +} + +.materialDesign-blue .arc { + -fx-stroke: #2962ff; +} + +.materialDesign-blue .percentage { + -fx-fill: #ab47bc; +} + +.materialDesign-cyan .arc { + -fx-stroke: #00b8d4; +} + +.materialDesign-green .arc { + -fx-stroke: #00c853; +} + +.materialDesign-green .text { + visibility: false; +} + +.materialDesign-yellow .arc { + -fx-stroke: #ffd600; +} + +.materialDesign-orange .arc { + -fx-stroke: #ff6d00; +} + +.materialDesign-red .arc { + -fx-stroke: #d50000; +} + + +/******************************************************************************* +* * +* JFX Textfield * +* * +*******************************************************************************/ + +.jfx-text-field, .jfx-password-field, .jfx-text-area, .jfx-combo-box { + -fx-background-color: transparent; + -fx-font-weight: bold; + -fx-prompt-text-fill: #808080; + -fx-alignment: top-left; + -jfx-focus-color: #4059A9; + -jfx-unfocus-color: #4d4d4d; +} + +/******************************************************************************* + * * + * JFX Dialog Layout * + * * + ******************************************************************************/ + +.jfx-dialog-overlay-pane { + -fx-background-color: rgba(0.0, 0.0, 0.0, 0.1); +} + +.dialog-trigger { + -fx-background-color: WHITE; + -jfx-button-type: RAISED; + -fx-font-size: 14.0px; +} + +.jfx-layout-heading .label { + -fx-font-size: 20.0px; +} + +.dialog-accept { + -fx-text-fill: #03A9F4; + -fx-font-weight: BOLD; + -fx-padding: 0.7em 0.8em; +} + + +/******************************************************************************* +* * +* Pickers * +* * +*******************************************************************************/ + +.custom-color-picker { + -jfx-default-color: #3f51b5; +} + +.jfx-date-picker > .jfx-text-field, +.jfx-time-picker > .jfx-text-field { + -jfx-focus-color: -jfx-default-color; +} + +.jfx-chip-view { + -fx-background-color: WHITE; + -fx-padding: 16; +} + +.jfx-chip-view .chips-pane > .text-area { + -fx-padding: 8 0 8 0; +} + +.jfx-chip-view .chips-pane .jfx-chip .chip-icon { + -jfx-size: 20; + -fx-background-color: #3f51b5; +} + +.jfx-chip-view .chips-pane .jfx-chip .heart { + -jfx-size: 20; + -fx-background-color: #D34336; +} + +.jfx-chips-popup { + -jfx-cell-limit: 3; +} + +.jfx-chips-popup .autocomplete-list { + -fx-fixed-cell-size: 32; + -fx-background-insets: 0.0; + -fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.26), 5, 0.06, -1, 2); +} + +.jfx-chips-popup .autocomplete-list .jfx-list-cell { + -fx-text-fill: rgba(0, 0, 0, .87); +} + +#menu-icon { + -jfx-size: 20; + -fx-background-color: #3f51b5; +} + +/******************************************************************************* +* * +* JFX List View * +* * +*******************************************************************************/ + +.jfx-list-cell { + -fx-alignment: center-left; + -fx-background-insets: 0.0; + -fx-text-fill: BLACK; + -fx-border-color: #e0e0e0; + -fx-border-width: 0 0 0 0; + +} + +.jfx-list-cell:hover { + -fx-background-color: derive(#5264AE, 20%); +} + +.jfx-list-cell:focused { + -fx-background-color: transparent; +} + +.jfx-list-cell > .jfx-svg-glyph, .sublist-label > .jfx-svg-glyph { + -jfx-size: 20; + -fx-alignment: center; +} + +.jfx-list-cell:odd, +.jfx-list-cell:even { + -fx-background-color: WHITE; +} + +.jfx-list-cell:filled:hover, +.jfx-list-cell:selected .label { + -fx-text-fill: black; +} + +.jfx-list-cell .jfx-rippler { + -jfx-rippler-fill: #5264AE; +} + +.jfx-list-cell:odd:selected > .jfx-rippler > StackPane, +.jfx-list-cell:even:selected > .jfx-rippler > StackPane { + -fx-background-color: rgba(0.0, 0.0, 255, 0.2); +} + +.jfx-list-view { + -fx-background-insets: 0.0; + -jfx-cell-horizontal-margin: 0.0; + -jfx-cell-vertical-margin: 5.0; + -jfx-vertical-gap: 10.0; + -jfx-expanded: false; +} + +/*******************************************************************************/ +/*******************************************************************************/ +/*******************************************************************************/ +/*******************************************************************************/ +/*******************************************************************************/ +/*******************************************************************************/ +/******************************************************************************* +* * +* JFX SUBLIST IMPORTANT * +* * +*******************************************************************************/ +.sublist .scroll-bar:vertical .increment-arrow, +.sublist .scroll-bar:vertical .decrement-arrow, +.sublist .scroll-bar:vertical .increment-button, +.sublist .scroll-bar:vertical .decrement-button { + -fx-padding: 0; +} + +.sublist .scroll-bar:vertical .track, +.sublist .scroll-bar:vertical .thumb { + -fx-background-color: WHITE; +} + +.sublist { + + /* important to hide the list change of height */ + -fx-background-color: TRANSPARENT; +} + +.sublist .jfx-list-cell:odd:selected > .jfx-rippler > StackPane, +.sublist .jfx-list-cell:even:selected > .jfx-rippler > StackPane { + -fx-background-color: rgba(0, 0, 255, 0.2); +} + +.sublist .jfx-list-cell { + -fx-background-insets: 0.0; + -fx-padding: 10 0 5 35; + -fx-text-fill: BLACK; + -fx-border-color: #e0e0e0; + -fx-border-width: 1 0 0 0; +} + +.sublist-header { + -fx-alignment: center-left; + -fx-padding: 0 0 0 13; +} + +.sublist-header .sub-label { + -fx-padding: 0 0 0 0; +} + +.user-info-listview { + -fx-background-color: TRANSPARENT; + +} + + + + + + + + + + + + diff --git a/client/src/main/resources/css/login.css b/client/src/main/resources/css/login.css new file mode 100644 index 0000000..e69de29 diff --git a/client/src/main/resources/css/test.css b/client/src/main/resources/css/test.css new file mode 100644 index 0000000..4c5de9b --- /dev/null +++ b/client/src/main/resources/css/test.css @@ -0,0 +1,3427 @@ +/* + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +/* + * Modena + * + * This is the second generation theme for JavaFX after Caspian. + */ + +/******************************************************************************* + * * + * THEMING INSTRUCTIONS * + * * + ******************************************************************************* + +TODO: Explain here how theming works: + + * -fx-text-base-color for text on top of -fx-base, -fx-color, and -fx-body-color + * -fx-text-background-color for text on top of -fx-background + * -fx-text-inner-color for text on top of -fx-control-inner-color + * -fx-selection-bar-text for text on top of -fx-selection-bar + +RESIZING FOR DIFFERENT SCREEN DPI +------------------------------- + +When the screen DPI changes Windows will use a different font size by default. +The default is 12px and can change to 15px or 18px depending on user +preference or screen DPI. On Mac the default is 13px and embedded will depend +on hardware. To make UI controls scale and be the right proportions for each of +these font sizes we base the padding (which controls size of control) on the +font size. This is done using the CSS measurement unit of a "em" where +(1em = font size). The default sizes are based on Windows default of 12px, as +a quick reference here are common px sizes in em units on windows. + +Windows 12px -> em units -> Mac 13px | +---------------------------------------- + 1px -> 0.083333em -> 1.08px ~ 2px + 2px -> 0.166667em -> 2.16px ~ 3px + 3px = 0.25em + 4px = 0.333333em + 5px = 0.416667em + 6px = 0.5em + 7px = 0.583333em + 8px = 0.666667em + 9px = 0.75em + 10px = 0.833333em + 11px = 0.916667em + 12px = 1em + +IMPORTANT: Not all sizes are scaled with em units only padding. All borders and +background insets are still in pixels. Also any padding where it has to match up +is being used to size a border should also be in pixels. + + ******************************************************************************/ + +/******************************************************************************* + * * + * CSS Styles for core infrastructure bits. The .root section provides the * + * overall default colors used by the rest of the sections. * + * * + ******************************************************************************/ + +.root { + /*************************************************************************** + * * + * The main color palette from which the rest of the colors are derived. * + * * + **************************************************************************/ + + /* A light grey that is the base color for objects. Instead of using + * -fx-base directly, the sections in this file will typically use -fx-color. + */ + -fx-base: #fafafa; + + /* A very light grey used for the background of windows. See also + * -fx-text-background-color, which should be used as the -fx-text-fill + * value for text painted on top of backgrounds colored with -fx-background. + */ + -fx-background: derive(-fx-base,26.4%); + + /* Used for the inside of text boxes, password boxes, lists, trees, and + * tables. See also -fx-text-inner-color, which should be used as the + * -fx-text-fill value for text painted on top of backgrounds colored + * with -fx-control-inner-background. + */ + -fx-control-inner-background: derive(-fx-base,80%); + /* Version of -fx-control-inner-background for alternative rows */ + -fx-control-inner-background-alt: derive(-fx-control-inner-background,-2%); + + /* One of these colors will be chosen based upon a ladder calculation + * that uses the brightness of a background color. Instead of using these + * colors directly as -fx-text-fill values, the sections in this file should + * use a derived color to match the background in use. See also: + * + * -fx-text-base-color for text on top of -fx-base, -fx-color, and -fx-body-color + * -fx-text-background-color for text on top of -fx-background + * -fx-text-inner-color for text on top of -fx-control-inner-color + * -fx-selection-bar-text for text on top of -fx-selection-bar + */ + -fx-dark-text-color: black; + -fx-mid-text-color: #333; + -fx-light-text-color: #ffffff; + + /* A bright blue for highlighting/accenting objects. For example: selected + * text; selected items in menus, lists, trees, and tables; progress bars */ + -fx-accent: #0096C9; + + /* Default buttons color, this is similar to accent but more subtle */ + -fx-default-button: #abd8ed; + + /* A bright blue for the focus indicator of objects. Typically used as the + * first color in -fx-background-color for the "focused" pseudo-class. Also + * typically used with insets of -1.4 to provide a glowing effect. + */ + -fx-focus-color: #039ed3; + -fx-faint-focus-color: #039ED322; + + /* The color that is used in styling controls. The default value is based + * on -fx-base, but is changed by pseudoclasses to change the base color. + * For example, the "hover" pseudoclass will typically set -fx-color to + * -fx-hover-base (see below) and the "armed" pseudoclass will typically + * set -fx-color to -fx-pressed-base. + */ + -fx-color: -fx-base; + + /* Chart Color Palette */ + CHART_COLOR_1: #f3622d; + CHART_COLOR_2: #fba71b; + CHART_COLOR_3: #57b757; + CHART_COLOR_4: #41a9c9; + CHART_COLOR_5: #4258c9; + CHART_COLOR_6: #9a42c8; + CHART_COLOR_7: #c84164; + CHART_COLOR_8: #888888; + /* Chart Color Palette Semi-Transparent + * These are used by charts that need semi transparent versions of the above colors, such as BubbleChart. They + * are exactly the same colors as above just with alpha + * + * 20% opacity + */ + CHART_COLOR_1_TRANS_20: #f3622d33; + CHART_COLOR_2_TRANS_20: #fba71b33; + CHART_COLOR_3_TRANS_20: #57b75733; + CHART_COLOR_4_TRANS_20: #41a9c933; + CHART_COLOR_5_TRANS_20: #4258c933; + CHART_COLOR_6_TRANS_20: #9a42c833; + CHART_COLOR_7_TRANS_20: #c8416433; + CHART_COLOR_8_TRANS_20: #88888833; + /* 70% opacity */ + CHART_COLOR_1_TRANS_70: #f3622db3; + CHART_COLOR_2_TRANS_70: #fba71bb3; + CHART_COLOR_3_TRANS_70: #57b757b3; + CHART_COLOR_4_TRANS_70: #41a9c9b3; + CHART_COLOR_5_TRANS_70: #4258c9b3; + CHART_COLOR_6_TRANS_70: #9a42c8b3; + CHART_COLOR_7_TRANS_70: #c84164b3; + CHART_COLOR_8_TRANS_70: #888888b3; + + /*************************************************************************** + * * + * Colors that are derived from the main color palette. * + * * + **************************************************************************/ + + /* A little lighter than -fx-base and used as the -fx-color for the + * "hovered" pseudoclass state. + */ + -fx-hover-base: ladder( + -fx-base, + derive(-fx-base,20%) 20%, + derive(-fx-base,30%) 35%, + derive(-fx-base,40%) 50% + ); + + /* A little darker than -fx-base and used as the -fx-color for the + * "armed" pseudoclass state. + * + * TODO: should this be renamed to -fx-armed-base? + */ + -fx-pressed-base: derive(-fx-base,-6%); + + /* The color to use for -fx-text-fill when text is to be painted on top of + * a background filled with the -fx-background color. + */ + -fx-text-background-color: ladder( + -fx-background, + -fx-light-text-color 45%, + -fx-dark-text-color 46%, + -fx-dark-text-color 59%, + -fx-mid-text-color 60% + ); + + /* A little darker than -fx-color and used to draw boxes around objects such + * as progress bars, scroll bars, scroll panes, trees, tables, and lists. + */ + -fx-box-border: ladder( + -fx-color, + black 20%, + derive(-fx-color,-15%) 30% + ); + + /* Darker than -fx-background and used to draw boxes around text boxes and + * password boxes. + */ + -fx-text-box-border: ladder( + -fx-background, + black 10%, + derive(-fx-background, -15%) 30% + ); + + /* Lighter than -fx-background and used to provide a small highlight when + * needed on top of -fx-background. This is never a shadow in Modena but + * keep -fx-shadow-highlight-color name to be compatible with Caspian. + */ + -fx-shadow-highlight-color: ladder( + -fx-background, + rgba(255,255,255,0.07) 0%, + rgba(255,255,255,0.07) 20%, + rgba(255,255,255,0.07) 70%, + rgba(255,255,255,0.7) 90%, + rgba(255,255,255,0.75) 100% + ); + + /* A gradient that goes from a little darker than -fx-color on the top to + * even more darker than -fx-color on the bottom. Typically is the second + * color in the -fx-background-color list as the small thin border around + * a control. It is typically the same size as the control (i.e., insets + * are 0). + */ + -fx-outer-border: derive(-fx-color,-23%); + + /* A gradient that goes from a bit lighter than -fx-color on the top to + * a little darker at the bottom. Typically is the third color in the + * -fx-background-color list as a thin highlight inside the outer border. + * Insets are typically 1. + */ + -fx-inner-border: linear-gradient(to bottom, + ladder( + -fx-color, + derive(-fx-color,30%) 0%, + derive(-fx-color,20%) 40%, + derive(-fx-color,25%) 60%, + derive(-fx-color,55%) 80%, + derive(-fx-color,55%) 90%, + derive(-fx-color,75%) 100% + ), + ladder( + -fx-color, + derive(-fx-color,20%) 0%, + derive(-fx-color,10%) 20%, + derive(-fx-color,5%) 40%, + derive(-fx-color,-2%) 60%, + derive(-fx-color,-5%) 100% + )); + -fx-inner-border-horizontal: linear-gradient(to right, derive(-fx-color,55%), derive(-fx-color,-5%)); + -fx-inner-border-bottomup: linear-gradient(to top, derive(-fx-color,55%), derive(-fx-color,-5%)); + + /* A gradient that goes from a little lighter than -fx-color at the top to + * a little darker than -fx-color at the bottom and is used to fill the + * body of many controls such as buttons. + */ + -fx-body-color: linear-gradient(to bottom, + ladder( + -fx-color, + derive(-fx-color,8%) 75%, + derive(-fx-color,10%) 80% + ), + derive(-fx-color,-8%)); + -fx-body-color-bottomup: linear-gradient(to top, derive(-fx-color,10%) ,derive(-fx-color,-6%)); + -fx-body-color-to-right: linear-gradient(to right, derive(-fx-color,10%) ,derive(-fx-color,-6%)); + + /* The color to use as -fx-text-fill when painting text on top of + * backgrounds filled with -fx-base, -fx-color, and -fx-body-color. + */ + -fx-text-base-color: ladder( + -fx-color, + -fx-light-text-color 45%, + -fx-dark-text-color 46%, + -fx-dark-text-color 59%, + -fx-mid-text-color 60% + ); + + /* The color to use as -fx-text-fill when painting text on top of + * backgrounds filled with -fx-control-inner-background. + */ + -fx-text-inner-color: ladder( + -fx-control-inner-background, + -fx-light-text-color 45%, + -fx-dark-text-color 46%, + -fx-dark-text-color 59%, + -fx-mid-text-color 60% + ); + + /* The color to use for small mark-like objects such as checks on check + * boxes, filled in circles in radio buttons, arrows on scroll bars, etc. + */ + -fx-mark-color: ladder( + -fx-color, + white 30%, + derive(-fx-color,-63%) 31% + ); + + /* The small thin light "shadow" for mark-like objects. Typically used in + * conjunction with -fx-mark-color with an insets of 1 0 -1 0. */ + -fx-mark-highlight-color: ladder( + -fx-color, + derive(-fx-color,80%) 60%, + white 70% + ); + + /* Background for items in list like things such as menus, lists, trees, + * and tables. */ + -fx-selection-bar: -fx-accent; + + /* Background color to use for selection of list cells etc. This is when + * the control doesn't have focus or the row of a previously selected item. */ + -fx-selection-bar-non-focused: lightgrey; + + /* The color to use as -fx-text-fill when painting text on top of + * backgrounds filled with -fx-selection-bar. + * + * TODO: this can be removed + */ + -fx-selection-bar-text: -fx-text-background-color; + + /* These are needed for Popup */ + -fx-background-color: inherit; + -fx-background-radius: inherit; + -fx-background-insets: inherit; + -fx-padding: inherit; + + /* The color to use in ListView/TreeView/TableView to indicate hover. */ + -fx-cell-hover-color: #cce3f4; + + /** Focus line for keyboard focus traversal on cell based controls */ + -fx-cell-focus-inner-border: derive(-fx-selection-bar,30%); + + /* The colors to use in Pagination */ + -fx-page-bullet-border: #acacac; + -fx-page-indicator-hover-border: #accee5; + + -fx-focused-text-base-color : ladder( + -fx-selection-bar, + -fx-light-text-color 45%, + -fx-dark-text-color 46%, + -fx-dark-text-color 59%, + -fx-mid-text-color 60% + ); + -fx-focused-mark-color : -fx-focused-text-base-color ; + + /*************************************************************************** + * * + * Set the default background color for the scene * + * * + **************************************************************************/ + + -fx-background-color: -fx-background; +} + +/* Make popups transparent */ +.root.popup { + -fx-background-color: transparent; +} + +/******************************************************************************* + * * + * Common Styles * + * * + * These are styles that give a standard look to a whole range of controls * + * * + ******************************************************************************/ + +/* ==== TEXT NODES IN CONTROLS ========================================== */ + +.text { + /* This adjusts text alignment within the bounds of text nodes so that + the text is always vertically centered within the bounds. Based on + the cap height of the text. */ + -fx-bounds-type: logical_vertical_center; + /* Enable LCD text rendering */ + -fx-font-smoothing-type: lcd; +} + +/* ==== BUTTON LIKE THINGS ============================================== */ + +.button, +.toggle-button, +.radio-button > .radio, +.check-box > .box, +.menu-button, +.choice-box, +.color-picker.split-button > .color-picker-label, +.combo-box-base, +.combo-box-base:editable > .arrow-button { + -fx-background-color: -fx-shadow-highlight-color, -fx-outer-border, -fx-inner-border, -fx-body-color; + -fx-background-insets: 0 0 -1 0, 0, 1, 2; + -fx-background-radius: 3px, 3px, 2px, 1px; + -fx-padding: 0.333333em 0.666667em 0.333333em 0.666667em; /* 4 8 4 8 */ + -fx-text-fill: -fx-text-base-color; + -fx-alignment: CENTER; + -fx-content-display: LEFT; +} +.menu-button > .label { + -fx-alignment: CENTER_LEFT; +} +.button:hover, +.toggle-button:hover, +.radio-button:hover > .radio, +.check-box:hover > .box, +.menu-button:hover, +.split-menu-button > .label:hover, +.split-menu-button > .arrow-button:hover, +.slider .thumb:hover, +.scroll-bar > .thumb:hover, +.scroll-bar > .increment-button:hover, +.scroll-bar > .decrement-button:hover, +.choice-box:hover, +.color-picker.split-button > .arrow-button:hover, +.color-picker.split-button > .color-picker-label:hover, +.combo-box-base:hover, +.combo-box-base:editable > .arrow-button:hover, +.spinner .increment-arrow-button:hover, +.spinner .decrement-arrow-button:hover, +.tab-pane > .tab-header-area > .control-buttons-tab > .container > .tab-down-button:hover { + -fx-color: -fx-hover-base; +} +.button:armed, +.toggle-button:armed, +.radio-button:armed > .radio, +.check-box:armed .box, +.menu-button:armed, +.split-menu-button:armed > .label, +.split-menu-button > .arrow-button:pressed, +.split-menu-button:showing > .arrow-button, +.slider .thumb:pressed, +.scroll-bar > .thumb:pressed, +.scroll-bar > .increment-button:pressed, +.scroll-bar > .decrement-button:pressed, +.choice-box:showing, +.combo-box-base:showing, +.combo-box-base:editable:showing > .arrow-button, +.spinner .increment-arrow-button:pressed, +.spinner .decrement-arrow-button:pressed, +.tab-pane > .tab-header-area > .control-buttons-tab > .container > .tab-down-button:pressed { + -fx-color: -fx-pressed-base; +} +.button:focused, +.toggle-button:focused, +.radio-button:focused > .radio, +.check-box:focused > .box, +.menu-button:focused, +.choice-box:focused, +.color-picker.split-button:focused > .color-picker-label, +.combo-box-base:focused, +.slider:focused .thumb { + -fx-background-color: -fx-focus-color, -fx-inner-border, -fx-body-color, -fx-faint-focus-color, -fx-body-color; + -fx-background-insets: -0.2, 1, 2, -1.4, 2.6; + -fx-background-radius: 3, 2, 1, 4, 1; +} + +/* ==== DISABLED THINGS ================================================= */ + +.label:disabled, +.button:disabled, +.toggle-button:disabled, +.radio-button:disabled, +.check-box:disabled, +.hyperlink:disabled, +.menu-button:disabled, +.split-menu-button:disabled, +.slider:disabled, +.scroll-bar:disabled, +.scroll-pane:disabled, +.progress-bar:disabled, +.progress-indicator:disabled, +.text-input:disabled, +.choice-box:disabled, +.combo-box-base:disabled, +.date-cell:disabled > *, /* This is set on children so border is not affected. */ +.list-view:disabled, +.tree-view:disabled, +.table-view:disabled, +.tree-table-view:disabled, +.tab-pane:disabled, +.titled-pane:disabled > .title, +.accordion:disabled > .titled-pane > .title, +.tab-pane > .tab-header-area > .headers-region > .tab:disabled, +.menu:disabled, +.menu-item:disabled > .label, +.menu-item:disabled, +.list-cell:filled:selected:focused:disabled, +.list-cell:filled:selected:disabled, +.tree-cell:filled:selected:focused:disabled, +.tree-cell:filled:selected:disabled, +.tree-cell > .tree-disclosure-node:disabled, +.tree-table-row-cell > .tree-disclosure-node:disabled, +.table-row-cell:selected:disabled, +.tree-table-row-cell:selected:disabled, +.table-cell:selected:disabled, +.tree-table-cell:selected:disabled, +.spinner:disabled { + -fx-opacity: 0.4; +} + +/* ==== MNEMONIC THINGS ================================================= */ + +.mnemonic-underline { + -fx-stroke: transparent; +} + +.titled-pane:show-mnemonics > .mnemonic-underline, +.label:show-mnemonics > .mnemonic-underline, +.context-menu:show-mnemonics > .mnemonic-underline, +.menu:show-mnemonics > .mnemonic-underline, +.menu-bar:show-mnemonics > .mnemonic-underline, +.menu-item:show-mnemonics > .mnemonic-underline, +.button:show-mnemonics > .mnemonic-underline, +.toggle-button:show-mnemonics > .mnemonic-underline, +.radio-button:show-mnemonics > .mnemonic-underline, +.check-box:show-mnemonics > .mnemonic-underline, +.hyperlink:show-mnemonics > .mnemonic-underline, +.split-menu-button:show-mnemonics > .mnemonic-underline, +.menu-button:show-mnemonics > .mnemonic-underline { + -fx-stroke: -fx-text-base-color; +} + +/* ==== MARKS =========================================================== */ + +.radio-button:selected > .radio > .dot, +.check-box:selected > .box > .mark, +.check-box:indeterminate > .box > .mark { + -fx-background-color: -fx-mark-highlight-color, -fx-mark-color; + -fx-background-insets: 1 0 -1 0, 0; +} + +/* ==== ARROWS ========================================================== */ + +.menu-button > .arrow-button > .arrow, +.split-menu-button > .arrow-button > .arrow { + -fx-background-color: -fx-mark-highlight-color, -fx-mark-color; + -fx-background-insets: 0 0 -1 0, 0; + -fx-padding: 0.25em; + -fx-shape: "M 0 -3.5 v 7 l 4 -3.5 z"; +} +.choice-box > .open-button > .arrow, +.menu-button:openvertically > .arrow-button > .arrow, +.split-menu-button:openvertically > .arrow-button > .arrow, +.combo-box-base > .arrow-button > .arrow, +.web-view .form-select-button .arrow, +.tab-pane > .tab-header-area > .control-buttons-tab > .container > .tab-down-button > .arrow { + -fx-background-color: -fx-mark-highlight-color, -fx-mark-color; + -fx-background-insets: 0 0 -1 0, 0; + -fx-padding: 0.166667em 0.333333em 0.166667em 0.333333em; /* 2 4 2 4 */ + -fx-shape: "M 0 0 h 7 l -3.5 4 z"; +} + +/* ==== CHOICE BOX LIKE THINGS ========================================== */ + +.choice-box, +.menu-button, +.combo-box-base { + -fx-padding: 0; +} +.choice-box > .label, +.menu-button > .label, +.color-picker > .label { + -fx-padding: 0.333333em 0.666667em 0.333333em 0.666667em; /* 4 8 4 8 */ + -fx-text-fill: -fx-text-base-color; +} +.choice-box > .open-button, +.menu-button > .arrow-button { + -fx-padding: 0.5em 0.667em 0.5em 0.0em; /* 6 8 6 0 */ +} + +/* ==== BOX LIKE THINGS ================================================= */ + +.scroll-pane, +.split-pane, +.list-view, +.tree-view, +.table-view, +.tree-table-view, +.html-editor { + -fx-background-color: -fx-box-border, -fx-control-inner-background; + -fx-background-insets: 0, 1; + -fx-padding: 1; +} +.scroll-pane:focused, +.split-pane:focused, +.list-view:focused, +.tree-view:focused, +.table-view:focused, +.tree-table-view:focused, +.html-editor:contains-focus { + -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-control-inner-background; + -fx-background-insets: -1.4, -0.3, 1; + -fx-background-radius: 2, 0, 0; +} +/* ones with grey -fx-background not lighter -fx-control-inner-background */ +.scroll-pane, +.split-pane { + -fx-background-color: -fx-box-border, -fx-background; +} +.scroll-pane:focused, +.split-pane:focused { + -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-background; +} + +/******************************************************************************* + * * + * Label * + * * + ******************************************************************************/ + +.label { + -fx-text-fill: -fx-text-background-color; +} + +/******************************************************************************* + * * + * Button & ToggleButton * + * * + ******************************************************************************/ + +/* ==== DEFAULT ========================================================= */ + +.button:default { + -fx-base: -fx-default-button; +} + +/* ==== WEB BUTTONS ===================================================== */ + +.web-view .form-select-button { + -fx-background-radius: 2, 2, 1, 0; + -fx-background-insets: 2 2 1 2, 2, 3, 4; +} + +/* ==== PILL BUTTONS ==================================================== */ + +.button.left-pill, +.toggle-button.left-pill { + -fx-background-radius: 3 0 0 3, 3 0 0 3, 2 0 0 2, 1 0 0 1; + -fx-background-insets: 0 0 -1 0, 0, 1, 2; + -fx-padding: 0.333333em 0.666667em 0.333333em 0.75em; /* 4 8 4 9 */ +} +.button.center-pill, +.toggle-button.center-pill { + -fx-background-radius: 0; + -fx-background-insets: 0 0 -1 0, 0 0 0 0, 1 1 1 0, 2 2 2 1 ; +} +.button.right-pill, +.toggle-button.right-pill { + -fx-background-radius: 0 3 3 0, 0 3 3 0, 0 2 2 0, 0 1 1 0; + -fx-background-insets: 0 0 -1 0, 0, 1 1 1 0, 2 2 2 1 ; +} +.button.left-pill:focused, +.toggle-button.left-pill:focused { + -fx-background-insets: -0.2 0 -0.2 -0.2, 1, 2, -1.4 0 -1.4 -1.4, 2.6; + -fx-background-radius: 3 0 0 3, 2 0 0 2, 1 0 0 1, 4 0 0 4, 1 0 0 1; +} +.button.center-pill:focused, +.toggle-button.center-pill:focused { + -fx-background-insets: -0.2 0 -0.2 -1, 1 1 1 0, 2 2 2 1, -1.4 0 -1.4 -1, 2.6 2.6 2.6 1.6; + -fx-background-radius: 0, 0, 0, 0, 0; +} +.button.right-pill:focused, +.toggle-button.right-pill:focused { + -fx-background-insets: -0.2 -0.2 -0.2 -1, 1 1 1 0, 2 2 2 1, -1.4 -1.4 -1.4 -1, 2.6 2.6 2.6 1.6; + -fx-background-radius: 0 3 3 0, 0 2 2 0, 0 1 1 0, 0 4 4 0, 0 1 1 0; +} +.toggle-button:selected.left-pill:focused { + -fx-background-insets: -0.2 0 -0.2 -0.2, 1, -1.4 0 -1.4 -1.4, 2.6; + -fx-background-radius: 3 0 0 3, 2 0 0 2, 4 0 0 4, 0; +} +.toggle-button:selected.center-pill:focused { + -fx-background-insets: -0.2 0 -0.2 -1, 1 1 1 0, -1.4 0 -1.4 -1, 2.6 2.6 2.6 1.6; + -fx-background-radius: 0, 0, 0, 0; +} +.toggle-button:selected.right-pill:focused { + -fx-background-insets: -0.2 -0.2 -0.2 -1, 1 1 1 0, -1.4 -1.4 -1.4 -1, 2.6 2.6 2.6 1.6; + -fx-background-radius: 0 3 3 0, 0 2 2 0, 0 4 4 0, 0; +} + +/* ==== SELECTED TOGGLE ================================================= */ + +.toggle-button:selected { + -fx-background-color: + -fx-shadow-highlight-color, + linear-gradient(to bottom, derive(-fx-outer-border, -20%), -fx-outer-border), + linear-gradient(to bottom, + derive(-fx-color, -22%) 0%, + derive(-fx-color, -13%) 20%, + derive(-fx-color, -11%) 50%); + -fx-background-insets: 0 0 -1 0, 0, 1; +} +.toggle-button:selected:focused { + -fx-background-color: + -fx-focus-color, + linear-gradient(to bottom, + derive(-fx-color, -22%) 0%, + derive(-fx-color, -13%) 20%, + derive(-fx-color, -11%) 50%), + -fx-faint-focus-color, + linear-gradient(to bottom, + derive(-fx-color, -22%) 0%, + derive(-fx-color, -13%) 20%, + derive(-fx-color, -11%) 50%); + -fx-background-insets: -0.2, 1, -1.4, 2.6; + -fx-background-radius: 3, 2, 4, 0; +} + +/******************************************************************************* + * * + * RadioButton * + * * + ******************************************************************************/ + +.radio-button { + -fx-label-padding: 0.0em 0.0em 0.0em 0.416667em; /* 0 0 0 5 */ + -fx-text-fill: -fx-text-background-color; +} +.radio-button > .radio, +.radio-button:focused > .radio { + -fx-background-radius: 1.0em; /* large value to make sure this remains circular */ + -fx-padding: 0.333333em; /* 4 -- padding from outside edge to the inner black dot */ +} +.radio-button > .radio > .dot { + -fx-background-color: transparent; + -fx-background-radius: 1.0em; /* large value to make sure this remains circular */ + -fx-padding: 0.333333em; /* 4 -- radius of the inner black dot when selected */ +} + +/******************************************************************************* + * * + * CheckBox * + * * + ******************************************************************************/ + +.check-box { + -fx-label-padding: 0.0em 0.0em 0.0em 0.416667em; /* 0 0 0 5 */ + -fx-text-fill: -fx-text-background-color; +} +.check-box > .box { + -fx-background-radius: 3, 2, 1; + -fx-padding: 0.166667em 0.166667em 0.25em 0.25em; /* 2 2 3 3 */ +} +.check-box > .box > .mark { + -fx-background-color: null; + -fx-padding: 0.416667em 0.416667em 0.5em 0.5em; /* 5 5 6 6 */ + -fx-shape: "M-0.25,6.083c0.843-0.758,4.583,4.833,5.75,4.833S14.5-1.5,15.917-0.917c1.292,0.532-8.75,17.083-10.5,17.083C3,16.167-1.083,6.833-0.25,6.083z"; +} +.check-box:indeterminate > .box { + -fx-padding: 0; +} +.check-box:indeterminate > .box > .mark { + -fx-shape: "M0,0H10V2H0Z"; + -fx-scale-shape: false; + -fx-padding: 0.666667em; /* 16x16 = 8+8 */ +} + +/******************************************************************************* + * * + * Hyperlink * + * * + ******************************************************************************/ + +.hyperlink { + -fx-padding: 0.166667em 0.25em 0.166667em 0.25em; /* 2 3 2 3 */ + -fx-cursor: hand; + -fx-content-display: LEFT; + -fx-border-color: transparent; + -fx-border-width: 1px; +} +.hyperlink, +.hyperlink:hover, +.hyperlink:hover:visited { + -fx-text-fill: -fx-accent; +} +.hyperlink:armed, +.hyperlink:visited, +.hyperlink:hover:armed { + -fx-text-fill: -fx-text-background-color; +} +.hyperlink:hover, +.hyperlink:visited, +.hyperlink:hover:visited { + -fx-underline: true; +} +.hyperlink:visited:armed { + -fx-underline: false; +} +.hyperlink:focused { + -fx-border-color: -fx-focus-color; + -fx-border-style: segments(0.166667em, 0.166667em); + -fx-border-width: 1px; +} +.hyperlink:show-mnemonics > .mnemonic-underline { + -fx-stroke: -fx-text-fill; +} + +/* Fix for RT-37971 */ +.cell:selected .hyperlink, +.cell:selected .hyperlink:hover, +.cell:selected .hyperlink:hover:visited { + -fx-text-fill: -fx-text-background-color; +} + +/******************************************************************************* + * * + * SplitMenuButton * + * * + ******************************************************************************/ + +.split-menu-button { + -fx-background-color: -fx-shadow-highlight-color, -fx-outer-border; + -fx-background-insets: 0 0 -1 0, 0; + -fx-background-radius: 3, 3; + -fx-padding: 0; +} +.split-menu-button > .label { + -fx-text-fill: -fx-text-base-color; + -fx-background-color: -fx-inner-border, -fx-body-color; + -fx-background-insets: 1 0 1 1, 2 1 2 2; + -fx-background-radius: 2 0 0 2, 1 0 0 1; + -fx-padding: 0.333333em 0.667em 0.333333em 0.667em; /* 4 8 4 8 */ +} +.split-menu-button > .arrow-button { + -fx-background-color: -fx-inner-border, -fx-body-color; + -fx-background-insets: 1, 2; + -fx-background-radius: 0 2 2 0, 0 1 1 0; + -fx-padding: 0.5em 0.667em 0.5em 0.667em; /* 6 8 6 8 */ +} +.split-menu-button:focused { + -fx-background-color: -fx-focus-color; + -fx-background-insets: -0.2; + -fx-background-radius: 3; +} +.split-menu-button:focused > .label { + -fx-background-color: -fx-inner-border, -fx-body-color, -fx-faint-focus-color, -fx-body-color; + -fx-background-insets: 1 0 1 1, 2 1 2 2, -1.4 0 -1.4 -1.4, 2.6 1.6 2.6 2.6; + -fx-background-radius: 2 0 0 2, 1 0 0 1, 4 0 0 4, 0; +} +.split-menu-button:focused > .arrow-button { + -fx-background-color: -fx-inner-border, -fx-body-color, -fx-faint-focus-color, -fx-body-color; + -fx-background-insets: 1, 2, -1.4, 2.6; + -fx-background-radius: 0 2 2 0, 0 1 1 0, 0 4 4 0, 0; +} + +/******************************************************************************* + * * + * ToolBar * + * * + ******************************************************************************/ + +.tool-bar:vertical { /* left */ + -fx-background-color: + -fx-outer-border, + linear-gradient(to right, derive(-fx-base,0%) 0%, derive(-fx-base,10%) 50%, derive(-fx-base,0%) 100%); + -fx-background-insets: 0, 0 0 0 1; + -fx-padding: 0.5em 0.416667em 0.5em 0.416667em; /* 6 5 6 5 */ + -fx-spacing: 0.333em; /* 4 */ + -fx-alignment: TOP_LEFT; +} +.tool-bar { /* top */ + TOP-COLOR: ladder( + -fx-base, + derive(-fx-base,0%) 0%, + derive(-fx-base,46%) 100% + ); + -fx-background-color: + linear-gradient(to bottom, derive(TOP-COLOR,25%) 0%, -fx-outer-border 90%), + linear-gradient(to bottom, TOP-COLOR 2%, derive(-fx-base,-2.1%) 95%); + -fx-background-insets: 0 0 0 0, 1 0 1 0; + -fx-padding: 0.416667em 0.5em 0.416667em 0.5em; /* 5 6 5 6 */ + -fx-spacing: 0.333em; /* 4 */ + -fx-alignment: CENTER_LEFT; +} +.tool-bar:vertical.right { + -fx-background-insets: 0, 0 1 0 0; +} +.tool-bar.bottom { + -fx-background-color: + -fx-outer-border, + derive(TOP-COLOR,25%), + linear-gradient(to bottom, TOP-COLOR 2%, derive(-fx-base,-2.1%) 95%); + -fx-background-insets: 0, 1 0 0 0, 2 0 0 0; +} +.tool-bar > .container > .separator { + -fx-orientation: vertical; +} +.tool-bar:vertical > .container > .separator { + -fx-orientation: horizontal; +} +.tool-bar-overflow-button { + -fx-padding: 0 0.75em 0 0 ; +} +.tool-bar:vertical > .tool-bar-overflow-button { + -fx-padding: 0 0 0.75em 0 ; +} +.tool-bar-overflow-button > .arrow { + -fx-background-color: -fx-mark-highlight-color, -fx-mark-color; + -fx-background-insets: 1 0 -1 0, 0; + -fx-padding: 0.666667em 0.916667em 0em 0em; /* 8 11 0 0 */ + -fx-shape: "M337.273,297.622l-0.016,1.069l2.724,2.639l-2.723,2.628l0.015,1.048h0.881l3.81-3.685l-3.788-3.699H337.273z M343.783,297.622h-0.902l-0.015,1.069l2.724,2.639l-2.724,2.628l0.015,1.048h0.882l3.809-3.685L343.783,297.622z" ; +} + +.tool-bar-overflow-button:focused > .arrow { + -fx-background-color: -fx-mark-highlight-color, derive(-fx-accent, -15%); + -fx-background-insets: 1 0 -1 0, 0; +} + +.tool-bar-overflow-button:hover > .arrow { + -fx-background-color: -fx-mark-highlight-color, derive(-fx-hover-base, -35%); + -fx-background-insets: 1 0 -1 0, 0; +} + +/******************************************************************************* + * * + * Slider * + * * + ******************************************************************************/ + +.slider .thumb { + -fx-background-color: + linear-gradient(to bottom, derive(-fx-text-box-border, -20%), derive(-fx-text-box-border, -30%)), + -fx-inner-border, + -fx-body-color; + -fx-background-insets: 0, 1, 2; + -fx-background-radius: 1.0em; /* makes sure this remains circular */ + -fx-padding: 0.583333em; /* 7 */ + -fx-effect: dropshadow(two-pass-box , rgba(0, 0, 0, 0.1), 5, 0.0 , 0, 2); +} +.slider:focused .thumb { + -fx-background-radius: 1.0em; /* makes sure this remains circular */ +} +.slider .track { + -fx-background-color: + -fx-shadow-highlight-color, + linear-gradient(to bottom, derive(-fx-text-box-border, -10%), -fx-text-box-border), + linear-gradient(to bottom, + derive(-fx-control-inner-background, -9%), + derive(-fx-control-inner-background, 0%), + derive(-fx-control-inner-background, -5%), + derive(-fx-control-inner-background, -12%) + ); + -fx-background-insets: 0 0 -1 0, 0, 1; + -fx-background-radius: 0.25em, 0.25em, 0.166667em; /* 3 3 2 */ + -fx-padding: 0.25em; /* 3 */ +} +.slider:vertical .track { + -fx-background-color: + -fx-shadow-highlight-color, + -fx-text-box-border, + linear-gradient(to right, + derive(-fx-control-inner-background, -9%), + -fx-control-inner-background, + derive(-fx-control-inner-background, -9%) + ); +} +.slider .axis { + -fx-tick-label-fill: derive(-fx-text-background-color, 30%); + -fx-tick-length: 5px; + -fx-minor-tick-length: 3px; + -fx-border-color: null; +} + +/******************************************************************************* + * * + * ScrollBar * + * * + ******************************************************************************/ + +.scroll-bar:horizontal { + -fx-background-color: derive(-fx-box-border,30%), linear-gradient(to bottom, derive(-fx-base,-3%), derive(-fx-base,5%) 50%, derive(-fx-base,-3%)); + -fx-background-insets: 0, 1 0 1 0; +} +.scroll-bar:vertical { + -fx-background-color: derive(-fx-box-border,30%), linear-gradient(to right, derive(-fx-base,-3%), derive(-fx-base,5%) 50%, derive(-fx-base,-3%)); + -fx-background-insets: 0, 0 1 0 1; +} +.scroll-bar:focused { + -fx-background-color: + -fx-focus-color, + linear-gradient(to bottom, derive(-fx-base,-3%), derive(-fx-base,5%) 50%, derive(-fx-base,-3%)), + -fx-faint-focus-color, + linear-gradient(to bottom, derive(-fx-base,-3%), derive(-fx-base,5%) 50%, derive(-fx-base,-3%)); + -fx-background-insets: -0.2, 1, -1.4, 2.6; +} +.scroll-bar:vertical:focused { + -fx-background-color: + -fx-focus-color, + linear-gradient(to right, derive(-fx-base,-3%), derive(-fx-base,5%) 50%, derive(-fx-base,-3%)), + -fx-faint-focus-color, + linear-gradient(to right, derive(-fx-base,-3%), derive(-fx-base,5%) 50%, derive(-fx-base,-3%)); +} +.scroll-bar > .thumb { + -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; + /*-fx-background-insets: 1, 2, 3;*/ + -fx-background-insets: 2, 3, 4; + /*-fx-background-radius: 0.416667em, 0.333333em, 0.25em; *//* 5, 4,3 */ + -fx-background-radius: 3, 2, 1; +} +.scroll-bar:vertical > .thumb { + -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color-to-right; +} +.scroll-bar > .increment-button, +.scroll-bar > .decrement-button { + -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; + -fx-color: transparent; + -fx-padding: 0.25em; /* 3px */ +} +.scroll-bar:horizontal > .increment-button, +.scroll-bar:horizontal > .decrement-button { + -fx-background-insets: 2 1 2 1, 3 2 3 2, 4 3 4 3; +} +.scroll-bar:vertical > .increment-button, +.scroll-bar:vertical > .decrement-button { + -fx-background-insets: 1 2 1 2, 2 3 2 3, 3 4 3 4; +} +.scroll-bar > .increment-button > .increment-arrow, +.scroll-bar > .decrement-button > .decrement-arrow { + -fx-background-color: -fx-mark-highlight-color,derive(-fx-base,-45%); +} +.scroll-bar > .increment-button:hover > .increment-arrow, +.scroll-bar > .decrement-button:hover > .decrement-arrow { + -fx-background-color: -fx-mark-highlight-color,derive(-fx-base,-50%); +} +.scroll-bar > .increment-button:pressed > .increment-arrow, +.scroll-bar > .decrement-button:pressed > .decrement-arrow { + -fx-background-color: -fx-mark-highlight-color,derive(-fx-base,-55%); +} +.scroll-bar:horizontal > .decrement-button > .decrement-arrow { + -fx-padding: 0.333em 0.167em 0.333em 0.167em; /* 4 2 4 2 */ + -fx-shape: "M5.997,5.072L5.995,6.501l-2.998-4l2.998-4l0.002,1.43l-1.976,2.57L5.997,5.072z"; + -fx-effect: dropshadow(two-pass-box , -fx-shadow-highlight-color, 1, 0.0 , 0, 1.4); + /*-fx-background-insets: 2 0 -2 0, 0;*/ +} +.scroll-bar:horizontal > .increment-button > .increment-arrow { + -fx-padding: 0.333em 0.167em 0.333em 0.167em; /* 4 2 4 2 */ + -fx-shape: "M2.998-0.07L3-1.499l2.998,4L3,6.501l-0.002-1.43l1.976-2.57L2.998-0.07z"; + -fx-effect: dropshadow(two-pass-box , -fx-shadow-highlight-color, 1, 0.0 , 0, 1.4); + /*-fx-background-insets: 2 0 -2 0, 0;*/ +} +.scroll-bar:vertical > .decrement-button > .decrement-arrow { + -fx-padding: 0.167em 0.333em 0.167em 0.333em; /* 2 4 2 4 */ + -fx-shape: "M1.929,4L0.5,3.998L4.5,1l4,2.998L7.07,4L4.5,2.024L1.929,4z"; + -fx-effect: dropshadow(two-pass-box , -fx-shadow-highlight-color, 1, 0.0 , 0, 1.4); + /*-fx-background-insets: 2 0 -2 0, 0;*/ +} +.scroll-bar:vertical > .increment-button > .increment-arrow { + -fx-padding: 0.167em 0.333em 0.167em 0.333em; /* 2 4 2 4 */ + -fx-shape: "M7.071,1L8.5,1.002L4.5,4l-4-2.998L1.93,1L4.5,2.976L7.071,1z"; + -fx-effect: dropshadow(two-pass-box , -fx-shadow-highlight-color, 1, 0.0 , 0, 1.4); + /*-fx-background-insets: 2 0 -2 0, 0;*/ +} + +/******************************************************************************* + * * + * ScrollPane * + * * + ******************************************************************************/ +.scroll-pane > .viewport { + -fx-background-color: -fx-background; +} +.scroll-pane > .scroll-bar:horizontal { + -fx-background-insets: 0 1 1 1, 1; + -fx-padding: 0 1 0 1; +} +.scroll-pane > .scroll-bar:horizontal > .increment-button, +.scroll-pane > .scroll-bar:horizontal > .decrement-button { + -fx-padding: 0.166667em 0.25em 0.25em 0.25em; /* 2 3 3 3 */ +} +.scroll-pane > .scroll-bar:vertical > .increment-button, +.scroll-pane > .scroll-bar:vertical > .decrement-button { + -fx-padding: 0.25em 0.25em 0.25em 0.166667em; /* 3 3 3 2 */ +} +.scroll-pane > .scroll-bar:vertical { + -fx-background-insets: 1 1 1 0, 1; + -fx-padding: 1 0 1 0; +} +.scroll-pane > .corner { + -fx-background-color: derive(-fx-base,-1%); + -fx-background-insets: 0 1 1 0; +} +/* new styleclass for edge to edge scrollpanes that don't want to draw a border */ +.scroll-pane.edge-to-edge, +.tab-pane > * > .scroll-pane { + -fx-background-color: -fx-background; + -fx-background-insets: 0; + -fx-padding: 0; +} +.scroll-pane.edge-to-edge > .scroll-bar, +.tab-pane > * > .scroll-pane > .scroll-bar, +.titled-pane > .content > .scroll-pane > .scroll-bar { + -fx-background-insets: 0; + -fx-padding: 0; +} +.scroll-pane.edge-to-edge > .scroll-bar > .increment-button, +.scroll-pane.edge-to-edge > .scroll-bar > .decrement-button, +.tab-pane > * > .scroll-pane > .scroll-bar > .increment-button, +.tab-pane > * > .scroll-pane > .scroll-bar > .decrement-button, +.titled-pane > .content > .scroll-pane > .scroll-bar > .increment-button, +.titled-pane > .content > .scroll-pane > .scroll-bar > .decrement-button { + -fx-padding: 0.25em; /* 3px */ +} + +/******************************************************************************* + * * + * Separator * + * * + ******************************************************************************/ + +.separator:horizontal .line { + -fx-border-color: -fx-text-box-border transparent transparent transparent, + -fx-shadow-highlight-color transparent transparent transparent; + -fx-border-insets: 0, 1 0 0 0; +} +.separator:vertical .line { + -fx-border-color: transparent transparent transparent -fx-shadow-highlight-color, + transparent transparent transparent -fx-text-box-border; + -fx-border-width: 3, 1; + -fx-border-insets: 0, 0 0 0 1; +} + +/******************************************************************************* + * * + * ProgressBar * + * * + ******************************************************************************/ + +.progress-bar { + -fx-indeterminate-bar-length: 60; + -fx-indeterminate-bar-escape: true; + -fx-indeterminate-bar-flip: true; + -fx-indeterminate-bar-animation-time: 2; +} +.progress-bar > .bar { + -fx-background-color: linear-gradient(to bottom, derive(-fx-accent, -7%), derive(-fx-accent, 0%), derive(-fx-accent, -3%), derive(-fx-accent, -9%) ); + -fx-background-insets: 3 3 4 3; + /*-fx-background-radius: 0.583em; *//* 7 */ + -fx-background-radius: 2; + -fx-padding: 0.75em; +} +.progress-bar:indeterminate > .bar { + -fx-background-color: linear-gradient(to left, transparent, -fx-accent); +} +.progress-bar > .track { + -fx-background-color: + -fx-shadow-highlight-color, + linear-gradient(to bottom, derive(-fx-text-box-border, -10%), -fx-text-box-border), + linear-gradient(to bottom, + derive(-fx-control-inner-background, -7%), + derive(-fx-control-inner-background, 0%), + derive(-fx-control-inner-background, -3%), + derive(-fx-control-inner-background, -9%) + ); + -fx-background-insets: 0, 0 0 1 0, 1 1 2 1; + -fx-background-radius: 4, 3, 2; /* 10, 9, 8 */ +} + +/******************************************************************************* + * * + * ProgressIndicator * + * * + ******************************************************************************/ + +.progress-indicator { + -fx-indeterminate-segment-count: 12; + -fx-spin-enabled: true; +} +.progress-indicator > .determinate-indicator > .indicator { + -fx-background-color: -fx-box-border, + radial-gradient(center 50% 50%, radius 50%, -fx-control-inner-background 70%, derive(-fx-control-inner-background, -9%) 100%), + -fx-control-inner-background; + -fx-background-insets: 0, 1, 5 2 1 2; + -fx-padding: 0.166667em; /* 2px */ +} +.progress-indicator > .determinate-indicator > .progress { + -fx-background-color: -fx-accent; + -fx-padding: 0.083333em; /* 1px */ +} +.progress-indicator > .determinate-indicator > .tick { + -fx-background-color: white; + -fx-background-insets: 0; + -fx-padding: 0.666667em; /* 8 */ + -fx-shape: "M-0.25,6.083c0.843-0.758,4.583,4.833,5.75,4.833S14.5-1.5,15.917-0.917c1.292,0.532-8.75,17.083-10.5,17.083C3,16.167-1.083,6.833-0.25,6.083z"; +} +.progress-indicator > .percentage { + -fx-font-size: 0.916667em; /* 11pt - 1 less than the default font */ + -fx-fill: -fx-text-background-color; +} +.progress-indicator:indeterminate > .spinner { + /** Applying to undo styling from .spinner, reported in RT-37965 */ + -fx-background-color: transparent; + -fx-background-insets: 0; + -fx-background-radius: 0; +} +.progress-indicator:indeterminate .segment { + -fx-background-color: -fx-accent; +} +.progress-indicator:indeterminate .segment0 { + -fx-shape:"M41.98 14.74 a3.5,3.5 0 1,1 0,1 Z"; +} +.progress-indicator:indeterminate .segment1 { + -fx-shape:"M33.75 6.51 a3.5,3.5 0 1,1 0,1 Z"; +} +.progress-indicator:indeterminate .segment2 { + -fx-shape:"M22.49 3.5 a3.5,3.5 0 1,1 0,1 Z"; +} +.progress-indicator:indeterminate .segment3 { + -fx-shape:"M11.24 6.51 a3.5,3.5 0 1,1 0,1 Z"; +} +.progress-indicator:indeterminate .segment4 { + -fx-shape:"M3.01 14.74 a3.5,3.5 0 1,1 0,1 Z"; +} +.progress-indicator:indeterminate .segment5 { + -fx-shape:"M0.0 26.0 a3.5,3.5 0 1,1 0,1 Z"; +} +.progress-indicator:indeterminate .segment6 { + -fx-shape:"M3.01 37.25 a3.5,3.5 0 1,1 0,1 Z"; +} +.progress-indicator:indeterminate .segment7 { + -fx-shape:"M11.25 45.48 a3.5,3.5 0 1,1 0,1 Z"; +} +.progress-indicator:indeterminate .segment8 { + -fx-shape:"M22.5 48.5 a3.5,3.5 0 1,1 0,1 Z"; +} +.progress-indicator:indeterminate .segment9 { + -fx-shape:"M33.75 45.48 a3.5,3.5 0 1,1 0,1 Z"; +} +.progress-indicator:indeterminate .segment10 { + -fx-shape:"M41.98 37.25 a3.5,3.5 0 1,1 0,1 Z"; +} +.progress-indicator:indeterminate .segment11 { + -fx-shape:"M45.0 26.0 a3.5,3.5 0 1,1 0,1 Z"; +} + +/******************************************************************************* + * * + * Text COMMON * + * * + ******************************************************************************/ + +.text-input { + -fx-text-fill: -fx-text-inner-color; + -fx-highlight-fill: derive(-fx-control-inner-background,-20%); + -fx-highlight-text-fill: -fx-text-inner-color; + -fx-prompt-text-fill: derive(-fx-control-inner-background,-30%); + -fx-background-color: linear-gradient(to bottom, derive(-fx-text-box-border, -10%), -fx-text-box-border), + linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background); + -fx-background-insets: 0, 1; + -fx-background-radius: 3, 2; + -fx-cursor: text; + -fx-padding: 0.333333em 0.583em 0.333333em 0.583em; /* 4 7 4 7 */ +} +.text-input:focused { + -fx-highlight-fill: -fx-accent; + -fx-highlight-text-fill: white; + -fx-background-color: + -fx-focus-color, + -fx-control-inner-background, + -fx-faint-focus-color, + linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background); + -fx-background-insets: -0.2, 1, -1.4, 3; + -fx-background-radius: 3, 2, 4, 0; + -fx-prompt-text-fill: transparent; +} + +/******************************************************************************* + * * + * TextArea * + * * + ******************************************************************************/ + +.text-area { + -fx-padding: 0; + -fx-cursor: default; + -fx-background-color: linear-gradient(to bottom, derive(-fx-text-box-border, -10%), -fx-text-box-border), + derive(-fx-base,-1%); +} +.text-area > .scroll-pane { + -fx-background-color: null; +} +.text-area > .scroll-pane > .scroll-bar:horizontal { + -fx-background-radius: 0 0 2 2; +} +.text-area > .scroll-pane > .scroll-bar:vertical { + -fx-background-radius: 0 2 2 0; +} +.text-area > .scroll-pane > .corner { + -fx-background-radius: 0 0 2 0; +} +.text-area .content { + /*the is 1px less top and bottom than TextInput because of scrollpane border */ + -fx-padding: 0.25em 0.583em 0.25em 0.583em; /* 3 7 3 7 */ + -fx-cursor: text; + -fx-background-color: + linear-gradient(from 0px 0px to 0px 4px, derive(-fx-control-inner-background, -8%), -fx-control-inner-background); + -fx-background-radius: 2; +} +.text-area:focused .content { + -fx-background-color: + -fx-control-inner-background, + -fx-faint-focus-color, + linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background); + -fx-background-insets: 0, 0, 2; + -fx-background-radius: 2, 1, 0; +} + +/******************************************************************************* + * * + * HTML Editor * + * * + ******************************************************************************/ + +.html-editor-foreground { + -fx-color-label-visible: false; + -fx-color-rect-x: 1; + -fx-color-rect-y: 1; + -fx-color-rect-width: 4; + -fx-color-rect-height: 3; + -fx-graphic: url("HTMLEditor-Text-Color.png"); +} +.html-editor-background { + -fx-color-label-visible: false; + -fx-color-rect-x: 1; + -fx-color-rect-y: 1; + -fx-color-rect-width: 4; + -fx-color-rect-height: 3; + -fx-graphic: url("HTMLEditor-Background-Color.png"); +} +.color-picker.html-editor-foreground > .color-picker-label > .picker-color > .picker-color-rect, +.color-picker.html-editor-background > .color-picker-label > .picker-color > .picker-color-rect { + -fx-stroke: null; +} +.html-editor .button , +.html-editor .toggle-button { + -fx-padding: 0.333333em 0.416667em 0.333333em 0.416667em; /* 4 5 4 5 */ +} +.html-editor-cut { + -fx-graphic: url("HTMLEditor-Cut.png"); +} +.html-editor-copy { + -fx-graphic: url("HTMLEditor-Copy.png"); +} +.html-editor-paste { + -fx-graphic: url("HTMLEditor-Paste.png"); +} +.html-editor-align-left { + -fx-graphic: url("HTMLEditor-Left.png"); +} +.html-editor-align-center { + -fx-graphic: url("HTMLEditor-Center.png"); +} +.html-editor-align-right { + -fx-graphic: url("HTMLEditor-Right.png"); +} +.html-editor-align-justify { + -fx-graphic: url("HTMLEditor-Justify.png"); +} +.html-editor-outdent { + -fx-graphic: url("HTMLEditor-Outdent.png"); +} +.html-editor-outdent:dir(rtl) { + -fx-graphic: url("HTMLEditor-Outdent-rtl.png"); +} +.html-editor-indent { + -fx-graphic: url("HTMLEditor-Indent.png"); +} +.html-editor-indent:dir(rtl) { + -fx-graphic: url("HTMLEditor-Indent-rtl.png"); +} +.html-editor-bullets { + -fx-graphic: url("HTMLEditor-Bullets.png"); +} +.html-editor-bullets:dir(rtl) { + -fx-graphic: url("HTMLEditor-Bullets-rtl.png"); +} +.html-editor-numbers { + -fx-graphic: url("HTMLEditor-Numbered.png"); +} +.html-editor-numbers:dir(rtl) { + -fx-graphic: url("HTMLEditor-Numbered-rtl.png"); +} +.html-editor-bold { + -fx-graphic: url("HTMLEditor-Bold.png"); +} +.html-editor-italic { + -fx-graphic: url("HTMLEditor-Italic.png"); +} +.html-editor-underline { + -fx-graphic: url("HTMLEditor-Underline.png"); +} +.html-editor-strike { + -fx-graphic: url("HTMLEditor-Strikethrough.png"); +} +.html-editor-hr { + -fx-graphic: url("HTMLEditor-Break.png"); +} + +/******************************************************************************* + * * + * PopupMenu * + * * + ******************************************************************************/ + +.context-menu { + -fx-background-color: + linear-gradient(to bottom, + derive(-fx-color,-17%), + derive(-fx-color,-30%) + ), + -fx-control-inner-background; + -fx-background-insets: 0, 1; + -fx-padding: 0.333333em 0.083333em 0.333333em 0.083333em; /* 4 1 8 1 */ + -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.2) , 12, 0.0 , 0 , 8 ); +} +.context-menu .separator:horizontal .line { + -fx-border-color: -fx-box-border transparent transparent transparent; + -fx-border-insets: 1 0 0 0; +} +.context-menu > .scroll-arrow { + -fx-padding: 0.416667em 0.416667em 0.416667em 0.416667em; /* 5 */ + -fx-background-color: transparent; +} +.context-menu > .scroll-arrow:hover { + -fx-background: -fx-selection-bar; + -fx-background-color: -fx-background; + -fx-text-fill: -fx-text-background-color; +} +.context-menu:show-mnemonics > .mnemonic-underline { + -fx-stroke: -fx-text-fill; +} + +/******************************************************************************* + * * + * Menu * + * * + ******************************************************************************/ + +.menu { + -fx-background-color: transparent; + -fx-padding: 0.333333em 0.666667em 0.333333em 0.666667em; /* 4 8 4 8 */ +} +.menu:show-mnemonics > .mnemonic-underline { + -fx-stroke: -fx-text-fill; +} +.menu > .right-container > .arrow { + -fx-padding: 0.458em 0.167em 0.458em 0.167em; /* 4.5 2 4.5 2 */ + -fx-background-color: -fx-mark-color; + -fx-shape: "M0,-4L4,0L0,4Z"; + -fx-scale-shape: false; +} +.menu:focused > .right-container > .arrow { + -fx-background-color: -fx-focused-mark-color; +} +.menu-up-arrow { + -fx-padding: 0.666667em 0.416667em 0.0em 0.416667em; /* 8 5 0 5 */ + -fx-background-color: derive(-fx-color,-2%); + -fx-shape: "M0 1 L1 1 L.5 0 Z"; + -fx-effect: innershadow( two-pass-box , rgba(0,0,0,0.6) , 4, 0.0 , 0 , 1 ); +} +.menu-down-arrow { + -fx-background-color: derive(-fx-color,-2%); + -fx-padding: 0.666667em 0.416667em 0.0em 0.416667em; /* 8 5 0 5 */ + -fx-shape: "M0 0 L1 0 L.5 1 Z"; + -fx-effect: innershadow( two-pass-box , rgba(0,0,0,0.6) , 4, 0.0 , 0 , 1 ); +} + + +/******************************************************************************* + * * + * MenuBar * + * * + ******************************************************************************/ + +.menu-bar { + -fx-padding: 0.0em 0.666667em 0.0em 0.666667em; /* 0 8 0 8 */ + -fx-spacing: 0.166667em; /* 2 */ + -fx-background-color: + linear-gradient(to bottom, derive(-fx-base,75%) 0%, -fx-outer-border 90%), + linear-gradient(to bottom, derive(-fx-base,46.9%) 2%, derive(-fx-base,-2.1%) 95%); + -fx-background-insets: 0 0 0 0, 1 0 1 0; + -fx-background-radius: 0, 0 ; +} +/* Show nothing for background of normal menu button in a menu bar */ +.menu-bar > .container > .menu-button { + -fx-background-radius: 0; + -fx-background-color: transparent; + -fx-background-insets: 0; +} +/* Change padding of menu buttons when in menu bar */ +.menu-bar > .container > .menu-button > .label { + -fx-padding: 0; +} +/* Hide the down arrow for a menu placed in a menubar */ +.menu-bar > .container > .menu-button > .arrow-button > .arrow { + -fx-padding: 0.167em 0 0.250em 0; /* 2 0 3 0 */ + -fx-background-color: transparent; + -fx-shape: null; +} +.menu-bar > .container > .menu > .arrow-button { + -fx-padding: 0.500em 0 0.500em 0; /* 6 0 6 0 */ +} +.menu-bar > .container > .menu-button:hover, +.menu-bar > .container > .menu-button:focused, +.menu-bar > .container > .menu-button:showing { + -fx-background: -fx-selection-bar; + -fx-background-color: -fx-background; +} +.menu-bar > .container > .menu-button:hover > .label, +.menu-bar > .container > .menu-button:focused > .label, +.menu-bar > .container > .menu-button:showing > .label { + -fx-text-fill: -fx-text-background-color; +} +.menu-bar:show-mnemonics > .mnemonic-underline { + -fx-stroke: -fx-text-fill; +} + +/******************************************************************************* + * * + * MenuItem * + * * + ******************************************************************************/ + +.menu-item { + -fx-background-color: transparent; + -fx-padding: 0.333333em 0.41777em 0.333333em 0.41777em; /* 4 5 4 5 */ +} +.menu-item > .left-container { + -fx-padding: 0.458em 0.791em 0.458em 0.458em; +} +.menu-item > .graphic-container { + -fx-padding: 0em 0.333em 0em 0em; +} +.menu-item >.label { + -fx-padding: 0em 0.5em 0em 0em; + -fx-text-fill: -fx-text-base-color; +} +.menu-item:focused { + -fx-background: -fx-selection-bar; + -fx-background-color: -fx-background; + -fx-text-fill: -fx-text-background-color; +} +.menu-item:focused > .label { + -fx-text-fill: -fx-focused-text-base-color; +} +.menu-item > .right-container { + -fx-padding: 0em 0em 0em 0.5em; +} +.menu-item:show-mnemonics > .mnemonic-underline { + -fx-stroke: -fx-text-fill; +} +.radio-menu-item:checked > .left-container > .radio { + -fx-background-color: -fx-mark-color; + -fx-shape: "M0,5H2L4,8L8,0H10L5,10H3Z"; + -fx-scale-shape: false; +} +.radio-menu-item:focused:checked > .left-container > .radio { + -fx-background-color: -fx-focused-mark-color; +} +.check-menu-item:checked > .left-container > .check { + -fx-background-color: -fx-mark-color; + -fx-shape: "M0,5H2L4,8L8,0H10L5,10H3Z"; + -fx-scale-shape: false; +} +.check-menu-item:focused:checked > .left-container > .check { + -fx-background-color: -fx-focused-mark-color; +} +/******************************************************************************* + * * + * ChoiceBox * + * * + ******************************************************************************/ + +/*.choice-box > .open-button > .arrow { + -fx-background-color: -fx-mark-highlight-color, -fx-mark-color; + -fx-background-insets: 1 0 -1 0, 0; + -fx-padding: 0.166667em 0.333333em 0.166667em 0.333333em; 2 3.5 2 3.5 + -fx-shape: "M 0 0 h 7 l -3.5 4 z"; +}*/ +.choice-box > .context-menu { + -fx-background-radius: 6, 5, 4; +} + +/******************************************************************************* + * * + * TabPane * + * * + ******************************************************************************/ + +.tab-pane { + -fx-tab-min-height: 1.8333em; /* 22 */ + -fx-tab-max-height: 1.8333em; /* 22 */ +} +.tab-pane > .tab-header-area > .headers-region > .tab > .tab-container > .tab-label { + -fx-alignment: CENTER; + -fx-text-fill: -fx-text-base-color; +} +.tab-pane > .tab-header-area > .headers-region > .tab { + -fx-background-insets: 0 1 1 0, 1 2 1 1, 2 3 1 2; + -fx-background-radius: 3 3 0 0, 2 2 0 0, 1 1 0 0; + -fx-padding: 0.083333em 0.5em 0.0769em 0.5em; /* 1 6 0.99 6 */ +} +.tab-pane > .tab-header-area > .headers-region > .tab:top { + -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; +} +.tab-pane > .tab-header-area > .headers-region > .tab:right { + -fx-background-color: -fx-outer-border, -fx-inner-border-bottomup, -fx-body-color-bottomup; +} +.tab-pane > .tab-header-area > .headers-region > .tab:bottom { + -fx-background-color: -fx-outer-border, -fx-inner-border-bottomup, -fx-body-color-bottomup; +} +.tab-pane > .tab-header-area > .headers-region > .tab:left { + -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; +} +.tab-pane > .tab-header-area > .headers-region > .tab:hover { + -fx-color: -fx-hover-base; +} +.tab-pane > .tab-header-area > .headers-region > .tab:selected { + -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-background; + -fx-background-insets: 0 1 1 0, 1 2 0 1, 2 3 0 2; +} +.tab-pane:focused > .tab-header-area > .headers-region > .tab:selected .focus-indicator { + -fx-border-width: 1, 1; + -fx-border-color: -fx-focus-color, -fx-faint-focus-color; + -fx-border-insets: -4 -4 -6 -5, -2 -2 -5 -3; + -fx-border-radius: 2, 1; /* looks sharper if outer border has a tighter radius (2 instead of 3) */ +} +.tab-pane:focused > .tab-header-area > .headers-region > .tab:bottom:selected .focus-indicator { + -fx-border-insets: -6 -5 -4 -4, -5 -3 -2 -2; +} +.tab-pane > .tab-header-area > .headers-region > .tab:disabled:hover { + -fx-color: -fx-base; +} +.tab-pane > .tab-header-area > .tab-header-background { + /* TODO should not be using text-box-border I think? */ + -fx-background-color: + -fx-outer-border, + -fx-text-box-border, + linear-gradient(from 0px 0px to 0px 5px, -fx-text-box-border, derive(-fx-text-box-border, 30%)); +} +.tab-pane:top > .tab-header-area > .tab-header-background { + -fx-background-insets: 0, 0 0 1 0, 1; +} +.tab-pane:bottom > .tab-header-area > .tab-header-background { + -fx-background-insets: 0, 1 0 0 0, 1; +} +.tab-pane:left > .tab-header-area > .tab-header-background { + -fx-background-insets: 0, 0 1 0 0, 1; +} +.tab-pane:right > .tab-header-area > .tab-header-background { + -fx-background-insets: 0, 0 0 0 1, 1; +} +.tab-pane:top > .tab-header-area { + /*-fx-padding: 0.416667em 0.166667em 0.0em 0.416667em; *//* 5 2 0 5 */ + -fx-padding: 0.416667em 5 0.0em 0.416667em; /* 5 2 0 5 */ +} +.tab-pane:bottom > .tab-header-area { + -fx-padding: 0 0.166667em 0.416667em 0.416667em; /* 0 2 5 5 */ +} +.tab-pane:left > .tab-header-area { + -fx-padding: 0.416667em 0.0em 0.166667em 0.416667em; /* 5 0 2 5 */ +} +.tab-pane:right > .tab-header-area { + -fx-padding: 0.416667em 0.416667em 0.166667em 0.0em; /* 5 5 2 0 */ +} +/* TODO: scaling the shape seems to make it way too large */ +.tab-pane > .tab-header-area > .headers-region > .tab > .tab-container > .tab-close-button { + -fx-background-color: -fx-mark-color; + -fx-shape: "M 0,0 H1 L 4,3 7,0 H8 V1 L 5,4 8,7 V8 H7 L 4,5 1,8 H0 V7 L 3,4 0,1 Z"; + -fx-scale-shape: false; + -fx-effect: dropshadow(two-pass-box , rgba(255, 255, 255, 0.4), 1, 0.0 , 0, 1); +} +.tab-pane > .tab-header-area > .headers-region > .tab > .tab-container > .tab-close-button:hover { + -fx-background-color: derive(-fx-mark-color, -30%); +} +/* CONTROL BUTTONS */ +.tab-pane > .tab-header-area > .control-buttons-tab > .container { + -fx-padding: 3 0 0 0; +} +.tab-pane > .tab-header-area > .control-buttons-tab > .container > .tab-down-button { + -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; + -fx-background-insets: -1 0 5 0, 0 1 6 1, 1 2 7 2; + -fx-padding: 4 4 9 4; + -fx-background-radius: 10; +} +.tab-pane:bottom > .tab-header-area > .control-buttons-tab > .container > .tab-down-button { + -fx-padding: -5 4 4 4; /* TODO convert to ems */ +} +/* FLOATING TABS CUSTOMISATION */ +.tab-pane.floating > .tab-header-area > .tab-header-background { + -fx-background-color: null; +} +.tab-pane.floating > .tab-header-area { + -fx-background-color: null; +} +.tab-pane.floating > .tab-content-area { + -fx-background-color: -fx-outer-border, -fx-background; + -fx-background-insets: 0, 1; + -fx-background-radius: 2, 0; + -fx-padding: 2; +} + +/******************************************************************************* + * * + * ComboBox * + * * + ******************************************************************************/ + +/* Customise the ListCell that appears in the ComboBox button itself */ +.combo-box > .list-cell { + -fx-background: transparent; + -fx-background-color: transparent; + -fx-text-fill: -fx-text-base-color; + -fx-padding: 0.333333em 0.666667em 0.333333em 0.666667em; /* 4 8 4 8 */ +} +.combo-box-base > .arrow-button { + -fx-background-radius: 0 3 3 0, 0 2 2 0, 0 1 1 0; + -fx-padding: 0.5em 0.667em 0.5em 0.833333em; /* 6 8 6 10 */ + -fx-background-color: transparent; +} + +/******************************************************************************* + * * + * Editable ComboBox * + * * + * The editable ComboBox TextBox inherits its properties from the TextBox * + * Control. Only the properties with values that are different from the * + * TextBox are specified here. * + * * + ******************************************************************************/ + +.combo-box-base:editable > .arrow-button, +.date-picker > .arrow-button { + -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; + -fx-background-insets: 1 1 1 0, 1, 2; + -fx-background-radius: 0 3 3 0, 0 2 2 0, 0 1 1 0; +} +.combo-box-base:editable > .text-field, +.date-picker > .text-field { + -fx-background-color: + linear-gradient(to bottom, derive(-fx-text-box-border, -10%), -fx-text-box-border), + linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background); + -fx-background-insets: 1 0 1 1; + -fx-background-radius: 2 0 0 2; +} +.combo-box-base:editable:focused, +.date-picker:focused { + -fx-background-color: -fx-focus-color; + -fx-background-insets: -0.2; + -fx-background-radius: 3; +} +.combo-box-base:editable:focused > .text-field, +.combo-box-base:editable > .text-field:focused, +.date-picker:focused > .text-field, +.date-picker > .text-field:focused { + -fx-background-color: + -fx-control-inner-background, + -fx-faint-focus-color, + linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background); + -fx-background-insets: 1 0 1 1, 1 0 1 1, 3 2 3 3; + -fx-background-radius: 2 0 0 2, 1 0 0 1, 0; +} +.combo-box-base:editable:focused > .arrow-button, +.date-picker:focused > .arrow-button { + -fx-background-color: -fx-inner-border, -fx-body-color, -fx-faint-focus-color, -fx-body-color; + -fx-background-insets: 1, 2, 1, 2.6; + -fx-background-radius: 0 2 2 0, 0 1 1 0, 0 1 1 0, 0 1 1 0; +} + +/* -------------- STYLES FOR THE DEFAULT LISTVIEW-BASED COMBOBOX ------------- */ + +.combo-box-popup > .list-view { + -fx-background-color: + linear-gradient(to bottom, + derive(-fx-color,-17%), + derive(-fx-color,-30%) + ), + -fx-control-inner-background; + -fx-background-insets: 0, 1; + -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.2) , 12, 0.0 , 0 , 8 ); +} +.combo-box-popup > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell { + -fx-padding: 4 0 4 5; + /* No alternate highlighting */ + -fx-background: -fx-control-inner-background; +} +.combo-box-popup > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:hover { + -fx-background: -fx-accent; + -fx-background-color: -fx-selection-bar; +} +.combo-box-popup > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected, +.combo-box-popup > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected:hover { + -fx-background: -fx-accent; + -fx-background-color: -fx-background, -fx-cell-focus-inner-border, -fx-background; + -fx-background-insets: 0, 1, 2; +} +.combo-box-popup > .list-view > .placeholder > .label { + -fx-text-fill: derive(-fx-control-inner-background,-30%); +} + +/******************************************************************************* + * * + * TitledPane * + * * + ******************************************************************************/ + +.titled-pane { + -fx-text-fill: -fx-text-base-color; +} +.titled-pane:focused { + -fx-color: -fx-base; +} +.titled-pane > .title { + -fx-background-color: + linear-gradient(to bottom, + derive(-fx-color,-15%) 95%, + derive(-fx-color,-25%) 100% + ), + -fx-inner-border, -fx-body-color; + -fx-background-insets: 0, 1, 2; + -fx-background-radius: 3 3 0 0, 2 2 0 0, 1 1 0 0; + -fx-padding: 0.3333em 0.75em 0.3333em 0.75em; /* 4 9 4 9 */ +} +/* alternative focus using the ring around the entire title area */ +/*.titled-pane:focused > .title { + -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-inner-border, -fx-body-color; + -fx-background-insets: 0, 0.7, 2, 3; +}*/ +/* focus purely on the arrow */ +.titled-pane:focused > .title > .arrow-button > .arrow { + -fx-background-color: -fx-focus-color, -fx-mark-color; + -fx-background-insets: -1, 0; + -fx-effect: dropshadow(two-pass-box , -fx-focus-color, 5, 0.2 , 0, 0); +} +.titled-pane > .title > .arrow-button { + -fx-background-color: null; + -fx-background-insets: 0; + -fx-background-radius: 0; + -fx-padding: 0.0em 0.583em 0.0em 0.0em; /* 0 7 0 0 */ +} +.titled-pane > .title > .arrow-button > .arrow { + -fx-background-color: -fx-mark-highlight-color, -fx-mark-color; + -fx-background-insets: 1 0 -1 0, 0; + -fx-padding: 0.25em 0.3125em 0.25em 0.3125em; /* 3 3.75 3 3.75 */ + -fx-shape: "M 0 0 h 7 l -3.5 4 z"; +} +.titled-pane > .title:hover { + -fx-color: -fx-hover-base; +} +/* alternative content using a border and a grad to transparent background - why should TitledPane content have a colour? */ +.titled-pane > *.content { + -fx-border-color: -fx-box-border; + -fx-border-insets: -1 0 0 0; + -fx-background-color: linear-gradient(from 0px 0px to 0px 5px, derive(-fx-background, -6%), -fx-background); +} + + + +/******************************************************************************* + * * + * Accordion * + * * + ******************************************************************************/ + +.accordion > .titled-pane > .title { + -fx-background-color: + linear-gradient(to bottom, + derive(-fx-color,-15%) 95%, + derive(-fx-color,-25%) 100% + ), + -fx-inner-border, + -fx-body-color; + -fx-background-insets: -1 0 0 0, 0 1 1 1, 1 2 2 2; + -fx-background-radius: 0, 0, 0; +} +.accordion > .first-titled-pane > .title { + -fx-background-insets: 0, 1, 2; +} + +/******************************************************************************* + * * + * SplitPane * + * * + ******************************************************************************/ + +.split-pane > .split-pane-divider { + -fx-padding: 0 0.25em 0 0.25em; /* 0 3 0 3 */ +} +/* horizontal the two nodes are placed to the left/right of each other. */ +.split-pane:horizontal > .split-pane-divider { + -fx-background-color: -fx-box-border, -fx-inner-border-horizontal; + -fx-background-insets: 0, 0 1 0 1; +} +/* vertical the two nodes are placed on top of each other. */ +.split-pane:vertical > .split-pane-divider { + -fx-background-color: -fx-box-border, -fx-inner-border; + -fx-background-insets: 0, 1 0 1 0; +} + +/******************************************************************************* + * * + * ColorPicker * + * * + ******************************************************************************/ + +.color-picker > .arrow-button { + -fx-background-color: null; + -fx-padding: 0.5em 0.667em 0.5em 0; /* 6 8 6 0 */ +} +.color-picker.split-button > .arrow-button { + -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; + -fx-background-insets: 1 1 1 0, 1, 2; + -fx-background-radius: 0 3 3 0, 0 2 2 0, 0 1 1 0; +} +.color-picker.split-button:focused > .arrow-button { + /*-fx-background-color: -fx-focus-color, -fx-inner-border, -fx-body-color !important;*/ + /*-fx-background-insets: 0, 1, 2;*/ + -fx-background-color: -fx-focus-color, -fx-inner-border, -fx-body-color, -fx-faint-focus-color, -fx-body-color; + -fx-background-insets: 1 1 1 0, 1, 2, 1, 2.6; + -fx-background-radius: 0 3 3 0, 0 2 2 0, 0 1 1 0, 0 1 1 0, 0 1 1 0; +} +.color-picker.split-button > .color-picker-label, +.color-picker.split-button:focused > .color-picker-label{ + -fx-background-color: null; +} +.color-picker.split-button > .arrow-button { + /*-fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color !important;*/ + -fx-padding: 0.5em 0.667em 0.5em 0.667em; /* 6 8 6 8 */ +} +.color-picker > .color-picker-label > .picker-color > .picker-color-rect { + -fx-stroke: -fx-box-border; +} + +.color-palette { + -fx-spacing: 0.833333em; /* 10px */ + -fx-background-color: + linear-gradient(to bottom, + derive(-fx-color,-17%), + derive(-fx-color,-30%) + ), + linear-gradient(to bottom, + derive(-fx-background,10%) 0%, + derive(-fx-background,-5%) 12%, + derive(-fx-background,15%) 88%, + derive(-fx-background,-10%) 100%); + -fx-background-insets: 0, 1; + -fx-background-radius: 6, 5; + -fx-padding: 1em; /* 12 */ + -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.2) , 12, 0.0 , 0 , 8 ); +} +.color-palette > .color-picker-grid { + -fx-padding: 0.5px; + -fx-snap-to-pixel: false; +} +.color-palette > .color-picker-grid > .color-square { + -fx-background-color: transparent; + -fx-padding: 0.5px; +} +/* the color over which the user is hovering */ +.color-palette-region > .color-square.hover-square { + -fx-background-color: -fx-faint-focus-color, -fx-focus-color; + -fx-background-insets: -3,-1; + -fx-background-radius: 5,0; + -fx-scale-x: 1.5; + -fx-scale-y: 1.5; +} +/* ------- CUSTOM COLOR DIALOG ------- */ +.custom-color-dialog > .color-rect-pane { + -fx-spacing: 0.75em; + -fx-pref-height: 16.666667em; + -fx-alignment: top-left; + -fx-fill-height: true; +} + +.custom-color-dialog .color-rect-pane .color-rect { + -fx-min-width: 16.666667em; + -fx-min-height: 16.666667em; +} + +.custom-color-dialog .color-rect-pane .color-rect-border { + -fx-border-color: derive(-fx-base, -20%); +} + +.custom-color-dialog > .color-rect-pane #color-rect-indicator { + -fx-background-color: null; + -fx-border-color: white; + -fx-border-radius: 0.4166667em; + -fx-translate-x: -0.4166667em; + -fx-translate-y: -0.4166667em; + -fx-pref-width: 0.833333em; + -fx-pref-height: 0.833333em; + -fx-effect: dropshadow(three-pass-box, black, 2, 0.0, 0, 1); +} + +.custom-color-dialog > .color-rect-pane > .color-bar { + -fx-min-width: 1.666667em; + -fx-min-height: 16.666667em; + -fx-max-width: 1.666667em; + -fx-border-color: derive(-fx-base, -20%); +} + +.custom-color-dialog > .color-rect-pane > .color-bar > #color-bar-indicator { + -fx-border-radius: 0.333333em; + -fx-border-color: white; + -fx-effect: dropshadow(three-pass-box, black, 2, 0.0, 0, 1); + -fx-pref-width: 2em; + -fx-pref-height: 0.833333em; + -fx-translate-x: -0.1666667em; + -fx-translate-y: -0.4166667em; +} + +.custom-color-dialog { + -fx-background-color: -fx-background; + -fx-padding: 1.25em; + -fx-spacing: 1.25em; +} +.custom-color-dialog .controls-pane .current-new-color-grid #current-new-color-border { + -fx-border-color: derive(-fx-base, -20%); + -fx-border-width: 2px; +} + +.custom-color-dialog .controls-pane .current-new-color-grid .color-rect { + -fx-min-width: 10.666667em; + -fx-min-height: 1.75em; + -fx-pref-width: 10.666667em; + -fx-pref-height: 1.75em; +} + +.custom-color-dialog .transparent-pattern { + -fx-background-image: url("pattern-transparent.png"); + -fx-background-repeat: repeat; + -fx-background-size: auto; +} + +.custom-color-dialog .controls-pane #spacer1 { + -fx-min-height: 0.1666667em; + -fx-max-height: 0.1666667em; + -fx-pref-height: 0.1666667em; +} + +.custom-color-dialog .controls-pane #spacer2 { + -fx-min-height: 1em; + -fx-max-height: 1em; + -fx-pref-height: 1em; +} + +.custom-color-dialog .controls-pane #settings-pane { + -fx-hgap: 0.4166667em; + -fx-vgap: 0.3333333em; +} + +.custom-color-dialog .controls-pane #settings-pane .settings-label { + -fx-min-width: 5.75em; +} + +.custom-color-dialog .controls-pane #settings-pane .settings-unit { + -fx-max-width: 1.5em; + -fx-min-width: 1.5em; + -fx-pref-width: 1.5em; +} + +.custom-color-dialog .controls-pane #settings-pane .slider { + -fx-pref-width: 8.25em; +} + +.custom-color-dialog .controls-pane .color-input-field { + -fx-pref-column-count: 3; + -fx-max-width: 3.25em; + -fx-min-width: 3.25em; + -fx-pref-width: 3.25em; +} + +.custom-color-dialog .controls-pane .web-field { + -fx-pref-column-count: 6; + -fx-pref-width: 8.25em; +} + +.custom-color-dialog .controls-pane #spacer-side { + -fx-min-width: 0.5em; + -fx-pref-width: 0.5em; +} + +.custom-color-dialog .controls-pane #spacer-bottom { + -fx-pref-height: 0.833333em; + -fx-min-height: 0.833333em; +} + +.custom-color-dialog .controls-pane .customcolor-controls-background { + -fx-background-color: -fx-text-box-border, -fx-control-inner-background; + -fx-background-insets: + 0.8333333em 0 0.4166667em 0, + 1em 0.166667em 0.5833333em 0.166667em; + -fx-background-radius: 0.3333333em, 0.166667em; +} + +.custom-color-dialog .controls-pane .current-new-color-grid .label { + -fx-padding: 0 0 0 0.4166667em; +} + +.custom-color-dialog .controls-pane #buttons-hbox { + -fx-spacing: 0.333333em; + -fx-padding: 1em 0 0 0; + -fx-alignment: bottom-right; +} + +/* The fix for RT-37494 forces the web color text's major direction to + * LTR. The following keeps the text right-aligned when in RTL mode. */ +.custom-color-dialog .webcolor-field:dir(rtl) > .text-field:dir(ltr) { + -fx-alignment: baseline-right; +} + +/******************************************************************************* + * * + * Pagination * + * * + ******************************************************************************/ + +.pagination { + -fx-padding: 0; + -fx-arrows-visible: true; + -fx-tooltip-visible: true; + -fx-page-information-visible: true; + -fx-page-information-alignment: bottom; + -fx-arrow-button-gap: 0; +} +.pagination > .page { + -fx-background-color: transparent; +} +.pagination > .pagination-control { + -fx-background-color: transparent; + -fx-font-size: 0.82em; +} +.pagination > .pagination-control > .control-box { + -fx-padding: 5px 0 0 0; + -fx-spacing: 2; + -fx-alignment: center; +} +.pagination > .pagination-control > .control-box > .left-arrow-button { + -fx-background-radius: 3 0 0 3, 3 0 0 3, 2 0 0 2, 1 0 0 1; + -fx-background-insets: 0 0 -1 5, 0 0 0 5, 1 1 1 6, 2 2 2 7; + -fx-padding: 0em 0.417em 0em 0.833em; /* 0 5 0 10 */ +} +.pagination > .pagination-control > .control-box > .right-arrow-button { + -fx-background-radius: 0 3 3 0, 0 3 3 0, 0 2 2 0, 0 1 1 0; + -fx-background-insets: 0 5 -1 0, 0 5 0 0, 1 6 1 1, 2 7 2 2; + -fx-padding: 0em 0.75em 0em 0.417em; /* 0 9 0 5 */ +} +.pagination > .pagination-control .left-arrow { + -fx-background-color: -fx-mark-highlight-color, -fx-mark-color; + -fx-background-insets: 1 0 -1 0, 0; + -fx-padding: 0.375em 0.291em 0.375em 0.291em; + -fx-shape: "M 0 0 L -13 7 L 0 13 z"; + -fx-scale-shape: true; +} +.pagination > .pagination-control .right-arrow { + -fx-background-color: -fx-mark-highlight-color, -fx-mark-color; + -fx-background-insets: 1 0 -1 0, 0; + -fx-padding: 0.375em 0.291em 0.375em 0.291em; + -fx-shape: "M 0 0 L 13 7 L 0 13 z"; + -fx-scale-shape: true; +} +.pagination > .pagination-control > .control-box > .bullet-button { + -fx-background-radius: 0, 4em, 4em, 4em, 4em; + -fx-padding: 0.333em; + -fx-background-color: transparent, -fx-outer-border, -fx-inner-border, -fx-body-color; + -fx-background-insets: 0, 5, 6, 7; +} +.pagination > .pagination-control > .control-box > .bullet-button:selected { + -fx-base: -fx-accent; +} +.pagination.bullet > .pagination-control > .control-box { + -fx-spacing: 0; + -fx-alignment: center; +} +.pagination.bullet > .pagination-control > .control-box > .left-arrow-button { + -fx-background-radius: 4em; + -fx-background-insets: 0, 1, 2; + -fx-padding: 0em 0.25em 0em 0.083em; /* 0 3 0 1 */ +} +.pagination.bullet > .pagination-control > .control-box > .right-arrow-button { + -fx-background-radius: 4em; + -fx-background-insets: 0, 1, 2; + -fx-padding: 0em 0.083em 0em 0.25em; /* 0 1 0 3 */ +} +.pagination > .pagination-control > .control-box > .number-button { + -fx-background-radius: 0; + -fx-padding: 0.166667em 0.333em 0.25em 0.333em; + -fx-background-color: -fx-shadow-highlight-color, -fx-outer-border, -fx-inner-border, -fx-body-color; +} +.pagination > .pagination-control > .control-box > .number-button:selected { + -fx-base: -fx-accent; +} +.pagination > .pagination-control > .page-information { + -fx-padding: 0.416em 0 0 0; +} + +/******************************************************************************* + * * + * Customised CSS for controls placed directly within cells * + * * + ******************************************************************************/ + +.cell > .choice-box { + -fx-background-color: transparent; + -fx-background-insets: 0; + -fx-background-radius: 0; + -fx-padding: 0.0em 0.5em 0.0em 0.0em; /* 0 6 0 0 */ + -fx-alignment: CENTER_LEFT; + -fx-content-display: LEFT; +} +.cell > .choice-box > .label { + -fx-padding: 0em 0.333333em 0.0em 0.333333; /* 2 4 3 6 */ +} +.cell:focused:selected > .choice-box > .label { + -fx-text-fill: white; +} +.cell:focused:selected > .choice-box > .open-button > .arrow { + -fx-background-color: -fx-mark-highlight-color, white; +} + +/******************************************************************************* + * * + * List, Tree, Table COMMON * + * * + ******************************************************************************/ + +/* remove double borders from scrollbars */ +.list-view > .virtual-flow > .scroll-bar:vertical, +.tree-view > .virtual-flow > .scroll-bar:vertical, +.table-view > .virtual-flow > .scroll-bar:vertical, +.tree-table-view > .virtual-flow > .scroll-bar:vertical { + -fx-background-insets: 0, 0 0 0 1; + -fx-padding: -1 -1 -1 0; +} +.list-view > .virtual-flow > .scroll-bar:horizontal, +.tree-view > .virtual-flow > .scroll-bar:horizontal, +.table-view > .virtual-flow > .scroll-bar:horizontal, +.tree-table-view > .virtual-flow > .scroll-bar:horizontal { + -fx-background-insets: 0, 1 0 0 0; + -fx-padding: 0 -1 -1 -1; +} +.list-view > .virtual-flow > .corner, +.tree-view > .virtual-flow > .corner, +.table-view > .virtual-flow > .corner, +.tree-table-view > .virtual-flow > .corner { + -fx-background-color: derive(-fx-base,-1%); +} +/* standard cell */ +.list-cell, +.tree-cell { + -fx-background: -fx-control-inner-background; + -fx-background-color: -fx-background; + -fx-text-fill: -fx-text-background-color; +} +/* Selected rows */ +.list-view:focused > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected, +.tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-cell:filled:selected, +.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled:selected, +.tree-table-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:selected, +.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell .table-cell:selected, +.tree-table-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell .tree-table-cell:selected { + -fx-background: -fx-selection-bar; + -fx-table-cell-border-color: derive(-fx-selection-bar, 20%); +} +/* Selected when control is not focused */ +.list-cell:filled:selected, +.tree-cell:filled:selected, +.table-row-cell:filled:selected, +.tree-table-row-cell:filled:selected, +.table-row-cell:filled > .table-cell:selected, +.tree-table-row-cell:filled > .tree-table-cell:selected { + -fx-background: -fx-selection-bar-non-focused; + -fx-table-cell-border-color: derive(-fx-selection-bar-non-focused, 20%); +} +/* focused cell (keyboard navigation) */ +.list-view:focused > .virtual-flow > .clipped-container > .sheet > .list-cell:focused, +.tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-cell:focused, +.table-view:focused:row-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:focused, +.tree-table-view:focused:row-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:focused, +.table-view:focused:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell > .table-cell:focused, +.tree-table-view:focused:cell-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell > .tree-table-cell:focused { + -fx-background-color: -fx-background, -fx-cell-focus-inner-border, -fx-background; + -fx-background-insets: 0, 1, 2; +} + +/******************************************************************************* + * * + * ListView and ListCell * + * * + ******************************************************************************/ + +.list-cell { + -fx-padding: 0.25em 0.583em 0.25em 0.583em; /* 3 7 3 7 */ +} +.list-cell:odd { + -fx-background: -fx-control-inner-background-alt; +} + +/******************************************************************************* + * * + * TreeView and TreeCell * + * * + ******************************************************************************/ + +.tree-cell { + -fx-padding: 0.25em; /* 3 */ + -fx-indent: 1em; +} +.tree-cell .label { + -fx-padding: 0.0em 0.0em 0.0em 0.25em; /* 0 0 0 3 */ +} +.tree-cell > .tree-disclosure-node, +.tree-table-row-cell > .tree-disclosure-node { + -fx-padding: 4 6 4 8; + -fx-background-color: transparent; +} +.tree-cell > .tree-disclosure-node > .arrow, +.tree-table-row-cell > .tree-disclosure-node > .arrow { + -fx-background-color: -fx-text-background-color; + -fx-padding: 0.333333em 0.229em 0.333333em 0.229em; /* 4 */ + -fx-shape: "M 0 -3.5 L 4 0 L 0 3.5 z"; +} +.tree-cell:expanded > .tree-disclosure-node > .arrow, +.tree-table-row-cell:expanded > .tree-disclosure-node > .arrow { + -fx-rotate: 90; +} + +/******************************************************************************* + * * + * TableView * + * * + ******************************************************************************/ + +.table-view, +.tree-table-view { + /* Constants used throughout the tableview. */ + -fx-table-header-border-color: -fx-box-border; + -fx-table-cell-border-color: derive(-fx-color,5%); +} +/***** ROW CELLS **************************************************************/ +/* Each row in the table is a table-row-cell. Inside a table-row-cell is any + number of table-cell. */ +.table-row-cell { + -fx-background: -fx-control-inner-background; + -fx-background-color: -fx-table-cell-border-color, -fx-background; + -fx-background-insets: 0, 0 0 1 0; + -fx-padding: 0; + -fx-text-fill: -fx-text-background-color; +} +.table-row-cell:odd { + -fx-background: -fx-control-inner-background-alt; +} +/***** INDIVIDUAL CELLS ********************************************************/ +.table-cell { + -fx-padding: 0.166667em; /* 2px, plus border adds 1px */ + -fx-background-color: null; + -fx-border-color: transparent -fx-table-cell-border-color transparent transparent; + -fx-cell-size: 2.0em; /* 24 */ + -fx-text-fill: -fx-text-background-color; +} +.table-view > .virtual-flow > .clipped-container > .sheet > .table-row-cell .table-cell:selected, +.tree-table-view > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell .tree-table-cell:selected { + -fx-background-color: -fx-table-cell-border-color, -fx-background; + -fx-background-insets: 0, 0 0 1 0; +} +/* When in constrained resize mode, the right-most visible cell should not have + a right-border, as it is not possible to get this cleanly out of view without + introducing horizontal scrollbars (see RT-14886). */ +.table-view:constrained-resize > .virtual-flow > .clipped-container > .sheet > .table-row-cell > .table-cell:last-visible, +.tree-table-view:constrained-resize > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell > .tree-table-cell:last-visible { + -fx-border-color: transparent; +} +/***** HEADER **********************************************************************/ +/* The column-resize-line is shown when the user is attempting to resize a column. */ +.table-view .column-resize-line, +.tree-table-view .column-resize-line { + -fx-background: -fx-accent; + -fx-background-color: -fx-background; + -fx-padding: 0.0em 0.0416667em 0.0em 0.0416667em; /* 0 0.571429 0 0.571429 */ +} +/* This is the area behind the column headers. An ideal place to specify background + and border colors for the whole area (not individual column-header's). */ +.table-view .column-header-background, +.tree-table-view > .column-header-background { + -fx-background-color: -fx-inner-border, -fx-body-color; + -fx-background-insets: 0, 1; +} +/* The column header row is made up of a number of column-header, one for each + TableColumn, and a 'filler' area that extends from the right-most column + to the edge of the tableview, or up to the 'column control' button. */ +.table-view .column-header, +.tree-table-view .column-header, +.table-view .filler, +.tree-table-view .filler, +.table-view > .column-header-background > .show-hide-columns-button, +.tree-table-view > .column-header-background > .show-hide-columns-button, +.table-view:constrained-resize .filler, +.tree-table-view:constrained-resize .filler { + -fx-background-color: -fx-box-border, -fx-inner-border, -fx-body-color; + -fx-background-insets: 0, 0 1 1 0, 1 2 2 1; + -fx-font-weight: bold; + -fx-size: 2em; + -fx-text-fill: -fx-selection-bar-text; + -fx-padding: 0.166667em; +} +.table-view .column-header .context-menu, +.tree-table-view .column-header .context-menu, +.table-view > .column-header-background > .show-hide-columns-button .context-menu, +.tree-table-view > .column-header-background > .show-hide-columns-button .context-menu { + -fx-font-weight: null; +} +.table-view .filler, +.tree-table-view .filler, +.table-view:constrained-resize .filler, +.tree-table-view:constrained-resize .filler { + -fx-background-insets: 0, 0 0 1 0, 1 1 2 1; +} +.table-view > .column-header-background > .show-hide-columns-button, +.tree-table-view > .column-header-background > .show-hide-columns-button { + -fx-background-insets: 0, 0 0 1 1, 1 1 2 2; +} +.table-view .column-header .sort-order-dots-container, +.tree-table-view .column-header .sort-order-dots-container{ + -fx-padding: 2 0 2 0; +} +.table-view .column-header .sort-order, +.tree-table-view .column-header .sort-order{ + -fx-font-size: 0.916667em; /* 11pt - 1 less than the default font */ +} +.table-view .column-header .sort-order-dot, +.tree-table-view .column-header .sort-order-dot { + -fx-background-color: -fx-mark-color; + -fx-padding: 0.115em; + -fx-background-radius: 0.115em; +} +.table-view .column-header .label, +.tree-table-view .column-header .label { + -fx-alignment: center; +} + +/* Plus Symbol */ +.table-view .show-hide-column-image, +.tree-table-view .show-hide-column-image { + -fx-background-color: -fx-mark-color; + -fx-padding: 0.25em; /* 3px */ + -fx-shape: "M398.902,298.045c0.667,0,1.333,0,2,0c0,0.667,0,1.333,0,2c0.667,0,1.333,0,2,0c0,0.667,0,1.333,0,2c-0.667,0-1.333,0-2,0c0,0.666,0,1.332,0,1.999c-0.667,0-1.333,0-2,0c0-0.667,0-1.333,0-1.999c-0.666,0-1.333,0-1.999,0c0-0.667,0-1.334,0-2c0.666,0,1.333,0,1.999,0C398.902,299.378,398.902,298.711,398.902,298.045z"; +} +/* When a column is being 'dragged' to be placed in a different position, there + is a region that follows along the column header area to indicate where the + column will be dropped. This region can be styled using the .column-drag-header + name. */ +.table-view .column-drag-header, +.tree-table-view .column-drag-header { + -fx-background: -fx-accent; + -fx-background-color: -fx-selection-bar; + -fx-border-color: transparent; + -fx-opacity: 0.6; +} +/* Semi-transparent overlay to indicate the column that is currently being moved */ +.table-view .column-overlay, +.tree-table-view .column-overlay { + -fx-background-color: darkgray; + -fx-opacity: 0.3; +} +/* Header Sort Arrows */ +.table-view /*> column-header-background > nested-column-header >*/ .arrow, +.tree-table-view /*> column-header-background > nested-column-header >*/ .arrow { + -fx-background-color: -fx-mark-color; + -fx-padding: 0.25em 0.3125em 0.25em 0.3125em; /* 3 3.75 3 3.75 */ + -fx-shape: "M 0 0 h 7 l -3.5 4 z"; +} +/* This is shown when the table has no rows and/or no columns. */ +.table-view .empty-table, +.tree-table-view .empty-table { + -fx-background-color: white; + -fx-font-size: 1.166667em; /* 14pt - 2 more than the default font */ +} + +/******************************************************************************* + * * + * Table Cells * + * * + ******************************************************************************/ + +.check-box-table-cell { + -fx-alignment: center; + -fx-padding: 0; +} +.check-box-table-cell > .check-box { + -fx-font-size: 0.8em; + -fx-opacity: 1; + -fx-padding: 0 0 1 0; +} +.check-box-table-cell > .check-box > .box { + -fx-background-color: -fx-outer-border, -fx-background; + -fx-background-insets: 0,1; +} +.check-box-table-cell > .check-box:focused > .box { + -fx-background-color: -fx-focus-color, -fx-outer-border, -fx-background; + -fx-background-insets: -0.2, 1, 1.6; + -fx-background-radius: 3, 2, 1; +} +.check-box-table-cell > .check-box:selected > .box > .mark { + -fx-background-color: -fx-text-background-color; + -fx-background-insets: 0; +} +.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .check-box-table-cell:selected > .check-box > .box, +.tree-table-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled > .check-box-table-cell:selected > .check-box > .box, +.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled:selected > .check-box-table-cell > .check-box > .box, +.tree-table-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:selected > .check-box-table-cell > .check-box > .box { + -fx-background-color: derive(-fx-accent,40%), -fx-background; +} + +/******************************************************************************* + * * + * TreeTableView * + * * + * Note: A lot of the CSS for TreeTableView is included with the TreeView and * + * TableView CSS styles elsewhere in modena.css (as they are the same, just * + * targeting different CSS style classes). * + ******************************************************************************/ + +.tree-table-row-cell { + -fx-background: -fx-control-inner-background; + -fx-background-color: -fx-background; + -fx-padding: 0; + -fx-text-fill: -fx-text-background-color; + -fx-indent: 1em; +} +.tree-table-cell { + /* tree-table-cell needs slightly different padding to make the text sit at + the right height for the arrow */ + -fx-padding: 0.25em 0.166667em 0.083em 0.166667em; /* 3 2 1 2 , plus border adds 1px */ + -fx-background-color: null; + -fx-border-color: transparent -fx-table-cell-border-color transparent transparent; + -fx-cell-size: 2.0em; /* 24 */ + -fx-text-fill: -fx-text-background-color; +} + +/******************************************************************************* + * * + * Tooltip * + * * + ******************************************************************************/ + +.tooltip { + -fx-background: rgba(30,30,30); + -fx-text-fill: white; + -fx-background-color: rgba(30,30,30,0.8); + -fx-background-radius: 6px; + -fx-background-insets: 0; + -fx-padding: 0.667em 0.75em 0.667em 0.75em; /* 10px */ + -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.5) , 10, 0.0 , 0 , 3 ); + -fx-font-size: 0.85em; +} + +/******************************************************************************* + * * + * Charts * + * * + ******************************************************************************/ + +.chart { + -fx-padding: 5px; +} +.chart-plot-background { + -fx-background-color: -fx-background; +} +.chart-content { + -fx-padding: 10px; +} +.chart-title { + -fx-font-size: 1.4em; +} +.chart-legend { + -fx-background-color: -fx-shadow-highlight-color, + linear-gradient(to bottom, derive(-fx-background, -10%), derive(-fx-background, -5%)), + linear-gradient(from 0px 0px to 0px 4px, derive(-fx-background, -4%), derive(-fx-background, 10%)); + -fx-background-insets: 0 0 -1 0, 0,1; + -fx-background-radius: 4,4,3; + -fx-padding: 6px; +} + +/******************************************************************************* + * * + * Axis * + * * + ******************************************************************************/ + +.axis { + AXIS_COLOR: derive(-fx-background,-20%); + -fx-tick-label-font-size: 0.833333em; /* 10px */ + -fx-tick-label-fill: derive(-fx-text-background-color, 30%); +} +.axis:top { + -fx-border-color: transparent transparent AXIS_COLOR transparent; +} +.axis:right { + -fx-border-color: transparent transparent transparent AXIS_COLOR; +} +.axis:bottom { + -fx-border-color: AXIS_COLOR transparent transparent transparent; +} +.axis:left { + -fx-border-color: transparent AXIS_COLOR transparent transparent; +} +.axis:top > .axis-label, +.axis:left > .axis-label { + -fx-padding: 0 0 4px 0; +} +.axis:bottom > .axis-label, +.axis:right > .axis-label { + -fx-padding: 4px 0 0 0; +} +.axis-tick-mark, +.axis-minor-tick-mark { + -fx-fill: null; + -fx-stroke: AXIS_COLOR; +} + +/******************************************************************************* + * * + * ChartPlot * + * * + ******************************************************************************/ + +.chart-vertical-grid-lines { + -fx-stroke: derive(-fx-background,-10%); + -fx-stroke-dash-array: 0.25em, 0.25em; +} +.chart-horizontal-grid-lines { + -fx-stroke: derive(-fx-background,-10%); + -fx-stroke-dash-array: 0.25em, 0.25em; +} +.chart-alternative-column-fill { + -fx-fill: null; + -fx-stroke: null; +} +.chart-alternative-row-fill { + -fx-fill: null; + -fx-stroke: null; +} +.chart-vertical-zero-line, +.chart-horizontal-zero-line { + -fx-stroke: derive(-fx-text-background-color, 40%); +} + +/******************************************************************************* + * * + * ScatterChart * + * * + ******************************************************************************/ + +.chart-symbol { /* solid circle */ + -fx-background-color: CHART_COLOR_1; + -fx-background-radius: 5px; + -fx-padding: 5px; +} +.default-color1.chart-symbol { /* solid square */ + -fx-background-color: CHART_COLOR_2; + -fx-background-radius: 0; +} +.default-color2.chart-symbol { /* solid diamond */ + -fx-background-color: CHART_COLOR_3; + -fx-background-radius: 0; + -fx-padding: 7px 5px 7px 5px; + -fx-shape: "M5,0 L10,9 L5,18 L0,9 Z"; +} +.default-color3.chart-symbol { /* cross */ + -fx-background-color: CHART_COLOR_4; + -fx-background-radius: 0; + -fx-background-insets: 0; + -fx-shape: "M2,0 L5,4 L8,0 L10,0 L10,2 L6,5 L10,8 L10,10 L8,10 L5,6 L2,10 L0,10 L0,8 L4,5 L0,2 L0,0 Z"; +} +.default-color4.chart-symbol { /* solid triangle */ + -fx-background-color: CHART_COLOR_5; + -fx-background-radius: 0; + -fx-background-insets: 0; + -fx-shape: "M5,0 L10,8 L0,8 Z"; +} +.default-color5.chart-symbol { /* hollow circle */ + -fx-background-color: CHART_COLOR_6, white; + -fx-background-insets: 0, 2; + -fx-background-radius: 5px; + -fx-padding: 5px; +} +.default-color6.chart-symbol { /* hollow square */ + -fx-background-color: CHART_COLOR_7, white; + -fx-background-insets: 0, 2; + -fx-background-radius: 0; +} +.default-color7.chart-symbol { /* hollow diamond */ + -fx-background-color: CHART_COLOR_8, white; + -fx-background-radius: 0; + -fx-background-insets: 0, 2.5; + -fx-padding: 7px 5px 7px 5px; + -fx-shape: "M5,0 L10,9 L5,18 L0,9 Z"; +} + +/******************************************************************************* + * * + * LineChart * + * * + ******************************************************************************/ + +.chart-line-symbol { + -fx-background-color: CHART_COLOR_1, white; + -fx-background-insets: 0, 2; + -fx-background-radius: 5px; + -fx-padding: 5px; +} +.chart-series-line { + -fx-stroke: CHART_COLOR_1; + -fx-stroke-width: 3px; +} +.default-color0.chart-line-symbol { -fx-background-color: CHART_COLOR_1, white; } +.default-color1.chart-line-symbol { -fx-background-color: CHART_COLOR_2, white; } +.default-color2.chart-line-symbol { -fx-background-color: CHART_COLOR_3, white; } +.default-color3.chart-line-symbol { -fx-background-color: CHART_COLOR_4, white; } +.default-color4.chart-line-symbol { -fx-background-color: CHART_COLOR_5, white; } +.default-color5.chart-line-symbol { -fx-background-color: CHART_COLOR_6, white; } +.default-color6.chart-line-symbol { -fx-background-color: CHART_COLOR_7, white; } +.default-color7.chart-line-symbol { -fx-background-color: CHART_COLOR_8, white; } +.default-color0.chart-series-line { -fx-stroke: CHART_COLOR_1; } +.default-color1.chart-series-line { -fx-stroke: CHART_COLOR_2; } +.default-color2.chart-series-line { -fx-stroke: CHART_COLOR_3; } +.default-color3.chart-series-line { -fx-stroke: CHART_COLOR_4; } +.default-color4.chart-series-line { -fx-stroke: CHART_COLOR_5; } +.default-color5.chart-series-line { -fx-stroke: CHART_COLOR_6; } +.default-color6.chart-series-line { -fx-stroke: CHART_COLOR_7; } +.default-color7.chart-series-line { -fx-stroke: CHART_COLOR_8; } + +/******************************************************************************* + * * + * AreaChart * + * * + ******************************************************************************/ + +.chart-area-symbol { + -fx-background-color: CHART_COLOR_1, white; + -fx-background-insets: 0, 1; + -fx-background-radius: 4px; /* makes sure this remains circular */ + -fx-padding: 3px; +} +.default-color0.chart-area-symbol { -fx-background-color: CHART_COLOR_1, white; } +.default-color1.chart-area-symbol { -fx-background-color: CHART_COLOR_2, white; } +.default-color2.chart-area-symbol { -fx-background-color: CHART_COLOR_3, white; } +.default-color3.chart-area-symbol { -fx-background-color: CHART_COLOR_4, white; } +.default-color4.chart-area-symbol { -fx-background-color: CHART_COLOR_5, white; } +.default-color5.chart-area-symbol { -fx-background-color: CHART_COLOR_6, white; } +.default-color6.chart-area-symbol { -fx-background-color: CHART_COLOR_7, white; } +.default-color7.chart-area-symbol { -fx-background-color: CHART_COLOR_8, white; } +.chart-series-area-line { + -fx-stroke: CHART_COLOR_1; + -fx-stroke-width: 1px; +} +.default-color0.chart-series-area-line { -fx-stroke: CHART_COLOR_1; } +.default-color1.chart-series-area-line { -fx-stroke: CHART_COLOR_2; } +.default-color2.chart-series-area-line { -fx-stroke: CHART_COLOR_3; } +.default-color3.chart-series-area-line { -fx-stroke: CHART_COLOR_4; } +.default-color4.chart-series-area-line { -fx-stroke: CHART_COLOR_5; } +.default-color5.chart-series-area-line { -fx-stroke: CHART_COLOR_6; } +.default-color6.chart-series-area-line { -fx-stroke: CHART_COLOR_7; } +.default-color7.chart-series-area-line { -fx-stroke: CHART_COLOR_8; } +.chart-series-area-fill { + -fx-stroke: null; + -fx-fill: CHART_COLOR_1_TRANS_20; +} +.default-color0.chart-series-area-fill { -fx-fill: CHART_COLOR_1_TRANS_20; } +.default-color1.chart-series-area-fill { -fx-fill: CHART_COLOR_2_TRANS_20; } +.default-color2.chart-series-area-fill { -fx-fill: CHART_COLOR_3_TRANS_20; } +.default-color3.chart-series-area-fill { -fx-fill: CHART_COLOR_4_TRANS_20; } +.default-color4.chart-series-area-fill { -fx-fill: CHART_COLOR_5_TRANS_20; } +.default-color5.chart-series-area-fill { -fx-fill: CHART_COLOR_6_TRANS_20; } +.default-color6.chart-series-area-fill { -fx-fill: CHART_COLOR_7_TRANS_20; } +.default-color7.chart-series-area-fill { -fx-fill: CHART_COLOR_8_TRANS_20; } +.area-legend-symbol { + -fx-padding: 6px; + -fx-background-radius: 6px; /* makes sure this remains circular */ + -fx-background-insets: 0, 3; +} + +/******************************************************************************* + * * + * BubbleChart * + * * + ******************************************************************************/ + +.bubble-legend-symbol { + -fx-background-radius: 8px; + -fx-padding: 8px; +} +.chart-bubble { + -fx-bubble-fill: CHART_COLOR_1_TRANS_70; + -fx-background-color: radial-gradient(center 50% 50%, radius 80%, derive(-fx-bubble-fill,20%), derive(-fx-bubble-fill,-30%)); +} +.default-color0.chart-bubble { -fx-bubble-fill: CHART_COLOR_1_TRANS_70; } +.default-color1.chart-bubble { -fx-bubble-fill: CHART_COLOR_2_TRANS_70; } +.default-color2.chart-bubble { -fx-bubble-fill: CHART_COLOR_3_TRANS_70; } +.default-color3.chart-bubble { -fx-bubble-fill: CHART_COLOR_4_TRANS_70; } +.default-color4.chart-bubble { -fx-bubble-fill: CHART_COLOR_5_TRANS_70; } +.default-color5.chart-bubble { -fx-bubble-fill: CHART_COLOR_6_TRANS_70; } +.default-color6.chart-bubble { -fx-bubble-fill: CHART_COLOR_7_TRANS_70; } +.default-color7.chart-bubble { -fx-bubble-fill: CHART_COLOR_8_TRANS_70; } + +/******************************************************************************* + * * + * BarChart * + * * + ******************************************************************************/ + +.chart-bar { + -fx-bar-fill: CHART_COLOR_1; + -fx-background-color: linear-gradient(to right, + derive(-fx-bar-fill, -4%), + derive(-fx-bar-fill, -1%), + derive(-fx-bar-fill, 0%), + derive(-fx-bar-fill, -1%), + derive(-fx-bar-fill, -6%) + ); + -fx-background-insets: 0; +} +.chart-bar.negative { + -fx-background-insets: 1 0 0 0; +} +.bar-chart:horizontal .chart-bar { + -fx-background-insets: 0 0 0 1; +} +.bar-chart:horizontal .chart-bar, +.stacked-bar-chart:horizontal .chart-bar { + -fx-background-color: linear-gradient(to bottom, + derive(-fx-bar-fill, -4%), + derive(-fx-bar-fill, -1%), + derive(-fx-bar-fill, 0%), + derive(-fx-bar-fill, -1%), + derive(-fx-bar-fill, -6%) + ); +} +.default-color0.chart-bar { -fx-bar-fill: CHART_COLOR_1; } +.default-color1.chart-bar { -fx-bar-fill: CHART_COLOR_2; } +.default-color2.chart-bar { -fx-bar-fill: CHART_COLOR_3; } +.default-color3.chart-bar { -fx-bar-fill: CHART_COLOR_4; } +.default-color4.chart-bar { -fx-bar-fill: CHART_COLOR_5; } +.default-color5.chart-bar { -fx-bar-fill: CHART_COLOR_6; } +.default-color6.chart-bar { -fx-bar-fill: CHART_COLOR_7; } +.default-color7.chart-bar { -fx-bar-fill: CHART_COLOR_8; } +.bar-legend-symbol { + -fx-padding: 8px; +} + +/******************************************************************************* + * * + * PieChart * + * * + ******************************************************************************/ + +.chart-pie { + -fx-pie-color: CHART_COLOR_1; + -fx-background-color: radial-gradient(radius 100%, derive(-fx-pie-color,20%), derive(-fx-pie-color,-10%)); + -fx-background-insets: 1; + -fx-border-color: -fx-background; +} +.chart-pie-label { + -fx-padding: 3px; + -fx-fill: -fx-text-base-color; +} +.chart-pie-label-line { + -fx-stroke: derive(-fx-background,-20%); +} +.default-color0.chart-pie { -fx-pie-color: CHART_COLOR_1; } +.default-color1.chart-pie { -fx-pie-color: CHART_COLOR_2; } +.default-color2.chart-pie { -fx-pie-color: CHART_COLOR_3; } +.default-color3.chart-pie { -fx-pie-color: CHART_COLOR_4; } +.default-color4.chart-pie { -fx-pie-color: CHART_COLOR_5; } +.default-color5.chart-pie { -fx-pie-color: CHART_COLOR_6; } +.default-color6.chart-pie { -fx-pie-color: CHART_COLOR_7; } +.default-color7.chart-pie { -fx-pie-color: CHART_COLOR_8; } +.negative.chart-pie { + -fx-pie-color: transparent; + -fx-background-color: white; +} +.pie-legend-symbol.chart-pie { + -fx-background-radius: 8px; + -fx-padding: 8px; + -fx-border-color: null; +} + +/******************************************************************************* + * * + * Combinations * + * * + * This section is for special handling of when one control is nested inside * + * another control. There are many cases where we would end up with ugly * + * double borders that are fixed here. * + * * + ******************************************************************************/ + +.tab-pane > * > .table-view, +.tab-pane > * > .tree-table-view, +.tab-pane > * > .list-view, +.tab-pane > * > .tree-view, +.tab-pane > * > .scroll-pane, +.tab-pane > * > .split-pane, +.tab-pane > * > .text-area, +.tab-pane > * > .html-editor, +.split-pane > * > .tab-pane, +.split-pane > * > .table-view, +.split-pane > * > .tree-table-view, +.split-pane > * > .list-view, +.split-pane > * > .tree-view, +.split-pane > * > .scroll-pane, +.split-pane > * > .split-pane, +.split-pane > * > .text-area, +.split-pane > * > .html-editor { + -fx-background-insets: 0, 0; + -fx-padding: 0; +} +.tab-pane > * > .scroll-pane > .corner { + -fx-background-insets: 0; /* Fix for RT-35067 */ +} +.tab-pane.floating > * > .table-view, +.tab-pane.floating > * > .tree-table-view, +.tab-pane.floating > * > .list-view, +.tab-pane.floating > * > .tree-view, +.tab-pane.floating > * > .scroll-pane, +.tab-pane.floating > * > .split-pane, +.tab-pane.floating > * > .text-area, +.tab-pane.floating > * > .html-editor { + -fx-background-insets: 0, 0; + -fx-padding: -1; +} +.split-pane > * > .accordion > .titled-pane > *.content { + -fx-border-color: null; + -fx-border-insets: 0; +} +.split-pane > * > .accordion > .titled-pane > .title { + -fx-background-insets: 0,1 0 1 0, 2 1 2 1; +} +.split-pane > * > .accordion > .first-titled-pane > .title { + -fx-background-insets: 0,0 0 1 0, 1 1 2 1; +} +.split-pane > * > .accordion > .titled-pane:collapsed > .title { + -fx-background-insets: 0,1 0 0 0, 2 1 1 1; +} +.split-pane > * > .accordion > .first-titled-pane:collapsed > .title { + -fx-background-insets: 0,0 0 0 0, 1 1 1 1; +} +.titled-pane > .content > .split-pane, +.titled-pane > .content > .text-area, +.titled-pane > .content > .html-editor, +.titled-pane > .content > .list-view, +.titled-pane > .content > .tree-view, +.titled-pane > .content > .table-view, +.titled-pane > .content > .tree-table-view, +.titled-pane > .content > .scroll-pane { + -fx-background-color: null; + -fx-background-insets: 0, 0; + -fx-padding: 0; +} + +.titled-pane > .content > AnchorPane, +.titled-pane > .content > BorderPane, +.titled-pane > .content > FlowPane, +.titled-pane > .content > GridPane, +.titled-pane > .content > HBox, +.titled-pane > .content > Pane, +.titled-pane > .content > StackPane, +.titled-pane > .content > TilePane, +.titled-pane > .content > VBox { + -fx-padding: 0.8em; +} + +/******************************************************************************* + * * + * DatePicker * + * * + ******************************************************************************/ + +.date-picker > .arrow-button > .arrow { + -fx-shape: "M0,0v9h9V0H0z M2,8H1V7h1V8z M2,6H1V5h1V6z M2,4H1V3h1V4z M4,8H3V7h1V8z M4,6H3V5h1V6z M4,4H3V3h1V4z M6,8H5V7h1V8z M6,6H5 V5h1V6z M6,4H5V3h1V4z M8,8H7V7h1V8z M8,6H7V5h1V6z M8,4H7V3h1V4z"; + -fx-background-color: -fx-mark-highlight-color, -fx-mark-color; + -fx-background-insets: 1 0 -1 0, 0; + -fx-padding: 0.416667em 0.416667em 0.333333em 0.333333em; /* 5 5 4 4 */ + -fx-scale-shape: true; +} + +.date-picker-popup { + -fx-background-color: + linear-gradient(to bottom, + derive(-fx-color,-17%), + derive(-fx-color,-30%) + ), + -fx-control-inner-background; + -fx-background-insets: 0, 1; + -fx-background-radius: 0; + -fx-alignment: CENTER; /* VBox */ + -fx-spacing: 0; /* VBox */ + -fx-padding: 0.083333em; /* 1 1 1 1 */ + -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.2) , 12, 0.0 , 0 , 8 ); +} +.date-picker-popup > .month-year-pane { + -fx-padding: 0.588883em 0.5em 0.666667em 0.5em; /* 7 6 8 6 */ + -fx-background-color: derive(-fx-box-border,30%), linear-gradient(to bottom, derive(-fx-base,-3%), derive(-fx-base,5%) 50%, derive(-fx-base,-3%)); + -fx-background-insets: 0 0 0 0, 0 0 1 0; +} +.date-picker-popup > * > .spinner { + -fx-spacing: 0.25em; /* 3 */ + -fx-alignment: CENTER; + -fx-fill-height: false; + -fx-background-color: transparent; +} +.date-picker-popup > * > .spinner > .button { + -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; + -fx-background-insets: 0, 1, 2; + -fx-color: transparent; + -fx-background-radius: 0; +} +.date-picker-popup > * > .spinner > .button:focused { + -fx-background-color: -fx-focus-color, -fx-inner-border, -fx-body-color, -fx-faint-focus-color, -fx-body-color; + -fx-color: -fx-hover-base; + -fx-background-insets: -0.2, 1, 2, -1.4, 2.6; +} +.date-picker-popup > * > .spinner > .button:hover { + -fx-color: -fx-hover-base; +} +.date-picker-popup > * > .spinner > .button:armed { + -fx-color: -fx-pressed-base; +} +.date-picker-popup > * > .spinner > .left-button { + -fx-padding: 0 0.333333em 0 0.25em; /* 0 4 0 3 */ +} +.date-picker-popup > * > .spinner > .right-button { + -fx-padding: 0 0.25em 0 0.333333em; /* 0 3 0 4 */ +} +.date-picker-popup > * > .spinner > .button > .left-arrow, +.date-picker-popup > * > .spinner > .button > .right-arrow { + -fx-background-color: -fx-mark-highlight-color, derive(-fx-base,-45%); + -fx-background-insets: 1 0 -1 0, 0; + -fx-padding: 0.333333em 0.166667em 0.333333em 0.166667em; /* 4 2 4 2 */ + -fx-effect: dropshadow(two-pass-box , -fx-shadow-highlight-color, 1, 0.0 , 0, 1.4); +} +.date-picker-popup > * > .spinner > .button:hover > .left-arrow, +.date-picker-popup > * > .spinner > .button:hover > .right-arrow { + -fx-background-color: -fx-mark-highlight-color, derive(-fx-base,-50%); +} +.date-picker-popup > * > .spinner > .button:pressed > .left-arrow, +.date-picker-popup > * > .spinner > .button:pressed > .right-arrow { + -fx-background-color: -fx-mark-highlight-color, derive(-fx-base,-55%); +} +.date-picker-popup > * > .spinner > .button > .left-arrow { + -fx-padding: 0.333333em 0.25em 0.333333em 0.166667em; /* 4 3 4 2 */ + -fx-shape: "M5.997,5.072L5.995,6.501l-2.998-4l2.998-4l0.002,1.43l-1.976,2.57L5.997,5.072z"; + -fx-scale-shape: true; +} +.date-picker-popup > * > .spinner > .button > .right-arrow { + -fx-padding: 0.333333em 0.25em 0.333333em 0.166667em; /* 4 3 4 2 */ + -fx-shape: "M2.998-0.07L3-1.499l2.998,4L3,6.501l-0.002-1.43l1.976-2.57L2.998-0.07z"; + -fx-scale-shape: true; +} +.date-picker-popup > * > .spinner > .label { + -fx-alignment: CENTER; +} +.date-picker-popup > .month-year-pane > .secondary-label { + -fx-alignment: BASELINE_CENTER; + -fx-padding: 0.5em 0 0 0; /* 6 0 0 0 */ + -fx-text-fill: #f3622d; +} + +.date-picker-popup > .calendar-grid { + -fx-background-color: derive(-fx-selection-bar-non-focused, 60%); + /*-fx-background-insets: 1 0 0 0;*/ + -fx-padding: 0; +} +.date-picker-popup > * > .date-cell { + -fx-background-color: transparent; + -fx-background-insets: 1, 2; + -fx-padding: 0; + -fx-alignment: BASELINE_CENTER; + -fx-opacity: 1.0; +} +.date-picker-popup > * > .day-name-cell, +.date-picker-popup > * > .week-number-cell { + -fx-font-size: 0.916667em; +} +.date-picker-popup > * > .week-number-cell { + -fx-padding: 0.333333em 0.583333em 0.333333em 0.583333em; /* 4 7 4 7 */ + -fx-border-color: -fx-control-inner-background; + -fx-border-width: 1px; + -fx-background: -fx-control-inner-background; + -fx-background-color: -fx-background; + -fx-text-fill: -fx-accent; +} +.date-picker-popup > * > .day-cell { + -fx-padding: 0.333333em 0.583333em 0.333333em 0.583333em; /* 4 7 4 7 */ + -fx-border-color: derive(-fx-selection-bar-non-focused, 60%); + -fx-border-width: 1px; + -fx-font-size: 1em; + -fx-background: -fx-control-inner-background; + -fx-background-color: -fx-background; + -fx-text-fill: -fx-text-background-color; +} +.date-picker-popup > * > .hijrah-day-cell { + -fx-alignment: TOP_LEFT; + -fx-padding: 0.083333em 0.333333em 0.083333em 0.333333em; /* 1 4 1 4 */ + -fx-cell-size: 2.75em; +} +.date-picker-popup > * > .day-cell > .secondary-text { + -fx-fill: #f3622d; +} +.date-picker-popup > * > .today { + -fx-background-color: -fx-control-inner-background, derive(-fx-selection-bar-non-focused, -20%), -fx-control-inner-background; + -fx-background-insets: 1, 2, 3; +} +.date-picker-popup > * > .day-cell:hover, +.date-picker-popup > * > .selected, +.date-picker-popup > * > .previous-month.selected, +.date-picker-popup > * > .next-month.selected { + -fx-background: -fx-selection-bar; +} +.date-picker-popup > * > .previous-month:hover, +.date-picker-popup > * > .next-month:hover { + -fx-background: -fx-selection-bar-non-focused; +} +.date-picker-popup > * > .today:hover, +.date-picker-popup > * > .today.selected { + -fx-background-color: -fx-selection-bar, derive(-fx-selection-bar-non-focused, -20%),-fx-selection-bar; +} +.date-picker-popup > * > .day-cell:focused, +.date-picker-popup > * > .today:focused { + -fx-background-color: -fx-control-inner-background, -fx-cell-focus-inner-border, -fx-control-inner-background; + -fx-background-insets: 1, 2, 3; +} +.date-picker-popup > * > .day-cell:focused:hover, +.date-picker-popup > * > .today:focused:hover, +.date-picker-popup > * > .selected:focused, +.date-picker-popup > * > .today.selected:focused { + -fx-background-color: -fx-selection-bar, -fx-cell-focus-inner-border, -fx-selection-bar; +} +.date-picker-popup > * > .previous-month, +.date-picker-popup > * > .next-month { + -fx-background: derive(-fx-control-inner-background, -4%); +} +.date-picker-popup > * > .day-cell:hover > .secondary-text, +.date-picker-popup > * > .previous-month > .secondary-text, +.date-picker-popup > * > .next-month > .secondary-text, +.date-picker-popup > * > .selected > .secondary-text { + -fx-fill: -fx-text-background-color; +} +.date-picker-popup > * > .previous-month.today, +.date-picker-popup > * > .next-month.today { + -fx-background-color: derive(-fx-control-inner-background, -4%), derive(-fx-selection-bar-non-focused, -20%), derive(-fx-control-inner-background, -4%); +} + +.date-picker-popup > * > .previous-month.today:hover, +.date-picker-popup > * > .next-month.today:hover { + -fx-background-color: -fx-selection-bar-non-focused, derive(-fx-selection-bar-non-focused, -20%), -fx-selection-bar-non-focused; +} + +/******************************************************************************* + * * + * Spinner * + * * + ******************************************************************************/ + +.spinner { + -fx-background-color: + linear-gradient(to bottom, derive(-fx-text-box-border, -10%), -fx-text-box-border), + linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background); + -fx-background-insets: 0, 1; + -fx-background-radius: 3, 2; +} +.spinner:focused, +.spinner:contains-focus { + -fx-background-color: -fx-focus-color, -fx-inner-border, -fx-body-color, -fx-faint-focus-color, -fx-body-color; + -fx-background-insets: -0.2, 1, 2, -1.4, 2.6; + -fx-background-radius: 3, 2, 1, 4, 1; +} +.spinner > .text-field { + -fx-background-color: + linear-gradient(to bottom, derive(-fx-text-box-border, -10%), -fx-text-box-border), + linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background); + -fx-background-insets: 0, 1 0 1 1; + -fx-background-radius: 3 0 0 3, 2 0 0 2; +} +.spinner:focused > .text-field, +.spinner:contains-focus > .text-field { + -fx-background-color: + -fx-control-inner-background, + -fx-faint-focus-color, + linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background); + -fx-background-insets: 1 0 1 1, 1 0 1 1, 3 2 3 3; + -fx-background-radius: 2 0 0 2, 1 0 0 1, 0; +} + +.spinner .increment-arrow-button { + -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; + /*Change the two 0's here to -1 to get rid of the horizontal line */ + -fx-background-insets: 0 0 -1 0, 1 1 0 1, 2 2 1 2; + -fx-background-radius: 0 3 0 0, 0 2 0 0, 0 1 0 0; + -fx-padding: 0.333335em 0.666667em 0.333335em 0.666667em; /* 5 8 3 8 */ +} +.spinner .decrement-arrow-button { + -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; + -fx-background-insets: 0, 1 1 1 1, 1 2 2 2; + -fx-background-radius: 0 0 3 0, 0 0 2 0, 0 0 1 0; + -fx-padding: 0.333335em 0.666667em 0.333335em 0.666667em; /* 3 8 5 8 */ +} +.spinner:focused .increment-arrow-button, +.spinner:contains-focus .increment-arrow-button, +.spinner:focused .decrement-arrow-button, +.spinner:contains-focus .decrement-arrow-button { + -fx-background-color: -fx-focus-color, -fx-body-color, -fx-faint-focus-color, -fx-body-color; +} + +.spinner .increment-arrow-button .increment-arrow { + -fx-background-color: -fx-mark-highlight-color, -fx-mark-color; + -fx-background-insets: 0 0 -1 0, 0; + -fx-padding: 0.166667em 0.333333em 0.166667em 0.333333em; /* 2 4 2 4 */ + -fx-shape: "M 0 4 h 7 l -3.5 -4 z"; +} +.spinner .decrement-arrow-button .decrement-arrow { + -fx-background-color: -fx-mark-highlight-color, -fx-mark-color; + -fx-background-insets: 0 0 -1 0, 0; + -fx-padding: 0.166667em 0.333333em 0.166667em 0.333333em; /* 2 4 2 4 */ + -fx-shape: "M 0 0 h 7 l -3.5 4 z"; +} + +/* Spinner - Horizontal arrows */ +.spinner.split-arrows-horizontal .increment-arrow-button .increment-arrow, +.spinner.arrows-on-right-horizontal .increment-arrow-button .increment-arrow, +.spinner.arrows-on-left-horizontal .increment-arrow-button .increment-arrow { + -fx-padding: 0.333333em 0.166667em 0.333333em 0.166667em; /* 4 2 4 2 */ + -fx-shape: "M 0 0 v 7 l 3.5 -4 z"; +} +.spinner.split-arrows-horizontal .decrement-arrow-button .decrement-arrow, +.spinner.arrows-on-right-horizontal .decrement-arrow-button .decrement-arrow, +.spinner.arrows-on-left-horizontal .decrement-arrow-button .decrement-arrow { + -fx-padding: 0.333333em 0.166667em 0.333333em 0.166667em; /* 4 2 4 2 */ + -fx-shape: "M 4 0 v 7 l -4 -3.5 z"; +} + +/* Spinner - STYLE_CLASS_ARROWS_ON_RIGHT_HORIZONTAL */ +.spinner.arrows-on-right-horizontal .increment-arrow-button { + -fx-background-radius: 0 3 3 0, 0 2 2 0, 0 1 1 0; + -fx-background-insets: 0 0 0 -1, 1 1 1 0, 2 2 2 1; +} +.spinner.arrows-on-right-horizontal .decrement-arrow-button { + -fx-background-radius: 0; + -fx-background-insets: 0, 1, 2; +} + +/* Spinner - STYLE_CLASS_ARROWS_ON_LEFT_VERTICAL */ +.spinner.arrows-on-left-vertical > .text-field { + -fx-background-insets: 0, 1 1 1 0; + -fx-background-radius: 0 3 3 0, 0 2 2 0; +} +.spinner.arrows-on-left-vertical .increment-arrow-button { + -fx-background-radius: 3 0 0 0, 2 0 0 0, 1 0 0 0; +} +.spinner.arrows-on-left-vertical .decrement-arrow-button { + -fx-background-radius: 0 0 0 3, 0 0 0 2, 0 0 0 1; +} + +/* Spinner - STYLE_CLASS_ARROWS_ON_LEFT_HORIZONTAL */ +.spinner.arrows-on-left-horizontal > .text-field { + -fx-background-insets: 0, 1 1 1 0; + -fx-background-radius: 0 3 3 0, 0 2 2 0; +} +.spinner.arrows-on-left-horizontal .increment-arrow-button { + -fx-background-insets: 0 0 0 -1, 1 1 1 0, 2 2 2 1; + -fx-background-radius: 0; +} +.spinner.arrows-on-left-horizontal .decrement-arrow-button { + -fx-background-insets: 0, 1, 2; + -fx-background-radius: 3 0 0 3, 2 0 0 2, 1 0 0 1; +} +.spinner.arrows-on-left-vertical:focused > .text-field, +.spinner.arrows-on-left-vertical:contains-focus > .text-field, +.spinner.arrows-on-left-horizontal:focused > .text-field, +.spinner.arrows-on-left-horizontal:contains-focus > .text-field { + -fx-background-insets: 1 1 1 0, 1 1 1 0, 3 3 3 2; +} + +/* Spinner - STYLE_CLASS_SPLIT_ARROWS_VERTICAL */ +.spinner.split-arrows-vertical > .text-field { + -fx-background-insets: 0, 0 1 0 1; + -fx-background-radius: 0, 0; +} +.spinner.split-arrows-vertical .increment-arrow-button { + -fx-background-insets: 0, 1, 2; + -fx-background-radius: 3 3 0 0, 2 2 0 0, 1 1 0 0; +} +.spinner.split-arrows-vertical .decrement-arrow-button { + -fx-background-insets: 0, 1, 2; + -fx-background-radius: 0 0 3 3, 0 0 2 2, 0 0 1 1; +} +.spinner.split-arrows-vertical:focused > .text-field, +.spinner.split-arrows-vertical:contains-focus > .text-field { + -fx-background-insets: 0 1 0 1, 0 1 0 1, 2 3 2 3; +} + +/* Spinner - STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL */ +.spinner.split-arrows-horizontal > .text-field { + -fx-background-insets: 0, 1 0 1 0; + -fx-background-radius: 0, 0; +} +.spinner.split-arrows-horizontal .increment-arrow-button { + -fx-background-insets: 0, 1, 2; + -fx-background-radius: 0 3 3 0, 0 2 2 0, 0 1 1 0; +} +.spinner.split-arrows-horizontal .decrement-arrow-button { + -fx-background-insets: 0, 1, 2; + -fx-background-radius: 3 0 0 3, 2 0 0 2, 1 0 0 1; +} +.spinner.split-arrows-horizontal:focused > .text-field, +.spinner.split-arrows-horizontal:contains-focus > .text-field { + -fx-background-insets: 1 0 1 0, 1 0 1 0, 3 2 3 2; +} + +/******************************************************************************* + * * + * Dialog * + * * + ******************************************************************************/ + +.dialog-pane { + -fx-background-color: -fx-background; + -fx-padding: 0; +} + +.dialog-pane > .expandable-content { + -fx-padding: 0.666em; /* 8px */ +} + +.dialog-pane > .button-bar > .container { + -fx-padding: 0.833em; /* 10px */ +} + +.dialog-pane > .content.label { + -fx-alignment: top-left; + -fx-padding: 1.333em 0.833em 0 0.833em; /* 16px 10px 0px 10px */ +} + +.dialog-pane > .content { + -fx-padding: 0.833em; /* 10 */ +} + +.dialog-pane:no-header .graphic-container { + -fx-padding: 0.833em 0 0 0.833em; /* 10px 0px 0px 10px */ +} + +.dialog-pane:header .header-panel { + /*-fx-padding: 0.833em 1.166em 0.833em 1.166em; *//* 10px 14px 10px 14px */ + -fx-padding: 0.833em; /* 10px */ + -fx-background-color: -fx-box-border, linear-gradient(-fx-background, derive(-fx-background, 30%)); + -fx-background-insets: 0, 0 0 1 0; +} + +.dialog-pane:header .header-panel .label { + -fx-font-size: 1.167em; /* 14px */ + -fx-wrap-text: true; +} + +.dialog-pane:header .header-panel .graphic-container { + /* This prevents the text in the header running directly into the graphic */ + -fx-padding: 0 0 0 0.833em; /* 0px 0px 0px 10px */ +} + +.dialog-pane > .button-bar > .container > .details-button { + -fx-alignment: baseline-left; + -fx-focus-traversable: false; + -fx-padding: 0.416em; /* 5px */ +} + +.dialog-pane > .button-bar > .container > .details-button.more { + -fx-graphic: url("dialog-more-details.png"); +} + +.dialog-pane > .button-bar > .container > .details-button.less { + -fx-graphic: url("dialog-fewer-details.png"); +} + +.dialog-pane > .button-bar > .container > .details-button:hover { + -fx-underline: true; +} + +.alert.confirmation.dialog-pane, +.text-input-dialog.dialog-pane, +.choice-dialog.dialog-pane { + -fx-graphic: url("dialog-confirm.png"); +} + +.alert.information.dialog-pane { + -fx-graphic: url("dialog-information.png"); +} + +.alert.error.dialog-pane { + -fx-graphic: url("dialog-error.png"); +} + +.alert.warning.dialog-pane { + -fx-graphic: url("dialog-warning.png"); +} diff --git a/client/src/main/resources/css/页面-1.svg b/client/src/main/resources/css/页面-1.svg new file mode 100644 index 0000000..02605dc --- /dev/null +++ b/client/src/main/resources/css/页面-1.svg @@ -0,0 +1,8584 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/demo.css b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/demo.css new file mode 100644 index 0000000..a67054a --- /dev/null +++ b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/demo.css @@ -0,0 +1,539 @@ +/* Logo 字体 */ +@font-face { + font-family: "iconfont logo"; + src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); + src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); +} + +.logo { + font-family: "iconfont logo"; + font-size: 160px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* tabs */ +.nav-tabs { + position: relative; +} + +.nav-tabs .nav-more { + position: absolute; + right: 0; + bottom: 0; + height: 42px; + line-height: 42px; + color: #666; +} + +#tabs { + border-bottom: 1px solid #eee; +} + +#tabs li { + cursor: pointer; + width: 100px; + height: 40px; + line-height: 40px; + text-align: center; + font-size: 16px; + border-bottom: 2px solid transparent; + position: relative; + z-index: 1; + margin-bottom: -1px; + color: #666; +} + + +#tabs .active { + border-bottom-color: #f00; + color: #222; +} + +.tab-container .content { + display: none; +} + +/* 页面布局 */ +.main { + padding: 30px 100px; + width: 960px; + margin: 0 auto; +} + +.main .logo { + color: #333; + text-align: left; + margin-bottom: 30px; + line-height: 1; + height: 110px; + margin-top: -50px; + overflow: hidden; + *zoom: 1; +} + +.main .logo a { + font-size: 160px; + color: #333; +} + +.helps { + margin-top: 40px; +} + +.helps pre { + padding: 20px; + margin: 10px 0; + border: solid 1px #e7e1cd; + background-color: #fffdef; + overflow: auto; +} + +.icon_lists { + width: 100% !important; + overflow: hidden; + *zoom: 1; +} + +.icon_lists li { + width: 100px; + margin-bottom: 10px; + margin-right: 20px; + text-align: center; + list-style: none !important; + cursor: default; +} + +.icon_lists li .code-name { + line-height: 1.2; +} + +.icon_lists .icon { + display: block; + height: 100px; + line-height: 100px; + font-size: 42px; + margin: 10px auto; + color: #333; + -webkit-transition: font-size 0.25s linear, width 0.25s linear; + -moz-transition: font-size 0.25s linear, width 0.25s linear; + transition: font-size 0.25s linear, width 0.25s linear; +} + +.icon_lists .icon:hover { + font-size: 100px; +} + +.icon_lists .svg-icon { + /* 通过设置 font-size 来改变图标大小 */ + width: 1em; + /* 图标和文字相邻时,垂直对齐 */ + vertical-align: -0.15em; + /* 通过设置 color 来改变 SVG 的颜色/fill */ + fill: currentColor; + /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 + normalize.css 中也包含这行 */ + overflow: hidden; +} + +.icon_lists li .name, +.icon_lists li .code-name { + color: #666; +} + +/* markdown 样式 */ +.markdown { + color: #666; + font-size: 14px; + line-height: 1.8; +} + +.highlight { + line-height: 1.5; +} + +.markdown img { + vertical-align: middle; + max-width: 100%; +} + +.markdown h1 { + color: #404040; + font-weight: 500; + line-height: 40px; + margin-bottom: 24px; +} + +.markdown h2, +.markdown h3, +.markdown h4, +.markdown h5, +.markdown h6 { + color: #404040; + margin: 1.6em 0 0.6em 0; + font-weight: 500; + clear: both; +} + +.markdown h1 { + font-size: 28px; +} + +.markdown h2 { + font-size: 22px; +} + +.markdown h3 { + font-size: 16px; +} + +.markdown h4 { + font-size: 14px; +} + +.markdown h5 { + font-size: 12px; +} + +.markdown h6 { + font-size: 12px; +} + +.markdown hr { + height: 1px; + border: 0; + background: #e9e9e9; + margin: 16px 0; + clear: both; +} + +.markdown p { + margin: 1em 0; +} + +.markdown>p, +.markdown>blockquote, +.markdown>.highlight, +.markdown>ol, +.markdown>ul { + width: 80%; +} + +.markdown ul>li { + list-style: circle; +} + +.markdown>ul li, +.markdown blockquote ul>li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown>ul li p, +.markdown>ol li p { + margin: 0.6em 0; +} + +.markdown ol>li { + list-style: decimal; +} + +.markdown>ol li, +.markdown blockquote ol>li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown code { + margin: 0 3px; + padding: 0 5px; + background: #eee; + border-radius: 3px; +} + +.markdown strong, +.markdown b { + font-weight: 600; +} + +.markdown>table { + border-collapse: collapse; + border-spacing: 0px; + empty-cells: show; + border: 1px solid #e9e9e9; + width: 95%; + margin-bottom: 24px; +} + +.markdown>table th { + white-space: nowrap; + color: #333; + font-weight: 600; +} + +.markdown>table th, +.markdown>table td { + border: 1px solid #e9e9e9; + padding: 8px 16px; + text-align: left; +} + +.markdown>table th { + background: #F7F7F7; +} + +.markdown blockquote { + font-size: 90%; + color: #999; + border-left: 4px solid #e9e9e9; + padding-left: 0.8em; + margin: 1em 0; +} + +.markdown blockquote p { + margin: 0; +} + +.markdown .anchor { + opacity: 0; + transition: opacity 0.3s ease; + margin-left: 8px; +} + +.markdown .waiting { + color: #ccc; +} + +.markdown h1:hover .anchor, +.markdown h2:hover .anchor, +.markdown h3:hover .anchor, +.markdown h4:hover .anchor, +.markdown h5:hover .anchor, +.markdown h6:hover .anchor { + opacity: 1; + display: inline-block; +} + +.markdown>br, +.markdown>p>br { + clear: both; +} + + +.hljs { + display: block; + background: white; + padding: 0.5em; + color: #333333; + overflow-x: auto; +} + +.hljs-comment, +.hljs-meta { + color: #969896; +} + +.hljs-string, +.hljs-variable, +.hljs-template-variable, +.hljs-strong, +.hljs-emphasis, +.hljs-quote { + color: #df5000; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-type { + color: #a71d5d; +} + +.hljs-literal, +.hljs-symbol, +.hljs-bullet, +.hljs-attribute { + color: #0086b3; +} + +.hljs-section, +.hljs-name { + color: #63a35c; +} + +.hljs-tag { + color: #333333; +} + +.hljs-title, +.hljs-attr, +.hljs-selector-id, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #795da3; +} + +.hljs-addition { + color: #55a532; + background-color: #eaffea; +} + +.hljs-deletion { + color: #bd2c00; + background-color: #ffecec; +} + +.hljs-link { + text-decoration: underline; +} + +/* 代码高亮 */ +/* PrismJS 1.15.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */ +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ +code[class*="language-"], +pre[class*="language-"] { + color: black; + background: none; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*="language-"]::-moz-selection, +pre[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, +code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +pre[class*="language-"]::selection, +pre[class*="language-"] ::selection, +code[class*="language-"]::selection, +code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; +} + +@media print { + + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; + } +} + +/* Code blocks */ +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; +} + +:not(pre)>code[class*="language-"], +pre[class*="language-"] { + background: #f5f2f0; +} + +/* Inline code */ +:not(pre)>code[class*="language-"] { + padding: .1em; + border-radius: .3em; + white-space: normal; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; +} + +.token.punctuation { + color: #999; +} + +.namespace { + opacity: .7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #905; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: #690; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #9a6e3a; + background: hsla(0, 0%, 100%, .5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; +} + +.token.function, +.token.class-name { + color: #DD4A68; +} + +.token.regex, +.token.important, +.token.variable { + color: #e90; +} + +.token.important, +.token.bold { + font-weight: bold; +} + +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} diff --git a/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/demo_index.html b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/demo_index.html new file mode 100644 index 0000000..8451b3f --- /dev/null +++ b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/demo_index.html @@ -0,0 +1,469 @@ + + + + + IconFont Demo + + + + + + + + + + + +
+

+ +
+
+
    + +
  • + +
    home-outline
    +
    &#xe9b0;
    +
  • + +
  • + +
    history
    +
    &#xe752;
    +
  • + +
  • + +
    exit-outline
    +
    &#xe9ac;
    +
  • + +
  • + +
    create-outline
    +
    &#xe9ad;
    +
  • + +
  • + +
    power-outline
    +
    &#xe9ae;
    +
  • + +
  • + +
    add-circle-outline
    +
    &#xe9af;
    +
  • + +
  • + +
    操作日志
    +
    &#xe65f;
    +
  • + +
  • + +
    菜单管理
    +
    &#xe6a4;
    +
  • + +
  • + +
    角色类型
    +
    &#xe666;
    +
  • + +
  • + +
    功能角色权限管理
    +
    &#xe642;
    +
  • + +
  • + +
    用户管理
    +
    &#xe62d;
    +
  • + +
  • + +
    基础配置
    +
    &#xe62e;
    +
  • + +
  • + +
    trash-outline
    +
    &#xea8d;
    +
  • + +
+
+

Unicode 引用

+
+ +

Unicode 是字体在网页端最原始的应用方式,特点是:

+
    +
  • 兼容性最好,支持 IE6+,及所有现代浏览器。
  • +
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • +
  • 但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。
  • +
+
+

注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用,如果有需求建议使用symbol 的引用方式

+
+

Unicode 使用步骤如下:

+

第一步:拷贝项目下面生成的 @font-face

+
@font-face {
+  font-family: 'iconfont';
+  src: url('iconfont.eot');
+  src: url('iconfont.eot?#iefix') format('embedded-opentype'),
+      url('iconfont.woff2') format('woff2'),
+      url('iconfont.woff') format('woff'),
+      url('iconfont.ttf') format('truetype'),
+      url('iconfont.svg#iconfont') format('svg');
+}
+
+

第二步:定义使用 iconfont 的样式

+
.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+

第三步:挑选相应图标并获取字体编码,应用于页面

+
+<span class="iconfont">&#x33;</span>
+
+
+

"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

+
+
+
+
+
    + +
  • + +
    + home-outline +
    +
    .icon-home-outline +
    +
  • + +
  • + +
    + history +
    +
    .icon-history +
    +
  • + +
  • + +
    + exit-outline +
    +
    .icon-exit-outline +
    +
  • + +
  • + +
    + create-outline +
    +
    .icon-create-outline +
    +
  • + +
  • + +
    + power-outline +
    +
    .icon-power-outline +
    +
  • + +
  • + +
    + add-circle-outline +
    +
    .icon-add-circle-outline +
    +
  • + +
  • + +
    + 操作日志 +
    +
    .icon-caozuorizhi +
    +
  • + +
  • + +
    + 菜单管理 +
    +
    .icon-jiaoyixulie +
    +
  • + +
  • + +
    + 角色类型 +
    +
    .icon-jiaoseleixing +
    +
  • + +
  • + +
    + 功能角色权限管理 +
    +
    .icon-gongnengjiaosequanxianguanli +
    +
  • + +
  • + +
    + 用户管理 +
    +
    .icon-yonghuguanli_huaban +
    +
  • + +
  • + +
    + 基础配置 +
    +
    .icon-jichupeizhi +
    +
  • + +
  • + +
    + trash-outline +
    +
    .icon-trash-outline +
    +
  • + +
+
+

font-class 引用

+
+ +

font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。

+

与 Unicode 使用方式相比,具有如下特点:

+
    +
  • 兼容性良好,支持 IE8+,及所有现代浏览器。
  • +
  • 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
  • +
  • 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
  • +
  • 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
  • +
+

使用步骤如下:

+

第一步:引入项目下面生成的 fontclass 代码:

+
<link rel="stylesheet" href="./iconfont.css">
+
+

第二步:挑选相应图标并获取类名,应用于页面:

+
<span class="iconfont icon-xxx"></span>
+
+
+

" + iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

+
+
+
+
+
    + +
  • + +
    home-outline
    +
    #icon-home-outline
    +
  • + +
  • + +
    history
    +
    #icon-history
    +
  • + +
  • + +
    exit-outline
    +
    #icon-exit-outline
    +
  • + +
  • + +
    create-outline
    +
    #icon-create-outline
    +
  • + +
  • + +
    power-outline
    +
    #icon-power-outline
    +
  • + +
  • + +
    add-circle-outline
    +
    #icon-add-circle-outline
    +
  • + +
  • + +
    操作日志
    +
    #icon-caozuorizhi
    +
  • + +
  • + +
    菜单管理
    +
    #icon-jiaoyixulie
    +
  • + +
  • + +
    角色类型
    +
    #icon-jiaoseleixing
    +
  • + +
  • + +
    功能角色权限管理
    +
    #icon-gongnengjiaosequanxianguanli
    +
  • + +
  • + +
    用户管理
    +
    #icon-yonghuguanli_huaban
    +
  • + +
  • + +
    基础配置
    +
    #icon-jichupeizhi
    +
  • + +
  • + +
    trash-outline
    +
    #icon-trash-outline
    +
  • + +
+
+

Symbol 引用

+
+ +

这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章 + 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:

+
    +
  • 支持多色图标了,不再受单色限制。
  • +
  • 通过一些技巧,支持像字体那样,通过 font-size, color 来调整样式。
  • +
  • 兼容性较差,支持 IE9+,及现代浏览器。
  • +
  • 浏览器渲染 SVG 的性能一般,还不如 png。
  • +
+

使用步骤如下:

+

第一步:引入项目下面生成的 symbol 代码:

+
<script src="./iconfont.js"></script>
+
+

第二步:加入通用 CSS 代码(引入一次就行):

+
<style>
+.icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+</style>
+
+

第三步:挑选相应图标并获取类名,应用于页面:

+
<svg class="icon" aria-hidden="true">
+  <use xlink:href="#icon-xxx"></use>
+</svg>
+
+
+
+ +
+
+ + + diff --git a/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.css b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.css new file mode 100644 index 0000000..791e4c5 --- /dev/null +++ b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.css @@ -0,0 +1,69 @@ +@font-face {font-family: "iconfont"; + src: url('iconfont.eot?t=1600418906476'); /* IE9 */ + src: url('iconfont.eot?t=1600418906476#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAt8AAsAAAAAFnwAAAssAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCEUAqdDJc8ATYCJAM4Cx4ABCAFhG0HggQbxhJFRoaNAyLgfTSy/8sEbgwBazyfESpePnvWFaq9JoDICGPC5EVuWee3DmvMC+JMx3AKICEEE4T+tNtUkeCafp5Off//i+9f7lqnSsVRV6ypmBqzMsjpxE6+Qc4ghudp5/vVZdglkEGQwQTGNJhMdqhLTy1LCcvvAuOGZCgByKu9CoJgvwpTGMbnMICDyX2ap6svuhXbvclqHRZ0vPVt1/WxtA0Fwqcp1tTW1Tz/mvu0yA4UsTrhTrhzbl/4ZffDJkf5OaYSoGVdoZIDQFVX1amsRlTC1mC4xTEroC3esQzro1YGCICauxBovSdkgBKD6Qh7HawqAaVjYmKSEaVX7pmxAbpARlnG43MAptr3jz6NowTAZBXYqlIqO5aD+Dz0ycRkNcknDEzlWQAwmw2AAAgBwAB0e+0lyBFDLFX7DmT0BAAbfPCn8TtEKFJpxYu06l9Ptlp5HnodtuFk7HnEhh3/DzxXABosNQUVJYxgyMghFKAOoGwQvoFTYyzJYqABz8M4sJRFgIMarAgcFGCV4KACW4FioAQv0ooBBq82cCCWbQQHBmwTOMjANoODHKwexQCB15MDQDHK6RlcAbQHzANkP3g6Wyq7x0iCDIaCPMAid3ziaQ85etQQyIb10dp6UZYVh3E6RijlP8tSvexseWrndlE2wIedbMwp23W7UY6zuK/Yj6PpnsTY54BZiHFL/wLMqoMIMEG1A3tJW99iIPNNlPV+8+Oe+VgTFKx/KFjoxx7hB/wxfliChTCswDZ5mpCU4Ez4PHs7w8I5BzAigMnOZGrKzeWE+KemgIDRX+e1p5aQ2vRe2pZcnH3aiviavKZw3rTyaHV+q16Iqk6DqoRruY50DzRswajF3YLlMZoUBhELX5YiOBfg3HLjCV7Gd9lC13FmrBeBuVFVWg843caNgJxW5mPlxTZI/27b3LwpVzVHZTQBmg/tncbLXZIVutXIHrg2XmJhBguTQqTYS7y1lNI+kOtGAtPNa6HYph2+X3Auq46m11RRxHZ07AeUU9mLGmm6wq+UbsRSelPXfHCsw4+lTx9w1k6hYZD0h/vgSzTTUwYBIQKFkP0uAcBlVNGPMfKkzymQYBkEC/B7gSnvW13YOrBw+gVgsVt54Ew0E9UToSHmATdcWbdxSzeS15Jm82XBOaTwar7xnf94zPzXRqUwynh27ALCIM0fZBIZ86aYSdaOZN1TidtAraEIcg15r4WDKitwnquU4dPQyR7j8dwK1Dh1nIxll0PdXTogpMAiQoIH6BEyjmfFBYOxmjxg8MD5XtNRgq6+vwDsT29nvJq/4WaevI8XWudIX3ceYLNSvwC6RW2lg+n5dmjTez21dAAWJZvKyo22JEvsWkGBU2qAEM/YsLZoNkylY7nu9aSBcbGqs/t1L4+atTlsKJokxUN7oTuu5syR8V77Ei3xVCt2FACM4ztuBCrPOYU436O7sCG2CP9HDbljo5bVZY9eBU5xy78FTvcBq6ndTFxRu/Z8w8pzLTUL3cqO1XbPQeI4QEhz33y7a7/b2kY2Wl61KlzHbOy4jrWm/9QaB1urJufjWPa8MjZ/PqlxbRtUvKI7FkrdGhk3G/+F+YE2b6vW5nLIr0rcfpUp/iCRPpbkzwTlw+hGFr5akCoQu+YVtsmrLKQEyzi6rnRzBP4xe9aapiBKnMDxinEKs0T+vErJ3ER9ixNcBe6W+SM6x5v5c+ij+cpd3aTRlqXU23n+2rngwonZb57OVjdvzRwsdpi3vQ7rFbntE/raGU44Y7EMer4/WB8Kcvw4mc2J3uBsQsap01MM4tkdYkFUxki1oq9scR3uhwcsWzYAg4AoXUy0hNqFotksWqCBh+nje61F+/6jpSkFH5lC1jU0NVxHLJA9Ltr3S5dQL9348eO4pjs0zlu6dLxDVMu8GUu9YkXdBps9LKXRZI8nuZRgS2j3oO5umpHN5pvWjI+iUZnyFfUb5zy8Q3VVE4LkaQTzDb2rq6O4jk0yOLB61JPXr0l9YeJKQ9u50xnnuUfDJ6aQWSdOzCKc6G2QWSkRE4/MCyQz5sa0TVpZSOpfv6ofyAmcqRaAmh3C8bU67sz+ZD6hIJGiS9ZQEXT19KUngjcE2nk+rZg9q/wcXldaNEG/HwCeH50zo7KkSaNwQPta9dgT0GYX8IyBj2r/tHg9t75Y+Tk/zymhynDKi23sZBupGaNp7DhdrbopAPTQKXYoP7BXpoU7y/fydxTOJdOycv6heC03uNxAMzwSGihO86flDXLI5ksayPfwtxUNxIDe7u/pdkuSJYOSigucZVCvMsUi7UIF3Z1bpACA8ceWsuJF1N0frlmZfD+ffjzdZazP2HkAOxF3eT94neDNKyPq0QMZUSZSjDgTg9KMeLsyz4uFfrGxfoVNIdbQZ2uXgHF70WDqjtT/HN7pkDsVG/TKze3VQDxSyg6fjCpxlxkz3Z/xJFy1z3afio8xZAr7hYrOnSps9qZE6kkEPX6MCrGGCWs5ZUWXzpk26yB9veQZHmEjCZER/DE9IgJJNkv4dEMwaiWhUpAEI0iFRqE8gS6EE6TpIyOx8flmZBRfaUKm7LVfLQkRxQzWS051gs5JHxDMb7lZIBj5jVqQS45HngTOQPMovYE1XeAwQ3WYWgeJ91mBFUFKCCKLLMOIzqaCde+JoSxPwzdIAf5XtbqJDIpIzw9XSB2Cvlwe1TK9ZR+hG7IlbMNYZ63PlQ0ZqMxlPSS9hKkyp3JsC63ON4Gi1M6dU5WGpgQadRegK/IeslRVQ/Eyvaump3lmT8xJ4KTpqeEpOYypqiZmcPYeB0NMcbGscLC3bpBepxyvwIr5ikUI9q5cOP8gvsmQjyteODbcSwj2+x6Yjwb2R7mcaDsf5Z0d/I6kh/vrkpO2HJZRavVmDytEL+1Ho2mcio96NDnatfbt9ey5xw8lnk9NPZ948ASW93ZgtMvkx6o450a6rdP0zuq4K5MNLkkWvGNzwc7jnsiYBbPzo5PGdArhns2K1vZcLCaKHvXMvVNw0uj86GYJbROamYUnjyluMC9D6BeFb8OuDt27Rwb4D6N4i56SHbWI684hrZvSoP4z1xMYMeyg9DKLuu89J3ApH87yJ5z8kQxO3eQOXBJBDzWFCqz2EMVmPZ12X7KiBD426s2Iww6sAMP+AtvJKk1/RETaQoqxxYZIJayW6XXEM1QfaibafkyMaZLX4/UZh8gM0qFnJXlK8nzDHcZPrX+sjAFiKjvYJP3vHAnkX74PLdK2/abU/D1tv+vPzrXHpRf/pzHYSP8pWxmw/vn7eLLA5hjwnS1pWP9ALKWOg0P/foIxZqj5dQD/KRtsPKjLY59a+tfssT/nYApuSHzhPsggPCRHRqMpyhHeIUctmGF2DVs9gUBNBQBBRiMH4W2muKUSkATh55FB+P0cGQfvNDniQ3LUbmnM/QI1/IJnLwyVQKvqTWFDoxZVcnbY+xNM6CumymSsX2CPNKo8yfb9HzAClzGJn00hopVmGtQ7mQD6ntTE1EEjiUXfdExTvZg0aWiIzkRioCK6YEupbaVRg4z0w8XZ1bv/BIygV+GYk25K/wLMwxdXcoksRfAHHVOdtC0HejOjINTSlDySkYHyTi3Q8x6iTP7hOqAhEjZH1+QopRfTaWlSv2d41Ck8fKdkr41LlGRF1XTDtGzH9QK7aYCYgvQ4wsGiF+LtAlaUEPOqudfK5V6XEy3Ak3HuqraNG+Smj1z6eVPRHohxt3jeYUUbrqFHuNw4eugBVxzNgyHlH0FKnkH/oRpXBBrb1OP9FlFhw4X/zxqrrsZiuhsbJihyr0vhytvKjCgCAAAA') format('woff2'), + url('iconfont.woff?t=1600418906476') format('woff'), + url('iconfont.ttf?t=1600418906476') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ + url('iconfont.svg?t=1600418906476#iconfont') format('svg'); /* iOS 4.1- */ +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-home-outline:before { + content: "\e9b0"; +} + +.icon-history:before { + content: "\e752"; +} + +.icon-exit-outline:before { + content: "\e9ac"; +} + +.icon-create-outline:before { + content: "\e9ad"; +} + +.icon-power-outline:before { + content: "\e9ae"; +} + +.icon-add-circle-outline:before { + content: "\e9af"; +} + +.icon-caozuorizhi:before { + content: "\e65f"; +} + +.icon-jiaoyixulie:before { + content: "\e6a4"; +} + +.icon-jiaoseleixing:before { + content: "\e666"; +} + +.icon-gongnengjiaosequanxianguanli:before { + content: "\e642"; +} + +.icon-yonghuguanli_huaban:before { + content: "\e62d"; +} + +.icon-jichupeizhi:before { + content: "\e62e"; +} + +.icon-trash-outline:before { + content: "\ea8d"; +} + diff --git a/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.eot b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.eot new file mode 100644 index 0000000..e85e6ab Binary files /dev/null and b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.eot differ diff --git a/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.js b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.js new file mode 100644 index 0000000..12527cb --- /dev/null +++ b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.js @@ -0,0 +1 @@ +!function(c){var a,t,l,e,h,o,i,n='',s=(a=document.getElementsByTagName("script"))[a.length-1].getAttribute("data-injectcss");if(s&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}function d(){o||(o=!0,e())}t=function(){var c,a,t,l,e,h=document.createElement("div");h.innerHTML=n,n=null,(c=h.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",a=c,(t=document.body).firstChild?(l=a,(e=t.firstChild).parentNode.insertBefore(l,e)):t.appendChild(a))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(t,0):(l=function(){document.removeEventListener("DOMContentLoaded",l,!1),t()},document.addEventListener("DOMContentLoaded",l,!1)):document.attachEvent&&(e=t,h=c.document,o=!1,(i=function(){try{h.documentElement.doScroll("left")}catch(c){return void setTimeout(i,50)}d()})(),h.onreadystatechange=function(){"complete"==h.readyState&&(h.onreadystatechange=null,d())})}(window); \ No newline at end of file diff --git a/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.json b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.json new file mode 100644 index 0000000..d387e4f --- /dev/null +++ b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.json @@ -0,0 +1,100 @@ +{ + "id": "2077973", + "name": "icon-font", + "font_family": "iconfont", + "css_prefix_text": "icon-", + "description": "", + "glyphs": [ + { + "icon_id": "17288958", + "name": "home-outline", + "font_class": "home-outline", + "unicode": "e9b0", + "unicode_decimal": 59824 + }, + { + "icon_id": "11488047", + "name": "history", + "font_class": "history", + "unicode": "e752", + "unicode_decimal": 59218 + }, + { + "icon_id": "17287306", + "name": "exit-outline", + "font_class": "exit-outline", + "unicode": "e9ac", + "unicode_decimal": 59820 + }, + { + "icon_id": "17287307", + "name": "create-outline", + "font_class": "create-outline", + "unicode": "e9ad", + "unicode_decimal": 59821 + }, + { + "icon_id": "17287308", + "name": "power-outline", + "font_class": "power-outline", + "unicode": "e9ae", + "unicode_decimal": 59822 + }, + { + "icon_id": "17287309", + "name": "add-circle-outline", + "font_class": "add-circle-outline", + "unicode": "e9af", + "unicode_decimal": 59823 + }, + { + "icon_id": "774447", + "name": "操作日志", + "font_class": "caozuorizhi", + "unicode": "e65f", + "unicode_decimal": 58975 + }, + { + "icon_id": "7133436", + "name": "菜单管理", + "font_class": "jiaoyixulie", + "unicode": "e6a4", + "unicode_decimal": 59044 + }, + { + "icon_id": "8605742", + "name": "角色类型", + "font_class": "jiaoseleixing", + "unicode": "e666", + "unicode_decimal": 58982 + }, + { + "icon_id": "11121526", + "name": "功能角色权限管理", + "font_class": "gongnengjiaosequanxianguanli", + "unicode": "e642", + "unicode_decimal": 58946 + }, + { + "icon_id": "12753449", + "name": "用户管理", + "font_class": "yonghuguanli_huaban", + "unicode": "e62d", + "unicode_decimal": 58925 + }, + { + "icon_id": "12820167", + "name": "基础配置", + "font_class": "jichupeizhi", + "unicode": "e62e", + "unicode_decimal": 58926 + }, + { + "icon_id": "17287082", + "name": "trash-outline", + "font_class": "trash-outline", + "unicode": "ea8d", + "unicode_decimal": 60045 + } + ] +} diff --git a/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.svg b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.svg new file mode 100644 index 0000000..49e00e8 --- /dev/null +++ b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.svg @@ -0,0 +1,65 @@ + + + + + +Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.ttf b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.ttf new file mode 100644 index 0000000..4be4eea Binary files /dev/null and b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.ttf differ diff --git a/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.woff b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.woff new file mode 100644 index 0000000..c5c5477 Binary files /dev/null and b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.woff differ diff --git a/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.woff2 b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.woff2 new file mode 100644 index 0000000..4c75fdd Binary files /dev/null and b/client/src/main/resources/fonts/icon_font/font_2077973_470ixam2xkt/iconfont.woff2 differ diff --git a/client/src/main/resources/fonts/icon_font/iconfont.svg b/client/src/main/resources/fonts/icon_font/iconfont.svg new file mode 100644 index 0000000..1d6b54d --- /dev/null +++ b/client/src/main/resources/fonts/icon_font/iconfont.svg @@ -0,0 +1,98 @@ + + + + + +Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fonts/msyh.ttf b/client/src/main/resources/fonts/msyh.ttf new file mode 100644 index 0000000..77bde49 Binary files /dev/null and b/client/src/main/resources/fonts/msyh.ttf differ diff --git a/client/src/main/resources/fonts/msyhbd.ttf b/client/src/main/resources/fonts/msyhbd.ttf new file mode 100644 index 0000000..7734c7d Binary files /dev/null and b/client/src/main/resources/fonts/msyhbd.ttf differ diff --git a/client/src/main/resources/fonts/msyhl.ttf b/client/src/main/resources/fonts/msyhl.ttf new file mode 100644 index 0000000..c44d540 Binary files /dev/null and b/client/src/main/resources/fonts/msyhl.ttf differ diff --git a/client/src/main/resources/fxml/admin/group/components/group_detail.fxml b/client/src/main/resources/fxml/admin/group/components/group_detail.fxml new file mode 100644 index 0000000..4912eab --- /dev/null +++ b/client/src/main/resources/fxml/admin/group/components/group_detail.fxml @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 取消 + 保存 + + + + + + + + + + + + 取消 + 保存 + + + + + + diff --git a/client/src/main/resources/fxml/admin/group/components/group_user.fxml b/client/src/main/resources/fxml/admin/group/components/group_user.fxml new file mode 100644 index 0000000..1612bce --- /dev/null +++ b/client/src/main/resources/fxml/admin/group/components/group_user.fxml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fxml/admin/group/group_management.fxml b/client/src/main/resources/fxml/admin/group/group_management.fxml new file mode 100644 index 0000000..fe7d3e5 --- /dev/null +++ b/client/src/main/resources/fxml/admin/group/group_management.fxml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/client/src/main/resources/fxml/admin/groupType/components/group_type_detailed.fxml b/client/src/main/resources/fxml/admin/groupType/components/group_type_detailed.fxml new file mode 100644 index 0000000..669efd3 --- /dev/null +++ b/client/src/main/resources/fxml/admin/groupType/components/group_type_detailed.fxml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fxml/admin/groupType/group_type_management.fxml b/client/src/main/resources/fxml/admin/groupType/group_type_management.fxml new file mode 100644 index 0000000..7f387d0 --- /dev/null +++ b/client/src/main/resources/fxml/admin/groupType/group_type_management.fxml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 取消 + 保存 + 确定 + + + + + diff --git a/client/src/main/resources/fxml/admin/menu/components/menu_detailed.fxml b/client/src/main/resources/fxml/admin/menu/components/menu_detailed.fxml new file mode 100644 index 0000000..047d894 --- /dev/null +++ b/client/src/main/resources/fxml/admin/menu/components/menu_detailed.fxml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fxml/admin/menu/menu_management.fxml b/client/src/main/resources/fxml/admin/menu/menu_management.fxml new file mode 100644 index 0000000..041111b --- /dev/null +++ b/client/src/main/resources/fxml/admin/menu/menu_management.fxml @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fxml/admin/user/user_detailed.fxml b/client/src/main/resources/fxml/admin/user/user_detailed.fxml new file mode 100644 index 0000000..b2e94d3 --- /dev/null +++ b/client/src/main/resources/fxml/admin/user/user_detailed.fxml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fxml/admin/user/user_management.fxml b/client/src/main/resources/fxml/admin/user/user_management.fxml new file mode 100644 index 0000000..9fa6cfd --- /dev/null +++ b/client/src/main/resources/fxml/admin/user/user_management.fxml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fxml/basicInfo/basic_data_set.fxml b/client/src/main/resources/fxml/basicInfo/basic_data_set.fxml new file mode 100644 index 0000000..44df67f --- /dev/null +++ b/client/src/main/resources/fxml/basicInfo/basic_data_set.fxml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fxml/basicInfo/coal_price_difference.fxml b/client/src/main/resources/fxml/basicInfo/coal_price_difference.fxml new file mode 100644 index 0000000..31807f9 --- /dev/null +++ b/client/src/main/resources/fxml/basicInfo/coal_price_difference.fxml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fxml/basicInfo/current_freight.fxml b/client/src/main/resources/fxml/basicInfo/current_freight.fxml new file mode 100644 index 0000000..421cbc2 --- /dev/null +++ b/client/src/main/resources/fxml/basicInfo/current_freight.fxml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fxml/basicInfo/main_conclusion.fxml b/client/src/main/resources/fxml/basicInfo/main_conclusion.fxml new file mode 100644 index 0000000..2eb7602 --- /dev/null +++ b/client/src/main/resources/fxml/basicInfo/main_conclusion.fxml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fxml/basicInfo/railway_cost.fxml b/client/src/main/resources/fxml/basicInfo/railway_cost.fxml new file mode 100644 index 0000000..ffe3767 --- /dev/null +++ b/client/src/main/resources/fxml/basicInfo/railway_cost.fxml @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/fxml/components/LFXDecorator.fxml b/client/src/main/resources/fxml/components/LFXDecorator.fxml new file mode 100644 index 0000000..fd33361 --- /dev/null +++ b/client/src/main/resources/fxml/components/LFXDecorator.fxml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/client/src/main/resources/fxml/featureView.fxml b/client/src/main/resources/fxml/featureView.fxml new file mode 100644 index 0000000..578838f --- /dev/null +++ b/client/src/main/resources/fxml/featureView.fxml @@ -0,0 +1,11 @@ + + + + + + +