├── .classpath ├── .gitattributes ├── .gitignore ├── .project ├── .settings ├── org.eclipse.core.resources.prefs ├── org.eclipse.jdt.core.prefs └── org.eclipse.m2e.core.prefs ├── .travis.yml ├── LICENSE ├── README.md ├── pom.xml ├── resources ├── fxml │ └── DownloadModeController.fxml ├── image │ └── icon.png └── style │ └── application.css ├── spartan.xml ├── spartanizer.xml └── src └── main └── java └── com └── goxr3plus └── xr3playerupdater ├── application └── Main.java ├── presenter └── DownloadModeController.java ├── services ├── DownloadService.java └── ExportZipService.java └── tools ├── ActionTool.java ├── InfoTool.java └── NotificationType.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | XR3PlayerUpdater 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | spartan.tipper 15 | 16 | 17 | 18 | 19 | org.eclipse.m2e.core.maven2Builder 20 | 21 | 22 | 23 | 24 | 25 | org.eclipse.m2e.core.maven2Nature 26 | org.eclipse.jdt.core.javanature 27 | il.org.spartan.nature 28 | 29 | 30 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | encoding/resources=UTF-8 4 | encoding/src=UTF-8 5 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 12 | org.eclipse.jdt.core.compiler.source=1.8 13 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: oraclejdk8 3 | script: mvn clean package -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Attribution 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More_considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution 4.0 International Public License 58 | 59 | By exercising the Licensed Rights (defined below), You accept and agree 60 | to be bound by the terms and conditions of this Creative Commons 61 | Attribution 4.0 International Public License ("Public License"). To the 62 | extent this Public License may be interpreted as a contract, You are 63 | granted the Licensed Rights in consideration of Your acceptance of 64 | these terms and conditions, and the Licensor grants You such rights in 65 | consideration of benefits the Licensor receives from making the 66 | Licensed Material available under these terms and conditions. 67 | 68 | 69 | Section 1 -- Definitions. 70 | 71 | a. Adapted Material means material subject to Copyright and Similar 72 | Rights that is derived from or based upon the Licensed Material 73 | and in which the Licensed Material is translated, altered, 74 | arranged, transformed, or otherwise modified in a manner requiring 75 | permission under the Copyright and Similar Rights held by the 76 | Licensor. For purposes of this Public License, where the Licensed 77 | Material is a musical work, performance, or sound recording, 78 | Adapted Material is always produced where the Licensed Material is 79 | synched in timed relation with a moving image. 80 | 81 | b. Adapter's License means the license You apply to Your Copyright 82 | and Similar Rights in Your contributions to Adapted Material in 83 | accordance with the terms and conditions of this Public License. 84 | 85 | c. Copyright and Similar Rights means copyright and/or similar rights 86 | closely related to copyright including, without limitation, 87 | performance, broadcast, sound recording, and Sui Generis Database 88 | Rights, without regard to how the rights are labeled or 89 | categorized. For purposes of this Public License, the rights 90 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 91 | Rights. 92 | 93 | d. Effective Technological Measures means those measures that, in the 94 | absence of proper authority, may not be circumvented under laws 95 | fulfilling obligations under Article 11 of the WIPO Copyright 96 | Treaty adopted on December 20, 1996, and/or similar international 97 | agreements. 98 | 99 | e. Exceptions and Limitations means fair use, fair dealing, and/or 100 | any other exception or limitation to Copyright and Similar Rights 101 | that applies to Your use of the Licensed Material. 102 | 103 | f. Licensed Material means the artistic or literary work, database, 104 | or other material to which the Licensor applied this Public 105 | License. 106 | 107 | g. Licensed Rights means the rights granted to You subject to the 108 | terms and conditions of this Public License, which are limited to 109 | all Copyright and Similar Rights that apply to Your use of the 110 | Licensed Material and that the Licensor has authority to license. 111 | 112 | h. Licensor means the individual(s) or entity(ies) granting rights 113 | under this Public License. 114 | 115 | i. Share means to provide material to the public by any means or 116 | process that requires permission under the Licensed Rights, such 117 | as reproduction, public display, public performance, distribution, 118 | dissemination, communication, or importation, and to make material 119 | available to the public including in ways that members of the 120 | public may access the material from a place and at a time 121 | individually chosen by them. 122 | 123 | j. Sui Generis Database Rights means rights other than copyright 124 | resulting from Directive 96/9/EC of the European Parliament and of 125 | the Council of 11 March 1996 on the legal protection of databases, 126 | as amended and/or succeeded, as well as other essentially 127 | equivalent rights anywhere in the world. 128 | 129 | k. You means the individual or entity exercising the Licensed Rights 130 | under this Public License. Your has a corresponding meaning. 131 | 132 | 133 | Section 2 -- Scope. 134 | 135 | a. License grant. 136 | 137 | 1. Subject to the terms and conditions of this Public License, 138 | the Licensor hereby grants You a worldwide, royalty-free, 139 | non-sublicensable, non-exclusive, irrevocable license to 140 | exercise the Licensed Rights in the Licensed Material to: 141 | 142 | a. reproduce and Share the Licensed Material, in whole or 143 | in part; and 144 | 145 | b. produce, reproduce, and Share Adapted Material. 146 | 147 | 2. Exceptions and Limitations. For the avoidance of doubt, where 148 | Exceptions and Limitations apply to Your use, this Public 149 | License does not apply, and You do not need to comply with 150 | its terms and conditions. 151 | 152 | 3. Term. The term of this Public License is specified in Section 153 | 6(a). 154 | 155 | 4. Media and formats; technical modifications allowed. The 156 | Licensor authorizes You to exercise the Licensed Rights in 157 | all media and formats whether now known or hereafter created, 158 | and to make technical modifications necessary to do so. The 159 | Licensor waives and/or agrees not to assert any right or 160 | authority to forbid You from making technical modifications 161 | necessary to exercise the Licensed Rights, including 162 | technical modifications necessary to circumvent Effective 163 | Technological Measures. For purposes of this Public License, 164 | simply making modifications authorized by this Section 2(a) 165 | (4) never produces Adapted Material. 166 | 167 | 5. Downstream recipients. 168 | 169 | a. Offer from the Licensor -- Licensed Material. Every 170 | recipient of the Licensed Material automatically 171 | receives an offer from the Licensor to exercise the 172 | Licensed Rights under the terms and conditions of this 173 | Public License. 174 | 175 | b. No downstream restrictions. You may not offer or impose 176 | any additional or different terms or conditions on, or 177 | apply any Effective Technological Measures to, the 178 | Licensed Material if doing so restricts exercise of the 179 | Licensed Rights by any recipient of the Licensed 180 | Material. 181 | 182 | 6. No endorsement. Nothing in this Public License constitutes or 183 | may be construed as permission to assert or imply that You 184 | are, or that Your use of the Licensed Material is, connected 185 | with, or sponsored, endorsed, or granted official status by, 186 | the Licensor or others designated to receive attribution as 187 | provided in Section 3(a)(1)(A)(i). 188 | 189 | b. Other rights. 190 | 191 | 1. Moral rights, such as the right of integrity, are not 192 | licensed under this Public License, nor are publicity, 193 | privacy, and/or other similar personality rights; however, to 194 | the extent possible, the Licensor waives and/or agrees not to 195 | assert any such rights held by the Licensor to the limited 196 | extent necessary to allow You to exercise the Licensed 197 | Rights, but not otherwise. 198 | 199 | 2. Patent and trademark rights are not licensed under this 200 | Public License. 201 | 202 | 3. To the extent possible, the Licensor waives any right to 203 | collect royalties from You for the exercise of the Licensed 204 | Rights, whether directly or through a collecting society 205 | under any voluntary or waivable statutory or compulsory 206 | licensing scheme. In all other cases the Licensor expressly 207 | reserves any right to collect such royalties. 208 | 209 | 210 | Section 3 -- License Conditions. 211 | 212 | Your exercise of the Licensed Rights is expressly made subject to the 213 | following conditions. 214 | 215 | a. Attribution. 216 | 217 | 1. If You Share the Licensed Material (including in modified 218 | form), You must: 219 | 220 | a. retain the following if it is supplied by the Licensor 221 | with the Licensed Material: 222 | 223 | i. identification of the creator(s) of the Licensed 224 | Material and any others designated to receive 225 | attribution, in any reasonable manner requested by 226 | the Licensor (including by pseudonym if 227 | designated); 228 | 229 | ii. a copyright notice; 230 | 231 | iii. a notice that refers to this Public License; 232 | 233 | iv. a notice that refers to the disclaimer of 234 | warranties; 235 | 236 | v. a URI or hyperlink to the Licensed Material to the 237 | extent reasonably practicable; 238 | 239 | b. indicate if You modified the Licensed Material and 240 | retain an indication of any previous modifications; and 241 | 242 | c. indicate the Licensed Material is licensed under this 243 | Public License, and include the text of, or the URI or 244 | hyperlink to, this Public License. 245 | 246 | 2. You may satisfy the conditions in Section 3(a)(1) in any 247 | reasonable manner based on the medium, means, and context in 248 | which You Share the Licensed Material. For example, it may be 249 | reasonable to satisfy the conditions by providing a URI or 250 | hyperlink to a resource that includes the required 251 | information. 252 | 253 | 3. If requested by the Licensor, You must remove any of the 254 | information required by Section 3(a)(1)(A) to the extent 255 | reasonably practicable. 256 | 257 | 4. If You Share Adapted Material You produce, the Adapter's 258 | License You apply must not prevent recipients of the Adapted 259 | Material from complying with this Public License. 260 | 261 | 262 | Section 4 -- Sui Generis Database Rights. 263 | 264 | Where the Licensed Rights include Sui Generis Database Rights that 265 | apply to Your use of the Licensed Material: 266 | 267 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 268 | to extract, reuse, reproduce, and Share all or a substantial 269 | portion of the contents of the database; 270 | 271 | b. if You include all or a substantial portion of the database 272 | contents in a database in which You have Sui Generis Database 273 | Rights, then the database in which You have Sui Generis Database 274 | Rights (but not its individual contents) is Adapted Material; and 275 | 276 | c. You must comply with the conditions in Section 3(a) if You Share 277 | all or a substantial portion of the contents of the database. 278 | 279 | For the avoidance of doubt, this Section 4 supplements and does not 280 | replace Your obligations under this Public License where the Licensed 281 | Rights include other Copyright and Similar Rights. 282 | 283 | 284 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 285 | 286 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 287 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 288 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 289 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 290 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 291 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 292 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 293 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 294 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 295 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 296 | 297 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 298 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 299 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 300 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 301 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 302 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 303 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 304 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 305 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 306 | 307 | c. The disclaimer of warranties and limitation of liability provided 308 | above shall be interpreted in a manner that, to the extent 309 | possible, most closely approximates an absolute disclaimer and 310 | waiver of all liability. 311 | 312 | 313 | Section 6 -- Term and Termination. 314 | 315 | a. This Public License applies for the term of the Copyright and 316 | Similar Rights licensed here. However, if You fail to comply with 317 | this Public License, then Your rights under this Public License 318 | terminate automatically. 319 | 320 | b. Where Your right to use the Licensed Material has terminated under 321 | Section 6(a), it reinstates: 322 | 323 | 1. automatically as of the date the violation is cured, provided 324 | it is cured within 30 days of Your discovery of the 325 | violation; or 326 | 327 | 2. upon express reinstatement by the Licensor. 328 | 329 | For the avoidance of doubt, this Section 6(b) does not affect any 330 | right the Licensor may have to seek remedies for Your violations 331 | of this Public License. 332 | 333 | c. For the avoidance of doubt, the Licensor may also offer the 334 | Licensed Material under separate terms or conditions or stop 335 | distributing the Licensed Material at any time; however, doing so 336 | will not terminate this Public License. 337 | 338 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 339 | License. 340 | 341 | 342 | Section 7 -- Other Terms and Conditions. 343 | 344 | a. The Licensor shall not be bound by any additional or different 345 | terms or conditions communicated by You unless expressly agreed. 346 | 347 | b. Any arrangements, understandings, or agreements regarding the 348 | Licensed Material not stated herein are separate from and 349 | independent of the terms and conditions of this Public License. 350 | 351 | 352 | Section 8 -- Interpretation. 353 | 354 | a. For the avoidance of doubt, this Public License does not, and 355 | shall not be interpreted to, reduce, limit, restrict, or impose 356 | conditions on any use of the Licensed Material that could lawfully 357 | be made without permission under this Public License. 358 | 359 | b. To the extent possible, if any provision of this Public License is 360 | deemed unenforceable, it shall be automatically reformed to the 361 | minimum extent necessary to make it enforceable. If the provision 362 | cannot be reformed, it shall be severed from this Public License 363 | without affecting the enforceability of the remaining terms and 364 | conditions. 365 | 366 | c. No term or condition of this Public License will be waived and no 367 | failure to comply consented to unless expressly agreed to by the 368 | Licensor. 369 | 370 | d. Nothing in this Public License constitutes or may be interpreted 371 | as a limitation upon, or waiver of, any privileges and immunities 372 | that apply to the Licensor or You, including from the legal 373 | processes of any jurisdiction or authority. 374 | 375 | 376 | ======================================================================= 377 | 378 | Creative Commons is not a party to its public 379 | licenses. Notwithstanding, Creative Commons may elect to apply one of 380 | its public licenses to material it publishes and in those instances 381 | will be considered the “Licensor.” The text of the Creative Commons 382 | public licenses is dedicated to the public domain under the CC0 Public 383 | Domain Dedication. Except for the limited purpose of indicating that 384 | material is shared under a Creative Commons public license or as 385 | otherwise permitted by the Creative Commons policies published at 386 | creativecommons.org/policies, Creative Commons does not authorize the 387 | use of the trademark "Creative Commons" or any other trademark or logo 388 | of Creative Commons without its prior written consent including, 389 | without limitation, in connection with any unauthorized modifications 390 | to any of its public licenses or any other arrangements, 391 | understandings, or agreements concerning use of licensed material. For 392 | the avoidance of doubt, this paragraph does not form part of the 393 | public licenses. 394 | 395 | Creative Commons may be contacted at creativecommons.org. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### [![AlexKent](https://user-images.githubusercontent.com/20374208/75432997-f5422100-5957-11ea-87a2-164eb98d83ef.png)](https://www.minepi.com/AlexKent) Support me joining PI Network app with invitation code [AlexKent](https://www.minepi.com/AlexKent) [![AlexKent](https://user-images.githubusercontent.com/20374208/75432997-f5422100-5957-11ea-87a2-164eb98d83ef.png)](https://www.minepi.com/AlexKent) 2 | 3 | --- 4 | 5 | # JavaFXApplicationAutoUpdater 6 | 7 | 8 | Let's say you have a Java Application . You want to distribute it to your users right ? Yep ! 9 | But you also want every time you release a new update for your application , that update to be automatically downloaded and update your application version. 10 | 11 | Well here you are! I have created this small application which does exactly this . Updates your application version . 12 | 13 | 14 | 15 | # How it works? 16 | 17 | Basically i have written this code for an application called [XR3Player](https://github.com/goxr3plus/XR3Player). 18 | Every once a while i am releasing an update for XR3Player in the format of a zip folder called [for example [XR3Player Update 70.zip]](https://github.com/goxr3plus/XR3Player/releases) 19 | 20 | The Updater downloads this zip folder , extracts it and after that it starts the main application which is XR3Player. 21 | 22 | # So what ? 23 | 24 | **You can use it for your own Java or any kind of application to do the same just by changing a few parameters !!!!!!!!!!!!** 25 | 26 | # Youtube Tutorials 27 | 28 | [![Youtube Tutorial](http://img.youtube.com/vi/Xo9BB8OVpL0/0.jpg)](https://www.youtube.com/watch?v=xdXyajYWMBQ&index=1&list=PL-xqaiRUr_iSKPRiMqdHMAEiewdirjag-) 29 | 30 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.github.goxr3plus 7 | XR3PlayerUpdater 8 | 3.0.90 9 | XR3PlayerUpdater 10 | 11 | 12 | 13 | 14 | 15 | 1.8 16 | 1.8 17 | UTF-8 18 | 19 | 20 | 21 | 22 | src 23 | 24 | 25 | resources 26 | 27 | 28 | 29 | 30 | 33 | 36 | 37 | org.apache.maven.plugins 38 | maven-compiler-plugin 39 | 3.7.0 40 | 41 | 1.8 42 | 1.8 43 | UTF-8 44 | 45 | 46 | 47 | 48 | 49 | org.apache.maven.plugins 50 | maven-assembly-plugin 51 | 3.1.0 52 | 53 | 54 | 55 | jar-with-dependencies 56 | 57 | 58 | XR3PlayerUpdater 59 | 60 | 61 | 62 | main.java.com.goxr3plus.xr3playerupdater.application.Main 63 | 64 | 65 | false 66 | 67 | 68 | 69 | make-assembly 70 | 71 | package 72 | 73 | single 74 | 75 | 76 | 77 | 78 | 79 | 80 | maven-jar-plugin 81 | 3.0.2 82 | 83 | 84 | default-jar 85 | 86 | none 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | jitpack.io 97 | https://jitpack.io 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | org.controlsfx 107 | controlsfx 108 | 8.40.14 109 | 110 | 111 | 112 | commons-io 113 | commons-io 114 | 2.7 115 | 116 | 117 | -------------------------------------------------------------------------------- /resources/fxml/DownloadModeController.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 35 | 36 | 37 | 42 | 47 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
56 |
57 | -------------------------------------------------------------------------------- /resources/image/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goxr3plus/JavaFXApplicationAutoUpdater/c2842066ae06356bf0d8d56c2959f699be15cf34/resources/image/icon.png -------------------------------------------------------------------------------- /resources/style/application.css: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | 3 | * Badge * 4 | 5 | ******************************************************************************/ 6 | 7 | .split-pane .split-pane-divider{ 8 | -fx-background-color: 9 | -darkest-black, 10 | -dark-highlight, 11 | linear-gradient(to bottom, -light-black 2.0%, -dark-black 98.0%); 12 | } 13 | 14 | .split-pane .split-pane-divider:hover{ 15 | -fx-background-color:firebrick; 16 | -fx-border-color:black; 17 | -fx-border-width:2.0; 18 | } 19 | 20 | 21 | /* .icon{ 22 | -fx-text-fill: #FE774D; 23 | -fx-padding: 10.0; 24 | -fx-cursor: hand; 25 | } 26 | 27 | .icons-badge .badge-pane { 28 | -fx-background-color:#ff4081; 29 | -fx-background-radius:23.0; 30 | -fx-pref-width: 23.0; 31 | -fx-pref-height: 23.0; 32 | -fx-alignment: center; 33 | } 34 | 35 | .icns-badge Label{ 36 | -fx-font-weight: BOLD; 37 | -fx-font-size: 13.0px !important; 38 | -fx-text-fill: WHITE; 39 | } 40 | */ 41 | 42 | .chart .chart-title .text{ 43 | -fx-font-size:9.0px; 44 | } 45 | 46 | .chart-pie-label { 47 | -fx-fill: white; 48 | /*-fx-font-weight:bold;*/ 49 | -fx-font-size: 1.0em; 50 | } 51 | 52 | .chart .chart-title .text{ 53 | -fx-font-weight:bold; 54 | -fx-fill:white; 55 | } 56 | 57 | .chart .chart-content .chart-pie-label-line { 58 | -fx-stroke: #8b4513; 59 | -fx-fill: #8b4513; 60 | } 61 | 62 | 63 | /******************************************************************************* 64 | 65 | * CheckBox * 66 | 67 | ******************************************************************************/ 68 | 69 | 70 | /*.check-box .box { 71 | -fx-background-color: -fx-shadow-highlight-color, -fx-outer-border, -fx-inner-border, -fx-body-color; 72 | -fx-background-insets: 0.0 0.0 -1.0 0.0, 0.0, 1.0, 2.0; 73 | -fx-background-radius: 2.0, 2.0, 1.0, 1.0; 74 | 75 | -fx-padding: 16.0; 3 -- padding from the outside edge to the mark 76 | } 77 | */ 78 | 79 | 80 | /******************************************************************************* 81 | 82 | * PlayListsSettingsController * 83 | 84 | ******************************************************************************/ 85 | 86 | .settingsLabel{ 87 | -fx-border-color: white white transparent white; 88 | -fx-text-fill:gold; 89 | -fx-font-weight:bold; 90 | -fx-font-size:18.0; 91 | } 92 | 93 | .settingsRadioButton{ 94 | -fx-text-fill:white; 95 | -fx-font-weight:bold; 96 | -fx-cursor:hand; 97 | } 98 | 99 | 100 | /******************************************************************************* 101 | 102 | * ToolBar * 103 | 104 | ******************************************************************************/ 105 | 106 | .tool-bar{ 107 | -light-black: rgb(74.0, 75.0, 78.0); 108 | -dark-highlight: rgb(87.0, 89.0, 92.0); 109 | -dark-black: rgb(39.0, 40.0, 40.0); 110 | -darkest-black: rgb(5.0, 5.0, 5.0); 111 | -mid-gray: rgb(216.0, 222.0, 227.0); 112 | -fx-background-color: -mid-gray; 113 | 114 | -fx-base: -dark-black; 115 | -fx-font-size: 15.0pt; 116 | -fx-font-weight:bold; 117 | -fx-background-color: 118 | linear-gradient(to bottom, derive(-fx-base,-30.0%), derive(-fx-base,-60.0%)), 119 | linear-gradient(to bottom, -light-black 2.0%, -dark-black 98.0%); 120 | -fx-background-insets: 0.0, 0.0 0.0 1.0 0.0; 121 | /*-fx-padding: 0.9em 0.416667em 0.9em 0.416667em;*/ 122 | -fx-effect: dropshadow(two-pass-box,black,5.0,0.2,0.0,0.0); 123 | } 124 | 125 | .tool-bar2{ 126 | -fx-base: white; 127 | } 128 | 129 | .segmented-button-bar .button { 130 | -fx-background-color: 131 | -darkest-black, 132 | -dark-highlight, 133 | linear-gradient(to bottom, -light-black 2.0%, -dark-black 98.0%); 134 | -fx-background-insets: 0.0, 1.0 1.0 1.0 0.0, 2.0 1.0 1.0 1.0; 135 | -fx-background-radius: 0.0; 136 | -fx-padding: 0.4em 1.833333em 0.4em 1.833333em; 137 | } 138 | 139 | .segmented-button-bar .button.first { 140 | -fx-background-insets: 0.0, 1.0, 2.0 1.0 1.0 1.0; 141 | -fx-background-radius: 3.0 0.0 0.0 3.0, 2.0 0.0 0.0 2.0, 2.0 0.0 0.0 2.0; 142 | } 143 | 144 | .segmented-button-bar .button.last { 145 | -fx-background-insets: 0.0, 1.0 1.0 1.0 0.0, 2.0 1.0 1.0 1.0; 146 | -fx-background-radius: 0.0 3.0 3.0 0.0, 0.0 2.0 2.0 0.0, 0.0 2.0 2.0 0.0; 147 | } 148 | 149 | .segmented-button-bar .button:hover{ 150 | -fx-background-color:firebrick; 151 | } 152 | 153 | /******************************************************************************* 154 | 155 | * TableView * 156 | 157 | ******************************************************************************/ 158 | 159 | 160 | 161 | .table-view{ 162 | /*-fx-background-color: transparent;*/ 163 | } 164 | 165 | .table-view:focused{ 166 | /*-fx-background-color: transparent;*/ 167 | } 168 | 169 | 170 | .table-view .column-header { 171 | -fx-background-color: transparent; 172 | } 173 | 174 | .table-view .column-header-background{ 175 | -fx-background-color: linear-gradient(#131313 0.0%, #424141 100.0%); 176 | } 177 | 178 | .table-view .column-header-background .label{ 179 | -fx-background-color: transparent; 180 | -fx-font-weight:bold; 181 | -fx-text-fill: white; 182 | } 183 | 184 | .table-view .table-column{ 185 | -fx-alignment:center; 186 | } 187 | 188 | 189 | /* .table-row-cell */ 190 | 191 | .table-row-cell:disabled{ 192 | -fx-opacity:0.5; 193 | -fx-background-color:darkgray; 194 | } 195 | 196 | .table-row-cell:disabled .text{ 197 | /*-fx-strikethrough: true ;*/ 198 | } 199 | 200 | .table-row-cell .text{ 201 | -fx-font-weight:bold; 202 | -fx-fill: black ; 203 | } 204 | 205 | /*.table-row-cell:focused .text { 206 | -fx-fill: white ; 207 | } */ 208 | 209 | .table-row-cell:hover .text , .table-row-cell:selected .text{ 210 | -fx-fill: white ; 211 | } 212 | 213 | .table-row-cell:hover:selected .text,.table-row-cell:focused:selected .text{ 214 | -fx-fill:rgb(173.0,255.0,10.0); 215 | } 216 | 217 | 218 | /*.table-row-cell:focused{ 219 | -fx-background-color:firebrick; 220 | }*/ 221 | 222 | .table-row-cell:focused:disabled{ 223 | -fx-background-color:darkgray; 224 | } 225 | 226 | .table-row-cell:hover , .table-row-cell:selected{ 227 | /*-fx-background-color:rgb(0.0,191.0,255.0);*/ 228 | -fx-background-color:firebrick; 229 | } 230 | 231 | 232 | 233 | 234 | /* .table-row-cell:focused{ 235 | -fx-background-color:purple; 236 | } 237 | 238 | .table-row-cell:focused:disabled{ 239 | -fx-background-color:blue; 240 | } 241 | 242 | .table-row-cell:hover{ 243 | -fx-background-color:magenta; 244 | } 245 | */ 246 | 247 | 248 | 249 | .table-view .filler { 250 | -fx-text-fill: white; 251 | -fx-border-width: 0.0, 0.0; 252 | -fx-font-size: 12.0px; 253 | } 254 | 255 | 256 | 257 | 258 | /*------------------------------* 259 | 260 | 261 | /* 262 | .table-view .table-cell{ 263 | -fx-font-weight:bold; 264 | -fx-text-fill:black; 265 | } 266 | 267 | .table-row-cell{ 268 | -fx-background-color: white; 269 | -fx-background-insets: 0.0, 0.0 0.0 1.0 0.0; 270 | -fx-padding: 0.0em; 271 | } 272 | 273 | .table-row-cell:odd{ 274 | -fx-background-color: orange; 275 | -fx-background-insets: 0.0, 0.0 0.0 1.0 0.0; 276 | -fx-padding: 0.0em; 277 | } 278 | 279 | .table-view { 280 | -fx-background-insets: 0; 281 | -fx-padding: 10; 282 | -fx-alignment: center; 283 | } 284 | .table-view .column-header-background { 285 | -fx-background-color: transparent; 286 | -fx-border-color: transparent transparent rgba(255,255,255,0.3) transparent; 287 | -fx-border-width: 1; 288 | -fx-background-insets: 0; 289 | -fx-padding: 0 10 0 0; 290 | } 291 | .table-view .column-header, .table-view .filler { 292 | -fx-border-color: transparent; 293 | } 294 | .table-view .column-header .label { 295 | -fx-text-fill: firebrick; 296 | -fx-font-weight: bold; 297 | } 298 | .table-view .table-cell { 299 | -fx-background-color: transparent; 300 | -fx-border-color: transparent; 301 | -fx-text-fill: black; 302 | -fx-alignment: center; 303 | } 304 | .table-view .table-row-cell:filled:selected:focused, 305 | .table-view .table-row-cell:filled:selected { 306 | -fx-background-color: rgba(0,0,0,0.3); 307 | } 308 | 309 | */ 310 | 311 | /******************************************************************************* 312 | 313 | * ListView * 314 | 315 | ******************************************************************************/ 316 | 317 | .list-cell:filled:selected:focused, .list-cell:filled:selected { 318 | -fx-background-color: linear-gradient(#328BDB 0.0%, #207BCF 25.0%, #1973C9 75.0%, #0A65BF 100.0%); 319 | -fx-text-fill: white; 320 | } 321 | 322 | .list-cell{ 323 | -fx-font-size:15.0; 324 | } 325 | 326 | .list-cell:even { /* <=== changed to even */ 327 | -fx-background-color: white; 328 | } 329 | 330 | .list-cell:filled:hover { 331 | -fx-background-color: #0093ff; 332 | -fx-text-fill: white; 333 | } 334 | 335 | 336 | /******************************************************************************* 337 | 338 | * DialogPane * 339 | 340 | ******************************************************************************/ 341 | 342 | 343 | /* .dialog-pane{ 344 | -fx-border-color:white; 345 | -fx-border-width:2.0px; 346 | } 347 | 348 | .dialog-pane > .button-bar > .container { 349 | -fx-background-color:black; 350 | } 351 | 352 | .dialog-pane > .content.label { 353 | -fx-padding: 0.5em 0.5em 0.5em 0.5em; 354 | -fx-background-color: orange; 355 | -fx-text-fill:black; 356 | -fx-font-size:15.0px; 357 | } 358 | 359 | .dialog-pane:header .header-panel { 360 | -fx-background-color: white; 361 | } 362 | 363 | .dialog-pane:header .header-panel .label{ 364 | -fx-background-color: orange; 365 | -fx-background-radius:10.0px; 366 | -fx-text-fill:black; 367 | -fx-font-size:15.0px; 368 | }*/ 369 | 370 | 371 | .dialog-pane .button{ 372 | -fx-background-color: linear-gradient(#38424b 0.0%, #1f2429 20.0%, #191d22 100.0%); 373 | -fx-background-radius: 5.0; 374 | -fx-text-fill: white; 375 | -fx-wrap-text:true; 376 | -fx-effect: dropshadow( three-pass-box , rgba(0.0,0.0,0.0,0.6) , 5.0, 0.0 , 0.0 , 1.0 ); 377 | -fx-font-size: 13.0px; 378 | -fx-cursor:hand; 379 | } 380 | 381 | .dialog-pane .button:hover{ 382 | -fx-background-color:rgb(255.0,119.0,0.0,0.7); 383 | /*-fx-font-weight:bold; */ 384 | } 385 | 386 | 387 | /******************************************************************************* 388 | 389 | * ToolTip * 390 | 391 | ******************************************************************************/ 392 | 393 | .tooltip{ 394 | -fx-background-color: white; 395 | -fx-text-fill:black; 396 | -fx-font-size:11.0; 397 | /* -fx-effect: dropshadow( three-pass-box, black, 10.0, 0.0, 0.0, 0.0); */ 398 | -fx-wrap-text:true; 399 | } 400 | 401 | 402 | 403 | /******************************************************************************* 404 | 405 | * TitledPane * 406 | 407 | ******************************************************************************/ 408 | 409 | 410 | .titled-pane { 411 | -fx-background-color:transparent; 412 | -fx-font-weight:bold; 413 | -fx-text-fill:white; 414 | } 415 | 416 | .titled-pane > *.content { 417 | /*-fx-effect: innershadow(three-pass-box, red , 15.0, 0.0, 0.0, 0.0);*/ 418 | -fx-background-color:transparent; 419 | -fx-border-color:transparent; 420 | } 421 | 422 | .titled-pane > .title { 423 | -fx-background-color: linear-gradient(#38424b 0.0%, #1f2429 20.0%, #191d22 100.0%); 424 | /*-fx-background-color: -fx-box-border, -fx-inner-border, -fx-body-color;*/ 425 | -fx-background-insets: 0.0, 1.0, 2.0; 426 | -fx-background-radius: 5.0 5.0 0.0 0.0, 4.0 4.0 0.0 0.0, 3.0 3.0 0.0 0.0; 427 | -fx-padding: 0.166667em 0.833333em 0.25em 0.833333em; /* 2 10 3 10 */ 428 | } 429 | 430 | 431 | /******************************************************************************* 432 | 433 | * JFXTabPane * 434 | 435 | ******************************************************************************/ 436 | 437 | .jfx-tab-pane#specialJFXTabPane .tab-header-area .tab-header-background { 438 | /*-fx-opacity: 0.0;*/ 439 | -fx-background-color:rgb(0.0,0.0,0.0,0.8); 440 | } 441 | 442 | 443 | .jfx-tab-pane#specialJFXTabPane .tab .tab-label { 444 | -fx-alignment: CENTER; 445 | -fx-text-fill: white; 446 | -fx-font-size: 12.0px; /* before it was 12px */ 447 | -fx-font-weight: bold; 448 | -fx-wrap-text: true; 449 | -fx-cursor:hand; 450 | } 451 | 452 | .jfx-tab-pane#specialJFXTabPane .tab-header-area .jfx-rippler{ 453 | -fx-rippler-fill :firebrick; 454 | -fx-cursor:hand; 455 | } 456 | 457 | .jfx-tab-pane#specialJFXTabPane .tab-header-area .tab-selected-line{ 458 | -fx-stroke : firebrick; 459 | } 460 | 461 | .jfx-tab-pane#specialJFXTabPane .tab:hover .tab-label{ 462 | -fx-text-fill:white; 463 | -fx-background-color:black; 464 | -fx-background-radius: 0.0; 465 | -fx-cursor:hand; 466 | } 467 | 468 | 469 | 470 | /******************************************************************************* 471 | 472 | * TabPane * 473 | 474 | ******************************************************************************/ 475 | 476 | #magicTabPane .tab-header-area { 477 | -fx-padding: 0.0 0.0 0.0 35.0 ; 478 | } 479 | 480 | 481 | .tab-pane .tab-header-area .tab-header-background { 482 | /*-fx-opacity: 0.0;*/ 483 | /*-fx-background-color:linear-gradient(#38424b 0.0%, #1f2429 20.0%, #191d22 100.0%); */ 484 | -fx-background-color:#303030; 485 | } 486 | 487 | .tab-pane{ 488 | -fx-tab-min-width:90.0; 489 | } 490 | 491 | 492 | .tab-pane .tab{ 493 | -fx-background-color: linear-gradient(#38424b 0.0%, #1f2429 20.0%, #191d22 100.0%); 494 | -fx-background-radius: 0.0 0.0 0.0 0.0; 495 | -fx-border-color:transparent transparent transparent transparent; 496 | -fx-focus-color: transparent; 497 | -fx-faint-focus-color: transparent; 498 | -fx-cursor:hand; 499 | } 500 | 501 | .tab-pane .tab:selected{ 502 | -fx-background-color: #FF4A00; 503 | } 504 | 505 | .tab-pane .tab:selected:hover{ 506 | -fx-background-color: #FF4A00; 507 | } 508 | 509 | .tab-pane .tab:hover{ 510 | -fx-background-color:black; 511 | } 512 | 513 | 514 | .tab-pane .tab .tab-label { 515 | -fx-alignment: CENTER; 516 | -fx-text-fill: white; 517 | -fx-font-size: 13.0px; /* before it was 12px */ 518 | -fx-font-weight: bold; 519 | -fx-wrap-text: true; 520 | 521 | } 522 | 523 | .tab-pane .tab:selected .tab-label { 524 | -fx-alignment: CENTER; 525 | -fx-text-fill:black ; /* before it was BROWN */ 526 | /*-fx-font-size:130.0%;*/ 527 | } 528 | 529 | .tab-pane .tab:hover .tab-label{ 530 | -fx-text-fill:black; 531 | -fx-background-color:white; 532 | -fx-background-radius: 0.0 0.0 0.0 0.0; 533 | } 534 | 535 | 536 | /*Special Tab Pane */ 537 | 538 | #SpecialTabPane .tab-header-area .tab-header-background { 539 | -fx-background-color:transparent; 540 | } 541 | 542 | #SpecialTabPane .sTab.tab{ 543 | -fx-background-color: 544 | -darkest-black, 545 | -dark-highlight, 546 | linear-gradient(to bottom, -light-black 2.0%, -dark-black 98.0%); 547 | -fx-background-insets: 0.0, 1.0 1.0 1.0 0.0, 2.0 1.0 1.0 1.0; 548 | -fx-background-radius:0.0 0.0 45.0 45.0; 549 | -fx-text-fill: white; 550 | -fx-font-size: 13.0px; 551 | -fx-font-weight:bold; 552 | -fx-padding:3.0em -1.0em 3.0em -1.0em; 553 | -fx-cursor:hand; 554 | } 555 | 556 | #SpecialTabPane .sTab.tab:hover{ 557 | -fx-background-color:orange; 558 | } 559 | 560 | #SpecialTabPane .sTab.tab:selected{ 561 | -fx-background-color:firebrick; 562 | } 563 | 564 | #SpecialTabPane .sTab.tab:pressed{ 565 | -fx-background-color: 566 | -darkest-black, 567 | rgb(55.0, 57.0, 58.0), 568 | linear-gradient(to top, -light-black 2.0%, -dark-black 98.0%); 569 | } 570 | 571 | #SpecialTabPane .sTab.tab .tab-label{ 572 | -fx-text-fill:white; 573 | -fx-background-color: transparent; 574 | -fx-background-radius:0.0px; 575 | -fx-rotate:90.0; 576 | } 577 | 578 | 579 | #SpecialTabPane .sTab.tab:hover .tab-label,#SpecialTabPane .sTab.tab:selected .tab-label{ 580 | -fx-text-fill:black; 581 | -fx-background-radius: 0.0 45.0 45.0 0.0; 582 | -fx-background-color: white; 583 | } 584 | 585 | 586 | 587 | 588 | /*#SpecialTabPane .tab-header-area .tab-header-background { 589 | -fx-background-color:transparent; 590 | } 591 | 592 | #SpecialTabPane .STab.tab .tab-label{ 593 | -fx-text-fill:white; 594 | -fx-background-color: transparent; 595 | -fx-background-radius:0.0px; 596 | -fx-rotate:90.0; 597 | } 598 | 599 | #SpecialTabPane .STab.tab:selected .tab-label{ 600 | -fx-text-fill:white; 601 | } 602 | 603 | #SpecialTabPane .STab.tab:hover .tab-label{ 604 | -fx-text-fill:black; 605 | -fx-background-radius:5.0px; 606 | -fx-background-color: white; 607 | } 608 | 609 | #SpecialTabPane .STab.tab{ 610 | -fx-background-color:black; 611 | -fx-background-radius: 0.0 0.0 20.0 20.0; 612 | -fx-padding:3.0em 0.0em 3.0em 0.0em; 613 | -fx-cursor:hand; 614 | -fx-effect: innershadow(two-pass-box, white, 15.0, 0.0, 0.0, 0.0); 615 | } 616 | 617 | #SpecialTabPane .STab.tab:selected{ 618 | -fx-effect: innershadow(two-pass-box, red, 15.0, 0.0, 0.0, 0.0); 619 | } 620 | */ 621 | 622 | 623 | /* LibrariesTabPane */ 624 | #MultipleLibrariesTabPane .tab-header-area .tab-header-background { 625 | -fx-background-color:rgb(0.0,0.0,0.0,0.8); 626 | -fx-background-radius:5.0 5.0 0.0 0.0; 627 | } 628 | 629 | 630 | /******************************************************************************* 631 | 632 | * Button * 633 | 634 | ******************************************************************************/ 635 | 636 | /**About Button ----------------------------------------*/ 637 | 638 | .root{ 639 | -light-black: rgb(74.0, 75.0, 78.0); 640 | -dark-highlight: rgb(87.0, 89.0, 92.0); 641 | -dark-black: rgb(39.0, 40.0, 40.0); 642 | -darkest-black: rgb(5.0, 5.0, 5.0); 643 | -mid-gray: rgb(216.0, 222.0, 227.0); 644 | } 645 | 646 | .button , .menu-button { 647 | /*-fx-effect: dropshadow( three-pass-box , rgba(0.0,0.0,0.0,0.6) , 5.0, 0.0 , 0.0 , 1.0 );*/ 648 | /* -fx-background-color: linear-gradient(#38424b 0.0%, #1f2429 20.0%, #191d22 100.0%); */ 649 | -fx-background-color: 650 | -darkest-black, 651 | -dark-highlight, 652 | linear-gradient(to bottom, -light-black 2.0%, -dark-black 98.0%); 653 | -fx-background-insets: 0.0, 1.0 1.0 1.0 0.0, 2.0 1.0 1.0 1.0; 654 | -fx-background-radius: 0.0; 655 | -fx-text-fill: white; 656 | -fx-font-size: 13.0px; 657 | -fx-font-weight:bold; 658 | } 659 | 660 | .button:hover{ 661 | -fx-background-color:firebrick; 662 | /*-fx-background-color: 663 | linear-gradient(from 0.0% 93.0% to 0.0% 100.0%, #a34313 0.0%, #903b12 100.0%), 664 | #9d4024, 665 | #d86e3a, 666 | radial-gradient(center 50.0% 50.0%, radius 100.0%, #ea7f4b, #c54e2c);*/ 667 | } 668 | 669 | .button:pressed , .menu-button:pressed{ 670 | -fx-background-color: 671 | -darkest-black, 672 | rgb(55.0, 57.0, 58.0), 673 | linear-gradient(to top, -light-black 2.0%, -dark-black 98.0%); 674 | } 675 | 676 | 677 | /**About SongButton ----------------------------------------*/ 678 | 679 | .songButton{ 680 | -fx-background-color: linear-gradient(#38424b 0.0%, #1f2429 20.0%, #191d22 100.0%); 681 | -fx-background-radius: 5.0; 682 | -fx-text-fill: white; 683 | -fx-font-size: 13.0px; 684 | 685 | } 686 | 687 | .songButton:hover{ 688 | -fx-background-color:orange; 689 | -fx-text-fill:black; 690 | } 691 | 692 | .songButton:focused{ 693 | -fx-background-color: linear-gradient(to bottom,black 60.0, #141414 60.2%, orange 87.0%); 694 | -fx-text-fill:white; 695 | } 696 | 697 | .songButton:marked{ 698 | -fx-background-color:cyan; 699 | -fx-background-radius:5.0; 700 | -fx-text-fill:black; 701 | -fx-font-size:13.0px; 702 | } 703 | 704 | 705 | /**About ArrowButon(in Libraries) ----------------------------------------*/ 706 | 707 | .arrowButton{ 708 | -fx-background-color:rgb(255.0,255.0,255.0,0.2); 709 | -fx-background-radius:45.0; 710 | -fx-cursor:hand; 711 | } 712 | 713 | .arrowButton2{ 714 | -fx-background-color:rgb(0.0,0.0,0.0,0.9); 715 | -fx-background-radius:45.0; 716 | -fx-cursor:hand; 717 | } 718 | 719 | 720 | 721 | 722 | 723 | 724 | /**About SpecialButton(in Navigation Bar) ----------------------------------------*/ 725 | 726 | .specialButton{ 727 | -fx-background-color:black; 728 | -fx-text-fill:white; 729 | -fx-background-radius:20.0px; 730 | -fx-effect: dropshadow( three-pass-box , orange , 5.0, 0.0 , 0.0 , 1.0 ); 731 | -fx-cursor:hand; 732 | } 733 | 734 | .specialButton:hover{ 735 | -fx-background-color:white; 736 | -fx-text-fill:black; 737 | } 738 | 739 | .windowButton{ 740 | -fx-font-size:9.0; 741 | -fx-font-weight:bold; 742 | } 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | /******************************************************************************* 751 | 752 | * CSS Styles for the ContextMenu,MenuItem,.. * 753 | 754 | ******************************************************************************/ 755 | 756 | 757 | .context-menu { 758 | -fx-background-color:rgb(0.0,0.0,0.0,0.95); 759 | -fx-background-radius:4.0; 760 | /*-fx-border-width:2.0; 761 | -fx-border-style:segments(4.0); */ 762 | -fx-cursor:hand; 763 | } 764 | 765 | .menu-item .label{ 766 | -fx-text-fill:white; 767 | -fx-font-weight:bold; 768 | -fx-font-size:13.0; 769 | } 770 | 771 | .menu-item:focused { 772 | -color: firebrick; 773 | -fx-background-color:linear-gradient( 774 | from 0.0px 0.75em to 0.75em 0.0px, 775 | repeat, 776 | -color 0.0%, 777 | -color 49.0%, 778 | derive(-color, 30.0%) 50.0%, 779 | derive(-color, 30.0%) 99.0% 780 | ); 781 | -fx-background-radius:10.0; 782 | } 783 | 784 | .menu-item:focused .label{ 785 | -fx-text-fill:white; 786 | } 787 | 788 | 789 | 790 | 791 | /******************************************************************************* 792 | 793 | * ScrollPane * 794 | 795 | ******************************************************************************/ 796 | .scroll-pane .viewport { 797 | -fx-background-color: transparent; 798 | } 799 | 800 | .scroll-pane { 801 | -fx-background-color:transparent; 802 | } 803 | 804 | 805 | /* The main scrollbar CSS class of ListView */ 806 | .scroll-bar:horizontal , 807 | .scroll-bar:vertical{ 808 | -fx-background-color:rgb(255.0,255.0,255.0,0.85); 809 | -fx-cursor: hand ; 810 | 811 | } 812 | 813 | /* The increment and decrement button CSS class of scrollbar */ 814 | .increment-button , .decrement-button { 815 | -fx-background-color:transparent; 816 | -fx-background-radius: 2.0em; 817 | 818 | 819 | } 820 | 821 | /* The main scrollbar **track** CSS class */ 822 | .scroll-bar:horizontal .track, 823 | .scroll-bar:vertical .track{ 824 | -fx-background-color: transparent; 825 | -fx-border-color:derive(gray,80.0%); 826 | -fx-background-radius: 2.0em; 827 | -fx-border-radius:2.0em; 828 | } 829 | 830 | 831 | 832 | /* The main scrollbar **thumb** CSS class which we drag every time (movable) */ 833 | .scroll-bar:horizontal .thumb, 834 | .scroll-bar:vertical .thumb { 835 | -fx-background-color:derive(black,90.0%); 836 | -fx-background-insets: 2.0, 0.0, 0.0; 837 | -fx-background-radius: 2.0em; 838 | 839 | 840 | } 841 | 842 | /* ------------------------------------------------------------------------------------- */ 843 | /** EVENT CSS **/ 844 | /* ------------------------------------------------------------------------------------- */ 845 | 846 | /* The main scrollbar **track** CSS class on event of "hover" and "pressed" */ 847 | 848 | .scroll-bar:horizontal:hover .track , 849 | .scroll-bar:horizontal:pressed .track , 850 | .scroll-bar:vertical:hover .track, 851 | .scroll-bar:vertical:pressed .track{ 852 | -fx-background-color: derive(#434343,70.0%); 853 | -fx-opacity: 0.5; 854 | -fx-background-radius: 0.0em; 855 | 856 | } 857 | 858 | /* The main scrollbar **thumb** CSS class on event of "hover" and "pressed" */ 859 | .scroll-bar .thumb:hover, 860 | .scroll-bar .thumb:pressed{ 861 | -fx-background-color: derive(black,50.0%); 862 | } 863 | 864 | 865 | .increment-button:hover , .decrement-button:hover { 866 | -fx-background-color:derive(gray,100.0%); 867 | -fx-border-color:derive(gray,80.0%); 868 | /*-fx-padding:10.0px;*/ 869 | } 870 | 871 | 872 | /*----------------OLD CODE-------------------------------------- */ 873 | 874 | /* .scroll-bar{ 875 | -fx-background-color: transparent; 876 | } 877 | 878 | .scroll-bar:vertical{ 879 | -fx-cursor: hand; 880 | } 881 | 882 | .scroll-bar:horizontal:hover .track , .scroll-bar:horizontal:pressed .track , .scroll-bar:vertical:hover .track, .scroll-bar:vertical:pressed .track{ 883 | -fx-background-color: derive(#434343,20.0%); 884 | -fx-opacity: 0.2; 885 | -fx-background-radius: 0.0em; 886 | } 887 | 888 | .scroll-bar .thumb:hover,.scroll-bar .thumb:pressed{ 889 | -fx-background-color: derive(black,50.0%); 890 | } 891 | 892 | .scroll-bar:horizontal .increment-arrow { 893 | -fx-background-color: black; 894 | -fx-shape: "M 0 0 L 4 8 L 8 0 Z"; 895 | -fx-padding: 0.3em; 896 | -fx-rotate: -90.0; 897 | } 898 | 899 | .scroll-bar:horizontal .decrement-arrow { 900 | -fx-background-color: black; 901 | -fx-shape: "M 0 0 L 4 8 L 8 0 Z"; 902 | -fx-padding: 0.3em; 903 | -fx-rotate: 90.0; 904 | } 905 | 906 | .scroll-bar:vertical .increment-arrow { 907 | -fx-background-color: rgb(211.0,211.0,211.0); 908 | -fx-shape: "M 0 0 L 4 8 L 8 0 Z"; 909 | -fx-padding: 0.3em; 910 | -fx-rotate: 0.0; 911 | } 912 | 913 | 914 | 915 | .scroll-bar:vertical .decrement-arrow { 916 | -fx-background-color: rgb(211.0,211.0,211.0); 917 | -fx-shape: "M 0 0 L 4 8 L 8 0 Z"; 918 | -fx-padding: 0.3em; 919 | -fx-rotate: -180.0; 920 | } 921 | 922 | .scroll-bar:vertical .increment-button, 923 | .scroll-bar:vertical .decrement-button { 924 | -fx-background-color:transparent; 925 | } 926 | 927 | .scroll-bar:horizontal .increment-button, 928 | .scroll-bar:horizontal .decrement-button { 929 | -fx-background-color:transparent; 930 | } 931 | */ 932 | 933 | /*----------------END OF OLD CODE-------------------------------------- */ 934 | 935 | 936 | 937 | /******************************************************************************* 938 | 939 | * TreeView * 940 | 941 | ******************************************************************************/ 942 | 943 | 944 | .tree-cell { 945 | -fx-background-color: black ; 946 | -fx-text-fill: white ; 947 | } 948 | 949 | .tree-cell:selected { 950 | -fx-font-weight: bold ; 951 | -fx-text-fill:orange; 952 | } 953 | .tree-cell { 954 | -fx-padding: 0.75em 0.0em 0.75em 0.0em ; 955 | } 956 | .tree-cell:sub-tree-item { 957 | -fx-padding: 0.25em ; 958 | } 959 | 960 | 961 | 962 | 963 | /******************************************************************************* 964 | 965 | * ProgressBar/ProgressIndicator * 966 | 967 | ******************************************************************************/ 968 | 969 | .progress-indicator{ 970 | -color: firebrick; 971 | -fx-accent:linear-gradient( 972 | from 0.0px 0.75em to 0.75em 0.0px, 973 | repeat, 974 | -color 0.0%, 975 | -color 49.0%, 976 | derive(-color, 30.0%) 50.0%, 977 | derive(-color, 30.0%) 99.0% 978 | ); 979 | } 980 | 981 | .progress-indicator:determinate .determinate-indicator .percentage{ 982 | -fx-fill:white; 983 | } 984 | 985 | /* .progress-bar{ 986 | -fx-progress-color:orange; 987 | } 988 | * */ 989 | 990 | 991 | .progress-bar > .bar { 992 | -fx-accent:firebrick; 993 | /*-fx-background-color:firebrick;*/ 994 | -fx-background-color: linear-gradient( 995 | from 0.0px 0.75em to 0.75em 0.0px, 996 | repeat, 997 | -fx-accent 0.0%, 998 | -fx-accent 49.0%, 999 | derive(-fx-accent, 30.0%) 50.0%, 1000 | derive(-fx-accent, 30.0%) 99.0% 1001 | ); 1002 | 1003 | -fx-background-insets: 1.0 1.0 1.0 1.0; 1004 | -fx-padding: 0.2em; 1005 | } 1006 | 1007 | 1008 | /******************************************************************************* 1009 | 1010 | * TagsBar * 1011 | 1012 | ******************************************************************************/ 1013 | 1014 | .tags-bar { 1015 | -fx-background-color:white; 1016 | -fx-background-radius:15.0px; 1017 | -fx-min-height: 45.0; 1018 | -fx-alignment:center-right; 1019 | -fx-spacing: 3.0px; 1020 | -fx-padding: 3.0px; 1021 | } 1022 | 1023 | .tags-bar .tag { 1024 | -fx-background-color:black; 1025 | -fx-background-radius:10.0px; 1026 | -fx-alignment: center; 1027 | -fx-padding:1.0px; 1028 | -fx-cursor:hand; 1029 | } 1030 | 1031 | .tags-bar .tag .label{ 1032 | -fx-text-fill:white; 1033 | -fx-font-size:14.0px; 1034 | } 1035 | 1036 | 1037 | /******************************************************************************* 1038 | 1039 | * Amazon * 1040 | 1041 | ******************************************************************************/ 1042 | 1043 | .amazon{ 1044 | -fx-background-color:orange; 1045 | -fx-background-radius:10.0; 1046 | } 1047 | 1048 | 1049 | .amazon .label{ 1050 | -fx-border-color: transparent black transparent transparent; 1051 | -fx-font-weight:bold; 1052 | -fx-text-fill:black; 1053 | } 1054 | 1055 | 1056 | /******************************************************************************* 1057 | 1058 | * Library * 1059 | 1060 | ******************************************************************************/ 1061 | 1062 | .library{ 1063 | -fx-background-color:rgb(0.0,0.0,0.0,0.65); 1064 | -fx-background-radius:5.0; 1065 | } 1066 | 1067 | 1068 | .library .libraryNameLabel{ 1069 | -fx-background-color:rgb(0.0,0.0,0.0,0.8); 1070 | -fx-text-fill:white; 1071 | -fx-font-size:14.0; 1072 | -fx-font-weight:bold; 1073 | -fx-font-family:"Younger than me"; 1074 | } 1075 | 1076 | .library:opened .libraryNameLabel{ 1077 | -fx-text-fill:lightgreen !important; 1078 | -fx-font-size:15.0; 1079 | } 1080 | 1081 | 1082 | /******************************************************************************* 1083 | 1084 | * LibrarySettings * 1085 | 1086 | ******************************************************************************/ 1087 | 1088 | .librarySettings { 1089 | -fx-background-color: #202020; 1090 | } 1091 | 1092 | 1093 | .librarySettings .label{ 1094 | -fx-text-fill:white; 1095 | -fx-font-size:12.0px; 1096 | -fx-font-weight:bold; 1097 | -fx-border-color:transparent white transparent transparent ; 1098 | -fx-border-insets: 5.0px; 1099 | } 1100 | 1101 | .librarySettings .text-area{ 1102 | -fx-background-color: white; 1103 | -fx-background-radius:5.0; 1104 | -fx-text-fill:black; 1105 | -fx-font-size:13.0; 1106 | } 1107 | 1108 | .librarySettings .text-area .content{ 1109 | -fx-background-color:transparent; 1110 | } 1111 | 1112 | 1113 | .librarySettings .text-area:focused{ 1114 | -fx-background-color: orange, white; 1115 | -fx-background-insets: -0.1, 2.0; 1116 | } 1117 | 1118 | /******************************************************************************* 1119 | 1120 | * search-box,libraries-search-box * 1121 | 1122 | ******************************************************************************/ 1123 | 1124 | .search-box .text-field, .libraries-search-box .text-field { 1125 | /*-fx-effect: dropshadow( three-pass-box, red , 10.0, 0.0,0.0,0.0);*/ 1126 | /*-fx-background-insets:3.0;*/ 1127 | -fx-background-insets: -0.1, 2.0; 1128 | -fx-background-radius: 5.0; 1129 | -fx-border-radius:5.0; 1130 | -fx-border-width:1.0; 1131 | -fx-prompt-text-fill:black; 1132 | -fx-text-fill:black; 1133 | -fx-font-size:13.0; 1134 | -fx-font-weight:bold; 1135 | } 1136 | 1137 | 1138 | .search-box .text-field:focused, .libraries-search-box .text-field:focused,.search-box .text-field:hover, .libraries-search-box .text-field:hover{ 1139 | /*-fx-effect: null;*/ 1140 | -fx-background-color: firebrick; 1141 | -fx-border-color:white; 1142 | -fx-text-fill:white; 1143 | -fx-prompt-text-fill:white; 1144 | /*-fx-background-insets: -0.1, 2.0;*/ 1145 | } 1146 | 1147 | .search-box-window-item{ 1148 | -fx-background-color:rgb(0.0,0.0,0.0,0.9); 1149 | -fx-background-radius:5.0; 1150 | -fx-text-fill:white; 1151 | -fx-font-size:15.0; 1152 | -fx-font-weight:bold; 1153 | -fx-cursor:hand; 1154 | 1155 | } 1156 | 1157 | .search-box-window-item:hover{ 1158 | -fx-background-color:black; 1159 | -fx-text-fill:firebrick; 1160 | } 1161 | 1162 | .search-box-window-label{ 1163 | -fx-text-fill:white; 1164 | -fx-font-weight:bold; 1165 | -fx-font-size:15.0; 1166 | } 1167 | 1168 | /******************************************************************************* 1169 | 1170 | * StationCofigurator * 1171 | 1172 | ******************************************************************************/ 1173 | .station-configurator{ 1174 | -fx-background-color:white; 1175 | } 1176 | 1177 | .station-configurator .text-area { 1178 | -fx-prompt-text-fill:white; 1179 | } 1180 | 1181 | .station-configurator .jfx-text-field,.jfx-text-area{ 1182 | -fx-background-color:white; 1183 | -fx-focus-color:yellow; 1184 | -fx-unfocus-color:black; 1185 | -fx-prompt-text-fill:black; 1186 | -fx-font-weight:bold; 1187 | } 1188 | 1189 | 1190 | 1191 | /******************************************************************************* 1192 | 1193 | * StarWindow * 1194 | 1195 | ******************************************************************************/ 1196 | 1197 | .starWindow{ 1198 | -fx-background-color:white; 1199 | -fx-background-radius:10.0; 1200 | } 1201 | 1202 | /******************************************************************************* 1203 | 1204 | * SearchSettings * 1205 | 1206 | ******************************************************************************/ 1207 | 1208 | .searchSettings .jfx-text-field{ 1209 | -fx-background-color:black; 1210 | -fx-focus-color:black; 1211 | -fx-unfocus-color:black; 1212 | -fx-prompt-text-fill:black; 1213 | -fx-font-weight:bold; 1214 | } 1215 | 1216 | 1217 | /******************************************************************************* 1218 | 1219 | * xPlayerSecondLayerTabPane * 1220 | 1221 | ******************************************************************************/ 1222 | 1223 | .xPlayerSettingsTab{ 1224 | -fx-font-weight:bold; 1225 | -fx-font-size:15.0; 1226 | -fx-text-fill:black; 1227 | } 1228 | 1229 | 1230 | 1231 | /******************************************************************************* 1232 | 1233 | * DragAdjustableLabel * 1234 | 1235 | ******************************************************************************/ 1236 | 1237 | @font-face{ 1238 | src: url("../fonts/Younger than me.ttf"); 1239 | } 1240 | 1241 | .drag-adjustable-label{ 1242 | -fx-background-color:white; 1243 | -fx-background-radius:15.0; 1244 | -fx-font-size:18.0; 1245 | -fx-font-family:"Younger than me"; 1246 | -fx-text-fill:black; 1247 | -fx-font-weight:bold; 1248 | } 1249 | 1250 | #LoginScreenTopLabel{ 1251 | -fx-font-family:"Younger than me"; 1252 | } 1253 | 1254 | /******************************************************************************* 1255 | 1256 | * SideBar * 1257 | 1258 | ******************************************************************************/ 1259 | 1260 | 1261 | .miniControl{ 1262 | -fx-text-fill:black; 1263 | -fx-background-color:white; 1264 | -fx-background-radius:10.0; 1265 | -fx-cursor:hand; 1266 | } 1267 | 1268 | #sideBar{ 1269 | -fx-background-color:#202020; 1270 | } 1271 | 1272 | .sideBarSectionLabel{ 1273 | -fx-border-width:2.0; 1274 | -fx-border-color:black transparent transparent transparent; 1275 | -fx-text-fill:black; 1276 | -fx-font-weight:bold; 1277 | -fx-font-size:15.0; 1278 | } 1279 | 1280 | 1281 | .windowMode{ 1282 | -fx-background-color:black; 1283 | -fx-border-radius:10.0; 1284 | -fx-border-width:2.0; 1285 | -fx-text-fill:white; 1286 | -fx-font-weight:bold; 1287 | -fx-cursor:hand; 1288 | } 1289 | 1290 | .windowMode:hover{ 1291 | -fx-background-color:firebrick; 1292 | } 1293 | 1294 | .windowMode:selected{ 1295 | -fx-text-fill:yellow; 1296 | -fx-background-color:firebrick; 1297 | } 1298 | 1299 | 1300 | 1301 | /******************************************************************************* 1302 | 1303 | * .menu-button * 1304 | 1305 | ******************************************************************************/ 1306 | 1307 | .menu-button{ 1308 | -fx-cursor:hand; 1309 | } 1310 | 1311 | .menu-button .label{ 1312 | -fx-text-fill:white; 1313 | } 1314 | 1315 | .menu-button .label:hover{ 1316 | -fx-background-color:rgb(0.0,0.0,0.0,0.7); 1317 | -fx-text-fill:white; 1318 | } 1319 | 1320 | .visWindowMenuButton .label{ 1321 | -fx-text-fill:white; 1322 | } 1323 | 1324 | .visWindowMenuButton .label:hover{ 1325 | -fx-background-color:rgb(0.0,0.0,0.0,0.7); 1326 | -fx-text-fill:white; 1327 | } 1328 | 1329 | 1330 | /******************************************************************************* 1331 | 1332 | * VisualizerWindow * 1333 | 1334 | ******************************************************************************/ 1335 | 1336 | 1337 | .transparency-slider{ 1338 | -fx-cursor:hand; 1339 | } 1340 | 1341 | .transparency-slider .axis .axis-tick-mark, .slider .axis .axis-minor-tick-mark { 1342 | -fx-text-fill:white; 1343 | -fx-stroke:white; 1344 | } 1345 | 1346 | 1347 | .transparency-slider .axis { 1348 | -fx-tick-label-fill: white; 1349 | -fx-tick-label-font-weight: bold; 1350 | -fx-tick-length: 7.0px; 1351 | } 1352 | 1353 | 1354 | /******************************************************************************* 1355 | 1356 | * BorderLessScene * 1357 | 1358 | ******************************************************************************/ 1359 | 1360 | /* Universal */ 1361 | .leftPane:hover , .rightPane:hover , .topPane:hover , .bottomPane:hover , .topLeftPane:hover , .topRightPane:hover , .bottomRightPane:hover , .bottomLeftPane:hover { 1362 | -fx-background-color:rgb(255.0,0.0,0.0,0.8); 1363 | -fx-border-width:2.0; 1364 | /*-fx-border-style:dotted ; */ 1365 | } 1366 | 1367 | /* Sides */ 1368 | .leftPane:hover{ 1369 | -fx-border-color:transparent transparent transparent black; 1370 | } 1371 | 1372 | .rightPane:hover{ 1373 | -fx-border-color:transparent black transparent transparent; 1374 | } 1375 | 1376 | .topPane:hover{ 1377 | -fx-border-color:black transparent transparent transparent; 1378 | } 1379 | 1380 | .bottomPane:hover{ 1381 | -fx-border-color:transparent transparent black transparent; 1382 | } 1383 | 1384 | /* Corners */ 1385 | 1386 | .topLeftPane:hover{ 1387 | -fx-border-color:black transparent transparent black; 1388 | } 1389 | 1390 | 1391 | .topRightPane:hover{ 1392 | -fx-border-color:black black transparent transparent; 1393 | } 1394 | 1395 | 1396 | .bottomRightPane:hover{ 1397 | -fx-border-color:transparent black black transparent; 1398 | } 1399 | 1400 | .bottomLeftPane:hover{ 1401 | -fx-border-color:transparent transparent black black; 1402 | } 1403 | 1404 | 1405 | 1406 | /******************************************************************************* 1407 | 1408 | * UpdateScreen * 1409 | 1410 | ******************************************************************************/ 1411 | 1412 | #updateScreenButtonLabel{ 1413 | 1414 | -fx-font-family:"Younger than me"; 1415 | -fx-text-fill:blue; 1416 | 1417 | } 1418 | 1419 | 1420 | 1421 | /******************************************************************************* 1422 | 1423 | * Label-Menu-Item * 1424 | 1425 | ******************************************************************************/ 1426 | .title-menu-item .label{ 1427 | -fx-text-alignment:center; 1428 | } 1429 | 1430 | .title-menu-item .label .text{ 1431 | -fx-text-alignment:center; 1432 | } 1433 | 1434 | 1435 | /* When the Label-Menu-Item is disabled [Always it is cause i don't want the user to be able to click it] */ 1436 | .title-menu-item:disabled { 1437 | -fx-opacity: 1.0; 1438 | -fx-border-color:transparent white white white; 1439 | -fx-cursor:default; 1440 | } 1441 | 1442 | .title-menu-item:disabled:hover{ 1443 | -fx-background-color: transparent; 1444 | } 1445 | 1446 | .title-menu-item:disabled .label { 1447 | -fx-opacity: 1.0; 1448 | -fx-font-size:11.0; 1449 | -fx-font-weight:bold; 1450 | -fx-text-fill:white; 1451 | -fx-text-alignment:center; 1452 | -fx-text-fill: #BBFF00; 1453 | } 1454 | 1455 | .title-menu-item:disabled:hover .label { 1456 | -fx-background-color: transparent; 1457 | } 1458 | 1459 | 1460 | -------------------------------------------------------------------------------- /spartan.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /spartanizer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /src/main/java/com/goxr3plus/xr3playerupdater/application/Main.java: -------------------------------------------------------------------------------- 1 | package main.java.com.goxr3plus.xr3playerupdater.application; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.IOException; 6 | import java.io.InputStreamReader; 7 | import java.net.MalformedURLException; 8 | import java.net.URL; 9 | import java.nio.file.Paths; 10 | import java.util.List; 11 | import java.util.logging.Level; 12 | import java.util.logging.Logger; 13 | 14 | import javafx.animation.PauseTransition; 15 | import javafx.application.Application; 16 | import javafx.application.Platform; 17 | import javafx.beans.value.ChangeListener; 18 | import javafx.scene.Scene; 19 | import javafx.stage.Stage; 20 | import javafx.util.Duration; 21 | import main.java.com.goxr3plus.xr3playerupdater.presenter.DownloadModeController; 22 | import main.java.com.goxr3plus.xr3playerupdater.services.DownloadService; 23 | import main.java.com.goxr3plus.xr3playerupdater.services.ExportZipService; 24 | import main.java.com.goxr3plus.xr3playerupdater.tools.ActionTool; 25 | import main.java.com.goxr3plus.xr3playerupdater.tools.InfoTool; 26 | import main.java.com.goxr3plus.xr3playerupdater.tools.NotificationType; 27 | 28 | public class Main extends Application { 29 | 30 | //================Variables================ 31 | 32 | /** 33 | * This is the folder where the update will take place [ obviously the 34 | * parent folder of the application] 35 | */ 36 | private File updateFolder = new File(InfoTool.getBasePathForClass(Main.class)); 37 | 38 | /** 39 | * Download update as a ZIP Folder , this is the prefix name of the ZIP 40 | * folder 41 | */ 42 | private static String foldersNamePrefix; 43 | 44 | /** Update to download */ 45 | private static int update; 46 | 47 | /** The name of the application you want to update */ 48 | private String applicationName; 49 | 50 | //================Listeners================ 51 | 52 | //Create a change listener 53 | ChangeListener listener = (observable , oldValue , newValue) -> { 54 | if (newValue.intValue() == 1) 55 | exportUpdate(); 56 | }; 57 | //Create a change listener 58 | ChangeListener listener2 = (observable , oldValue , newValue) -> { 59 | if (newValue.intValue() == 1) 60 | packageUpdate(); 61 | }; 62 | 63 | //================Services================ 64 | 65 | DownloadService downloadService; 66 | ExportZipService exportZipService; 67 | 68 | //============================================= 69 | 70 | private Stage window; 71 | private static DownloadModeController downloadMode = new DownloadModeController(); 72 | 73 | //--------------------------------------------------------------------- 74 | 75 | @Override 76 | public void start(Stage primaryStage) throws Exception { 77 | 78 | //Parse Arguments -> I want one parameter -> for example [45] which is the update i want 79 | List applicationParameters = super.getParameters().getRaw(); 80 | if (!applicationParameters.isEmpty()) 81 | update = Integer.valueOf(applicationParameters.get(0)); 82 | else { 83 | System.out.println("No arguments given...\nApplication exit."); 84 | System.exit(0); 85 | } 86 | 87 | //We need this in order to restart the update when it fails 88 | System.out.println("XR3PlayerUpdater Application Started"); 89 | 90 | // --------Window--------- 91 | window = primaryStage; 92 | window.setResizable(false); 93 | window.centerOnScreen(); 94 | window.getIcons().add(InfoTool.getImageFromResourcesFolder("icon.png")); 95 | window.centerOnScreen(); 96 | window.setOnCloseRequest(exit -> { 97 | 98 | //Check 99 | if (exportZipService != null && exportZipService.isRunning()) { 100 | ActionTool.showNotification("Message", "Can not exit right now cause it will corrupt the update", Duration.seconds(5), NotificationType.WARNING); 101 | exit.consume(); 102 | return; 103 | } 104 | 105 | //Question 106 | if (!ActionTool.doQuestion("Soore you want to exit " + applicationName + " Updater?", window)) 107 | exit.consume(); 108 | else { 109 | 110 | //Delete the ZIP Folder 111 | deleteZipFolder(); 112 | 113 | //Exit the application 114 | System.exit(0); 115 | } 116 | 117 | }); 118 | 119 | // Scene 120 | Scene scene = new Scene(downloadMode); 121 | scene.getStylesheets().add(getClass().getResource(InfoTool.STYLES + InfoTool.APPLICATIONCSS).toExternalForm()); 122 | window.setScene(scene); 123 | 124 | //Show 125 | window.show(); 126 | 127 | //Start 128 | prepareForUpdate("XR3Player"); 129 | } 130 | 131 | //------------------------------------------------------------------------------------------------------------------------------- 132 | 133 | /** 134 | * Prepare for the Update 135 | * 136 | * @param applicationName 137 | */ 138 | public void prepareForUpdate(String applicationName) { 139 | this.applicationName = applicationName; 140 | window.setTitle(applicationName + " Updater"); 141 | 142 | //FoldersNamePrefix 143 | foldersNamePrefix = updateFolder.getAbsolutePath() + File.separator + applicationName + " Update Package " + update; 144 | 145 | //Check the Permissions 146 | if (checkPermissions()) { 147 | downloadMode.getProgressLabel().setText("Checking permissions"); 148 | downloadUpdate("https://github.com/goxr3plus/XR3Player/releases/download/V3." + update + "/XR3Player.Update." + update + ".zip"); 149 | } else { 150 | 151 | //Update 152 | downloadMode.getProgressBar().setProgress(-1); 153 | downloadMode.getProgressLabel().setText("Please close the updater"); 154 | 155 | //Show Message 156 | ActionTool.showNotification("Permission Denied[FATAL ERROR]", 157 | "Application has no permission to write inside this folder:\n [ " + updateFolder.getAbsolutePath() 158 | + " ]\n -> I am working to find a solution for this error\n -> You can download " + applicationName + " manually :) ]", 159 | Duration.minutes(1), NotificationType.ERROR); 160 | } 161 | } 162 | 163 | /** 164 | * In order to update this application must have READ,WRITE AND CREATE 165 | * permissions on the current folder 166 | */ 167 | public boolean checkPermissions() { 168 | 169 | //Check for permission to Create 170 | try { 171 | File sample = new File(updateFolder.getAbsolutePath() + File.separator + "empty123123124122354345436.txt"); 172 | /* 173 | * Create and delete a dummy file in order to check file 174 | * permissions. Maybe there is a safer way for this check. 175 | */ 176 | sample.createNewFile(); 177 | sample.delete(); 178 | } catch (IOException e) { 179 | //Error message shown to user. Operation is aborted 180 | return false; 181 | } 182 | 183 | //Also check for Read and Write Permissions 184 | return updateFolder.canRead() && updateFolder.canWrite(); 185 | } 186 | 187 | /** Try to download the Update */ 188 | private void downloadUpdate(String downloadURL) { 189 | 190 | if (InfoTool.isReachableByPing("www.google.com")) { 191 | 192 | //Download it 193 | try { 194 | //Delete the ZIP Folder 195 | deleteZipFolder(); 196 | 197 | //Create the downloadService 198 | downloadService = new DownloadService(); 199 | 200 | //Add Bindings 201 | downloadMode.getProgressBar().progressProperty().bind(downloadService.progressProperty()); 202 | downloadMode.getProgressLabel().textProperty().bind(downloadService.messageProperty()); 203 | downloadMode.getProgressLabel().textProperty().addListener((observable , oldValue , newValue) -> { 204 | //Give try again option to the user 205 | if (newValue.toLowerCase().contains("failed")) 206 | downloadMode.getFailedStackPane().setVisible(true); 207 | }); 208 | downloadMode.getProgressBar().progressProperty().addListener(listener); 209 | window.setTitle("Downloading ( " + this.applicationName + " ) Update -> " + this.update); 210 | 211 | //Start 212 | downloadService.startDownload(new URL(downloadURL), Paths.get(foldersNamePrefix + ".zip")); 213 | } catch (MalformedURLException e) { 214 | e.printStackTrace(); 215 | } 216 | 217 | } else { 218 | //Update 219 | downloadMode.getProgressBar().setProgress(-1); 220 | downloadMode.getProgressLabel().setText("No internet Connection,please exit..."); 221 | 222 | //Delete the ZIP Folder 223 | deleteZipFolder(); 224 | 225 | //Give try again option to the user 226 | downloadMode.getFailedStackPane().setVisible(true); 227 | } 228 | } 229 | 230 | /** Exports the Update ZIP Folder */ 231 | private void exportUpdate() { 232 | 233 | //Create the ExportZipService 234 | exportZipService = new ExportZipService(); 235 | 236 | //Remove Listeners 237 | downloadMode.getProgressBar().progressProperty().removeListener(listener); 238 | 239 | //Add Bindings 240 | downloadMode.getProgressBar().progressProperty().bind(exportZipService.progressProperty()); 241 | downloadMode.getProgressLabel().textProperty().bind(exportZipService.messageProperty()); 242 | downloadMode.getProgressBar().progressProperty().addListener(listener2); 243 | 244 | //Start it 245 | exportZipService.exportZip(foldersNamePrefix + ".zip", updateFolder.getAbsolutePath()); 246 | 247 | } 248 | 249 | /** 250 | * After the exporting has been done i must delete the old update files and 251 | * add the new ones 252 | */ 253 | private void packageUpdate() { 254 | 255 | //Remove Listeners 256 | downloadMode.getProgressBar().progressProperty().removeListener(listener2); 257 | 258 | //Bindings 259 | downloadMode.getProgressBar().progressProperty().unbind(); 260 | downloadMode.getProgressLabel().textProperty().unbind(); 261 | 262 | //Packaging 263 | downloadMode.getProgressBar().setProgress(-1); 264 | downloadMode.getProgressLabel().setText("Starting " + applicationName + "..."); 265 | 266 | //Delete the ZIP Folder 267 | deleteZipFolder(); 268 | 269 | //Start XR3Player 270 | restartApplication(applicationName); 271 | 272 | } 273 | 274 | //--------------------------------------------------------------------------------------- 275 | 276 | /** Calling this method to start the main Application which is XR3Player */ 277 | public static void restartApplication(String appName) { 278 | 279 | // Restart XR3Player 280 | new Thread(() -> { 281 | String path = InfoTool.getBasePathForClass(Main.class); 282 | String[] applicationPath = { new File(path + appName + ".jar").getAbsolutePath() }; 283 | 284 | //Show message that application is restarting 285 | Platform.runLater(() -> ActionTool.showNotification("Starting " + appName, 286 | "Application Path:[ " + applicationPath[0] + " ]\n\tIf this takes more than [20] seconds either the computer is slow or it has failed....", Duration.seconds(25), 287 | NotificationType.INFORMATION)); 288 | 289 | try { 290 | 291 | //Delete the ZIP Folder 292 | deleteZipFolder(); 293 | 294 | //------------Wait until Application is created 295 | File applicationFile = new File(applicationPath[0]); 296 | while (!applicationFile.exists()) { 297 | Thread.sleep(50); 298 | System.out.println("Waiting " + appName + " Jar to be created..."); 299 | } 300 | 301 | System.out.println(appName + " Path is : " + applicationPath[0]); 302 | 303 | //Create a process builder 304 | ProcessBuilder builder = new ProcessBuilder("java", "-jar", applicationPath[0], !"XR3PlayerUpdater".equals(appName) ? "" : String.valueOf(update)); 305 | builder.redirectErrorStream(true); 306 | Process process = builder.start(); 307 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); 308 | 309 | // Wait n seconds 310 | PauseTransition pause = new PauseTransition(Duration.seconds(10)); 311 | pause.setOnFinished(f -> Platform.runLater(() -> ActionTool.showNotification("Starting " + appName + " failed", 312 | "\nApplication Path: [ " + applicationPath[0] + " ]\n\tTry to do it manually...", Duration.seconds(10), NotificationType.ERROR))); 313 | pause.play(); 314 | 315 | // Continuously Read Output to check if the main application started 316 | String line; 317 | while (process.isAlive()) 318 | while ( ( line = bufferedReader.readLine() ) != null) { 319 | if (line.isEmpty()) 320 | break; 321 | //This line is being printed when XR3Player Starts 322 | //So the AutoUpdater knows that it must exit 323 | else if (line.contains("XR3Player ready to rock!")) 324 | System.exit(0); 325 | } 326 | 327 | } catch (IOException | InterruptedException ex) { 328 | Logger.getLogger(Main.class.getName()).log(Level.INFO, null, ex); 329 | 330 | // Show failed message 331 | Platform.runLater(() -> Platform.runLater(() -> ActionTool.showNotification("Starting " + appName + " failed", 332 | "\nApplication Path: [ " + applicationPath[0] + " ]\n\tTry to do it manually...", Duration.seconds(10), NotificationType.ERROR))); 333 | 334 | } 335 | }, "Start Application Thread").start(); 336 | } 337 | 338 | /** 339 | * Delete the ZIP folder from the update 340 | * 341 | * @return True if deleted , false if not 342 | */ 343 | public static boolean deleteZipFolder() { 344 | return new File(foldersNamePrefix + ".zip").delete(); 345 | } 346 | 347 | public static void main(String[] args) { 348 | 349 | launch(args); 350 | } 351 | 352 | } 353 | -------------------------------------------------------------------------------- /src/main/java/com/goxr3plus/xr3playerupdater/presenter/DownloadModeController.java: -------------------------------------------------------------------------------- 1 | package main.java.com.goxr3plus.xr3playerupdater.presenter; 2 | 3 | import java.io.IOException; 4 | import java.util.logging.Level; 5 | import java.util.logging.Logger; 6 | 7 | import javafx.fxml.FXML; 8 | import javafx.fxml.FXMLLoader; 9 | import javafx.scene.control.Button; 10 | import javafx.scene.control.Label; 11 | import javafx.scene.control.ProgressIndicator; 12 | import javafx.scene.layout.BorderPane; 13 | import javafx.scene.layout.StackPane; 14 | import javafx.scene.shape.Rectangle; 15 | import main.java.com.goxr3plus.xr3playerupdater.application.Main; 16 | import main.java.com.goxr3plus.xr3playerupdater.tools.ActionTool; 17 | import main.java.com.goxr3plus.xr3playerupdater.tools.InfoTool; 18 | 19 | public class DownloadModeController extends BorderPane { 20 | 21 | //----------------------------------------------------- 22 | 23 | @FXML 24 | private Rectangle rectangle; 25 | 26 | @FXML 27 | private ProgressIndicator progressBar; 28 | 29 | @FXML 30 | private Label progressLabel; 31 | 32 | @FXML 33 | private StackPane failedStackPane; 34 | 35 | @FXML 36 | private Button tryAgainButton; 37 | 38 | @FXML 39 | private Button downloadManually; 40 | 41 | // ------------------------------------------------------------- 42 | 43 | /** The logger. */ 44 | private final Logger logger = Logger.getLogger(getClass().getName()); 45 | 46 | /** 47 | * Constructor. 48 | */ 49 | public DownloadModeController() { 50 | 51 | // ------------------------------------FXMLLOADER ---------------------------------------- 52 | FXMLLoader loader = new FXMLLoader(getClass().getResource(InfoTool.FXMLS + "DownloadModeController.fxml")); 53 | loader.setController(this); 54 | loader.setRoot(this); 55 | 56 | try { 57 | loader.load(); 58 | } catch (IOException ex) { 59 | logger.log(Level.SEVERE, "", ex); 60 | } 61 | 62 | } 63 | 64 | /** 65 | * Called as soon as .FXML is loaded from FXML Loader 66 | */ 67 | @FXML 68 | private void initialize() { 69 | 70 | //-- failedStackPane 71 | failedStackPane.setVisible(false); 72 | 73 | //-- tryAgainButton 74 | tryAgainButton.setOnAction(a -> { 75 | Main.restartApplication("XR3PlayerUpdater"); 76 | tryAgainButton.setDisable(true); 77 | }); 78 | 79 | //== Download Manually 80 | downloadManually.setOnAction(a -> ActionTool.openWebSite("https://sourceforge.net/projects/xr3player/")); 81 | 82 | } 83 | 84 | public ProgressIndicator getProgressBar() { 85 | return progressBar; 86 | } 87 | 88 | public Label getProgressLabel() { 89 | return progressLabel; 90 | } 91 | 92 | /** 93 | * @return the failedStackPane 94 | */ 95 | public StackPane getFailedStackPane() { 96 | return failedStackPane; 97 | } 98 | 99 | /** 100 | * @return the downloadManually 101 | */ 102 | public Button getDownloadManually() { 103 | return downloadManually; 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/com/goxr3plus/xr3playerupdater/services/DownloadService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package main.java.com.goxr3plus.xr3playerupdater.services; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.net.URL; 9 | import java.net.URLConnection; 10 | import java.nio.channels.Channels; 11 | import java.nio.channels.FileChannel; 12 | import java.nio.file.Path; 13 | import java.nio.file.StandardOpenOption; 14 | import java.util.logging.Level; 15 | import java.util.logging.Logger; 16 | 17 | import javafx.beans.property.ObjectProperty; 18 | import javafx.beans.property.SimpleObjectProperty; 19 | import javafx.concurrent.Service; 20 | import javafx.concurrent.Task; 21 | import main.java.com.goxr3plus.xr3playerupdater.tools.InfoTool; 22 | 23 | /** 24 | * JavaFX Service which is Capable of Downloading Files from the Internet to the LocalHost 25 | * 26 | * @author GOXR3PLUS 27 | * 28 | */ 29 | public class DownloadService extends Service { 30 | 31 | /** 32 | * The logger of the class 33 | */ 34 | private final Logger logger = Logger.getLogger(DownloadService.class.getName()); 35 | 36 | // ----- 37 | private long totalBytes; 38 | private boolean succeeded; 39 | private volatile boolean stopThread; 40 | 41 | private final ObjectProperty remoteResourceLocation = new SimpleObjectProperty<>(); 42 | private final ObjectProperty pathToLocalResource = new SimpleObjectProperty<>(); 43 | 44 | private Thread copyThread; 45 | 46 | /** 47 | * Constructor 48 | */ 49 | public DownloadService() { 50 | 51 | setOnSucceeded(s -> { 52 | System.out.println("Succeeded with value: " + super.getValue() + " , Copy Thread is Alive? " + copyThread.isAlive()); 53 | done(); 54 | }); 55 | 56 | setOnFailed(f -> { 57 | System.out.println("Failed with value: " + super.getValue() + " , Copy Thread is Alive? " + copyThread.isAlive()); 58 | done(); 59 | }); 60 | 61 | setOnCancelled(c -> { 62 | System.out.println("Cancelled with value: " + super.getValue() + " , Copy Thread is Alive? " + copyThread.isAlive()); 63 | done(); 64 | }); 65 | } 66 | 67 | private volatile FileChannel zip; 68 | 69 | @Override 70 | protected Task createTask() { 71 | return new Task() { 72 | @Override 73 | protected Boolean call() throws Exception { 74 | 75 | // Succeeded boolean 76 | succeeded = true; 77 | 78 | // URL and LocalFile 79 | //URL urlFile = new URL(java.net.URLDecoder.decode(urlString, "UTF-8")) 80 | File destinationFile = new File(pathToLocalResource.get().toString()); 81 | 82 | //Update the message 83 | super.updateMessage("Connecting with Server"); 84 | String failMessage; 85 | 86 | try { 87 | 88 | // Open the connection and get totalBytes 89 | URLConnection connection = remoteResourceLocation.get().openConnection(); 90 | totalBytes = Long.parseLong(connection.getHeaderField("Content-Length")); 91 | 92 | // ------------------------------------------------ Copy the File to External Thread------------------------------------------------------- 93 | copyThread = new Thread(() -> { 94 | // Start File Copy 95 | try { 96 | zip = FileChannel.open(pathToLocalResource.get(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE); 97 | 98 | zip.transferFrom(Channels.newChannel(connection.getInputStream()), 0, Long.MAX_VALUE); 99 | // Files.copy(dl.openStream(), fl.toPath(),StandardCopyOption.REPLACE_EXISTING) 100 | 101 | } catch (Exception ex) { 102 | stopThread = true; 103 | logger.log(Level.WARNING, "DownloadService failed", ex); 104 | } finally { 105 | try { 106 | zip.close(); 107 | } catch (IOException ex) { 108 | ex.printStackTrace(); 109 | } 110 | } 111 | 112 | System.out.println("Copy Thread exited..."); 113 | }); 114 | // Set to Daemon 115 | copyThread.setDaemon(true); 116 | // Start the Thread 117 | copyThread.start(); 118 | // ----------------------------------------------- End: Copy the File to External Thread----------------------------------------------- 119 | 120 | // --------------------------------------------------Check the %100 Progress------------------------------------------------------------- 121 | long outPutFileLength; 122 | long previousLength = 0; 123 | //actually it is millisecondsFailTime*50(cause Thread is sleeping for 50 milliseconds 124 | int millisecondsFailTime = 40; 125 | // While Loop 126 | while ( ( outPutFileLength = destinationFile.length() ) < totalBytes && !stopThread) { 127 | 128 | // Check the previous length 129 | if (previousLength != outPutFileLength) { 130 | previousLength = outPutFileLength; 131 | millisecondsFailTime = 0; 132 | } else 133 | ++millisecondsFailTime; 134 | 135 | // 2 Seconds passed without response 136 | if (millisecondsFailTime == 40 || stopThread) 137 | break; 138 | 139 | // Update Progress 140 | super.updateMessage("Downloading: [ " + InfoTool.getFileSizeEdited(totalBytes) + " ] Progress: [ " + ( outPutFileLength * 100 ) / totalBytes + " % ]"); 141 | super.updateProgress( ( outPutFileLength * 100 ) / totalBytes, 100); 142 | System.out.println( 143 | "Current Bytes:" + outPutFileLength + " ,|, TotalBytes:" + totalBytes + " ,|, Current Progress: " + ( outPutFileLength * 100 ) / totalBytes + " %"); 144 | 145 | // Sleep 146 | try { 147 | Thread.sleep(50); 148 | } catch (InterruptedException ex) { 149 | logger.log(Level.WARNING, "", ex); 150 | } 151 | } 152 | 153 | //Update to show 100% 154 | super.updateMessage("Downloading: [ " + InfoTool.getFileSizeEdited(totalBytes) + " ] Progress: [ " + ( outPutFileLength * 100 ) / totalBytes + " % ]"); 155 | super.updateProgress( ( outPutFileLength * 100 ) / totalBytes, 100); 156 | System.out.println( 157 | "Current Bytes:" + outPutFileLength + " ,|, TotalBytes:" + totalBytes + " ,|, Current Progress: " + ( outPutFileLength * 100 ) / totalBytes + " %"); 158 | 159 | // 2 Seconds passed without response 160 | if (millisecondsFailTime == 40) 161 | succeeded = false; 162 | // ---------------------------------------------------End: Check the %100 Progress----------------------------------------------------- 163 | 164 | } catch (Exception ex) { 165 | succeeded = false; 166 | // Stop the External Thread which is updating the %100 progress 167 | stopThread = true; 168 | logger.log(Level.WARNING, "DownloadService failed", ex); 169 | failMessage = ex.getMessage(); 170 | } 171 | 172 | //-------------------------------------------------------Finally------------------------------------------------------------------------------- 173 | 174 | System.out.println("\nTrying to interrupt[shoot with an assault rifle] the copy Thread"); 175 | 176 | // ---FORCE STOP COPY FILES 177 | if (!succeeded && copyThread != null && copyThread.isAlive()) { 178 | zip.close(); 179 | copyThread.interrupt(); 180 | System.out.println("\nDone an interrupt to the copy Thread"); 181 | 182 | // Run a Looping checking if the copyThread has stopped... 183 | while (copyThread.isAlive()) { 184 | System.out.println("Copy Thread is still Alive,refusing to die."); 185 | Thread.sleep(50); 186 | } 187 | } 188 | 189 | //Check if failed && Update the message 190 | if (!succeeded) 191 | super.updateMessage("Failed..." + ( InfoTool.isReachableByPing("www.google.com") ? "" : "No internet Connection" ) + " , please exit..."); 192 | 193 | System.out 194 | .println("\n ->Download Service exited:[Value=" + succeeded + "]" + " Copy Thread is Alive? " + ( copyThread == null ? "" : copyThread.isAlive() + "\n" )); 195 | 196 | //----------------------------------------------------- End: Finally------------------------------------------------------------------------------- 197 | 198 | return succeeded; 199 | } 200 | 201 | }; 202 | } 203 | 204 | /** 205 | * The Service is done 206 | * 207 | * @param value 208 | */ 209 | private boolean done() { 210 | 211 | boolean fileDeleted = false; 212 | 213 | //Check if The Service Succeeded 214 | if (!succeeded) 215 | fileDeleted = new File(pathToLocalResource.get().toString()).delete(); 216 | 217 | return fileDeleted; 218 | } 219 | 220 | /** 221 | * Start the Download Service [[SuppressWarningsSpartan]] 222 | */ 223 | public void startDownload(URL remoteResourceLocation , Path pathToLocalResource) { 224 | //!Running and Report null 225 | if (!isRunning() && pathToLocalResource != null && remoteResourceLocation != null) { 226 | 227 | //Set 228 | this.setRemoteResourceLocation(remoteResourceLocation); 229 | this.setPathToLocalResource(pathToLocalResource); 230 | 231 | // setRemoteResourceLocation(new URL(java.net.URLDecoder.decode(remoteResourceLocation, "UTF-8"))) 232 | 233 | //TotalBytes 234 | totalBytes = 0; 235 | 236 | //Restart 237 | restart(); 238 | } else 239 | logger.log(Level.INFO, "Please specify [Remote Resource Location] and [ Path to Local Resource ]"); 240 | 241 | } 242 | 243 | //----------------------@Overrided methods-------------------------------------- 244 | 245 | @Override 246 | protected void succeeded() { 247 | super.succeeded(); 248 | } 249 | 250 | @Override 251 | protected void cancelled() { 252 | super.cancelled(); 253 | } 254 | 255 | @Override 256 | protected void failed() { 257 | super.failed(); 258 | } 259 | 260 | //----------------------Getters-------------------------------------- 261 | 262 | /** 263 | * @return The remoteResouceLocation 264 | */ 265 | public final URL getRemoteResourceLocation() { 266 | return remoteResourceLocation.get(); 267 | } 268 | 269 | /** 270 | * @return The PathToLocalResource 271 | */ 272 | public final Path getPathToLocalResource() { 273 | return pathToLocalResource.get(); 274 | 275 | } 276 | 277 | //----------------------Setters-------------------------------------- 278 | 279 | /** 280 | * Set the remote resource location 281 | * 282 | * @param remoteResourceLocation 283 | */ 284 | public final void setRemoteResourceLocation(URL remoteResourceLocation) { 285 | this.remoteResourceLocation.set(remoteResourceLocation); 286 | } 287 | 288 | /** 289 | * Set the path to the local resource 290 | * 291 | * @param pathToLocalResource 292 | */ 293 | public final void setPathToLocalResource(Path pathToLocalResource) { 294 | this.pathToLocalResource.set(pathToLocalResource); 295 | } 296 | 297 | //----------------------Properties Getters-------------------------------------- 298 | 299 | /** 300 | * @return remoteResourceLocation property 301 | */ 302 | public ObjectProperty remoteResourceLocationProperty() { 303 | return remoteResourceLocation; 304 | } 305 | 306 | /** 307 | * @return pathToLocalResource property 308 | */ 309 | public ObjectProperty pathToLocalResourceProperty() { 310 | return pathToLocalResource; 311 | } 312 | 313 | } 314 | -------------------------------------------------------------------------------- /src/main/java/com/goxr3plus/xr3playerupdater/services/ExportZipService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | */ 4 | package main.java.com.goxr3plus.xr3playerupdater.services; 5 | 6 | import java.io.File; 7 | import java.io.FileInputStream; 8 | import java.io.FileOutputStream; 9 | import java.io.IOException; 10 | import java.util.logging.Level; 11 | import java.util.logging.Logger; 12 | import java.util.zip.ZipEntry; 13 | import java.util.zip.ZipFile; 14 | import java.util.zip.ZipInputStream; 15 | 16 | import javafx.concurrent.Service; 17 | import javafx.concurrent.Task; 18 | import javafx.util.Duration; 19 | import main.java.com.goxr3plus.xr3playerupdater.tools.ActionTool; 20 | import main.java.com.goxr3plus.xr3playerupdater.tools.NotificationType; 21 | 22 | /** 23 | * This class is used to import an XR3Player database (as .zip folder) 24 | * 25 | * @author SuperGoliath 26 | * 27 | */ 28 | public class ExportZipService extends Service { 29 | 30 | /** The logger. */ 31 | private final Logger logger = Logger.getLogger(getClass().getName()); 32 | 33 | /** The given ZIP file */ 34 | private String zipFile; 35 | 36 | /** The output folder */ 37 | private String destinationFolder; 38 | 39 | /** The exception. */ 40 | private String exception; 41 | 42 | /** 43 | * Constructor. 44 | */ 45 | public ExportZipService() { 46 | 47 | setOnSucceeded(s -> { 48 | 49 | //Check the value 50 | if (!getValue()) { 51 | ActionTool.showNotification("Exporting ZIP File", exception, Duration.seconds(2), NotificationType.ERROR); 52 | done(); 53 | } else { 54 | ActionTool.showNotification("Exporting ZIP File", "Successfully exported the ZIP File", Duration.seconds(2), NotificationType.INFORMATION); 55 | 56 | } 57 | 58 | }); 59 | 60 | setOnFailed(failed -> { 61 | done(); 62 | ActionTool.showNotification("Exporting ZIP File", exception, Duration.seconds(2), NotificationType.ERROR); 63 | }); 64 | 65 | setOnCancelled(c -> { 66 | done(); 67 | ActionTool.showNotification("Exporting ZIP File", exception, Duration.seconds(2), NotificationType.ERROR); 68 | 69 | }); 70 | } 71 | 72 | /** 73 | * Done. 74 | */ 75 | private static void done() { 76 | 77 | // Main.updateScreen.setVisible(false); 78 | // Main.updateScreen.getProgressBar().progressProperty().unbind(); 79 | } 80 | 81 | /** 82 | * This Services initialises and external Thread to Export a ZIP folder to a 83 | * Destination Folder 84 | * 85 | * @param zipFolder 86 | * The absolute path of the ZIP folder 87 | * @param destinationFolder 88 | * The absolutePath of the destination folder 89 | */ 90 | public void exportZip(String zipFolder , String destinationFolder) { 91 | 92 | //----- 93 | this.zipFile = zipFolder; 94 | this.destinationFolder = destinationFolder; 95 | 96 | reset(); 97 | restart(); 98 | } 99 | 100 | /* 101 | * (non-Javadoc) 102 | * @see javafx.concurrent.Service#createTask() 103 | */ 104 | @Override 105 | protected Task createTask() { 106 | return new Task() { 107 | @Override 108 | protected Boolean call() throws Exception { 109 | 110 | //---------------------Move on Importing the Database----------------------------------------------- 111 | 112 | // get the zip file content 113 | try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) { 114 | 115 | // create output directory is not exists 116 | File folder = new File(destinationFolder); 117 | if (!folder.exists()) 118 | folder.mkdir(); 119 | 120 | // get the zipped file list entry 121 | ZipEntry ze = zis.getNextEntry(); 122 | 123 | // Count entries 124 | ZipFile zip = new ZipFile(zipFile); 125 | double counter = 0 , total = zip.size(); 126 | 127 | //Start 128 | for (byte[] buffer = new byte[1024]; ze != null;) { 129 | 130 | String fileName = ze.getName(); 131 | File newFile = new File(destinationFolder + File.separator + fileName); 132 | 133 | // Refresh the dataLabel text 134 | updateMessage("Exporting: [ " + newFile.getName() + " ]"); 135 | 136 | // create all non exists folders else you will hit FileNotFoundException for compressed folder 137 | new File(newFile.getParent()).mkdirs(); 138 | 139 | //Create File OutputStream 140 | try (FileOutputStream fos = new FileOutputStream(newFile)) { 141 | 142 | // Copy byte by byte 143 | int len; 144 | while ( ( len = zis.read(buffer) ) > 0) 145 | fos.write(buffer, 0, len); 146 | 147 | } catch (IOException ex) { 148 | exception = ex.getMessage(); 149 | logger.log(Level.WARNING, "", ex); 150 | } 151 | 152 | //Get next entry 153 | ze = zis.getNextEntry(); 154 | 155 | //Update the progress 156 | updateProgress(++counter / total, 1); 157 | } 158 | 159 | zis.closeEntry(); 160 | zis.close(); 161 | zip.close(); 162 | 163 | } catch (IOException ex) { 164 | exception = ex.getMessage(); 165 | logger.log(Level.WARNING, "", ex); 166 | return false; 167 | } 168 | 169 | return true; 170 | } 171 | 172 | }; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/main/java/com/goxr3plus/xr3playerupdater/tools/ActionTool.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | */ 4 | package main.java.com.goxr3plus.xr3playerupdater.tools; 5 | 6 | import java.awt.Desktop; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.net.URI; 10 | import java.net.URISyntaxException; 11 | import java.nio.file.Files; 12 | import java.nio.file.Paths; 13 | import java.nio.file.StandardCopyOption; 14 | import java.util.logging.Level; 15 | import java.util.logging.Logger; 16 | 17 | import org.controlsfx.control.Notifications; 18 | 19 | import javafx.application.Platform; 20 | import javafx.scene.control.Alert; 21 | import javafx.scene.control.Alert.AlertType; 22 | import javafx.scene.control.ButtonType; 23 | import javafx.stage.Stage; 24 | import javafx.stage.StageStyle; 25 | import javafx.util.Duration; 26 | 27 | /** 28 | * A class which has a lot of useful methods. 29 | * 30 | * @author GOXR3PLUS 31 | */ 32 | public final class ActionTool { 33 | 34 | /** The logger for this class */ 35 | private static final Logger logger = Logger.getLogger(ActionTool.class.getName()); 36 | 37 | /** 38 | * Tries to open that URI on the default browser 39 | * 40 | * @param uri 41 | * @return True if succeeded , False if not 42 | */ 43 | public static boolean openWebSite(String uri) { 44 | 45 | try { 46 | //Check if Desktop is supported 47 | if (!Desktop.isDesktopSupported()) { 48 | ActionTool.showNotification("Problem Occured", "Can't open default web browser at:\n[" + uri + " ]", Duration.millis(2500), NotificationType.INFORMATION); 49 | return false; 50 | } 51 | 52 | ActionTool.showNotification("Opening WebSite", "Opening on default Web Browser :\n" + uri, Duration.millis(1500), NotificationType.INFORMATION); 53 | Desktop.getDesktop().browse(new URI(uri)); 54 | } catch (IOException | URISyntaxException ex) { 55 | ActionTool.showNotification("Problem Occured", "Can't open default web browser at:\n[" + uri + " ]", Duration.millis(2500), NotificationType.INFORMATION); 56 | logger.log(Level.INFO, "", ex); 57 | return false; 58 | } 59 | return true; 60 | } 61 | 62 | /** 63 | * Private Constructor. 64 | */ 65 | private ActionTool() { 66 | } 67 | 68 | /** 69 | * Copy a file from source to destination. 70 | * 71 | * @param source 72 | * the source 73 | * @param destination 74 | * the destination 75 | * @return True if succeeded , False if not 76 | */ 77 | public static boolean copy(InputStream source , String destination) { 78 | boolean succeess = true; 79 | 80 | System.out.println("Copying ->" + source + "\n\tto ->" + destination); 81 | 82 | try { 83 | Files.copy(source, Paths.get(destination), StandardCopyOption.REPLACE_EXISTING); 84 | } catch (IOException ex) { 85 | logger.log(Level.WARNING, "", ex); 86 | succeess = false; 87 | } 88 | 89 | return succeess; 90 | } 91 | 92 | /** 93 | * Show a notification. 94 | * 95 | * @param title 96 | * The notification title 97 | * @param text 98 | * The notification text 99 | * @param d 100 | * The duration that notification will be visible 101 | * @param t 102 | * The notification type 103 | */ 104 | public static void showNotification(String title , String text , Duration d , NotificationType t) { 105 | 106 | //Check if it is JavaFX Application Thread 107 | if (!Platform.isFxApplicationThread()) { 108 | Platform.runLater(() -> showNotification(title, text, d, t)); 109 | return; 110 | } 111 | 112 | Notifications notification1 = Notifications.create().title(title).text(text); 113 | notification1.hideAfter(d); 114 | 115 | switch (t) { 116 | case CONFIRM: 117 | notification1.showConfirm(); 118 | break; 119 | case ERROR: 120 | notification1.showError(); 121 | break; 122 | case INFORMATION: 123 | notification1.showInformation(); 124 | break; 125 | case SIMPLE: 126 | notification1.show(); 127 | break; 128 | case WARNING: 129 | notification1.showWarning(); 130 | break; 131 | default: 132 | break; 133 | } 134 | 135 | } 136 | 137 | /** 138 | * Makes a question to the user. 139 | * 140 | * @param text 141 | * the text 142 | * @return true, if successful 143 | */ 144 | public static boolean doQuestion(String text , Stage window) { 145 | boolean[] questionAnswer = { false }; 146 | 147 | // Show Alert 148 | Alert alert = new Alert(AlertType.CONFIRMATION); 149 | alert.initStyle(StageStyle.UTILITY); 150 | alert.initOwner(window); 151 | alert.setHeaderText("Question"); 152 | alert.setContentText(text); 153 | alert.showAndWait().ifPresent(answer -> questionAnswer[0] = ( answer == ButtonType.OK )); 154 | 155 | return questionAnswer[0]; 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/com/goxr3plus/xr3playerupdater/tools/InfoTool.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | */ 4 | package main.java.com.goxr3plus.xr3playerupdater.tools; 5 | 6 | import java.io.File; 7 | import java.net.URISyntaxException; 8 | import java.util.logging.Level; 9 | import java.util.logging.Logger; 10 | 11 | import javafx.scene.image.Image; 12 | import main.java.com.goxr3plus.xr3playerupdater.application.Main; 13 | 14 | /** 15 | * Provides useful methods for retrieving informations. 16 | * 17 | * @author GOXR3PLUS 18 | */ 19 | public final class InfoTool { 20 | 21 | /** Logger */ 22 | public static final Logger logger = Logger.getLogger(InfoTool.class.getName()); 23 | 24 | /** WebSite url */ 25 | public static final String WEBSITE = "http://goxr3plus.co.nf"; 26 | 27 | /** XR3Player Tutorials */ 28 | public static final String TUTORIALS = "https://www.youtube.com/playlist?list=PL-xqaiRUr_iRKDkpFWPfSRFmJvHSr1VJI"; 29 | 30 | /** The Constant images. */ 31 | public static final String IMAGES = "/image/"; 32 | 33 | /** The Constant styLes. */ 34 | public static final String STYLES = "/style/"; 35 | 36 | /** The Constant applicationCss. */ 37 | public static final String APPLICATIONCSS = "application.css"; 38 | 39 | /** The Constant fxmls. */ 40 | public static final String FXMLS = "/fxml/"; 41 | 42 | // -------------------------------------------------------------------------------------------------------------- 43 | 44 | /** 45 | * Private Constructor , we don't want instances of this class 46 | */ 47 | private InfoTool() { 48 | } 49 | 50 | /** 51 | * Returns the absolute path of the current directory in which the given 52 | * class file is. 53 | * 54 | * @param classs 55 | * * @return The absolute path of the current directory in which the 56 | * class file is. [it ends with File.Separator!!] 57 | * @author GOXR3PLUS[StackOverFlow user] + bachden [StackOverFlow user] 58 | */ 59 | public static final String getBasePathForClass(Class classs) { 60 | 61 | // Local variables 62 | File file; 63 | String basePath = ""; 64 | boolean failed = false; 65 | 66 | // Let's give a first try 67 | try { 68 | file = new File(classs.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()); 69 | 70 | basePath = ( file.isFile() || file.getPath().endsWith(".jar") || file.getPath().endsWith(".zip") ) ? file.getParent() : file.getPath(); 71 | } catch (URISyntaxException ex) { 72 | failed = true; 73 | Logger.getLogger(classs.getName()).log(Level.WARNING, "Cannot firgue out base path for class with way (1): ", ex); 74 | } 75 | 76 | // The above failed? 77 | if (failed) 78 | try { 79 | file = new File(classs.getClassLoader().getResource("").toURI().getPath()); 80 | basePath = file.getAbsolutePath(); 81 | 82 | // the below is for testing purposes... 83 | // starts with File.separator? 84 | // String l = local.replaceFirst("[" + File.separator + 85 | // "/\\\\]", "") 86 | } catch (URISyntaxException ex) { 87 | Logger.getLogger(classs.getName()).log(Level.WARNING, "Cannot firgue out base path for class with way (2): ", ex); 88 | } 89 | 90 | // fix to run inside Eclipse 91 | if (basePath.endsWith(File.separator + "lib") || basePath.endsWith(File.separator + "bin") || basePath.endsWith("bin" + File.separator) 92 | || basePath.endsWith("lib" + File.separator)) { 93 | basePath = basePath.substring(0, basePath.length() - 4); 94 | } 95 | // fix to run inside NetBeans 96 | if (basePath.endsWith(File.separator + "build" + File.separator + "classes")) { 97 | basePath = basePath.substring(0, basePath.length() - 14); 98 | } 99 | // end fix 100 | if (!basePath.endsWith(File.separator)) 101 | basePath += File.separator; 102 | 103 | return basePath; 104 | } 105 | 106 | /** 107 | * Checks if a web site is reachable using ping command. 108 | * 109 | * @param host 110 | * the host 111 | * @return true if Connected on Internet, false if not. 112 | */ 113 | public static boolean isReachableByPing(String host) { 114 | try { 115 | 116 | // Start a new Process 117 | Process process = Runtime.getRuntime().exec("ping -" + ( System.getProperty("os.name").toLowerCase().startsWith("windows") ? "n" : "c" ) + " 1 " + host); 118 | 119 | //Wait for it to finish 120 | process.waitFor(); 121 | 122 | //Check the return value 123 | return process.exitValue() == 0; 124 | 125 | } catch (Exception ex) { 126 | Logger.getLogger(Main.class.getName()).log(Level.INFO, null, ex); 127 | return false; 128 | } 129 | } 130 | 131 | /** 132 | * Use this method to retrieve an image from the resources of the 133 | * application. 134 | * 135 | * @param imageName 136 | * the image name 137 | * @return Returns an image which is already into the resources folder of 138 | * the application 139 | */ 140 | public static Image getImageFromResourcesFolder(String imageName) { 141 | return new Image(InfoTool.class.getResourceAsStream(IMAGES + imageName)); 142 | } 143 | 144 | /** 145 | * Gets the file size edited in format "x MiB , y KiB" 146 | * 147 | * @param bytes 148 | * File size in bytes 149 | * @return a String representing the file size in MB and kB 150 | */ 151 | public static String getFileSizeEdited(long bytes) { 152 | 153 | //Find it 154 | int kilobytes = (int) ( bytes / 1024 ) , megabytes = kilobytes / 1024; 155 | if (kilobytes < 1024) 156 | return kilobytes + " KiB"; 157 | else if (kilobytes > 1024) 158 | return megabytes + " MiB + " + ( kilobytes - ( megabytes * 1024 ) ) + " KiB"; 159 | 160 | return "error"; 161 | 162 | } 163 | 164 | } 165 | -------------------------------------------------------------------------------- /src/main/java/com/goxr3plus/xr3playerupdater/tools/NotificationType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | */ 4 | package main.java.com.goxr3plus.xr3playerupdater.tools; 5 | 6 | /** 7 | * The type of the notification to be shown. 8 | * 9 | * @author GOXR3PLUS 10 | */ 11 | public enum NotificationType { 12 | 13 | /** The simple. */ 14 | SIMPLE, 15 | 16 | /** The warning. */ 17 | WARNING, 18 | 19 | /** The information. */ 20 | INFORMATION, 21 | 22 | /** The confirm. */ 23 | CONFIRM, 24 | 25 | /** The error. */ 26 | ERROR; 27 | 28 | } 29 | --------------------------------------------------------------------------------