[
  {
    "path": ".gitattributes",
    "content": "*.svg filter=lfs diff=lfs merge=lfs -text\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "* @kotcrab\n"
  },
  {
    "path": ".github/workflows/pr.yml",
    "content": "name: Build pull request\n\non:\n  pull_request:\n    branches: [ master ]\npermissions:\n  contents: read\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Repository checkout\n        uses: actions/checkout@v2\n      - name: Set up JDK 11\n        uses: actions/setup-java@v1\n        with:\n          java-version: 11\n      - name: Run tests\n        run: ./gradlew check\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\non:\n  push:\n    tags:\n      - 'visui-*'\n\njobs:\n  release:\n    runs-on: ubuntu-latest\n    environment: release\n\n    steps:\n      - name: Repository checkout\n        uses: actions/checkout@v2\n      - name: Set up JDK 11\n        uses: actions/setup-java@v1\n        with:\n          java-version: 11\n      - name: Run tests\n        run: ./gradlew check\n      - name: Upload to Maven Central\n        run: ./gradlew :ui:publishToMavenCentral\n        env:\n          ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.CENTRAL_USERNAME }}\n          ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.CENTRAL_PASSWORD }}\n          ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_KEY }}\n          ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }}\n"
  },
  {
    "path": ".github/workflows/snapshot.yml",
    "content": "name: Build and upload snapshot\n\non:\n  push:\n    branches: [ master ]\n  schedule:\n    - cron: \"40 16 10 * *\"\n\njobs:\n  snapshot:\n    runs-on: ubuntu-latest\n    environment: release\n\n    steps:\n      - name: Repository checkout\n        uses: actions/checkout@v2\n      - name: Set up JDK 11\n        uses: actions/setup-java@v1\n        with:\n          java-version: 11\n      - name: Run tests\n        run: ./gradlew check\n      - name: Upload to Maven Central\n        run: ./gradlew :ui:publishSnapshot\n        env:\n          ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.CENTRAL_USERNAME }}\n          ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.CENTRAL_PASSWORD }}\n"
  },
  {
    "path": ".gitignore",
    "content": "## Maven\ntarget/\n\n## Java\n\n*.class\n*.war\n*.ear\nhs_err_pid*\n\n## GWT\n\nwar/gwt_bree/\ngwt-unitCache/\n.apt_generated/\nwar/WEB-INF/deploy/\nwar/WEB-INF/classes/\n.gwt/\ngwt-unitCache/\nwww-test/\n.gwt-tmp/\n\n## Android Studio and Intellij\n\n.idea/\n*.ipr\n*.iws\n*.iml\nout/\ncom_crashlytics_export_strings.xml\n\n## Eclipse\n\n.metadata\nbin/\ntmp/\n*.tmp\n*.bak\n*.swp\n*~.nib\nlocal.properties\n.settings/\n.loadpath\n.pydevproject\n.project\n.classpath\n.externalToolBuilders/\n*.launch\n\n## NetBeans\nnbproject/private/\nbuild/\nnbbuild/\ndist/\nnbdist/\nnbactions.xml\nnb-configuration.xml\n\n## Gradle\n\n.gradle\nbuild/\n/target\n/target\n/target\n"
  },
  {
    "path": "AUTHORS",
    "content": "# This is the official list of the AUTHORS of Vis Project\n# for copyright purposes.\n# This file is distinct from the CONTRIBUTORS files.\n# See the latter for an explanation.\n\n# Names should be added to this file as\n#\tName or Organization <email address>\n# The email address is not required for organizations.\n\nKotcrab <contact(a)kotcrab.com>\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "We are glad that you would like to contribute to the Vis Project. Here are some guidelines that you should follow when making your contributions.\n\nStart by forking this repository, then learn [how to run Vis Projects from source code](https://github.com/kotcrab/vis-ui/wiki/Building-Vis-From-Source).\n\n#### Git commits messages\n* Use sentence case (i.e. \"Add feature\" not \"add feature\")\n* Use imperative, present tense (i.e. \"Add\", not \"Added\" or \"Adds\")\n* Don't use dots, exclamation or question marks at the end of commit message\n\n#### Code Formatter\nWe require you to use code formatter when making pull requests. Code formatter for IntelliJ IDEA can be found in root directory of this repository. If you are using Eclipse then\nyou must use [libGDX Eclipse formatter](https://github.com/kotcrab/libgdx/blob/master/eclipse-formatter.xml). \n\nRemember to don't use Eclipse formatter on existing source code because it isn't fully compatible with the IntelliJ IDEA formatter used in this repository. It may change other irrelevant source code and if you decide to make pull request later it will be harder to review.\n\nTo install formatter in Eclipse simply import xml file from settings window.\n\nTo install formatter in IntelliJ IDEA copy xml to config directory, restart IDE, then select formatter from settings.  \nMac OS X: `~/Library/Preferences/.IdeaIC15/codestyles/`  \nLinux: `~/.IdeaIC15/config/codestyles/`  \nWindows: `<User home>\\.IdeaIC15\\config\\codeStyles\\`\n\n`.IdeaIC15` directory may be named different depending on your IDEA version\n\n#### Code Style\nPlease follow [libGDX code style](https://github.com/libgdx/libgdx/blob/master/CONTRIBUTING.md#code-style).\n\nThanks!\n"
  },
  {
    "path": "CONTRIBUTORS",
    "content": "# This is the official list of people who can contribute\n# (and who have contributed) code to the Vis Project\n# repository.\n# The AUTHORS file lists the copyright holders; this file\n# lists people.\n#\nkotcrab https://github.com/kotcrab\nJavier https://github.com/jdiazcano\nMJ https://github.com/czyzby/\nStrongJoshua https://github.com/StrongJoshua\ncode-disaster https://github.com/code-disaster\npiotr-j https://github.com/piotr-j\nintrigus https://github.com/intrigus\nStQuote https://github.com/StQuote\nFavorlock https://github.com/Favorlock\nstrubelz https://github.com/strubelz\nSnehks https://github.com/Snehks\nericnondahl https://github.com/ericnondahl\nmetaphore https://github.com/metaphore\ncypherdare https://github.com/cypherdare\nfgnm https://github.com/fgnm\nccmb2r https://github.com/ccmb2r\nbploeckelman https://github.com/bploeckelman\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS"
  },
  {
    "path": "README.md",
    "content": "# VisUI\n\nVisUI allows to create nice looking UI in libGDX using scene2d.ui. Library contains scene2d.ui skin, useful widgets like color picker and file chooser, it also contains modified scene2d.ui widgets to provide some extra functionality like focus borders, background change on over and click, etc.\n\nVisUI is licensed under Apache2 license meaning that you can use it for free in both commercial and non-commercial projects.\n\n##### [CHANGES](https://github.com/kotcrab/vis-ui/blob/master/ui/CHANGES.md) file (definitely read before updating!)\n\n**[Web demo!](http://vis.kotcrab.com/demo/ui)** [(source code)](https://github.com/kotcrab/vis-ui/tree/master/ui/src/test/java/com/kotcrab/vis/ui/test/manual)\n\n![VisUI screenshot](http://dl.kotcrab.com/github/vis/visui2.png)\n[Bigger screenshot](http://dl.kotcrab.com/github/vis/visui2.png)\n\n## Adding VisUI to your project\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.kotcrab.vis/vis-ui.svg)](https://search.maven.org/artifact/com.kotcrab.vis/vis-ui)\n\nPlease refer to [libGDX documentation](https://libgdx.com/wiki/articles/dependency-management-with-gradle) if you don't know how to manage dependencies with Gradle. Alternatively JAR can be downloaded from [Maven repository](http://search.maven.org/#search|gav|1|g%3A%22com.kotcrab.vis%22%20AND%20a%3A%22vis-ui%22). If you are creating new project, you can use gdx-setup to automatically add VisUI for you. (press 'Show Third Party Extension' button)\n\n#### Manual Gradle setup:\n\nOpen build.gradle in project root.\nIn ``ext`` section under ``allprojects`` add:\n```groovy\nvisuiVersion = '1.X.X'\n```\nLook at [CHANGES](https://github.com/kotcrab/vis-ui/blob/master/ui/CHANGES.md) file to see what version of VisUI you can use\nfor your version of libGDX. Note that using not matching versions is likely to cause runtime exceptions.\n\n**Core dependency**\n```groovy\napi \"com.kotcrab.vis:vis-ui:$visuiVersion\"\n```\n\n**HTML dependency** (only if you are using GWT):\n```groovy\napi \"com.kotcrab.vis:vis-ui:$visuiVersion:sources\"\n```\n\n``GdxDefinition.gwt.xml`` and ``GdxDefinitionSuperdev.gwt.xml``:\n```xml\n<inherits name='com.kotcrab.vis.vis-ui' />\n```\n\nRefresh Gradle dependencies.\n\n## Usage\n\nUsing VisUI is pretty simple, to load or unload the skin call:\n```java\nVisUI.load();\nVisUI.dispose();\n```\n\nCreate your UI like always, for extra skin features you have to use Vis widgets instead of standard scene2d.ui:\n\n| VisUI         | Standard scene2d.ui |\n| ------------- | ------------------- |\n| VisLabel      | Label               |\n| [LinkLabel](https://github.com/kotcrab/vis-ui/wiki/LinkLabel) | -                   |\n| VisCheckBox   | CheckBox            |\n| VisList       | List                |\n| VisProgressBar| ProgressBar         |\n| VisRadioButton| -                   |\n| VisScrollPane | ScrollPane          |\n| VisSelectBox  | SelectBox           |\n| VisSlider     | Slider              |\n| VisSplitPane  | SplitPane           |\n| VisTextArea   | TextArea            |\n| VisTextButton | TextButton          |\n| VisImageTextButton | ImageTextButton |\n| VisImageButton | ImageButton        |\n| VisTextField  | TextField           |\n| [VisValidatableTextField](https://github.com/kotcrab/vis-ui/wiki/VisValidatableTextField) | -       |\n| VisTree       | Tree                |\n| VisWindow     | Window              |\n| VisTable      | Table               |\n| [DragPane](https://github.com/kotcrab/vis-ui/wiki/DragPane)  | -                   |\n| [GridGroup](https://github.com/kotcrab/vis-ui/wiki/GridGroup) | -                   |\n| [ListView](https://github.com/kotcrab/vis-ui/wiki/ListView)  | -                   |\n| [TabbedPane](https://github.com/kotcrab/vis-ui/wiki/TabbedPane)  | -                 |\n| [Spinner](https://github.com/kotcrab/vis-ui/wiki/Spinner)  | - |\n| [CollapsibleWidget](https://github.com/kotcrab/vis-ui/wiki/CollapsibleWidget) | -           |\n| [ButtonBar](https://github.com/kotcrab/vis-ui/wiki/ButtonBar) | -           |\n| [FlowGroups](https://github.com/kotcrab/vis-ui/wiki/FlowGroups) | -           |\n\nUsing Vis widgets is necessary for proper focus border management. All VisUI widgets constructors do not have Skin argument, they are using VisUI.skin field.\n\n### VisTable\n\nVisTable allows to easily set default spacing for vis components, construct it like this:\n```\nVisTable table = new VisTable(true);\n```\n\nVisTable also allows adding vertical and horizontal separators to table:\n```java\ntable.addSeparator() //horizontal\ntable.addSeparator(true) //vertical\n```\n\n### Using different `SkinScale`s\n\nDefault VisUI skin can be too small for high resolution screens or mobile devices, in that case you can load a upscaled skin version simply by calling:\n```\nVisUI.load(SkinScale.X2);\n```\n\n### Internal classes\n\nClasses inside `com.kotcrab.vis.[...].internal` packages are considered private and aren't part of public API. Changes to that classes won't be listed in change log.\n\n### Default title align\n\nDefault title align for VisWindow and VisDialog is `Align.left` this can be changed by calling:\n```java\nVisUI.setDefaultTitleAlign(int align)\n```\nCalling this method does not affect windows that have been already created.\n\n## Modifying skin\n\n[Raw skin files](https://github.com/kotcrab/vis-ui/tree/master/ui/assets-raw) are available if you would like to modify them. After you pack them using libGDX texture packer, add generated atlas to your project with [uiskin.json, default.fnt and font-small.fnt](https://github.com/kotcrab/vis-ui/tree/master/ui/src/main/resources/com/kotcrab/vis/ui/skin/x1) and load it by calling:\n```java\nVisUI.load(Gdx.files.internal(\"path/to/your/modified/files/uiskin.json\"))\n```\nConsider using USL if you want to extend existing VisUI styles. [Read more](https://github.com/kotcrab/vis-ui/wiki/USL)\n\n## See also\n\n* [vis-ui-contrib](https://github.com/kotcrab/vis-ui-contrib) - Community driven extension, utilities and skins for VisUI\n* [ktx](https://github.com/czyzby/ktx) - Kotlin utilities for libGDX applications.\n  The [ktx-vis](https://github.com/czyzby/ktx/tree/master/vis) and\n  [ktx-style-vis](https://github.com/czyzby/ktx/tree/master/vis-style) modules provide Kotlin APIs for VisUI.\n"
  },
  {
    "path": "build.gradle",
    "content": "import com.vanniktech.maven.publish.JavaLibrary\nimport com.vanniktech.maven.publish.JavadocJar\n\nbuildscript {\n    repositories {\n        gradlePluginPortal()\n        mavenCentral()\n    }\n\n    dependencies {\n        classpath \"com.kotcrab.vis:vis-usl:0.2.1\"\n        classpath \"com.badlogicgames.gdx:gdx-tools:1.9.2\"\n    }\n}\n\nplugins {\n    id(\"com.github.ben-manes.versions\") version \"0.52.0\"\n    id(\"com.vanniktech.maven.publish.base\") version \"0.33.0\"\n}\n\nsubprojects {\n    apply plugin: \"java\"\n    apply plugin: \"idea\"\n    apply plugin: \"signing\"\n    apply plugin: \"com.vanniktech.maven.publish.base\"\n\n    group = 'com.kotcrab.vis'\n    version = projectVersion\n\n    ext {\n        appName = 'vis'\n        gdxVersion = '1.14.0'\n        jnaVersion = '4.1.0'\n        jnaPlatformVersion = '3.5.2'\n        junitVersion = '4.13.2'\n        imgscalrVersion = '4.2'\n\n        isReleaseVersion = !version.endsWith(\"SNAPSHOT\")\n    }\n\n    repositories {\n        mavenCentral()\n    }\n\n    mavenPublishing {\n        publishToMavenCentral(true)\n        if (isReleaseVersion) {\n            signAllPublications()\n        }\n\n        coordinates(\"com.kotcrab.vis\", projectName, projectVersion)\n        configure(new JavaLibrary(new JavadocJar.Javadoc(), true))\n\n        pom {\n            name = projectName\n            description = projectDesc\n            url = 'https://github.com/kotcrab/vis-ui/'\n\n            scm {\n                connection = 'scm:git:git@github.com:kotcrab/vis-ui.git'\n                developerConnection = 'scm:git:git@github.com:kotcrab/vis-ui.git'\n                url = 'git@github.com:kotcrab/vis-ui.git'\n            }\n\n            licenses {\n                license {\n                    name = 'The Apache License, Version 2.0'\n                    url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'\n                }\n            }\n\n            developers {\n                developer {\n                    id = 'kotcrab'\n                    name = 'Kotcrab'\n                    url = 'https://kotcrab.com'\n                }\n            }\n        }\n    }\n\n    task publishSnapshot {\n        if (!isReleaseVersion) {\n            finalizedBy(tasks[\"publishToMavenCentral\"])\n        }\n    }\n\n    javadoc {\n        options.encoding = 'UTF-8'\n        options.addStringOption('Xdoclint:none', '-quiet')\n    }\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.14.3-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "org.gradle.daemon=true\norg.gradle.jvmargs=-Xms256m -Xmx1024m\norg.gradle.configureondemand=true\n\n#required by deploy, change in your home gradle.properties file\nmavenCentralUsername=\nmavenCentralPassword=\n"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\n# This is normally unused\n# shellcheck disable=SC2034\nAPP_BASE_NAME=${0##*/}\n# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)\nAPP_HOME=$( cd -P \"${APP_HOME:-./}\" > /dev/null && printf '%s\\n' \"$PWD\" ) || exit\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=\"\\\\\\\"\\\\\\\"\"\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    if ! command -v java >/dev/null 2>&1\n    then\n        die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Collect all arguments for the java command:\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,\n#     and any embedded shellness will be escaped.\n#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be\n#     treated as '${Hostname}' itself on the command line.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        -jar \"$APP_HOME/gradle/wrapper/gradle-wrapper.jar\" \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\n@rem you may not use this file except in compliance with the License.\n@rem You may obtain a copy of the License at\n@rem\n@rem      https://www.apache.org/licenses/LICENSE-2.0\n@rem\n@rem Unless required by applicable law or agreed to in writing, software\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n@rem See the License for the specific language governing permissions and\n@rem limitations under the License.\n@rem\n@rem SPDX-License-Identifier: Apache-2.0\n@rem\n\n@if \"%DEBUG%\"==\"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\n@rem This is normally unused\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif %ERRORLEVEL% equ 0 goto execute\n\necho. 1>&2\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2\necho. 1>&2\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\necho location of your Java installation. 1>&2\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto execute\n\necho. 1>&2\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2\necho. 1>&2\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\necho location of your Java installation. 1>&2\n\ngoto fail\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=\n\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" -jar \"%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\" %*\n\n:end\n@rem End local scope for the variables with windows NT shell\nif %ERRORLEVEL% equ 0 goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nset EXIT_CODE=%ERRORLEVEL%\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\nexit /b %EXIT_CODE%\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "settings.gradle",
    "content": "rootProject.name = 'vis-ui'\nrootProject.buildFileName = 'build.gradle'\ninclude 'ui', 'usl'\n"
  },
  {
    "path": "ui/CHANGES.md",
    "content": "#### Version: 1.5.9-SNAPSHOT (libGDX 1.14.0)\n\n#### Version: 1.5.8 (libGDX 1.14.0)\n- Updated to libGDX 1.14.0\n\n#### Version: 1.5.7 (libGDX 1.13.5)\n- Updated to libGDX 1.13.5\n\n#### Version: 1.5.6 (libGDX 1.13.1)\n- Project is now published using Maven Central Portal instead of OSSRH\n  - If you're using snapshots add new repository https://central.sonatype.com/repository/maven-snapshots/\n- Source compatibility is now Java 1.8\n- **Changed**: [#399](https://github.com/kotcrab/vis-ui/issues/399) - Font color markup is now disabled when drawing text field to prevent crashes \n\n#### Version: 1.5.5 (libGDX 1.13.1)\n- Updated to libGDX 1.13.1\n- **Improved**: [#396](https://github.com/kotcrab/vis-ui/issues/396) - Added missing Czech diacritics characters\n  - This required re-rendering the font, it was last done 8 years ago. I'm pretty sure I used same Hiero version as before,\n    but I'm guessing newer JDK has some changes. Font baseline is affected by this, but I think it looks better now.\n    Your UI will have slightly different paddings, see the issue for screenshots \n- **Added**: [#394](https://github.com/kotcrab/vis-ui/issues/394) - `VisImageTextButton` now supports focus font colors\n\n#### Version: 1.5.4 (libGDX 1.12.1)\n- **Changed**: [#393](https://github.com/kotcrab/vis-ui/pull/393) - Removed use of Apple Java extensions in `FileUtils`\n\n#### Version: 1.5.3 (libGDX 1.12.1)\n- Updated to libGDX 1.12.1\n\n#### Version: 1.5.2 (libGDX 1.12.0)\n- Updated to libGDX 1.12.0\n- **Added**: [#373](https://github.com/kotcrab/vis-ui/issues/373) - `VisImageTextButton` an optional `Orientation` value can be set to change how the button label is positioned relative to the button image\n  - Defaults to existing behavior (label to the right of image in the same row), and orientation can be changed via `VisImageTextButton.setOrientation()`\n\n#### Version: 1.5.1 (libGDX 1.11.0)\n- Updated to libGDX 1.11.0\n- **Added**: [#374](https://github.com/kotcrab/vis-ui/issues/374) - `ToastManager` now supports 'center' horizontal alignment for 'top' and 'bottom' alignments.\n  - `ToastManager.updateToastsPositions` and `ToastManager` member variables are now protected, allowing further customization of the toast positions.\n\n#### Version: 1.5.0 (libGDX 1.10.0)\n- Updated to libGDX 1.10.0\n- **Removed deprecated API**: `VisUI.VERSION` field\n- **Changed**: The project now uses Java 1.7 compatibility level, similarly to libGDX 1.10.0\n- **Fixed**: [#355](https://github.com/kotcrab/vis-ui/issues/355) - Changing color of `VisImageButton` and `VisImageTextButton` did not work\n- **Fixed**: [#357](https://github.com/kotcrab/vis-ui/issues/357) - `CollapsibleWidget` rendering issues when placed inside a scroll pane\n- **Fixed**: [#358](https://github.com/kotcrab/vis-ui/issues/358) - `CollapsibleWidget` performance issue\n\n#### Version: 1.4.11 (libGDX 1.9.14)\n- Some changes have been made to simplify VisUI release process\n   - **API Deprecated**: `VisUI.VERSION`, this field is no longer updated and will be removed in future versions\n   - New VisUI USL file (in `usl/styles` directory) will be created only when breaking changes have to be made to the style definitions\n\n#### Version: 1.4.10 (libGDX 1.9.14)\n- Updated to libGDX 1.9.14\n\n#### Version: 1.4.9 (libGDX 1.9.12)\n- **Changed**: [#350](https://github.com/kotcrab/vis-ui/pull/350) - Improve `CollapseAction` to support custom duration and interpolation\n- **Fixed**: `IllegalArgumentException` thrown by `MenuItem#getImageCell` when `MenuItem` was created without image ([reported indirectly here](https://github.com/crashinvaders/gdx-texture-packer-gui/issues/98))\n\n#### Version: 1.4.8 (libGDX 1.9.12)\n- Updated to libGDX 1.9.12\n\n#### Version: 1.4.7 (libGDX 1.9.11)\n- **Added**: [#335](https://github.com/kotcrab/vis-ui/issues/335) - `VisImageButton (Drawable imageUp, Drawable imageDown, Drawable imageChecked, String styleName)` constructor\n- **Added**: [#340](https://github.com/kotcrab/vis-ui/issues/340) - Option to disable color picker preview, added: `BasicColorPicker#setShowColorPreviews(boolean)`, `BasicColorPicker#isShowColorPreviews` \n- **Added**: [#333](https://github.com/kotcrab/vis-ui/issues/333) - `FlowGroup` a generalization of `HorizontalFlowGroup` and `VerticalFlowGroup`\n   - `FlowGroup` fixes some layout issues, see linked pull request\n   - `HorizontalFlowGroup` and `VerticalFlowGroup` are deprecated\n   - To avoid breaking changes `DragPane` and `TabbedPane` implementation was not changed in this version\n- **Fixed**: [#331](https://github.com/kotcrab/vis-ui/issues/331)\n   - `TabbedPane::removeAll` does not clear the active tab field\n   - `TabbedPane::remove(Tab)` does not clear the active tab field when it removes last tab\n- **Fixed**: [#336](https://github.com/kotcrab/vis-ui/issues/336) - `VisTextField` crash when text has newlines\n- **Fixed**: [#339](https://github.com/kotcrab/vis-ui/issues/339) - `HighlightTextArea` was not disabling soft wrapping when using some constructors\n- **Fixed**: [#341](https://github.com/kotcrab/vis-ui/issues/341) - `HighlightTextArea` parent alpha was not used when drawing font \n\n#### Version: 1.4.6 (libGDX 1.9.11)\n- Updated to libGDX 1.9.11\n\n#### Version: 1.4.5 (libGDX 1.9.10)\n- **Added**: [#328](https://github.com/kotcrab/vis-ui/issues/328) `BasicColorPicker#focusHexField`\n- **Fixed**: [#316](https://github.com/kotcrab/vis-ui/issues/316) `BusyBar` grows but does not shrink\n- **Fixed**: [#324](https://github.com/kotcrab/vis-ui/issues/324) `Spinner#getSelectorName` returns wrong field\n- **Fixed**: [#326](https://github.com/kotcrab/vis-ui/issues/326) Possible crash in `FocusManager`\n- **Changed**: [#315](https://github.com/kotcrab/vis-ui/issues/315) Generify `VisTree` to match libGDX implementation\n- **Changed**: [#314](https://github.com/kotcrab/vis-ui/issues/314) List `corner` Drawable wasn't set resulting in blank spot when both scrollbars were visible\n- **Changed**: [#325](https://github.com/kotcrab/vis-ui/issues/325) `VisTable#addSeparator(true)` will create `Separator` with `vertical` style\n   - **Warning**: This might be a breaking change if you're using a custom skin\n- **Changed**: `FileChooser` will auto focus selected file text field when added to stage (use `FileChooser.focusSelectedFileTextFieldOnShow` to override this setting)   \n- **Skin changes**:\n   - **Added style**: `Separator`: `vertical` style\n\n#### Version: 1.4.4 (libGDX 1.9.10)\n- Updated to libGDX 1.9.10\n\n#### Version: 1.4.3 (libGDX 1.9.9)\n- **Fixed**: Infinite loop in `PopupMenu` when trying to select next (or previous) `MenuItem` using keyboard and menu has no selectable `MenuItem`s.\n- **Fixed**: [#307](https://github.com/kotcrab/vis-ui/issues/307) `ArrayIndexOutOfBounds` exception in `VisTextArea` when trying to select text having empty first line\n- **Changed**: `PopupMenu` keyboard events will be now treated as handled by scene2d (they won't be passed to application under the stage)\n- **Changed**: [#302](https://github.com/kotcrab/vis-ui/issues/302) `ToastManager` now allows to specify X and Y screen padding separately\n   - **Added**: `ToastManager#setScreenPaddingX(int)`, `ToastManager#setScreenPaddingY(int)`, `ToastManager#setScreenPadding(int, int)`, `ToastManager#getScreenPaddingX()`\n`ToastManager#getScreenPaddingY()`\n   - **Deprecated**: `ToastManager#getScreenPadding()`, use either `ToastManager#getScreenPaddingX()` or `ToastManager#getScreenPaddingY()`. \nNow this method will throw `IllegalStateException` when padding X is different than padding Y. \nThis should not cause any breaking changes until new API is used. This method will be removed in future versions.\n\n#### Version: 1.4.2 (libGDX 1.9.9)\n- Updated to libGDX 1.9.9\n- **Fixed**: `TabbedPane` was not removing `Tab` from internal `ButtonGroup` thus preventing tab instance from being garbage collected \n\n#### Version: 1.4.1 (libGDX 1.9.8)\n- **Fixed**: `FileChooser`'s icon provider not working correctly when chooser's selection checkboxes were enabled \n- **Fixed**: [#292](https://github.com/kotcrab/vis-ui/issues/292) removing `Menu` from `MenuBar` causes `IllegalStateException`\n\n#### Version: 1.4.0 (libGDX 1.9.6)\n- **Added**: [#259](https://github.com/kotcrab/vis-ui/issues/259) `VisImageTextButton#setGenerateDisabledImage(boolean)` along with getter, added `VisImageButton#isGenerateDisabledImage`\n- **Added**: [#260](https://github.com/kotcrab/vis-ui/issues/260) `FileChooser#setDefaultFileName(String)`\n- **Added**: [#279](https://github.com/kotcrab/vis-ui/issues/279) `ToastManager(Group)` constructor\n- **Fixed**: [#255](https://github.com/kotcrab/vis-ui/issues/255) Custom cursor handling in `VisSplitPane` and `MultiSplitPane`\n- **Fixed**: [#262](https://github.com/kotcrab/vis-ui/issues/262) `FileChooser` was not updating selected file list when text was cut or pasted into file name field \n- **Fixed**: `FileChooser` file name suggestion menu was not updating file name field when navigating suggestion list using arrow keys\n- **Fixed**: [#273](https://github.com/kotcrab/vis-ui/issues/273) Fixed rare crash when doing undo in VisTextField can cause `IllegalStateException`\n- [#252](https://github.com/kotcrab/vis-ui/issues/252) `Spinner` now implements `Disableable`\n- **Improved**: [#264](https://github.com/kotcrab/vis-ui/issues/264) Added Turkish diacritics, added currency symbols: €, ¥\n- **Changed**: [#272](https://github.com/kotcrab/vis-ui/pull/272) `VisTextField` and subclasses will now use `style.backgroundOver` when field has keyboard focus or mouse is over it (previously it was only shown on mouse over)\n\n#### Version: 1.3.0 (libGDX 1.9.6)\n- **Added**: `VisUI#dispose (boolean disposeSkin)`\n- Updated to libGDX 1.9.6\n- Excluded `AsyncTask` API from GWT compilation\n\n#### Version: 1.2.5 (libGDX 1.9.4)\n- **Added**: `AsyncTask` API and `AsyncTaskProgressDialog`\n- **Added**: `PopupMenu.removeEveryMenu(Stage)`\n- **Added**: `FileChooser#setShowSelectionCheckboxes`\n- **Added**: `FileChooser#getIconProvider`\n- **Added**: `Spinner#setDisabled(boolean)`, `Spinner#isDisabled()`\n- **Added**: `HorizontalCollapsibleWidget`\n- **Fixed**: `MultiSplitPane#setSplit` not affecting split values\n- **Fixed**: `MultiSplitPane` and `VisSplitPane` default cursor not restored when mouse exited widget bounds when mouse was still on split handle bar \n- **Changed**: Selection of menu item is removed when mouse pointer leaves popup menu structure\n- **I18N Changes**:\n   - Added `Common` bundle\n\n#### Version: 1.2.4 (libGDX 1.9.4)\n- **Added**: `ListSelection#setListener`, `#setProgrammaticChangeEvents` (with getters)\n- **Fixed**: `Spinner.TextFieldEventPolicy` is now public (was package-private)\n- **Fixed**: `HighlightTextArea` scroll pane not immediately updated after changing text using `setText()`\n- **Improved**: [#220](https://github.com/kotcrab/vis-ui/issues/220) when sub menu can't fit on the right side of parent menu, it will be shown on the side that has more available space (before in such case it was always shown on the left side)\n- **Improved**: When mouse is moved from sub-menu to parent menu, selection of menu item in sub-menu will be removed.\n- **Improved**: [#222](https://github.com/kotcrab/vis-ui/issues/222) Added clipping to BusyBar\n- **Skin changes**:\n   - **Added style**: `ListViewStyle` - allows to customize `ListView` scroll pane style\n   - **Added new icons**: `icon-maximize`, `icon-minimize`, `icon-restore`, `icon-close-titlebar`\n   - **Added style**: `VisImageButtonStyle`: `close-titlebar`\n\n#### Version: 1.2.3 (libGDX 1.9.4)\n- **Added**: constructor `LinkLabel (CharSequence text, CharSequence url, LinkLabelStyle style)`\n- **Fixed**: Spinner could overflow Table cell bounds by 1 pixel\n - Removed `Sizes.spinnerButtonsWidth` and `Sizes.spinnerFieldRightPadding` (no longer needed)\n - Renamed `Sizes.spinnerButtonSize` to `Sizes.spinnerButtonHeight`\n- **Skin changes**:\n - Styles that used to reference other style by name (for example `FileChooserStyle` referencing `PopupMenu` style name) now embeds that style directly\n   - Changed `String ToastStyle#closeButtonStyleName` to `VisImageButtonStyle ToastStyle#closeButtonStyle`\n   - Changed `String FileChooserStyle#popupMenuStyleName` to `PopupMenuStyle FileChooserStyle#popupMenuStyle`\n   - Changed `String MenuStyle#openButtonStyleName` to `VisTextButtonStyle MenuStyle#openButtonStyle`\n   - For existing JSON files you only need to remove 'Name' postfix from field name, Skin loading mechanism can automatically resolve such references\n\n#### Version: 1.2.2 (libGDX 1.9.4)\n- **Fixed**: [#214](https://github.com/kotcrab/vis-ui/issues/214) minus sign not visible in Spinner when value was changed with text field focus\n- **Fixed**: When there was not enough space on the right to fully show sub-menu it was appearing in wrong position on the left side.\n\n#### Version: 1.2.1 (libGDX 1.9.4)\n- **Fixed**: When using libGDX 1.9.4 message was printed that libGDX version is incorrect. If your project is using 1.9.4 you could safely ignore it.\n\n#### Version: 1.2.0 (libGDX 1.9.4)\n- Updated to libGDX 1.9.4\n\n#### Version: 1.1.6 (libGDX 1.9.3)\n- **Added**: `MenuBar#setMenuListener`, `MenuBarListener`\n- **Changed**: Spinner by default will fire change event after text field has lost focus, this can be changed. See `Spinner#setTextFieldEventPolicy` and `Spinner#TextFieldEventPolicy`.\n   - Use `TextFieldEventPolicy.ON_ENTER_ONLY` to preserve old behaviour\n- **Changed**: `FileChooser` will auto focus file list scroll pane when added to stage (use `FileChooser.focusFileScrollPaneOnShow` to override this setting)\n- **Fixed**: [#207](https://github.com/kotcrab/vis-ui/issues/207) crash when user has placed text field cursor after last letter (possibly on LWJGL backend only)\n\n#### Version: 1.1.5 (libGDX 1.9.3)\n- **API Changed**: `VisTextField#setCurosrAtTextEnd` renamed to `setCursorAtTextEnd` (typo)\n- **Added**: `Tooltip#getTarget`\n- **Added**: `MenuItem` constructors taking style name\n- **Changed**: It's now impossible to create `FileTypeFilter` `Rule` without providing at least one extension\n- **Changed**: `FileTypeFilter` select box won't be shown when `FileChooser` `SelectionMode` is set to `DIRECTORIES`\n- **Changed**: `FileChooser` now can be closed by pressing enter when file name field has focus\n- **Changed**: `Dialogs#showOKDialog` can be closed using enter and escape key\n- **Changed**: [#176 (comment)](https://github.com/kotcrab/vis-ui/issues/176#issuecomment-237046516) - `FileChooser` path text field will now show end of the path when it's too long\n- **Changed**: `FileChooser` will fallback to default directory when `setDirectory` is called with invalid file handle (either non existing path or pointing to file)\n   - Fixes possible crash when current directory is removed while it's open in file chooser\n   - Removed protected `handleAsyncError`, no longer needed\n\n#### Version: 1.1.4 (libGDX 1.9.3)\n- **Added**: `BusyBar` - used to indicate that background work is going on - see `TestBusyBar`\n- **Added**: `MultiSplitPane` - similar to `VisSplitPane` but supports multiple widgets at once\n- **Added**: `Tooltip.Builder#width()`, `Tooltip#setText(String)`, `Tooltip#getContentCell()`\n- **Changed**: `FileChooser` directory listing is now performed on separate thread to prevent application hanging when accessing unresponsive drive\n- **Changed**: When `ColorPicker` is canceled previous color is restored after window fade out have been finished to avoid flickering (listeners are not affected by this change)\n- **Fixed**: `PopupMenu` with single item is now accessible using keyboard\n- **Fixed**: `TabbedPane` unable to move tab to the last position in pane\n- **Skin changes**:\n   - **Added**: `TabbedPane` added style: `vertical`\n\n#### Version: 1.1.3 (libGDX 1.9.3)\n- **API Changed**: `FileChooser.setSaveLastDirectory` is now static and must be called before creating chooser to properly restore saved directory.\n - Last directory will not be saved when user has canceled selection dialog\n- **Changed**: `VisWindow#fadeOut` will reset alpha back to 1f after completing action.\n\n#### Version: 1.1.2 (libGDX 1.9.3)\n- **Added**: `CursorManager`\n- **Added**: `ScrollableTextArea` and `HighlightTextArea` with `Highlighter` API\n- **Added**: `VisTextField#setCurosrAtTextEnd()`, `#getProgrammaticChangeEvents()`\n- **Added**: `FileChooser` file sorting options available under right click menu\n- **Added**: `FileChooser#setSorting(FileSorting)` and `#setSortingOrderAscending` along with appropriate getters\n- **Added**: `FileChooser#setSaveLastDirectory` - allows to automatically remember last directory user browsed between app launches, disabled by default\n- **Fixed**: VisSplitPane was not restoring default cursor when user dragged pointer outside od pane area \n- **Fixed**: [#188](https://github.com/kotcrab/vis-ui/issues/188) - same instance of `VisDialog` couldn't be closed for the second time using close button \n- **Fixed**: `FileChooser` NPE when user right clicked last file item after deleting all others files\n- **Fixed**: `FileChooser` Duplicated instances of same disk could be visible on list when chooser was displayed right after creating\n- **Fixed**: [#196](https://github.com/kotcrab/vis-ui/issues/196) - `ColorPicker` sending old color to listener instead of new\n- **Changed**: `FileChooser` in save mode with active file type filter rule will automatically append rule extensions if user haven't typed extension or extension was wrong\n- **Changed**: `FileChooser` now shows files modified date when using details view mode\n- **Changed**: `FileChooser` will no longer show files when selection mode is `DIRECTORIES` - this behaviour can be changed in `DefaultFileFilter`\n- **Changed**: When `VisWindow#fadeOut()` is called then window touchable is set to disabled. Additionally keyboard focus is reset if any window child `Actor` owns keyboard focus.\n   - This is done to prevent user input after fade out animation has started.\n   - After fade out has finished window touchable property will be restored to previous value which was set before fade out started.\n- **Skin changes**:\n   - **Added**: `VisTextArea` added style: `textArea` - no background drawable and focus border is disabled\n   - **Added**: `FileChooserStyle` added `Drawable`: `contextMenuSelectedItem` - used to mark active item in context menu (by default `vis-radio-tick`)\n- **I18N Changes**:\n   - **FileChooser**: added keys `contextMenuSortBy`, `sortByName`, `sortByDate`, `sortBySize`, `sortByAscending`, `sortByDescending`\n- **Misc**: Disabling Android Lint is no longer necessary\n\n#### Version: 1.1.1 (libGDX 1.9.3)\n- **Fixed**: NPE in FileChooser crash when navigating to other directory\n\n#### Version: 1.1.0 (libGDX 1.9.3)\n- **API Moved**: `JNAFileDeleter` was moved to [vis-ui-contrib](https://github.com/kotcrab/vis-ui-contrib) project\n- **API Deprecated**: `FileChooser.setFavoritesPrefsName()` replaced by `FileChooser.setDefaultPrefsName()`\n- **API Changed**: GridGroup is now taking float for item size instead of int.\n    - **Warning:** There were two constructors `GridGroup (float spacing)` and `GridGroup (int itemSize)`. Constructor taking float spacing was removed. Constructor taking int item size now takes float. \n- **API Changed**: Refactored `FileChoose.FileIconProvider`, new methods added. `#provideIcon` takes `FileChooser.FileItem`, was `FileHandle`\n- **API Changed**: Refactored `VisCheckBox`\n    - Style was refactored to separate checkbox background and tick drawable (see below for full skin drawables changes)\n    - `VisCheckBoxStyle` now extends `TextButtonStyle`, was `CheckBox` (fields was renamed to properly communicate their functions)\n    - `getImage()` removed, use `getBackgroundImage()` or `getTickImage()` \n    - `getImageCell()` removed, use `getImageStackCell()`\n    - protected `getCheckboxImage()` removed, override `getCheckboxBgImage()` or `getCheckboxTickImage()`\n    - `getStyle()` returns `VisCheckBoxStyle`, was `CheckBoxStyle`\n- **Added**: default styles for `ImageButton` and `ImageTextButton`. Note: this is only applies to standard scene2d widgets. VisUI widgets equivalents (`VisImageButton`, `VisImageTextButton`) already had them.\n- **Added**: `SimpleFormValidator#validate`\n- **Added**: `ToastManager`, `Toast`, `ToastTable`\n- **Added**: VisTextField read-only mode (`VisTextField#setReadOnly(boolean)`)\n- **Added**: `TabbedPane#getUIOrderedTabs()`\n- **Added**: `FileChooser#setFavoriteFolderButtonVisible(true)` - FileChooser now can display 'add folder to favorites' button in the toolbar \n- **Added**: `FileChooser#setPrefsName()` \n- **Added**: `FileTypeFilter`, `FileChooser#setFileTypeFilter(...)` \n- **Added**: `MenuItem#getSubMenuIconCell()` and `MenuItem#getShortcutCell()` \n- **Added**: `VisTextField#setEnterKeyFocusTraversal(boolean)`\n- **Added**: `VisTextField#setCursorPercentHeight`\n- **Added**: `PopupMenuListener`\n- **Added**: `PopupMenu#showMenu (Stage stage, Actor actor)`\n- **Added**: `ConstantIfVisibleValue`\n- **Added**: `Sizes#borderSize`\n- **Added**: `Sizes#fileChooserViewModeBigIconsSize`, `fileChooserViewModeMediumIconsSize`, `fileChooserViewModeSmallIconsSize`, `fileChooserViewModeListWidthSize`\n- **Changed**: [#169](https://github.com/kotcrab/vis-ui/issues/169) - `TabbedPane#getTable()` returns `TabbedPaneTable` (holds reference to `TabbedPane` and allow to easily get its cells for customization)\n- **Changed**: `FileChooser` now tries to maintain selection while rebuilding file list\n- **Changed**: `FileChooser` will now select new folder after creating it \n- **Changed**: `FileChooser` will be automatically refreshed when added to `Stage`\n- **Changed**: `FileChooser` when typing file names manually suggestion will be showed\n- **Changed**: `TabbedPane`'s Tab now can't be dragged using it's close button  \n- **Changed**: Synced `VisTextField` ans `VisTextArea` with equivalents of those classes libGDX\n- **Changed**: `PopupMenu` now support menu navigation using arrows keys\n- **Changed**: `PopupMenu` now optionally takes `Sizes` instance (added constructor `PopupMenu (Sizes sizes, PopupMenuStyle style)`)\n- **Removed deprecated API**: `NumberSelector` - replaced by `Spinner`\n- **Removed deprecated API**: `Sizes#numberSelectorButtonSize`, `numberSelectorButtonsWidth`, `numberSelectorFieldSize`, `numberSelectorFieldRightPadding`\n- **Fixed**: `Sizes.buttonBarSpacing` was ignored by `ButtonBar`\n    - **Added**: constructors `ButtonBar(Sizes sizes, String order)` and `ButtonBar(Sizes sizes)`\n- **Fixed**: `TabbedPane` layout when no separator image was used. Fixed misc issue with close button style on touch down. \n- **Fixed**: `FileChooser` NPE when error occurred during directory deleting\n- **Fixed**: `FileChooser` non empty directories are now deleted correctly when using default `FileChooser` deleter\n- **Fixed**: `FileChooser` crash when user manually entered path to file instead of directory\n- **Fixed**: `FocusManager` calling `focusLost()` when the widget that was already focused tried to gain focus again\n- **Fixed**: `VisSplitPane` was not implementing `hit(...)` which could result in widget that was underneath split pane's handle get touch events  \n- **Fixed**: Now it's not possible to call `VisWindow#fadeOut` multiple times\n- **Skin changes**:\n    - **Changed**: `FileChooserStyle`: added drawable fields: `iconStar`, `iconStarOutline`, `iconRefresh`, `iconListSettings`, `expandDropdown`\n    - **Added**: drawable `window-border-bg.9`, `icon-star`, `icon-star-outline`, `icon-refresh`, `icon-list-settings`\n    - **Added**: style `BaseToastStyle`\n    - **Added**: VisTextField `label` style - if combined with read-only mode allows to create selectable labels\n    - **Updated**: `cursor` drawable (`cursor.9.png`)\n    - **Removed**: `check-down-on`, `check-down`, `check-on-disabled`, `check-over-off`, `check-over-on`, `radio-down-on`, `radio-down`, `radio-on-disabled`, `radio-over-off`, `radio-over-on`\n    - **Added**: `vis-check`, `vis-check-over`, `vis-check-down`, `vis-check-tick`, `vis-check-tick-disabled`, `vis-radio`, `vis-radio-over`, `vis-radio-down`, `vis-radio-tick`, `vis-radio-tick-disabled`\n- **I18N Changes**:\n    - **FileChooser**: added keys `contextMenuRefresh`, `fileType`, `allFiles`, `changeViewMode`, `viewModeList`, `viewModeDetails`, `viewModeBigIcons`, `viewModeMediumIcons`, `viewModeSmallIcons`\n- **Misc**: Added Gradle tasks to package VisUI skin textures and compile USL into JSON (`gradlew :ui:compileSkin`)\n\n#### Version: 1.0.2 (libGDX 1.9.2)\n- **Changed**: [#163](https://github.com/kotcrab/vis-ui/issues/163) - When `VisCheckBox` or `VisTextField` is disabled and is marked as invalid then error border won't be drawn. \n- **Changed**: [#163](https://github.com/kotcrab/vis-ui/issues/163) - Added `SimpleFormValidator#setTreatDisabledFieldsAsValid` (and it's getter) - allow to control whether to mark form as invalid when invalid but disabled field is encountered. If set to true then all disabled fields are treated as valid, regardless of their state.\n    - Defaults to true! Set to false to preserve old behaviour.\n- **API Changed**: `DragListener`: `Draggable` argument was added to each method\n- **API Deprecated**: `Sizes#numberSelectorButtonSize`, `numberSelectorButtonsWidth`, `numberSelectorFieldSize`, `numberSelectorFieldRightPadding` replaced by `spinnerButtonSize`. `spinnerButtonsWidth`, `spinnerFieldSize`, `spinnerFieldRightPadding`\n- **API Deprecated**: `NumberSelector` - replaced by `Spinner`, `NumberSelector` will be removed in future version\n- **Added**: `VisTextField#isTextSelected()`\n- **Added**: `VisTextField#clearText()`\n- **Added**: `FloatingGroup`\n- **Added**: `VisWindow#isKeepWithinParent` and `VisWindow#setKeepWithinParent` \n- **Added**: constructor `VisImage (String drawableName)`\n- **Added**: `VisUI.load(String internalVisSkinPath)`\n- **Added**: `VisTextField#setIgnoreEqualsTextChange(...)` - see [#165](https://github.com/kotcrab/vis-ui/issues/165)\n- **Fixed**: `OptionDialog#set(...)ButtonText` now updates dialog size\n- **Fixed**: [#131](https://github.com/kotcrab/vis-ui/issues/131) - fixed issue when copying numbers between `VisTextField`s with `FloatDigitsOnlyFilter` decimal point was lost\n- **Fixed**: `ListView#AbstractListAdapter` error on GWT\n- **Fixed**: `VisTextField` was changing system cursor when it was disabled\n- **Fixed**: [#165](https://github.com/kotcrab/vis-ui/issues/165) - fixed form not refreshed when text field content was changed to the same as before\n\n#### Version: 1.0.1 (libGDX 1.9.2)\n- **Added**: `ListView#getListAdapter()`\n- **Added**: `ListView#rebuildView()` and `UpdatePolicy.MANUAL`\n- **Added**: `Draggable#setDeadzoneRadius`\n- **Fixed**: Not being able to resize window with `TabbedPane`\n- **Fixed**: `OptionDialog` not modal by default\n- **Fixed**: `SimpleListAdapter` not working on GWT\n- **Fixed**: `VisCheckBox` focus border appeared was displayed in wrong place when using `Cell#growX()`\n- **Changed**: `DragPane`: `LimitChildren` listener now never rejects own children, even when max children amount is achieved.\n- **API Changed**: `ListView#getMainTable()` now returns `ListViewTable<ItemT>` instead of `VisTable`\n- **API Changed**: Added `ListAdapter.add(ItemT)`\n\n#### Version: 1.0.0 (libGDX 1.9.2)\n- **Changed**: `InputValidator` moved to `com.kotcrab.vis.ui.util` package\n- **Changed**: `LesserThanValidator#setEquals(boolean)` renamed to `setUseEquals`\n- **Changed**: `GreaterThanValidator#setEquals(boolean)` renamed to `setUseEquals`\n- **Changed**: `FormInputValidator#validateInput` is now final and can't be overridden\n- **Changed**: `FormInputValidator#getLastResult` is now package-private\n- **Changed**: `DialogUtils` renamed to `Dialogs`\n    - **Changed**: `DialogUtils.properties` is now `Dialogs.properties`\n    - **Changed**: `VisUI#setDialogUtilsBundle(...)` is now `VisUI#setDialogsBundle(...)`\n    - **Changed**: `VisUI#getDialogUtilsBundle()` is now `VisUI#getDialogsBundle()`\n    - **Added**: `showDetailsDialog (Stage stage, String text, String title, String details)`\n    - **Added**: `showDetailsDialog (Stage stage, String text, String title, String details, boolean expandDetails)`\n- **Changed**: `ErrorDialog` renamed to `DetailsDialog`\n    - **Changed**: Constructor `ErrorDialog (String text, String stacktrace)` changed to `DetailsDialog (String text, String title, String details)`\n    - **Added**: `DetailsDialog#setDetailsVisible(...)`\n    - **Added**: `DetailsDialog#setCopyDetailsButtonVisible(...)`\n- **Changed**: `FileChooserText`, `FilePopupMenu` and `ColorPickerText` moved to `internal` subpackages (were not part of public API)\n- **Changed**: `FileChooser#getFileDeleter` removed\n- **Changed**: `FileChooserListener` was refactored\n    - `FileChooserListener#selected(FileHandle)` removed\n    - If user can select single file use `SingleFileChooserListener`\n    - If user can select multiple files use `StreamingFileChooserListener` or use `FileChooserListener` directly\n- **Changed**: `VisTextField#toString()` now returns field text\n- **Changed**: `OptionDialog` now extends `VisWindow` (was extending `VisDialog`)\n- **Changed**: `OptionDialog` and `InputDialog` now will show buttons in platform dependant order using `ButtonBar`\n- **Removed**: Removed all `Tooltip` constructors except those taking style\n    - Use `new Tooltip.Builder(...)` eg. `new Tooltip.Builder(\"Tooltip Text\").target(label).build()`\n    - **Changed**: constructor `Tooltip (String text)` is now `Tooltip (String styleName)`\n    - **Added**: constructor `Tooltip ()` \n    - **Added**: constructor `Tooltip (TooltipStyle)` \n- **Removed**: `SeparatorStyle#vertical`, was not used\n- **Removed**: constructor `Separator (boolean vertical)`\n- **Added**: `ListView` and `ItemAdapter` API\n- **Added**: constructor `TabbedPane(TabbedPaneStyle style, Sizes sizes)`\n- **Added**: constructor `VisWindow(String title, String styleName)`\n- **Added**: `PrefWidthIfVisibleValue`\n- **Added**: `HorizontalFlowGroup` and `VerticalFlowGroup`\n- **Added**: `ButtonBar` - convenient class for creating button panels arranged in platform dependant order.\n    - `FileChooser`, `ColorPicker` and `Dialogs` will now show buttons in platform dependant order\n- **Added**: `LinkLabel`, `VisTextField`, `VisTextArea` and `VisSplitPane` supports system cursors when using LWJGL3 or GWT backend\n- **Fixed**: `TabbedPane`: Tab close button too small when using `SkinScale.X2`\n- **Fixed**: `TabbedPane`: In vertical mode, tabs buttons were centered instead of being aligned at the top \n- **Removed deprecated API**: `ColumnGroup` (use libGDX's `VerticalGroup`)\n- **Skin**: \n    - **Changed**: Color `menuitem-grey` renamed to `menuitem`\n    - **Changed**: `TabbedPaneStyle#bottomBar` renamed to `separatorBar`\n    - **Removed**: `FormValidatorStyle#colorTransition`, no longer needed. \n        - If `colorTransitionDuration` is set to 0 then transition will be skipped.\n    - **Removed**: `SeparatorStyle#vertical`, no longer needed\n    - **Added**: Drawables: `grey`, `vis-blue`, `vis-red`\n    - **Added**: New `Window` style: `resizable`\n- **I18N**:\n    - **Changed** Bundle management moved to `Locales` class. Instead of calling `VisUI.setXYZBundle(...)` call `Locales.setXYZBundle(...)`\n    - **Removed**: Dialogs bundle entries: yes, no, cancel, ok. Now handled by `ButtonBar` bundle. \n\n#### Version: 0.9.5 (libGDX 1.7.1)\n- **Added**: constructor `SimpleFormValidator(Disableable)`.\n- **Added**: `ActorUtils#keepWithinStage(Actor)`.\n- **Deprecated**: `ColumnGroup`. Will be removed in future versions. Use libGDX's `VerticalGroup` which supports more features.\n- **Fixed**: `BasicColorPicker` palette color selection were flipped.\n- **Fixed**: `BasicColorPicker` removed unnecessary right padding.\n- **Fixed**: `MenuItem` sub menu could appear outside screen.\n- **Fixed**: `DialogUtils`'s `ConfirmDialog` text label was not centered.\n\n#### Old changelog file:\n```\n[0.9.4] [libGDX 1.7.1]\n-Fixed GWT support\n\n[0.9.3] [libGDX 1.7.1]\n-API Change: FocusManager.getFocus(Stage) renamed to resetFocus\n-API Change: FocusManager.getFocus(Stage, Focusable) renamed to switchFocus\n-API Change: GridGroup#getItemSize() removed, use getItemWidth or getItemHeight\n-API Change: Moved FileChooser's FavouritesIO to 'com.kotcrab.vis.ui.widget.file.internal' package (isn't VisUI public API)\n-API Addition: FocusManager.resetFocus(Stage, Actor)\n-API Addition: FileChooser#getCurrentDirectory()\n-API Addition: GridGroup#setItemWidth(int), GridGroup#setItemWidth(int), GridGroup#getItemWidth(), GridGroup#getItemWidth()\n-API Addition: GridGroup#getItemSize(int width, int height)\n-API Addition: TabbedPane#disableTab(Tab tab, boolean disable), TabbedPane#isTabDisabled(Tab)\n-API Addition: IntDigitsOnlyFilter\n-API Addition: DragPane\n-API Addition: VisValue, VisWidgetValue - standard Table Values can be used as lambadas if you are using Java 1.8\n-API Addition: PrefHeightIfVisibleValue\n-ColorPicker:\n -API Change: added ColorPickerListener#reset (Color previousColor, Color newColor)\n -Rewritten using shaders, huge performance boost, now usable on gwt and low end devices\n -Internal ColorPicker classes moved to `com.kotcrab.vis.ui.widget.color.internal` package (remember that those classes aren't considered as public api)\n -ColorPicker can now be used as embeddable widget, see ExtendedColorPicker and BasicColorPicker\n -Added ColorPickerWidgetStyle used by ExtendedColorPicker and BasicColorPicker\n  -Changed ColorPickerStyle, now uses ColorPickerWidgetStyle as composition\n -I18N: Removed entries: \"old\", \"new\" (no longer needed)\n -Style: removed fields: alphaBar10px and alphaBar25px, white (no longer needed)\n-NumberSelector:\n -API Addition: setMaxLength(int), getMaxLength()\n -Fixed entering negative integer values\n -Fixed NumberSelector text field focus border when using SkinScale.X2\n -When selector loses focus and entered value is bigger than max it will be set to max value, if it's smaller than min it will be set to min value\n  -Previous behaviour was to restore last valid value\n-Trying to use PopupMenu.add(Actor) with MenuItem will throw an exception (MenuItems must be added using addItem method)\n-ColorPickerStyle now extends WindowStyle\n-Fixed GridGroup too high when total items width in single row was equals to group width\n-GridGroup now supports setting item width and height separately\n-TabbedPane tabs order can be changed by mouse dragging\n-Skin changes:\n -Removed drawables: alpha-bar-10px, alpha-bar-25px\n-VisUI is now supported by LML (templates for scene2d.ui with HTML-like syntax), https://github.com/czyzby/gdx-lml-vis\n\n[0.9.2] [libGDX 1.7.1]\n-API Change: VisValidatableTextField#getValidator() removed, use getValidators() instead\n-API Change: Removed constructors FileChooser taking I18NBundle\n -This way inconsistent with other widgets that did not support this, use VisUI class for setting global I18NBundles\n-API Change: NumberSelector now supports float values, methods taking and returning integers are now using floats\n-API Change: NumberSelectorListener#changed(int) is now NumberSelectorListener#changed(float)\n-API Change: VisProgressBar and VisSlider now extends standard scene2d.ui ProgressBar and Slider (should not affect existing code)\n -VisSliderStyle was removed, use SliderStyle which is fully compatible with VisSliderStyle\n-API Change: changed ColorPickerListener#canceled () to ColorPickerListener#canceled (Color oldColor)\n-API Change: added ColorPickerListener#changed (Color newColor)\n -If you are using ColorPickerAdapter this does not affect you\n-API Change: removed constructor LinkLabel (CharSequence text, String fontName, String colorName) because it was misleading\n             with LinkLabel (CharSequence text, CharSequence url, String styleName)\n-API Addition: NumberSelector#setPrecision\n-API Addition: NumberSelector(String name, float initialValue, float min, float max, float step, int precision)\n-API Addition: NumberSelector(String styleName, String name, float initialValue, float min, float max, float step, int precision)\n-API Addition: NumberSelector(NumberSelectorStyle style, Sizes sizes, String name, float initialValue, float min, float max, float step, int precision)\n-API Addition: InputDialog#setText(String text), InputDialog#setText(String text, boolean selectAll)\n-API Addition: FileChooser#setSelectedFiles (FileHandle... files)\n-API Addition: FloatDigitsOnlyFilter\n-API Addition: VisUI.isLoaded()\n-API Addition: constructor VisValidatableTextField (String text, String styleName)\n-API Addition: constructor VisValidatableTextField (String text, VisTextFieldStyle style)\n-API Addition: CollapsibleWidget#setTable()\n-API Addition: VisWindow#setCenterOnAdd(boolean)\n-API Addition: ColorPicker#setAllowAlphaEdit (boolean allowAlphaEdit)\n-API Addition: ColorPicker#isDisposed()\nAPI Addition: VisCheckBox.setStateInvalid(boolean) and VisCheckBox.isStateInvalid()\n -VisCheckBox and VisRadioButton can now be marked as invalid (error border will be drawn around them)\n-CollapsibleWidget now supports creation without setting initial table\n-Added default style for standard scene2d.ui TextTooltip\n-Added VisTextField and TextArea \"small\" style with smaller font\n-LinkLabel now uses LinkLabelStyle\n-LinkLabel now has link underline on mouse over\n-SimpleFormValidator (note that following also applies to FormValidator):\n -API Addition: constructor SimpleFormValidator (Disableable targetToDisable, Label messageLabel, String styleName)\n -API Addition: constructor SimpleFormValidator (Disableable targetToDisable, Label messageLabel, FormValidatorStyle style)\n -API Addition: SimpleFormValidator#setMessageLabel(), and #setSuccessMessage\n -API Addition: SimpleFormValidator#addDisableTarget(Disableable) and SimpleFormValidator#removeDisableTarget(Disableable)\n -Now using FormValidatorStyle: allows to set color for message label when form is valid or invalid\n  -Two built-in styles: 'default' and 'smooth' with smooth transition between colors\n -Any object implementing Disableable interface may be passed to FormInputValidator as target to disable if form is invalid\n -Multiple Disableable targets are supported\n -Added CheckBox support (checking if checkbox is checked/unchecked)\n-TextField/VisTextField.setMessageText(String text) now works properly.\n-DialogUtils methods now return dialogs objects (was void)\n-Focus border can now be disabled on all widgets having it\n-Fixed VisTree taking VisTextField focus when it was placed inside tree node\n-Fixed invalid key up/down events propagation when using multiple input processors\n-Fixed font kerning for character pairs: Ma, Me, Mi\n-Fixed TabbedPane listener called multiple times when user was switching current tab\n-Fixed TabbedPane close tab buttons styles\n-Fixed 'directory' validator in FormValidator\n-Added libGDX version check before loading VisUI, in case of version mismatch warning will be printed to console\n -Can be suppressed by VisUI.setSkipGdxVersionCheck(true);\n\n[0.9.1] [libGDX 1.7.0]\n-Updated to libGDX 1.7.0\n\n[0.9.0] [libGDX 1.6.5]\n-API Change: Renamed VisValidableTextField to VisValidatableTextField (fixes typo in name)\n-API Change: MenuItem#getShortcut() returns CharSequence (was String)\n-API Addition: ColorPicker#setCloseAfterPickingFinished(boolean)\n-Now Tab#onHide() is called before Tab#dispose()\n-VisValidatableTextField ChangeEvent is now fired after input validation\n -Fixes bug with input dialog with validator, it was possible to enter invalid value\n-Fixed MenuItem not properly updated after changing menu shortcut when item was already added to PopupMenu\n-Fixed MenuItem not using bigger icons when using SkinScale.X2\n-FileChooser:\n -Added tooltips for back, forward, and parent directory buttons\n -Added \"New directory\" button next to path field\n -Added popup menu icons\n -DefaultFileFilter class is now public so it's possible to extend it\n -If your project uses JNA library you can enable moving files to trash instead of deleting them permanently (chooser.setFileDeleter(new JNAFileDeleter()))\n -In file view added icons for common file types: text, images, audio and pdf. Custom icons can be supplied by setting FileIconProvider (see chooser.setIconProvider(...))\n -I18N changes: added entries: back, forward, parentDirectory, newDirectory, popupDeleteFileFailed, contextMenuMoveToTrash, contextMenuMoveToTrashWarning\n -Skin changes: added iconFolderNew, iconFolderStar, iconTrash, iconFileText, iconFileImage, iconFilePdf, iconFileAudio\n\n[0.8.2] [libGDX 1.6.4]\n-API Addition: VisValidableTextField#restoreLastValidText()\n-API Addition: OsUtils.isAndroid(), OsUtils.getAndroidApiLevel(), OsUtils.isIos(), OsUtils.getShortcutFor(int... keycodes)\n-API Addition: MenuItem#setShortcut(int... keycodes)\n-API Addition: VisSplitPane#getFirstWidgetBounds(), VisSplitPane#getSecondWidgetBounds()\n-API Addition: NumberSelector#setProgrammaticChangeEvents(boolean), NumberSelector#setValue(int value, boolean fireEvent)\n-API Addition: NumberSelector#removeChangeListener(...)\n-API Change: Removed MenuItem#setShortcut(int modifier, int keycode)\n-API Change: FileUtils.isMac(), FileUtils.isUnix() and FileUtils.isWindows() moved to OsUtils\n-Added ColumnGroup\n-Fixed MenuItem shortcut label color when MenuItem is disabled\n-If user clicks mouse before Tooltip appears, Tooltip won't be showed\n-Fixed issue with GridGroup in ScrollPane - scroll bar appeared too late\n-Fixed GWT compilation issues\n-PopupMenu is now kept inside stage when displaying it\n-FileChooser\n -API Change: Removed FileChooser#setVisble(boolean) (typo in name), use FileChooser#setVisible(boolean)\n -API Change: Renamed: setGroupMultiselectKey to setGroupMultiSelectKey, getGroupMultiselectKey to getGroupMultiSelectKey,\n                       setMultiselectKey to setMultiSelectKey, getMultiselectKey to getMultiSelectKey\n                       setMultiselectionEnabled to setMultiSelectionEnabled, isMultiselectionEnabled to isMultiSelectionEnabled\n -Fixed issue with very slow chooser creation on computers with floppy disk drivers installed ( https://github.com/kotcrab/vis-ui/issues/11#issuecomment-136892177 )\n -Fixed crash in when user tried to use history buttons for no longer existing directory\n -Fixed multiple selection when selection mode was set to FILES or DIRECTORIES\n -Added support for the back and forward mouse button for navigating in the history\n -I18N\n  -added directoryNoLongerExists\n  -added missing entries: newDirectoryDialogTitle, newDirectoryDialogText\n\n[0.8.1] [libGDX 1.6.4]\n-Updated libGDX to 1.6.4\n-Error dialog from DialogUtils with exception will now show stacktrace from nested exceptions\n-Skin change: ColorPickerStyle alphaBar25pxShifted removed (no longer necessary)\n-Fixed VisSelectBox list elements padding\n-Added skin in higher resolution (can be loaded by new method: VisUI.load(SkinScale.X2))\n -SVG file is also available thanks to piotr-j (https://github.com/piotr-j)\n-Removed VisUI.getDefaultSpacingTop/Bottom/Right/Left and VisUI.setDefaultSpacingTop/Bottom/Right/Left\n -Replaced by Sizes class ( VisUI.getSizes() )\n -TableUtils.setSpacingDefault now properly uses all spacings if set\n-OptionDialog (DialogUtils.showOptionDialog(...)) message label is now by default center aligned.\n-Fixed bug in ColorPicker: pasting hex value was changing picker old color\n\n[0.8.0] [libGDX 1.6.3]\n-API Addition: Tooltip (Actor target, String text, int textAlign)\n-API Addition: Tooltip (String styleName, Actor target, String text, int textAlign)\n-API Addition: FormInputValidator#hideErrorOnEmptyInput (can be used with FromValidator to don't display error\n               message if field is empty, field will be still marked with red border and accept button will be disabled)\n-API Addition: FormValidator#directory(...)\n-API Addition: FormValidator#directoryEmpty(...)\n-API Addition: FormValidator#directoryNotEmpty(...)\n-Optimized FileChooser ( https://github.com/kotcrab/vis-ui/issues/11 )\n-Fixed issue when FileChooser confirm button text wasn't updated after changing mode ( https://github.com/kotcrab/vis-ui/pull/14 )\n-Fixed issue when FileChooser would crash on file delete dialog\n-Added 'blue' button style\n-Added New Directory item in FileChooser popup menu (\"contextMenuNewDirectory\" was added to FileChooser I18N file)\n-FileChooser I18N file: added contextMenuNewDirectory, newDirectoryDialogIllegalCharacters, newDirectoryDialogAlreadyExists properties\n-Improved small font (some uppercase letters were missing 1px at the top)\n\n[0.7.7] [libGDX 1.6.1]\n-uiskin.json is now generated from USL (see USL page on GitHub Wiki, if you are not writing custom VisUI skins this does not affect you)\n-API Addition: various getters and setters in NumberSelector\n-API Addition: TabbedPane#getActiveTab\n-API Change: Menu#selectButton(TextButton) and deselectButton(TextButton) no longer public, they wasn't part of public API\n-Added 'navigate to parent directory' button in FileChooser\n-FileChooser now displays \"Computer\" instead of \"/\" in partitions list (also added 'computer' entry in FileChooser I18N file)\n-FileChooser: improved history (back and forward button)\n-FileChooser now can will automatically updates drives list after connecting/removing drive, usb stick etc.\n-FileChooser now will refresh files list after some files were changed in current directory\n-FileChooser I18N: added property: popupSelectedFileDoesNotExist. Removed: popupOk, popupYes, popupNo (replaced by DialogUtils)\n-Added some constructors that allows to use widgets without depending on VisUI.getSkin()\n-Fixed infinite key repeat bug on Android in VisTextField ( https://github.com/kotcrab/vis-ui/issues/9 )\n-Fixed small gap with empty title in NumberSelector\n-Fixed issue where FileChooser file list wasn't rebuilt after setting new file filter\n-Fixed issue where NumberSelector won't allow to enter value if min is greater than 0 ( related to https://github.com/kotcrab/vis-ui/issues/7 )\n-Fixed closeOnEscape() with multiple windows (windows were closed in improper order) ( https://github.com/kotcrab/vis-ui/issues/10 )\n-Fixed invalid title align in VisWindow after adding close button when title align is not set to center\n-Fixed issue with disappearing MenuItem after opening PopupMenu while holding right mouse button and dragging down ( https://github.com/kotcrab/vis-ui/commit/a17e309b980b5d0db061a315685501e405811ff6 )\n-FileChooser, ColorPicker, Tooltip, Menu and MenuBar now can use styles defined in skin file\n-ColorPicker now supports I18N (added VisUI.setColorPickerBundle(I18NBundle))\n\n[0.7.6] [libGDX 1.6.0]\n-Updating to libGDX 1.6.0\n\n[0.7.5] [libGDX 1.5.6]\n-Added VisImageTextButton\n\n[0.7.4] [libGDX 1.5.6]\n-API Addition: NumberSelector#setValue(int)\n-After adding close button to VisWindow, title label will be automatically centered if noting else was added to title table\n\n[0.7.3] [libGDX 1.5.6] [POM invalid, don't use]\n-Updating to libGDX 1.5.6\n-Fixed input bug in VisTextField\n-Tooltip now can be created without setting target\n\n[0.7.2] [libGDX 1.5.5] [POM invalid, don't use]\n-API Addition: NumberSelector (String name, int initialValue, int min, int max)\n-API Addition: VisUI.load(Skin)\n-API Addition: GridGroup\n-API Addition: LinkLabel\n-API Addition: VisValidableTextField#setRestoreLastValid(boolean)\n-API Addition: VisTextButton (String, ChangeListener)\n-API Addition: VisTextButton (String, String, ChangeListener)\n-API Addition CollapsibleWidget.setCollapsed (boolean collapse, boolean applyAnimation) to change collapse state without animation\n-Fixed menu not closing after clicking it on MenuBar\n-Fixed submenu visible for disabled MenuItem\n-Fixing some Tooltip problems, Tooltip now won't fade away when user has it mosue over it\n-Better padding on VisList/List item (default list style selection drawable now uses 'padded-list-selection.9')\n-New default favoritesPrefsName is com.kotcrab.vis.ui.widget.file.filechooser_favorites (was pl.kotcrab.vis.ui.widget.file.filechooser_favorites)\n-Now waring will be printed to console if using default favorites preference name (see FileChooser.setFavoritesPrefsName(String))\n-Improving text field (faster input while holding key)\n\n[0.7.1] [libGDX 1.5.5]\n-Fixing GWT compatibility\n\n[0.7.0] [libGDX 1.5.5]\n* Renaming:\n   Validators.integers renamed to Validators.INTEGERS\n   Validators.floats renamed to Validators.FLOAT\n   PopupMenu#displayMenu renamed to PopupMenu#showMenu\n   Skin Change: Separator 'height' renamed to 'thickness'\n* Moving classes / reorganizing:\n   VisTable moved to com.kotcrab.vis.ui.widget package\n   DialogUtils moved to com.kotcrab.vis.ui.util.dialog package\n   OptionDialogListener and OptionDialogAdapter moved to com.kotcrab.vis.ui.util.dialog package\n   InputDialogListener and InputDialogAdapter moved to com.kotcrab.vis.ui.util.dialog package\n   FormValidator, SimpleFormValidator, FormInputValidator moved to com.kotcrab.vis.ui.util.form package\n   BasicFormValidator renamed to SimpleFormValidator\n   TableUtils.setSpaceDefaults renamed to TableUtils.setSpacingDefaults\n* Menu system changes:\n   Submenus are now supported\n   Removed PopupMenu constructors taking boolean, now auto remove is always enabled. Now when user has clicked MenuItem then PopupMenu will be removed from stage\n   MenuBar constructor doesn't take Stage argument anymore\n   Added: MenuItem#setSubMenu(PopupMenu subMenu)\n   Added: MenuBar#addMenu(Menu menu) MenuBar#removeMenu(Menu menu) MenuBar#insertMenu(int index, Menu menu)\n   Added: MenuBar#closeMenu()\n   Skin Change: MenuItem widget now uses MenuItemStyle (used TextButtonStyle). MenuItemStyle extends TextButtonStyle. MenuItemStyle adds submenu icon.\n* Skin changes:\n   Separator style now has 'vertical' property\n   Added VisSplitPane handleOver property\n* Other API changes:\n   API Change: Constructor Separator(boolean useMenuStyle) is now Separator(boolean vertical). Use 'new Separator(\"menu\")' for menu styled separator\n   API Change: FileChooserLocale removed, now using libGDX's I18NBundle, see FileChooserText class\n   API Change: VisWindow#getButtonTable deprecated, instead use VisWindow#getTitleTable\n   API Change: VisDialog#getButtonTable deprecated, instead use VisDialog#getButtonsTable\n   API Change: Removed FileChooser.getFavoritesPrefsName()\n* Other API additions:\n   Added New FormValidators: integerNumber, floatNumber, valueLesserThan, valueGreaterThan\n   Added VisTable#addSeparator (boolean vertical)\n   Added constructor VisLabel (CharSequence text, LabelStyle style)\n   Added constructor VisLabel (CharSequence text, int alignment)\n   Added TableBuilder and its implementations: StandardTableBuilder, CenteredTableBuilder, GridTableBuilder, OneColumnTableBuilder, OneRowTableBuilder\n* Other changes:\n   VisTree/Tree now have default mouse over drawable\n   Added shift selection for FileChooser (key can be changed by FielChooser#setGroupMultiselectKey(...))\n   Tooltip is now kept within Stage border\n   Focus border is now optional for every widget that was using it\n   Font support for Polish, German, Spanish, French, Greek and Russian characters\n   FormInputValidator now uses validate(String) instead of validateInput(String) for input validation, calling setResult is no longer required\n    (for examples on how to use it see SimpleFormValidator)\n   Added ValidatorWrapper that allows standard validator to be used with (Simple)FormValidator#custom(...)\n   Added DialogUtils.showConfirmDialog(...)\n   Added TabbedPane\n\n[0.6.1] [libGDX 1.5.4]\n-Fixed FileChooser disappearing when removing favourite\n\n[0.6.0] [libGDX 1.5.4]\n-API Change: VisUI.skin is not private, use VisUI.getSkin() instead\n-API Addition: DialogUtils.showOptionDialog (Stage stage, String title, String text, OptionDialogType type, OptionDialogListener listener)\n-API Addition: FormValidator.fileExists (VisValidableTextField field, VisTextField relativeTo, String errorMsg, boolean errorIfRelativeEmpty)\n-API Addition: ColorPicker\n-API Addition: ColorUtils\n-API Addition: VisImage\n-API Addition: constructor VisLabel (CharSequence text, Color textColor)\n-Changed close button style name to 'close-window' (was 'close')\n-Added 'close' button style that matches other normal buttons\n-Fixed focus traversing when TAB pressed in VisTextField, doesn't change focus to invisible fields and doesn't leaves modal windows\n-Added built-in validators: IntegerValidator, FloatValidator, GreaterThanValidator, LesserThanValidator (see Validators class)\n-Added VERSION string constant in VisUI\n\n[0.5.1] [libGDX 1.5.3]\n-Added cancelable input dialog in DialogUtils\n\n[0.5.0] [libGDX 1.5.3]\n-API Addition: VisValidableTextField.setValidationEnabled(boolean)\n-API Addition: VisValidableTextField.isValidationEnabled()\n-API Addition: VisValidableTextField.setProgrammaticChangeEvents(boolean)\n-API Addition: constructor VisImageButton (String styleName)\n-API Addition: constructor VisCheckBox (String text, boolean checked)\n-API Addition: VisWindow.addCloseButton()\n-API Addition: VisWindow.closeOnEscape()\n-API Addition: VisTextField.focusField()\n-API Addition: MenuItem.getShortcut()\n-API Addition: DialogUtils.showInputDialog (Stage stage, String title, String fieldTitle, InputDialogListener listener)\n-API Addition: DialogUtils.showInputDialog (Stage stage, String title, String fieldTitle, InputValidator validator, InputDialogListener listener)\n-API Change: VisUI.setDefaultTitleAlign and VisUI.getDefaultTitleAlign (typo fixed)\n-API Change: Removed deprecated TableUtils.setColumnsDefaults(Table)\n-Separator style \"menu\" height changed to 3px (was 4px), that means PopupMenu separator height is now 3px as well\n-File chooser now have close button in top right corner\n-File chooser now closes when escape key has been pressed\n-Fixed bug where VisValidableTextField would loss focus if user type something and field don't have ChangeListener attached\n-Fixed focusing next field when TAB key is pressed inside VisTextField\n-Added Tooltips\n-Moved TableUtils to com.kotcrab.vis.util package (sorry!)\n\n[0.4.1] [libGDX 1.5.2]\n-Fixed FileChooser padding when scrollbar was showed (because libGDX scrollpane was probably fixed as well) \n\n[0.4.0] [libGDX 1.5.2] [Important]\n-Important: Moving everything to com.kotcrab.vis package, new Gradle definitions:\n in core: com.kotcrab.vis:vis-ui:$visuiVersion\n in html: com.kotcrab.vis:vis-ui:$visuiVersion:sources\n Also don't forget to update your GdxDefinition.gwt.xml and GdxDefinitionSuperdev.gwt.xml files!\n\n[0.3.1] [libGDX 1.5.0]\n-Added CollapsibleWidget\n-Fixed VisImageButton.setGenerateDisabledImage(boolean)\n-Fixed MenuBar not rendering Menu content if added Menu to MenuBar after adding items to it\n-VisTable.addSeparator() now sets expandX() and fillX() for separator instead of expand() and fill()\n-GWT compatibility for DialogUtils and FormValidator\n-Fixed VisCheckBox and VisRadioButton focus border padding\n\n[0.3.0] [libGDX 1.5.0]\n-libGDX dependency version changed to 1.5.0\n-Font size changed to 15\n-Separator width changed to 4px, split pane bar width/height changed to 4px\n-Removed markup font\n-API Change: Removed deprecated resize() from MenuBar\n-API Change: New MenuItem constructors which takes Image instead of Drawable, removed MenuItem (String text, Drawable image, String styleName)\n-API Change: FormValidator.fileExist(...) -> FormValidator.fileExists(...)\n-API Change: VisTable.addSeparator() returns Cell<Separator> instead of void\n-API Addition: FileChooser(FileChooserLocale, Mode)\n-API Addition: MenuItem (String, ChangeListener)\n-API Addition: VisUI.setDefualtTitleAlign(int align) \n-API Addition: VisUI.getDefualtTitleAlign()\n-API Addition: FormValidator.fileExist(VisValidableTextField field, File relavtiveTo, String errorMsg)\n-API Addition: FormValidator can also take FileHandle when using file(Not)Exist relativeTo method \n-API Addition: Added VisTextField.isFocusBorderEnabled() and VisTextField.setFocusBorderEnabled(boolean)\n-API Addition: Added FormValidator.fileNotExist(...) methods\n-API Addition: Added FormValidator.custom (VisValidableTextField field, FormInputValidator customValidator)\n-API Addition: VisSplitPane.setWidgets (Actor firstWidget, Actor secondWidget)\n-Fixed bug when FormValidator doesn't updated all fields borders after changes in other field\n-FileChooser deselects all files when reopened\n-FileChooser: When clicked on drive shortcut file scroll pane table will get focus automaticly\n-FileChooser: When sorting file list chooser now ignores uppercase/lowercase\n-Fixed problem where Separator didn't set color before rendering\n-Fixed look of disabled MenuItem, if MenuItem has an image and it is disabled, image color will be set to Color.GRAY. \n This can be disabled by calling item.setGenerateDisabledImage(false)\n\n[0.2.0] [libGDX 1.4.1]\n-API change: removed Stage from VisWindow and VisDialog constructors\n-API change: removed VisWindow.setPositonToCenter() replaced with VisWindow.centerWindow()\n-API change: VisImageButton.setGeneateDisabledImage() -> VisImageButton.setGenerateDisabledImage() (typo)\n-Fixed findNextTextField in VisTextField\n-Increased default bottom padding from 6 to 8\n-Calling MenuBar.resize() no longer required\n-When FileChooser is in SelectionMode.DIRECTORIES, none directory is selected, and finish button was clicked, current directory will be selected\n-VisValidableTextField will validate input on setText() and fire ChangeEvent\n-VisValidableTextField.validateInput() method is now public\n-Added SeparatorStyle class\n-Added PopupMenu.addSeparator()\n-Added FileUtils.toFileHandle(File file)\n-Added FormValidator\n-Added VisValidableTextField()\n-Added VisValidableTextField(InputValidator validator)\n-Added VisValidableTextField(String text)\n-Added VisLabel()\n-Added VisValidableTextField.getValidator()\n-Added VisValidableTextField.getValidators()\n-Added MenuItem(String text, Drawable image)\n-Added DialogUtils\n\n[0.1.1] [libGDX 1.4.1]\n-Updated menu bar look\n\n[0.1.0] [libGDX 1.4.1]\n-API change: VisValidableTextField#addValidable -> VisValidableTextField#addValidator\n-Added: VisTextField#isEmpty()\n-Added: VisTable#addSeparator()\n-Added: VisWindow(String title)\n-Added: VisTextButton(String text, VisTextButtonStyle buttonStyle)\n-Added FileChooser (Desktop only)\n-Added fadeOut(), fadeIn() to VisWindow\n-Added VisImageButton\n-Added VisDialog\n-Added PopupMenu\n-Disabling button will remove its focus\n-VisWindow can be created with border or without it\n-MenuItem can be created with icon\n-Fixed horizontal scroll pane slider not fully visible\n-Fixed fade out animation not worked on VisSplitPane\n\n[0.0.3] [libGDX 1.4.1]\n-API change: Renamed 'components' package to 'widget' (sorry!)\n-Added VisValidableTextField with InputValidator\n-Better CheckBox text padding\n\n[0.0.2] [libGDX 1.4.1]\n-Added GWT compatibility\n\n[0.0.1] [libGDX 1.4.1]\n-Initial release\n```\n"
  },
  {
    "path": "ui/NOTICE",
    "content": "VisUI uses icons licensed under CC BY-ND 3.0\nhttps://github.com/Templarian/WindowsIcons/blob/master/WindowsPhone/license.txt (file: icons-license)\n"
  },
  {
    "path": "ui/assets-raw/x1/pack.json",
    "content": "{\n  duplicatePadding: false,\n  paddingX: 1,\n  paddingY: 1,\n  stripWhitespaceX: true,\n  stripWhitespaceY: true\n}"
  },
  {
    "path": "ui/assets-raw/x1-fonts/default.hiero",
    "content": "font.name=Vis Open Sans\nfont.size=15\nfont.bold=false\nfont.italic=false\n\nfont2.file=C:\\Data\\Git\\vis-ui\\ui\\assets-raw\\VisOpenSansKerned.ttf\nfont2.use=true\n\npad.top=0\npad.right=0\npad.bottom=0\npad.left=0\npad.advance.x=0\npad.advance.y=0\n\nglyph.native.rendering=false\nglyph.page.width=256\nglyph.page.height=256\nglyph.text=ABCDEFGHIJKLMNOPQRSTUVWXYZ\\nabcdefghijklmnopqrstuvwxyz\\n1234567890•\\n\"!`?¿'.,;:()[]{}<>|/@\\^$€¥-%+=#_&~*\\nñÑąćęłńóśźżĄĆĘŁŃÓŚŹŻÄäÖöÜüßĞğŞşİıÇç\\náéíóúàèìòùÁÉÍÓÚÀÈÌÒÙ\\nАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ\\nабвгдеёжзийклмнопрстуфхцчшщъыьэюя\\nΑΆΒΓΔΕΈΖΗΉΘΙΊΚΛΜΝΞΟΌΠΡΣΤΥΎΦΧΨΩΏ·\\nαάβγδεέζηήθιίκλμνξοόπρστυύφχψωώ\\nϊΐςϋΰ⌘⌥⇧čďěňřšťůýžČĎĚŇŘŠŤŮÝŽ\n\neffect.class=com.badlogic.gdx.tools.hiero.unicodefont.effects.ColorEffect\neffect.Color=ffffff\n\n"
  },
  {
    "path": "ui/assets-raw/x1-fonts/font-small.hiero",
    "content": "font.name=Vis Open Sans\nfont.size=12\nfont.bold=false\nfont.italic=false\n\nfont2.file=C:\\Data\\Git\\vis-ui\\ui\\assets-raw\\VisOpenSansKerned.ttf\nfont2.use=true\n\npad.top=1\npad.right=0\npad.bottom=0\npad.left=0\npad.advance.x=0\npad.advance.y=0\n\nglyph.native.rendering=false\nglyph.page.width=256\nglyph.page.height=128\nglyph.text=ABCDEFGHIJKLMNOPQRSTUVWXYZ\\nabcdefghijklmnopqrstuvwxyz\\n1234567890•\\n\"!`?¿'.,;:()[]{}<>|/@\\^$€¥-%+=#_&~*\\nñÑąćęłńóśźżĄĆĘŁŃÓŚŹŻÄäÖöÜüßĞğŞşİıÇç\\náéíóúàèìòùÁÉÍÓÚÀÈÌÒÙ\\nАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ\\nабвгдеёжзийклмнопрстуфхцчшщъыьэюя\\nΑΆΒΓΔΕΈΖΗΉΘΙΊΚΛΜΝΞΟΌΠΡΣΤΥΎΦΧΨΩΏ·\\nαάβγδεέζηήθιίκλμνξοόπρστυύφχψωώ\\nϊΐςϋΰ⌘⌥⇧čďěňřšťůýžČĎĚŇŘŠŤŮÝŽ\n\neffect.class=com.badlogic.gdx.tools.hiero.unicodefont.effects.ColorEffect\neffect.Color=ffffff\n\neffect.class=com.badlogic.gdx.tools.hiero.unicodefont.effects.OutlineEffect\neffect.Color=ffffff\neffect.Width=0.3\neffect.Join=2\n\n"
  },
  {
    "path": "ui/assets-raw/x2/pack.json",
    "content": "{\n  duplicatePadding: false,\n  paddingX: 1,\n  paddingY: 1,\n  stripWhitespaceX: true,\n  stripWhitespaceY: true\n}"
  },
  {
    "path": "ui/assets-raw/x2-fonts/default.hiero",
    "content": "font.name=Vis Open Sans\nfont.size=30\nfont.bold=false\nfont.italic=false\n\nfont2.file=C:\\Data\\Git\\vis-ui\\ui\\assets-raw\\VisOpenSansKerned.ttf\nfont2.use=true\n\npad.top=0\npad.right=0\npad.bottom=0\npad.left=0\npad.advance.x=0\npad.advance.y=0\n\nglyph.native.rendering=false\nglyph.page.width=512\nglyph.page.height=256\nglyph.text=ABCDEFGHIJKLMNOPQRSTUVWXYZ\\nabcdefghijklmnopqrstuvwxyz\\n1234567890•\\n\"!`?¿'.,;:()[]{}<>|/@\\^$€¥-%+=#_&~*\\nñÑąćęłńóśźżĄĆĘŁŃÓŚŹŻÄäÖöÜüßĞğŞşİıÇç\\náéíóúàèìòùÁÉÍÓÚÀÈÌÒÙ\\nАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ\\nабвгдеёжзийклмнопрстуфхцчшщъыьэюя\\nΑΆΒΓΔΕΈΖΗΉΘΙΊΚΛΜΝΞΟΌΠΡΣΤΥΎΦΧΨΩΏ·\\nαάβγδεέζηήθιίκλμνξοόπρστυύφχψωώ\\nϊΐςϋΰ⌘⌥⇧čďěňřšťůýžČĎĚŇŘŠŤŮÝŽ\n\neffect.class=com.badlogic.gdx.tools.hiero.unicodefont.effects.ColorEffect\neffect.Color=ffffff\n\n"
  },
  {
    "path": "ui/assets-raw/x2-fonts/font-small.hiero",
    "content": "font.name=Vis Open Sans\nfont.size=24\nfont.bold=false\nfont.italic=false\n\nfont2.file=C:\\Data\\Git\\vis-ui\\ui\\assets-raw\\VisOpenSansKerned.ttf\nfont2.use=true\n\npad.top=1\npad.right=0\npad.bottom=0\npad.left=0\npad.advance.x=0\npad.advance.y=0\n\nglyph.native.rendering=false\nglyph.page.width=512\nglyph.page.height=256\nglyph.text=ABCDEFGHIJKLMNOPQRSTUVWXYZ\\nabcdefghijklmnopqrstuvwxyz\\n1234567890•\\n\"!`?¿'.,;:()[]{}<>|/@\\^$€¥-%+=#_&~*\\nñÑąćęłńóśźżĄĆĘŁŃÓŚŹŻÄäÖöÜüßĞğŞşİıÇç\\náéíóúàèìòùÁÉÍÓÚÀÈÌÒÙ\\nАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ\\nабвгдеёжзийклмнопрстуфхцчшщъыьэюя\\nΑΆΒΓΔΕΈΖΗΉΘΙΊΚΛΜΝΞΟΌΠΡΣΤΥΎΦΧΨΩΏ·\\nαάβγδεέζηήθιίκλμνξοόπρστυύφχψωώ\\nϊΐςϋΰ⌘⌥⇧čďěňřšťůýžČĎĚŇŘŠŤŮÝŽ\n\neffect.class=com.badlogic.gdx.tools.hiero.unicodefont.effects.ColorEffect\neffect.Color=ffffff\n\n"
  },
  {
    "path": "ui/build.gradle",
    "content": "archivesBaseName = \"vis-ui\"\nsourceCompatibility = 1.8\n[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'\n\ndependencies {\n    implementation \"com.badlogicgames.gdx:gdx:$gdxVersion\"\n    testImplementation \"com.badlogicgames.gdx:gdx-backend-lwjgl3:$gdxVersion\"\n    testImplementation \"com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop\"\n    testImplementation \"junit:junit:$junitVersion\"\n    //testImplementation \"com.kotcrab.vne:vne-runtime:1.0.1\"\n    //testImplementation \"com.kotcrab.vne:vne-win-thumbnails:1.0.1\"\n    //testImplementation group: 'com.kotcrab.vis', name: 'vis-ui-contrib', version: '1.3.0'\n    //testImplementation \"org.imgscalr:imgscalr-lib:4.2\"\n}\n\ncompileTestJava {\n    targetCompatibility = 1.8\n}\n\ntest {\n    useJUnit {\n        include \"**/*Test.**\"\n        exclude 'com.kotcrab.vis.ui.test.manual.**'\n    }\n}\n\ntask run(dependsOn: jar, type: JavaExec) {\n    main = 'com.kotcrab.vis.ui.test.manual.TestLauncher'\n    classpath = sourceSets.test.runtimeClasspath\n    ignoreExitValue = true\n\n    if (System.getProperty(\"os.name\").toLowerCase().contains(\"mac\")) {\n        // Required to run lwjgl java apps on Mac OSX\n        jvmArgs = [\"-XstartOnFirstThread\"]\n    }\n}\n\ntask packSkin {\n    doLast {\n        description 'Compiles VisUI USL skin to JSON'\n\n        def basePath = rootProject.projectDir.absolutePath + \"/ui/\"\n\n        def x1Input = new File(basePath + \"assets-raw/x1\").absolutePath\n        def x1Output = new File(basePath + \"src/main/resources/com/kotcrab/vis/ui/skin/x1/\").absolutePath\n        com.badlogic.gdx.tools.texturepacker.TexturePacker.process(x1Input, x1Output, \"uiskin\")\n        def x2Input = new File(basePath + \"assets-raw/x2\").absolutePath\n        def x2Output = new File(basePath + \"src/main/resources/com/kotcrab/vis/ui/skin/x2/\").absolutePath\n        com.badlogic.gdx.tools.texturepacker.TexturePacker.process(x2Input, x2Output, \"uiskin\")\n    }\n}\n\ntask compileUsl {\n    doLast {\n        description 'Pack skin textures into texture atlases'\n\n        def basePath = rootProject.projectDir.absolutePath + \"/ui/src/main/resources/com/kotcrab/vis/ui/skin/\"\n        def x1File = new File(basePath + \"x1/uiskin.json\")\n        def x2File = new File(basePath + \"x2/uiskin.json\")\n        com.kotcrab.vis.usl.Lexer.addIncludeSource(rootProject.projectDir.absolutePath + \"/usl/styles\")\n        def json = com.kotcrab.vis.usl.USL.parse(null, \"include <visui-\" + version + \">\")\n        x1File.text = json\n        x2File.text = json\n    }\n}\n\ntask compileSkin(dependsOn: ['compileUsl', 'packSkin']) {\n    description 'Pack skin textures into texture atlases and compile USL into JSON'\n}\n"
  },
  {
    "path": "ui/gradle.properties",
    "content": "projectName=vis-ui\nprojectDesc=UI toolkit and flat design skin for scene2d.ui\nprojectVersion=1.5.9-SNAPSHOT\n"
  },
  {
    "path": "ui/icons-license",
    "content": "# License\nPlease carefully understand the license and download the latest icons at ModernUIIcons.com.\n## Understand Your Rights\nNo Attribution and No Derived Works\nhttp://creativecommons.org/licenses/by-nd/3.0/ *\n- If your project is open source include this license file in the source.\n- Nothing is needed in the front facing project (UNLESS you\nare using any of the icons listed below in the attribution section).\n- Commercial use is not only allowed but encouraged. If it is an icon\nin the attribution list below, you still need to attribute those!\n- Do not distribute the entire package (I've allowed this dozens of\ntimes for open source projects, but email me first).\n## Creator\n- Austin Andrews (@templarian)\n## Contributor**\n- Jay Zawrotny (@JayZawrotny)\n- A Bunch\n- Oren Nachman\n- appbar.chevron.down\n- appbar.chevron.up\n- appbar.chevron.left\n- appbar.chevron.right\n## Derived Works\n- Alex Peattie\n- Social: http://www.alexpeattie.com/projects/justvector_icons/\n## Attribution***\n- Kris Vandermotten (@kvandermotten)\n- appbar.medical.pulse\n- Constantin Kichinsky (@kichinsky)\n- appbar.currency.rubles\n- appbar.currency.grivna\n- Massimo Savazzi (@msavazzi)\n- List of missing exported icons\n- Proletkult Graphik, from The Noun Project\n- appbar.draw.pen (inspired)\n- Olivier Guin, from The Noun Project\n- appbar.draw.marker\n- Gibran Bisio, from The Noun Project\n- appbar.draw.bucket\nAndrew Forrester, from The Noun Project\n- appbar.fingerprint\n* The license is for attribution, but this is not required.\n** Developers and designers that emailed Templarian the source .design icons to be added into the package. PNGs also accepted, but may take longer to be added.\n*** Icons I've copied so closely you want to attribute them and are also under the CC license.\nContact\n- http://templarian.com/\n- admin[@]templarian[.]com\n* Does not apply to copyrighted logos\n- Skype\n- Facebook\n- Twitter\n- etc..."
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/FocusManager.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.Stage;\n\n/**\n * Manages focus of VisUI components. This is different from stage2d.ui focus management. In scene2d widgets can only\n * acquire keyboard and scroll focus. VisUI focus managers allows any widget to acquire general user focus, this is used\n * mainly to manage rendering focus borders around widgets. Generally there is no need to call those method manually.\n * @author Kotcrab\n * @see Focusable\n */\npublic class FocusManager {\n\tprivate static Focusable focusedWidget;\n\n\t/**\n\t * Takes focus from current focused widget (if any), and sets focus to provided widget\n\t * @param stage if passed stage is not null then stage keyboard focus will be set to null\n\t * @param widget that will acquire focus\n\t */\n\tpublic static void switchFocus (Stage stage, Focusable widget) {\n\t\tif (focusedWidget == widget) return;\n\t\tif (focusedWidget != null) focusedWidget.focusLost();\n\t\tfocusedWidget = null;\n\t\tif (stage != null) stage.setKeyboardFocus(null);\n\t\tfocusedWidget = widget;\n\t\tfocusedWidget.focusGained();\n\t}\n\n\t/**\n\t * Takes focus from current focused widget (if any), and sets current focused widget to null. If widgets owns\n\t * keyboard focus {@link #resetFocus(Stage, Actor)} should be always preferred.\n\t * @param stage if passed stage is not null then stage keyboard focus will be set to null\n\t */\n\tpublic static void resetFocus (Stage stage) {\n\t\tif (focusedWidget != null) focusedWidget.focusLost();\n\t\tif (stage != null) stage.setKeyboardFocus(null);\n\t\tfocusedWidget = null;\n\t}\n\n\t/**\n\t * Takes focus from current focused widget (if any), and sets current focused widget to null\n\t * @param stage if passed stage is not null then stage keyboard focus will be set to null only if current\n\t * focus owner is passed actor\n\t */\n\tpublic static void resetFocus (Stage stage, Actor caller) {\n\t\tif (focusedWidget != null) focusedWidget.focusLost();\n\t\tif (stage != null && stage.getKeyboardFocus() == caller) stage.setKeyboardFocus(null);\n\t\tfocusedWidget = null;\n\t}\n\n\tpublic static Focusable getFocusedWidget () {\n\t\treturn focusedWidget;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/Focusable.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui;\n\n/**\n * Implemented by objects that can acquire VisUI focus.\n * @author Kotcrab\n * @see FocusManager\n */\npublic interface Focusable {\n\t/** Called by VisUI when object lost focus. Don not cally manually, see {@link FocusManager}. */\n\tvoid focusLost ();\n\n\t/** Called by VisUI when object gained focus. Don not cally manually, see {@link FocusManager}. */\n\tvoid focusGained ();\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/Locales.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.utils.I18NBundle;\nimport com.kotcrab.vis.ui.i18n.BundleText;\nimport com.kotcrab.vis.ui.util.dialog.Dialogs;\nimport com.kotcrab.vis.ui.widget.ButtonBar;\nimport com.kotcrab.vis.ui.widget.color.ColorPicker;\nimport com.kotcrab.vis.ui.widget.file.FileChooser;\nimport com.kotcrab.vis.ui.widget.tabbedpane.TabbedPane;\n\nimport java.util.Locale;\n\n/**\n * Manages VisUI's I18N bundles.\n * @author Kotcrab\n * @since 1.0.0\n */\npublic class Locales {\n\tprivate static Locale locale = new Locale(\"en\");\n\tprivate static I18NBundle commonBundle;\n\tprivate static I18NBundle buttonBarBundle;\n\tprivate static I18NBundle fileChooserBundle;\n\tprivate static I18NBundle dialogsBundle;\n\tprivate static I18NBundle tabbedPaneBundle;\n\tprivate static I18NBundle colorPickerBundle;\n\n\t/** Returns common I18N bundle. If current bundle is null, a default bundle is set and returned */\n\tpublic static I18NBundle getCommonBundle () {\n\t\tif (commonBundle == null) commonBundle = getBundle(\"com/kotcrab/vis/ui/i18n/Common\");\n\t\treturn commonBundle;\n\t}\n\n\t/**\n\t * Changes common bundle. Since this bundle may be used by multiple VisUI parts it should be changed before loading VisUI.\n\t * If set to null then {@link #getCommonBundle()} will return default bundle.\n\t */\n\tpublic static void setCommonBundle (I18NBundle commonBundle) {\n\t\tLocales.commonBundle = commonBundle;\n\t}\n\n\t/** Returns I18N bundle used by {@link FileChooser}, if current bundle is null, a default bundle is set and returned */\n\tpublic static I18NBundle getFileChooserBundle () {\n\t\tif (fileChooserBundle == null) fileChooserBundle = getBundle(\"com/kotcrab/vis/ui/i18n/FileChooser\");\n\t\treturn fileChooserBundle;\n\t}\n\n\t/**\n\t * Changes bundle used by {@link FileChooser}, will not affect already created FileChoosers.\n\t * If set to null then {@link #getFileChooserBundle()} will return default bundle.\n\t */\n\tpublic static void setFileChooserBundle (I18NBundle fileChooserBundle) {\n\t\tLocales.fileChooserBundle = fileChooserBundle;\n\t}\n\n\t/** Returns I18N bundle used by {@link Dialogs}, if current bundle is null, a default bundle is set and returned */\n\tpublic static I18NBundle getDialogsBundle () {\n\t\tif (dialogsBundle == null) dialogsBundle = getBundle(\"com/kotcrab/vis/ui/i18n/Dialogs\");\n\t\treturn dialogsBundle;\n\t}\n\n\t/**\n\t * Changes bundle used by {@link Dialogs}, will not affect already created dialogs.\n\t * If set to null then {@link #getDialogsBundle()} will return default bundle.\n\t */\n\tpublic static void setDialogsBundle (I18NBundle dialogsBundle) {\n\t\tLocales.dialogsBundle = dialogsBundle;\n\t}\n\n\t/** Returns I18N bundle used by {@link TabbedPane}, if current bundle is null, a default bundle is set and returned */\n\tpublic static I18NBundle getTabbedPaneBundle () {\n\t\tif (tabbedPaneBundle == null) tabbedPaneBundle = getBundle(\"com/kotcrab/vis/ui/i18n/TabbedPane\");\n\t\treturn tabbedPaneBundle;\n\t}\n\n\t/**\n\t * Changes bundle used by {@link TabbedPane}, will not affect already created TabbedPane.\n\t * If set to null then {@link #getTabbedPaneBundle()} will return default bundle.\n\t */\n\tpublic static void setTabbedPaneBundle (I18NBundle tabbedPaneBundle) {\n\t\tLocales.tabbedPaneBundle = tabbedPaneBundle;\n\t}\n\n\t/** Returns I18N bundle used by {@link ColorPicker}, if current bundle is null, a default bundle is set and returned */\n\tpublic static I18NBundle getColorPickerBundle () {\n\t\tif (colorPickerBundle == null) colorPickerBundle = getBundle(\"com/kotcrab/vis/ui/i18n/ColorPicker\");\n\t\treturn colorPickerBundle;\n\t}\n\n\t/**\n\t * Changes bundle used by {@link ColorPicker}, will not affect already created pickers.\n\t * If set to null then {@link #getColorPickerBundle()} will return default bundle.\n\t */\n\tpublic static void setColorPickerBundle (I18NBundle colorPickerBundle) {\n\t\tLocales.colorPickerBundle = colorPickerBundle;\n\t}\n\n\t/** Returns I18N bundle used by {@link ButtonBar}, if current bundle is null, a default bundle is set and returned */\n\tpublic static I18NBundle getButtonBarBundle () {\n\t\tif (buttonBarBundle == null) buttonBarBundle = getBundle(\"com/kotcrab/vis/ui/i18n/ButtonBar\");\n\t\treturn buttonBarBundle;\n\t}\n\n\t/**\n\t * Changes bundle used by {@link ButtonBar}, will not affect already created bars.\n\t * If set to null then {@link #getButtonBarBundle()} ()} will return default bundle.\n\t */\n\tpublic static void setButtonBarBundle (I18NBundle buttonBarBundle) {\n\t\tLocales.buttonBarBundle = buttonBarBundle;\n\t}\n\n\t/**\n\t * Changes current locale, this should be done when VisUI isn't loaded yet because changing this won't affect bundles\n\t * that are already loaded.\n\t */\n\tpublic static void setLocale (Locale locale) {\n\t\tLocales.locale = locale;\n\t}\n\n\tprivate static I18NBundle getBundle (String path) {\n\t\tFileHandle bundleFile = Gdx.files.classpath(path);\n\t\treturn I18NBundle.createBundle(bundleFile, locale);\n\t}\n\n\tpublic enum CommonText implements BundleText {\n\t\tPLEASE_WAIT(\"pleaseWait\"),\n\t\tUNKNOWN_ERROR_OCCURRED(\"unknownErrorOccurred\");\n\n\t\tprivate final String name;\n\n\t\tCommonText (final String name) {\n\t\t\tthis.name = name;\n\t\t}\n\n\t\tprivate static I18NBundle getBundle () {\n\t\t\treturn Locales.getCommonBundle();\n\t\t}\n\n\t\t@Override\n\t\tpublic final String getName () {\n\t\t\treturn name;\n\t\t}\n\n\t\t@Override\n\t\tpublic final String get () {\n\t\t\treturn getBundle().get(name);\n\t\t}\n\n\t\t@Override\n\t\tpublic final String format () {\n\t\t\treturn getBundle().format(name);\n\t\t}\n\n\t\t@Override\n\t\tpublic final String format (final Object... arguments) {\n\t\t\treturn getBundle().format(name, arguments);\n\t\t}\n\n\t\t@Override\n\t\tpublic final String toString () {\n\t\t\treturn get();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/Sizes.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui;\n\n/**\n * VisUI padding, spacings and sizes. Loaded from skin, will differ between different skin sizes. If you are using\n * custom skin it must contain \"default\" definition of Sizes values.\n * @author Kotcrab\n * @since 0.8.1\n */\npublic class Sizes {\n\tpublic float scaleFactor;\n\n\tpublic float spacingTop;\n\tpublic float spacingBottom;\n\tpublic float spacingRight;\n\tpublic float spacingLeft;\n\n\tpublic float buttonBarSpacing;\n\n\tpublic float menuItemIconSize;\n\n\t/**\n\t * Size of focus border. 1 for standard Vis skin. This is used to avoid showing overlapping borders when two widgets\n\t * have borders (for example button can have it's own focus border which without this padding would overlap with menu border)\n\t */\n\tpublic float borderSize;\n\n\tpublic float spinnerButtonHeight;\n\tpublic float spinnerFieldSize;\n\n\tpublic float fileChooserViewModeBigIconsSize;\n\tpublic float fileChooserViewModeMediumIconsSize;\n\tpublic float fileChooserViewModeSmallIconsSize;\n\tpublic float fileChooserViewModeListWidthSize;\n\n\tpublic Sizes () {\n\t}\n\n\tpublic Sizes (Sizes other) {\n\t\tthis.scaleFactor = other.scaleFactor;\n\t\tthis.spacingTop = other.spacingTop;\n\t\tthis.spacingBottom = other.spacingBottom;\n\t\tthis.spacingRight = other.spacingRight;\n\t\tthis.spacingLeft = other.spacingLeft;\n\t\tthis.buttonBarSpacing = other.buttonBarSpacing;\n\t\tthis.menuItemIconSize = other.menuItemIconSize;\n\t\tthis.borderSize = other.borderSize;\n\t\tthis.spinnerButtonHeight = other.spinnerButtonHeight;\n\t\tthis.spinnerFieldSize = other.spinnerFieldSize;\n\t\tthis.fileChooserViewModeBigIconsSize = other.fileChooserViewModeBigIconsSize;\n\t\tthis.fileChooserViewModeMediumIconsSize = other.fileChooserViewModeMediumIconsSize;\n\t\tthis.fileChooserViewModeSmallIconsSize = other.fileChooserViewModeSmallIconsSize;\n\t\tthis.fileChooserViewModeListWidthSize = other.fileChooserViewModeListWidthSize;\n\t}\n}\n\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/VisUI.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.Version;\nimport com.badlogic.gdx.assets.AssetManager;\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.scenes.scene2d.ui.Skin;\nimport com.badlogic.gdx.utils.Align;\nimport com.badlogic.gdx.utils.GdxRuntimeException;\n\n/**\n * Allows to easily load VisUI skin and change default title alignment and I18N bundles.\n * Contains static field with VisUI version.\n * @author Kotcrab\n */\npublic class VisUI {\n\tprivate static final String TARGET_GDX_VERSION = \"1.14.0\";\n\tprivate static boolean skipGdxVersionCheck = false;\n\n\tprivate static int defaultTitleAlign = Align.left;\n\n\tprivate static SkinScale scale;\n\tprivate static Skin skin;\n\n\t/** Defines possible built-in skin scales. */\n\tpublic enum SkinScale {\n\t\t/** Standard VisUI skin */\n\t\tX1(\"com/kotcrab/vis/ui/skin/x1/uiskin.json\", \"default\"),\n\t\t/** VisUI skin 2x upscaled */\n\t\tX2(\"com/kotcrab/vis/ui/skin/x2/uiskin.json\", \"x2\");\n\n\t\tprivate final String classpath;\n\t\tprivate final String sizesName;\n\n\t\tSkinScale (String classpath, String sizesName) {\n\t\t\tthis.classpath = classpath;\n\t\t\tthis.sizesName = sizesName;\n\t\t}\n\n\t\tpublic FileHandle getSkinFile () {\n\t\t\treturn Gdx.files.classpath(classpath);\n\t\t}\n\n\t\tpublic String getSizesName () {\n\t\t\treturn sizesName;\n\t\t}\n\t}\n\n\t/** Loads default VisUI skin with {@link SkinScale#X1}. */\n\tpublic static void load () {\n\t\tload(SkinScale.X1);\n\t}\n\n\t/** Loads default VisUI skin for given {@link SkinScale}. */\n\tpublic static void load (SkinScale scale) {\n\t\tVisUI.scale = scale;\n\t\tload(scale.getSkinFile());\n\t}\n\n\t/** Loads skin from provided internal file path. Skin must be compatible with default VisUI skin. */\n\tpublic static void load (String internalVisSkinPath) {\n\t\tload(Gdx.files.internal(internalVisSkinPath));\n\t}\n\n\t/** Loads skin from provided file. Skin must be compatible with default VisUI skin. */\n\tpublic static void load (FileHandle visSkinFile) {\n\t\tcheckBeforeLoad();\n\t\tVisUI.skin = new Skin(visSkinFile);\n\t}\n\n\t/**\n\t * Sets provided skin as default for every VisUI widget. Skin must be compatible with default VisUI skin. This\n\t * can be used if you prefer to load skin manually for example by using {@link AssetManager}.\n\t */\n\tpublic static void load (Skin skin) {\n\t\tcheckBeforeLoad();\n\t\tVisUI.skin = skin;\n\t}\n\n\tprivate static void checkBeforeLoad () {\n\t\tif (skin != null) throw new GdxRuntimeException(\"VisUI cannot be loaded twice\");\n\t\tif (!skipGdxVersionCheck && !Version.VERSION.equals(TARGET_GDX_VERSION)) {\n\t\t\tGdx.app.log(\"VisUI\", \"Warning, using invalid libGDX version.\\n\" +\n\t\t\t\t\t\"You are using libGDX \" + Version.VERSION + \" but you need \" + TARGET_GDX_VERSION + \". This may cause \" +\n\t\t\t\t\t\"unexpected problems and runtime exceptions.\");\n\t\t}\n\t}\n\n\t/** Unloads VisUI. */\n\tpublic static void dispose () {\n\t\tdispose(true);\n\t}\n\n\t/**\n\t * Unloads VisUI.\n\t * @param disposeSkin if true then internal skin instance will be disposed\n\t */\n\tpublic static void dispose (boolean disposeSkin) {\n\t\tif (skin != null) {\n\t\t\tif (disposeSkin) skin.dispose();\n\t\t\tskin = null;\n\t\t}\n\t}\n\n\tpublic static Skin getSkin () {\n\t\tif (skin == null) throw new IllegalStateException(\"VisUI is not loaded!\");\n\t\treturn skin;\n\t}\n\n\tpublic static boolean isLoaded () {\n\t\treturn skin != null;\n\t}\n\n\tpublic static Sizes getSizes () {\n\t\tif (scale == null)\n\t\t\treturn getSkin().get(Sizes.class);\n\t\telse\n\t\t\treturn getSkin().get(scale.getSizesName(), Sizes.class);\n\t}\n\n\t/** @return int value from {@link Align} */\n\tpublic static int getDefaultTitleAlign () {\n\t\treturn defaultTitleAlign;\n\t}\n\n\t/**\n\t * Sets default title align user for VisWindow and VisDialog\n\t * @param defaultTitleAlign int value from {@link Align}\n\t */\n\tpublic static void setDefaultTitleAlign (int defaultTitleAlign) {\n\t\tVisUI.defaultTitleAlign = defaultTitleAlign;\n\t}\n\n\t/**\n\t * @param setSkipGdxVersionCheck if true VisUI won't check if provided libGDX version is compatible for current version of VisUI.\n\t * If false, before loading VisUI, a libGDX version check will be performed, in case of version mismatch warning\n\t * will be printed to console\n\t * @see <a href=\"https://github.com/kotcrab/vis-ui#libgdx-compatibility\">Version compatiblity table (online)</a>\n\t */\n\tpublic static void setSkipGdxVersionCheck (boolean setSkipGdxVersionCheck) {\n\t\tVisUI.skipGdxVersionCheck = setSkipGdxVersionCheck;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/building/CenteredTableBuilder.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.building;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Cell;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.utils.IntArray;\nimport com.kotcrab.vis.ui.building.utilities.Padding;\n\n/**\n * Builds a table with the appended widgets, trying to keep them centered. Expands X axis for first and last\n * widget in each row and overrides their alignments to right and left, keeping the widgets centered. Each\n * table's row will have the same colspan. While useful, StandardTableBuilder might be more appropriate for\n * complex tables.\n * @author MJ\n */\npublic class CenteredTableBuilder extends TableBuilder {\n\tpublic CenteredTableBuilder () {\n\t\tsuper();\n\t}\n\n\t/** @param defaultWidgetPadding will be applied to all added widgets if no specific padding is given. */\n\tpublic CenteredTableBuilder (final Padding defaultWidgetPadding) {\n\t\tsuper(defaultWidgetPadding);\n\t}\n\n\tpublic CenteredTableBuilder (final int estimatedWidgetsAmount, final int estimatedRowsAmount) {\n\t\tsuper(estimatedWidgetsAmount, estimatedRowsAmount);\n\t}\n\n\t/** @param defaultWidgetPadding will be applied to all added widgets if no specific padding is given. */\n\tpublic CenteredTableBuilder (final int estimatedWidgetsAmount, final int estimatedRowsAmount,\n\t\t\t\t\t\t\t\t final Padding defaultWidgetPadding) {\n\t\tsuper(estimatedWidgetsAmount, estimatedRowsAmount, defaultWidgetPadding);\n\t}\n\n\t@Override\n\tprotected void fillTable (final Table table) {\n\t\tfinal IntArray rowSizes = getRowSizes();\n\t\tfinal int widgetsInRow = getLowestCommonMultiple(rowSizes);\n\n\t\tfor (int rowIndex = 0, widgetIndex = 0; rowIndex < rowSizes.size; rowIndex++) {\n\t\t\tfinal int rowSize = rowSizes.get(rowIndex);\n\t\t\tfinal int currentWidgetColspan = widgetsInRow / rowSize;\n\t\t\tboolean isFirst = shouldExpand(rowSize);\n\n\t\t\tfor (final int totalWidgetsBeforeRowEnd = widgetIndex + rowSize; widgetIndex < totalWidgetsBeforeRowEnd; widgetIndex++) {\n\t\t\t\tfinal Cell<?> cell =\n\t\t\t\t\t\tgetWidget(widgetIndex).buildCell(table, getDefaultWidgetPadding()).colspan(\n\t\t\t\t\t\t\t\tcurrentWidgetColspan);\n\t\t\t\t// Keeping widgets together - expanding X for first and last widget, setting alignments:\n\t\t\t\tif (isFirst) {\n\t\t\t\t\tisFirst = false;\n\t\t\t\t\tcell.expandX().right();\n\t\t\t\t} else if (isLast(widgetIndex, rowSize, totalWidgetsBeforeRowEnd)) {\n\t\t\t\t\tcell.expandX().left();\n\t\t\t\t}\n\t\t\t}\n\t\t\ttable.row();\n\t\t}\n\t}\n\n\t/**\n\t * When table is trying to keep widgets together and widget is not alone in the row (in which case it\n\t * should be centered instead), it has to expand on X and be aligned right.\n\t * @param rowSize current row size.\n\t * @return true if row size is bigger than 1.\n\t */\n\tprivate boolean shouldExpand (final int rowSize) {\n\t\treturn rowSize != 1;\n\t}\n\n\t/**\n\t * @return true if the widget is last. It is used to determine if the widget has to be left-aligned and\n\t * expand on X axis.\n\t */\n\tprivate boolean isLast (final int widgetIndex, final int rowSize, final int totalWidgetsInRow) {\n\t\treturn shouldExpand(rowSize) && widgetIndex == totalWidgetsInRow - 1;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/building/GridTableBuilder.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.building;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.kotcrab.vis.ui.building.utilities.CellWidget;\nimport com.kotcrab.vis.ui.building.utilities.Padding;\n\n/**\n * Ignores row() calls and builds table with all widgets put into rows of given size. Note that this builder\n * will not center or in any way try to \"repair\" the last row if too few widgets are given to create a true\n * grid.\n * @author MJ\n */\npublic class GridTableBuilder extends TableBuilder {\n\tprivate final int rowSize;\n\n\tpublic GridTableBuilder (final int rowSize) {\n\t\tsuper();\n\t\tthis.rowSize = rowSize;\n\t}\n\n\t/** @param defaultWidgetPadding will be applied to all added widgets if no specific padding is given. */\n\tpublic GridTableBuilder (final Padding defaultWidgetPadding, final int rowSize) {\n\t\tsuper(defaultWidgetPadding);\n\t\tthis.rowSize = rowSize;\n\t}\n\n\tpublic GridTableBuilder (final int rowSize, final int estimatedWidgetsAmount, final int estimatedRowsAmount) {\n\t\tsuper(estimatedWidgetsAmount, estimatedRowsAmount);\n\t\tthis.rowSize = rowSize;\n\t}\n\n\t/** @param defaultWidgetPadding will be applied to all added widgets if no specific padding is given. */\n\tpublic GridTableBuilder (final int rowSize, final int estimatedWidgetsAmount,\n\t\t\t\t\t\t\t final int estimatedRowsAmount, final Padding defaultWidgetPadding) {\n\t\tsuper(estimatedWidgetsAmount, estimatedRowsAmount, defaultWidgetPadding);\n\t\tthis.rowSize = rowSize;\n\t}\n\n\t@Override\n\tprotected void fillTable (final Table table) {\n\t\tint widgetsCounter = 0;\n\t\tfor (final CellWidget<? extends Actor> widget : getWidgets()) {\n\t\t\twidget.buildCell(table, getDefaultWidgetPadding());\n\t\t\tif (++widgetsCounter == rowSize) {\n\t\t\t\twidgetsCounter -= rowSize;\n\t\t\t\ttable.row();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/building/OneColumnTableBuilder.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.building;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.kotcrab.vis.ui.building.utilities.CellWidget;\nimport com.kotcrab.vis.ui.building.utilities.Padding;\n\n/**\n * Ignores row() calls and builds table with all widgets put into one column.\n * @author MJ\n */\npublic class OneColumnTableBuilder extends TableBuilder {\n\tpublic OneColumnTableBuilder () {\n\t\tsuper();\n\t}\n\n\t/** @param defaultWidgetPadding will be applied to all added widgets if no specific padding is given. */\n\tpublic OneColumnTableBuilder (final Padding defaultWidgetPadding) {\n\t\tsuper(defaultWidgetPadding);\n\t}\n\n\tpublic OneColumnTableBuilder (final int estimatedWidgetsAmount, final int estimatedRowsAmount) {\n\t\tsuper(estimatedWidgetsAmount, estimatedRowsAmount);\n\t}\n\n\t/** @param defaultWidgetPadding will be applied to all added widgets if no specific padding is given. */\n\tpublic OneColumnTableBuilder (final int estimatedWidgetsAmount, final int estimatedRowsAmount,\n\t\t\t\t\t\t\t\t  final Padding defaultWidgetPadding) {\n\t\tsuper(estimatedWidgetsAmount, estimatedRowsAmount, defaultWidgetPadding);\n\t}\n\n\t@Override\n\tprotected void fillTable (final Table table) {\n\t\tfor (final CellWidget<? extends Actor> widget : getWidgets()) {\n\t\t\twidget.buildCell(table, getDefaultWidgetPadding()).row();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/building/OneRowTableBuilder.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.building;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.kotcrab.vis.ui.building.utilities.CellWidget;\nimport com.kotcrab.vis.ui.building.utilities.Padding;\n\n/**\n * Ignores row() calls and builds table with all widgets put into one row. Works like a StandardTableBuilder\n * if row() is never used, but keeps the code clearer, as the name pretty much tells what you are trying to\n * do.\n * @author MJ\n */\npublic class OneRowTableBuilder extends TableBuilder {\n\tpublic OneRowTableBuilder () {\n\t\tsuper();\n\t}\n\n\t/** @param defaultWidgetPadding will be applied to all added widgets if no specific padding is given. */\n\tpublic OneRowTableBuilder (final Padding defaultWidgetPadding) {\n\t\tsuper(defaultWidgetPadding);\n\t}\n\n\tpublic OneRowTableBuilder (final int estimatedWidgetsAmount, final int estimatedRowsAmount) {\n\t\tsuper(estimatedWidgetsAmount, estimatedRowsAmount);\n\t}\n\n\t/** @param defaultWidgetPadding will be applied to all added widgets if no specific padding is given. */\n\tpublic OneRowTableBuilder (final int estimatedWidgetsAmount, final int estimatedRowsAmount,\n\t\t\t\t\t\t\t   final Padding defaultWidgetPadding) {\n\t\tsuper(estimatedWidgetsAmount, estimatedRowsAmount, defaultWidgetPadding);\n\t}\n\n\t@Override\n\tprotected void fillTable (final Table table) {\n\t\tfor (final CellWidget<? extends Actor> widget : getWidgets()) {\n\t\t\twidget.buildCell(table, getDefaultWidgetPadding());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/building/StandardTableBuilder.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.building;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.utils.IntArray;\nimport com.kotcrab.vis.ui.building.utilities.Padding;\n\n/**\n * Builds a standard table with the appended widgets. Each table's row will have the same colspan. Honors all\n * CellWidget settings and TableBuilder commands, making it the most flexible TableBuilder and the best one\n * for complex, custom tables.\n * @author MJ\n */\npublic class StandardTableBuilder extends TableBuilder {\n\tpublic StandardTableBuilder () {\n\t\tsuper();\n\t}\n\n\t/** @param defaultWidgetPadding will be applied to all added widgets if no specific padding is given. */\n\tpublic StandardTableBuilder (final Padding defaultWidgetPadding) {\n\t\tsuper(defaultWidgetPadding);\n\t}\n\n\tpublic StandardTableBuilder (final int estimatedWidgetsAmount, final int estimatedRowsAmount) {\n\t\tsuper(estimatedWidgetsAmount, estimatedRowsAmount);\n\t}\n\n\t/** @param defaultWidgetPadding will be applied to all added widgets if no specific padding is given. */\n\tpublic StandardTableBuilder (final int estimatedWidgetsAmount, final int estimatedRowsAmount,\n\t\t\t\t\t\t\t\t final Padding defaultWidgetPadding) {\n\t\tsuper(estimatedWidgetsAmount, estimatedRowsAmount, defaultWidgetPadding);\n\t}\n\n\t@Override\n\tprotected void fillTable (final Table table) {\n\t\tfinal IntArray rowSizes = getRowSizes();\n\t\tfinal int widgetsInRow = getLowestCommonMultiple(rowSizes);\n\t\tfor (int rowIndex = 0, widgetIndex = 0; rowIndex < rowSizes.size; rowIndex++) {\n\t\t\tfinal int rowSize = rowSizes.get(rowIndex);\n\t\t\tfinal int currentWidgetColspan = widgetsInRow / rowSize;\n\t\t\tfor (final int totalWidgets = widgetIndex + rowSize; widgetIndex < totalWidgets; widgetIndex++) {\n\t\t\t\tgetWidget(widgetIndex).buildCell(table, getDefaultWidgetPadding()).colspan(\n\t\t\t\t\t\tcurrentWidgetColspan);\n\t\t\t}\n\t\t\ttable.row();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/building/TableBuilder.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.building;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.utils.Array;\nimport com.badlogic.gdx.utils.IntArray;\nimport com.kotcrab.vis.ui.building.utilities.CellWidget;\nimport com.kotcrab.vis.ui.building.utilities.CellWidget.CellWidgetBuilder;\nimport com.kotcrab.vis.ui.building.utilities.Padding;\nimport com.kotcrab.vis.ui.building.utilities.layouts.ActorLayout;\nimport com.kotcrab.vis.ui.building.utilities.layouts.TableLayout;\n\n/**\n * Allows to easily build Scene2D tables, without having to worry about different colspans of table's rows.\n * Table built using this helper class will have the same amount of cells in each row. CellWidget class allows\n * to store cell's settings, and thanks to that - even the most complex tables can be built using one of the\n * TableBuilders.\n * @author MJ\n */\npublic abstract class TableBuilder {\n\tprivate final static int DEFAULT_WIDGETS_AMOUNT = 10, DEFAULT_ROWS_AMOUNT = 3;\n\n\tprivate final Array<CellWidget<? extends Actor>> widgets;\n\tprivate final IntArray rowSizes;\n\t// Control variables.\n\tprivate int currentRowSize;\n\t// Settings.\n\tprivate final Padding widgetPadding;\n\tprivate Padding tablePadding;\n\n\tpublic TableBuilder () {\n\t\tthis(DEFAULT_WIDGETS_AMOUNT, DEFAULT_ROWS_AMOUNT, Padding.PAD_0);\n\t}\n\n\t/** @param defaultWidgetPadding will be applied to all added widgets if no specific padding is given. */\n\tpublic TableBuilder (final Padding defaultWidgetPadding) {\n\t\tthis(DEFAULT_WIDGETS_AMOUNT, DEFAULT_ROWS_AMOUNT, defaultWidgetPadding);\n\t}\n\n\tpublic TableBuilder (final int estimatedWidgetsAmount, final int estimatedRowsAmount) {\n\t\tthis(estimatedWidgetsAmount, estimatedRowsAmount, Padding.PAD_0);\n\t}\n\n\t/** @param defaultWidgetPadding will be applied to all added widgets if no specific padding is given. */\n\tpublic TableBuilder (final int estimatedWidgetsAmount, final int estimatedRowsAmount,\n\t\t\t\t\t\t final Padding defaultWidgetPadding) {\n\t\twidgets = new Array<CellWidget<? extends Actor>>(estimatedWidgetsAmount);\n\t\trowSizes = new IntArray(estimatedRowsAmount);\n\t\twidgetPadding = defaultWidgetPadding;\n\t}\n\n\t/** @return the greatest common denominator of two values. */\n\tpublic static int getGreatestCommonDenominator (final int valueA, final int valueB) {\n\t\treturn valueB == 0 ? valueA : getGreatestCommonDenominator(valueB, valueA % valueB);\n\t}\n\n\t/** @return lowest common multiple for the given two values. */\n\tpublic static int getLowestCommonMultiple (final int valueA, final int valueB) {\n\t\treturn valueA * (valueB / getGreatestCommonDenominator(valueA, valueB));\n\t}\n\n\t/**\n\t * @param values cannot be empty or null.\n\t * @return lowest common multiple for the given values.\n\t */\n\tpublic static int getLowestCommonMultiple (final IntArray values) {\n\t\tint lowestCommonMultiple = values.first();\n\t\tfor (int index = 1; index < values.size; index++) {\n\t\t\tlowestCommonMultiple = getLowestCommonMultiple(lowestCommonMultiple, values.get(index));\n\t\t}\n\t\treturn lowestCommonMultiple;\n\t}\n\n\t/**\n\t * @param tablePadding will define the amount of pixels separating widgets from the table's borders. Can be\n\t * null - nulled padding will be ignored.\n\t */\n\tpublic TableBuilder setTablePadding (final Padding tablePadding) {\n\t\tthis.tablePadding = tablePadding;\n\t\treturn this;\n\t}\n\n\t/**\n\t * @return default widgets' padding. Should be applied to cells that have not specified custom padding\n\t * setting.\n\t */\n\tprotected Padding getDefaultWidgetPadding () {\n\t\treturn widgetPadding;\n\t}\n\n\t/** @param widget will be added to the table with current default table's padding. */\n\tpublic TableBuilder append (final Actor widget) {\n\t\treturn append(CellWidget.of(widget).padding(widgetPadding).wrap());\n\t}\n\n\t/** @param widget will be added to the table with custom provided data. */\n\tpublic TableBuilder append (final CellWidget<? extends Actor> widget) {\n\t\twidgets.add(widget);\n\t\tcurrentRowSize++;\n\n\t\treturn this;\n\t}\n\n\t/** @param widgets will be converted into one cell, with widgets appended into one row. */\n\tpublic TableBuilder append (final Actor... widgets) {\n\t\treturn append(TableLayout.HORIZONTAL, widgets);\n\t}\n\n\t/**\n\t * @param widgets will be converted into one cell, with widgets appended into one row. Note that these\n\t * CellWidgets' settings are local to the merging widget and additional data might have to be\n\t * passed. See methods that consume CellWidgetBuilder.\n\t */\n\tpublic TableBuilder append (final CellWidget<?>... widgets) {\n\t\treturn append(TableLayout.HORIZONTAL, widgets);\n\t}\n\n\t/**\n\t * @param layout will determine how widgets are converted into one cell. See TableLayout for default\n\t * implementations.\n\t * @param widgets will be converted into one cell using passed layout.\n\t */\n\tpublic TableBuilder append (final ActorLayout layout, final Actor... widgets) {\n\t\treturn append(layout.convertToActor(widgets));\n\t}\n\n\t/**\n\t * @param layout will determine how widgets are converted into one cell. See TableLayout for default\n\t * implementations.\n\t * @param widgets will be converted into one cell using passed layout. Note that some (or all) CellWidget\n\t * settings might be ignored, depending on the implementation of ActorLayout. Default layouts\n\t * use TableBuilders, so they do not ignore (most of) passed data. Also, these CellWidgets'\n\t * settings are local to the merging widget and additional data might have to be passed. See\n\t * methods that consume CellWidgetBuilder.\n\t */\n\tpublic TableBuilder append (final ActorLayout layout, final CellWidget<?>... widgets) {\n\t\treturn append(layout.convertToActor(widgets));\n\t}\n\n\t/**\n\t * @param mergedCellSettings its data will be applied to the cell that will contain passed widgets merged\n\t * into one actor.\n\t * @param widgets will be converted into one cell, with widgets appended into one row.\n\t */\n\tpublic TableBuilder append (final CellWidgetBuilder<Actor> mergedCellSettings, final Actor... widgets) {\n\t\treturn append(TableLayout.HORIZONTAL, mergedCellSettings, widgets);\n\t}\n\n\t/**\n\t * @param mergedCellSettings its data will be applied to the cell that will contain passed widgets merged\n\t * into one actor.\n\t * @param widgets will be converted into one cell, with widgets appended into one row.\n\t */\n\tpublic TableBuilder append (final CellWidgetBuilder<Actor> mergedCellSettings,\n\t\t\t\t\t\t\t\tfinal CellWidget<?>... widgets) {\n\t\treturn append(TableLayout.HORIZONTAL, mergedCellSettings, widgets);\n\t}\n\n\t/**\n\t * @param layout will determine how widgets are converted into one cell. See TableLayout for default\n\t * implementations.\n\t * @param mergedCellSettings its data will be applied to the cell that will contain passed widgets merged\n\t * into one actor.\n\t * @param widgets will be converted into one cell using passed layout.\n\t */\n\tpublic TableBuilder append (final ActorLayout layout, final CellWidgetBuilder<Actor> mergedCellSettings,\n\t\t\t\t\t\t\t\tfinal Actor... widgets) {\n\t\treturn append(mergedCellSettings.widget(layout.convertToActor(widgets)).wrap());\n\t}\n\n\t/**\n\t * @param layout will determine how widgets are converted into one cell. See TableLayout for default\n\t * implementations.\n\t * @param mergedCellSettings its data will be applied to the cell that will contain passed widgets merged\n\t * into one actor.\n\t * @param widgets will be converted into one cell using passed layout. Note that some (or all) CellWidget\n\t * settings might be ignored, depending on the implementation of ActorLayout. Default layouts\n\t * use TableBuilders, so they do not ignore (most of) passed data.\n\t */\n\tpublic TableBuilder append (final ActorLayout layout, final CellWidgetBuilder<Actor> mergedCellSettings,\n\t\t\t\t\t\t\t\tfinal CellWidget<?>... widgets) {\n\t\treturn append(mergedCellSettings.widget(layout.convertToActor(widgets)).wrap());\n\t}\n\n\t/**\n\t * Appends an empty cell to the table. Equivalent to passing null to append methods or appending\n\t * CellWidget.EMPTY/CellWidget.empty().\n\t */\n\tpublic TableBuilder append () {\n\t\treturn append(CellWidget.EMPTY);\n\t}\n\n\t/**\n\t * Changes the current row, starts another. If no widgets were appended since the last call, row() will be\n\t * ignored.\n\t */\n\tpublic TableBuilder row () {\n\t\tif (currentRowSize != 0) {\n\t\t\trowSizes.add(currentRowSize);\n\t\t\tcurrentRowSize = 0;\n\t\t}\n\t\treturn this;\n\t}\n\n\t/** @return a new table with the appended widgets, with widgets added depending on the chosen builder type. */\n\tpublic Table build () {\n\t\treturn build(new Table());\n\t}\n\n\t/**\n\t * @return passed table with the appended widgets, with widgets added depending on the chosen builder type.\n\t * Note that if the passed table is not empty, builder implementations do not have to ensure that\n\t * the widgets are actually correctly appended.\n\t */\n\tpublic <T extends Table> T build (final T table) {\n\t\tprepareNewTable(table);\n\t\tif (widgets.size == 0) {\n\t\t\t// Table is empty; avoiding unnecessary operations.\n\t\t\treturn table;\n\t\t} else {\n\t\t\tfillTable(table);\n\t\t\treturn prepareBuiltTable(table);\n\t\t}\n\t}\n\n\tprivate Table prepareNewTable (final Table table) {\n\t\tvalidateRowSize();\n\t\tif (tablePadding != null) {\n\t\t\treturn tablePadding.applyPadding(table);\n\t\t}\n\t\treturn table;\n\t}\n\n\t/**\n\t * Should fill the given table with the widgets appended to the builder. Widgets can be accessed with\n\t * getWidget(index) and getWidgets() methods. Row sizes are already validated. There is at least one\n\t * widget.\n\t * @param table is a properly created Scene2D table. Will be packed and return after filling.\n\t */\n\tprotected abstract void fillTable (Table table);\n\n\tprivate <T extends Table> T prepareBuiltTable (final T table) {\n\t\ttable.pack();\n\t\treturn table;\n\t}\n\n\t/** Will append a new row if any new widgets were passed to make sure that all widgets are honored. */\n\tprivate void validateRowSize () {\n\t\tif (currentRowSize != 0) {\n\t\t\trow();\n\t\t}\n\t}\n\n\t/** @return array with sizes of each row. */\n\tprotected IntArray getRowSizes () {\n\t\treturn rowSizes;\n\t}\n\n\t/** @return CellWidget with the given index in the widgets array. */\n\tprotected CellWidget<? extends Actor> getWidget (final int index) {\n\t\treturn widgets.get(index);\n\t}\n\n\t/** @return all CellWidgets appended to the builder. */\n\tprotected Array<CellWidget<? extends Actor>> getWidgets () {\n\t\treturn widgets;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/building/utilities/Alignment.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.building.utilities;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Cell;\nimport com.badlogic.gdx.utils.Align;\n\n/**\n * libGDX alignments are simple integers and it's rather easy to make a mistake while using the align methods.\n * This enums wraps all default alignments, allowing to validate if the alignment value is actually correct.\n * @author MJ\n */\npublic enum Alignment {\n\tCENTER(Align.center),\n\tTOP(Align.top),\n\tBOTTOM(Align.bottom),\n\tLEFT(Align.left),\n\tRIGHT(Align.right),\n\tTOP_LEFT(Align.topLeft),\n\tTOP_RIGHT(Align.topRight),\n\tBOTTOM_LEFT(Align.bottomLeft),\n\tBOTTOM_RIGHT(Align.bottomRight);\n\n\tprivate final int alignment;\n\n\tprivate Alignment (final int alignment) {\n\t\tthis.alignment = alignment;\n\t}\n\n\tpublic int getAlignment () {\n\t\treturn alignment;\n\t}\n\n\tpublic void apply (final Cell<?> cell) {\n\t\tcell.align(alignment);\n\t}\n\n\t/** @return true for TOP, TOP_LEFT and TOP_RIGHT. */\n\tpublic boolean isAlignedWithTop () {\n\t\treturn (alignment & Align.top) != 0;\n\t}\n\n\t/** @return true for BOTTOM, BOTTOM_LEFT and BOTTOM_RIGHT. */\n\tpublic boolean isAlignedWithBottom () {\n\t\treturn (alignment & Align.bottom) != 0;\n\t}\n\n\t/** @return true for LEFT, BOTTOM_LEFT and TOP_LEFT. */\n\tpublic boolean isAlignedWithLeft () {\n\t\treturn (alignment & Align.left) != 0;\n\t}\n\n\t/** @return true for RIGHT, BOTTOM_RIGHT and TOP_RIGHT. */\n\tpublic boolean isAlignedWithRight () {\n\t\treturn (alignment & Align.right) != 0;\n\t}\n\n\t/** @return true for CENTER. */\n\tpublic boolean isCentered () {\n\t\treturn alignment == Align.center;\n\t}\n\n\t/**\n\t * @param index ordinal of an enum constant.\n\t * @return optional value of enum constant. Will be null for invalid index.\n\t */\n\tpublic static Alignment getByIndex (final int index) {\n\t\treturn isIndexValid(index) ? values()[index] : null;\n\t}\n\n\t/**\n\t * @param index a valid ordinal of an enum constant.\n\t * @return enum constant with the selected index.\n\t * @throws ArrayIndexOutOfBoundsException for invalid index.\n\t */\n\tpublic static Alignment getByValidIndex (final int index) {\n\t\treturn values()[index];\n\t}\n\n\t/** @return true if the index is connected with an enum constant. */\n\tpublic static boolean isIndexValid (final int index) {\n\t\treturn index >= 0 && index < values().length;\n\t}\n\n\t/** @return true if the index is connected with the last enum constant. */\n\tpublic static boolean isIndexLast (final int index) {\n\t\treturn index == values().length - 1;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/building/utilities/CellWidget.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.building.utilities;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Cell;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\n\n/**\n * Wraps a Scene2D widget, allowing to store cell data for delayed Table creation. Note that some filling data\n * (like expanding on X axis or alignment) might be overridden by some TableBuilders (like the\n * CenteredTableBuilder, which tries to keep all widgets centered by setting expansion and alignment of some\n * cells).\n * @author MJ\n */\npublic class CellWidget<Widget extends Actor> {\n\tprivate final static int IGNORED_SIZE = 0;\n\t/** Contains nulled actor. */\n\tpublic final static CellWidget<?> EMPTY = empty();\n\n\tprivate final Widget widget;\n\tprivate final Padding padding;\n\tprivate final boolean expandX, expandY, fillX, fillY, useSpacing;\n\tprivate final Alignment alignment;\n\tprivate final int width, height, minWidth, minHeight;\n\n\t// Cast is safe - builder will have the same type as the cell widget.\n\t@SuppressWarnings(\"unchecked\")\n\tprivate CellWidget (final CellWidgetBuilder<Widget> cellWidgetBuilder) {\n\t\twidget = (Widget) cellWidgetBuilder.widget;\n\t\tpadding = cellWidgetBuilder.padding;\n\t\texpandX = cellWidgetBuilder.expandX;\n\t\texpandY = cellWidgetBuilder.expandY;\n\t\tfillX = cellWidgetBuilder.fillX;\n\t\tfillY = cellWidgetBuilder.fillY;\n\t\tuseSpacing = cellWidgetBuilder.useSpacing;\n\t\talignment = cellWidgetBuilder.alignment;\n\t\twidth = cellWidgetBuilder.width;\n\t\theight = cellWidgetBuilder.height;\n\t\tminWidth = cellWidgetBuilder.minWidth;\n\t\tminHeight = cellWidgetBuilder.minHeight;\n\t}\n\n\t/**\n\t * @param widget will be wrapped with CellWidget.\n\t * @return a new CellWidgetBuilder, allowing to specify the cell's settings.\n\t */\n\tpublic static <Widget extends Actor> CellWidgetBuilder<Widget> of (final Widget widget) {\n\t\treturn new CellWidgetBuilder<Widget>(widget);\n\t}\n\n\t/**\n\t * @param widget will be used to set initial data of builder, allowing to \"modify\" a prepared CellWidget.\n\t * @return a new CellWidgetBuilder, allowing to respecify the cell's settings.\n\t */\n\tpublic static <Widget extends Actor> CellWidgetBuilder<Widget> using (final CellWidget<Widget> widget) {\n\t\treturn new CellWidgetBuilder<Widget>(widget);\n\t}\n\n\t/**\n\t * @param widget will be immediately wrapped into a CellWidget with no specific settings.\n\t * @return wrapped widget.\n\t */\n\tpublic static <Widget extends Actor> CellWidget<Widget> wrap (final Widget widget) {\n\t\treturn of(widget).wrap();\n\t}\n\n\t/**\n\t * @param widgets will be converted to CellWidgets without any specific settings.\n\t * @return wrapped widgets.\n\t */\n\tpublic static CellWidget<?>[] wrap (final Actor... widgets) {\n\t\tfinal CellWidget<?>[] wrappedWidgets = new CellWidget<?>[widgets.length];\n\t\tfor (int index = 0; index < widgets.length; index++) {\n\t\t\twrappedWidgets[index] = CellWidget.of(widgets[index]).wrap();\n\t\t}\n\t\treturn wrappedWidgets;\n\t}\n\n\t/** @return a new empty, non-null CellWidget with no actor. */\n\tpublic static CellWidget<?> empty () {\n\t\treturn builder().wrap();\n\t}\n\n\t/** @return an empty builder with no widget that can be used as data container. */\n\tpublic static CellWidgetBuilder<Actor> builder () {\n\t\treturn of(null);\n\t}\n\n\t/** @return widget wrapped with the CellWidget object. */\n\tpublic Widget getWidget () {\n\t\treturn widget;\n\t}\n\n\t/**\n\t * @param table will contain a cell with the object's widget with specified cell settings.\n\t * @return a reference to the built cell.\n\t */\n\tpublic Cell<?> buildCell (final Table table) {\n\t\treturn buildCell(table, null);\n\t}\n\n\t/**\n\t * @param table will contain a cell with the object's widget with specified cell settings.\n\t * @param defaultWidgetPadding will be applied to the cell if padding was not specified. Can be null.\n\t * @return a reference to the built cell.\n\t */\n\tpublic Cell<?> buildCell (final Table table, final Padding defaultWidgetPadding) {\n\t\tfinal Cell<?> cell = table.add(widget);\n\n\t\tapplyPadding(cell, defaultWidgetPadding);\n\t\tapplySizeData(cell);\n\t\tapplyFillingData(cell);\n\n\t\treturn cell;\n\t}\n\n\tprivate void applyPadding (final Cell<?> cell, final Padding defaultWidgetPadding) {\n\t\tfinal Padding appliedPadding = Nullables.getOrElse(padding, defaultWidgetPadding);\n\t\tif (appliedPadding != null) {\n\t\t\tif (useSpacing) {\n\t\t\t\tappliedPadding.applySpacing(cell);\n\t\t\t} else {\n\t\t\t\tappliedPadding.applyPadding(cell);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void applySizeData (final Cell<?> cell) {\n\t\tif (width > IGNORED_SIZE) {\n\t\t\tcell.width(width);\n\t\t}\n\t\tif (height > IGNORED_SIZE) {\n\t\t\tcell.height(height);\n\t\t}\n\t\tif (minWidth > IGNORED_SIZE) {\n\t\t\tcell.minWidth(minWidth);\n\t\t}\n\t\tif (minHeight > IGNORED_SIZE) {\n\t\t\tcell.minHeight(minHeight);\n\t\t}\n\t}\n\n\tprivate void applyFillingData (final Cell<?> cell) {\n\t\tif (alignment != null) {\n\t\t\talignment.apply(cell);\n\t\t}\n\t\tcell.expand(expandX, expandY);\n\t\tcell.fill(fillX, fillY);\n\t}\n\n\t/**\n\t * Allows to set the CellWidget's data. All setter methods return this for chaining.\n\t * @author MJ\n\t */\n\tpublic static class CellWidgetBuilder<Widget extends Actor> {\n\t\tprivate Actor widget;\n\t\tprivate Padding padding;\n\t\tprivate boolean expandX, expandY, fillX, fillY, useSpacing;\n\t\tprivate Alignment alignment;\n\t\tprivate int width = IGNORED_SIZE, height = IGNORED_SIZE, minWidth = IGNORED_SIZE,\n\t\t\t\tminHeight = IGNORED_SIZE;\n\n\t\tprivate CellWidgetBuilder (final Actor widget) {\n\t\t\tthis.widget = widget;\n\t\t}\n\n\t\tprivate CellWidgetBuilder (final CellWidget<Widget> widget) {\n\t\t\tthis.widget = widget.widget;\n\t\t\tpadding = widget.padding;\n\t\t\texpandX = widget.expandX;\n\t\t\texpandY = widget.expandY;\n\t\t\tfillX = widget.fillX;\n\t\t\tfillY = widget.fillY;\n\t\t\tuseSpacing = widget.useSpacing;\n\t\t\talignment = widget.alignment;\n\t\t\twidth = widget.width;\n\t\t\theight = widget.height;\n\t\t\tminWidth = widget.minWidth;\n\t\t\tminHeight = widget.minHeight;\n\t\t}\n\n\t\t/** @return widget passed to factory method wrapped with CellWidget with the applied data. */\n\t\tpublic CellWidget<Widget> wrap () {\n\t\t\treturn new CellWidget<Widget>(this);\n\t\t}\n\n\t\t/** @param widget will replace the original widget wrapped by the builder. */\n\t\tpublic CellWidgetBuilder<Widget> widget (final Widget widget) {\n\t\t\tthis.widget = widget;\n\t\t\treturn this;\n\t\t}\n\n\t\t/** @param padding can be also applied as spacing after calling useSpacing(). */\n\t\tpublic CellWidgetBuilder<Widget> padding (final Padding padding) {\n\t\t\tthis.padding = padding;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Forces the given padding object to work as spacing data. Spacing will be applied to the cell\n\t\t * instead of padding.\n\t\t */\n\t\tpublic CellWidgetBuilder<Widget> useSpacing () {\n\t\t\tuseSpacing = true;\n\t\t\treturn this;\n\t\t}\n\n\t\t/** Widget will expand on X axis. */\n\t\tpublic CellWidgetBuilder<Widget> expandX () {\n\t\t\texpandX = true;\n\t\t\treturn this;\n\t\t}\n\n\t\t/** Widget will expand on Y axis. */\n\t\tpublic CellWidgetBuilder<Widget> expandY () {\n\t\t\texpandY = true;\n\t\t\treturn this;\n\t\t}\n\n\t\t/** Widget will fill X axis. Often used with expansion or fixed width setting. */\n\t\tpublic CellWidgetBuilder<Widget> fillX () {\n\t\t\tfillX = true;\n\t\t\treturn this;\n\t\t}\n\n\t\t/** Widget will fill Y axis. Often used with expansion or fixed width setting. */\n\t\tpublic CellWidgetBuilder<Widget> fillY () {\n\t\t\tfillY = true;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * @param alignment will be used to align the widget in the cell area it has. May need expansion to\n\t\t * take any effect.\n\t\t */\n\t\tpublic CellWidgetBuilder<Widget> align (final Alignment alignment) {\n\t\t\tthis.alignment = alignment;\n\t\t\treturn this;\n\t\t}\n\n\t\t/** @param width set as min, preffered and max width. Has to be higher than 0 or it will be ignored. */\n\t\tpublic CellWidgetBuilder<Widget> width (final int width) {\n\t\t\tthis.width = width;\n\t\t\treturn this;\n\t\t}\n\n\t\t/** @param height set as min, preffered and max height. Has to be higher than 0 or it will be ignored. */\n\t\tpublic CellWidgetBuilder<Widget> height (final int height) {\n\t\t\tthis.height = height;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * @param minWidth forces the minimum width of the widget. Note that it overrides width() setting for\n\t\t * the min width. Has to be higher than 0 or it will be ignored.\n\t\t */\n\t\tpublic CellWidgetBuilder<Widget> minWidth (final int minWidth) {\n\t\t\tthis.minWidth = minWidth;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * @param minHeight forces the minimum height of the widget. Note that it overrides height() setting\n\t\t * for the min height. Has to be higher than 0 or it will be ignored.\n\t\t */\n\t\tpublic CellWidgetBuilder<Widget> minHeight (final int minHeight) {\n\t\t\tthis.minHeight = minHeight;\n\t\t\treturn this;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/building/utilities/Nullables.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.building.utilities;\n\n/**\n * Provides static utilities for nullable objects to avoid NullPointerExceptions. Java 6 compatible, although\n * some methods might be quite useful for lambdas.\n * @author MJ\n */\npublic class Nullables {\n\tprivate Nullables () {\n\t}\n\n\t/** A simple null-check. */\n\tpublic static boolean isNull (final Object nullable) {\n\t\treturn nullable == null;\n\t}\n\n\t/** A simple not-null-check. */\n\tpublic static boolean isNotNull (final Object nullable) {\n\t\treturn nullable != null;\n\t}\n\n\t/**\n\t * @param nullable probable null.\n\t * @param alternative will be return if nullable is null.\n\t */\n\tpublic static <Type> Type getOrElse (final Type nullable, final Type alternative) {\n\t\treturn nullable == null ? alternative : nullable;\n\t}\n\n\t/**\n\t * @param nullable probable null.\n\t * @param command will be executed only if nullable object exists.\n\t */\n\tpublic static void executeIfNotNull (final Object nullable, final Runnable command) {\n\t\tif (nullable != null) {\n\t\t\tcommand.run();\n\t\t}\n\t}\n\n\t/** @return true if objects are equal (using equals method) or if both are null. */\n\tpublic static boolean areEqual (final Object first, final Object second) {\n\t\treturn first == second || first != null && first.equals(second);\n\t}\n\n\t/**\n\t * @param nullables nullable objects.\n\t * @return true if any of the objects is null.\n\t */\n\tpublic static boolean isAnyNull (final Object... nullables) {\n\t\tfor (final Object object : nullables) {\n\t\t\tif (object == null) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * @param nullables nullable objects.\n\t * @return true if all passed objects are null.\n\t */\n\tpublic static boolean areAllNull (final Object... nullables) {\n\t\tfor (final Object object : nullables) {\n\t\t\tif (object != null) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * @param nullables nullable objects.\n\t * @return true if any of the objects is not null.\n\t */\n\tpublic static boolean isAnyNotNull (final Object... nullables) {\n\t\tfor (final Object object : nullables) {\n\t\t\tif (object != null) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * @param nullables nullable objects.\n\t * @return true if all passed objects are not null.\n\t */\n\tpublic static boolean areAllNotNull (final Object... nullables) {\n\t\tfor (final Object object : nullables) {\n\t\t\tif (object == null) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/building/utilities/Padding.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.building.utilities;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Cell;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\n\n/**\n * A simple helper class that holds informations about padding on each side of an object. Static methods can\n * be used to quickly set padding or spacing of a cell or a table using this class' object.\n * <p>\n * When padding is set for a table, its cells will be separated from its borders by the given value. When\n * padding is set for a window, additionally to the table's padding effect, top padding will be a draggable\n * area, allowing to move the window.\n * <p>\n * When padding is set for a cell, it will be separated from other cells and table's border by the given\n * value. When spacing is set for a cell, it will be separated by at least as many pixels from other cells as\n * specified. If spacing or padding with the same values is used on every cell in a table, padding will\n * provide twice as big distances between cells, since spacings can overlap.\n * @author MJ\n */\npublic class Padding {\n\t/** Common padding sizes. */\n\tpublic static final Padding PAD_0 = of(0f), PAD_2 = of(2f), PAD_4 = of(4f), PAD_8 = of(8f);\n\n\tprivate final float top, left, bottom, right;\n\n\t/** @param padding will be set as padding for all directions. */\n\tpublic Padding (final float padding) {\n\t\tthis(padding, padding, padding, padding);\n\t}\n\n\t/**\n\t * @param horizontal will be set as left and right padding.\n\t * @param vertical will be set as top and bottom padding.\n\t */\n\tpublic Padding (final float horizontal, final float vertical) {\n\t\tthis(vertical, horizontal, vertical, horizontal);\n\t}\n\n\t/**\n\t * @param top top padding value.\n\t * @param left left padding value.\n\t * @param bottom bottom padding value.\n\t * @param right right padding value.\n\t */\n\tpublic Padding (final float top, final float left, final float bottom, final float right) {\n\t\tthis.top = top;\n\t\tthis.left = left;\n\t\tthis.bottom = bottom;\n\t\tthis.right = right;\n\t}\n\n\t/** @param padding will be set as padding for all directions. */\n\tpublic static Padding of (final float padding) {\n\t\treturn new Padding(padding, padding, padding, padding);\n\t}\n\n\t/**\n\t * @param horizontal will be set as left and right padding.\n\t * @param vertical will be set as top and bottom padding.\n\t */\n\tpublic static Padding of (final float horizontal, final float vertical) {\n\t\treturn new Padding(vertical, horizontal, vertical, horizontal);\n\t}\n\n\t/**\n\t * @param top top padding value.\n\t * @param left left padding value.\n\t * @param bottom bottom padding value.\n\t * @param right right padding value.\n\t */\n\tpublic static Padding of (final float top, final float left, final float bottom, final float right) {\n\t\treturn new Padding(top, left, bottom, right);\n\t}\n\n\t/** @return top padding value. */\n\tpublic float getTop () {\n\t\treturn top;\n\t}\n\n\t/** @return left padding value. */\n\tpublic float getLeft () {\n\t\treturn left;\n\t}\n\n\t/** @return bottom padding value. */\n\tpublic float getBottom () {\n\t\treturn bottom;\n\t}\n\n\t/** @return right padding value. */\n\tpublic float getRight () {\n\t\treturn right;\n\t}\n\n\t/**\n\t * @param padding will be added to the given padding.\n\t * @return new Padding object with summed pad values.\n\t */\n\tpublic Padding add (final Padding padding) {\n\t\treturn new Padding(top + padding.getTop(), left + padding.getLeft(), bottom + padding.getBottom(),\n\t\t\t\tright + padding.getRight());\n\t}\n\n\t/**\n\t * @param padding will be subtracted from the given padding.\n\t * @return new Padding object with subtracted pad values.\n\t */\n\tpublic Padding subtract (final Padding padding) {\n\t\treturn new Padding(top - padding.getTop(), left - padding.getLeft(), bottom - padding.getBottom(),\n\t\t\t\tright - padding.getRight());\n\t}\n\n\t/** @return new Padding object with reversed pad values. */\n\tpublic Padding reverse () {\n\t\treturn new Padding(-top, -left, -bottom, -right);\n\t}\n\n\t/**\n\t * Allows to set Table's padding with the Padding object, which has be done externally, as it's not part\n\t * of the standard libGDX API.\n\t * @param table will have the padding set according to the this object's data.\n\t * @return the given table for chaining.\n\t */\n\tpublic Table applyPadding (final Table table) {\n\t\ttable.pad(top, left, bottom, right);\n\t\treturn table;\n\t}\n\n\t/**\n\t * Allows to set Cell's padding with the Padding object, which has be done externally, as it's not part of\n\t * the standard libGDX API.\n\t * @param cell will have the padding set according to the this object's data.\n\t * @return the given cell for chaining.\n\t */\n\tpublic Cell<?> applyPadding (final Cell<?> cell) {\n\t\tcell.pad(top, left, bottom, right);\n\t\treturn cell;\n\t}\n\n\t/**\n\t * Allows to set Cell's spacing with the Padding object, which has be done externally, as it's not part of\n\t * the standard libGDX API. Padding holds 4 floats for each direction, so it's compatible with both\n\t * padding and spacing settings without any additional changes.\n\t * @param cell will have the padding set according to the this object's data.\n\t * @return the given cell for chaining.\n\t */\n\tpublic Cell<?> applySpacing (final Cell<?> cell) {\n\t\tcell.space(top, left, bottom, right);\n\t\treturn cell;\n\t}\n\n\t// Padding utilities:\n\n\t/**\n\t * Allows to set Table's padding with the Padding object, which has be done externally, as it's not part\n\t * of the standard libGDX API.\n\t * @param padding contains data of padding sizes.\n\t * @param table will have the padding set according to the given data.\n\t * @return the given table for chaining.\n\t */\n\tpublic static Table setPadding (final Padding padding, final Table table) {\n\t\ttable.pad(padding.getTop(), padding.getLeft(), padding.getBottom(), padding.getRight());\n\t\treturn table;\n\t}\n\n\t/**\n\t * Allows to set Cell's padding with the Padding object, which has be done externally, as it's not part of\n\t * the standard libGDX API.\n\t * @param padding contains data of padding sizes.\n\t * @param cell will have the padding set according to the given data.\n\t * @return the given cell for chaining.\n\t */\n\tpublic static Cell<?> setPadding (final Padding padding, final Cell<?> cell) {\n\t\treturn cell.pad(padding.getTop(), padding.getLeft(), padding.getBottom(), padding.getRight());\n\t}\n\n\t/**\n\t * Allows to set Cell's spacing with the Padding object, which has be done externally, as it's not part of\n\t * the standard libGDX API. Padding holds 4 floats for each direction, so it's compatible with both\n\t * padding and spacing settings without any additional changes.\n\t * @param spacing contains data of spacing sizes.\n\t * @param cell will have the padding set according to the given data.\n\t * @return the given cell for chaining.\n\t */\n\tpublic static Cell<?> setSpacing (final Padding spacing, final Cell<?> cell) {\n\t\treturn cell.space(spacing.getTop(), spacing.getLeft(), spacing.getBottom(), spacing.getRight());\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/building/utilities/layouts/ActorLayout.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.building.utilities.layouts;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.kotcrab.vis.ui.building.utilities.CellWidget;\n\n/**\n * An interface that allows to convert multiple widgets into one, providing utilities for complex tables\n * building. For sample implementations, see TableLayout class.\n * @author MJ\n */\npublic interface ActorLayout {\n\t/** @return passed actors merged into one widget. */\n\tpublic Actor convertToActor (Actor... widgets);\n\n\t/** @return passed wrapped actors merged into one widget. */\n\tpublic Actor convertToActor (CellWidget<?>... widgets);\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/building/utilities/layouts/GridTableLayout.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.building.utilities.layouts;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.kotcrab.vis.ui.building.GridTableBuilder;\nimport com.kotcrab.vis.ui.building.utilities.CellWidget;\n\n/**\n * Additional TableLayout with customizable variables. Converts passed widgets into a table using\n * GridTableBuilder.\n * @author MJ\n */\npublic class GridTableLayout implements ActorLayout {\n\tprivate final int rowSize;\n\n\tpublic GridTableLayout (final int rowSize) {\n\t\tthis.rowSize = rowSize;\n\t}\n\n\t/**\n\t * Default factory method.\n\t * @return new GridTableLayout, building grid with the passed row size.\n\t */\n\tpublic static GridTableLayout withRowSize (final int rowSize) {\n\t\treturn new GridTableLayout(rowSize);\n\t}\n\n\t@Override\n\tpublic Actor convertToActor (final Actor... widgets) {\n\t\treturn convertToActor(CellWidget.wrap(widgets));\n\t}\n\n\t@Override\n\tpublic Actor convertToActor (final CellWidget<?>... widgets) {\n\t\treturn TableLayout.convertToTable(new GridTableBuilder(rowSize), widgets);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/building/utilities/layouts/TableLayout.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.building.utilities.layouts;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.kotcrab.vis.ui.building.OneColumnTableBuilder;\nimport com.kotcrab.vis.ui.building.OneRowTableBuilder;\nimport com.kotcrab.vis.ui.building.TableBuilder;\nimport com.kotcrab.vis.ui.building.utilities.CellWidget;\n\n/**\n * Default ActorLayout implementations, using table builders that don't require row() calls to convert\n * multiple actors into one cell.\n * <p>\n * Beside VERTICAL and HORIZONTAL, there's also grid layout available. Since it's customizable, an instance of\n * grid table layout must be manually initiated using grid() method.\n * @author MJ\n */\npublic enum TableLayout implements ActorLayout {\n\t/** Converts passed widgets into a single column. */\n\tVERTICAL {\n\t\t@Override\n\t\tpublic Actor convertToActor (final CellWidget<?>... widgets) {\n\t\t\treturn convertToTable(new OneColumnTableBuilder(), widgets);\n\t\t}\n\t},\n\t/** Converts passed widgets into a single row. */\n\tHORIZONTAL {\n\t\t@Override\n\t\tpublic Actor convertToActor (final CellWidget<?>... widgets) {\n\t\t\treturn convertToTable(new OneRowTableBuilder(), widgets);\n\t\t}\n\t};\n\n\t@Override\n\tpublic Actor convertToActor (final Actor... widgets) {\n\t\treturn convertToActor(CellWidget.wrap(widgets));\n\t}\n\n\t/**\n\t * Utility method. Appends all widgets into the passed builder and creates a table with no additional\n\t * settings.\n\t */\n\tpublic static Actor convertToTable (final TableBuilder usingBuilder, final CellWidget<?>... widgets) {\n\t\tfor (final CellWidget<?> widget : widgets) {\n\t\t\tusingBuilder.append(widget);\n\t\t}\n\t\treturn usingBuilder.build();\n\t}\n\n\t/** @return a new instance of GridTableLayout that creates tables as grids with the specified row size. */\n\tpublic static GridTableLayout grid (final int rowSize) {\n\t\treturn GridTableLayout.withRowSize(rowSize);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/i18n/BundleText.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.i18n;\n\n/**\n * A simple interface for one text line of the bundle file.\n * @author MJ\n */\npublic interface BundleText {\n\n\t/** @return name of the bundle text in the bundle file. */\n\tString getName ();\n\n\t/** @return text's unformatted message as it appears in the bundle. */\n\tString get ();\n\n\t/** @return text's formatted message without any arguments. */\n\tString format ();\n\n\t/** @return text's formatted message with the passes arguments filling bundle placeholders. */\n\tString format (Object... arguments);\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/layout/DragPane.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.layout;\n\nimport com.badlogic.gdx.math.Vector2;\nimport com.badlogic.gdx.scenes.scene2d.*;\nimport com.badlogic.gdx.scenes.scene2d.ui.Container;\nimport com.badlogic.gdx.scenes.scene2d.ui.HorizontalGroup;\nimport com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;\nimport com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;\nimport com.badlogic.gdx.utils.Array;\nimport com.badlogic.gdx.utils.SnapshotArray;\nimport com.kotcrab.vis.ui.widget.Draggable;\nimport com.kotcrab.vis.ui.widget.Draggable.DragListener;\n\n/**\n * Stores actors in an internally managed {@link WidgetGroup}. Allows actors with specialized {@link Draggable} listener attached\n * to be dropped and added into its group's content.\n * <p>\n * Note that unless {@link Draggable} with appropriate listener (preferably {@link DefaultDragListener}) is attached to dragged\n * actors, this widget will act like a regular group with no extra functionalities. It's usually a good idea to use\n * {@link #setDraggable(Draggable)} method, as it will attach the listener to all its children, making them all draggable. If you\n * want to filter widgets accepted by this pane, use {@link #setListener(DragPaneListener)} method.\n * @author MJ\n * @see #setDraggable(Draggable)\n * @see #setListener(DragPaneListener)\n * @since 0.9.3\n */\npublic class DragPane extends Container<WidgetGroup> {\n\tprivate Draggable draggable;\n\tprivate DragPaneListener listener;\n\n\t/** Creates a new horizontal drag pane. */\n\tpublic DragPane () {\n\t\tthis(false);\n\t}\n\n\t/** @param vertical if true, actors will be stored vertically, if false - horizontally. */\n\tpublic DragPane (final boolean vertical) {\n\t\tthis(vertical ? new VerticalGroup() : new HorizontalGroup());\n\t}\n\n\t/**\n\t * @param group must append its actors through standard {@link WidgetGroup#addActor(Actor)} method. Must support\n\t * {@link WidgetGroup#addActorAfter(Actor, Actor)} and {@link WidgetGroup#addActorBefore(Actor, Actor)} methods. Note\n\t * that {@link com.badlogic.gdx.scenes.scene2d.ui.Table} does not meet these requirements.\n\t * @see VerticalGroup\n\t * @see HorizontalGroup\n\t * @see GridGroup\n\t */\n\tpublic DragPane (final WidgetGroup group) {\n\t\tif (group == null) {\n\t\t\tthrow new IllegalArgumentException(\"Group cannot be null.\");\n\t\t}\n\t\tsuper.setActor(group);\n\t\tsetTouchable(Touchable.enabled);\n\t}\n\n\t/**\n\t * @return true if children are displayed vertically in a {@link VerticalGroup}.\n\t * @see #getVerticalGroup()\n\t */\n\tpublic boolean isVertical () {\n\t\treturn getActor() instanceof VerticalGroup;\n\t}\n\n\t/**\n\t * @return true if children are displayed horizontally in a {@link HorizontalGroup}.\n\t * @see #getHorizontalGroup()\n\t */\n\tpublic boolean isHorizontal () {\n\t\treturn getActor() instanceof HorizontalGroup;\n\t}\n\n\t/**\n\t * @return true if children are displayed as a grid in a {@link GridGroup}.\n\t * @see #getGridGroup()\n\t */\n\tpublic boolean isGrid () {\n\t\treturn getActor() instanceof GridGroup;\n\t}\n\n\t/**\n\t * @return true if children are displayed with a {@link VerticalFlowGroup}.\n\t * @see #getVerticalFlowGroup()\n\t */\n\tpublic boolean isVerticalFlow () {\n\t\treturn getActor() instanceof VerticalFlowGroup;\n\t}\n\n\t/**\n\t * @return true if children are displayed with a {@link HorizontalFlowGroup}.\n\t * @see #getHorizontalFlowGroup()\n\t */\n\tpublic boolean isHorizontalFlow () {\n\t\treturn getActor() instanceof HorizontalFlowGroup;\n\t}\n\n\t/**\n\t * @return true if children are displayed with a {@link FloatingGroup}.\n\t * @see #getFloatingGroup()\n\t */\n\tpublic boolean isFloating () {\n\t\treturn getActor() instanceof FloatingGroup;\n\t}\n\n\t@Override\n\tpublic SnapshotArray<Actor> getChildren () {\n\t\treturn getActor().getChildren();\n\t}\n\n\t/** @return internally managed group of actors. */\n\tpublic WidgetGroup getGroup () {\n\t\treturn getActor();\n\t}\n\n\t/** @param group will replace the internally managed group. All current children will be moved to this group. */\n\tpublic void setGroup (final WidgetGroup group) {\n\t\tsetActor(group);\n\t}\n\n\t/** @param group will replace the internally managed group. All current children will be moved to this group. */\n\t@Override\n\tpublic void setActor (final WidgetGroup group) {\n\t\tif (group == null) {\n\t\t\tthrow new IllegalArgumentException(\"Group cannot be null.\");\n\t\t}\n\t\tfinal Group previousGroup = getActor();\n\t\tsuper.setActor(group);\n\t\tattachListener(); // Attaches draggable to all previous group children.\n\t\tfor (final Actor child : previousGroup.getChildren()) {\n\t\t\tgroup.addActor(child); // No need to attach draggable, child was already in pane.\n\t\t}\n\t}\n\n\t/**\n\t * @return internally managed group of actors.\n\t * @throws ClassCastException if drag pane is not horizontal.\n\t * @see #isHorizontal()\n\t */\n\tpublic HorizontalGroup getHorizontalGroup () {\n\t\treturn (HorizontalGroup) getActor();\n\t}\n\n\t/**\n\t * @return internally managed group of actors.\n\t * @throws ClassCastException if drag pane is not vertical.\n\t * @see #isVertical()\n\t */\n\tpublic VerticalGroup getVerticalGroup () {\n\t\treturn (VerticalGroup) getActor();\n\t}\n\n\t/**\n\t * @return internally managed group of actors.\n\t * @throws ClassCastException if drag pane is not a grid.\n\t * @see #isGrid()\n\t */\n\tpublic GridGroup getGridGroup () {\n\t\treturn (GridGroup) getActor();\n\t}\n\n\t/**\n\t * @return internally managed group of actors.\n\t * @throws ClassCastException if drag pane is not horizontal flow.\n\t * @see #isHorizontalFlow()\n\t */\n\tpublic HorizontalFlowGroup getHorizontalFlowGroup () {\n\t\treturn (HorizontalFlowGroup) getActor();\n\t}\n\n\t/**\n\t * @return internally managed group of actors.\n\t * @throws ClassCastException if drag pane is not vertical flow.\n\t * @see #isVerticalFlow()\n\t */\n\tpublic VerticalFlowGroup getVerticalFlowGroup () {\n\t\treturn (VerticalFlowGroup) getActor();\n\t}\n\n\t/**\n\t * @return internally managed group of actors.\n\t * @throws ClassCastException if drag pane is not floating.\n\t * @see #isFloating()\n\t */\n\tpublic FloatingGroup getFloatingGroup () {\n\t\treturn (FloatingGroup) getActor();\n\t}\n\n\t/** @return dragging listener automatically added to all panes' children. */\n\tpublic Draggable getDraggable () {\n\t\treturn draggable;\n\t}\n\n\t/** @param draggable will be automatically added to all children. */\n\tpublic void setDraggable (final Draggable draggable) {\n\t\tremoveListener();\n\t\tthis.draggable = draggable;\n\t\tattachListener();\n\t}\n\n\t@Override\n\tpublic void setBounds (final float x, final float y, final float width, final float height) {\n\t\tsuper.setBounds(x, y, width, height);\n\t\tgetActor().setWidth(width);\n\t\tgetActor().setHeight(height);\n\t\t// Child position omitted on purpose.\n\t}\n\n\t@Override\n\tpublic void setWidth (final float width) {\n\t\tsuper.setWidth(width);\n\t\tgetActor().setWidth(width);\n\t}\n\n\t@Override\n\tpublic void setHeight (final float height) {\n\t\tsuper.setHeight(height);\n\t\tgetActor().setHeight(height);\n\t}\n\n\tprivate void removeListener () {\n\t\tif (draggable == null) {\n\t\t\treturn;\n\t\t}\n\t\tfor (final Actor actor : getChildren()) {\n\t\t\tactor.removeListener(draggable);\n\t\t}\n\t}\n\n\tprivate void attachListener () {\n\t\tif (draggable == null) {\n\t\t\treturn;\n\t\t}\n\t\tfor (final Actor actor : getChildren()) {\n\t\t\tdraggable.attachTo(actor);\n\t\t}\n\t}\n\n\t/**\n\t * @param actor might be in the drag pane.\n\t * @return true if actor is added to the pane's internal group.\n\t */\n\tpublic boolean contains (final Actor actor) {\n\t\treturn actor.getParent() == getActor();\n\t}\n\n\t/**\n\t * Removes an actor from this group. If the actor will not be used again and has actions, they should be\n\t * {@link Actor#clearActions() cleared} so the actions will be returned to their\n\t * {@link Action#setPool(com.badlogic.gdx.utils.Pool) pool}, if any. This is not done automatically.\n\t * <p>\n\t * Note that the direct parent of {@link DragPane}'s children is the internal pane's group accessible through\n\t * {@link #getGroup()} - and since this removal method is overridden and extended, pane's children should be deleted with\n\t * {@code dragPane.removeActor(child)} rather than {@link Actor#remove()} method.\n\t * @param actor will be removed, if present in the internal {@link WidgetGroup}.\n\t * @return true if the actor was removed from this group.\n\t */\n\t@Override\n\tpublic boolean removeActor (final Actor actor) {\n\t\treturn removeActor(actor, true);\n\t}\n\n\t/**\n\t * Removes an actor from this group. If the actor will not be used again and has actions, they should be\n\t * {@link Actor#clearActions() cleared} so the actions will be returned to their\n\t * {@link Action#setPool(com.badlogic.gdx.utils.Pool) pool}, if any. This is not done automatically.\n\t * <p>\n\t * Note that the direct parent of {@link DragPane}'s children is the internal pane's group accessible through\n\t * {@link #getGroup()} - and since this removal method is overridden and extended, pane's children should be deleted with\n\t * {@code dragPane.removeActor(child, true)} rather than {@link Actor#remove()} method.\n\t * @param unfocus if true, {@link Stage#unfocus(Actor)} is called.\n\t * @param actor will be removed, if present in the internal {@link WidgetGroup}.\n\t * @return true if the actor was removed from this group.\n\t */\n\t@Override\n\tpublic boolean removeActor (final Actor actor, final boolean unfocus) {\n\t\tif (getActor().getChildren().contains(actor, true)) {\n\t\t\t// Stage input focus causes problems, as touchUp is called in Draggable. Reproducing input unfocus after stage removed.\n\t\t\tStage stage = actor.getStage();\n\t\t\tgetActor().removeActor(actor, false); // Stage is cleared.\n\t\t\tif (unfocus && stage != null) {\n\t\t\t\tstage.unfocus(actor);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void clear () {\n\t\tgetActor().clear();\n\t}\n\n\t@Override\n\tpublic void addActor (final Actor actor) {\n\t\tgetActor().addActor(actor);\n\t\tdoOnAdd(actor);\n\t}\n\n\t@Override\n\tpublic void addActorAfter (final Actor actorAfter, final Actor actor) {\n\t\tgetActor().addActorAfter(actorAfter, actor);\n\t\tdoOnAdd(actor);\n\t}\n\n\t@Override\n\tpublic void addActorAt (final int index, final Actor actor) {\n\t\tgetActor().addActorAt(index, actor);\n\t\tdoOnAdd(actor);\n\t}\n\n\t@Override\n\tpublic void addActorBefore (final Actor actorBefore, final Actor actor) {\n\t\tgetActor().addActorBefore(actorBefore, actor);\n\t\tdoOnAdd(actor);\n\t}\n\n\t/** @param actor was just added to the group. */\n\tprotected void doOnAdd (final Actor actor) {\n\t\tif (draggable != null) {\n\t\t\tdraggable.attachTo(actor);\n\t\t}\n\t}\n\n\t@Override\n\tpublic <T extends Actor> T findActor (final String name) {\n\t\treturn getActor().findActor(name);\n\t}\n\n\t@Override\n\tpublic void invalidate () {\n\t\tsuper.invalidate();\n\t\tgetActor().invalidate();\n\t}\n\n\t@Override\n\tpublic void validate () {\n\t\tsuper.validate();\n\t\tgetActor().validate();\n\t}\n\n\t/** @param listener manages children appended to the drag pane. */\n\tpublic void setListener (final DragPaneListener listener) {\n\t\tthis.listener = listener;\n\t}\n\n\t/**\n\t * @param actor is dragged over the pane.\n\t * @return true if actor can be added to the pane.\n\t */\n\tprotected boolean accept (final Actor actor) {\n\t\treturn listener == null || listener.accept(this, actor);\n\t}\n\n\t/**\n\t * Default {@link DragListener} implementation. Implements {@link DragPane} behavior.\n\t * @author MJ\n\t * @since 0.9.3\n\t */\n\tpublic static class DefaultDragListener implements DragListener {\n\t\t/** Contains stage drag end position, which might be changed to local widget coordinates by some methods. */\n\t\tprotected static final Vector2 DRAG_POSITION = new Vector2();\n\t\tprivate Policy policy;\n\n\t\t/** Creates a new drag listener with default policy. */\n\t\tpublic DefaultDragListener () {\n\t\t\tthis(DefaultPolicy.ALLOW_REMOVAL);\n\t\t}\n\n\t\t/**\n\t\t * @param policy determines behavior of dragged actors. Allows to prohibit actors from being added to a {@link DragPane}.\n\t\t * Cannot be null.\n\t\t * @see #setPolicy(Policy)\n\t\t */\n\t\tpublic DefaultDragListener (final Policy policy) {\n\t\t\tsetPolicy(policy);\n\t\t}\n\n\t\t/**\n\t\t * @param policy determines behavior of dragged actors. Allows to prohibit actors from being added to a {@link DragPane}.\n\t\t * Cannot be null.\n\t\t * @see DefaultPolicy\n\t\t */\n\t\tpublic void setPolicy (final Policy policy) {\n\t\t\tif (policy == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"Policy cannot be null.\");\n\t\t\t}\n\t\t\tthis.policy = policy;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean onStart (final Draggable draggable, final Actor actor, final float stageX, final float stageY) {\n\t\t\treturn APPROVE;\n\t\t}\n\n\t\t@Override\n\t\tpublic void onDrag (final Draggable draggable, final Actor actor, final float stageX, final float stageY) {\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean onEnd (final Draggable draggable, final Actor actor, final float stageX, final float stageY) {\n\t\t\tif (actor == null || actor.getStage() == null) {\n\t\t\t\treturn CANCEL;\n\t\t\t}\n\t\t\tfinal Actor overActor = actor.getStage().hit(stageX, stageY, true);\n\t\t\tif (overActor == null || overActor == actor) {\n\t\t\t\treturn CANCEL;\n\t\t\t} else if (overActor.isAscendantOf(actor)) {\n\t\t\t\tfinal DragPane dragPane = getDragPane(actor);\n\t\t\t\tif (dragPane != null && dragPane.isFloating()) {\n\t\t\t\t\tDRAG_POSITION.set(stageX, stageY);\n\t\t\t\t\treturn addToFloatingGroup(draggable, actor, dragPane);\n\t\t\t\t}\n\t\t\t\treturn CANCEL;\n\t\t\t}\n\t\t\tDRAG_POSITION.set(stageX, stageY);\n\t\t\tif (overActor instanceof DragPane) {\n\t\t\t\treturn addDirectlyToPane(draggable, actor, (DragPane) overActor);\n\t\t\t}\n\t\t\tfinal DragPane dragPane = getDragPane(overActor);\n\t\t\tif (accept(actor, dragPane)) {\n\t\t\t\treturn addActor(draggable, actor, overActor, dragPane);\n\t\t\t}\n\t\t\treturn CANCEL;\n\t\t}\n\n\t\t/**\n\t\t * @param draggable is attached to the actor.\n\t\t * @param actor dragged actor.\n\t\t * @param dragPane is directly under the dragged actor. If accepts the actor, it should be added to its content.\n\t\t * @return true if actor was accepted.\n\t\t */\n\t\tprotected boolean addDirectlyToPane (final Draggable draggable, final Actor actor, final DragPane dragPane) {\n\t\t\tif (accept(actor, dragPane)) {\n\t\t\t\tif (dragPane.isFloating()) {\n\t\t\t\t\treturn addToFloatingGroup(draggable, actor, dragPane);\n\t\t\t\t}\n\t\t\t\t// Dragged directly to a pane. Assuming no padding, adding last:\n\t\t\t\tdragPane.addActor(actor);\n\t\t\t\treturn APPROVE;\n\t\t\t}\n\t\t\treturn CANCEL;\n\t\t}\n\n\t\t/**\n\t\t * @param actor has just been dragged.\n\t\t * @param dragPane is under the dragged actor (if exists). Can be null.\n\t\t * @return true if the actor can be added to the dragPane.\n\t\t */\n\t\tprotected boolean accept (final Actor actor, final DragPane dragPane) {\n\t\t\treturn dragPane != null && dragPane.accept(actor) && policy.accept(dragPane, actor);\n\t\t}\n\n\t\t/**\n\t\t * @param draggable is attached to the actor.\n\t\t * @param actor is being dragged.\n\t\t * @param overActor is directly under the dragged actor.\n\t\t * @param dragPane contains the actor under dragged widget.\n\t\t * @return true if actor is accepted and added to the group.\n\t\t */\n\t\tprotected boolean addActor (final Draggable draggable, final Actor actor, final Actor overActor, final DragPane dragPane) {\n\t\t\tfinal Actor directPaneChild = getActorInDragPane(overActor, dragPane);\n\t\t\tdirectPaneChild.stageToLocalCoordinates(DRAG_POSITION);\n\t\t\tif (dragPane.isVertical() || dragPane.isVerticalFlow()) {\n\t\t\t\treturn addToVerticalGroup(actor, dragPane, directPaneChild);\n\t\t\t} else if (dragPane.isHorizontal() || dragPane.isHorizontalFlow()) {\n\t\t\t\treturn addToHorizontalGroup(actor, dragPane, directPaneChild);\n\t\t\t} else if (dragPane.isFloating()) {\n\t\t\t\treturn addToFloatingGroup(draggable, actor, dragPane);\n\t\t\t} // This is the default behavior for grid and unknown groups:\n\t\t\treturn addToOtherGroup(actor, dragPane, directPaneChild);\n\t\t}\n\n\t\t/**\n\t\t * @param actor is being dragged.\n\t\t * @param dragPane is under the actor. Stores a {@link HorizontalGroup}.\n\t\t * @param directPaneChild actor under the cursor.\n\t\t * @return true if actor was accepted by the group.\n\t\t */\n\t\tprotected boolean addToHorizontalGroup (final Actor actor, final DragPane dragPane, final Actor directPaneChild) {\n\t\t\tfinal Array<Actor> children = dragPane.getChildren();\n\t\t\tfinal int indexOfDraggedActor = children.indexOf(actor, true);\n\t\t\tactor.remove();\n\t\t\tif (indexOfDraggedActor >= 0) {\n\t\t\t\tfinal int indexOfDirectChild = children.indexOf(directPaneChild, true);\n\t\t\t\tif (indexOfDirectChild > indexOfDraggedActor) {\n\t\t\t\t\tdragPane.addActorAfter(directPaneChild, actor);\n\t\t\t\t} else {\n\t\t\t\t\tdragPane.addActorBefore(directPaneChild, actor);\n\t\t\t\t}\n\t\t\t} else if (DRAG_POSITION.x > directPaneChild.getWidth() / 2f) {\n\t\t\t\tdragPane.addActorAfter(directPaneChild, actor);\n\t\t\t} else {\n\t\t\t\tdragPane.addActorBefore(directPaneChild, actor);\n\t\t\t}\n\t\t\treturn APPROVE;\n\t\t}\n\n\t\t/**\n\t\t * @param actor is being dragged.\n\t\t * @param dragPane is under the actor. Stores a {@link VerticalGroup}.\n\t\t * @param directPaneChild actor under the cursor.\n\t\t * @return true if actor was accepted by the group.\n\t\t */\n\t\tprotected boolean addToVerticalGroup (final Actor actor, final DragPane dragPane, final Actor directPaneChild) {\n\t\t\tfinal Array<Actor> children = dragPane.getChildren();\n\t\t\tfinal int indexOfDraggedActor = children.indexOf(actor, true);\n\t\t\tactor.remove();\n\t\t\tif (indexOfDraggedActor >= 0) {\n\t\t\t\tfinal int indexOfDirectChild = children.indexOf(directPaneChild, true);\n\t\t\t\tif (indexOfDirectChild > indexOfDraggedActor) {\n\t\t\t\t\tdragPane.addActorAfter(directPaneChild, actor);\n\t\t\t\t} else {\n\t\t\t\t\tdragPane.addActorBefore(directPaneChild, actor);\n\t\t\t\t}\n\t\t\t} else if (DRAG_POSITION.y < directPaneChild.getHeight() / 2f) { // Y inverted.\n\t\t\t\tdragPane.addActorAfter(directPaneChild, actor);\n\t\t\t} else {\n\t\t\t\tdragPane.addActorBefore(directPaneChild, actor);\n\t\t\t}\n\t\t\treturn APPROVE;\n\t\t}\n\n\t\t/**\n\t\t * @param draggable attached to dragged actor.\n\t\t * @param actor is being dragged.\n\t\t * @param dragPane is under the actor. Stores a {@link FloatingGroup}.\n\t\t * @return true if actor was accepted by the group.\n\t\t */\n\t\tprotected boolean addToFloatingGroup (final Draggable draggable, final Actor actor, final DragPane dragPane) {\n\t\t\tfinal FloatingGroup group = dragPane.getFloatingGroup();\n\t\t\tdragPane.stageToLocalCoordinates(DRAG_POSITION);\n\t\t\tfloat x = DRAG_POSITION.x + draggable.getOffsetX();\n\t\t\tif (x < 0f || x + actor.getWidth() > dragPane.getWidth()) {\n\t\t\t\t// Normalizing value if set to keep within parent's bounds:\n\t\t\t\tif (draggable.isKeptWithinParent()) {\n\t\t\t\t\tx = x < 0f ? 0f : dragPane.getWidth() - actor.getWidth() - 1f;\n\t\t\t\t} else {\n\t\t\t\t\treturn CANCEL;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfloat y = DRAG_POSITION.y + draggable.getOffsetY();\n\t\t\tif (y < 0f || y + actor.getHeight() > dragPane.getHeight()) {\n\t\t\t\tif (draggable.isKeptWithinParent()) {\n\t\t\t\t\ty = y < 0f ? 0f : dragPane.getHeight() - actor.getHeight() - 1f;\n\t\t\t\t} else {\n\t\t\t\t\treturn CANCEL;\n\t\t\t\t}\n\t\t\t}\n\t\t\tactor.remove();\n\t\t\tactor.setPosition(x, y);\n\t\t\tgroup.addActor(actor);\n\t\t\treturn APPROVE;\n\t\t}\n\n\t\t/**\n\t\t * @param actor is being dragged.\n\t\t * @param dragPane is under the actor. Stores a {@link GridGroup} or unknown group.\n\t\t * @param directPaneChild actor under the cursor.\n\t\t * @return true if actor was accepted by the group.\n\t\t */\n\t\tprotected boolean addToOtherGroup (final Actor actor, final DragPane dragPane, final Actor directPaneChild) {\n\t\t\tfinal Array<Actor> children = dragPane.getChildren();\n\t\t\tfinal int indexOfDirectChild = children.indexOf(directPaneChild, true);\n\t\t\tfinal int indexOfDraggedActor = children.indexOf(actor, true);\n\t\t\tactor.remove();\n\t\t\tif (indexOfDraggedActor >= 0) { // Dragging own actor.\n\t\t\t\tif (indexOfDraggedActor > indexOfDirectChild) { // Dropped after current position.\n\t\t\t\t\tdragPane.addActorBefore(directPaneChild, actor);\n\t\t\t\t} else { // Dropped before current position.\n\t\t\t\t\tdragPane.addActorAfter(directPaneChild, actor);\n\t\t\t\t}\n\t\t\t} else if (indexOfDirectChild == children.size - 1) { // Dragged into last element.\n\t\t\t\tif (DRAG_POSITION.y < directPaneChild.getHeight() / 2f || DRAG_POSITION.x > directPaneChild.getWidth() / 2f) {\n\t\t\t\t\t// Adding last:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// last:\n\t\t\t\t\tdragPane.addActor(actor);\n\t\t\t\t} else {\n\t\t\t\t\tdragPane.addActorBefore(directPaneChild, actor);\n\t\t\t\t}\n\t\t\t} else if (indexOfDirectChild == 0) { // Dragged into first element.\n\t\t\t\tif (DRAG_POSITION.y < directPaneChild.getHeight() / 2f || DRAG_POSITION.x > directPaneChild.getWidth() / 2f) {\n\t\t\t\t\tdragPane.addActorAfter(directPaneChild, actor);\n\t\t\t\t} else { // Adding first:\n\t\t\t\t\tdragPane.addActorBefore(directPaneChild, actor);\n\t\t\t\t}\n\t\t\t} else { // Replacing hovered actor:\n\t\t\t\tdragPane.addActorBefore(directPaneChild, actor);\n\t\t\t}\n\t\t\treturn APPROVE;\n\t\t}\n\n\t\t/**\n\t\t * @param actor if in the drag pane, but does not have to be added directly.\n\t\t * @param dragPane contains the actor.\n\t\t * @return passed actor or the parent of the actor added directly to the pane.\n\t\t */\n\t\tprotected Actor getActorInDragPane (Actor actor, final DragPane dragPane) {\n\t\t\twhile (actor != dragPane && actor != null) {\n\t\t\t\tif (dragPane.contains(actor)) {\n\t\t\t\t\treturn actor;\n\t\t\t\t} // Actor might not be added directly to the drag pane. Trying out the parent:\n\t\t\t\tactor = actor.getParent();\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\t/**\n\t\t * @param fromActor might be in a drag pane.\n\t\t * @return drag pane parent or null.\n\t\t */\n\t\tprotected DragPane getDragPane (Actor fromActor) {\n\t\t\twhile (fromActor != null) {\n\t\t\t\tif (fromActor instanceof DragPane) {\n\t\t\t\t\treturn (DragPane) fromActor;\n\t\t\t\t}\n\t\t\t\tfromActor = fromActor.getParent();\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\t/**\n\t\t * Determines behavior of {@link DefaultDragListener}.\n\t\t * @author MJ\n\t\t * @since 0.9.3\n\t\t */\n\t\tpublic static interface Policy {\n\t\t\t/**\n\t\t\t * @param dragPane is under the actor.\n\t\t\t * @param actor was dragged into the drag pane.\n\t\t\t * @return true if the actor can be added to the {@link DragPane}\n\t\t\t */\n\t\t\tboolean accept (DragPane dragPane, Actor actor);\n\t\t}\n\n\t\t/**\n\t\t * Contains basic {@link DefaultDragListener} behaviors, allowing to modify the listener without extending it.\n\t\t * @author MJ\n\t\t * @since 0.9.3\n\t\t */\n\t\tpublic static enum DefaultPolicy implements Policy {\n\t\t\t/** Allows children to be moved to different {@link DragPane}s. */\n\t\t\tALLOW_REMOVAL {\n\t\t\t\t@Override\n\t\t\t\tpublic boolean accept (final DragPane dragPane, final Actor actor) {\n\t\t\t\t\treturn APPROVE;\n\t\t\t\t}\n\t\t\t},\n\t\t\t/** Prohibits from removing children from the {@link DragPane}, allowing them only to be moved within their own group. */\n\t\t\tKEEP_CHILDREN {\n\t\t\t\t@Override\n\t\t\t\tpublic boolean accept (final DragPane dragPane, final Actor actor) {\n\t\t\t\t\treturn dragPane.contains(actor); // dragPane must be the direct parent of actor.\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Allows to select children added to the group.\n\t * @author MJ\n\t * @since 0.9.3\n\t */\n\tpublic static interface DragPaneListener {\n\t\t/** Return in {@link #accept(DragPane, Actor)} method for code clarity. */\n\t\tboolean ACCEPT = true, REFUSE = false;\n\n\t\t/**\n\t\t * @param dragPane has this listener attached.\n\t\t * @param actor if being dragged over the {@link DragPane}.\n\t\t * @return true if actor can be added to the drag pane. False if it cannot.\n\t\t */\n\t\tboolean accept (DragPane dragPane, Actor actor);\n\n\t\t/**\n\t\t * When actors are dragged into the {@link DragPane}, they are accepted and added into the pane only if their direct parent\n\t\t * is the pane itself.\n\t\t * @author MJ\n\t\t * @since 0.9.3\n\t\t */\n\t\tpublic static class AcceptOwnChildren implements DragPaneListener {\n\t\t\t@Override\n\t\t\tpublic boolean accept (final DragPane dragPane, final Actor actor) {\n\t\t\t\treturn dragPane.contains(actor);\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Limits {@link DragPane} children amount to a certain number. Never rejects own children.\n\t\t * @author MJ\n\t\t * @since 0.9.3\n\t\t */\n\t\tpublic static class LimitChildren implements DragPaneListener {\n\t\t\tprivate final int max;\n\n\t\t\t/**\n\t\t\t * @param max if {@link DragPane}'s children amount equals (or is greater than) this value, other children will not be\n\t\t\t * accepted.\n\t\t\t */\n\t\t\tpublic LimitChildren (final int max) {\n\t\t\t\tthis.max = max;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean accept (final DragPane dragPane, final Actor actor) {\n\t\t\t\treturn dragPane.contains(actor) || dragPane.getChildren().size < max;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/layout/FloatingGroup.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.layout;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;\nimport com.badlogic.gdx.scenes.scene2d.utils.Layout;\nimport com.badlogic.gdx.utils.SnapshotArray;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\n/**\n * Does not arranges actors in specific layout, instead it uses their position and preferred sizes to place them inside\n * group. Does not check position values and allows widgets to be placed outside group. If combined with\n * {@link VisWindow#setKeepWithinParent(boolean)} allows to create windows that can only moved within this group area.\n * @author Kotcrab\n * @since 1.0.2\n */\npublic class FloatingGroup extends WidgetGroup {\n\tprivate boolean useChildrenPreferredSize = false;\n\tprivate float prefWidth = 0f;\n\tprivate float prefHeight = 0f;\n\n\t/**\n\t * Creates floating group without preferred sizes set. Group size should be controlled by parent, note that\n\t * most group relies on correctness of preferred width and height so not all groups can be applied.\n\t * <p>\n\t * This can be useful for adding group to {@link Table}. For example: add(floatingGroup).grow() to fill all available\n\t * space.\n\t */\n\tpublic FloatingGroup () {\n\t\tsetTouchable(Touchable.childrenOnly);\n\t}\n\n\t/**\n\t * Creates floating group with fixed area size.\n\t * @param prefHeight preferred height of group. If set to to lower than 0 then {@link #getHeight()} is used as preferred height.\n\t * @param prefWidth preferred width of group. If set to to lower than 0 then {@link #getWidth()} is used as preferred width.\n\t */\n\tpublic FloatingGroup (float prefWidth, float prefHeight) {\n\t\tsetTouchable(Touchable.childrenOnly);\n\t\tsetPrefWidth(prefWidth);\n\t\tsetPrefHeight(prefHeight);\n\t}\n\n\t@Override\n\tpublic void layout () {\n\t\tif (useChildrenPreferredSize == false) return;\n\t\tSnapshotArray<Actor> children = getChildren();\n\n\t\tfor (int i = 0; i < children.size; i++) {\n\t\t\tActor child = children.get(i);\n\t\t\tfloat width = child.getWidth();\n\t\t\tfloat height = child.getHeight();\n\t\t\tif (child instanceof Layout) {\n\t\t\t\tLayout layout = (Layout) child;\n\t\t\t\twidth = layout.getPrefWidth();\n\t\t\t\theight = layout.getPrefHeight();\n\t\t\t}\n\n\t\t\tchild.setBounds(child.getX(), child.getY(), width, height);\n\t\t}\n\t}\n\n\tpublic boolean isUseChildrenPreferredSize () {\n\t\treturn useChildrenPreferredSize;\n\t}\n\n\t/**\n\t * If true then children preferred size will be used whenever possible when doing group layout. If set to true\n\t * changing widget and height using {@link Actor#getWidth()} and {@link Actor#getHeight()} may not have effect\n\t * for instances of {@link Layout} (depending on implementation). Default is false.\n\t */\n\tpublic void setUseChildrenPreferredSize (boolean useChildrenPreferredSize) {\n\t\tthis.useChildrenPreferredSize = useChildrenPreferredSize;\n\t\tinvalidate();\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\treturn prefWidth < 0f ? getWidth() : prefWidth;\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\treturn prefHeight < 0f ? getHeight() : prefHeight;\n\t}\n\n\tpublic void setPrefWidth (float prefWidth) {\n\t\tthis.prefWidth = prefWidth;\n\t\tinvalidate();\n\t}\n\n\tpublic void setPrefHeight (float prefHeight) {\n\t\tthis.prefHeight = prefHeight;\n\t\tinvalidate();\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/layout/FlowGroup.java",
    "content": "package com.kotcrab.vis.ui.layout;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;\nimport com.badlogic.gdx.scenes.scene2d.utils.Layout;\nimport com.badlogic.gdx.utils.SnapshotArray;\n\n/**\n * Arranges actors to flow in a specified layout direction using up available space and, if sensible, expanding in that direction.\n * <br/>\n * For horizontal layout direction ({@code vertical=false}), attempts to expand to the desired width, creates new rows and expands vertically as necessary.\n * Children automatically overflow to the next row when necessary.\n * <br/>\n * For vertical layout direction ({@code vertical=true}), attempts to expand to the desired height, creates new columns and expands horizontally as necessary.\n * Children automatically overflow to the next column when necessary.\n * <br/>\n * <br/>\n * Can be embedded in a scroll pane. To ensure proper flowing (instead of expanding in the layout direction), scrolling in the layout direction should be disabled, i.e., horizontal layout direction should have scrolling in x direction disabled and vertical layout direction should have scrolling in y direction disabled.\n * <br/>\n * <br/>\n * This is a more versatile implementation of a flow group subsuming\n * {@link com.kotcrab.vis.ui.layout.HorizontalFlowGroup HorizontalFlowGroup} and {@link com.kotcrab.vis.ui.layout.VerticalFlowGroup VerticalFlowGroup}.\n * <br/>\n * <br/>\n * Key differences:\n * <ul>\n *   <li>Can be configured to have a layout direction as either horizontal ({@code vertical=false}) or vertical ({@code vertical=true}).</li>\n *   <li>Layout direction can be changed programmatically during runtime.</li>\n *   <li>If available, uses up all necessary space in the layout direction, i.e., when {@code vertical=false}, attempts to expand horizontally and, when {@code vertical=true}, attempts to expand vertically (instead of using the specified width/height as before).</li>\n *   <li>Adds spacing only between children, but not after the last element.</li>\n *   <li>When even the first child does not fit its row/column, space is no longer placed before it.</li>\n * </ul>\n * @author ccmb2r\n * @since 1.4.7\n */\npublic class FlowGroup extends WidgetGroup {\n\tprivate static final float DEFAULT_SPACING = 0;\n\n\tprivate boolean vertical;\n\tprivate float spacing;\n\n\tprivate boolean sizeInvalid = true;\n\n\tprivate float minWidth;\n\tprivate float minHeight;\n\n\tprivate float layoutedWidth;\n\tprivate float layoutedHeight;\n\n\tprivate float relaxedWidth;\n\tprivate float relaxedHeight;\n\n\tpublic FlowGroup (boolean vertical) {\n\t\tthis(vertical, DEFAULT_SPACING);\n\t}\n\n\tpublic FlowGroup (boolean vertical, float spacing) {\n\t\tthis.vertical = vertical;\n\t\tthis.spacing = spacing;\n\t\tsetTouchable(Touchable.childrenOnly);\n\t}\n\n\tpublic boolean isVertical () {\n\t\treturn vertical;\n\t}\n\n\tpublic void setVertical (boolean vertical) {\n\t\tif (this.vertical == vertical) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.vertical = vertical;\n\t\tinvalidate();\n\t}\n\n\tprotected void computeSize () {\n\t\tif (vertical) {\n\t\t\tcomputeSizeVertical();\n\t\t} else {\n\t\t\tcomputeSizeHorizontal();\n\t\t}\n\t}\n\n\tprotected void computeSizeHorizontal () {\n\t\tfinal float targetWidth = getWidth();\n\n\t\tfloat maxChildWidth = 0;\n\t\tfloat maxChildHeight = 0;\n\n\t\tfloat x = 0;\n\t\tfloat currentRowHeight = 0;\n\t\tfloat totalWidth = 0;\n\t\tfloat totalHeight = 0;\n\n\t\tSnapshotArray<Actor> children = getChildren();\n\t\tboolean wasChildProcessed = false;\n\n\t\tfor (Actor child : children) {\n\t\t\tfloat childWidth;\n\t\t\tfloat childHeight;\n\n\t\t\tif (child instanceof Layout) {\n\t\t\t\tLayout layout = (Layout) child;\n\n\t\t\t\tchildWidth = layout.getPrefWidth();\n\t\t\t\tchildHeight = layout.getPrefHeight();\n\t\t\t} else {\n\t\t\t\tchildWidth = child.getWidth();\n\t\t\t\tchildHeight = child.getHeight();\n\t\t\t}\n\n\t\t\t//See if it fits this row but place at least one child in the first row!\n\t\t\tif (x + childWidth <= targetWidth || !wasChildProcessed) {\n\t\t\t\t//Fits into this row.\n\t\t\t\tcurrentRowHeight = Math.max(childHeight, currentRowHeight);\n\t\t\t} else {\n\t\t\t\t//Start new row.\n\t\t\t\ttotalHeight += currentRowHeight + spacing;\n\t\t\t\tx = 0;\n\t\t\t\tcurrentRowHeight = childHeight;\n\t\t\t}\n\n\t\t\tfloat widthIncrement = childWidth + spacing;\n\n\t\t\tx += widthIncrement;\n\t\t\ttotalWidth += widthIncrement;\n\n\t\t\tmaxChildWidth = Math.max(maxChildWidth, childWidth);\n\t\t\tmaxChildHeight = Math.max(maxChildHeight, childHeight);\n\n\t\t\twasChildProcessed = true;\n\t\t}\n\n\t\t//Handle last column (if at least one column exists).\n\t\tif (wasChildProcessed) {\n\t\t\t//Remove the last spacing that was added excessively.\n\t\t\ttotalWidth -= spacing;\n\t\t}\n\n\t\t//Handle last row (no final spacing).\n\t\ttotalHeight += currentRowHeight;\n\n\t\t//Store results.\n\t\tminWidth = maxChildWidth;\n\t\tminHeight = maxChildHeight;\n\n\t\tlayoutedWidth = targetWidth;\n\t\tlayoutedHeight = totalHeight;\n\n\t\trelaxedWidth = totalWidth;\n\n\t\tsizeInvalid = false;\n\t}\n\n\tprotected void computeSizeVertical () {\n\t\tfinal float targetHeight = getHeight();\n\n\t\tfloat maxChildWidth = 0;\n\t\tfloat maxChildHeight = 0;\n\n\t\tfloat y = targetHeight;\n\t\tfloat currentColumnWidth = 0;\n\t\tfloat totalWidth = 0;\n\t\tfloat totalHeight = 0;\n\n\t\tSnapshotArray<Actor> children = getChildren();\n\t\tboolean wasChildProcessed = false;\n\n\t\tfor (Actor child : children) {\n\t\t\tfloat childWidth;\n\t\t\tfloat childHeight;\n\n\t\t\tif (child instanceof Layout) {\n\t\t\t\tLayout layout = (Layout) child;\n\n\t\t\t\tchildWidth = layout.getPrefWidth();\n\t\t\t\tchildHeight = layout.getPrefHeight();\n\t\t\t} else {\n\t\t\t\tchildWidth = child.getWidth();\n\t\t\t\tchildHeight = child.getHeight();\n\t\t\t}\n\n\t\t\t//See if it fits this column but place at least one child in the first column!\n\t\t\tif (y - childHeight >= 0 || !wasChildProcessed) {\n\t\t\t\t//Fits into this column.\n\t\t\t\tcurrentColumnWidth = Math.max(childWidth, currentColumnWidth);\n\t\t\t} else {\n\t\t\t\t//Start new column.\n\t\t\t\ttotalWidth += currentColumnWidth + spacing;\n\t\t\t\ty = targetHeight;\n\t\t\t\tcurrentColumnWidth = childWidth;\n\t\t\t}\n\n\t\t\tfloat heightIncrement = childHeight + spacing;\n\n\t\t\ty -= heightIncrement;\n\t\t\ttotalHeight += heightIncrement;\n\n\t\t\tmaxChildWidth = Math.max(maxChildWidth, childWidth);\n\t\t\tmaxChildHeight = Math.max(maxChildHeight, childHeight);\n\n\t\t\twasChildProcessed = true;\n\t\t}\n\n\t\t//Handle last row (if at least one row exists).\n\t\tif (wasChildProcessed) {\n\t\t\t//Remove the last spacing that was added excessively.\n\t\t\ttotalHeight -= spacing;\n\t\t}\n\n\t\t//Handle last column (no final spacing).\n\t\ttotalWidth += currentColumnWidth;\n\n\t\t//Store results.\n\t\tminWidth = maxChildWidth;\n\t\tminHeight = maxChildHeight;\n\n\t\tlayoutedWidth = totalWidth;\n\t\tlayoutedHeight = targetHeight;\n\n\t\trelaxedHeight = totalHeight;\n\n\t\tsizeInvalid = false;\n\t}\n\n\t@Override\n\tpublic void layout () {\n\t\tif (vertical) {\n\t\t\tlayoutVertical();\n\t\t} else {\n\t\t\tlayoutHorizontal();\n\t\t}\n\t}\n\n\tprotected void layoutHorizontal () {\n\t\t//NOTE: Should children invalidate/validate as per contract?\n\n\t\tcomputeSizeIfNeeded();\n\n\t\tfinal float targetWidth = getWidth();\n\t\tfinal float targetHeight = getHeight();\n\n\t\tfloat x = 0;\n\t\tfloat y = targetHeight;\n\t\tfloat rowHeight = 0;\n\n\t\tSnapshotArray<Actor> children = getChildren();\n\t\tboolean wasChildProcessed = false;\n\n\t\t//Layout the child; first upside down as total height is, as of yet, unknown\n\t\t//(due to the dynamic width used) and will be determined during this run.\n\t\tfor (Actor child : children) {\n\t\t\tfloat childWidth;\n\t\t\tfloat childHeight;\n\n\t\t\tif (child instanceof Layout) {\n\t\t\t\tLayout layout = (Layout) child;\n\n\t\t\t\tchildWidth = layout.getPrefWidth();\n\t\t\t\tchildHeight = layout.getPrefHeight();\n\n\t\t\t\t//Need to update size.\n\t\t\t\tchild.setSize(childWidth, childHeight);\n\t\t\t} else {\n\t\t\t\tchildWidth = child.getWidth();\n\t\t\t\tchildHeight = child.getHeight();\n\n\t\t\t\t//Child already at size.\n\t\t\t}\n\n\t\t\t//See if it fits this row but place at least one child in the first row!\n\t\t\tif (x + childWidth <= targetWidth || !wasChildProcessed) {\n\t\t\t\t//Fits into this row.\n\t\t\t\trowHeight = Math.max(childHeight, rowHeight);\n\t\t\t} else {\n\t\t\t\t//Start new row.\n\t\t\t\tx = 0;\n\t\t\t\ty -= rowHeight + spacing;\n\t\t\t\trowHeight = childHeight;\n\t\t\t}\n\n\t\t\tchild.setPosition(x, y - childHeight);\n\n\t\t\tx += childWidth + spacing;\n\n\t\t\twasChildProcessed = true;\n\t\t}\n\n\t\t//Did a best effort to fit into the specified size but it still did not work.\n\t\t//Let the ancestors know in hopes that they resize the group.\n\t\tif (getHeight() != layoutedHeight) {\n\t\t\tinvalidateHierarchy();\n\t\t}\n\t}\n\n\tprotected void layoutVertical () {\n\t\t//NOTE: Should children invalidate/validate as per contract?\n\n\t\tcomputeSizeIfNeeded();\n\n\t\tfinal float targetHeight = getHeight();\n\n\t\tfloat x = 0;\n\t\tfloat y = targetHeight;\n\t\tfloat columnWidth = 0;\n\n\t\tSnapshotArray<Actor> children = getChildren();\n\t\tboolean wasChildProcessed = false;\n\n\t\t//Layout the child; first upside down as total height is, as of yet, unknown\n\t\t//(due to the dynamic width used) and will be determined during this run.\n\t\tfor (Actor child : children) {\n\t\t\tfloat childWidth;\n\t\t\tfloat childHeight;\n\n\t\t\tif (child instanceof Layout) {\n\t\t\t\tLayout layout = (Layout) child;\n\n\t\t\t\tchildWidth = layout.getPrefWidth();\n\t\t\t\tchildHeight = layout.getPrefHeight();\n\n\t\t\t\t//Need to update size.\n\t\t\t\tchild.setSize(childWidth, childHeight);\n\t\t\t} else {\n\t\t\t\tchildWidth = child.getWidth();\n\t\t\t\tchildHeight = child.getHeight();\n\n\t\t\t\t//Child already at size.\n\t\t\t}\n\n\t\t\t//See if it fits this column but place at least one child in the first column!\n\t\t\tif (y - childHeight >= 0 || !wasChildProcessed) {\n\t\t\t\t//Fits into this column.\n\t\t\t\tcolumnWidth = Math.max(childWidth, columnWidth);\n\t\t\t} else {\n\t\t\t\t//Start new column.\n\t\t\t\tx += columnWidth + spacing;\n\t\t\t\ty = targetHeight;\n\t\t\t\tcolumnWidth = childWidth;\n\t\t\t}\n\n\t\t\tchild.setPosition(x, y - childHeight);\n\t\t\ty -= childHeight + spacing;\n\n\t\t\twasChildProcessed = true;\n\t\t}\n\n\t\t//Did a best effort to fit into the specified size but it still did not work.\n\t\t//Let the ancestors know in hopes that they resize the group.\n\t\tif (getWidth() != layoutedWidth) {\n\t\t\tinvalidateHierarchy();\n\t\t}\n\t}\n\n\tpublic float getSpacing () {\n\t\treturn spacing;\n\t}\n\n\tpublic void setSpacing (float spacing) {\n\t\tthis.spacing = spacing;\n\t\tinvalidateHierarchy();\n\t}\n\n\t@Override\n\tpublic void invalidate () {\n\t\tsizeInvalid = true;\n\t\tsuper.invalidate();\n\t}\n\n\t@Override\n\tpublic float getMinWidth () {\n\t\tcomputeSizeIfNeeded();\n\t\treturn minWidth;\n\t}\n\n\t@Override\n\tpublic float getMinHeight () {\n\t\tcomputeSizeIfNeeded();\n\t\treturn minHeight;\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\tcomputeSizeIfNeeded();\n\t\treturn vertical ? layoutedWidth : relaxedWidth;\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\tcomputeSizeIfNeeded();\n\t\treturn vertical ? relaxedHeight : layoutedHeight;\n\t}\n\n\tprotected void computeSizeIfNeeded () {\n\t\tif (sizeInvalid) {\n\t\t\tcomputeSize();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/layout/GridGroup.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.layout;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;\nimport com.badlogic.gdx.utils.SnapshotArray;\n\n/**\n * Arrange actors in grid layout. You can set item width, height and spacing between items.\n * <p>\n * Grid group can be embedded in scroll pane. However in such case scrolling in X direction must be disabled.\n * @author Kotcrab\n * @since 0.7.2\n */\npublic class GridGroup extends WidgetGroup {\n\tprivate float prefWidth;\n\tprivate float prefHeight;\n\tprivate float lastPrefHeight;\n\tprivate boolean sizeInvalid = true;\n\n\tprivate float itemWidth = 256;\n\tprivate float itemHeight = 256;\n\tprivate float spacing = 8;\n\n\tpublic GridGroup () {\n\t\tsetTouchable(Touchable.childrenOnly);\n\t}\n\n\tpublic GridGroup (float itemSize) {\n\t\tthis.itemWidth = itemSize;\n\t\tthis.itemHeight = itemSize;\n\t\tsetTouchable(Touchable.childrenOnly);\n\t}\n\n\tpublic GridGroup (float itemSize, float spacing) {\n\t\tthis.spacing = spacing;\n\t\tthis.itemWidth = itemSize;\n\t\tthis.itemHeight = itemSize;\n\t\tsetTouchable(Touchable.childrenOnly);\n\t}\n\n\tprivate void computeSize () {\n\t\tprefWidth = getWidth();\n\t\tprefHeight = 0;\n\t\tsizeInvalid = false;\n\n\t\tSnapshotArray<Actor> children = getChildren();\n\n\t\tif (children.size == 0) {\n\t\t\tprefWidth = 0;\n\t\t\tprefHeight = 0;\n\t\t\treturn;\n\t\t}\n\n\t\tfloat width = getWidth();\n\n\t\tfloat maxHeight = 0;\n\t\tfloat tempX = spacing;\n\n\t\tfor (int i = 0; i < children.size; i++) {\n\t\t\tif (tempX + itemWidth + spacing > width) {\n\t\t\t\ttempX = spacing;\n\t\t\t\tmaxHeight += itemHeight + spacing;\n\t\t\t}\n\n\t\t\ttempX += itemWidth + spacing;\n\t\t}\n\n\t\tif (itemWidth + spacing * 2 > prefWidth)\n\t\t\tmaxHeight += spacing;\n\t\telse\n\t\t\tmaxHeight += itemHeight + spacing * 2;\n\n\t\tprefHeight = maxHeight;\n\t}\n\n\t@Override\n\tpublic void layout () {\n\t\tif (sizeInvalid) {\n\t\t\tcomputeSize();\n\t\t\tif (lastPrefHeight != prefHeight) {\n\t\t\t\tlastPrefHeight = prefHeight;\n\t\t\t\tinvalidateHierarchy();\n\t\t\t}\n\t\t}\n\n\t\tSnapshotArray<Actor> children = getChildren();\n\n\t\tfloat width = getWidth();\n\t\tboolean notEnoughSpace = itemWidth + spacing * 2 > width;\n\n\t\tfloat x = spacing;\n\t\tfloat y = notEnoughSpace ? (getHeight()) : (getHeight() - itemHeight - spacing);\n\n\t\tfor (int i = 0; i < children.size; i++) {\n\t\t\tActor child = children.get(i);\n\n\t\t\tif (x + itemWidth + spacing > width) {\n\t\t\t\tx = spacing;\n\t\t\t\ty -= itemHeight + spacing;\n\t\t\t}\n\n\t\t\tchild.setBounds(x, y, itemWidth, itemHeight);\n\t\t\tx += itemWidth + spacing;\n\t\t}\n\t}\n\n\tpublic float getSpacing () {\n\t\treturn spacing;\n\t}\n\n\tpublic void setSpacing (float spacing) {\n\t\tthis.spacing = spacing;\n\t\tinvalidateHierarchy();\n\t}\n\n\tpublic void setItemSize (float itemSize) {\n\t\tthis.itemWidth = itemSize;\n\t\tthis.itemHeight = itemSize;\n\t\tinvalidateHierarchy();\n\t}\n\n\tpublic void setItemSize (float itemWidth, float itemHeight) {\n\t\tthis.itemWidth = itemWidth;\n\t\tthis.itemHeight = itemHeight;\n\t\tinvalidateHierarchy();\n\t}\n\n\tpublic float getItemWidth () {\n\t\treturn itemWidth;\n\t}\n\n\tpublic void setItemWidth (float itemWidth) {\n\t\tthis.itemWidth = itemWidth;\n\t}\n\n\tpublic float getItemHeight () {\n\t\treturn itemHeight;\n\t}\n\n\tpublic void setItemHeight (float itemHeight) {\n\t\tthis.itemHeight = itemHeight;\n\t}\n\n\t@Override\n\tpublic void invalidate () {\n\t\tsuper.invalidate();\n\t\tsizeInvalid = true;\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\tif (sizeInvalid) computeSize();\n\t\treturn prefWidth;\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\tif (sizeInvalid) computeSize();\n\t\treturn prefHeight;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/layout/HorizontalFlowGroup.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.layout;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;\nimport com.badlogic.gdx.scenes.scene2d.utils.Layout;\nimport com.badlogic.gdx.utils.SnapshotArray;\n\n/**\n * Arranges actors in rows filling available horizontal space. Creates new rows and expands vertically as necessary.\n * Children automatically overflow to next row when necessary.\n * <p>\n * Can be embedded in scroll pane however in that case scrolling in X direction must be disabled.\n * @author Kotcrab\n * @since 1.0.0\n * @deprecated Deprecated since 1.4.7. Use {@link com.kotcrab.vis.ui.layout.FlowGroup} instead.\n */\n@Deprecated\npublic class HorizontalFlowGroup extends WidgetGroup {\n\tprivate float prefWidth;\n\tprivate float prefHeight;\n\tprivate float lastPrefHeight;\n\tprivate boolean sizeInvalid = true;\n\n\tprivate float spacing = 0;\n\n\tpublic HorizontalFlowGroup () {\n\t\tsetTouchable(Touchable.childrenOnly);\n\t}\n\n\tpublic HorizontalFlowGroup (float spacing) {\n\t\tthis.spacing = spacing;\n\t\tsetTouchable(Touchable.childrenOnly);\n\t}\n\n\tprivate void computeSize () {\n\t\tprefWidth = getWidth();\n\t\tprefHeight = 0;\n\t\tsizeInvalid = false;\n\n\t\tSnapshotArray<Actor> children = getChildren();\n\n\t\tfloat x = 0;\n\t\tfloat rowHeight = 0;\n\n\t\tfor (int i = 0; i < children.size; i++) {\n\t\t\tActor child = children.get(i);\n\t\t\tfloat width = child.getWidth();\n\t\t\tfloat height = child.getHeight();\n\t\t\tif (child instanceof Layout) {\n\t\t\t\tLayout layout = (Layout) child;\n\t\t\t\twidth = layout.getPrefWidth();\n\t\t\t\theight = layout.getPrefHeight();\n\t\t\t}\n\n\t\t\tif (x + width > getWidth()) {\n\t\t\t\tx = 0;\n\t\t\t\tprefHeight += rowHeight + spacing;\n\t\t\t\trowHeight = height;\n\t\t\t} else {\n\t\t\t\trowHeight = Math.max(height, rowHeight);\n\t\t\t}\n\n\t\t\tx += width + spacing;\n\t\t}\n\n\t\t//handle last row height\n\t\tprefHeight += rowHeight + spacing;\n\t}\n\n\t@Override\n\tpublic void layout () {\n\t\tif (sizeInvalid) {\n\t\t\tcomputeSize();\n\t\t\tif (lastPrefHeight != prefHeight) {\n\t\t\t\tlastPrefHeight = prefHeight;\n\t\t\t\tinvalidateHierarchy();\n\t\t\t}\n\t\t}\n\n\t\tSnapshotArray<Actor> children = getChildren();\n\n\t\tfloat x = 0;\n\t\tfloat y = getHeight();\n\t\tfloat rowHeight = 0;\n\n\t\tfor (int i = 0; i < children.size; i++) {\n\t\t\tActor child = children.get(i);\n\t\t\tfloat width = child.getWidth();\n\t\t\tfloat height = child.getHeight();\n\t\t\tif (child instanceof Layout) {\n\t\t\t\tLayout layout = (Layout) child;\n\t\t\t\twidth = layout.getPrefWidth();\n\t\t\t\theight = layout.getPrefHeight();\n\t\t\t}\n\n\t\t\tif (x + width > getWidth()) {\n\t\t\t\tx = 0;\n\t\t\t\ty -= rowHeight + spacing;\n\t\t\t\trowHeight = height;\n\t\t\t} else {\n\t\t\t\trowHeight = Math.max(height, rowHeight);\n\t\t\t}\n\n\t\t\tchild.setBounds(x, y - height, width, height);\n\t\t\tx += width + spacing;\n\t\t}\n\t}\n\n\tpublic float getSpacing () {\n\t\treturn spacing;\n\t}\n\n\tpublic void setSpacing (float spacing) {\n\t\tthis.spacing = spacing;\n\t\tinvalidateHierarchy();\n\t}\n\n\t@Override\n\tpublic void invalidate () {\n\t\tsuper.invalidate();\n\t\tsizeInvalid = true;\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\tif (sizeInvalid) computeSize();\n\t\treturn prefWidth;\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\tif (sizeInvalid) computeSize();\n\t\treturn prefHeight;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/layout/VerticalFlowGroup.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.layout;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;\nimport com.badlogic.gdx.scenes.scene2d.utils.Layout;\nimport com.badlogic.gdx.utils.SnapshotArray;\n\n/**\n * Arranges actors in single column filling available vertical space. Creates new columns and expands horizontally as\n * necessary.\n * Children automatically overflow to next column when necessary.\n * <p>\n * Can be embedded in scroll pane however in that case scrolling in Y direction must be disabled.\n * @author Kotcrab\n * @since 1.0.0\n * @deprecated Deprecated since 1.4.7. Use {@link com.kotcrab.vis.ui.layout.FlowGroup} instead.\n */\n@Deprecated\npublic class VerticalFlowGroup extends WidgetGroup {\n\tprivate float prefWidth;\n\tprivate float prefHeight;\n\tprivate float lastPrefHeight;\n\tprivate boolean sizeInvalid = true;\n\n\tprivate float spacing = 0;\n\n\tpublic VerticalFlowGroup () {\n\t\tsetTouchable(Touchable.childrenOnly);\n\t}\n\n\tpublic VerticalFlowGroup (float spacing) {\n\t\tthis.spacing = spacing;\n\t\tsetTouchable(Touchable.childrenOnly);\n\t}\n\n\tprivate void computeSize () {\n\t\tprefWidth = 0;\n\t\tprefHeight = getHeight();\n\t\tsizeInvalid = false;\n\n\t\tSnapshotArray<Actor> children = getChildren();\n\n\t\tfloat y = 0;\n\t\tfloat columnWidth = 0;\n\n\t\tfor (int i = 0; i < children.size; i++) {\n\t\t\tActor child = children.get(i);\n\t\t\tfloat width = child.getWidth();\n\t\t\tfloat height = child.getHeight();\n\t\t\tif (child instanceof Layout) {\n\t\t\t\tLayout layout = (Layout) child;\n\t\t\t\twidth = layout.getPrefWidth();\n\t\t\t\theight = layout.getPrefHeight();\n\t\t\t}\n\n\t\t\tif (y + height > getHeight()) {\n\t\t\t\ty = 0;\n\t\t\t\tprefWidth += columnWidth + spacing;\n\t\t\t\tcolumnWidth = width;\n\t\t\t} else {\n\t\t\t\tcolumnWidth = Math.max(width, columnWidth);\n\t\t\t}\n\n\t\t\ty += height + spacing;\n\t\t}\n\n\t\t//handle last column width\n\t\tprefWidth += columnWidth + spacing;\n\t}\n\n\t@Override\n\tpublic void layout () {\n\t\tif (sizeInvalid) {\n\t\t\tcomputeSize();\n\t\t\tif (lastPrefHeight != prefHeight) {\n\t\t\t\tlastPrefHeight = prefHeight;\n\t\t\t\tinvalidateHierarchy();\n\t\t\t}\n\t\t}\n\n\t\tSnapshotArray<Actor> children = getChildren();\n\n\t\tfloat x = 0;\n\t\tfloat y = getHeight();\n\t\tfloat columnWidth = 0;\n\n\t\tfor (int i = 0; i < children.size; i++) {\n\t\t\tActor child = children.get(i);\n\t\t\tfloat width = child.getWidth();\n\t\t\tfloat height = child.getHeight();\n\t\t\tif (child instanceof Layout) {\n\t\t\t\tLayout layout = (Layout) child;\n\t\t\t\twidth = layout.getPrefWidth();\n\t\t\t\theight = layout.getPrefHeight();\n\t\t\t}\n\n\t\t\tif (y - height < 0) {\n\t\t\t\ty = getHeight();\n\t\t\t\tx += columnWidth + spacing;\n\t\t\t\tcolumnWidth = width;\n\t\t\t} else {\n\t\t\t\tcolumnWidth = Math.max(width, columnWidth);\n\t\t\t}\n\n\t\t\tchild.setBounds(x, y - height, width, height);\n\t\t\ty -= height + spacing;\n\t\t}\n\t}\n\n\tpublic float getSpacing () {\n\t\treturn spacing;\n\t}\n\n\tpublic void setSpacing (float spacing) {\n\t\tthis.spacing = spacing;\n\t\tinvalidateHierarchy();\n\t}\n\n\t@Override\n\tpublic void invalidate () {\n\t\tsuper.invalidate();\n\t\tsizeInvalid = true;\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\tif (sizeInvalid) computeSize();\n\t\treturn prefWidth;\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\tif (sizeInvalid) computeSize();\n\t\treturn prefHeight;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/ActorUtils.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util;\n\nimport com.badlogic.gdx.graphics.Camera;\nimport com.badlogic.gdx.graphics.OrthographicCamera;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.Stage;\nimport com.badlogic.gdx.utils.Align;\n\n/**\n * {@link Actor} related utils.\n * @author Kotcrab\n */\npublic class ActorUtils {\n\t/**\n\t * Makes sures that actor will be fully visible in stage. If it's necessary actor position will be changed to fit it\n\t * on screen.\n\t * @throws IllegalStateException if actor does not belong to any stage.\n\t */\n\tpublic static void keepWithinStage (Actor actor) {\n\t\tStage stage = actor.getStage();\n\t\tif (stage == null) {\n\t\t\tthrow new IllegalStateException(\"keepWithinStage cannot be used on Actor that doesn't belong to any stage. \");\n\t\t}\n\t\tkeepWithinStage(actor.getStage(), actor);\n\t}\n\n\t/**\n\t * Makes sures that actor will be fully visible in stage. If it's necessary actor position will be changed to fit it\n\t * on screen.\n\t */\n\tpublic static void keepWithinStage (Stage stage, Actor actor) {\n\t\t//taken from scene2d.ui Window\n\t\tCamera camera = stage.getCamera();\n\t\tif (camera instanceof OrthographicCamera) {\n\t\t\tOrthographicCamera orthographicCamera = (OrthographicCamera) camera;\n\t\t\tfloat parentWidth = stage.getWidth();\n\t\t\tfloat parentHeight = stage.getHeight();\n\t\t\tif (actor.getX(Align.right) - camera.position.x > parentWidth / 2 / orthographicCamera.zoom)\n\t\t\t\tactor.setPosition(camera.position.x + parentWidth / 2 / orthographicCamera.zoom, actor.getY(Align.right), Align.right);\n\t\t\tif (actor.getX(Align.left) - camera.position.x < -parentWidth / 2 / orthographicCamera.zoom)\n\t\t\t\tactor.setPosition(camera.position.x - parentWidth / 2 / orthographicCamera.zoom, actor.getY(Align.left), Align.left);\n\t\t\tif (actor.getY(Align.top) - camera.position.y > parentHeight / 2 / orthographicCamera.zoom)\n\t\t\t\tactor.setPosition(actor.getX(Align.top), camera.position.y + parentHeight / 2 / orthographicCamera.zoom, Align.top);\n\t\t\tif (actor.getY(Align.bottom) - camera.position.y < -parentHeight / 2 / orthographicCamera.zoom)\n\t\t\t\tactor.setPosition(actor.getX(Align.bottom), camera.position.y - parentHeight / 2 / orthographicCamera.zoom, Align.bottom);\n\t\t} else if (actor.getParent() == stage.getRoot()) {\n\t\t\tfloat parentWidth = stage.getWidth();\n\t\t\tfloat parentHeight = stage.getHeight();\n\t\t\tif (actor.getX() < 0) actor.setX(0);\n\t\t\tif (actor.getRight() > parentWidth) actor.setX(parentWidth - actor.getWidth());\n\t\t\tif (actor.getY() < 0) actor.setY(0);\n\t\t\tif (actor.getTop() > parentHeight) actor.setY(parentHeight - actor.getHeight());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/BorderOwner.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util;\n\n/**\n * Implemented by actors that has VisUI focus border, actor implementing this interface must support disabling its border.\n * @author Kotcrab\n */\npublic interface BorderOwner {\n\tboolean isFocusBorderEnabled ();\n\n\tvoid setFocusBorderEnabled (boolean focusBorderEnabled);\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/ColorUtils.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.math.MathUtils;\n\n/**\n * Utilities for converting between RGB and HSV color systems.\n * @author Kotcrab\n * @since 0.6.0\n */\npublic class ColorUtils {\n\t/**\n\t * Converts HSV to RGB\n\t * @param h hue 0-360\n\t * @param s saturation 0-100\n\t * @param v value 0-100\n\t * @param alpha 0-1\n\t * @return RGB values in libGDX {@link Color} class\n\t */\n\tpublic static Color HSVtoRGB (float h, float s, float v, float alpha) {\n\t\tColor c = HSVtoRGB(h, s, v);\n\t\tc.a = alpha;\n\t\treturn c;\n\t}\n\n\t/**\n\t * Converts HSV color system to RGB\n\t * @param h hue 0-360\n\t * @param s saturation 0-100\n\t * @param v value 0-100\n\t * @return RGB values in libGDX {@link Color} class\n\t */\n\tpublic static Color HSVtoRGB (float h, float s, float v) {\n\t\tColor c = new Color(1, 1, 1, 1);\n\t\tHSVtoRGB(h, s, v, c);\n\t\treturn c;\n\t}\n\n\t/**\n\t * Converts HSV color system to RGB\n\t * @param h hue 0-360\n\t * @param s saturation 0-100\n\t * @param v value 0-100\n\t * @param targetColor color that result will be stored in\n\t * @return targetColor\n\t */\n\tpublic static Color HSVtoRGB (float h, float s, float v, Color targetColor) {\n\t\tif (h == 360) h = 359;\n\t\tint r, g, b;\n\t\tint i;\n\t\tfloat f, p, q, t;\n\t\th = (float) Math.max(0.0, Math.min(360.0, h));\n\t\ts = (float) Math.max(0.0, Math.min(100.0, s));\n\t\tv = (float) Math.max(0.0, Math.min(100.0, v));\n\t\ts /= 100;\n\t\tv /= 100;\n\t\th /= 60;\n\t\ti = MathUtils.floor(h);\n\t\tf = h - i;\n\t\tp = v * (1 - s);\n\t\tq = v * (1 - s * f);\n\t\tt = v * (1 - s * (1 - f));\n\t\tswitch (i) {\n\t\t\tcase 0:\n\t\t\t\tr = MathUtils.round(255 * v);\n\t\t\t\tg = MathUtils.round(255 * t);\n\t\t\t\tb = MathUtils.round(255 * p);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tr = MathUtils.round(255 * q);\n\t\t\t\tg = MathUtils.round(255 * v);\n\t\t\t\tb = MathUtils.round(255 * p);\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tr = MathUtils.round(255 * p);\n\t\t\t\tg = MathUtils.round(255 * v);\n\t\t\t\tb = MathUtils.round(255 * t);\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tr = MathUtils.round(255 * p);\n\t\t\t\tg = MathUtils.round(255 * q);\n\t\t\t\tb = MathUtils.round(255 * v);\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tr = MathUtils.round(255 * t);\n\t\t\t\tg = MathUtils.round(255 * p);\n\t\t\t\tb = MathUtils.round(255 * v);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tr = MathUtils.round(255 * v);\n\t\t\t\tg = MathUtils.round(255 * p);\n\t\t\t\tb = MathUtils.round(255 * q);\n\t\t}\n\n\t\ttargetColor.set(r / 255.0f, g / 255.0f, b / 255.0f, targetColor.a);\n\t\treturn targetColor;\n\t}\n\n\t/**\n\t * Converts {@link Color} to HSV color system\n\t * @return 3 element int array with hue (0-360), saturation (0-100) and value (0-100)\n\t */\n\tpublic static int[] RGBtoHSV (Color c) {\n\t\treturn RGBtoHSV(c.r, c.g, c.b);\n\t}\n\n\t/**\n\t * Converts RGB to HSV color system\n\t * @param r red 0-1\n\t * @param g green 0-1\n\t * @param b blue 0-1\n\t * @return 3 element int array with hue (0-360), saturation (0-100) and value (0-100)\n\t */\n\tpublic static int[] RGBtoHSV (float r, float g, float b) {\n\t\tfloat h, s, v;\n\t\tfloat min, max, delta;\n\n\t\tmin = Math.min(Math.min(r, g), b);\n\t\tmax = Math.max(Math.max(r, g), b);\n\t\tv = max;\n\n\t\tdelta = max - min;\n\n\t\tif (max != 0)\n\t\t\ts = delta / max;\n\t\telse {\n\t\t\ts = 0;\n\t\t\th = 0;\n\t\t\treturn new int[]{MathUtils.round(h), MathUtils.round(s), MathUtils.round(v)};\n\t\t}\n\n\t\tif (delta == 0)\n\t\t\th = 0;\n\t\telse {\n\n\t\t\tif (r == max)\n\t\t\t\th = (g - b) / delta;\n\t\t\telse if (g == max)\n\t\t\t\th = 2 + (b - r) / delta;\n\t\t\telse\n\t\t\t\th = 4 + (r - g) / delta;\n\t\t}\n\n\t\th *= 60;\n\t\tif (h < 0)\n\t\t\th += 360;\n\n\t\ts *= 100;\n\t\tv *= 100;\n\n\t\treturn new int[]{MathUtils.round(h), MathUtils.round(s), MathUtils.round(v)};\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/CursorManager.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.graphics.Cursor;\n\n/**\n * Manages default cursor of VisUI app. If you are using custom cursor you must set it here otherwise some VisUI widget\n * that changes cursors will reset it to default system cursor.\n * @author Kotcrab\n * @since 1.1.2\n */\npublic class CursorManager {\n\tprivate static Cursor defaultCursor;\n\tprivate static Cursor.SystemCursor defaultSystemCursor = Cursor.SystemCursor.Arrow;\n\tprivate static boolean systemCursorAsDefault = true;\n\n\t/**\n\t * Sets cursor that will be used as default when {@link #restoreDefaultCursor()} is called, for example by VisUI widget.\n\t * @param defaultCursor default cursor, can't be null\n\t */\n\tpublic static void setDefaultCursor (Cursor defaultCursor) {\n\t\tif (defaultCursor == null) throw new IllegalArgumentException(\"defaultCursor can't be null\");\n\t\tCursorManager.defaultCursor = defaultCursor;\n\t\tCursorManager.systemCursorAsDefault = false;\n\t}\n\n\t/**\n\t * Sets cursor that will be used as default when {@link #restoreDefaultCursor()} is called, for example by Vis widget.\n\t * @param defaultCursor default cursor from {@link Cursor.SystemCursor}, can't be null\n\t */\n\tpublic static void setDefaultCursor (Cursor.SystemCursor defaultCursor) {\n\t\tif (defaultCursor == null) throw new IllegalArgumentException(\"defaultCursor can't be null\");\n\t\tCursorManager.defaultSystemCursor = defaultCursor;\n\t\tCursorManager.systemCursorAsDefault = true;\n\t}\n\n\t/** Restores currently used cursor to default one. */\n\tpublic static void restoreDefaultCursor () {\n\t\tif (systemCursorAsDefault) {\n\t\t\tGdx.graphics.setSystemCursor(defaultSystemCursor);\n\t\t} else {\n\t\t\tGdx.graphics.setCursor(defaultCursor);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/FloatDigitsOnlyFilter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util;\n\nimport com.kotcrab.vis.ui.widget.VisTextField;\nimport com.kotcrab.vis.ui.widget.VisTextField.TextFieldFilter;\n\n/**\n * {@link TextFieldFilter} that only allows digits for float values.\n * @author Kotcrab\n */\npublic class FloatDigitsOnlyFilter extends IntDigitsOnlyFilter {\n\tpublic FloatDigitsOnlyFilter (boolean acceptNegativeValues) {\n\t\tsuper(acceptNegativeValues);\n\t}\n\n\t@Override\n\tpublic boolean acceptChar (VisTextField field, char c) {\n\t\tint selectionStart = field.getSelectionStart();\n\t\tint cursorPos = field.getCursorPosition();\n\t\tString text;\n\t\tif (field.isTextSelected()) { //issue #131\n\t\t\tString beforeSelection = field.getText().substring(0, Math.min(selectionStart, cursorPos));\n\t\t\tString afterSelection = field.getText().substring(Math.max(selectionStart, cursorPos));\n\t\t\ttext = beforeSelection + afterSelection;\n\t\t} else {\n\t\t\ttext = field.getText();\n\t\t}\n\n\t\tif (c == '.' && text.contains(\".\") == false) return true;\n\t\treturn super.acceptChar(field, c);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/InputValidator.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util;\n\nimport com.kotcrab.vis.ui.util.dialog.Dialogs;\nimport com.kotcrab.vis.ui.util.form.SimpleFormValidator;\nimport com.kotcrab.vis.ui.widget.VisValidatableTextField;\n\n/**\n * Interface implemented by classes that can validate whether user input is right or wrong, typically used by {@link VisValidatableTextField}\n * {@link SimpleFormValidator} and {@link Dialogs} input dialogs.\n * @author Kotcrab\n * @since 0.0.3\n */\npublic interface InputValidator {\n\t/**\n\t * Called when input must be validated.\n\t * @param input text that should be validated\n\t * @return true if input is valid, false otherwise\n\t */\n\tboolean validateInput (String input);\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/IntDigitsOnlyFilter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util;\n\nimport com.kotcrab.vis.ui.widget.VisTextField;\nimport com.kotcrab.vis.ui.widget.VisTextField.TextFieldFilter;\n\n/**\n * {@link TextFieldFilter} that only allows digits for integer values.\n * @author Kotcrab\n */\npublic class IntDigitsOnlyFilter extends NumberDigitsTextFieldFilter {\n\tpublic IntDigitsOnlyFilter (boolean acceptNegativeValues) {\n\t\tsuper(acceptNegativeValues);\n\t}\n\n\t@Override\n\tpublic boolean acceptChar (VisTextField field, char c) {\n\t\tif (isAcceptNegativeValues()) {\n\t\t\tif (isUseFieldCursorPosition()) {\n\t\t\t\tif (c == '-' && (field.getCursorPosition() > 0 || field.getText().startsWith(\"-\"))) return false;\n\t\t\t} else {\n\t\t\t\tif (c == '-' && field.getText().startsWith(\"-\")) return false;\n\t\t\t}\n\n\t\t\tif (c == '-') return true;\n\t\t}\n\t\treturn Character.isDigit(c);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/NumberDigitsTextFieldFilter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util;\n\nimport com.kotcrab.vis.ui.widget.VisTextField.TextFieldFilter;\n\n/**\n * Base class for number digits text field filters. Filters extending this class must handle disabling entering\n * negative number values and using cursor position to prevent typing minus in wrong place.\n * @author Kotcrab\n * @see IntDigitsOnlyFilter\n * @see FloatDigitsOnlyFilter\n */\npublic abstract class NumberDigitsTextFieldFilter implements TextFieldFilter {\n\tprivate boolean acceptNegativeValues;\n\tprivate boolean useFieldCursorPosition;\n\n\tpublic NumberDigitsTextFieldFilter (boolean acceptNegativeValues) {\n\t\tthis.acceptNegativeValues = acceptNegativeValues;\n\t}\n\n\tpublic boolean isAcceptNegativeValues () {\n\t\treturn acceptNegativeValues;\n\t}\n\n\tpublic void setAcceptNegativeValues (boolean acceptNegativeValues) {\n\t\tthis.acceptNegativeValues = acceptNegativeValues;\n\t}\n\n\tpublic boolean isUseFieldCursorPosition () {\n\t\treturn useFieldCursorPosition;\n\t}\n\n\t/**\n\t * @param useFieldCursorPosition if true this filter will use current field cursor position to prevent typing minus sign\n\t * in wrong place. This is disabled by default. If you enable this feature you must ensure that field cursor position is\n\t * set to 0 when you change text programmatically. Non zero cursor position can happen when you are changing text when\n\t * field still has user focus.\n\t */\n\tpublic void setUseFieldCursorPosition (boolean useFieldCursorPosition) {\n\t\tthis.useFieldCursorPosition = useFieldCursorPosition;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/OsUtils.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util;\n\nimport com.badlogic.gdx.Application.ApplicationType;\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.Input.Keys;\n\n/**\n * Operating system related utils.\n * @author Kotcrab\n * @author Simon Gerst\n */\npublic class OsUtils {\n\tprivate static final String OS = System.getProperty(\"os.name\", \"\").toLowerCase();\n\tprivate static final boolean WINDOWS = OS.contains(\"win\");\n\tprivate static final boolean MAC = OS.contains(\"mac\");\n\tprivate static final boolean UNIX = OS.contains(\"nix\") || OS.contains(\"nux\") || OS.contains(\"aix\");\n\n\t/** @return {@code true} if the current OS is Windows */\n\tpublic static boolean isWindows () {\n\t\treturn WINDOWS;\n\t}\n\n\t/** @return {@code true} if the current OS is Mac */\n\tpublic static boolean isMac () {\n\t\treturn MAC;\n\t}\n\n\t/** @return {@code true} if the current OS is Unix */\n\tpublic static boolean isUnix () {\n\t\treturn UNIX;\n\t}\n\n\t/** @return {@code true} if the current OS is iOS */\n\tpublic static boolean isIos () {\n\t\treturn Gdx.app.getType() == ApplicationType.iOS;\n\t}\n\n\t/** @return {@code true} if the current OS is Android */\n\tpublic static boolean isAndroid () {\n\t\treturn Gdx.app.getType() == ApplicationType.Android;\n\t}\n\n\t/**\n\t * Returns the Android API level it's basically the same as android.os.Build.VERSION.SDK_INT\n\t * @return the API level. Returns 0 if the current OS isn't Android\n\t */\n\tpublic static int getAndroidApiLevel () {\n\t\tif (isAndroid()) {\n\t\t\treturn Gdx.app.getVersion();\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\t/**\n\t * Creates platform dependant shortcut text. Converts int keycodes to String text. Eg. Keys.CONTROL_LEFT,\n\t * Keys.SHIFT_LEFT, Keys.F5 will be converted to Ctrl+Shift+F5 on Windows and Linux, and to ⌘⇧F5 on Mac.\n\t * <p>\n\t * CONTROL_LEFT and CONTROL_RIGHT and SYM are mapped to Ctrl. The same goes for Alt (ALT_LEFT, ALT_RIGHT) and Shift (SHIFT_LEFT, SHIFT_RIGHT).\n\t * <p>\n\t * Keycodes equal to {@link Integer#MIN_VALUE} will be ignored.\n\t * @param keycodes keycodes from {@link Keys} that are used to create shortcut text\n\t * @return the platform dependent shortcut text\n\t */\n\tpublic static String getShortcutFor (int... keycodes) {\n\t\tStringBuilder builder = new StringBuilder();\n\n\t\tString separatorString = \"+\";\n\t\tString ctrlKey = \"Ctrl\";\n\t\tString altKey = \"Alt\";\n\t\tString shiftKey = \"Shift\";\n\n\t\tif (OsUtils.isMac()) {\n\t\t\tseparatorString = \"\";\n\t\t\tctrlKey = \"\\u2318\";\n\t\t\taltKey = \"\\u2325\";\n\t\t\tshiftKey = \"\\u21E7\";\n\t\t}\n\n\t\tfor (int i = 0; i < keycodes.length; i++) {\n\t\t\tif (keycodes[i] == Integer.MIN_VALUE) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (keycodes[i] == Keys.CONTROL_LEFT || keycodes[i] == Keys.CONTROL_RIGHT || keycodes[i] == Keys.SYM) {\n\t\t\t\tbuilder.append(ctrlKey);\n\t\t\t} else if (keycodes[i] == Keys.SHIFT_LEFT || keycodes[i] == Keys.SHIFT_RIGHT) {\n\t\t\t\tbuilder.append(shiftKey);\n\t\t\t} else if (keycodes[i] == Keys.ALT_LEFT || keycodes[i] == Keys.ALT_RIGHT) {\n\t\t\t\tbuilder.append(altKey);\n\t\t\t} else {\n\t\t\t\tbuilder.append(Keys.toString(keycodes[i]));\n\t\t\t}\n\n\t\t\tif (i < keycodes.length - 1) { // Is this NOT the last key\n\t\t\t\tbuilder.append(separatorString);\n\t\t\t}\n\t\t}\n\n\t\treturn builder.toString();\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/TableUtils.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * Utilities for VisTable/Table.\n * @author Kotcrab\n */\npublic class TableUtils {\n\t/** Sets default table spacing for VisUI skin. Uses values from current skin {@link Sizes} class obtained from {@link VisUI#getSizes()}. */\n\tpublic static void setSpacingDefaults (Table table) {\n\t\tSizes sizes = VisUI.getSizes();\n\t\tif (sizes.spacingTop != 0) table.defaults().spaceTop(sizes.spacingTop);\n\t\tif (sizes.spacingBottom != 0) table.defaults().spaceBottom(sizes.spacingBottom);\n\t\tif (sizes.spacingRight != 0) table.defaults().spaceRight(sizes.spacingRight);\n\t\tif (sizes.spacingLeft != 0) table.defaults().spaceLeft(sizes.spacingLeft);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/ToastManager.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util;\n\nimport com.badlogic.gdx.scenes.scene2d.Group;\nimport com.badlogic.gdx.scenes.scene2d.Stage;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;\nimport com.badlogic.gdx.utils.Align;\nimport com.badlogic.gdx.utils.Array;\nimport com.badlogic.gdx.utils.ObjectMap;\nimport com.badlogic.gdx.utils.Timer;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.toast.MessageToast;\nimport com.kotcrab.vis.ui.widget.toast.Toast;\nimport com.kotcrab.vis.ui.widget.toast.ToastTable;\n\n/**\n * Utility for displaying toast messages at corner of application screen (by default top right). Toasts can be closed by users or they\n * can automatically disappear after a period of time. Typically only one instance of ToastManager is used per\n * application window.\n * <p>\n * To properly support window resize {@link #resize()} must be called when application resize has occurred.\n * <p>\n * Most show methods are taking {@link VisTable} however {@link ToastTable} should be preferred because it's provides\n * access to enclosing {@link Toast} instance.\n * @author Kotcrab\n * @see Toast\n * @see ToastTable\n * @see MessageToast\n * @since 1.1.0\n */\npublic class ToastManager {\n\tpublic static final int UNTIL_CLOSED = -1;\n\n\tprotected final Group root;\n\n\tprotected int screenPaddingX = 20;\n\tprotected int screenPaddingY = 20;\n\tprotected int messagePadding = 5;\n\tprotected int alignment = Align.topRight;\n\n\tprotected Array<Toast> toasts = new Array<Toast>();\n\tprotected ObjectMap<Toast, Timer.Task> timersTasks = new ObjectMap<Toast, Timer.Task>();\n\n\t/** Toast manager will create own group to host toasts and put it into the stage root. */\n\tpublic ToastManager (Stage stage) {\n\t\tWidgetGroup widgetGroup = new WidgetGroup();\n\t\twidgetGroup.setFillParent(true);\n\t\twidgetGroup.setTouchable(Touchable.childrenOnly);\n\t\tstage.addActor(widgetGroup);\n\t\tthis.root = widgetGroup;\n\t}\n\n\t/** @param root Toast manager will use this group as a host for toast actors. */\n\tpublic ToastManager (Group root) {\n\t\tthis.root = root;\n\t}\n\n\t/** Displays basic toast with provided text as message. Toast will be displayed until it is closed by user. */\n\tpublic void show (String text) {\n\t\tshow(text, UNTIL_CLOSED);\n\t}\n\n\t/** Displays basic toast with provided text as message. Toast will be displayed for given amount of seconds. */\n\tpublic void show (String text, float timeSec) {\n\t\tVisTable table = new VisTable();\n\t\ttable.add(text).grow();\n\t\tshow(table, timeSec);\n\t}\n\n\t/** Displays toast with provided table as toast's content. Toast will be displayed until it is closed by user. */\n\tpublic void show (Table table) {\n\t\tshow(table, UNTIL_CLOSED);\n\t}\n\n\t/** Displays toast with provided table as toast's content. Toast will be displayed for given amount of seconds. */\n\tpublic void show (Table table, float timeSec) {\n\t\tshow(new Toast(table), timeSec);\n\t}\n\n\t/**\n\t * Displays toast with provided table as toast's content. If this toast was already displayed then it reuses\n\t * stored {@link Toast} instance.\n\t * Toast will be displayed until it is closed by user.\n\t */\n\tpublic void show (ToastTable toastTable) {\n\t\tshow(toastTable, UNTIL_CLOSED);\n\t}\n\n\t/**\n\t * Displays toast with provided table as toast's content. If this toast was already displayed then it reuses\n\t * stored {@link Toast} instance.\n\t * Toast will be displayed for given amount of seconds.\n\t */\n\tpublic void show (ToastTable toastTable, float timeSec) {\n\t\tToast toast = toastTable.getToast();\n\t\tif (toast != null) {\n\t\t\tshow(toast, timeSec);\n\t\t} else {\n\t\t\tshow(new Toast(toastTable), timeSec);\n\t\t}\n\t}\n\n\t/** Displays toast. Toast will be displayed until it is closed by user. */\n\tpublic void show (Toast toast) {\n\t\tshow(toast, UNTIL_CLOSED);\n\t}\n\n\t/** Displays toast. Toast will be displayed for given amount of seconds. */\n\tpublic void show (final Toast toast, float timeSec) {\n\t\tTable toastMainTable = toast.getMainTable();\n\t\tif (toastMainTable.getStage() != null) {\n\t\t\tremove(toast);\n\t\t}\n\t\ttoasts.add(toast);\n\n\t\ttoast.setToastManager(this);\n\t\ttoast.fadeIn();\n\t\ttoastMainTable.pack();\n\t\troot.addActor(toastMainTable);\n\n\t\tupdateToastsPositions();\n\n\t\tif (timeSec > 0) {\n\t\t\tTimer.Task fadeOutTask = new Timer.Task() {\n\t\t\t\t@Override\n\t\t\t\tpublic void run () {\n\t\t\t\t\ttoast.fadeOut();\n\t\t\t\t\ttimersTasks.remove(toast);\n\t\t\t\t}\n\t\t\t};\n\t\t\ttimersTasks.put(toast, fadeOutTask);\n\t\t\tTimer.schedule(fadeOutTask, timeSec);\n\t\t}\n\t}\n\n\t/** Must be called after application window resize to properly update toast positions on screen. */\n\tpublic void resize () {\n\t\tupdateToastsPositions();\n\t}\n\n\t/**\n\t * Removes toast from screen.\n\t * @return true when toast was removed, false otherwise\n\t */\n\tpublic boolean remove (Toast toast) {\n\t\tboolean removed = toasts.removeValue(toast, true);\n\t\tif (removed) {\n\t\t\ttoast.getMainTable().remove();\n\t\t\tTimer.Task timerTask = timersTasks.remove(toast);\n\t\t\tif (timerTask != null) timerTask.cancel();\n\t\t\tupdateToastsPositions();\n\t\t}\n\t\treturn removed;\n\t}\n\n\tpublic void clear () {\n\t\tfor (Toast toast : toasts) {\n\t\t\ttoast.getMainTable().remove();\n\t\t}\n\t\ttoasts.clear();\n\t\tfor (Timer.Task task : timersTasks.values()) {\n\t\t\ttask.cancel();\n\t\t}\n\t\ttimersTasks.clear();\n\t\tupdateToastsPositions();\n\t}\n\n\tpublic void toFront () {\n\t\troot.toFront();\n\t}\n\n\tprotected void updateToastsPositions () {\n\t\tboolean bottom = (alignment & Align.bottom) != 0;\n\t\tboolean left = (alignment & Align.left) != 0;\n\t\tboolean center = (alignment & Align.center) != 0;\n\t\tfloat y = bottom ? screenPaddingY : root.getHeight() - screenPaddingY;\n\n\t\tfor (Toast toast : toasts) {\n\t\t\tTable table = toast.getMainTable();\n\t\t\tfloat x = left ? screenPaddingX\n\t\t\t\t\t: center ? (root.getWidth() - table.getWidth() - screenPaddingX) / 2f\n\t\t\t\t\t: /*right*/ root.getWidth() - table.getWidth() - screenPaddingX;\n\t\t\ttable.setPosition(x, bottom ? y : y - table.getHeight());\n\n\t\t\ty += (table.getHeight() + messagePadding) * (bottom ? 1 : -1);\n\t\t}\n\t}\n\n\t/**\n\t * @return returns current screen padding only if padding X is equals to padding Y.\n\t * @throws IllegalStateException when current screen padding X is different than screen padding Y\n\t * @deprecated this method was deprecated in VisUI 1.4.3. Use either {@link #getScreenPaddingX()} or\n\t * {@link #getScreenPaddingY()}. This method will be removed in future versions.\n\t */\n\t@Deprecated\n\tpublic int getScreenPadding () {\n\t\tif (screenPaddingX != screenPaddingY) {\n\t\t\tthrow new IllegalStateException(\"Value of screen padding X is different than padding Y. \" +\n\t\t\t\t\t\"Use either getScreenPaddingX or getScreenPaddingY.\");\n\t\t}\n\t\treturn screenPaddingX;\n\t}\n\n\tpublic int getScreenPaddingX () {\n\t\treturn screenPaddingX;\n\t}\n\n\tpublic int getScreenPaddingY () {\n\t\treturn screenPaddingY;\n\t}\n\n\t/** Sets padding of a message from window corner (actual corner used depends on current alignment settings). */\n\tpublic void setScreenPadding (int screenPadding) {\n\t\tthis.screenPaddingX = screenPadding;\n\t\tthis.screenPaddingY = screenPadding;\n\t\tupdateToastsPositions();\n\t}\n\n\t/** Sets padding of a message from window corner (actual corner used depends on current alignment settings). */\n\tpublic void setScreenPadding (int screenPaddingX, int screenPaddingY) {\n\t\tthis.screenPaddingX = screenPaddingX;\n\t\tthis.screenPaddingY = screenPaddingY;\n\t\tupdateToastsPositions();\n\t}\n\n\t/** Sets padding of a message from window vertical edge (actual edge used depends on current alignment settings). */\n\tpublic void setScreenPaddingX (int screenPaddingX) {\n\t\tthis.screenPaddingX = screenPaddingX;\n\t\tupdateToastsPositions();\n\t}\n\n\t/** Sets padding of a message from window horizontal edge (actual edge used depends on current alignment settings). */\n\tpublic void setScreenPaddingY (int screenPaddingY) {\n\t\tthis.screenPaddingY = screenPaddingY;\n\t\tupdateToastsPositions();\n\t}\n\n\tpublic int getMessagePadding () {\n\t\treturn messagePadding;\n\t}\n\n\t/** Sets padding between messages */\n\tpublic void setMessagePadding (int messagePadding) {\n\t\tthis.messagePadding = messagePadding;\n\t\tupdateToastsPositions();\n\t}\n\n\tpublic int getAlignment () {\n\t\treturn alignment;\n\t}\n\n\t/**\n\t * Sets toast messages screen alignment. By default toasts are displayed in application top right corner\n\t * @param alignment one of {@link Align#topLeft}, {@link Align#topRight}, {@link Align#bottomLeft} or {@link Align#bottomRight},\n\t */\n\tpublic void setAlignment (int alignment) {\n\t\tthis.alignment = alignment;\n\t\tupdateToastsPositions();\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/Validators.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util;\n\nimport com.kotcrab.vis.ui.util.dialog.Dialogs;\nimport com.kotcrab.vis.ui.widget.VisValidatableTextField;\n\n/**\n * Provides premade validators that can be used with for example with {@link VisValidatableTextField} or {@link Dialogs}\n * when displaying input dialogs.\n * @author Kotcrab\n */\npublic class Validators {\n\t/** Shared static instance of {@link IntegerValidator}. Can be safely reused. */\n\tpublic static final IntegerValidator INTEGERS = new IntegerValidator();\n\t/** Shared static instance of {@link FloatValidator}. Can be safely reused. */\n\tpublic static final FloatValidator FLOATS = new FloatValidator();\n\n\t/** Validates whether input is an integer number. You should use shared instance {@link Validators#INTEGERS}. */\n\tpublic static class IntegerValidator implements InputValidator {\n\t\t@Override\n\t\tpublic boolean validateInput (String input) {\n\t\t\ttry {\n\t\t\t\tInteger.parseInt(input);\n\t\t\t\treturn true;\n\t\t\t} catch (NumberFormatException e) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Validates whether input is a float number. You should use shared instance {@link Validators#FLOATS}. */\n\tpublic static class FloatValidator implements InputValidator {\n\t\t@Override\n\t\tpublic boolean validateInput (String input) {\n\t\t\ttry {\n\t\t\t\tFloat.parseFloat(input);\n\t\t\t\treturn true;\n\t\t\t} catch (NumberFormatException e) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Validates whether input is lesser (alternatively lesser or equal) than provided number. */\n\tpublic static class LesserThanValidator implements InputValidator {\n\t\tprivate float lesserThan;\n\t\tprivate boolean equals;\n\n\t\tpublic LesserThanValidator (float lesserThan) {\n\t\t\tthis.lesserThan = lesserThan;\n\t\t}\n\n\t\t/** @param inputCanBeEqual if true &lt;= comparison will be used, if false &lt; will be used. */\n\t\tpublic LesserThanValidator (float lesserThan, boolean inputCanBeEqual) {\n\t\t\tthis.lesserThan = lesserThan;\n\t\t\tthis.equals = inputCanBeEqual;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean validateInput (String input) {\n\t\t\ttry {\n\t\t\t\tfloat value = Float.valueOf(input);\n\t\t\t\treturn equals ? value <= lesserThan : value < lesserThan;\n\t\t\t} catch (NumberFormatException ex) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t/*** @param equals if true &lt;= comparison will be used, if false &lt; will be used. */\n\t\tpublic void setUseEquals (boolean equals) {\n\t\t\tthis.equals = equals;\n\t\t}\n\n\t\tpublic void setLesserThan (float lesserThan) {\n\t\t\tthis.lesserThan = lesserThan;\n\t\t}\n\t}\n\n\t/** Validates whether input is greater (alternatively greater or equal) than provided number. */\n\tpublic static class GreaterThanValidator implements InputValidator {\n\t\tprivate float greaterThan;\n\t\tprivate boolean useEquals;\n\n\t\tpublic GreaterThanValidator (float greaterThan) {\n\t\t\tthis.greaterThan = greaterThan;\n\t\t}\n\n\t\t/** @param inputCanBeEqual if true &gt;= comparison will be used, if false &gt; will be used. */\n\t\tpublic GreaterThanValidator (float greaterThan, boolean inputCanBeEqual) {\n\t\t\tthis.greaterThan = greaterThan;\n\t\t\tthis.useEquals = inputCanBeEqual;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean validateInput (String input) {\n\t\t\ttry {\n\t\t\t\tfloat value = Float.valueOf(input);\n\t\t\t\treturn useEquals ? value >= greaterThan : value > greaterThan;\n\t\t\t} catch (NumberFormatException ex) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t/*** @param useEquals if true &gt;= comparison will be used, if false &gt; will be used. */\n\t\tpublic void setUseEquals (boolean useEquals) {\n\t\t\tthis.useEquals = useEquals;\n\t\t}\n\n\t\tpublic void setGreaterThan (float greaterThan) {\n\t\t\tthis.greaterThan = greaterThan;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/adapter/AbstractListAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.adapter;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.Input.Keys;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.EventListener;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.UIUtils;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.widget.ListView;\nimport com.kotcrab.vis.ui.widget.ListView.ItemClickListener;\nimport com.kotcrab.vis.ui.widget.ListView.ListAdapterListener;\nimport com.kotcrab.vis.ui.widget.VisTable;\n\nimport java.util.Comparator;\n\n/**\n * Basic {@link ListAdapter} implementation using {@link CachedItemAdapter}. Supports item selection. Classes\n * extending this should store provided list and provide delegates for all common methods that change array state.\n * Those delegates should call {@link #itemAdded(Object)} or {@link #itemRemoved(Object)} in order to properly update\n * view cache. When changes to array are too big to be handled by those two methods {@link #itemsChanged()} should be\n * called. When only items fields has changed, and no new item were added or removed you should call\n * {@link #itemsDataChanged()}.\n * <p>\n * When view does not existed in cache and must be created {@link #createView(Object)} is called. When item view exists\n * in cache {@link #updateView(Actor, Object)} will be called.\n * <p>\n * Enabling item selection requires calling {@link #setSelectionMode(SelectionMode)} and overriding\n * {@link #selectView(Actor)} and {@link #deselectView(Actor)}.\n * @author Kotcrab\n * @see ArrayAdapter\n * @see ArrayListAdapter\n * @since 1.0.0\n */\npublic abstract class AbstractListAdapter<ItemT, ViewT extends Actor> extends CachedItemAdapter<ItemT, ViewT>\n\t\timplements ListAdapter<ItemT> {\n\tprotected ListView<ItemT> view;\n\tprotected ListAdapterListener viewListener;\n\n\tprivate ItemClickListener<ItemT> clickListener;\n\n\tprivate SelectionMode selectionMode = SelectionMode.DISABLED;\n\tprivate ListSelection<ItemT, ViewT> selection = new ListSelection<ItemT, ViewT>(this);\n\n\tprivate Comparator<ItemT> itemsComparator;\n\n\t@Override\n\tpublic void fillTable (VisTable itemsTable) {\n\t\tif (itemsComparator != null) sort(itemsComparator);\n\t\tfor (final ItemT item : iterable()) {\n\t\t\tfinal ViewT view = getView(item);\n\t\t\tprepareViewBeforeAddingToTable(item, view);\n\t\t\titemsTable.add(view).growX();\n\t\t\titemsTable.row();\n\t\t}\n\t}\n\n\tprotected void prepareViewBeforeAddingToTable (ItemT item, ViewT view) {\n\t\tboolean listenerMissing = true;\n\t\tfor (EventListener listener : view.getListeners()) {\n\t\t\tif (listener instanceof AbstractListAdapter.ListClickListener) {\n\t\t\t\tlistenerMissing = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (listenerMissing) {\n\t\t\tview.setTouchable(Touchable.enabled);\n\t\t\tview.addListener(new ListClickListener(view, item));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setListView (ListView<ItemT> view, ListAdapterListener viewListener) {\n\t\tif (this.view != null) throw new IllegalStateException(\"Adapter was already assigned to ListView\");\n\t\tthis.view = view;\n\t\tthis.viewListener = viewListener;\n\t}\n\n\t@Override\n\tpublic void setItemClickListener (ItemClickListener<ItemT> listener) {\n\t\tclickListener = listener;\n\t}\n\n\tprotected void itemAdded (ItemT item) {\n\t\tviewListener.invalidateDataSet();\n\t}\n\n\tprotected void itemRemoved (ItemT item) {\n\t\tselection.deselect(item);\n\t\tgetViews().remove(item);\n\t\tviewListener.invalidateDataSet();\n\t}\n\n\t/**\n\t * Notifies adapter that underlying collection has changed, ie. some items were added or removed. This does not need to\n\t * be called when only the fields of stored objects changed see {@link #itemsDataChanged()}.\n\t * <p>\n\t * WARNING: When using {@link ListView.UpdatePolicy#MANUAL} this won't cause to rebuild {@link ListView}. This method\n\t * only notifies ListView that it needs rebuilding however when using {@link ListView.UpdatePolicy#MANUAL} mode it\n\t * will be ignored.\n\t */\n\tpublic void itemsChanged () {\n\t\tselection.deselectAll();\n\t\tgetViews().clear();\n\t\tviewListener.invalidateDataSet();\n\t}\n\n\t/**\n\t * Notifies adapter that data of items has changed. This means that objects fields in underlying collection has changed\n\t * and views needs updating. This must not be called if some items were removed or added from collection for that\n\t * {@link #itemsChanged()}\n\t * <p>\n\t * WARNING: When using {@link ListView.UpdatePolicy#MANUAL} this won't cause to rebuild {@link ListView}. This method\n\t * only notifies ListView that it needs rebuilding however when using {@link ListView.UpdatePolicy#MANUAL} mode it\n\t * will be ignored.\n\t */\n\tpublic void itemsDataChanged () {\n\t\tviewListener.invalidateDataSet();\n\t}\n\n\t@Override\n\tprotected void updateView (ViewT view, ItemT item) {\n\n\t}\n\n\tpublic SelectionMode getSelectionMode () {\n\t\treturn selectionMode;\n\t}\n\n\tpublic void setSelectionMode (SelectionMode selectionMode) {\n\t\tif (selectionMode == null) throw new IllegalArgumentException(\"selectionMode can't be null\");\n\t\tthis.selectionMode = selectionMode;\n\t}\n\n\t/**\n\t * Sets items comparator allowing to define order in which items will be displayed in list view. This will sort\n\t * underlying array before building views.\n\t * @param comparator that will be used to compare items\n\t */\n\tpublic void setItemsSorter (Comparator<ItemT> comparator) {\n\t\tthis.itemsComparator = comparator;\n\t}\n\n\tpublic Comparator<ItemT> getItemsSorter () {\n\t\treturn itemsComparator;\n\t}\n\n\t/** @return selected items, must not be modified */\n\tpublic Array<ItemT> getSelection () {\n\t\treturn selection.getSelection();\n\t}\n\n\tpublic ListSelection<ItemT, ViewT> getSelectionManager () {\n\t\treturn selection;\n\t}\n\n\tprotected void selectView (ViewT view) {\n\t\tif (selectionMode == SelectionMode.DISABLED) return;\n\t\tthrow new UnsupportedOperationException(\"selectView must be implemented when `selectionMode` is different than SelectionMode.DISABLED\");\n\t}\n\n\tprotected void deselectView (ViewT view) {\n\t\tif (selectionMode == SelectionMode.DISABLED) return;\n\t\tthrow new UnsupportedOperationException(\"deselectView must be implemented when `selectionMode` is different than SelectionMode.DISABLED\");\n\t}\n\n\tprivate class ListClickListener extends ClickListener {\n\t\tprivate ViewT view;\n\t\tprivate ItemT item;\n\n\t\tpublic ListClickListener (ViewT view, ItemT item) {\n\t\t\tthis.view = view;\n\t\t\tthis.item = item;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\tsuper.touchDown(event, x, y, pointer, button);\n\t\t\tselection.touchDown(view, item);\n\t\t\treturn true;\n\t\t}\n\n\t\t@Override\n\t\tpublic void clicked (InputEvent event, float x, float y) {\n\t\t\tif (clickListener != null) clickListener.clicked(item);\n\t\t}\n\t}\n\n\tprotected abstract void sort (Comparator<ItemT> comparator);\n\n\tpublic enum SelectionMode {\n\t\t/** Selecting items is not possible. */\n\t\tDISABLED,\n\t\t/**\n\t\t * Only one element can be selected. {@link AbstractListAdapter#selectView(Actor)} and\n\t\t * {@link AbstractListAdapter#deselectView(Actor)} must be implemented.\n\t\t */\n\t\tSINGLE,\n\t\t/**\n\t\t * Multiple elements can be selected. {@link AbstractListAdapter#selectView(Actor)} and\n\t\t * {@link AbstractListAdapter#deselectView(Actor)} must be implemented.\n\t\t */\n\t\tMULTIPLE\n\t}\n\n\t/**\n\t * Manages selection of {@link AbstractListAdapter} items.\n\t * @author Kotcrab\n\t */\n\tpublic static class ListSelection<ItemT, ViewT extends Actor> {\n\t\tprivate AbstractListAdapter<ItemT, ViewT> adapter;\n\n\t\tpublic static final int DEFAULT_KEY = -1;\n\t\tprivate int groupMultiSelectKey = DEFAULT_KEY; //shift by default\n\t\tprivate int multiSelectKey = DEFAULT_KEY; //ctrl (or command on mac) by default\n\n\t\tprivate Array<ItemT> selection = new Array<ItemT>();\n\n\t\tprivate boolean programmaticChangeEvents = true;\n\t\tprivate ListSelectionListener<ItemT, ViewT> listener = new ListSelectionAdapter<ItemT, ViewT>();\n\n\t\tprivate ListSelection (AbstractListAdapter<ItemT, ViewT> adapter) {\n\t\t\tthis.adapter = adapter;\n\t\t}\n\n\t\tpublic void select (ItemT item) {\n\t\t\tselect(item, adapter.getViews().get(item), true);\n\t\t}\n\n\t\tvoid select (ItemT item, ViewT view, boolean programmaticChange) {\n\t\t\tif (adapter.getSelectionMode() == SelectionMode.DISABLED) return;\n\t\t\tif (adapter.getSelectionMode() == SelectionMode.SINGLE) deselectAll(programmaticChange);\n\t\t\tif (adapter.getSelectionMode() == SelectionMode.MULTIPLE && selection.size >= 1 && isGroupMultiSelectKeyPressed()) {\n\t\t\t\tselectGroup(item);\n\t\t\t}\n\n\t\t\tdoSelect(item, view, programmaticChange);\n\t\t}\n\n\t\tprivate void doSelect (ItemT item, ViewT view, boolean programmaticChange) {\n\t\t\tif (selection.contains(item, true) == false) {\n\t\t\t\tadapter.selectView(view);\n\t\t\t\tselection.add(item);\n\t\t\t\tif (programmaticChange == false || programmaticChangeEvents) listener.selected(item, view);\n\t\t\t}\n\t\t}\n\n\t\tpublic void deselect (ItemT item) {\n\t\t\tdeselect(item, adapter.getViews().get(item), true);\n\t\t}\n\n\t\tpublic void deselectAll () {\n\t\t\tdeselectAll(true);\n\t\t}\n\n\t\tprivate void selectGroup (ItemT newItem) {\n\t\t\tint thisSelectionIndex = adapter.indexOf(newItem);\n\t\t\tint lastSelectionIndex = adapter.indexOf(selection.peek());\n\n\t\t\tif (lastSelectionIndex == -1) return;\n\n\t\t\tint start;\n\t\t\tint end;\n\n\t\t\tif (thisSelectionIndex > lastSelectionIndex) {\n\t\t\t\tstart = lastSelectionIndex;\n\t\t\t\tend = thisSelectionIndex;\n\t\t\t} else {\n\t\t\t\tstart = thisSelectionIndex;\n\t\t\t\tend = lastSelectionIndex;\n\t\t\t}\n\n\t\t\tfor (int i = start; i < end; i++) {\n\t\t\t\tItemT item = adapter.get(i);\n\t\t\t\tdoSelect(item, adapter.getViews().get(item), false);\n\t\t\t}\n\t\t}\n\n\t\tvoid deselect (ItemT item, ViewT view, boolean programmaticChange) {\n\t\t\tif (selection.contains(item, true) == false) return;\n\t\t\tadapter.deselectView(view);\n\t\t\tselection.removeValue(item, true);\n\t\t\tif (programmaticChange == false || programmaticChangeEvents) listener.deselected(item, view);\n\t\t}\n\n\t\tvoid deselectAll (boolean programmaticChange) {\n\t\t\tArray<ItemT> items = new Array<ItemT>(selection);\n\t\t\tfor (ItemT item : items) {\n\t\t\t\tdeselect(item, adapter.getViews().get(item), programmaticChange);\n\t\t\t}\n\t\t}\n\n\t\t/** @return internal array, MUST NOT be modified directly */\n\t\tpublic Array<ItemT> getSelection () {\n\t\t\treturn selection;\n\t\t}\n\n\t\tvoid touchDown (ViewT view, ItemT item) {\n\t\t\tif (adapter.getSelectionMode() == SelectionMode.DISABLED) return;\n\n\t\t\tif (isMultiSelectKeyPressed() == false && isGroupMultiSelectKeyPressed() == false) {\n\t\t\t\tdeselectAll(false);\n\t\t\t}\n\n\t\t\tif (selection.contains(item, true) == false) {\n\t\t\t\tselect(item, view, false);\n\t\t\t} else {\n\t\t\t\tdeselect(item, view, false);\n\t\t\t}\n\t\t}\n\n\t\tpublic int getMultiSelectKey () {\n\t\t\treturn multiSelectKey;\n\t\t}\n\n\t\t/** @param multiSelectKey from {@link Keys} or {@link ListSelection#DEFAULT_KEY} to restore default */\n\t\tpublic void setMultiSelectKey (int multiSelectKey) {\n\t\t\tthis.multiSelectKey = multiSelectKey;\n\t\t}\n\n\t\tpublic int getGroupMultiSelectKey () {\n\t\t\treturn groupMultiSelectKey;\n\t\t}\n\n\t\t/** @param groupMultiSelectKey from {@link Keys} or {@link ListSelection#DEFAULT_KEY} to restore default */\n\t\tpublic void setGroupMultiSelectKey (int groupMultiSelectKey) {\n\t\t\tthis.groupMultiSelectKey = groupMultiSelectKey;\n\t\t}\n\n\t\tpublic void setListener (ListSelectionListener<ItemT, ViewT> listener) {\n\t\t\tif (listener == null) listener = new ListSelectionAdapter<ItemT, ViewT>();\n\t\t\tthis.listener = listener;\n\t\t}\n\n\t\tpublic ListSelectionListener<ItemT, ViewT> getListener () {\n\t\t\treturn listener;\n\t\t}\n\n\t\tpublic boolean isProgrammaticChangeEvents () {\n\t\t\treturn programmaticChangeEvents;\n\t\t}\n\n\t\tpublic void setProgrammaticChangeEvents (boolean programmaticChangeEvents) {\n\t\t\tthis.programmaticChangeEvents = programmaticChangeEvents;\n\t\t}\n\n\t\tprivate boolean isMultiSelectKeyPressed () {\n\t\t\tif (multiSelectKey == DEFAULT_KEY)\n\t\t\t\treturn UIUtils.ctrl();\n\t\t\telse\n\t\t\t\treturn Gdx.input.isKeyPressed(multiSelectKey);\n\t\t}\n\n\t\tprivate boolean isGroupMultiSelectKeyPressed () {\n\t\t\tif (groupMultiSelectKey == DEFAULT_KEY)\n\t\t\t\treturn UIUtils.shift();\n\t\t\telse\n\t\t\t\treturn Gdx.input.isKeyPressed(groupMultiSelectKey);\n\t\t}\n\t}\n\n\tpublic interface ListSelectionListener<ItemT, ViewT> {\n\t\tvoid selected (ItemT item, ViewT view);\n\n\t\tvoid deselected (ItemT item, ViewT view);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/adapter/ArrayAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.adapter;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.utils.Array;\n\nimport java.util.Comparator;\n\n/**\n * Built-in adapter implementation for {@link Array}.\n * @author Kotcrab\n * @since 1.0.0\n */\npublic abstract class ArrayAdapter<ItemT, ViewT extends Actor> extends AbstractListAdapter<ItemT, ViewT> {\n\tprivate Array<ItemT> array;\n\n\tpublic ArrayAdapter (Array<ItemT> array) {\n\t\tthis.array = array;\n\t}\n\n\t@Override\n\tpublic int indexOf (ItemT item) {\n\t\treturn array.indexOf(item, true);\n\t}\n\n\t@Override\n\tpublic int size () {\n\t\treturn array.size;\n\t}\n\n\t@Override\n\tpublic ItemT get (int index) {\n\t\treturn array.get(index);\n\t}\n\n\t@Override\n\tpublic void add (ItemT element) {\n\t\tarray.add(element);\n\t\titemAdded(element);\n\t}\n\n\t@Override\n\tprotected void sort (Comparator<ItemT> comparator) {\n\t\tarray.sort(comparator);\n\t}\n\n\t@Override\n\tpublic Iterable<ItemT> iterable () {\n\t\treturn array;\n\t}\n\n\t//Delegates\n\n\tpublic void addAll (Array<? extends ItemT> array) {\n\t\tthis.array.addAll(array);\n\t\titemsChanged();\n\t}\n\n\tpublic void addAll (Array<? extends ItemT> array, int start, int count) {\n\t\tthis.array.addAll(array, start, count);\n\t\titemsChanged();\n\t}\n\n\tpublic void addAll (ItemT... array) {\n\t\tthis.array.addAll(array);\n\t\titemsChanged();\n\t}\n\n\tpublic void addAll (ItemT[] array, int start, int count) {\n\t\tthis.array.addAll(array, start, count);\n\t\titemsChanged();\n\t}\n\n\tpublic void set (int index, ItemT value) {\n\t\tarray.set(index, value);\n\t\titemsChanged();\n\t}\n\n\tpublic void insert (int index, ItemT value) {\n\t\tarray.insert(index, value);\n\t\titemsChanged();\n\t}\n\n\tpublic void swap (int first, int second) {\n\t\tarray.swap(first, second);\n\t\titemsChanged();\n\t}\n\n\tpublic boolean removeValue (ItemT value, boolean identity) {\n\t\tboolean res = array.removeValue(value, identity);\n\t\tif (res) itemRemoved(value);\n\t\treturn res;\n\t}\n\n\tpublic ItemT removeIndex (int index) {\n\t\tItemT item = array.removeIndex(index);\n\t\tif (item != null) itemRemoved(item);\n\t\treturn item;\n\t}\n\n\tpublic void removeRange (int start, int end) {\n\t\tarray.removeRange(start, end);\n\t\titemsChanged();\n\t}\n\n\tpublic boolean removeAll (Array<? extends ItemT> array, boolean identity) {\n\t\tboolean res = this.array.removeAll(array, identity);\n\t\titemsChanged();\n\t\treturn res;\n\t}\n\n\tpublic void clear () {\n\t\tarray.clear();\n\t\titemsChanged();\n\t}\n\n\tpublic void shuffle () {\n\t\tarray.shuffle();\n\t\titemsChanged();\n\t}\n\n\tpublic void reverse () {\n\t\tarray.reverse();\n\t\titemsChanged();\n\t}\n\n\tpublic ItemT pop () {\n\t\tItemT item = array.pop();\n\t\titemsChanged();\n\t\treturn item;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/adapter/ArrayListAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.adapter;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Comparator;\n\n/**\n * Built-in adapter implementation for {@link ArrayList}.\n * @author Kotcrab\n * @since 1.0.0\n */\npublic abstract class ArrayListAdapter<ItemT, ViewT extends Actor> extends AbstractListAdapter<ItemT, ViewT> {\n\tprivate ArrayList<ItemT> array;\n\n\tpublic ArrayListAdapter (ArrayList<ItemT> array) {\n\t\tthis.array = array;\n\t}\n\n\t@Override\n\tpublic Iterable<ItemT> iterable () {\n\t\treturn array;\n\t}\n\n\t@Override\n\tpublic int size () {\n\t\treturn array.size();\n\t}\n\n\t@Override\n\tpublic int indexOf (ItemT item) {\n\t\treturn array.indexOf(item);\n\t}\n\n\t@Override\n\tpublic void add (ItemT element) {\n\t\tarray.add(element);\n\t\titemAdded(element);\n\t}\n\n\t@Override\n\tpublic ItemT get (int index) {\n\t\treturn array.get(index);\n\t}\n\n\t@Override\n\tprotected void sort (Comparator<ItemT> comparator) {\n\t\tCollections.sort(array, comparator);\n\t}\n\n\t// Delegates\n\n\tpublic ItemT set (int index, ItemT element) {\n\t\tItemT res = array.set(index, element);\n\t\titemsChanged();\n\t\treturn res;\n\t}\n\n\tpublic void add (int index, ItemT element) {\n\t\tarray.add(index, element);\n\t\titemAdded(element);\n\t}\n\n\tpublic ItemT remove (int index) {\n\t\tItemT res = array.remove(index);\n\t\tif (res != null) itemRemoved(res);\n\t\treturn res;\n\t}\n\n\tpublic boolean remove (ItemT item) {\n\t\tboolean res = array.remove(item);\n\t\tif (res) itemRemoved(item);\n\t\treturn res;\n\t}\n\n\tpublic void clear () {\n\t\tarray.clear();\n\t\titemsChanged();\n\t}\n\n\tpublic boolean addAll (Collection<? extends ItemT> c) {\n\t\tboolean res = array.addAll(c);\n\t\titemsChanged();\n\t\treturn res;\n\t}\n\n\tpublic boolean addAll (int index, Collection<? extends ItemT> c) {\n\t\tboolean res = array.addAll(index, c);\n\t\titemsChanged();\n\t\treturn res;\n\t}\n\n\tpublic boolean removeAll (Collection<?> c) {\n\t\tboolean res = array.removeAll(c);\n\t\titemsChanged();\n\t\treturn res;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/adapter/CachedItemAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.adapter;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.utils.ObjectMap;\n\n/**\n * Implementation of {@link ItemAdapter} that caches created views. Provides two methods that are called when new view\n * should be created and when old view should be updated (see {@link #createView(Object)} and {@link #updateView(Actor, Object)}).\n * Internal cache is not cleared automatically and obsolete entries must be removed manually.\n * @author Kotcrab\n * @since 1.0.0\n */\npublic abstract class CachedItemAdapter<ItemT, ViewT extends Actor> implements ItemAdapter<ItemT> {\n\tprivate ObjectMap<ItemT, ViewT> views = new ObjectMap<ItemT, ViewT>();\n\n\t@Override\n\tpublic final ViewT getView (ItemT item) {\n\t\tViewT view = views.get(item);\n\n\t\tif (view == null) {\n\t\t\tview = createView(item);\n\t\t\tif (view == null) throw new IllegalStateException(\"Returned view view can't be null\");\n\t\t\tviews.put(item, view);\n\t\t} else {\n\t\t\tupdateView(view, item);\n\t\t}\n\n\t\treturn view;\n\t}\n\n\t/** @return internal views cache map */\n\tprotected ObjectMap<ItemT, ViewT> getViews () {\n\t\treturn views;\n\t}\n\n\tprotected abstract ViewT createView (ItemT item);\n\n\tprotected abstract void updateView (ViewT view, ItemT item);\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/adapter/ItemAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.adapter;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\n\n/**\n * Generic use adapter used to create views for given objects.\n * @author Kotcrab\n * @since 1.0.0\n */\npublic interface ItemAdapter<ItemT> {\n\tActor getView (ItemT item);\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/adapter/ListAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.adapter;\n\nimport com.kotcrab.vis.ui.widget.ListView;\nimport com.kotcrab.vis.ui.widget.ListView.ItemClickListener;\nimport com.kotcrab.vis.ui.widget.ListView.ListAdapterListener;\nimport com.kotcrab.vis.ui.widget.VisTable;\n\n/**\n * Adapter used to display items list in {@link ListView}. Classes implementing this interface should store array and\n * provide delegates to methods that change array state, such as add/remove etc. Those delegates should call\n * {@link ListAdapterListener#invalidateDataSet()}. Single instance of ListAdapter can only be used for one ListView.\n * Implementations must support setting item click listener.\n * @author Kotcrab\n * @see ArrayAdapter\n * @see ArrayListAdapter\n * @since 1.0.0\n */\npublic interface ListAdapter<ItemT> {\n\t/** Called by {@link ListView} when this adapter is assigned to it. */\n\tvoid setListView (ListView<ItemT> view, ListAdapterListener viewListener);\n\n\t/** Called by {@link ListView} when this adapter should create and add all views to provided itemsTable. */\n\tvoid fillTable (VisTable itemsTable);\n\n\t/** Called by {@link ListView} when it's item click listener changed. */\n\tvoid setItemClickListener (ItemClickListener<ItemT> listener);\n\n\t/** @return iterable for internal collection */\n\tIterable<ItemT> iterable ();\n\n\t/** @return size of internal collection */\n\tint size ();\n\n\t/** @return index of element in internal collection */\n\tint indexOf (ItemT item);\n\n\t/** Adds item to internal collection */\n\tvoid add (ItemT item);\n\n\t/** @return element for given index */\n\tItemT get (int index);\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/adapter/ListSelectionAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.adapter;\n\nimport com.kotcrab.vis.ui.util.adapter.AbstractListAdapter.ListSelectionListener;\n\n/**\n * Empty {@link ListSelectionListener} implementation.\n * @author Kotcrab\n */\npublic class ListSelectionAdapter<ItemT, ViewT> implements ListSelectionListener<ItemT, ViewT> {\n\t@Override\n\tpublic void selected (ItemT item, ViewT view) {\n\n\t}\n\n\t@Override\n\tpublic void deselected (ItemT item, ViewT view) {\n\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/adapter/SimpleListAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.adapter;\n\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.widget.ListView;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisTable;\n\n/**\n * Very simple default implementation of adapter for {@link ListView}. Uses {@link Object#toString()} to create text\n * view for item.\n * @author Kotcrab\n */\npublic class SimpleListAdapter<ItemT> extends ArrayAdapter<ItemT, VisTable> {\n\tprivate final SimpleListAdapterStyle style;\n\n\tpublic SimpleListAdapter (Array<ItemT> array) {\n\t\tthis(array, \"default\");\n\t}\n\n\tpublic SimpleListAdapter (Array<ItemT> array, String styleName) {\n\t\tthis(array, VisUI.getSkin().get(styleName, SimpleListAdapterStyle.class));\n\t}\n\n\tpublic SimpleListAdapter (Array<ItemT> array, SimpleListAdapterStyle style) {\n\t\tsuper(array);\n\t\tthis.style = style;\n\t}\n\n\t@Override\n\tprotected VisTable createView (ItemT item) {\n\t\tVisTable table = new VisTable();\n\t\ttable.left();\n\t\ttable.add(new VisLabel(item.toString()));\n\t\treturn table;\n\t}\n\n\t@Override\n\tprotected void selectView (VisTable view) {\n\t\tview.setBackground(style.selection);\n\t}\n\n\t@Override\n\tprotected void deselectView (VisTable view) {\n\t\tview.setBackground(style.background);\n\t}\n\n\tpublic static class SimpleListAdapterStyle {\n\t\tpublic Drawable background;\n\t\tpublic Drawable selection;\n\n\t\tpublic SimpleListAdapterStyle () {\n\t\t}\n\n\t\tpublic SimpleListAdapterStyle (Drawable background, Drawable selection) {\n\t\t\tthis.background = background;\n\t\t\tthis.selection = selection;\n\t\t}\n\n\t\tpublic SimpleListAdapterStyle (SimpleListAdapterStyle style) {\n\t\t\tthis.background = style.background;\n\t\t\tthis.selection = style.selection;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/async/AsyncTask.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.async;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.utils.Array;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicReference;\n\n/**\n * Represents task that is executed asynchronously in another thread. AsyncTask and related classes are not available\n * on GWT.\n * @author Kotcrab\n * @see AsyncTaskListener\n * @see SteppedAsyncTask\n * @see AsyncTaskProgressDialog\n */\npublic abstract class AsyncTask {\n\tprivate String threadName;\n\tprivate Status status = Status.PENDING;\n\tprivate Array<AsyncTaskListener> listeners = new Array<AsyncTaskListener>();\n\n\tpublic AsyncTask (String threadName) {\n\t\tthis.threadName = threadName;\n\t}\n\n\tpublic void execute () {\n\t\tif (status == Status.RUNNING) throw new IllegalStateException(\"Task is already running.\");\n\t\tif (status == Status.FINISHED)\n\t\t\tthrow new IllegalStateException(\"Task has been already executed and can't be reused.\");\n\t\tstatus = Status.RUNNING;\n\t\tnew Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run () {\n\t\t\t\texecuteInBackground();\n\t\t\t}\n\t\t}, threadName).start();\n\t}\n\n\tprivate void executeInBackground () {\n\t\ttry {\n\t\t\tdoInBackground();\n\t\t} catch (Exception e) {\n\t\t\tfailed(e);\n\t\t}\n\n\t\tGdx.app.postRunnable(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run () {\n\t\t\t\tfor (AsyncTaskListener listener : listeners) {\n\t\t\t\t\tlistener.finished();\n\t\t\t\t}\n\t\t\t\tstatus = Status.FINISHED;\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Called when this task should execute some action in background. This is always called from non-main thread.\n\t * From this method only {@link #setProgressPercent(int)}, {@link #setMessage(String)}, {@link #failed(String)},\n\t * {@link #failed(Exception)}, {@link #failed(String, Exception)} should be called.\n\t */\n\tprotected abstract void doInBackground () throws Exception;\n\n\tprotected void failed (String message) {\n\t\tfailed(message, new IllegalStateException(message));\n\t}\n\n\tprotected void failed (Exception exception) {\n\t\tfailed(exception.getMessage(), exception);\n\t}\n\n\tprotected void failed (final String message, final Exception exception) {\n\t\tGdx.app.postRunnable(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run () {\n\t\t\t\tfor (AsyncTaskListener listener : listeners) {\n\t\t\t\t\tlistener.failed(message, exception);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tprotected void setProgressPercent (final int progressPercent) {\n\t\tGdx.app.postRunnable(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run () {\n\t\t\t\tfor (AsyncTaskListener listener : listeners) {\n\t\t\t\t\tlistener.progressChanged(progressPercent);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tprotected void setMessage (final String message) {\n\t\tGdx.app.postRunnable(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run () {\n\t\t\t\tfor (AsyncTaskListener listener : listeners) {\n\t\t\t\t\tlistener.messageChanged(message);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Executes runnable on main GDX thread. This methods blocks until runnable has finished executing. Note that this\n\t * runnable will also block main render thread.\n\t */\n\tprotected void executeOnGdx (final Runnable runnable) {\n\t\tfinal CountDownLatch latch = new CountDownLatch(1);\n\n\t\tfinal AtomicReference<Exception> exceptionAt = new AtomicReference<Exception>();\n\n\t\tGdx.app.postRunnable(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run () {\n\t\t\t\ttry {\n\t\t\t\t\trunnable.run();\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\texceptionAt.set(e);\n\t\t\t\t} finally {\n\t\t\t\t\tlatch.countDown();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\ttry {\n\t\t\tlatch.await();\n\n\t\t\tfinal Exception e = exceptionAt.get();\n\t\t\tif (e != null) {\n\t\t\t\tfailed(e);\n\t\t\t}\n\t\t} catch (InterruptedException e) {\n\t\t\tfailed(e);\n\t\t}\n\t}\n\n\tpublic void addListener (AsyncTaskListener listener) {\n\t\tlisteners.add(listener);\n\t}\n\n\tpublic boolean removeListener (AsyncTaskListener listener) {\n\t\treturn listeners.removeValue(listener, true);\n\t}\n\n\tpublic String getThreadName () {\n\t\treturn threadName;\n\t}\n\n\tpublic Status getStatus () {\n\t\treturn status;\n\t}\n\n\tenum Status {\n\t\tPENDING, RUNNING, FINISHED\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/async/AsyncTaskListener.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.async;\n\n/**\n * Allows to listen to events occurring in {@link AsyncTask}.\n * @author Kotcrab\n */\npublic interface AsyncTaskListener {\n\t/** Called when task status message has changed. */\n\tvoid messageChanged (String message);\n\n\t/** Called when task progress has changed. */\n\tvoid progressChanged (int newProgressPercent);\n\n\t/**\n\t * Called when task has finished executing. Finished will always called, even if some exception occurred during task\n\t * execution.\n\t */\n\tvoid finished ();\n\n\t/** Called when some error occurred during task execution. */\n\tvoid failed (String message, Exception exception);\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/async/AsyncTaskProgressDialog.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.async;\n\nimport com.kotcrab.vis.ui.Locales.CommonText;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.util.async.AsyncTask.Status;\nimport com.kotcrab.vis.ui.util.dialog.Dialogs;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisProgressBar;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\n/**\n * Dialog used to display progress of {@link AsyncTask} as standard VisUI window. Shows progress bar and status\n * of currently executed task.\n * @author Kotcrab\n */\npublic class AsyncTaskProgressDialog extends VisWindow {\n\tprivate AsyncTask task;\n\n\t/**\n\t * Creates new dialog, note that task will be automatically started. Created dialog must be manually added to stage,\n\t * preferably with {@link VisWindow#fadeIn()} animation.\n\t * @param title title used as window title\n\t * @param task task to be executed\n\t */\n\tpublic AsyncTaskProgressDialog (String title, AsyncTask task) {\n\t\tsuper(title);\n\t\tthis.task = task;\n\t\tsetModal(true);\n\n\t\tTableUtils.setSpacingDefaults(this);\n\n\t\tfinal VisLabel statusLabel = new VisLabel(CommonText.PLEASE_WAIT.get());\n\t\tfinal VisProgressBar progressBar = new VisProgressBar(0, 100, 1, false);\n\n\t\tdefaults().padLeft(6).padRight(6);\n\n\t\tadd(statusLabel).padTop(6).left().row();\n\t\tadd(progressBar).width(300).padTop(6).padBottom(6);\n\n\t\ttask.addListener(new AsyncTaskListener() {\n\t\t\t@Override\n\t\t\tpublic void progressChanged (int newProgressPercent) {\n\t\t\t\tprogressBar.setValue(newProgressPercent);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void messageChanged (String message) {\n\t\t\t\tstatusLabel.setText(message);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void finished () {\n\t\t\t\tfadeOut();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void failed (String message, Exception exception) {\n\t\t\t\tDialogs.showErrorDialog(getStage(), exception.getMessage() == null ? CommonText.UNKNOWN_ERROR_OCCURRED.get() : exception.getMessage(), exception);\n\t\t\t}\n\t\t});\n\n\t\tpack();\n\t\tcenterWindow();\n\n\t\ttask.execute();\n\t}\n\n\tpublic AsyncTask getTask () {\n\t\treturn task;\n\t}\n\n\tpublic void addListener (AsyncTaskListener listener) {\n\t\ttask.addListener(listener);\n\t}\n\n\tpublic Status getStatus () {\n\t\treturn task.getStatus();\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/async/SteppedAsyncTask.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.async;\n\n/**\n * {@link AsyncTask} that performs fixed numbers of steps, provides convenient methods to calculate and update task progress.\n * @author Kotcrab\n */\npublic abstract class SteppedAsyncTask extends AsyncTask {\n\tprivate int step;\n\tprivate int totalSteps;\n\n\tpublic SteppedAsyncTask (String threadName) {\n\t\tsuper(threadName);\n\t}\n\n\t/**\n\t * Sets total numbers ot steps this task will have to perform, usually called at the beginning of {@link #doInBackground()}.\n\t * @see #nextStep()\n\t */\n\tprotected void setTotalSteps (int totalSteps) {\n\t\tthis.totalSteps = totalSteps;\n\t\tthis.step = 0;\n\t\tsetProgressPercent(0);\n\t}\n\n\t/** Advances task to next step and updates its percent progress. */\n\tprotected void nextStep () {\n\t\tsetProgressPercent(++step * 100 / totalSteps);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/dialog/ConfirmDialogListener.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.dialog;\n\n/**\n * Used to get events from {@link Dialogs} confirm dialog.\n * @author Kotcrab\n */\npublic interface ConfirmDialogListener<T> {\n\t/** Called when dialog button was pressed, type of results is generic and depends on created dialog. */\n\tvoid result (T result);\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/dialog/Dialogs.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.dialog;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.Input.Keys;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.Stage;\nimport com.badlogic.gdx.scenes.scene2d.ui.Cell;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.utils.Align;\nimport com.badlogic.gdx.utils.CharArray;\nimport com.badlogic.gdx.utils.I18NBundle;\nimport com.kotcrab.vis.ui.Locales;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.i18n.BundleText;\nimport com.kotcrab.vis.ui.util.InputValidator;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.util.Validators;\nimport com.kotcrab.vis.ui.widget.*;\nimport com.kotcrab.vis.ui.widget.ButtonBar.ButtonType;\n\n/**\n * Utilities for displaying various type of dialogs. Equivalent of JOptionPane from Swing.\n * @author Kotcrab\n * @since 0.2.0\n */\npublic class Dialogs {\n\tprivate static final int BUTTON_OK = 1;\n\tprivate static final int BUTTON_DETAILS = 2;\n\n\t/**\n\t * Dialog with given text and single OK button.\n\t * @param title dialog title\n\t */\n\tpublic static VisDialog showOKDialog (Stage stage, String title, String text) {\n\t\tfinal VisDialog dialog = new VisDialog(title);\n\t\tdialog.closeOnEscape();\n\t\tdialog.text(text);\n\t\tdialog.button(ButtonType.OK.getText()).padBottom(3);\n\t\tdialog.pack();\n\t\tdialog.centerWindow();\n\t\tdialog.addListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\t\tif (keycode == Keys.ENTER) {\n\t\t\t\t\tdialog.fadeOut();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tstage.addActor(dialog.fadeIn());\n\t\treturn dialog;\n\t}\n\n\t/**\n\t * Dialog with text and buttons like Yes, No, Cancel.\n\t * @param title dialog title\n\t * @param type specifies what types of buttons will this dialog have\n\t * @param listener dialog buttons listener.\n\t * @return dialog for the purpose of changing buttons text.\n\t * @see OptionDialog\n\t * @since 0.6.0\n\t */\n\tpublic static OptionDialog showOptionDialog (Stage stage, String title, String text, OptionDialogType type, OptionDialogListener listener) {\n\t\tOptionDialog dialog = new OptionDialog(title, text, type, listener);\n\t\tstage.addActor(dialog.fadeIn());\n\t\treturn dialog;\n\t}\n\n\t/**\n\t * Dialog with title, text and n amount of buttons. If you need dialog with only buttons like Yes, No, Cancel then\n\t * see {@link #showOptionDialog(Stage, String, String, OptionDialogType, OptionDialogListener)}.\n\t * <p>\n\t * @param title dialog title.\n\t * @param listener button listener for this dialog. This dialog is generic, listener type will depend on\n\t * 'returns' param type.\n\t * @since 0.7.0\n\t */\n\tpublic static <T> ConfirmDialog<T> showConfirmDialog (Stage stage, String title, String text, String[] buttons, T[] returns, ConfirmDialogListener<T> listener) {\n\t\tConfirmDialog<T> dialog = new ConfirmDialog<T>(title, text, buttons, returns, listener);\n\t\tstage.addActor(dialog.fadeIn());\n\t\treturn dialog;\n\t}\n\n\t/**\n\t * Dialog with text and text field for user input. Cannot be canceled.\n\t * @param title dialog title.\n\t * @param fieldTitle displayed before input field, may be null.\n\t * @param listener dialog buttons listener.\n\t */\n\tpublic static InputDialog showInputDialog (Stage stage, String title, String fieldTitle, InputDialogListener listener) {\n\t\tInputDialog dialog = new InputDialog(title, fieldTitle, true, null, listener);\n\t\tstage.addActor(dialog.fadeIn());\n\t\treturn dialog;\n\t}\n\n\t/**\n\t * Dialog with text and text field for user input. Cannot be canceled.\n\t * @param title dialog title.\n\t * @param fieldTitle displayed before input field, may be null.\n\t * @param validator used to validate user input. Eg. limit input to integers only. See {@link Validators} for built-in validators.\n\t * @param listener dialog buttons listener.\n\t */\n\tpublic static InputDialog showInputDialog (Stage stage, String title, String fieldTitle, InputValidator validator, InputDialogListener listener) {\n\t\tInputDialog dialog = new InputDialog(title, fieldTitle, true, validator, listener);\n\t\tstage.addActor(dialog.fadeIn());\n\t\treturn dialog;\n\t}\n\n\t/**\n\t * Dialog with text and text field for user input.\n\t * @param title dialog title.\n\t * @param cancelable if true dialog may be canceled by user.\n\t * @param fieldTitle displayed before input field, may be null.\n\t * @param listener dialog buttons listener.\n\t */\n\tpublic static InputDialog showInputDialog (Stage stage, String title, String fieldTitle, boolean cancelable, InputDialogListener listener) {\n\t\tInputDialog dialog = new InputDialog(title, fieldTitle, cancelable, null, listener);\n\t\tstage.addActor(dialog.fadeIn());\n\t\treturn dialog;\n\t}\n\n\t/**\n\t * Dialog with text and text field for user input.\n\t * @param title dialog title\n\t * @param validator used to validate user input, can be used to easily limit input to int etc. See {@link Validators} for premade validators.\n\t * @param cancelable if true dialog may be canceled.\n\t * @param fieldTitle displayed before input field, may be null.\n\t */\n\tpublic static InputDialog showInputDialog (Stage stage, String title, String fieldTitle, boolean cancelable, InputValidator validator, InputDialogListener listener) {\n\t\tInputDialog dialog = new InputDialog(title, fieldTitle, cancelable, validator, listener);\n\t\tstage.addActor(dialog.fadeIn());\n\t\treturn dialog;\n\t}\n\n\t/** Dialog with title \"Error\" and provided text. */\n\tpublic static DetailsDialog showErrorDialog (Stage stage, String text) {\n\t\treturn showErrorDialog(stage, text, (String) null);\n\t}\n\n\t/** Dialog with title \"Error\", provided text and exception stacktrace available after pressing 'Details' button. */\n\tpublic static DetailsDialog showErrorDialog (Stage stage, String text, Throwable exception) {\n\t\tif (exception == null)\n\t\t\treturn showErrorDialog(stage, text, (String) null);\n\t\telse\n\t\t\treturn showErrorDialog(stage, text, getStackTrace(exception));\n\t}\n\n\t/** Dialog with title \"Error\", provided text, and provided details available after pressing 'Details' button. */\n\tpublic static DetailsDialog showErrorDialog (Stage stage, String text, String details) {\n\t\tDetailsDialog dialog = new DetailsDialog(text, Text.ERROR.get(), details);\n\t\tstage.addActor(dialog.fadeIn());\n\t\treturn dialog;\n\t}\n\n\t/** Dialog with given title, provided text, and more details available after pressing 'Details' button. */\n\tpublic static DetailsDialog showDetailsDialog (Stage stage, String text, String title, String details) {\n\t\treturn showDetailsDialog(stage, text, title, details, false);\n\t}\n\n\t/**\n\t * Dialog with given title, provided text, and more details available after pressing 'Details' button.\n\t * @param expandDetails if true details will be visible without need to press 'Details' button\n\t */\n\tpublic static DetailsDialog showDetailsDialog (Stage stage, String text, String title, String details, boolean expandDetails) {\n\t\tDetailsDialog dialog = new DetailsDialog(text, title, details);\n\t\tdialog.setDetailsVisible(expandDetails);\n\t\tstage.addActor(dialog.fadeIn());\n\t\treturn dialog;\n\t}\n\n\tprivate static VisScrollPane createScrollPane (Actor widget) {\n\t\tVisScrollPane scrollPane = new VisScrollPane(widget);\n\t\tscrollPane.setOverscroll(false, true);\n\t\tscrollPane.setFadeScrollBars(false);\n\t\treturn scrollPane;\n\t}\n\n\tprivate static String getStackTrace (Throwable throwable) {\n\t\tCharArray builder = new CharArray();\n\t\tgetStackTrace(throwable, builder);\n\t\treturn builder.toString();\n\t}\n\n\tprivate static void getStackTrace (Throwable throwable, CharArray builder) {\n\t\tString msg = throwable.getMessage();\n\t\tif (msg != null) {\n\t\t\tbuilder.append(msg);\n\t\t\tbuilder.append(\"\\n\\n\");\n\t\t}\n\n\t\tfor (StackTraceElement element : throwable.getStackTrace()) {\n\t\t\tbuilder.append(element);\n\t\t\tbuilder.append(\"\\n\");\n\t\t}\n\n\t\tif (throwable.getCause() != null) {\n\t\t\tbuilder.append(\"\\nCaused by: \");\n\t\t\tgetStackTrace(throwable.getCause(), builder);\n\t\t}\n\t}\n\n\tpublic enum OptionDialogType {\n\t\tYES_NO, YES_NO_CANCEL, YES_CANCEL\n\t}\n\n\t/**\n\t * Dialog with input field and optional {@link InputValidator}. Can be used directly although you should use {@link Dialogs}\n\t * showInputDialog methods.\n\t */\n\tpublic static class InputDialog extends VisWindow {\n\t\tprivate InputDialogListener listener;\n\t\tprivate VisTextField field;\n\t\tprivate VisTextButton okButton;\n\t\tprivate VisTextButton cancelButton;\n\n\t\tpublic InputDialog (String title, String fieldTitle, boolean cancelable, InputValidator validator, InputDialogListener listener) {\n\t\t\tsuper(title);\n\t\t\tthis.listener = listener;\n\n\t\t\tTableUtils.setSpacingDefaults(this);\n\t\t\tsetModal(true);\n\n\t\t\tif (cancelable) {\n\t\t\t\taddCloseButton();\n\t\t\t\tcloseOnEscape();\n\t\t\t}\n\n\t\t\tButtonBar buttonBar = new ButtonBar();\n\t\t\tbuttonBar.setIgnoreSpacing(true);\n\t\t\tbuttonBar.setButton(ButtonType.CANCEL, cancelButton = new VisTextButton(ButtonType.CANCEL.getText()));\n\t\t\tbuttonBar.setButton(ButtonType.OK, okButton = new VisTextButton(ButtonType.OK.getText()));\n\n\t\t\tVisTable fieldTable = new VisTable(true);\n\n\t\t\tif (validator == null)\n\t\t\t\tfield = new VisTextField();\n\t\t\telse\n\t\t\t\tfield = new VisValidatableTextField(validator);\n\n\t\t\tif (fieldTitle != null) fieldTable.add(new VisLabel(fieldTitle));\n\n\t\t\tfieldTable.add(field).expand().fill();\n\n\t\t\tadd(fieldTable).padTop(3).spaceBottom(4);\n\t\t\trow();\n\t\t\tadd(buttonBar.createTable()).padBottom(3);\n\n\t\t\taddListeners();\n\n\t\t\tif (validator != null) {\n\t\t\t\taddValidatableFieldListener(field);\n\t\t\t\tokButton.setDisabled(!field.isInputValid());\n\t\t\t}\n\n\t\t\tpack();\n\t\t\tcenterWindow();\n\t\t}\n\n\t\t@Override\n\t\tprotected void close () {\n\t\t\tsuper.close();\n\t\t\tlistener.canceled();\n\t\t}\n\n\t\t@Override\n\t\tprotected void setStage (Stage stage) {\n\t\t\tsuper.setStage(stage);\n\t\t\tif (stage != null)\n\t\t\t\tfield.focusField();\n\t\t}\n\n\t\tpublic InputDialog setText (String text) {\n\t\t\treturn setText(text, false);\n\t\t}\n\n\t\t/** @param selectText if true text will be selected (this can be useful if you want to allow user quickly erase all text). */\n\t\tpublic InputDialog setText (String text, boolean selectText) {\n\t\t\tfield.setText(text);\n\t\t\tfield.setCursorPosition(text.length());\n\t\t\tif (selectText) {\n\t\t\t\tfield.selectAll();\n\t\t\t}\n\n\t\t\treturn this;\n\t\t}\n\n\t\tprivate InputDialog addValidatableFieldListener (final VisTextField field) {\n\t\t\tfield.addListener(new ChangeListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\tif (field.isInputValid()) {\n\t\t\t\t\t\tokButton.setDisabled(false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tokButton.setDisabled(true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn this;\n\t\t}\n\n\t\tprivate void addListeners () {\n\t\t\tokButton.addListener(new ChangeListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\tlistener.finished(field.getText());\n\t\t\t\t\tfadeOut();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tcancelButton.addListener(new ChangeListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\tclose();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tfield.addListener(new InputListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\t\t\tif (keycode == Keys.ENTER && okButton.isDisabled() == false) {\n\t\t\t\t\t\tlistener.finished(field.getText());\n\t\t\t\t\t\tfadeOut();\n\t\t\t\t\t}\n\n\t\t\t\t\treturn super.keyDown(event, keycode);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Dialog with text and buttons like Yes, No, Cancel. Can be used directly although you should use {@link Dialogs}\n\t * showOptionDialog methods.\n\t */\n\tpublic static class OptionDialog extends VisWindow {\n\t\t//NOTE: when updating this class, don't forget about Editor's DisableableOptionDialog\n\t\tprivate final ButtonBar buttonBar;\n\n\t\tpublic OptionDialog (String title, String text, OptionDialogType type, final OptionDialogListener listener) {\n\t\t\tsuper(title);\n\n\t\t\tsetModal(true);\n\n\t\t\tadd(new VisLabel(text, Align.center));\n\t\t\trow();\n\t\t\tdefaults().space(6);\n\t\t\tdefaults().padBottom(3);\n\n\t\t\tbuttonBar = new ButtonBar();\n\t\t\tbuttonBar.setIgnoreSpacing(true);\n\n\t\t\tChangeListener yesBtnListener = new ChangeListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\tlistener.yes();\n\t\t\t\t\tfadeOut();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tChangeListener noBtnListener = new ChangeListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\tlistener.no();\n\t\t\t\t\tfadeOut();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tChangeListener cancelBtnListener = new ChangeListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\tlistener.cancel();\n\t\t\t\t\tfadeOut();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tswitch (type) {\n\t\t\t\tcase YES_NO:\n\t\t\t\t\tbuttonBar.setButton(ButtonType.YES, yesBtnListener);\n\t\t\t\t\tbuttonBar.setButton(ButtonType.NO, noBtnListener);\n\t\t\t\t\tbreak;\n\t\t\t\tcase YES_CANCEL:\n\t\t\t\t\tbuttonBar.setButton(ButtonType.YES, yesBtnListener);\n\t\t\t\t\tbuttonBar.setButton(ButtonType.CANCEL, cancelBtnListener);\n\t\t\t\t\tbreak;\n\t\t\t\tcase YES_NO_CANCEL:\n\t\t\t\t\tbuttonBar.setButton(ButtonType.YES, yesBtnListener);\n\t\t\t\t\tbuttonBar.setButton(ButtonType.NO, noBtnListener);\n\t\t\t\t\tbuttonBar.setButton(ButtonType.CANCEL, cancelBtnListener);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tadd(buttonBar.createTable());\n\n\t\t\tpack();\n\t\t\tcenterWindow();\n\t\t}\n\n\t\tpublic OptionDialog setNoButtonText (String text) {\n\t\t\tbuttonBar.getTextButton(ButtonType.NO).setText(text);\n\t\t\tpack();\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic OptionDialog setYesButtonText (String text) {\n\t\t\tbuttonBar.getTextButton(ButtonType.YES).setText(text);\n\t\t\tpack();\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic OptionDialog setCancelButtonText (String text) {\n\t\t\tbuttonBar.getTextButton(ButtonType.CANCEL).setText(text);\n\t\t\tpack();\n\t\t\treturn this;\n\t\t}\n\t}\n\n\t/**\n\t * Dialog with text and exception stacktrace available after pressing Details button.\n\t * Can be used directly although you should use {@link Dialogs} showErrorDialog methods.\n\t */\n\tpublic static class DetailsDialog extends VisDialog {\n\t\tprivate VisTable detailsTable = new VisTable(true);\n\t\tprivate Cell<?> detailsCell;\n\t\tprivate boolean detailsVisible;\n\n\t\tprivate VisTextButton copyButton;\n\t\tprivate VisLabel detailsLabel;\n\n\t\tpublic DetailsDialog (String text, String title, String details) {\n\t\t\tsuper(title);\n\n\t\t\ttext(text);\n\n\t\t\tif (details != null) {\n\t\t\t\tcopyButton = new VisTextButton(Text.COPY.get());\n\t\t\t\tdetailsLabel = new VisLabel(details);\n\n\t\t\t\tSizes sizes = VisUI.getSizes();\n\n\t\t\t\tcopyButton.addListener(new ChangeListener() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\t\tGdx.app.getClipboard().setContents((detailsLabel.getText().toString()));\n\t\t\t\t\t\tcopyButton.setText(Text.COPIED.get());\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tdetailsTable.add(new VisLabel(Text.DETAILS_COLON.get())).left().expand().padTop(6);\n\t\t\t\tdetailsTable.add(copyButton);\n\t\t\t\tdetailsTable.row();\n\n\t\t\t\tVisTable detailsTable = new VisTable();\n\t\t\t\tdetailsTable.add(detailsLabel).top().expand().fillX();\n\t\t\t\tthis.detailsTable.add(createScrollPane(detailsTable)).colspan(2).minWidth(600 * sizes.scaleFactor).height(300 * sizes.scaleFactor);\n\n\t\t\t\tgetContentTable().row();\n\t\t\t\tdetailsCell = getContentTable().add(this.detailsTable);\n\t\t\t\tdetailsCell.setActor(null);\n\t\t\t\tbutton(Text.DETAILS.get(), BUTTON_DETAILS);\n\t\t\t}\n\n\t\t\tbutton(ButtonType.OK.getText(), BUTTON_OK).padBottom(3);\n\t\t\tpack();\n\t\t\tcenterWindow();\n\t\t}\n\n\t\t@Override\n\t\tprotected void result (Object object) {\n\t\t\tint result = (Integer) object;\n\n\t\t\tif (result == BUTTON_DETAILS) {\n\t\t\t\tsetDetailsVisible(!detailsVisible);\n\t\t\t\tcancel();\n\t\t\t}\n\t\t}\n\n\t\tpublic void setWrapDetails (boolean wrap) {\n\t\t\tdetailsLabel.setWrap(wrap);\n\t\t}\n\n\t\tpublic void setCopyDetailsButtonVisible (boolean visible) {\n\t\t\tcopyButton.setVisible(visible);\n\t\t}\n\n\t\tpublic boolean isCopyDetailsButtonVisible () {\n\t\t\treturn copyButton.isVisible();\n\t\t}\n\n\t\t/**\n\t\t * Changes visibility of details pane. Note that Window must be added to Stage or Window won't be packed properly and\n\t\t * it's size will be wrong. If Window is not added to Stage packing will be performed next frame, if it is still\n\t\t * not added at that point, Window size will be incorrect.\n\t\t */\n\t\tpublic void setDetailsVisible (boolean visible) {\n\t\t\tif (detailsVisible == visible) return;\n\t\t\tdetailsVisible = visible;\n\t\t\tdetailsCell.setActor(detailsCell.hasActor() ? null : detailsTable);\n\n\t\t\t//looks like Stage is required to properly pack window\n\t\t\t//if it's null do packing next frame and hope that window have been already added to Stage at that point\n\t\t\tif (getStage() == null) {\n\t\t\t\tGdx.app.postRunnable(new Runnable() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void run () {\n\t\t\t\t\t\tpack();\n\t\t\t\t\t\tcenterWindow();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tpack();\n\t\t\t\tcenterWindow();\n\t\t\t}\n\t\t}\n\n\t\tpublic boolean isDetailsVisible () {\n\t\t\treturn detailsVisible;\n\t\t}\n\t}\n\n\t/**\n\t * Dialog with title, text and n amount of buttons. Can be used directly although you should use {@link Dialogs}\n\t * showConfirmDialog methods.\n\t * @author Javier\n\t * @author Kotcrab\n\t */\n\tpublic static class ConfirmDialog<T> extends VisDialog {\n\t\tprivate ConfirmDialogListener<T> listener;\n\n\t\tpublic ConfirmDialog (String title, String text, String[] buttons, T[] returns, ConfirmDialogListener<T> listener) {\n\t\t\tsuper(title);\n\n\t\t\tif (buttons.length != returns.length) {\n\t\t\t\tthrow new IllegalStateException(\"buttons.length must be equal to returns.length\");\n\t\t\t}\n\n\t\t\tthis.listener = listener;\n\n\t\t\ttext(new VisLabel(text, Align.center));\n\t\t\tdefaults().padBottom(3);\n\n\t\t\tfor (int i = 0; i < buttons.length; i++) {\n\t\t\t\tbutton(buttons[i], returns[i]);\n\t\t\t}\n\n\t\t\tpadBottom(3);\n\t\t\tpack();\n\t\t\tcenterWindow();\n\t\t}\n\n\t\t@Override\n\t\tprotected void result (Object object) {\n\t\t\tlistener.result((T) object);\n\t\t}\n\t}\n\n\t/** {@link Dialogs} I18N properties. */\n\tprivate enum Text implements BundleText {\n\t\tDETAILS(\"details\"),\n\t\tDETAILS_COLON(\"detailsColon\"),\n\t\tCOPY(\"copy\"),\n\t\tCOPIED(\"copied\"),\n\t\tERROR(\"error\");\n\n\t\tprivate final String name;\n\n\t\tText (final String name) {\n\t\t\tthis.name = name;\n\t\t}\n\n\t\tprivate static I18NBundle getBundle () {\n\t\t\treturn Locales.getDialogsBundle();\n\t\t}\n\n\t\t@Override\n\t\tpublic final String getName () {\n\t\t\treturn name;\n\t\t}\n\n\t\t@Override\n\t\tpublic final String get () {\n\t\t\treturn getBundle().get(name);\n\t\t}\n\n\t\t@Override\n\t\tpublic final String format () {\n\t\t\treturn getBundle().format(name);\n\t\t}\n\n\t\t@Override\n\t\tpublic final String format (final Object... arguments) {\n\t\t\treturn getBundle().format(name, arguments);\n\t\t}\n\n\t\t@Override\n\t\tpublic final String toString () {\n\t\t\treturn get();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/dialog/InputDialogAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.dialog;\n\n/**\n * Empty implementation of {@link InputDialogListener}.\n * @author Kotcrab\n */\npublic class InputDialogAdapter implements InputDialogListener {\n\t@Override\n\tpublic void finished (String input) {\n\n\t}\n\n\t@Override\n\tpublic void canceled () {\n\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/dialog/InputDialogListener.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.dialog;\n\n/**\n * Used to get events from {@link Dialogs} input dialog.\n * @author Kotcrab\n */\npublic interface InputDialogListener {\n\t/**\n\t * Called when input dialog has finished.\n\t * @param input text entered by user.\n\t */\n\tvoid finished (String input);\n\n\t/**\n\t * Called when user canceled dialog or pressed 'close' button. This won't be ever called if dialog is not\n\t * cancelable.\n\t */\n\tvoid canceled ();\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/dialog/OptionDialogAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.dialog;\n\n/**\n * Empty implementation of {@link OptionDialogListener}.\n * @author Kotcrab\n */\npublic class OptionDialogAdapter implements OptionDialogListener {\n\t@Override\n\tpublic void yes () {\n\n\t}\n\n\t@Override\n\tpublic void no () {\n\n\t}\n\n\t@Override\n\tpublic void cancel () {\n\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/dialog/OptionDialogListener.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.dialog;\n\n/**\n * Used to get events from {@link Dialogs} option dialog.\n * @author Kotcrab\n */\npublic interface OptionDialogListener {\n\t/** Called when 'yes' button was pressed. */\n\tvoid yes ();\n\n\t/** Called when 'no' button was pressed. */\n\tvoid no ();\n\n\t/** Called when 'cancel' button was pressed. */\n\tvoid cancel ();\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/form/FormInputValidator.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.form;\n\nimport com.kotcrab.vis.ui.util.InputValidator;\n\n/**\n * Base class for all validators used in {@link SimpleFormValidator}. Implementing custom {@link FormInputValidator} doesn't\n * differ from creating standard {@link InputValidator}. You just need to supply error message which will be displayed\n * when form validation failed on this validator. Because implementing custom {@link FormInputValidator} does not require\n * any more changes you can use {@link ValidatorWrapper} for existing {@link InputValidator}s.\n * @author Kotcrab\n * @see InputValidator\n * @see ValidatorWrapper\n */\npublic abstract class FormInputValidator implements InputValidator {\n\tprivate String errorMsg;\n\tprivate boolean result;\n\tprivate boolean hideErrorOnEmptyInput = false;\n\n\tpublic FormInputValidator (String errorMsg) {\n\t\tthis.errorMsg = errorMsg;\n\t}\n\n\t@Override\n\tpublic final boolean validateInput (String input) {\n\t\tresult = validate(input);\n\t\treturn result;\n\t}\n\n\t/**\n\t * Called by FormInputValidator when input should be validated, for proper validator behaviour this must be used\n\t * instead of {@link #validateInput(String)}.\n\t * Last result of this function will be stored because it is required by FromValidator.\n\t * @param input that should be validated.\n\t * @return if input is valid, false otherwise.\n\t */\n\tprotected abstract boolean validate (String input);\n\n\t/**\n\t * When called, error message of this validator won't be displayed if input field is empty, however from still will\n\t * be treated as invalid (confirm button won't be enabled). This is UX improvement feature, simply don't display\n\t * error before user typed in something.\n\t */\n\tpublic FormInputValidator hideErrorOnEmptyInput () {\n\t\thideErrorOnEmptyInput = true;\n\t\treturn this;\n\t}\n\n\t/** @see #hideErrorOnEmptyInput() */\n\tpublic void setHideErrorOnEmptyInput (boolean hideErrorOnEmptyInput) {\n\t\tthis.hideErrorOnEmptyInput = hideErrorOnEmptyInput;\n\t}\n\n\tpublic boolean isHideErrorOnEmptyInput () {\n\t\treturn hideErrorOnEmptyInput;\n\t}\n\n\tpublic void setErrorMsg (String errorMsg) {\n\t\tthis.errorMsg = errorMsg;\n\t}\n\n\tpublic String getErrorMsg () {\n\t\treturn errorMsg;\n\t}\n\n\tboolean getLastResult () {\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/form/FormValidator.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.form;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.scenes.scene2d.ui.Label;\nimport com.badlogic.gdx.scenes.scene2d.utils.Disableable;\nimport com.kotcrab.vis.ui.widget.VisTextField;\nimport com.kotcrab.vis.ui.widget.VisValidatableTextField;\n\nimport java.io.File;\n\n/**\n * Utility class made for creating input forms that requires inputting various information and that information cannot be wrong.\n * For example user registration form.\n * <p></p>\n * FromValidator is not GWT compatible, if you need that see {@link SimpleFormValidator}.\n * @author Kotcrab\n */\npublic class FormValidator extends SimpleFormValidator {\n\t/** @see SimpleFormValidator#SimpleFormValidator(Disableable) */\n\tpublic FormValidator (Disableable targetToDisable) {\n\t\tsuper(targetToDisable);\n\t}\n\n\t/** @see SimpleFormValidator#SimpleFormValidator(Disableable, Label) */\n\tpublic FormValidator (Disableable targetToDisable, Label messageLabel) {\n\t\tsuper(targetToDisable, messageLabel);\n\t}\n\n\t/** @see SimpleFormValidator#SimpleFormValidator(Disableable, Label, String) */\n\tpublic FormValidator (Disableable targetToDisable, Label messageLabel, String styleName) {\n\t\tsuper(targetToDisable, messageLabel, styleName);\n\t}\n\n\t/** @see SimpleFormValidator#SimpleFormValidator(Disableable, Label, FormValidatorStyle) */\n\tpublic FormValidator (Disableable targetToDisable, Label messageLabel, FormValidatorStyle style) {\n\t\tsuper(targetToDisable, messageLabel, style);\n\t}\n\n\t/** Validates if absolute path entered in text field points to an existing file. */\n\tpublic FormInputValidator fileExists (VisValidatableTextField field, String errorMsg) {\n\t\tFileExistsValidator validator = new FileExistsValidator(errorMsg);\n\t\tfield.addValidator(validator);\n\t\tadd(field);\n\t\treturn validator;\n\t}\n\n\t/**\n\t * Validates if relative path entered in text field points to an existing file.\n\t * @param relativeTo path entered in this field is used to create absolute path from entered in field (see {@link FileExistsValidator}).\n\t */\n\tpublic FormInputValidator fileExists (VisValidatableTextField field, VisTextField relativeTo, String errorMsg) {\n\t\tFileExistsValidator validator = new FileExistsValidator(relativeTo, errorMsg);\n\t\tfield.addValidator(validator);\n\t\tadd(field);\n\t\treturn validator;\n\t}\n\n\t/**\n\t * Validates if relative path entered in text field points to an existing file.\n\t * @param relativeTo path entered in this field is used to create absolute path from entered in field (see {@link FileExistsValidator}).\n\t * @param errorIfRelativeEmpty if true field input will be valid if 'relativeTo' field is empty, usually used with notEmpty validator on 'relativeTo' field to\n\t * avoid form errors. Settings this to true improves UX, errors are not displayed until user types something in 'relativeTo' field.\n\t */\n\tpublic FormInputValidator fileExists (VisValidatableTextField field, VisTextField relativeTo, String errorMsg, boolean errorIfRelativeEmpty) {\n\t\tFileExistsValidator validator = new FileExistsValidator(relativeTo, errorMsg, false, errorIfRelativeEmpty);\n\t\tfield.addValidator(validator);\n\t\tadd(field);\n\t\treturn validator;\n\t}\n\n\t/**\n\t * Validates if relative path entered in text field points to an existing file.\n\t * @param relativeTo path of this file is used to create absolute path from entered in field (see {@link FileExistsValidator}).\n\t */\n\tpublic FormInputValidator fileExists (VisValidatableTextField field, File relativeTo, String errorMsg) {\n\t\tFileExistsValidator validator = new FileExistsValidator(relativeTo, errorMsg);\n\t\tfield.addValidator(validator);\n\t\tadd(field);\n\t\treturn validator;\n\t}\n\n\t/**\n\t * Validates if relative path entered in text field points to an existing file.\n\t * @param relativeTo path of this file is used to create absolute path from entered in field (see {@link FileExistsValidator}).\n\t */\n\tpublic FormInputValidator fileExists (VisValidatableTextField field, FileHandle relativeTo, String errorMsg) {\n\t\tFileExistsValidator validator = new FileExistsValidator(relativeTo.file(), errorMsg);\n\t\tfield.addValidator(validator);\n\t\tadd(field);\n\t\treturn validator;\n\n\t}\n\n\t/** Validates if relative path entered in text field points to an non existing file. */\n\tpublic FormInputValidator fileNotExists (VisValidatableTextField field, String errorMsg) {\n\t\tFileExistsValidator validator = new FileExistsValidator(errorMsg, true);\n\t\tfield.addValidator(validator);\n\t\tadd(field);\n\t\treturn validator;\n\n\t}\n\n\t/**\n\t * Validates if relative path entered in text field points to an non existing file.\n\t * @param relativeTo path entered in this field is used to create absolute path from entered in field (see {@link FileExistsValidator}).\n\t */\n\tpublic FormInputValidator fileNotExists (VisValidatableTextField field, VisTextField relativeTo, String errorMsg) {\n\t\tFileExistsValidator validator = new FileExistsValidator(relativeTo, errorMsg, true);\n\t\tfield.addValidator(validator);\n\t\tadd(field);\n\t\treturn validator;\n\n\t}\n\n\t/**\n\t * Validates if relative path entered in text field points to an non existing file.\n\t * @param relativeTo path of this file is used to create absolute path from entered in field (see {@link FileExistsValidator}).\n\t */\n\tpublic FormInputValidator fileNotExists (VisValidatableTextField field, File relativeTo, String errorMsg) {\n\t\tFileExistsValidator validator = new FileExistsValidator(relativeTo, errorMsg, true);\n\t\tfield.addValidator(validator);\n\t\tadd(field);\n\t\treturn validator;\n\n\t}\n\n\t/**\n\t * Validates if relative path entered in text field points to an non existing file.\n\t * @param relativeTo path of this file is used to create absolute path from entered in field (see {@link FileExistsValidator}).\n\t */\n\tpublic FormInputValidator fileNotExists (VisValidatableTextField field, FileHandle relativeTo, String errorMsg) {\n\t\tFileExistsValidator validator = new FileExistsValidator(relativeTo.file(), errorMsg, true);\n\t\tfield.addValidator(validator);\n\t\tadd(field);\n\t\treturn validator;\n\t}\n\n\t/** Validates if relative path entered in text field points to an existing directory. */\n\tpublic FormInputValidator directory (VisValidatableTextField field, String errorMsg) {\n\t\tDirectoryValidator validator = new DirectoryValidator(errorMsg);\n\t\tfield.addValidator(validator);\n\t\tadd(field);\n\t\treturn validator;\n\t}\n\n\t/** Validates if relative path entered in text field points to an existing and empty directory. */\n\tpublic FormInputValidator directoryEmpty (VisValidatableTextField field, String errorMsg) {\n\t\tDirectoryContentValidator validator = new DirectoryContentValidator(errorMsg, true);\n\t\tfield.addValidator(validator);\n\t\tadd(field);\n\t\treturn validator;\n\t}\n\n\t/** Validates if relative path entered in text field points to an existing and non empty directory. */\n\tpublic FormInputValidator directoryNotEmpty (VisValidatableTextField field, String errorMsg) {\n\t\tDirectoryContentValidator validator = new DirectoryContentValidator(errorMsg, false);\n\t\tfield.addValidator(validator);\n\t\tadd(field);\n\t\treturn validator;\n\t}\n\n\t/** Validates if entered absolute path points to existing directory. */\n\tpublic static class DirectoryValidator extends FormInputValidator {\n\t\tpublic DirectoryValidator (String errorMsg) {\n\t\t\tsuper(errorMsg);\n\t\t}\n\n\t\t@Override\n\t\tprotected boolean validate (String input) {\n\t\t\tFileHandle file = Gdx.files.absolute(input);\n\t\t\treturn file.exists() && file.isDirectory();\n\t\t}\n\t}\n\n\t/**\n\t * Validates if entered path (absolute) points to an existing directory. Then checks if this directory is empty or if\n\t * it has files in it.\n\t * @see DirectoryValidator\n\t */\n\tpublic static class DirectoryContentValidator extends FormInputValidator {\n\t\tprivate boolean mustBeEmpty;\n\n\t\t/** @param mustBeEmpty if true validated directory must be empty, if false that directory must not be empty. */\n\t\tpublic DirectoryContentValidator (String errorMsg, boolean mustBeEmpty) {\n\t\t\tsuper(errorMsg);\n\t\t\tthis.mustBeEmpty = mustBeEmpty;\n\t\t}\n\n\t\t@Override\n\t\tprotected boolean validate (String input) {\n\t\t\tFileHandle file = Gdx.files.absolute(input);\n\t\t\tif (file.exists() == false || file.isDirectory() == false) return false;\n\t\t\tif (mustBeEmpty) {\n\t\t\t\treturn file.list().length == 0;\n\t\t\t} else {\n\t\t\t\treturn file.list().length != 0;\n\t\t\t}\n\t\t}\n\n\t\tpublic void setMustBeEmpty (boolean mustBeEmpty) {\n\t\t\tthis.mustBeEmpty = mustBeEmpty;\n\t\t}\n\n\t\tpublic boolean isMustBeEmpty () {\n\t\t\treturn mustBeEmpty;\n\t\t}\n\t}\n\n\t/**\n\t * Validates if entered path points to an existing or non existing file.\n\t * <p>\n\t * Additionally you can specify relativePath that entered path will be checked against. Relative path can be\n\t * either supplied as File or some other VisTextField. In that case path entered in that relative text field is used to check\n\t * if file exist in that directory. Eg. if relativePath points to \"C:\\directory\\\" and field that\n\t * has this validator contains \"test.txt\" then this validator will check if file \"\"C:\\directory\\text.txt\" exists (or not).\n\t */\n\tpublic static class FileExistsValidator extends FormInputValidator {\n\t\tVisTextField relativeTo;\n\t\tFile relativeToFile;\n\n\t\tboolean mustNotExist;\n\t\tboolean errorIfRelativeEmpty;\n\n\t\tpublic FileExistsValidator (String errorMsg) {\n\t\t\tthis(errorMsg, false);\n\t\t}\n\n\t\tpublic FileExistsValidator (String errorMsg, boolean mustNotExist) {\n\t\t\tsuper(errorMsg);\n\t\t\tthis.mustNotExist = mustNotExist;\n\t\t}\n\n\t\tpublic FileExistsValidator (File relativeTo, String errorMsg) {\n\t\t\tthis(relativeTo, errorMsg, false);\n\t\t}\n\n\t\tpublic FileExistsValidator (File relativeTo, String errorMsg, boolean mustNotExist) {\n\t\t\tsuper(errorMsg);\n\t\t\tthis.relativeToFile = relativeTo;\n\t\t\tthis.mustNotExist = mustNotExist;\n\t\t}\n\n\t\tpublic FileExistsValidator (VisTextField relativeTo, String errorMsg) {\n\t\t\tthis(relativeTo, errorMsg, false);\n\t\t}\n\n\t\tpublic FileExistsValidator (VisTextField relativeTo, String errorMsg, boolean mustNotExist) {\n\t\t\tsuper(errorMsg);\n\t\t\tthis.relativeTo = relativeTo;\n\t\t\tthis.mustNotExist = mustNotExist;\n\t\t}\n\n\t\t/** @see FormValidator#fileExists(VisValidatableTextField, VisTextField, String, boolean) */\n\t\tpublic FileExistsValidator (VisTextField relativeTo, String errorMsg, boolean mustNotExist, boolean errorIfRelativeEmpty) {\n\t\t\tsuper(errorMsg);\n\t\t\tthis.relativeTo = relativeTo;\n\t\t\tthis.mustNotExist = mustNotExist;\n\t\t\tthis.errorIfRelativeEmpty = errorIfRelativeEmpty;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean validate (String input) {\n\t\t\tFile file;\n\n\t\t\tif (relativeTo != null) {\n\t\t\t\tif (relativeTo.getText().length() == 0 && errorIfRelativeEmpty == false) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tfile = new File(relativeTo.getText(), input);\n\t\t\t} else if (relativeToFile != null) {\n\t\t\t\tfile = new File(relativeToFile, input);\n\t\t\t} else {\n\t\t\t\tfile = new File(input);\n\t\t\t}\n\n\t\t\tif (mustNotExist)\n\t\t\t\treturn !file.exists();\n\t\t\telse\n\t\t\t\treturn file.exists();\n\t\t}\n\n\t\tpublic void setRelativeToFile (File relativeToFile) {\n\t\t\tif (relativeTo != null)\n\t\t\t\tthrow new IllegalStateException(\"This validator already has relativeToTextField set\");\n\n\t\t\tthis.relativeToFile = relativeToFile;\n\t\t}\n\n\t\tpublic void setRelativeToTextField (VisTextField relativeTo) {\n\t\t\tif (relativeToFile != null)\n\t\t\t\tthrow new IllegalStateException(\"This validator already has relativeToFile set.\");\n\n\t\t\tthis.relativeTo = relativeTo;\n\t\t}\n\n\t\tpublic void setMustNotExist (boolean notExist) {\n\t\t\tthis.mustNotExist = notExist;\n\t\t}\n\n\t\tpublic void setErrorIfRelativeEmpty (boolean errorIfRelativeEmpty) {\n\t\t\tthis.errorIfRelativeEmpty = errorIfRelativeEmpty;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/form/SimpleFormValidator.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.form;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.actions.Actions;\nimport com.badlogic.gdx.scenes.scene2d.ui.Button;\nimport com.badlogic.gdx.scenes.scene2d.ui.Label;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Disableable;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.InputValidator;\nimport com.kotcrab.vis.ui.util.Validators;\nimport com.kotcrab.vis.ui.util.Validators.GreaterThanValidator;\nimport com.kotcrab.vis.ui.util.Validators.LesserThanValidator;\nimport com.kotcrab.vis.ui.widget.VisCheckBox;\nimport com.kotcrab.vis.ui.widget.VisValidatableTextField;\n\n/**\n * Utility class made for creating input forms that requires inputting various information and that information cannot be wrong.\n * For example user registration form.\n * <p>\n * SimpleFormValidator is GWT compatible and does not provide fileExists methods, if you are not using GWT use\n * {@link FormValidator}.\n * @author Kotcrab\n */\npublic class SimpleFormValidator {\n\tprivate FormValidatorStyle style;\n\n\tprivate ChangeSharedListener changeListener = new ChangeSharedListener();\n\tprivate Array<VisValidatableTextField> fields = new Array<VisValidatableTextField>();\n\tprivate Array<CheckedButtonWrapper> buttons = new Array<CheckedButtonWrapper>();\n\n\tprivate String successMsg;\n\n\tprivate boolean formInvalid = false;\n\tprivate String errorMsgText = \"\";\n\n\tprivate Array<Disableable> disableTargets = new Array<Disableable>();\n\tprivate Label messageLabel;\n\n\tprivate boolean treatDisabledFieldsAsValid = true;\n\n\t/**\n\t * @param targetToDisable target actor that will be disabled if form is invalid. Eg. you can pass form Confirm button.\n\t * May be null.\n\t */\n\tpublic SimpleFormValidator (Disableable targetToDisable) {\n\t\tthis(targetToDisable, null, \"default\");\n\t}\n\n\t/**\n\t * @param targetToDisable target actor that will be disabled if form is invalid. Eg. you can pass form Confirm button.\n\t * May be null.\n\t * @param messageLabel label that text will be changed if from is valid or invalid. May be null.\n\t */\n\tpublic SimpleFormValidator (Disableable targetToDisable, Label messageLabel) {\n\t\tthis(targetToDisable, messageLabel, \"default\");\n\t}\n\n\t/**\n\t * @param targetToDisable target actor that will be disabled if form is invalid. Eg. you can pass form Confirm button.\n\t * May be null.\n\t * @param messageLabel label that text will be changed if from is valid or invalid. May be null.\n\t */\n\tpublic SimpleFormValidator (Disableable targetToDisable, Label messageLabel, String styleName) {\n\t\tthis(targetToDisable, messageLabel, VisUI.getSkin().get(styleName, FormValidatorStyle.class));\n\t}\n\n\t/**\n\t * @param targetToDisable target actor that will be disabled if form is invalid. Eg. you can pass form Confirm button.\n\t * May be null.\n\t * @param messageLabel label that text will be changed if from is valid or invalid. May be null.\n\t */\n\tpublic SimpleFormValidator (Disableable targetToDisable, Label messageLabel, FormValidatorStyle style) {\n\t\tthis.style = style;\n\t\tif (targetToDisable != null) disableTargets.add(targetToDisable);\n\t\tthis.messageLabel = messageLabel;\n\t}\n\n\t/** Validates if file is not empty */\n\tpublic FormInputValidator notEmpty (VisValidatableTextField field, String errorMsg) {\n\t\tEmptyInputValidator validator = new EmptyInputValidator(errorMsg);\n\t\tfield.addValidator(validator);\n\t\tadd(field);\n\t\treturn validator;\n\t}\n\n\t/** Validates if entered text is integer number */\n\tpublic FormInputValidator integerNumber (VisValidatableTextField field, String errorMsg) {\n\t\tValidatorWrapper wrapper = new ValidatorWrapper(errorMsg, Validators.INTEGERS);\n\t\tfield.addValidator(wrapper);\n\t\tadd(field);\n\t\treturn wrapper;\n\t}\n\n\t/** Validates if entered text is float number */\n\tpublic FormInputValidator floatNumber (VisValidatableTextField field, String errorMsg) {\n\t\tValidatorWrapper wrapper = new ValidatorWrapper(errorMsg, Validators.FLOATS);\n\t\tfield.addValidator(wrapper);\n\t\tadd(field);\n\t\treturn wrapper;\n\t}\n\n\t/**\n\t * Validates if entered text is greater than entered number <p>\n\t * Can be used in combination with {@link #integerNumber(VisValidatableTextField, String)} to only allows integers.\n\t */\n\tpublic FormInputValidator valueGreaterThan (VisValidatableTextField field, String errorMsg, float value) {\n\t\treturn valueGreaterThan(field, errorMsg, value, false);\n\t}\n\n\t/**\n\t * Validates if entered text is lesser than entered number <p>\n\t * Can be used in combination with {@link #integerNumber(VisValidatableTextField, String)} to only allows integers.\n\t */\n\tpublic FormInputValidator valueLesserThan (VisValidatableTextField field, String errorMsg, float value) {\n\t\treturn valueLesserThan(field, errorMsg, value, false);\n\t}\n\n\t/**\n\t * Validates if entered text is greater than (or equal) entered number <p>\n\t * Can be used in combination with {@link #integerNumber(VisValidatableTextField, String)} to only allows integers.\n\t */\n\tpublic FormInputValidator valueGreaterThan (VisValidatableTextField field, String errorMsg, float value, boolean validIfEqualsValue) {\n\t\tValidatorWrapper wrapper = new ValidatorWrapper(errorMsg, new GreaterThanValidator(value, validIfEqualsValue));\n\t\tfield.addValidator(wrapper);\n\t\tadd(field);\n\t\treturn wrapper;\n\t}\n\n\t/**\n\t * Validates if entered text is lesser (or equal) than entered number <p>\n\t * Can be used in combination with {@link #integerNumber(VisValidatableTextField, String)} to only allows integers.\n\t */\n\tpublic FormInputValidator valueLesserThan (VisValidatableTextField field, String errorMsg, float value, boolean validIfEqualsValue) {\n\t\tValidatorWrapper wrapper = new ValidatorWrapper(errorMsg, new LesserThanValidator(value, validIfEqualsValue));\n\t\tfield.addValidator(wrapper);\n\t\tadd(field);\n\t\treturn wrapper;\n\t}\n\n\t/** Allows to add custom validator to field */\n\tpublic FormInputValidator custom (VisValidatableTextField field, FormInputValidator customValidator) {\n\t\tfield.addValidator(customValidator);\n\t\tadd(field);\n\t\treturn customValidator;\n\t}\n\n\t/** Validates if given button (usually checkbox) is checked. Use VisCheckBox to additionally support error border around it. */\n\tpublic void checked (Button button, String errorMsg) {\n\t\tbuttons.add(new CheckedButtonWrapper(button, true, errorMsg));\n\t\tbutton.addListener(changeListener);\n\t\tvalidate();\n\t}\n\n\t/** Validates if given button (usually checkbox) is unchecked. Use VisCheckBox to additionally support error border around it. */\n\tpublic void unchecked (Button button, String errorMsg) {\n\t\tbuttons.add(new CheckedButtonWrapper(button, false, errorMsg));\n\t\tbutton.addListener(changeListener);\n\t\tvalidate();\n\t}\n\n\t/**\n\t * Adds field to this form without attaching any {@link FormInputValidator} to it. This can be used when field\n\t * already has added all required validators.\n\t */\n\tpublic void add (VisValidatableTextField field) {\n\t\tif (fields.contains(field, true) == false) fields.add(field);\n\t\tfield.addListener(changeListener); //addListener won't allow to add same listener twice\n\t\tvalidate();\n\t}\n\n\tpublic void addDisableTarget (Disableable disableable) {\n\t\tdisableTargets.add(disableable);\n\t\tupdateWidgets();\n\t}\n\n\tpublic boolean removeDisableTarget (Disableable disableable) {\n\t\tboolean result = disableTargets.removeValue(disableable, true);\n\t\tupdateWidgets();\n\t\treturn result;\n\t}\n\n\tpublic void setMessageLabel (Label messageLabel) {\n\t\tthis.messageLabel = messageLabel;\n\t\tupdateWidgets();\n\t}\n\n\t/** @param successMsg message that will be displayed on {@link #messageLabel} if all fields were valid. May be null. */\n\tpublic void setSuccessMessage (String successMsg) {\n\t\tthis.successMsg = successMsg;\n\t\tupdateWidgets();\n\t}\n\n\tpublic boolean isTreatDisabledFieldsAsValid () {\n\t\treturn treatDisabledFieldsAsValid;\n\t}\n\n\t/**\n\t * If true then this FormValidator will treat disabled fields as valid regardless of their validator states.\n\t * Default is true. Changing this cause form to be revalidated.\n\t * @since 1.0.2\n\t */\n\tpublic void setTreatDisabledFieldsAsValid (boolean treatDisabledFieldAsValid) {\n\t\tthis.treatDisabledFieldsAsValid = treatDisabledFieldAsValid;\n\t\tvalidate();\n\t}\n\n\t/**\n\t * Performs full check of this form, typically there is no need to call this method manually since form will be automatically\n\t * validated upon field content change. However calling this might be required when change made to field state does not\n\t * cause change event to be fired. For example disabling or enabling field.\n\t */\n\tpublic void validate () {\n\t\tformInvalid = false;\n\t\terrorMsgText = null;\n\n\t\tfor (CheckedButtonWrapper wrapper : buttons) {\n\t\t\tif (wrapper.button.isChecked() != wrapper.mustBeChecked) {\n\t\t\t\twrapper.setButtonStateInvalid(true);\n\t\t\t} else {\n\t\t\t\twrapper.setButtonStateInvalid(false);\n\t\t\t}\n\t\t}\n\n\t\tfor (CheckedButtonWrapper wrapper : buttons) {\n\t\t\tif (treatDisabledFieldsAsValid && wrapper.button.isDisabled()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (wrapper.button.isChecked() != wrapper.mustBeChecked) {\n\t\t\t\terrorMsgText = wrapper.errorMsg;\n\t\t\t\tformInvalid = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tfor (VisValidatableTextField field : fields) {\n\t\t\tfield.validateInput();\n\t\t}\n\n\t\tfor (VisValidatableTextField field : fields) {\n\t\t\tif (treatDisabledFieldsAsValid && field.isDisabled()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (field.isInputValid() == false) {\n\t\t\t\tArray<InputValidator> validators = field.getValidators();\n\t\t\t\tfor (InputValidator v : validators) {\n\t\t\t\t\tif (v instanceof FormInputValidator == false) {\n\t\t\t\t\t\tthrow new IllegalStateException(\"Fields validated by FormValidator cannot have validators not added using FormValidator methods. \" +\n\t\t\t\t\t\t\t\t\"Are you adding validators to field manually?\");\n\t\t\t\t\t}\n\n\t\t\t\t\tFormInputValidator validator = (FormInputValidator) v;\n\n\t\t\t\t\tif (validator.getLastResult() == false) {\n\t\t\t\t\t\tif (!(validator.isHideErrorOnEmptyInput() && field.getText().equals(\"\"))) {\n\t\t\t\t\t\t\terrorMsgText = validator.getErrorMsg();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tformInvalid = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tupdateWidgets();\n\t}\n\n\tprivate void updateWidgets () {\n\t\tfor (Disableable disableable : disableTargets) {\n\t\t\tdisableable.setDisabled(formInvalid);\n\t\t}\n\n\t\tif (messageLabel != null) {\n\t\t\tif (errorMsgText != null) {\n\t\t\t\tmessageLabel.setText(errorMsgText);\n\t\t\t} else {\n\t\t\t\tmessageLabel.setText(successMsg); //setText will default to \"\" if successMsg is null\n\t\t\t}\n\n\t\t\tColor targetColor = errorMsgText != null ? style.errorLabelColor : style.validLabelColor;\n\t\t\tif (targetColor != null && style.colorTransitionDuration != 0) {\n\t\t\t\tmessageLabel.addAction(Actions.color(targetColor, style.colorTransitionDuration));\n\t\t\t} else {\n\t\t\t\tmessageLabel.setColor(targetColor);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate class ChangeSharedListener extends ChangeListener {\n\t\t@Override\n\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\tvalidate();\n\t\t}\n\t}\n\n\tprivate static class CheckedButtonWrapper {\n\t\tpublic Button button;\n\t\tpublic boolean mustBeChecked;\n\t\tpublic String errorMsg;\n\n\t\tpublic CheckedButtonWrapper (Button button, boolean mustBeChecked, String errorMsg) {\n\t\t\tthis.button = button;\n\t\t\tthis.mustBeChecked = mustBeChecked;\n\t\t\tthis.errorMsg = errorMsg;\n\t\t}\n\n\t\tpublic void setButtonStateInvalid (boolean state) {\n\t\t\tif (button instanceof VisCheckBox) {\n\t\t\t\t((VisCheckBox) button).setStateInvalid(state);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static class EmptyInputValidator extends FormInputValidator {\n\t\tpublic EmptyInputValidator (String errorMsg) {\n\t\t\tsuper(errorMsg);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean validate (String input) {\n\t\t\treturn !input.isEmpty();\n\t\t}\n\t}\n\n\tpublic static class FormValidatorStyle {\n\t\t/** Optional */\n\t\tpublic Color errorLabelColor;\n\t\t/** Optional */\n\t\tpublic Color validLabelColor;\n\n\t\tpublic float colorTransitionDuration;\n\n\t\tpublic FormValidatorStyle () {\n\t\t}\n\n\t\tpublic FormValidatorStyle (Color errorLabelColor, Color validLabelColor) {\n\t\t\tthis.errorLabelColor = errorLabelColor;\n\t\t\tthis.validLabelColor = validLabelColor;\n\t\t}\n\n\t\tpublic FormValidatorStyle (FormValidatorStyle style) {\n\t\t\tthis.errorLabelColor = style.errorLabelColor;\n\t\t\tthis.validLabelColor = style.validLabelColor;\n\t\t\tthis.colorTransitionDuration = style.colorTransitionDuration;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/form/ValidatorWrapper.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.form;\n\nimport com.kotcrab.vis.ui.util.InputValidator;\nimport com.kotcrab.vis.ui.widget.VisValidatableTextField;\n\n/**\n * Allows standard {@link InputValidator} to be used with {@link SimpleFormValidator#custom(VisValidatableTextField, FormInputValidator)}\n * Wraps standard input validator and adds error message.\n * @author Kotcrab\n */\npublic class ValidatorWrapper extends FormInputValidator {\n\tprivate InputValidator validator;\n\n\tpublic ValidatorWrapper (String errorMsg, InputValidator validator) {\n\t\tsuper(errorMsg);\n\t\tthis.validator = validator;\n\t}\n\n\t@Override\n\tprotected boolean validate (String input) {\n\t\treturn validator.validateInput(input);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/highlight/BaseHighlighter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.highlight;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.widget.HighlightTextArea;\n\n/**\n * Highlighter aggregates multiple {@link HighlightRule} into single collection. Highlighter is used by {@link HighlightTextArea}\n * to get information about which parts of text should be highlighted. Compared to {@link Highlighter} this class is GWT compatible.\n * @author Kotcrab\n * @see Highlighter\n * @since 1.1.2\n */\npublic class BaseHighlighter {\n\tprivate Array<HighlightRule> rules = new Array<HighlightRule>();\n\n\t/** Adds highlighter rule. What is highlighted depends on rule implementation. */\n\tpublic void addRule (HighlightRule rule) {\n\t\trules.add(rule);\n\t}\n\n\t/**\n\t * Adds word based highlighter rule. Note that for most uses, word based rules are not sophisticated enough - for example\n\t * using regex rule for programming language keywords detection is far more robust.\n\t * @see WordHighlightRule\n\t */\n\tpublic void word (Color color, String word) {\n\t\taddRule(new WordHighlightRule(color, word));\n\t}\n\n\t/**\n\t * Adds word based highlighter rule. Utility method allowing to add many words at once.\n\t * @see #word(Color, String)\n\t * @see WordHighlightRule\n\t */\n\tpublic void word (Color color, String... words) {\n\t\tfor (String word : words) {\n\t\t\taddRule(new WordHighlightRule(color, word));\n\t\t}\n\t}\n\n\t/**\n\t * Process all rules in this highlighter.\n\t * @param highlights current highlights, new highlights can be added to this list however it should not be modified in any other ways\n\t */\n\tpublic void process (HighlightTextArea textArea, Array<Highlight> highlights) {\n\t\tfor (HighlightRule rule : rules) {\n\t\t\trule.process(textArea, highlights);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/highlight/Highlight.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.highlight;\n\nimport com.badlogic.gdx.graphics.Color;\n\n/**\n * Represents single highlight.\n * @author Kotcrab\n * @since 1.1.2\n */\npublic class Highlight implements Comparable<Highlight> {\n\tprivate Color color;\n\tprivate int start;\n\tprivate int end;\n\n\tpublic Highlight (Color color, int start, int end) {\n\t\tif (color == null) throw new IllegalArgumentException(\"color can't be null\");\n\t\tif (start >= end) throw new IllegalArgumentException(\"start can't be >= end: \" + start + \" >= \" + end);\n\t\tthis.color = color;\n\t\tthis.start = start;\n\t\tthis.end = end;\n\t}\n\n\tpublic Color getColor () {\n\t\treturn color;\n\t}\n\n\tpublic int getStart () {\n\t\treturn start;\n\t}\n\n\tpublic int getEnd () {\n\t\treturn end;\n\t}\n\n\t@Override\n\tpublic int compareTo (Highlight o) {\n\t\treturn getStart() - o.getStart();\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/highlight/HighlightRule.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.highlight;\n\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.widget.HighlightTextArea;\n\n/**\n * @author Kotcrab\n * @since 1.1.2\n */\npublic interface HighlightRule {\n\t/**\n\t * Process this rule. This method should detect matches in text area text, create {@link Highlight} instances and add them to provided\n\t * highlights array.\n\t * @param textArea text area\n\t * @param highlights current highlights, new highlights can be added to this list however it should not be modified in any other ways\n\t */\n\tvoid process (HighlightTextArea textArea, Array<Highlight> highlights);\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/highlight/Highlighter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.highlight;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.kotcrab.vis.ui.widget.HighlightTextArea;\n\n/**\n * Highlighter aggregates multiple {@link HighlightRule} into single collection. Highlighter is used by {@link HighlightTextArea}\n * to get information about which parts of text should be highlighted. If you need GWT compatibility, you need to use {@link BaseHighlighter}.\n * @author Kotcrab\n * @see BaseHighlighter\n * @since 1.1.2\n */\npublic class Highlighter extends BaseHighlighter {\n\t/** Adds regex based highlighter rule. */\n\tpublic void regex (Color color, String regex) {\n\t\taddRule(new RegexHighlightRule(color, regex));\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/highlight/RegexHighlightRule.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.highlight;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.widget.HighlightTextArea;\n\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n/**\n * Highlighter rule using regex to detect text matches. Regexes and thus this rule can't be used on GWT.\n * @author Kotcrab\n * @since 1.1.2\n */\npublic class RegexHighlightRule implements HighlightRule {\n\tprivate Color color;\n\tprivate Pattern pattern;\n\n\tpublic RegexHighlightRule (Color color, String regex) {\n\t\tthis.color = color;\n\t\tpattern = Pattern.compile(regex);\n\t}\n\n\t@Override\n\tpublic void process (HighlightTextArea textArea, Array<Highlight> highlights) {\n\t\tMatcher matcher = pattern.matcher(textArea.getText());\n\t\twhile (matcher.find()) {\n\t\t\thighlights.add(new Highlight(color, matcher.start(), matcher.end()));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/highlight/WordHighlightRule.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.highlight;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.widget.HighlightTextArea;\n\n/**\n * Highlighter rule using {@link String#indexOf(String)} to detect text matches.\n * @author Kotcrab\n * @since 1.1.2\n */\npublic class WordHighlightRule implements HighlightRule {\n\tprivate Color color;\n\tprivate String word;\n\n\tpublic WordHighlightRule (Color color, String word) {\n\t\tthis.color = color;\n\t\tthis.word = word;\n\t}\n\n\t@Override\n\tpublic void process (HighlightTextArea textArea, Array<Highlight> highlights) {\n\t\tString text = textArea.getText();\n\t\tint index = text.indexOf(word);\n\t\twhile (index >= 0) {\n\t\t\thighlights.add(new Highlight(color, index, index += word.length()));\n\t\t\tindex = text.indexOf(word, index);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/value/ConstantIfVisibleValue.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.value;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Value;\n\n/**\n * Value that returns given fixed constant value if widget is visible. If actor is invisible then returns 0.\n * @author Kotcrab\n * @since 1.1.0\n */\npublic class ConstantIfVisibleValue extends Value {\n\tprivate Actor actor;\n\tprivate float constant;\n\n\tpublic ConstantIfVisibleValue (float constant) {\n\t\tthis.constant = constant;\n\t}\n\n\tpublic ConstantIfVisibleValue (Actor actor, float constant) {\n\t\tthis.actor = actor;\n\t\tthis.constant = constant;\n\t}\n\n\t@Override\n\tpublic float get (Actor context) {\n\t\tif (actor != null) context = actor;\n\t\treturn context.isVisible() ? constant : 0;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/value/PrefHeightIfVisibleValue.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.value;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.scenes.scene2d.ui.Value;\nimport com.badlogic.gdx.scenes.scene2d.ui.Widget;\n\n/**\n * Value that returns widget preferred height if it's visible. If widget is invisible then returns 0.\n * This can be only added to classes extending {@link Widget} or {@link Table}, if you try to add it to any other class\n * you will get {@link IllegalStateException} during runtime.\n * @author Kotcrab\n * @since 0.9.3\n */\npublic class PrefHeightIfVisibleValue extends Value {\n\tpublic static final PrefHeightIfVisibleValue INSTANCE = new PrefHeightIfVisibleValue();\n\n\t@Override\n\tpublic float get (Actor actor) {\n\t\tif (actor instanceof Widget) {\n\t\t\tWidget widget = (Widget) actor;\n\t\t\treturn widget.isVisible() ? widget.getPrefHeight() : 0;\n\t\t}\n\n\t\tif (actor instanceof Table) {\n\t\t\tTable table = (Table) actor;\n\t\t\treturn table.isVisible() ? table.getPrefHeight() : 0;\n\t\t}\n\n\t\tthrow new IllegalStateException(\"Unsupported actor type for PrefHeightIfVisibleValue: \" + actor.getClass());\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/value/PrefWidthIfVisibleValue.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.value;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.scenes.scene2d.ui.Value;\nimport com.badlogic.gdx.scenes.scene2d.ui.Widget;\n\n/**\n * Value that returns widget preferred width if it's visible. If widget is invisible then returns 0.\n * This can be only added to classes extending {@link Widget} or {@link Table}, if you try to add it to any other class\n * you will get {@link IllegalStateException} during runtime.\n * @author Kotcrab\n * @since 1.0.0\n */\npublic class PrefWidthIfVisibleValue extends Value {\n\tpublic static final PrefWidthIfVisibleValue INSTANCE = new PrefWidthIfVisibleValue();\n\n\t@Override\n\tpublic float get (Actor actor) {\n\t\tif (actor instanceof Widget) {\n\t\t\tWidget widget = (Widget) actor;\n\t\t\treturn widget.isVisible() ? widget.getPrefWidth() : 0;\n\t\t}\n\n\t\tif (actor instanceof Table) {\n\t\t\tTable table = (Table) actor;\n\t\t\treturn table.isVisible() ? table.getPrefWidth() : 0;\n\t\t}\n\n\t\tthrow new IllegalStateException(\"Unsupported actor type for PrefWidthIfVisibleValue: \" + actor.getClass());\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/value/VisValue.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.value;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Value;\n\n/**\n * Allows to use libGDX {@link Value} with lambdas. Using this on Java lower than 1.8 is pointless because lambadas are\n * not supported.\n * @author Kotcrab\n * @see VisWidgetValue\n * @since 0.9.3\n */\npublic class VisValue extends Value {\n\tprivate ValueGetter getter;\n\n\tpublic VisValue (ValueGetter getter) {\n\t\tthis.getter = getter;\n\t}\n\n\t@Override\n\tpublic float get (Actor context) {\n\t\treturn getter.get(context);\n\t}\n\n\tpublic interface ValueGetter {\n\t\tfloat get (Actor context);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/util/value/VisWidgetValue.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.util.value;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Value;\nimport com.badlogic.gdx.scenes.scene2d.ui.Widget;\n\n/**\n * Allows to use libGDX {@link Value} with lambdas for scene2d.ui widgets. Note that this cannot be added to actors,\n * only widgets are supported, if you try to do so you will get {@link ClassCastException} when this Value has been invoked.\n * Using this on Java lower than 1.8 is pointless because lambadas are not supported.\n * @author Kotcrab\n * @see VisValue\n * @see PrefHeightIfVisibleValue\n * @since 0.9.3\n */\npublic class VisWidgetValue extends Value {\n\tprotected WidgetValueGetter getter;\n\n\tpublic VisWidgetValue (WidgetValueGetter getter) {\n\t\tthis.getter = getter;\n\t}\n\n\t@Override\n\tpublic float get (Actor context) {\n\t\treturn getter.get((Widget) context);\n\t}\n\n\tpublic interface WidgetValueGetter {\n\t\tfloat get (Widget context);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/BusyBar.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.scenes.scene2d.ui.Widget;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * BusyBar is a type of indeterminate progress bar. This widget is usually added at the top of table and is shown\n * to indicate that some background work is going on. This widget should span across full width of table that is added to.\n * Default style of widget is blue rectangle that moves from left to right edge of screen in loop. For example you can\n * see it in FileChooser when opening directory containing thousand of files or checkout TestBusyBar in VisUI test application.\n * @author Kotcrab\n * @since 1.1.4\n */\npublic class BusyBar extends Widget {\n\tprivate BusyBarStyle style;\n\n\tprivate float segmentX;\n\n\tpublic BusyBar () {\n\t\tstyle = VisUI.getSkin().get(BusyBarStyle.class);\n\t}\n\n\tpublic BusyBar (String styleName) {\n\t\tstyle = VisUI.getSkin().get(styleName, BusyBarStyle.class);\n\t}\n\n\tpublic BusyBar (BusyBarStyle style) {\n\t\tthis.style = style;\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\treturn style.height;\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\treturn style.segmentWidth;\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tbatch.flush();\n\t\tif (clipBegin()) {\n\t\t\tColor c = getColor();\n\t\t\tbatch.setColor(c.r, c.g, c.b, c.a * parentAlpha);\n\t\t\tsegmentX += getSegmentDeltaX();\n\t\t\tstyle.segment.draw(batch, getX() + segmentX, getY(), style.segmentWidth, style.height);\n\t\t\tif (segmentX > getWidth() + style.segmentOverflow) {\n\t\t\t\tresetSegment();\n\t\t\t}\n\t\t\tif (isVisible()) Gdx.graphics.requestRendering();\n\t\t\tbatch.flush();\n\t\t\tclipEnd();\n\t\t}\n\t}\n\n\tpublic void resetSegment () {\n\t\tsegmentX = -style.segmentWidth - style.segmentOverflow;\n\t}\n\n\tprotected float getSegmentDeltaX () {\n\t\treturn Gdx.graphics.getDeltaTime() * getWidth();\n\t}\n\n\tpublic BusyBarStyle getStyle () {\n\t\treturn style;\n\t}\n\n\tstatic public class BusyBarStyle {\n\t\tpublic Drawable segment;\n\t\tpublic int segmentOverflow;\n\t\tpublic int segmentWidth;\n\t\tpublic int height;\n\n\t\tpublic BusyBarStyle () {\n\t\t}\n\n\t\tpublic BusyBarStyle (BusyBarStyle style) {\n\t\t\tthis.segment = style.segment;\n\t\t\tthis.segmentOverflow = style.segmentOverflow;\n\t\t\tthis.segmentWidth = style.segmentWidth;\n\t\t\tthis.height = style.height;\n\t\t}\n\n\t\tpublic BusyBarStyle (Drawable segment, int segmentOverflow, int segmentWidth, int height) {\n\t\t\tthis.segment = segment;\n\t\t\tthis.segmentOverflow = segmentOverflow;\n\t\t\tthis.segmentWidth = segmentWidth;\n\t\t\tthis.height = height;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/ButtonBar.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Button;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.utils.ObjectMap;\nimport com.kotcrab.vis.ui.Locales;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.OsUtils;\n\n/**\n * Convenient class for creating button panels with buttons such as \"Ok\", \"Cancel\", \"Yes\" etc. Buttons are arranged in\n * platform dependent order. Built-in orders support Windows, Mac, and Linux. When no platform matches ButtonBar\n * defaults to Linux order.\n * User may specify custom order, see {@link ButtonType} for buttons ids.\n * @author Kotcrab\n * @since 1.0.0\n */\npublic class ButtonBar {\n\tpublic static final String WINDOWS_ORDER = \"L H BEF YNOCA R\";\n\tpublic static final String OSX_ORDER = \"L H BEF NYCOA R\";\n\tpublic static final String LINUX_ORDER = \"L H NYACBEFO R\";\n\n\tprivate Sizes sizes;\n\n\tprivate ObjectMap<Character, Button> buttons = new ObjectMap<Character, Button>();\n\n\tprivate boolean ignoreSpacing;\n\tprivate String order;\n\n\tpublic ButtonBar () {\n\t\tthis(VisUI.getSizes(), getDefaultOrder());\n\t}\n\n\tpublic ButtonBar (String order) {\n\t\tthis(VisUI.getSizes(), order);\n\t}\n\n\tpublic ButtonBar (Sizes sizes) {\n\t\tthis(sizes, getDefaultOrder());\n\t}\n\n\tpublic ButtonBar (Sizes sizes, String order) {\n\t\tif (sizes == null) throw new IllegalArgumentException(\"sizes can't be null\");\n\t\tthis.sizes = sizes;\n\t\tsetOrder(order);\n\t}\n\n\tprivate static String getDefaultOrder () {\n\t\tif (OsUtils.isWindows()) {\n\t\t\treturn WINDOWS_ORDER;\n\t\t} else if (OsUtils.isMac()) {\n\t\t\treturn OSX_ORDER;\n\t\t} else //default to linux order\n\t\t\treturn LINUX_ORDER;\n\t}\n\n\tpublic boolean isIgnoreSpacing () {\n\t\treturn ignoreSpacing;\n\t}\n\n\t/** @param ignoreSpacing if true spacing symbols in order will be ignored */\n\tpublic void setIgnoreSpacing (boolean ignoreSpacing) {\n\t\tthis.ignoreSpacing = ignoreSpacing;\n\t}\n\n\tpublic String getOrder () {\n\t\treturn order;\n\t}\n\n\tpublic void setOrder (String order) {\n\t\tif (order == null) throw new IllegalArgumentException(\"order can't be null\");\n\t\tthis.order = order;\n\t}\n\n\tpublic void setButton (ButtonType type, ChangeListener listener) {\n\t\tsetButton(type, type.getText(), listener);\n\t}\n\n\tpublic void setButton (ButtonType type, String text, ChangeListener listener) {\n\t\tsetButton(type, new VisTextButton(text), listener);\n\t}\n\n\tpublic void setButton (ButtonType type, Button button) {\n\t\tsetButton(type, button, null);\n\t}\n\n\tpublic void setButton (ButtonType type, Button button, ChangeListener listener) {\n\t\tif (type == null) throw new IllegalArgumentException(\"type can't be null\");\n\t\tif (button == null) throw new IllegalArgumentException(\"button can't be null\");\n\t\tif (buttons.containsKey(type.id)) buttons.remove(type.id);\n\t\tbuttons.put(type.id, button);\n\t\tif (listener != null) button.addListener(listener);\n\t}\n\n\tpublic Button getButton (ButtonType type) {\n\t\treturn buttons.get(type.getId());\n\t}\n\n\t/**\n\t * @return stored button casted to {@link VisTextButton}. Will throw {@link ClassCastException} in case stored button\n\t * type is wrong. This may be safely used when button was created using {@link #setButton(ButtonType, String, ChangeListener)}.\n\t */\n\tpublic VisTextButton getTextButton (ButtonType type) {\n\t\treturn (VisTextButton) getButton(type);\n\t}\n\n\t/**\n\t * Builds and returns {@link VisTable} containing buttons in platform dependant order. Note that calling this multiple\n\t * times will remove buttons from previous tables.\n\t */\n\tpublic VisTable createTable () {\n\t\tVisTable table = new VisTable(true);\n\n\t\ttable.left();\n\n\t\tboolean spacingValid = false;\n\t\tfor (int i = 0; i < order.length(); i++) {\n\t\t\tchar ch = order.charAt(i);\n\n\t\t\tif (ignoreSpacing == false && ch == ' ' && spacingValid) {\n\t\t\t\ttable.add().width(sizes.buttonBarSpacing);\n\t\t\t\tspacingValid = false;\n\t\t\t}\n\n\t\t\tButton button = buttons.get(ch);\n\n\t\t\tif (button != null) {\n\t\t\t\ttable.add(button);\n\t\t\t\tspacingValid = true;\n\t\t\t}\n\t\t}\n\n\t\treturn table;\n\t}\n\n\t/** Defines possible button types for {@link ButtonBar} */\n\tpublic enum ButtonType {\n\t\tLEFT(\"left\", 'L'),\n\t\tRIGHT(\"right\", 'R'),\n\t\tHELP(\"help\", 'H'),\n\t\tNO(\"no\", 'N'),\n\t\tYES(\"yes\", 'Y'),\n\t\tCANCEL(\"cancel\", 'C'),\n\t\tBACK(\"back\", 'B'),\n\t\tNEXT(\"next\", 'E'),\n\t\tAPPLY(\"apply\", 'A'),\n\t\tFINISH(\"finish\", 'F'),\n\t\tOK(\"ok\", 'O');\n\n\t\tprivate final String key;\n\t\tprivate final char id;\n\n\t\tButtonType (String key, char id) {\n\t\t\tthis.key = key;\n\t\t\tthis.id = id;\n\t\t}\n\n\t\tpublic char getId () {\n\t\t\treturn id;\n\t\t}\n\n\t\tpublic final String getText () {\n\t\t\treturn Locales.getButtonBarBundle().get(key);\n\t\t}\n\n\t\t@Override\n\t\tpublic final String toString () {\n\t\t\treturn getText();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/CollapsibleWidget.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.math.Interpolation;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.actions.FloatAction;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;\nimport com.badlogic.gdx.utils.GdxRuntimeException;\n\n/**\n * Widget containing table that can be vertically collapsed.\n *\n * @author Kotcrab\n * @see HorizontalCollapsibleWidget\n * @since 0.3.1\n */\npublic class CollapsibleWidget extends WidgetGroup {\n\tprivate Table table;\n\n\tprivate CollapseAction collapseAction = new CollapseAction();\n\tprivate float collapseDuration = 0.3f;\n\tprivate Interpolation collapseInterpolation = Interpolation.pow3Out;\n\n\tprivate boolean collapsed;\n\tprivate boolean actionRunning;\n\n\tprivate float currentHeight;\n\n\tpublic CollapsibleWidget () {\n\t}\n\n\tpublic CollapsibleWidget (Table table) {\n\t\tthis(table, false);\n\t}\n\n\tpublic CollapsibleWidget (Table table, boolean collapsed) {\n\t\tthis.collapsed = collapsed;\n\t\tthis.table = table;\n\n\t\tupdateTouchable();\n\n\t\tif (table != null) addActor(table);\n\t}\n\n\tpublic void setCollapsed (boolean collapse, boolean withAnimation) {\n\t\tthis.collapsed = collapse;\n\t\tupdateTouchable();\n\n\t\tif (table == null) return;\n\n\t\tactionRunning = true;\n\n\t\tif (withAnimation) {\n\t\t\tcollapseAction.reset();\n\t\t\tcollapseAction.setStart(currentHeight);\n\t\t\tcollapseAction.setEnd(collapse ? 0f : table.getPrefHeight());\n\t\t\tcollapseAction.setDuration(collapseDuration);\n\t\t\tcollapseAction.setInterpolation(collapseInterpolation);\n\t\t\taddAction(collapseAction);\n\t\t} else {\n\t\t\tif (collapse) {\n\t\t\t\tcurrentHeight = 0;\n\t\t\t\tcollapsed = true;\n\t\t\t} else {\n\t\t\t\tcurrentHeight = table.getPrefHeight();\n\t\t\t\tcollapsed = false;\n\t\t\t}\n\n\t\t\tactionRunning = false;\n\t\t\tinvalidateHierarchy();\n\t\t}\n\t}\n\n\tpublic void setCollapsed (boolean collapse) {\n\t\tsetCollapsed(collapse, true);\n\t}\n\n\tpublic boolean isCollapsed () {\n\t\treturn collapsed;\n\t}\n\n\tprivate void updateTouchable () {\n\t\tif (collapsed)\n\t\t\tsetTouchable(Touchable.disabled);\n\t\telse\n\t\t\tsetTouchable(Touchable.enabled);\n\t}\n\n\tpublic void setCollapseDuration (float collapseDuration) {\n\t\tthis.collapseDuration = collapseDuration;\n\t}\n\n\tpublic void setCollapseInterpolation (Interpolation collapseInterpolation) {\n\t\tthis.collapseInterpolation = collapseInterpolation;\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tif (currentHeight > 1 && getY() + currentHeight > 1) {\n\t\t\tif (actionRunning) {\n\t\t\t\tbatch.flush();\n\t\t\t\tboolean clipEnabled = clipBegin(getX(), getY(), getWidth(), currentHeight);\n\n\t\t\t\tsuper.draw(batch, parentAlpha);\n\n\t\t\t\tbatch.flush();\n\t\t\t\tif (clipEnabled) clipEnd();\n\t\t\t} else {\n\t\t\t\tsuper.draw(batch, parentAlpha);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void layout () {\n\t\tif (table == null) return;\n\n\t\ttable.setBounds(0, 0, table.getPrefWidth(), table.getPrefHeight());\n\n\t\tif (actionRunning == false) {\n\t\t\tif (collapsed)\n\t\t\t\tcurrentHeight = 0;\n\t\t\telse\n\t\t\t\tcurrentHeight = table.getPrefHeight();\n\t\t}\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\treturn table == null ? 0 : table.getPrefWidth();\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\tif (table == null) return 0;\n\n\t\tif (actionRunning == false) {\n\t\t\tif (collapsed)\n\t\t\t\treturn 0;\n\t\t\telse\n\t\t\t\treturn table.getPrefHeight();\n\t\t}\n\n\t\treturn currentHeight;\n\t}\n\n\tpublic void setTable (Table table) {\n\t\tthis.table = table;\n\t\tclearChildren();\n\t\taddActor(table);\n\t}\n\n\t@Override\n\tprotected void childrenChanged () {\n\t\tsuper.childrenChanged();\n\t\tif (getChildren().size > 1) throw new GdxRuntimeException(\"Only one actor can be added to CollapsibleWidget\");\n\t}\n\n\tprivate class CollapseAction extends FloatAction {\n\n\t\t@Override\n\t\tprotected void update (float percent) {\n\t\t\tsuper.update(percent);\n\t\t\tcurrentHeight = getValue();\n\n\t\t\tif (percent == 1) {\n\t\t\t\tactionRunning = false;\n\t\t\t\tcollapsed = currentHeight == 0;\n\t\t\t}\n\n\t\t\tinvalidateHierarchy();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/Draggable.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.math.Interpolation;\nimport com.badlogic.gdx.math.MathUtils;\nimport com.badlogic.gdx.math.Vector2;\nimport com.badlogic.gdx.scenes.scene2d.*;\nimport com.badlogic.gdx.scenes.scene2d.actions.Actions;\nimport com.badlogic.gdx.scenes.scene2d.utils.Disableable;\nimport com.kotcrab.vis.ui.layout.DragPane;\n\nimport java.util.Iterator;\n\n/**\n * Draws copies of dragged actors which have this listener attached.\n * @author MJ\n * @since 0.9.3\n */\npublic class Draggable extends InputListener {\n\tprivate static final Vector2 MIMIC_COORDINATES = new Vector2();\n\tprivate static final Vector2 STAGE_COORDINATES = new Vector2();\n\n\t/**\n\t * Initial fading time value of dragged actors.\n\t * @see #setFadingTime(float)\n\t */\n\tpublic static float DEFAULT_FADING_TIME = 0.1f;\n\t/**\n\t * Initial moving time value of dragged actors.\n\t * @see #setMovingTime(float)\n\t */\n\tpublic static float DEFAULT_MOVING_TIME = 0.1f;\n\t/**\n\t * Initial invisibility setting of dragged actors.\n\t * @see #setInvisibleWhenDragged(boolean)\n\t */\n\tpublic static boolean INVISIBLE_ON_DRAG = false;\n\t/**\n\t * Initial setting of keeping the dragged widget within its parent's bounds.\n\t * @see #setKeepWithinParent(boolean)\n\t */\n\tpublic static boolean KEEP_WITHIN_PARENT = false;\n\t/**\n\t * Initial alpha setting of dragged actors.\n\t * @see #setAlpha(float)\n\t */\n\tpublic static float DEFAULT_ALPHA = 1f;\n\t/**\n\t * Initial listener of draggables, unless a different listener is specified in the constructor. By default,\n\t * {@link DragPane.DefaultDragListener} is used, which allows to drag actors into {@link DragPane} widgets.\n\t * @see #setListener(DragListener)\n\t * @see DragListener\n\t */\n\tpublic static DragListener DEFAULT_LISTENER = new DragPane.DefaultDragListener();\n\t/**\n\t * If true, other actors will not receive mouse events while the actor is dragged.\n\t * @see #setBlockInput(boolean)\n\t */\n\tpublic static boolean BLOCK_INPUT = true;\n\t/*** Blocks mouse input during dragging. */\n\tprivate static final Actor BLOCKER = new Actor();\n\n\t// Settings.\n\tprivate DragListener listener;\n\tprivate boolean blockInput = BLOCK_INPUT;\n\tprivate boolean invisibleWhenDragged = INVISIBLE_ON_DRAG;\n\tprivate boolean keepWithinParent = KEEP_WITHIN_PARENT;\n\tprivate float deadzoneRadius;\n\tprivate float fadingTime = DEFAULT_FADING_TIME;\n\tprivate float movingTime = DEFAULT_FADING_TIME;\n\tprivate float alpha = DEFAULT_ALPHA;\n\tprivate Interpolation fadingInterpolation = Interpolation.fade;\n\tprivate Interpolation movingInterpolation = Interpolation.sineOut;\n\n\t// Control variables.\n\tprivate final MimicActor mimic = new MimicActor();\n\tprivate float dragStartX;\n\tprivate float dragStartY;\n\tprivate float offsetX;\n\tprivate float offsetY;\n\n\t/** Creates a new draggable with default listener. */\n\tpublic Draggable () {\n\t\tthis(DEFAULT_LISTENER);\n\t}\n\n\t/** @param listener is being notified of draggable events and can change its behavior. Can be null. */\n\tpublic Draggable (final DragListener listener) {\n\t\tthis.listener = listener;\n\t\tmimic.setTouchable(Touchable.disabled);\n\t}\n\n\tstatic {\n\t\t// Blocks mouse input.\n\t\tBLOCKER.addListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean mouseMoved (final InputEvent event, final float x, final float y) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (final InputEvent event, final float x, final float y, final int pointer, final int button) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean scrolled (final InputEvent event, final float x, final float y, final float amountX, final float amountY) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * @param actor will have this listener attached and all other {@link Draggable} listeners removed. If you want multiple\n\t * {@link Draggable} listeners or you are sure that the widget has no other {@link Draggable}s attached, you can add\n\t * the listener using the standard method: {@link Actor#addListener(EventListener)} - avoiding validation and\n\t * iteration over actor's listeners.\n\t */\n\tpublic void attachTo (final Actor actor) {\n\t\tfor (final Iterator<EventListener> listeners = actor.getListeners().iterator(); listeners.hasNext(); ) {\n\t\t\tfinal EventListener listener = listeners.next();\n\t\t\tif (listener instanceof Draggable) {\n\t\t\t\tlisteners.remove();\n\t\t\t}\n\t\t}\n\t\tactor.addListener(this);\n\t}\n\n\t/** @return during dragging, this is the offset value on X axis from the start of the dragged widget. */\n\tpublic float getOffsetX () {\n\t\treturn offsetX;\n\t}\n\n\t/** @return during dragging, this is the offset value on Y axis from the start of the dragged widget. */\n\tpublic float getOffsetY () {\n\t\treturn offsetY;\n\t}\n\n\t/** @return alpha color value of dragged actor copy. */\n\tpublic float getAlpha () {\n\t\treturn alpha;\n\t}\n\n\t/** @param alpha alpha color value of dragged actor copy. */\n\tpublic void setAlpha (final float alpha) {\n\t\tthis.alpha = alpha;\n\t}\n\n\t/** @return true if mouse input is blocked during dragging. */\n\tpublic boolean isBlockingInput () {\n\t\treturn blockInput;\n\t}\n\n\t/**\n\t * @param blockInput true if mouse input should be blocked during actors dragging. If false, other actors might still receive\n\t * mouse events (for example, buttons might switch to \"over\" style).\n\t */\n\tpublic void setBlockInput (final boolean blockInput) {\n\t\tthis.blockInput = blockInput;\n\t}\n\n\t/** @return if true, original actor is invisible while it's being dragged. */\n\tpublic boolean isInvisibleWhenDragged () {\n\t\treturn invisibleWhenDragged;\n\t}\n\n\t/** @param invisibleWhenDragged if true, original actor is invisible while it's being dragged. */\n\tpublic void setInvisibleWhenDragged (final boolean invisibleWhenDragged) {\n\t\tthis.invisibleWhenDragged = invisibleWhenDragged;\n\t}\n\n\t/** @return if true, widget cannot be dragged out of the bounds of its parent. */\n\tpublic boolean isKeptWithinParent () {\n\t\treturn keepWithinParent;\n\t}\n\n\t/**\n\t * @param keepWithinParent if true, widget cannot be dragged out of the bounds of its parent. Stage coordinates in listener\n\t * will always be inside the parent. Note that for this setting to work properly, both actor and its parent have to\n\t * correctly return their sizes with {@link Actor#getWidth()} and {@link Actor#getHeight()} methods.\n\t */\n\tpublic void setKeepWithinParent (final boolean keepWithinParent) {\n\t\tthis.keepWithinParent = keepWithinParent;\n\t}\n\n\t/** @return distance from the widget's parent in which the actor is not dragged out of parent bounds. */\n\tpublic float getDeadzoneRadius () {\n\t\treturn deadzoneRadius;\n\t}\n\n\t/**\n\t * @param deadzoneRadius distance from the widget's parent in which the actor is not dragged out of parent bounds. Defaults to\n\t * 0f. Values lower or equal to 0 are ignored during dragging. If {@link #isKeptWithinParent()} returns true, this\n\t * value is ignored and actor is always kept within parent.\n\t */\n\tpublic void setDeadzoneRadius (float deadzoneRadius) {\n\t\tthis.deadzoneRadius = deadzoneRadius;\n\t}\n\n\t/** @return time after which the dragged actor copy disappears. */\n\tpublic float getFadingTime () {\n\t\treturn fadingTime;\n\t}\n\n\t/** @param fadingTime time after which the dragged actor copy disappears. */\n\tpublic void setFadingTime (final float fadingTime) {\n\t\tthis.fadingTime = fadingTime;\n\t}\n\n\t/** @return time after which the dragged actor copy returns to its origin. */\n\tpublic float getMovingTime () {\n\t\treturn movingTime;\n\t}\n\n\t/** @param movingTime time after which the dragged actor copy returns to its origin. */\n\tpublic void setMovingTime (final float movingTime) {\n\t\tthis.movingTime = movingTime;\n\t}\n\n\t/** @param movingInterpolation used to move the dragged widgets to the original position when their drag was cancelled. */\n\tpublic void setMovingInterpolation (final Interpolation movingInterpolation) {\n\t\tthis.movingInterpolation = movingInterpolation;\n\t}\n\n\t/** @param fadingInterpolation used to fade out dragged widgets after their drag was accepted. */\n\tpublic void setFadingInterpolation (final Interpolation fadingInterpolation) {\n\t\tthis.fadingInterpolation = fadingInterpolation;\n\t}\n\n\t/**\n\t * @param listener is being notified of draggable events and can change its behavior. Can be null.\n\t * @see DragAdapter\n\t */\n\tpublic void setListener (final DragListener listener) {\n\t\tthis.listener = listener;\n\t}\n\n\t/** @return listener notified of draggable events. Can be null. */\n\tpublic DragListener getListener () {\n\t\treturn listener;\n\t}\n\n\t@Override\n\tpublic boolean touchDown (final InputEvent event, final float x, final float y, final int pointer, final int button) {\n\t\tfinal Actor actor = event.getListenerActor();\n\t\tif (!isValid(actor) || isDisabled(actor)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (listener == null || listener.onStart(this, actor, event.getStageX(), event.getStageY())) {\n\t\t\tattachMimic(actor, event, x, y);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * @param actor might be already removed.\n\t * @return true if actor is not null and has a {@link Stage}.\n\t */\n\tprotected boolean isValid (final Actor actor) {\n\t\treturn actor != null && actor.getStage() != null;\n\t}\n\n\t/**\n\t * @param actor might be a {@link Disableable}.\n\t * @return true if actor is disabled.\n\t */\n\tprotected boolean isDisabled (final Actor actor) {\n\t\treturn actor instanceof Disableable && ((Disableable) actor).isDisabled();\n\t}\n\n\t/**\n\t * @param actor has the listener attached.\n\t * @param event touch down event which triggered mimic spawning.\n\t * @param x actor's relative X event position.\n\t * @param y actor's relative Y event position.\n\t */\n\tprotected void attachMimic (final Actor actor, final InputEvent event, final float x, final float y) {\n\t\tmimic.clearActions();\n\t\tmimic.getColor().a = alpha;\n\t\tmimic.setActor(actor);\n\t\toffsetX = -x;\n\t\toffsetY = -y;\n\t\tgetStageCoordinates(event);\n\t\tdragStartX = MIMIC_COORDINATES.x;\n\t\tdragStartY = MIMIC_COORDINATES.y;\n\t\tmimic.setPosition(dragStartX, dragStartY);\n\t\tactor.getStage().addActor(mimic);\n\t\tmimic.toFront();\n\t\tactor.setVisible(!invisibleWhenDragged);\n\t\tif (blockInput) {\n\t\t\taddBlocker(actor.getStage());\n\t\t}\n\t}\n\n\t/** @param stage will contain a mock-up blocker actor, which blocks all mouse input. */\n\tprotected static void addBlocker (final Stage stage) {\n\t\tstage.addActor(BLOCKER);\n\t\tBLOCKER.setBounds(0f, 0f, stage.getWidth(), stage.getHeight());\n\t\tBLOCKER.toFront();\n\t}\n\n\t/** Removes mock-up blocker actor from the stage. */\n\tprotected static void removeBlocker () {\n\t\tBLOCKER.remove();\n\t}\n\n\t/** @param event will extract stage coordinates from the event, respecting mimic offset and other dragging settings. */\n\tprotected void getStageCoordinates (final InputEvent event) {\n\t\tif (keepWithinParent) {\n\t\t\tgetStageCoordinatesWithinParent(event);\n\t\t} else if (deadzoneRadius > 0f) {\n\t\t\tgetStageCoordinatesWithDeadzone(event);\n\t\t} else {\n\t\t\tgetStageCoordinatesWithOffset(event);\n\t\t}\n\t}\n\n\tprivate void getStageCoordinatesWithDeadzone (final InputEvent event) {\n\t\tfinal Actor parent = mimic.getActor().getParent();\n\t\tif (parent != null) {\n\t\t\tMIMIC_COORDINATES.set(Vector2.Zero);\n\t\t\tparent.localToStageCoordinates(MIMIC_COORDINATES);\n\t\t\tfinal float parentX = MIMIC_COORDINATES.x;\n\t\t\tfinal float parentY = MIMIC_COORDINATES.y;\n\t\t\tfinal float parentEndX = parentX + parent.getWidth();\n\t\t\tfinal float parentEndY = parentY + parent.getHeight();\n\t\t\tif (isWithinDeadzone(event, parentX, parentY, parentEndX, parentEndY)) {\n\t\t\t\t// Keeping within parent bounds:\n\t\t\t\tMIMIC_COORDINATES.set(event.getStageX() + offsetX, event.getStageY() + offsetY);\n\t\t\t\tif (MIMIC_COORDINATES.x < parentX) {\n\t\t\t\t\tMIMIC_COORDINATES.x = parentX;\n\t\t\t\t} else if (MIMIC_COORDINATES.x + mimic.getWidth() > parentEndX) {\n\t\t\t\t\tMIMIC_COORDINATES.x = parentEndX - mimic.getWidth();\n\t\t\t\t}\n\t\t\t\tif (MIMIC_COORDINATES.y < parentY) {\n\t\t\t\t\tMIMIC_COORDINATES.y = parentY;\n\t\t\t\t} else if (MIMIC_COORDINATES.y + mimic.getHeight() > parentEndY) {\n\t\t\t\t\tMIMIC_COORDINATES.y = parentEndY - mimic.getHeight();\n\t\t\t\t}\n\t\t\t\tSTAGE_COORDINATES.set(MathUtils.clamp(event.getStageX(), parentX, parentEndX - 1f),\n\t\t\t\t\t\tMathUtils.clamp(event.getStageY(), parentY, parentEndY - 1f));\n\t\t\t} else {\n\t\t\t\tgetStageCoordinatesWithOffset(event);\n\t\t\t}\n\t\t} else {\n\t\t\tgetStageCoordinatesWithOffset(event);\n\t\t}\n\t}\n\n\tprivate boolean isWithinDeadzone (InputEvent event, float parentX, float parentY, float parentEndX, float parentEndY) {\n\t\treturn parentX - deadzoneRadius <= event.getStageX() && parentEndX + deadzoneRadius >= event.getStageX()\n\t\t\t\t&& parentY - deadzoneRadius <= event.getStageY() && parentEndY + deadzoneRadius >= event.getStageY();\n\t}\n\n\tprivate void getStageCoordinatesWithinParent (final InputEvent event) {\n\t\tfinal Actor parent = mimic.getActor().getParent();\n\t\tif (parent != null) {\n\t\t\tMIMIC_COORDINATES.set(Vector2.Zero);\n\t\t\tparent.localToStageCoordinates(MIMIC_COORDINATES);\n\t\t\tfinal float parentX = MIMIC_COORDINATES.x;\n\t\t\tfinal float parentY = MIMIC_COORDINATES.y;\n\t\t\tfinal float parentEndX = parentX + parent.getWidth();\n\t\t\tfinal float parentEndY = parentY + parent.getHeight();\n\t\t\tMIMIC_COORDINATES.set(event.getStageX() + offsetX, event.getStageY() + offsetY);\n\t\t\tif (MIMIC_COORDINATES.x < parentX) {\n\t\t\t\tMIMIC_COORDINATES.x = parentX;\n\t\t\t} else if (MIMIC_COORDINATES.x + mimic.getWidth() > parentEndX) {\n\t\t\t\tMIMIC_COORDINATES.x = parentEndX - mimic.getWidth();\n\t\t\t}\n\t\t\tif (MIMIC_COORDINATES.y < parentY) {\n\t\t\t\tMIMIC_COORDINATES.y = parentY;\n\t\t\t} else if (MIMIC_COORDINATES.y + mimic.getHeight() > parentEndY) {\n\t\t\t\tMIMIC_COORDINATES.y = parentEndY - mimic.getHeight();\n\t\t\t}\n\t\t\tSTAGE_COORDINATES.set(MathUtils.clamp(event.getStageX(), parentX, parentEndX - 1f),\n\t\t\t\t\tMathUtils.clamp(event.getStageY(), parentY, parentEndY - 1f));\n\t\t} else {\n\t\t\tgetStageCoordinatesWithOffset(event);\n\t\t}\n\t}\n\n\tprivate void getStageCoordinatesWithOffset (final InputEvent event) {\n\t\tMIMIC_COORDINATES.set(event.getStageX() + offsetX, event.getStageY() + offsetY);\n\t\tSTAGE_COORDINATES.set(event.getStageX(), event.getStageY());\n\t}\n\n\t@Override\n\tpublic void touchDragged (final InputEvent event, final float x, final float y, final int pointer) {\n\t\tif (isDragged()) {\n\t\t\tgetStageCoordinates(event);\n\t\t\tmimic.setPosition(MIMIC_COORDINATES.x, MIMIC_COORDINATES.y);\n\t\t\tif (listener != null) {\n\t\t\t\tlistener.onDrag(this, mimic.getActor(), STAGE_COORDINATES.x, STAGE_COORDINATES.y);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void touchUp (final InputEvent event, final float x, final float y, final int pointer, final int button) {\n\t\tif (isDragged()) {\n\t\t\tremoveBlocker();\n\t\t\tgetStageCoordinates(event);\n\t\t\tmimic.setPosition(MIMIC_COORDINATES.x, MIMIC_COORDINATES.y);\n\t\t\tif (listener == null || mimic.getActor().getStage() != null\n\t\t\t\t\t&& listener.onEnd(this, mimic.getActor(), STAGE_COORDINATES.x, STAGE_COORDINATES.y)) {\n\t\t\t\t// Drag end approved - fading out.\n\t\t\t\taddMimicHidingAction(Actions.fadeOut(fadingTime, fadingInterpolation), fadingTime);\n\t\t\t} else {\n\t\t\t\t// Drag end cancelled - returning to the original position.\n\t\t\t\taddMimicHidingAction(Actions.moveTo(dragStartX, dragStartY, movingTime, movingInterpolation), movingTime);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** @return true if some actor with this listener attached is currently dragged. */\n\tpublic boolean isDragged () {\n\t\treturn mimic.getActor() != null;\n\t}\n\n\t/** @param hidingAction will be attached to the mimic actor. */\n\tprotected void addMimicHidingAction (final Action hidingAction, final float delay) {\n\t\tmimic.addAction(Actions.sequence(hidingAction, Actions.removeActor()));\n\t\tmimic.getActor().addAction(Actions.delay(delay, Actions.visible(true)));\n\t}\n\n\t/**\n\t * Allows to control {@link Draggable} behavior.\n\t * @author MJ\n\t * @since 0.9.3\n\t */\n\tpublic static interface DragListener {\n\t\t/** Use in listner's method for code clarity. */\n\t\tboolean CANCEL = false, APPROVE = true;\n\n\t\t/**\n\t\t * @param draggable source of event.\n\t\t * @param actor is about to be dragged.\n\t\t * @param stageX stage coordinate on X axis where the drag started.\n\t\t * @param stageY stage coordinate on Y axis where the drag started.\n\t\t * @return if true, actor will not be dragged.\n\t\t */\n\t\tboolean onStart (Draggable draggable, Actor actor, float stageX, float stageY);\n\n\t\t/**\n\t\t * @param draggable source of event.\n\t\t * @param actor is being dragged.\n\t\t * @param stageX stage coordinate on X axis with current cursor position.\n\t\t * @param stageY stage coordinate on Y axis with current cursor position.\n\t\t */\n\t\tvoid onDrag (Draggable draggable, Actor actor, float stageX, float stageY);\n\n\t\t/**\n\t\t * @param draggable source of event.\n\t\t * @param actor is about to stop being dragged.\n\t\t * @param stageX stage coordinate on X axis where the drag ends.\n\t\t * @param stageY stage coordinate on X axis where the drag ends.\n\t\t * @return if true, \"mirror\" of the actor will quickly fade out. If false, mirror will return to the original actor's\n\t\t * position.\n\t\t */\n\t\tboolean onEnd (Draggable draggable, Actor actor, float stageX, float stageY);\n\t}\n\n\t/**\n\t * Default, empty implementation of {@link DragListener}. Approves all drag requests.\n\t * @author MJ\n\t * @since 0.9.3\n\t */\n\tpublic static class DragAdapter implements DragListener {\n\t\t@Override\n\t\tpublic boolean onStart (final Draggable draggable, final Actor actor, final float stageX, final float stageY) {\n\t\t\treturn APPROVE;\n\t\t}\n\n\t\t@Override\n\t\tpublic void onDrag (final Draggable draggable, final Actor actor, final float stageX, final float stageY) {\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean onEnd (final Draggable draggable, final Actor actor, final float stageX, final float stageY) {\n\t\t\treturn APPROVE;\n\t\t}\n\t}\n\n\t/**\n\t * Draws the chosen actor with modified alpha value in a custom position. Clears mimicked actor upon removing from the stage.\n\t * @author MJ\n\t * @since 0.9.3\n\t */\n\tpublic static class MimicActor extends Actor {\n\t\tprivate static final Vector2 LAST_POSITION = new Vector2();\n\t\tprivate Actor actor;\n\n\t\t/** Has no actor to mimic. See {@link #setActor(Actor)}. */\n\t\tpublic MimicActor () {\n\t\t}\n\n\t\t/** @param actor will be mimicked. */\n\t\tpublic MimicActor (final Actor actor) {\n\t\t\tthis.actor = actor;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean remove () {\n\t\t\tactor = null;\n\t\t\treturn super.remove();\n\t\t}\n\n\t\t/** @return mimicked actor. */\n\t\tpublic Actor getActor () {\n\t\t\treturn actor;\n\t\t}\n\n\t\t/** @param actor will be mimicked. */\n\t\tpublic void setActor (final Actor actor) {\n\t\t\tthis.actor = actor;\n\t\t}\n\n\t\t@Override\n\t\tpublic float getWidth () {\n\t\t\treturn actor == null ? 0f : actor.getWidth();\n\t\t}\n\n\t\t@Override\n\t\tpublic float getHeight () {\n\t\t\treturn actor == null ? 0f : actor.getHeight();\n\t\t}\n\n\t\t@Override\n\t\tpublic void draw (final Batch batch, final float parentAlpha) {\n\t\t\tif (actor != null) {\n\t\t\t\tLAST_POSITION.set(actor.getX(), actor.getY());\n\t\t\t\tactor.setPosition(getX(), getY());\n\t\t\t\tactor.draw(batch, getColor().a * parentAlpha);\n\t\t\t\tactor.setPosition(LAST_POSITION.x, LAST_POSITION.y);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/HighlightTextArea.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.graphics.g2d.BitmapFont;\nimport com.badlogic.gdx.graphics.g2d.GlyphLayout;\nimport com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;\nimport com.badlogic.gdx.utils.Array;\nimport com.badlogic.gdx.utils.Pool;\nimport com.badlogic.gdx.utils.Pools;\nimport com.kotcrab.vis.ui.util.highlight.BaseHighlighter;\nimport com.kotcrab.vis.ui.util.highlight.Highlight;\nimport com.kotcrab.vis.ui.util.highlight.Highlighter;\n\n/**\n * Text area implementation supporting highlighting words and scrolling in both X and Y directions.\n * <p>\n * For best scroll pane settings you should create scroll pane using {@link #createCompatibleScrollPane()}.\n * <p>\n * Note about overlapping highlights: this text area can handle overlapping highlights, highlights that starts earlier\n * have higher priority. If two highlights have the exactly the same start point, then it is undefined which highlight\n * will be used and depends on how array containing highlights will be sorted.\n * @author Kotcrab\n * @see Highlighter\n * @since 1.1.2\n */\npublic class HighlightTextArea extends ScrollableTextArea {\n\tprivate Array<Highlight> highlights = new Array<Highlight>();\n\tprivate Array<Chunk> renderChunks = new Array<Chunk>();\n\tprivate boolean chunkUpdateScheduled = true;\n\tprivate Color defaultColor = Color.WHITE;\n\n\tprivate BaseHighlighter highlighter;\n\n\tprivate float maxAreaWidth = 0;\n\tprivate float maxAreaHeight = 0;\n\n\tpublic HighlightTextArea (String text) {\n\t\tsuper(text);\n\t\tinit();\n\t}\n\n\tpublic HighlightTextArea (String text, String styleName) {\n\t\tsuper(text, styleName);\n\t\tinit();\n\t}\n\n\tpublic HighlightTextArea (String text, VisTextFieldStyle style) {\n\t\tsuper(text, style);\n\t\tinit();\n\t}\n\n\tprivate void init() {\n\t\tsoftwrap = false;\n\t}\n\n\t@Override\n\tvoid updateDisplayText () {\n\t\tsuper.updateDisplayText();\n\t\tprocessHighlighter();\n\t}\n\n\t@Override\n\tprotected void calculateOffsets () {\n\t\tsuper.calculateOffsets();\n\t\tif (chunkUpdateScheduled == false) return;\n\t\tchunkUpdateScheduled = false;\n\t\thighlights.sort();\n\t\trenderChunks.clear();\n\n\t\tString text = getText();\n\n\t\tPool<GlyphLayout> layoutPool = Pools.get(GlyphLayout.class);\n\t\tGlyphLayout layout = layoutPool.obtain();\n\t\tboolean carryHighlight = false;\n\t\tfor (int lineIdx = 0, highlightIdx = 0; lineIdx < linesBreak.size; lineIdx += 2) {\n\t\t\tint lineStart = linesBreak.items[lineIdx];\n\t\t\tint lineEnd = linesBreak.items[lineIdx + 1];\n\t\t\tint lineProgress = lineStart;\n\t\t\tfloat chunkOffset = 0;\n\n\t\t\tfor (; highlightIdx < highlights.size; ) {\n\t\t\t\tHighlight highlight = highlights.get(highlightIdx);\n\t\t\t\tif (highlight.getStart() > lineEnd) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (highlight.getStart() == lineProgress || carryHighlight) {\n\t\t\t\t\trenderChunks.add(new Chunk(text.substring(lineProgress, Math.min(highlight.getEnd(), lineEnd)), highlight.getColor(), chunkOffset, lineIdx));\n\t\t\t\t\tlineProgress = Math.min(highlight.getEnd(), lineEnd);\n\n\t\t\t\t\tif (highlight.getEnd() > lineEnd) {\n\t\t\t\t\t\tcarryHighlight = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcarryHighlight = false;\n\t\t\t\t\t\thighlightIdx++;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t//protect against overlapping highlights\n\t\t\t\t\tboolean noMatch = false;\n\t\t\t\t\twhile (highlight.getStart() <= lineProgress) {\n\t\t\t\t\t\thighlightIdx++;\n\t\t\t\t\t\tif (highlightIdx >= highlights.size) {\n\t\t\t\t\t\t\tnoMatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\thighlight = highlights.get(highlightIdx);\n\t\t\t\t\t\tif (highlight.getStart() > lineEnd) {\n\t\t\t\t\t\t\tnoMatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (noMatch) break;\n\t\t\t\t\trenderChunks.add(new Chunk(text.substring(lineProgress, highlight.getStart()), defaultColor, chunkOffset, lineIdx));\n\t\t\t\t\tlineProgress = highlight.getStart();\n\t\t\t\t}\n\n\t\t\t\tChunk chunk = renderChunks.peek();\n\t\t\t\tlayout.setText(style.font, chunk.text);\n\t\t\t\tchunkOffset += layout.width;\n\t\t\t\t//current highlight needs to be applied to next line meaning that there is no other highlights that can be applied to currently parsed line\n\t\t\t\tif (carryHighlight) break;\n\t\t\t}\n\n\t\t\tif (lineProgress < lineEnd) {\n\t\t\t\trenderChunks.add(new Chunk(text.substring(lineProgress, lineEnd), defaultColor, chunkOffset, lineIdx));\n\t\t\t}\n\t\t}\n\n\t\tmaxAreaWidth = 0;\n\t\tfor (String line : text.split(\"\\\\n\")) {\n\t\t\tlayout.setText(style.font, line);\n\t\t\tmaxAreaWidth = Math.max(maxAreaWidth, layout.width + 30);\n\t\t}\n\n\t\tlayoutPool.free(layout);\n\t\tupdateScrollLayout();\n\t}\n\n\t@Override\n\tprotected void drawText (Batch batch, BitmapFont font, float x, float y) {\n\t\tmaxAreaHeight = 0;\n\t\tfloat offsetY = 0;\n\t\tfloat parentAlpha = font.getColor().a;\n\t\tfor (int i = firstLineShowing * 2; i < (firstLineShowing + linesShowing) * 2 && i < linesBreak.size; i += 2) {\n\t\t\tfor (Chunk chunk : renderChunks) {\n\t\t\t\tif (chunk.lineIndex == i) {\n\t\t\t\t\tfont.setColor(chunk.color);\n\t\t\t\t\tfont.getColor().a *= parentAlpha;\n\t\t\t\t\tfont.draw(batch, chunk.text, x + chunk.offsetX, y + offsetY);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toffsetY -= font.getLineHeight();\n\t\t\tmaxAreaHeight += font.getLineHeight();\n\t\t}\n\n\t\tmaxAreaHeight += 30;\n\t}\n\n\t/**\n\t * Processes highlighter rules, collects created highlights and schedules text area displayed text update. This should be called\n\t * after highlighter rules has changed to update highlights.\n\t */\n\tpublic void processHighlighter () {\n\t\tif (highlights == null) return;\n\t\thighlights.clear();\n\t\tif (highlighter != null) highlighter.process(this, highlights);\n\t\tchunkUpdateScheduled = true;\n\t}\n\n\t/**\n\t * Changes highlighter of text area. Note that you don't have to call {@link #processHighlighter()} after changing\n\t * highlighter - you only have to call it when highlighter rules has changed.\n\t */\n\tpublic void setHighlighter (BaseHighlighter highlighter) {\n\t\tthis.highlighter = highlighter;\n\t\tprocessHighlighter();\n\t}\n\n\tpublic BaseHighlighter getHighlighter () {\n\t\treturn highlighter;\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\treturn maxAreaWidth + 5;\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\treturn maxAreaHeight + 5;\n\t}\n\n\t@Override\n\tpublic ScrollPane createCompatibleScrollPane () {\n\t\tScrollPane scrollPane = super.createCompatibleScrollPane();\n\t\tscrollPane.setScrollingDisabled(false, false);\n\t\treturn scrollPane;\n\t}\n\n\tprivate static class Chunk {\n\t\tString text;\n\t\tColor color;\n\t\tfloat offsetX;\n\t\tint lineIndex;\n\n\t\tpublic Chunk (String text, Color color, float offsetX, int lineIndex) {\n\t\t\tthis.text = text;\n\t\t\tthis.color = color;\n\t\t\tthis.offsetX = offsetX;\n\t\t\tthis.lineIndex = lineIndex;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/HorizontalCollapsibleWidget.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.math.Interpolation;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.actions.FloatAction;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;\nimport com.badlogic.gdx.utils.GdxRuntimeException;\n\n/**\n * Widget containing table that can be horizontally collapsed.\n * @author Kotcrab\n * @see CollapsibleWidget\n * @since 1.2.5\n */\npublic class HorizontalCollapsibleWidget extends WidgetGroup {\n\tprivate Table table;\n\n\tprivate CollapseAction collapseAction = new CollapseAction();\n\tprivate float collapseDuration = 0.3f;\n\tprivate Interpolation collapseInterpolation = Interpolation.pow3Out;\n\n\tprivate boolean collapsed;\n\tprivate boolean actionRunning;\n\n\tprivate float currentWidth;\n\n\tpublic HorizontalCollapsibleWidget () {\n\t}\n\n\tpublic HorizontalCollapsibleWidget (Table table) {\n\t\tthis(table, false);\n\t}\n\n\tpublic HorizontalCollapsibleWidget (Table table, boolean collapsed) {\n\t\tthis.collapsed = collapsed;\n\t\tthis.table = table;\n\n\t\tupdateTouchable();\n\n\t\tif (table != null) addActor(table);\n\t}\n\n\tpublic void setCollapsed (boolean collapse, boolean withAnimation) {\n\t\tthis.collapsed = collapse;\n\t\tupdateTouchable();\n\n\t\tif (table == null) return;\n\n\t\tactionRunning = true;\n\n\t\tif (withAnimation) {\n\t\t\tcollapseAction.reset();\n\t\t\tcollapseAction.setStart(currentWidth);\n\t\t\tcollapseAction.setEnd(collapse ? 0f : table.getPrefWidth());\n\t\t\tcollapseAction.setDuration(collapseDuration);\n\t\t\tcollapseAction.setInterpolation(collapseInterpolation);\n\t\t\taddAction(collapseAction);\n\t\t} else {\n\t\t\tif (collapse) {\n\t\t\t\tcurrentWidth = 0;\n\t\t\t\tcollapsed = true;\n\t\t\t} else {\n\t\t\t\tcurrentWidth = table.getPrefWidth();\n\t\t\t\tcollapsed = false;\n\t\t\t}\n\n\t\t\tactionRunning = false;\n\t\t\tinvalidateHierarchy();\n\t\t}\n\t}\n\n\tpublic void setCollapsed (boolean collapse) {\n\t\tsetCollapsed(collapse, true);\n\t}\n\n\tpublic boolean isCollapsed () {\n\t\treturn collapsed;\n\t}\n\n\tprivate void updateTouchable () {\n\t\tif (collapsed)\n\t\t\tsetTouchable(Touchable.disabled);\n\t\telse\n\t\t\tsetTouchable(Touchable.enabled);\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tif (currentWidth > 1 && getX() + currentWidth > 1) {\n\t\t\tif (actionRunning) {\n\t\t\t\tbatch.flush();\n\t\t\t\tboolean clipEnabled = clipBegin(getX(), getY(), currentWidth, getHeight());\n\n\t\t\t\tsuper.draw(batch, parentAlpha);\n\n\t\t\t\tbatch.flush();\n\t\t\t\tif (clipEnabled) clipEnd();\n\t\t\t} else {\n\t\t\t\tsuper.draw(batch, parentAlpha);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void layout () {\n\t\tif (table == null) return;\n\n\t\ttable.setBounds(0, 0, table.getPrefWidth(), table.getPrefHeight());\n\n\t\tif (actionRunning == false) {\n\t\t\tif (collapsed)\n\t\t\t\tcurrentWidth = 0;\n\t\t\telse\n\t\t\t\tcurrentWidth = table.getPrefWidth();\n\t\t}\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\treturn table == null ? 0 : table.getPrefHeight();\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\tif (table == null) return 0;\n\n\t\tif (actionRunning == false) {\n\t\t\tif (collapsed)\n\t\t\t\treturn 0;\n\t\t\telse\n\t\t\t\treturn table.getPrefWidth();\n\t\t}\n\n\t\treturn currentWidth;\n\t}\n\n\tpublic void setTable (Table table) {\n\t\tthis.table = table;\n\t\tclearChildren();\n\t\taddActor(table);\n\t}\n\n\t@Override\n\tprotected void childrenChanged () {\n\t\tsuper.childrenChanged();\n\t\tif (getChildren().size > 1) throw new GdxRuntimeException(\"Only one actor can be added to CollapsibleWidget\");\n\t}\n\n\tprivate class CollapseAction extends FloatAction {\n\n\t\t@Override\n\t\tprotected void update (float percent) {\n\t\t\tsuper.update(percent);\n\t\t\tcurrentWidth = getValue();\n\n\t\t\tif (percent == 1) {\n\t\t\t\tactionRunning = false;\n\t\t\t\tcollapsed = currentWidth == 0;\n\t\t\t}\n\n\t\t\tinvalidateHierarchy();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/LinkLabel.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.Input.Buttons;\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.graphics.Cursor.SystemCursor;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.graphics.g2d.BitmapFont;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.CursorManager;\n\n/**\n * Simple LinkLabel allows to create label with clickable link and underline on mouse over. Link can have custom text.\n * By default clicking link will open it in default browser, this can be changed by settings label listener.\n * @author Kotcrab\n * @since 0.7.2\n */\npublic class LinkLabel extends VisLabel {\n\tstatic private final Color tempColor = new Color();\n\n\tprivate LinkLabelStyle style;\n\tprivate ClickListener clickListener;\n\n\tprivate LinkLabelListener listener;\n\tprivate CharSequence url;\n\n\tpublic LinkLabel (CharSequence url) {\n\t\tsuper(url, VisUI.getSkin().get(LinkLabelStyle.class));\n\t\tinit(url);\n\t}\n\n\tpublic LinkLabel (CharSequence text, CharSequence url) {\n\t\tsuper(text, VisUI.getSkin().get(LinkLabelStyle.class));\n\t\tinit(url);\n\t}\n\n\tpublic LinkLabel (CharSequence text, int alignment) {\n\t\tsuper(text, VisUI.getSkin().get(LinkLabelStyle.class));\n\t\tsetAlignment(alignment);\n\t\tinit(text);\n\t}\n\n\tpublic LinkLabel (CharSequence text, Color textColor) {\n\t\tsuper(text, VisUI.getSkin().get(LinkLabelStyle.class));\n\t\tsetColor(textColor);\n\t\tinit(text);\n\t}\n\n\tpublic LinkLabel (CharSequence text, LinkLabelStyle style) {\n\t\tsuper(text, style);\n\t\tinit(text);\n\t}\n\n\tpublic LinkLabel (CharSequence text, CharSequence url, String styleName) {\n\t\tsuper(text, VisUI.getSkin().get(styleName, LinkLabelStyle.class));\n\t\tinit(url);\n\t}\n\n\tpublic LinkLabel (CharSequence text, CharSequence url, LinkLabelStyle style) {\n\t\tsuper(text, style);\n\t\tinit(url);\n\t}\n\n\tpublic LinkLabel (CharSequence text, String fontName, Color color) {\n\t\tsuper(text, new LinkLabelStyle(VisUI.getSkin().getFont(fontName), color, VisUI.getSkin().getDrawable(\"white\")));\n\t\tinit(text);\n\t}\n\n\t@Override\n\tpublic LinkLabelStyle getStyle () {\n\t\treturn (LinkLabelStyle) super.getStyle();\n\t}\n\n\tprivate void init (CharSequence linkUrl) {\n\t\tthis.url = linkUrl;\n\t\tstyle = getStyle();\n\n\t\taddListener(clickListener = new ClickListener(Buttons.LEFT) {\n\t\t\t@Override\n\t\t\tpublic void clicked (InputEvent event, float x, float y) {\n\t\t\t\tsuper.clicked(event, x, y);\n\n\t\t\t\tif (listener == null) {\n\t\t\t\t\tGdx.net.openURI(url.toString());\n\t\t\t\t} else {\n\t\t\t\t\tlistener.clicked(url.toString());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void enter (InputEvent event, float x, float y, int pointer, Actor fromActor) {\n\t\t\t\tsuper.enter(event, x, y, pointer, fromActor);\n\t\t\t\tGdx.graphics.setSystemCursor(SystemCursor.Hand);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void exit (InputEvent event, float x, float y, int pointer, Actor toActor) {\n\t\t\t\tsuper.exit(event, x, y, pointer, toActor);\n\t\t\t\tCursorManager.restoreDefaultCursor();\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tsuper.draw(batch, parentAlpha);\n\t\tDrawable underline = style.underline;\n\t\tif (underline != null && clickListener.isOver()) {\n\t\t\tColor color = tempColor.set(getColor());\n\t\t\tcolor.a *= parentAlpha;\n\t\t\tif (style.fontColor != null) color.mul(style.fontColor);\n\t\t\tbatch.setColor(color);\n\t\t\tunderline.draw(batch, getX(), getY(), getWidth(), 1);\n\t\t}\n\t}\n\n\tpublic CharSequence getUrl () {\n\t\treturn url;\n\t}\n\n\tpublic void setUrl (CharSequence url) {\n\t\tthis.url = url;\n\t}\n\n\tpublic LinkLabelListener getListener () {\n\t\treturn listener;\n\t}\n\n\tpublic void setListener (LinkLabelListener listener) {\n\t\tthis.listener = listener;\n\t}\n\n\tpublic interface LinkLabelListener {\n\t\tvoid clicked (String url);\n\t}\n\n\tpublic static class LinkLabelStyle extends LabelStyle {\n\t\t/** Optional */\n\t\tpublic Drawable underline;\n\n\t\tpublic LinkLabelStyle () {\n\t\t}\n\n\t\tpublic LinkLabelStyle (BitmapFont font, Color fontColor, Drawable underline) {\n\t\t\tsuper(font, fontColor);\n\t\t\tthis.underline = underline;\n\t\t}\n\n\t\tpublic LinkLabelStyle (LinkLabelStyle style) {\n\t\t\tsuper(style);\n\t\t\tthis.underline = style.underline;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/ListView.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.Stage;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.adapter.AbstractListAdapter;\nimport com.kotcrab.vis.ui.util.adapter.ArrayAdapter;\nimport com.kotcrab.vis.ui.util.adapter.ArrayListAdapter;\nimport com.kotcrab.vis.ui.util.adapter.ListAdapter;\n\n/**\n * ListView displays list of scrollable items. Item views are created by using {@link ListAdapter}s.\n * @author Kotcrab\n * @see ListAdapter\n * @see ArrayAdapter\n * @see ArrayListAdapter\n * @since 1.0.0\n */\npublic class ListView<ItemT> {\n\tprivate ListAdapter<ItemT> adapter;\n\tprivate ItemClickListener<ItemT> clickListener;\n\n\tprivate UpdatePolicy updatePolicy = UpdatePolicy.IMMEDIATELY;\n\tprivate boolean dataInvalidated = false;\n\n\tprivate ListViewTable<ItemT> mainTable;\n\tprivate VisScrollPane scrollPane;\n\n\tprivate VisTable scrollTable;\n\tprivate VisTable itemsTable;\n\n\tprivate Actor header;\n\tprivate Actor footer;\n\n\tpublic ListView (ListAdapter<ItemT> adapter) {\n\t\tthis(adapter, \"default\");\n\t}\n\n\tpublic ListView (ListAdapter<ItemT> adapter, String styleName) {\n\t\tthis(adapter, VisUI.getSkin().get(styleName, ListViewStyle.class));\n\t}\n\n\tpublic ListView (ListAdapter<ItemT> adapter, ListViewStyle style) {\n\t\tif (style == null) throw new IllegalArgumentException(\"style can't be null\");\n\t\tif (adapter == null) throw new IllegalArgumentException(\"adapter can't be null\");\n\t\tthis.adapter = adapter;\n\n\t\tmainTable = new ListViewTable<ItemT>(this);\n\t\tscrollTable = new VisTable();\n\t\titemsTable = new VisTable();\n\n\t\tscrollPane = new VisScrollPane(scrollTable, style.scrollPaneStyle);\n\t\tscrollPane.setOverscroll(false, true);\n\t\tscrollPane.setFlickScroll(false);\n\t\tscrollPane.setFadeScrollBars(false);\n\t\tmainTable.add(scrollPane).grow();\n\n\t\tadapter.setListView(this, new ListAdapterListener());\n\t\trebuildView(true);\n\t}\n\n\tpublic void rebuildView () {\n\t\trebuildView(true);\n\t}\n\n\tprivate void rebuildView (boolean full) {\n\t\tscrollTable.clearChildren();\n\t\tscrollTable.top();\n\t\tif (header != null) {\n\t\t\tscrollTable.add(header).growX();\n\t\t\tscrollTable.row();\n\t\t}\n\n\t\tif (full) {\n\t\t\titemsTable.clearChildren();\n\t\t\tadapter.fillTable(itemsTable);\n\t\t}\n\n\t\tscrollTable.add(itemsTable).growX();\n\t\tscrollTable.row();\n\n\t\tif (footer != null) {\n\t\t\tscrollTable.add(footer).growX();\n\t\t\tscrollTable.row();\n\t\t}\n\t}\n\n\tpublic ListAdapter<ItemT> getAdapter () {\n\t\treturn adapter;\n\t}\n\n\t/** @return main table containing scroll pane and all items view */\n\tpublic ListViewTable<ItemT> getMainTable () {\n\t\treturn mainTable;\n\t}\n\n\t/**\n\t * @return internal {@link VisScrollPane}. Do NOT add this scroll pane directly to {@link Stage}\n\t * use {@link #getMainTable()} instead. Use this only for changing scroll pane properties.\n\t */\n\tpublic VisScrollPane getScrollPane () {\n\t\treturn scrollPane;\n\t}\n\n\tpublic void setItemClickListener (ItemClickListener<ItemT> listener) {\n\t\tthis.clickListener = listener;\n\t\tadapter.setItemClickListener(listener);\n\t}\n\n\tpublic ItemClickListener<ItemT> getClickListener () {\n\t\treturn clickListener;\n\t}\n\n\tpublic Actor getHeader () {\n\t\treturn header;\n\t}\n\n\tpublic void setHeader (Actor header) {\n\t\tthis.header = header;\n\t\trebuildView(false);\n\t}\n\n\tpublic Actor getFooter () {\n\t\treturn footer;\n\t}\n\n\tpublic void setFooter (Actor footer) {\n\t\tthis.footer = footer;\n\t\trebuildView(false);\n\t}\n\n\tpublic void setUpdatePolicy (UpdatePolicy updatePolicy) {\n\t\tthis.updatePolicy = updatePolicy;\n\t}\n\n\tpublic UpdatePolicy getUpdatePolicy () {\n\t\treturn updatePolicy;\n\t}\n\n\tpublic interface ItemClickListener<ItemT> {\n\t\tvoid clicked (ItemT item);\n\t}\n\n\tpublic class ListAdapterListener {\n\t\tpublic void invalidateDataSet () {\n\t\t\tif (updatePolicy == UpdatePolicy.IMMEDIATELY) rebuildView(true);\n\t\t\tif (updatePolicy == UpdatePolicy.ON_DRAW) dataInvalidated = true;\n\t\t}\n\t}\n\n\t/** Controls when list view's views are updated after underlying data was invalidated. */\n\tpublic enum UpdatePolicy {\n\t\t/** If list data was was invalidated then views are updated before drawing list. */\n\t\tON_DRAW,\n\t\t/** If list data was was invalidated then views are updated immediately after data invalidation. */\n\t\tIMMEDIATELY,\n\t\t/**\n\t\t * In manual mode ListView must be rebuild manually by calling {@link #rebuildView()}. Notification from adapter\n\t\t * about need to rebuild view will be ignored (see {@link AbstractListAdapter#itemsChanged()}). This mode should\n\t\t * be only used when it's really required to have manual control over how {@link ListView} rebuilds. Note that\n\t\t * ListView should be rebuild before user interacts with it.\n\t\t */\n\t\tMANUAL\n\t}\n\n\t/** ListView main table. */\n\tpublic static class ListViewTable<ItemT> extends VisTable {\n\t\tprivate ListView<ItemT> listView;\n\n\t\tprivate ListViewTable (ListView<ItemT> listView) {\n\t\t\tthis.listView = listView;\n\t\t}\n\n\t\t@Override\n\t\tpublic void draw (Batch batch, float parentAlpha) {\n\t\t\tif (listView.updatePolicy == UpdatePolicy.ON_DRAW && listView.dataInvalidated) listView.rebuildView(true);\n\t\t\tsuper.draw(batch, parentAlpha);\n\t\t}\n\n\t\tpublic ListView<ItemT> getListView () {\n\t\t\treturn listView;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/ListViewStyle.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;\n\n/** @author Kotcrab */\npublic class ListViewStyle {\n\tpublic ScrollPane.ScrollPaneStyle scrollPaneStyle;\n\n\tpublic ListViewStyle () {\n\t}\n\n\tpublic ListViewStyle (ListViewStyle style) {\n\t\tif (style.scrollPaneStyle != null) this.scrollPaneStyle = new ScrollPane.ScrollPaneStyle(style.scrollPaneStyle);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/Menu.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.math.Vector2;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.ui.TextButton;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.widget.VisTextButton.VisTextButtonStyle;\n\n/**\n * Menu used in {@link MenuBar}, it is a standard {@link PopupMenu} with tittle displayed in MenuBar.\n * @author Kotcrab\n */\npublic class Menu extends PopupMenu {\n\tprivate MenuBar menuBar;\n\n\tpublic VisTextButton openButton;\n\tpublic Drawable buttonDefault;\n\n\tprivate String title;\n\n\tpublic Menu (String title) {\n\t\tthis(title, \"default\");\n\t}\n\n\tpublic Menu (String title, String styleName) {\n\t\tthis(title, VisUI.getSkin().get(styleName, MenuStyle.class));\n\t}\n\n\tpublic Menu (String title, MenuStyle style) {\n\t\tsuper(style);\n\t\tthis.title = title;\n\n\t\topenButton = new VisTextButton(title, new VisTextButtonStyle(style.openButtonStyle));\n\t\tbuttonDefault = openButton.getStyle().up;\n\n\t\topenButton.addListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tif (menuBar.getCurrentMenu() == Menu.this) {\n\t\t\t\t\tmenuBar.closeMenu();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tswitchMenu();\n\t\t\t\tevent.stop();\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void enter (InputEvent event, float x, float y, int pointer, Actor fromActor) {\n\t\t\t\tif (menuBar.getCurrentMenu() != null && menuBar.getCurrentMenu() != Menu.this) switchMenu();\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic String getTitle () {\n\t\treturn title;\n\t}\n\n\tprivate void switchMenu () {\n\t\tmenuBar.closeMenu();\n\t\tshowMenu();\n\t}\n\n\tprivate void showMenu () {\n\t\tVector2 pos = openButton.localToStageCoordinates(new Vector2(0, 0));\n\t\tsetPosition(pos.x, pos.y - getHeight());\n\t\topenButton.getStage().addActor(this);\n\t\tmenuBar.setCurrentMenu(this);\n\t}\n\n\t@Override\n\tpublic boolean remove () {\n\t\tboolean result = super.remove();\n\t\tmenuBar.setCurrentMenu(null);\n\t\treturn result;\n\t}\n\n\t/** Called by MenuBar when this menu is added to it */\n\tvoid setMenuBar (MenuBar menuBar) {\n\t\tif (this.menuBar != null && menuBar != null) throw new IllegalStateException(\"Menu was already added to MenuBar\");\n\t\tthis.menuBar = menuBar;\n\t}\n\n\tTextButton getOpenButton () {\n\t\treturn openButton;\n\t}\n\n\tvoid selectButton () {\n\t\topenButton.getStyle().up = openButton.getStyle().over;\n\t}\n\n\tvoid deselectButton () {\n\t\topenButton.getStyle().up = buttonDefault;\n\t}\n\n\tpublic static class MenuStyle extends PopupMenuStyle {\n\t\tpublic VisTextButtonStyle openButtonStyle;\n\n\t\tpublic MenuStyle () {\n\t\t}\n\n\t\tpublic MenuStyle (MenuStyle style) {\n\t\t\tsuper(style);\n\t\t\tthis.openButtonStyle = style.openButtonStyle;\n\t\t}\n\n\t\tpublic MenuStyle (Drawable background, Drawable border, VisTextButtonStyle openButtonStyle) {\n\t\t\tsuper(background, border);\n\t\t\tthis.openButtonStyle = openButtonStyle;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/MenuBar.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * Bar with expandable menus available after pressing button, usually displayed on top of the stage.\n * @author Kotcrab\n */\npublic class MenuBar {\n\tprivate Table mainTable;\n\tprivate Table menuItems;\n\n\tprivate Menu currentMenu;\n\tprivate Array<Menu> menus = new Array<Menu>();\n\n\tprivate MenuBarListener menuListener;\n\n\tpublic MenuBar () {\n\t\tthis(\"default\");\n\t}\n\n\tpublic MenuBar (String styleName) {\n\t\tthis(VisUI.getSkin().get(styleName, MenuBarStyle.class));\n\t}\n\n\tpublic MenuBar (MenuBarStyle style) {\n\t\tmenuItems = new VisTable();\n\n\t\tmainTable = new VisTable() {\n\t\t\t@Override\n\t\t\tprotected void sizeChanged () {\n\t\t\t\tsuper.sizeChanged();\n\t\t\t\tcloseMenu();\n\t\t\t}\n\t\t};\n\n\t\tmainTable.left();\n\t\tmainTable.add(menuItems);\n\t\tmainTable.setBackground(style.background);\n\t}\n\n\tpublic void addMenu (Menu menu) {\n\t\tmenus.add(menu);\n\t\tmenu.setMenuBar(this);\n\t\tmenuItems.add(menu.getOpenButton());\n\t}\n\n\tpublic boolean removeMenu (Menu menu) {\n\t\tboolean removed = menus.removeValue(menu, true);\n\n\t\tif (removed) {\n\t\t\tmenu.setMenuBar(null);\n\t\t\tmenuItems.removeActor(menu.getOpenButton());\n\t\t}\n\n\t\treturn removed;\n\t}\n\n\tpublic void insertMenu (int index, Menu menu) {\n\t\tmenus.insert(index, menu);\n\t\tmenu.setMenuBar(this);\n\t\trebuild();\n\t}\n\n\tprivate void rebuild () {\n\t\tmenuItems.clear();\n\t\tfor (Menu menu : menus)\n\t\t\tmenuItems.add(menu.getOpenButton());\n\t}\n\n\t/** Closes currently opened menu (if any). Used by framework and typically there is no need to call this manually */\n\tpublic void closeMenu () {\n\t\tif (currentMenu != null) {\n\t\t\tcurrentMenu.deselectButton();\n\t\t\tcurrentMenu.remove();\n\t\t\tcurrentMenu = null;\n\t\t}\n\t}\n\n\tMenu getCurrentMenu () {\n\t\treturn currentMenu;\n\t}\n\n\tvoid setCurrentMenu (Menu newMenu) {\n\t\tif (currentMenu == newMenu) return;\n\t\tif (currentMenu != null) {\n\t\t\tcurrentMenu.deselectButton();\n\t\t\tif (menuListener != null) menuListener.menuClosed(currentMenu);\n\t\t}\n\t\tif (newMenu != null) {\n\t\t\tnewMenu.selectButton();\n\t\t\tif (menuListener != null) menuListener.menuOpened(newMenu);\n\t\t}\n\t\tcurrentMenu = newMenu;\n\t}\n\n\tpublic void setMenuListener (MenuBarListener menuListener) {\n\t\tthis.menuListener = menuListener;\n\t}\n\n\t/** Returns table containing all menus that should be added to Stage, typically with expandX and fillX properties. */\n\tpublic Table getTable () {\n\t\treturn mainTable;\n\t}\n\n\tpublic static class MenuBarStyle {\n\t\tpublic Drawable background;\n\n\t\tpublic MenuBarStyle () {\n\t\t}\n\n\t\tpublic MenuBarStyle (MenuBarStyle style) {\n\t\t\tthis.background = style.background;\n\t\t}\n\n\t\tpublic MenuBarStyle (Drawable background) {\n\t\t\tthis.background = background;\n\t\t}\n\t}\n\n\tpublic interface MenuBarListener {\n\t\tvoid menuOpened (Menu menu);\n\n\t\tvoid menuClosed (Menu menu);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/MenuItem.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.Input.Keys;\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.math.Vector2;\nimport com.badlogic.gdx.scenes.scene2d.*;\nimport com.badlogic.gdx.scenes.scene2d.ui.Button;\nimport com.badlogic.gdx.scenes.scene2d.ui.Cell;\nimport com.badlogic.gdx.scenes.scene2d.ui.Image;\nimport com.badlogic.gdx.scenes.scene2d.ui.Label;\nimport com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;\nimport com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.utils.Align;\nimport com.badlogic.gdx.utils.Pools;\nimport com.badlogic.gdx.utils.Scaling;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.OsUtils;\n\n/**\n * MenuItem displayed in {@link Menu} and {@link PopupMenu}. MenuItem contains text or text with icon.\n * Best icon size is 22px. MenuItem can also have a hotkey text.\n * <p>\n * When listening for menu item press {@link ChangeListener} should be always preferred (instead of {@link ClickListener}).\n * {@link ClickListener} does not support disabling menu item and will still report item clicks.\n * @author Kotcrab\n */\npublic class MenuItem extends Button {\n\tprivate static final Vector2 tmpVector = new Vector2();\n\n\t//MenuItem is modified version of TextButton\n\n\tprivate MenuItemStyle style;\n\n\tprivate Image image;\n\tprivate Cell<Image> imageCell;\n\tprivate boolean generateDisabledImage = true;\n\tprivate Label label;\n\tprivate Color shortcutLabelColor;\n\tprivate VisLabel shortcutLabel;\n\tprivate Image subMenuImage;\n\tprivate Cell<Image> subMenuIconCell;\n\n\tprivate PopupMenu subMenu;\n\n\t/** Menu that this item belongs to */\n\tPopupMenu containerMenu;\n\n\tpublic MenuItem (String text) {\n\t\tthis(text, (Image) null, VisUI.getSkin().get(MenuItemStyle.class));\n\t}\n\n\tpublic MenuItem (String text, String styleName) {\n\t\tthis(text, (Image) null, VisUI.getSkin().get(styleName, MenuItemStyle.class));\n\t}\n\n\tpublic MenuItem (String text, ChangeListener changeListener) {\n\t\tthis(text, (Image) null, VisUI.getSkin().get(MenuItemStyle.class));\n\t\taddListener(changeListener);\n\t}\n\n\tpublic MenuItem (String text, Drawable drawable) {\n\t\tthis(text, drawable, VisUI.getSkin().get(MenuItemStyle.class));\n\t}\n\n\tpublic MenuItem (String text, Drawable drawable, ChangeListener changeListener) {\n\t\tthis(text, drawable, VisUI.getSkin().get(MenuItemStyle.class));\n\t\taddListener(changeListener);\n\t}\n\n\tpublic MenuItem (String text, Drawable drawable, String styleName) {\n\t\tthis(text, drawable, VisUI.getSkin().get(styleName, MenuItemStyle.class));\n\t}\n\n\tpublic MenuItem (String text, Image image) {\n\t\tthis(text, image, VisUI.getSkin().get(MenuItemStyle.class));\n\t}\n\n\tpublic MenuItem (String text, Image image, ChangeListener changeListener) {\n\t\tthis(text, image, VisUI.getSkin().get(MenuItemStyle.class));\n\t\taddListener(changeListener);\n\t}\n\n\tpublic MenuItem (String text, Image image, String styleName) {\n\t\tthis(text, image, VisUI.getSkin().get(styleName, MenuItemStyle.class));\n\t}\n\n\t// Base constructors\n\n\tpublic MenuItem (String text, Image image, MenuItemStyle style) {\n\t\tsuper(style);\n\t\tinit(text, image, style);\n\t}\n\n\tpublic MenuItem (String text, Drawable drawable, MenuItemStyle style) {\n\t\tsuper(style);\n\t\tinit(text, new Image(drawable), style);\n\t}\n\n\tprivate void init (String text, Image image, MenuItemStyle style) {\n\t\tthis.style = style;\n\t\tthis.image = image;\n\t\tsetSkin(VisUI.getSkin());\n\t\tSizes sizes = VisUI.getSizes();\n\n\t\tdefaults().space(3);\n\n\t\tif (image != null) image.setScaling(Scaling.fit);\n\t\timageCell = add(image).size(sizes.menuItemIconSize);\n\n\t\tlabel = new Label(text, new LabelStyle(style.font, style.fontColor));\n\t\tlabel.setAlignment(Align.left);\n\t\tadd(label).expand().fill();\n\n\t\tadd(shortcutLabel = new VisLabel(\"\", \"menuitem-shortcut\")).padLeft(10).right();\n\t\tshortcutLabelColor = shortcutLabel.getStyle().fontColor;\n\n\t\tsubMenuIconCell = add(subMenuImage = new Image(style.subMenu)).padLeft(3).padRight(3)\n\t\t\t\t.size(style.subMenu.getMinWidth(), style.subMenu.getMinHeight());\n\t\tsubMenuIconCell.setActor(null);\n\n\t\taddListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tif (subMenu != null) { //makes submenu item not clickable\n\t\t\t\t\tevent.stop();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic void enter (InputEvent event, float x, float y, int pointer, Actor fromActor) {\n\t\t\t\tif (subMenu != null) { //removes selection of child submenu if mouse moved to parent submenu\n\t\t\t\t\tsubMenu.setActiveItem(null, false);\n\t\t\t\t\tsubMenu.setActiveSubMenu(null);\n\t\t\t\t}\n\n\t\t\t\tif (subMenu == null || isDisabled()) { //hides last visible submenu (if any)\n\t\t\t\t\thideSubMenu();\n\t\t\t\t} else {\n\t\t\t\t\tshowSubMenu();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic void setSubMenu (final PopupMenu subMenu) {\n\t\tthis.subMenu = subMenu;\n\n\t\tif (subMenu == null) {\n\t\t\tsubMenuIconCell.setActor(null);\n\t\t} else {\n\t\t\tsubMenuIconCell.setActor(subMenuImage);\n\t\t}\n\t}\n\n\tpublic PopupMenu getSubMenu () {\n\t\treturn subMenu;\n\t}\n\n\tvoid packContainerMenu () {\n\t\tif (containerMenu != null) containerMenu.pack();\n\t}\n\n\t@Override\n\tprotected void setParent (Group parent) {\n\t\tsuper.setParent(parent);\n\t\tif (parent instanceof PopupMenu)\n\t\t\tcontainerMenu = (PopupMenu) parent;\n\t\telse\n\t\t\tcontainerMenu = null;\n\t}\n\n\tvoid hideSubMenu () {\n\t\tif (containerMenu != null) {\n\t\t\tcontainerMenu.setActiveSubMenu(null);\n\t\t}\n\t}\n\n\tvoid showSubMenu () {\n\t\tStage stage = getStage();\n\t\tVector2 pos = localToStageCoordinates(tmpVector.setZero());\n\n\t\tfloat availableSpaceLeft = pos.x;\n\t\tfloat availableSpaceRight = stage.getWidth() - (pos.x + getWidth());\n\t\tboolean canFitOnTheRight = pos.x + getWidth() + subMenu.getWidth() <= stage.getWidth();\n\t\tfloat subMenuX;\n\t\tif (canFitOnTheRight || availableSpaceRight > availableSpaceLeft) {\n\t\t\tsubMenuX = pos.x + getWidth() - 1;\n\t\t} else {\n\t\t\tsubMenuX = pos.x - subMenu.getWidth() + 1;\n\t\t}\n\n\t\tif (containerMenu.getActiveSubMenu() != subMenu) {\n\t\t\tboolean hasEnoughBottomSpace = stage.getHeight() - (pos.y + getHeight()) + subMenu.getHeight() <= stage.getHeight();\n\t\t\tfloat heightCorrection = hasEnoughBottomSpace ? getHeight() : 0;\n\n\t\t\tsubMenu.showMenu(stage, subMenuX, pos.y + heightCorrection);\n\t\t\tcontainerMenu.setActiveSubMenu(subMenu);\n\t\t}\n\t}\n\n\tvoid fireChangeEvent () {\n\t\tChangeListener.ChangeEvent changeEvent = Pools.obtain(ChangeListener.ChangeEvent.class);\n\t\tfire(changeEvent);\n\t\tPools.free(changeEvent);\n\t}\n\n\t@Override\n\tpublic MenuItemStyle getStyle () {\n\t\treturn style;\n\t}\n\n\t@Override\n\tpublic void setStyle (ButtonStyle style) {\n\t\tif (!(style instanceof MenuItemStyle)) throw new IllegalArgumentException(\"style must be a MenuItemStyle.\");\n\t\tsuper.setStyle(style);\n\t\tthis.style = (MenuItemStyle) style;\n\t\tif (label != null) {\n\t\t\tTextButtonStyle textButtonStyle = (TextButtonStyle) style;\n\t\t\tLabelStyle labelStyle = label.getStyle();\n\t\t\tlabelStyle.font = textButtonStyle.font;\n\t\t\tlabelStyle.fontColor = textButtonStyle.fontColor;\n\t\t\tlabel.setStyle(labelStyle);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tColor fontColor;\n\t\tif (isDisabled() && style.disabledFontColor != null)\n\t\t\tfontColor = style.disabledFontColor;\n\t\telse if (isPressed() && style.downFontColor != null)\n\t\t\tfontColor = style.downFontColor;\n\t\telse if (isChecked() && style.checkedFontColor != null)\n\t\t\tfontColor = (isOver() && style.checkedOverFontColor != null) ? style.checkedOverFontColor : style.checkedFontColor;\n\t\telse if (isOver() && style.overFontColor != null)\n\t\t\tfontColor = style.overFontColor;\n\t\telse\n\t\t\tfontColor = style.fontColor;\n\t\tif (fontColor != null) label.getStyle().fontColor = fontColor;\n\n\t\tif (isDisabled())\n\t\t\tshortcutLabel.getStyle().fontColor = style.disabledFontColor;\n\t\telse\n\t\t\tshortcutLabel.getStyle().fontColor = shortcutLabelColor;\n\n\t\tif (generateDisabledImage && image != null) {\n\t\t\tif (isDisabled()) {\n\t\t\t\timage.setColor(Color.GRAY);\n\t\t\t} else {\n\t\t\t\timage.setColor(Color.WHITE);\n\t\t\t}\n\t\t}\n\n\t\tsuper.draw(batch, parentAlpha);\n\t}\n\n\t@Override\n\tpublic boolean isOver () {\n\t\tif (containerMenu == null || containerMenu.getActiveItem() == null) {\n\t\t\treturn super.isOver();\n\t\t} else {\n\t\t\treturn containerMenu.getActiveItem() == this;\n\t\t}\n\t}\n\n\tpublic boolean isGenerateDisabledImage () {\n\t\treturn generateDisabledImage;\n\t}\n\n\t/**\n\t * Changes generateDisabledImage property, when true that function is enabled. When it is enabled and this MenuItem\n\t * is disabled then image color will be changed to gray meaning that it is disabled, by default it is enabled.\n\t */\n\tpublic void setGenerateDisabledImage (boolean generateDisabledImage) {\n\t\tthis.generateDisabledImage = generateDisabledImage;\n\t}\n\n\t/**\n\t * Set shortcuts text displayed in this menu item.\n\t * This DOES NOT set actual hot key for this menu item, it only makes shortcut text visible in item.\n\t * @param keycode from {@link Keys}.\n\t */\n\tpublic MenuItem setShortcut (int keycode) {\n\t\treturn setShortcut(Keys.toString(keycode));\n\t}\n\n\tpublic CharSequence getShortcut () {\n\t\treturn shortcutLabel.getText();\n\t}\n\n\t/**\n\t * Set shortcuts text displayed in this menu item. This DOES NOT set actual hot key for this menu item,\n\t * it only makes shortcut text visible in item.\n\t * @param text text that will be displayed\n\t * @return this object for the purpose of chaining methods\n\t */\n\tpublic MenuItem setShortcut (String text) {\n\t\tshortcutLabel.setText(text);\n\t\tpackContainerMenu();\n\t\treturn this;\n\t}\n\n\t/**\n\t * Creates platform dependant shortcut text. Converts int keycodes to String text. Eg. Keys.CONTROL_LEFT,\n\t * Keys.SHIFT_LEFT, Keys.F5 will be converted to Ctrl+Shift+F5 on Windows and Linux, and to ⌘⇧F5 on Mac.\n\t * <p>\n\t * CONTROL_LEFT and CONTROL_RIGHT are mapped to Ctrl. The same goes for Alt (ALT_LEFT, ALT_RIGHT) and Shift (SHIFT_LEFT, SHIFT_RIGHT).\n\t * <p>\n\t * This DOES NOT set actual hot key for this menu item, it only makes shortcut text visible in item.\n\t * @param keycodes keycodes from {@link Keys} that are used to create shortcut text\n\t * @return this object for the purpose of chaining methods\n\t */\n\tpublic MenuItem setShortcut (int... keycodes) {\n\t\tshortcutLabel.setText(OsUtils.getShortcutFor(keycodes));\n\t\tpackContainerMenu();\n\t\treturn this;\n\t}\n\n\t@Override\n\tprotected void setStage (Stage stage) {\n\t\tsuper.setStage(stage);\n\t\tlabel.invalidate(); //fixes issue with disappearing menu item after holding right mouse button and dragging down while opening menu\n\t}\n\n\tpublic Image getImage () {\n\t\treturn image;\n\t}\n\n\tpublic Cell<?> getImageCell () {\n\t\treturn imageCell;\n\t}\n\n\tpublic Label getLabel () {\n\t\treturn label;\n\t}\n\n\tpublic Cell<?> getLabelCell () {\n\t\treturn getCell(label);\n\t}\n\n\tpublic CharSequence getText () {\n\t\treturn label.getText();\n\t}\n\n\tpublic void setText (CharSequence text) {\n\t\tlabel.setText(text);\n\t}\n\n\tpublic Cell<Image> getSubMenuIconCell () {\n\t\treturn subMenuIconCell;\n\t}\n\n\tpublic Cell<VisLabel> getShortcutCell () {\n\t\treturn getCell(shortcutLabel);\n\t}\n\n\tstatic public class MenuItemStyle extends TextButtonStyle {\n\t\tpublic Drawable subMenu;\n\n\t\tpublic MenuItemStyle () {\n\t\t}\n\n\t\tpublic MenuItemStyle (Drawable subMenu) {\n\t\t\tthis.subMenu = subMenu;\n\t\t}\n\n\t\tpublic MenuItemStyle (MenuItemStyle style) {\n\t\t\tsuper(style);\n\t\t\tthis.subMenu = style.subMenu;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/MultiSplitPane.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.math.MathUtils;\nimport com.badlogic.gdx.math.Rectangle;\nimport com.badlogic.gdx.math.Vector2;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.scenes.scene2d.utils.Layout;\nimport com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;\nimport com.badlogic.gdx.utils.Array;\nimport com.badlogic.gdx.utils.FloatArray;\nimport com.badlogic.gdx.utils.SnapshotArray;\nimport com.kotcrab.vis.ui.FocusManager;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.widget.internal.SplitPaneCursorManager;\n\nimport java.util.Arrays;\n\n/**\n * Similar to {@link VisSplitPane} but supports multiple widgets with multiple split bars at once. Use {@link #setWidgets(Actor...)}\n * after creating to set pane widgets.\n * @author Kotcrab\n * @see VisSplitPane\n * @since 1.1.4\n */\npublic class MultiSplitPane extends WidgetGroup {\n\tprivate MultiSplitPaneStyle style;\n\tprivate boolean vertical;\n\n\tprivate Array<Rectangle> widgetBounds = new Array<Rectangle>();\n\tprivate Array<Rectangle> scissors = new Array<Rectangle>();\n\n\tprivate Array<Rectangle> handleBounds = new Array<Rectangle>();\n\tprivate FloatArray splits = new FloatArray();\n\n\tprivate Vector2 handlePosition = new Vector2();\n\tprivate Vector2 lastPoint = new Vector2();\n\n\tprivate Rectangle handleOver;\n\tprivate int handleOverIndex;\n\n\tpublic MultiSplitPane (boolean vertical) {\n\t\tthis(vertical, \"default-\" + (vertical ? \"vertical\" : \"horizontal\"));\n\t}\n\n\tpublic MultiSplitPane (boolean vertical, String styleName) {\n\t\tthis(vertical, VisUI.getSkin().get(styleName, MultiSplitPaneStyle.class));\n\t}\n\n\tpublic MultiSplitPane (boolean vertical, MultiSplitPaneStyle style) {\n\t\tthis.vertical = vertical;\n\t\tsetStyle(style);\n\t\tsetSize(getPrefWidth(), getPrefHeight());\n\t\tinitialize();\n\t}\n\n\tprivate void initialize () {\n\t\taddListener(new SplitPaneCursorManager(this, vertical) {\n\t\t\t@Override\n\t\t\tprotected boolean handleBoundsContains (float x, float y) {\n\t\t\t\treturn getHandleContaining(x, y) != null;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tprotected boolean contains (float x, float y) {\n\t\t\t\tfor (Rectangle bound : widgetBounds) {\n\t\t\t\t\tif (bound.contains(x, y)) return true;\n\t\t\t\t}\n\t\t\t\treturn getHandleContaining(x, y) != null;\n\t\t\t}\n\t\t});\n\n\t\taddListener(new InputListener() {\n\t\t\tint draggingPointer = -1;\n\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tif (isTouchable() == false) return false;\n\n\t\t\t\tif (draggingPointer != -1) return false;\n\t\t\t\tif (pointer == 0 && button != 0) return false;\n\t\t\t\tRectangle containingHandle = getHandleContaining(x, y);\n\t\t\t\tif (containingHandle != null) {\n\t\t\t\t\thandleOverIndex = handleBounds.indexOf(containingHandle, true);\n\t\t\t\t\tFocusManager.resetFocus(getStage());\n\n\t\t\t\t\tdraggingPointer = pointer;\n\t\t\t\t\tlastPoint.set(x, y);\n\t\t\t\t\thandlePosition.set(containingHandle.x, containingHandle.y);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void touchUp (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tif (pointer == draggingPointer) draggingPointer = -1;\n\t\t\t\thandleOver = getHandleContaining(x, y);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean mouseMoved (InputEvent event, float x, float y) {\n\t\t\t\thandleOver = getHandleContaining(x, y);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void touchDragged (InputEvent event, float x, float y, int pointer) {\n\t\t\t\tif (pointer != draggingPointer) return;\n\n\t\t\t\tDrawable handle = style.handle;\n\t\t\t\tif (!vertical) {\n\t\t\t\t\tfloat delta = x - lastPoint.x;\n\t\t\t\t\tfloat availWidth = getWidth() - handle.getMinWidth();\n\t\t\t\t\tfloat dragX = handlePosition.x + delta;\n\t\t\t\t\thandlePosition.x = dragX;\n\t\t\t\t\tdragX = Math.max(0, dragX);\n\t\t\t\t\tdragX = Math.min(availWidth, dragX);\n\t\t\t\t\tfloat targetSplit = dragX / availWidth;\n\t\t\t\t\tsetSplit(handleOverIndex, targetSplit);\n\t\t\t\t\tlastPoint.set(x, y);\n\t\t\t\t} else {\n\t\t\t\t\tfloat delta = y - lastPoint.y;\n\t\t\t\t\tfloat availHeight = getHeight() - handle.getMinHeight();\n\t\t\t\t\tfloat dragY = handlePosition.y + delta;\n\t\t\t\t\thandlePosition.y = dragY;\n\t\t\t\t\tdragY = Math.max(0, dragY);\n\t\t\t\t\tdragY = Math.min(availHeight, dragY);\n\t\t\t\t\tfloat targetSplit = 1 - (dragY / availHeight);\n\t\t\t\t\tsetSplit(handleOverIndex, targetSplit);\n\t\t\t\t\tlastPoint.set(x, y);\n\t\t\t\t}\n\t\t\t\tinvalidate();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate Rectangle getHandleContaining (float x, float y) {\n\t\tfor (Rectangle rect : handleBounds) {\n\t\t\tif (rect.contains(x, y)) {\n\t\t\t\treturn rect;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Returns the split pane's style. Modifying the returned style may not have an effect until {@link #setStyle(MultiSplitPaneStyle)}\n\t * is called.\n\t */\n\tpublic MultiSplitPaneStyle getStyle () {\n\t\treturn style;\n\t}\n\n\tpublic void setStyle (MultiSplitPaneStyle style) {\n\t\tthis.style = style;\n\t\tinvalidateHierarchy();\n\t}\n\n\t@Override\n\tpublic void layout () {\n\t\tif (!vertical)\n\t\t\tcalculateHorizBoundsAndPositions();\n\t\telse\n\t\t\tcalculateVertBoundsAndPositions();\n\n\t\tSnapshotArray<Actor> actors = getChildren();\n\t\tfor (int i = 0; i < actors.size; i++) {\n\t\t\tActor actor = actors.get(i);\n\t\t\tRectangle bounds = widgetBounds.get(i);\n\t\t\tactor.setBounds(bounds.x, bounds.y, bounds.width, bounds.height);\n\t\t\tif (actor instanceof Layout) ((Layout) actor).validate();\n\t\t}\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\tfloat width = 0;\n\t\tfor (Actor actor : getChildren()) {\n\t\t\twidth = actor instanceof Layout ? ((Layout) actor).getPrefWidth() : actor.getWidth();\n\t\t}\n\t\tif (!vertical) width += handleBounds.size * style.handle.getMinWidth();\n\t\treturn width;\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\tfloat height = 0;\n\t\tfor (Actor actor : getChildren()) {\n\t\t\theight = actor instanceof Layout ? ((Layout) actor).getPrefHeight() : actor.getHeight();\n\n\t\t}\n\t\tif (vertical) height += handleBounds.size * style.handle.getMinHeight();\n\t\treturn height;\n\t}\n\n\t@Override\n\tpublic float getMinWidth () {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic float getMinHeight () {\n\t\treturn 0;\n\t}\n\n\tpublic void setVertical (boolean vertical) {\n\t\tthis.vertical = vertical;\n\t}\n\n\tprivate void calculateHorizBoundsAndPositions () {\n\t\tfloat height = getHeight();\n\t\tfloat width = getWidth();\n\t\tfloat handleWidth = style.handle.getMinWidth();\n\n\t\tfloat availWidth = width - (handleBounds.size * handleWidth);\n\n\t\tfloat areaUsed = 0;\n\t\tfloat currentX = 0;\n\t\tfor (int i = 0; i < splits.size; i++) {\n\t\t\tfloat areaWidthFromLeft = (int) (availWidth * splits.get(i));\n\t\t\tfloat areaWidth = areaWidthFromLeft - areaUsed;\n\t\t\tareaUsed += areaWidth;\n\t\t\twidgetBounds.get(i).set(currentX, 0, areaWidth, height);\n\t\t\tcurrentX += areaWidth;\n\t\t\thandleBounds.get(i).set(currentX, 0, handleWidth, height);\n\t\t\tcurrentX += handleWidth;\n\t\t}\n\t\tif (widgetBounds.size != 0) widgetBounds.peek().set(currentX, 0, availWidth - areaUsed, height);\n\t}\n\n\tprivate void calculateVertBoundsAndPositions () {\n\t\tfloat width = getWidth();\n\t\tfloat height = getHeight();\n\t\tfloat handleHeight = style.handle.getMinHeight();\n\n\t\tfloat availHeight = height - (handleBounds.size * handleHeight);\n\n\t\tfloat areaUsed = 0;\n\t\tfloat currentY = height;\n\t\tfor (int i = 0; i < splits.size; i++) {\n\t\t\tfloat areaHeightFromTop = (int) (availHeight * splits.get(i));\n\t\t\tfloat areaHeight = areaHeightFromTop - areaUsed;\n\t\t\tareaUsed += areaHeight;\n\t\t\twidgetBounds.get(i).set(0, currentY - areaHeight, width, areaHeight);\n\t\t\tcurrentY -= areaHeight;\n\t\t\thandleBounds.get(i).set(0, currentY - handleHeight, width, handleHeight);\n\t\t\tcurrentY -= handleHeight;\n\t\t}\n\t\tif (widgetBounds.size != 0) widgetBounds.peek().set(0, 0, width, availHeight - areaUsed);\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tvalidate();\n\n\t\tColor color = getColor();\n\n\t\tapplyTransform(batch, computeTransform());\n\n\t\tSnapshotArray<Actor> actors = getChildren();\n\t\tfor (int i = 0; i < actors.size; i++) {\n\t\t\tActor actor = actors.get(i);\n\t\t\tRectangle bounds = widgetBounds.get(i);\n\t\t\tRectangle scissor = scissors.get(i);\n\t\t\tgetStage().calculateScissors(bounds, scissor);\n\t\t\tif (ScissorStack.pushScissors(scissor)) {\n\t\t\t\tif (actor.isVisible()) actor.draw(batch, parentAlpha * color.a);\n\t\t\t\tbatch.flush();\n\t\t\t\tScissorStack.popScissors();\n\t\t\t}\n\t\t}\n\n\t\tbatch.setColor(color.r, color.g, color.b, parentAlpha * color.a);\n\n\t\tDrawable handle = style.handle;\n\t\tDrawable handleOver = style.handle;\n\t\tif (isTouchable() && style.handleOver != null) handleOver = style.handleOver;\n\t\tfor (Rectangle rect : handleBounds) {\n\t\t\tif (this.handleOver == rect) {\n\t\t\t\thandleOver.draw(batch, rect.x, rect.y, rect.width, rect.height);\n\t\t\t} else {\n\t\t\t\thandle.draw(batch, rect.x, rect.y, rect.width, rect.height);\n\t\t\t}\n\t\t}\n\t\tresetTransform(batch);\n\t}\n\n\t@Override\n\tpublic Actor hit (float x, float y, boolean touchable) {\n\t\tif (touchable && getTouchable() == Touchable.disabled) return null;\n\t\tif (getHandleContaining(x, y) != null) {\n\t\t\treturn this;\n\t\t} else {\n\t\t\treturn super.hit(x, y, touchable);\n\t\t}\n\t}\n\n\t/** Changes widgets of this split pane. You can pass any number of actors even 1 or 0. Actors can't be null. */\n\tpublic void setWidgets (Actor... actors) {\n\t\tsetWidgets(Arrays.asList(actors));\n\t}\n\n\t/** Changes widgets of this split pane. You can pass any number of actors even 1 or 0. Actors can't be null. */\n\tpublic void setWidgets (Iterable<Actor> actors) {\n\t\tclearChildren();\n\t\twidgetBounds.clear();\n\t\tscissors.clear();\n\t\thandleBounds.clear();\n\t\tsplits.clear();\n\n\t\tfor (Actor actor : actors) {\n\t\t\tsuper.addActor(actor);\n\t\t\twidgetBounds.add(new Rectangle());\n\t\t\tscissors.add(new Rectangle());\n\t\t}\n\t\tfloat currentSplit = 0;\n\t\tfloat splitAdvance = 1f / getChildren().size;\n\t\tfor (int i = 0; i < getChildren().size - 1; i++) {\n\t\t\thandleBounds.add(new Rectangle());\n\t\t\tcurrentSplit += splitAdvance;\n\t\t\tsplits.add(currentSplit);\n\t\t}\n\t\tinvalidate();\n\t}\n\n\t/**\n\t * @param handleBarIndex index of handle bar starting from zero, max index is number of widgets - 1\n\t * @param split new value of split, must be greater than 0 and lesser than 1 and must be smaller and bigger than\n\t * previous and next split value. Invalid values will be clamped to closest valid one.\n\t */\n\tpublic void setSplit (int handleBarIndex, float split) {\n\t\tif (handleBarIndex < 0) throw new IllegalStateException(\"handleBarIndex can't be < 0\");\n\t\tif (handleBarIndex >= splits.size) throw new IllegalStateException(\"handleBarIndex can't be >= splits size\");\n\t\tfloat minSplit = handleBarIndex == 0 ? 0 : splits.get(handleBarIndex - 1);\n\t\tfloat maxSplit = handleBarIndex == splits.size - 1 ? 1 : splits.get(handleBarIndex + 1);\n\t\tsplit = MathUtils.clamp(split, minSplit, maxSplit);\n\t\tsplits.set(handleBarIndex, split);\n\t}\n\n\t@Override\n\tpublic void addActorAfter (Actor actorAfter, Actor actor) {\n\t\tthrow new UnsupportedOperationException(\"Use MultiSplitPane#setWidgets\");\n\t}\n\n\t@Override\n\tpublic void addActor (Actor actor) {\n\t\tthrow new UnsupportedOperationException(\"Use MultiSplitPane#setWidgets\");\n\t}\n\n\t@Override\n\tpublic void addActorAt (int index, Actor actor) {\n\t\tthrow new UnsupportedOperationException(\"Use MultiSplitPane#setWidgets\");\n\t}\n\n\t@Override\n\tpublic void addActorBefore (Actor actorBefore, Actor actor) {\n\t\tthrow new UnsupportedOperationException(\"Use MultiSplitPane#setWidgets\");\n\t}\n\n\t@Override\n\tpublic boolean removeActor (Actor actor) {\n\t\tthrow new UnsupportedOperationException(\"Use MultiSplitPane#setWidgets\");\n\t}\n\n\tpublic static class MultiSplitPaneStyle extends VisSplitPane.VisSplitPaneStyle {\n\t\tpublic MultiSplitPaneStyle () {\n\t\t}\n\n\t\tpublic MultiSplitPaneStyle (VisSplitPane.VisSplitPaneStyle style) {\n\t\t\tsuper(style);\n\t\t}\n\n\t\tpublic MultiSplitPaneStyle (Drawable handle, Drawable handleOver) {\n\t\t\tsuper(handle, handleOver);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/PopupMenu.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.ApplicationListener;\nimport com.badlogic.gdx.Input;\nimport com.badlogic.gdx.Input.Buttons;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.math.Vector2;\nimport com.badlogic.gdx.scenes.scene2d.*;\nimport com.badlogic.gdx.scenes.scene2d.ui.Cell;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.utils.SnapshotArray;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.ActorUtils;\n\n/**\n * Standard popup menu that can be displayed anywhere on stage. Menu is automatically removed when user clicked outside menu,\n * or clicked menu item. For proper behaviour menu should be displayed in touchUp event. If you want to display\n * menu from touchDown you have to call event.stop() otherwise menu will by immediately closed.\n * <p>\n * If you want to add right click menu to actor you can use getDefaultInputListener() to get premade default listener.\n * <p>\n * Since 1.0.2 arrow keys can be used to navigate menu hierarchy.\n * @author Kotcrab\n */\npublic class PopupMenu extends Table {\n\tprivate static final Vector2 tmpVector = new Vector2();\n\n\tprivate Sizes sizes;\n\tprivate PopupMenuStyle style;\n\tprivate PopupMenuListener listener;\n\n\tprivate InputListener stageListener;\n\tprivate InputListener sharedMenuItemInputListener;\n\n\tprivate ChangeListener sharedMenuItemChangeListener;\n\n\tprivate InputListener defaultInputListener;\n\t/** The parent sub-menu, that this popup menu belongs to or null if this sub menu is root */\n\tprivate PopupMenu parentSubMenu;\n\n\t/** The current sub-menu, set by MenuItem */\n\tprivate PopupMenu activeSubMenu;\n\tprivate MenuItem activeItem;\n\n\tpublic PopupMenu () {\n\t\tthis(\"default\");\n\t}\n\n\tpublic PopupMenu (String styleName) {\n\t\tthis(VisUI.getSkin().get(styleName, PopupMenuStyle.class));\n\t}\n\n\tpublic PopupMenu (PopupMenuStyle style) {\n\t\tthis(VisUI.getSizes(), style);\n\t}\n\n\tpublic PopupMenu (Sizes sizes, PopupMenuStyle style) {\n\t\tthis.sizes = sizes;\n\t\tthis.style = style;\n\t\tsetTouchable(Touchable.enabled);\n\t\tpad(0);\n\t\tsetBackground(style.background);\n\t\tcreateListeners();\n\t}\n\n\t/**\n\t * Removes every instance of {@link PopupMenu} form {@link Stage} actors.\n\t * <p>\n\t * Generally called from {@link ApplicationListener#resize(int, int)} to remove menus on resize event.\n\t */\n\tpublic static void removeEveryMenu (Stage stage) {\n\t\tfor (Actor actor : stage.getActors()) {\n\t\t\tif (actor instanceof PopupMenu) {\n\t\t\t\tPopupMenu menu = (PopupMenu) actor;\n\t\t\t\tmenu.removeHierarchy();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void createListeners () {\n\t\tstageListener = new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tif (getRootMenu().subMenuStructureContains(x, y) == false) {\n\t\t\t\t\tremove();\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\t\tSnapshotArray<Actor> children = getChildren();\n\t\t\t\tif (children.size == 0 || activeSubMenu != null) return false;\n\t\t\t\tif (keycode == Input.Keys.DOWN) {\n\t\t\t\t\tselectNextItem();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (keycode == Input.Keys.UP) {\n\t\t\t\t\tselectPreviousItem();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (activeItem == null) return false;\n\t\t\t\tif (keycode == Input.Keys.LEFT && activeItem.containerMenu.parentSubMenu != null) {\n\t\t\t\t\tactiveItem.containerMenu.parentSubMenu.setActiveSubMenu(null);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (keycode == Input.Keys.RIGHT && activeItem.getSubMenu() != null) {\n\t\t\t\t\tactiveItem.showSubMenu();\n\t\t\t\t\tactiveSubMenu.selectNextItem();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (keycode == Input.Keys.ENTER) {\n\t\t\t\t\tactiveItem.fireChangeEvent();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t};\n\n\t\tsharedMenuItemInputListener = new InputListener() {\n\t\t\t@Override\n\t\t\tpublic void enter (InputEvent event, float x, float y, int pointer, Actor fromActor) {\n\t\t\t\tif (pointer == -1 && event.getListenerActor() instanceof MenuItem) {\n\t\t\t\t\tMenuItem item = (MenuItem) event.getListenerActor();\n\t\t\t\t\tif (item.isDisabled() == false) {\n\t\t\t\t\t\tsetActiveItem(item, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void exit (InputEvent event, float x, float y, int pointer, Actor toActor) {\n\t\t\t\tif (pointer == -1 && event.getListenerActor() instanceof MenuItem) {\n\t\t\t\t\tif (activeSubMenu != null) return;\n\n\t\t\t\t\tMenuItem item = (MenuItem) event.getListenerActor();\n\t\t\t\t\tif (item == activeItem) {\n\t\t\t\t\t\tsetActiveItem(null, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tsharedMenuItemChangeListener = new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tif (event.isStopped() == false) removeHierarchy();\n\t\t\t}\n\t\t};\n\t}\n\n\tprivate PopupMenu getRootMenu () {\n\t\tif (parentSubMenu != null) return parentSubMenu.getRootMenu();\n\t\treturn this;\n\t}\n\n\tprivate boolean subMenuStructureContains (float x, float y) {\n\t\tif (contains(x, y)) return true;\n\t\tif (activeSubMenu != null) return activeSubMenu.subMenuStructureContains(x, y);\n\t\treturn false;\n\t}\n\n\tprivate void removeHierarchy () {\n\t\tif (activeItem != null && activeItem.containerMenu != null && activeItem.containerMenu.parentSubMenu != null) {\n\t\t\tactiveItem.containerMenu.parentSubMenu.removeHierarchy();\n\t\t}\n\t\tremove();\n\t}\n\n\tprivate void selectNextItem () {\n\t\tSnapshotArray<Actor> children = getChildren();\n\t\tif (!hasSelectableMenuItems()) return;\n\t\tint startIndex = activeItem == null ? 0 : children.indexOf(activeItem, true) + 1;\n\t\tfor (int i = startIndex; ; i++) {\n\t\t\tif (i >= children.size) i = 0;\n\t\t\tActor actor = children.get(i);\n\t\t\tif (actor instanceof MenuItem && ((MenuItem) actor).isDisabled() == false) {\n\t\t\t\tsetActiveItem((MenuItem) actor, true);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void selectPreviousItem () {\n\t\tSnapshotArray<Actor> children = getChildren();\n\t\tif (!hasSelectableMenuItems()) return;\n\t\tint startIndex = activeItem == null ? children.size - 1 : children.indexOf(activeItem, true) - 1;\n\t\tfor (int i = startIndex; ; i--) {\n\t\t\tif (i <= -1) i = children.size - 1;\n\t\t\tActor actor = children.get(i);\n\t\t\tif (actor instanceof MenuItem && ((MenuItem) actor).isDisabled() == false) {\n\t\t\t\tsetActiveItem((MenuItem) actor, true);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate boolean hasSelectableMenuItems () {\n\t\tSnapshotArray<Actor> children = getChildren();\n\t\tfor (Actor actor : children) {\n\t\t\tif (actor instanceof MenuItem && ((MenuItem) actor).isDisabled() == false) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic <T extends Actor> Cell<T> add (T actor) {\n\t\tif (actor instanceof MenuItem) {\n\t\t\tthrow new IllegalArgumentException(\"MenuItems can be only added to PopupMenu by using addItem(MenuItem) method\");\n\t\t}\n\n\t\treturn super.add(actor);\n\t}\n\n\tpublic void addItem (MenuItem item) {\n\t\tsuper.add(item).fillX().expandX().row();\n\t\tpack();\n\t\titem.addListener(sharedMenuItemChangeListener);\n\t\titem.addListener(sharedMenuItemInputListener);\n\t}\n\n\tpublic void addSeparator () {\n\t\tadd(new Separator(\"menu\")).padTop(2).padBottom(2).fill().expand().row();\n\t}\n\n\t/**\n\t * Returns input listener that can be added to scene2d actor. When right mouse button is pressed on that actor,\n\t * menu will be displayed\n\t */\n\tpublic InputListener getDefaultInputListener () {\n\t\treturn getDefaultInputListener(Buttons.RIGHT);\n\t}\n\n\t/**\n\t * Returns input listener that can be added to scene2d actor. When mouse button is pressed on that actor,\n\t * menu will be displayed\n\t * @param mouseButton from {@link Buttons}\n\t */\n\tpublic InputListener getDefaultInputListener (final int mouseButton) {\n\t\tif (defaultInputListener == null) {\n\t\t\tdefaultInputListener = new InputListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void touchUp (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\t\tif (event.getButton() == mouseButton)\n\t\t\t\t\t\tshowMenu(event.getStage(), event.getStageX(), event.getStageY());\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\treturn defaultInputListener;\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tsuper.draw(batch, parentAlpha);\n\t\tif (style.border != null) style.border.draw(batch, getX(), getY(), getWidth(), getHeight());\n\t}\n\n\t/**\n\t * Shows menu as given stage coordinates\n\t * @param stage stage instance that this menu is being added to\n\t * @param x stage x position\n\t * @param y stage y position\n\t */\n\tpublic void showMenu (Stage stage, float x, float y) {\n\t\tsetPosition(x, y - getHeight());\n\t\tif (stage.getHeight() - getY() > stage.getHeight()) setY(getY() + getHeight());\n\t\tActorUtils.keepWithinStage(stage, this);\n\t\tstage.addActor(this);\n\t}\n\n\t/**\n\t * Shows menu below (or above if not enough space) given actor.\n\t * @param stage stage instance that this menu is being added to\n\t * @param actor used to get calculate menu position in stage, menu will be displayed above or below it\n\t */\n\tpublic void showMenu (Stage stage, Actor actor) {\n\t\tVector2 pos = actor.localToStageCoordinates(tmpVector.setZero());\n\t\tfloat menuY;\n\t\tif (pos.y - getHeight() <= 0) {\n\t\t\tmenuY = pos.y + actor.getHeight() + getHeight() - sizes.borderSize;\n\t\t} else {\n\t\t\tmenuY = pos.y + sizes.borderSize;\n\t\t}\n\t\tshowMenu(stage, pos.x, menuY);\n\t}\n\n\tpublic boolean contains (float x, float y) {\n\t\treturn getX() < x && getX() + getWidth() > x && getY() < y && getY() + getHeight() > y;\n\t}\n\n\t/** Called by framework, when PopupMenu is added to MenuItem as submenu */\n\tvoid setActiveSubMenu (PopupMenu newSubMenu) {\n\t\tif (activeSubMenu == newSubMenu) return;\n\t\tif (activeSubMenu != null) activeSubMenu.remove();\n\t\tactiveSubMenu = newSubMenu;\n\t\tif (newSubMenu != null) {\n\t\t\tnewSubMenu.setParentMenu(this);\n\t\t}\n\t}\n\n\tpublic PopupMenu getActiveSubMenu () {\n\t\treturn activeSubMenu;\n\t}\n\n\t@Override\n\tprotected void setStage (Stage stage) {\n\t\tsuper.setStage(stage);\n\t\tif (stage != null) stage.addListener(stageListener);\n\t}\n\n\t@Override\n\tpublic boolean remove () {\n\t\tif (getStage() != null) getStage().removeListener(stageListener);\n\t\tif (activeSubMenu != null) activeSubMenu.remove();\n\t\tsetActiveItem(null, false);\n\t\tparentSubMenu = null;\n\t\tactiveSubMenu = null;\n\t\treturn super.remove();\n\t}\n\n\tvoid setActiveItem (MenuItem newItem, boolean keyboardChange) {\n\t\tactiveItem = newItem;\n\t\tif (listener != null) listener.activeItemChanged(newItem, keyboardChange);\n\t}\n\n\tpublic MenuItem getActiveItem () {\n\t\treturn activeItem;\n\t}\n\n\tvoid setParentMenu (PopupMenu parentSubMenu) {\n\t\tthis.parentSubMenu = parentSubMenu;\n\t}\n\n\tpublic PopupMenuListener getListener () {\n\t\treturn listener;\n\t}\n\n\tpublic void setListener (PopupMenuListener listener) {\n\t\tthis.listener = listener;\n\t}\n\n\t/**\n\t * Listener used to get events from {@link PopupMenu}.\n\t * @since 1.0.2\n\t */\n\tpublic interface PopupMenuListener {\n\t\t/**\n\t\t * Called when active menu item (the highlighted one) has changed. This can't be used to listen when\n\t\t * {@link MenuItem} was pressed, add {@link ChangeListener} to {@link MenuItem} directly to achieve this.\n\t\t * @param newActiveItem new item that is now active. May be null.\n\t\t * @param changedByKeyboard whether the change occurred by keyboard (arrows keys) or by mouse.\n\t\t */\n\t\tvoid activeItemChanged (MenuItem newActiveItem, boolean changedByKeyboard);\n\t}\n\n\tstatic public class PopupMenuStyle {\n\t\tpublic Drawable background;\n\t\tpublic Drawable border;\n\n\t\tpublic PopupMenuStyle () {\n\t\t}\n\n\t\tpublic PopupMenuStyle (Drawable background, Drawable border) {\n\t\t\tthis.background = background;\n\t\t\tthis.border = border;\n\t\t}\n\n\t\tpublic PopupMenuStyle (PopupMenuStyle style) {\n\t\t\tthis.background = style.background;\n\t\t\tthis.border = style.border;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/ScrollableTextArea.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.math.Rectangle;\nimport com.badlogic.gdx.scenes.scene2d.Group;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;\nimport com.badlogic.gdx.scenes.scene2d.utils.Cullable;\n\n/**\n * Custom {@link VisTextArea} supporting embedding in scroll pane by calculating required space needed for current text.\n * <p>\n * Warning: By default this can only support vertical scrolling. Scrolling in X direction MUST be disabled. It is NOT possible\n * to use vertical scrolling without child class properly implementing {@link #getPrefWidth()} and disabling soft wraps.\n * Example of such class is {@link HighlightTextArea}.\n * <p>\n * For best scroll pane settings you should create scroll pane using {@link #createCompatibleScrollPane()}.\n * @author Kotcrab\n * @since 1.1.2\n */\npublic class ScrollableTextArea extends VisTextArea implements Cullable {\n\tprivate Rectangle cullingArea;\n\n\tpublic ScrollableTextArea (String text) {\n\t\tsuper(text, \"textArea\");\n\t}\n\n\tpublic ScrollableTextArea (String text, String styleName) {\n\t\tsuper(text, styleName);\n\t}\n\n\tpublic ScrollableTextArea (String text, VisTextFieldStyle style) {\n\t\tsuper(text, style);\n\t}\n\n\t@Override\n\tprotected InputListener createInputListener () {\n\t\treturn new ScrollTextAreaListener();\n\t}\n\n\t@Override\n\tprotected void setParent (Group parent) {\n\t\tsuper.setParent(parent);\n\t\tif (parent instanceof ScrollPane) {\n\t\t\tcalculateOffsets();\n\t\t}\n\t}\n\n\tprivate void updateScrollPosition () {\n\t\tif (cullingArea == null || getParent() instanceof ScrollPane == false) return;\n\t\tScrollPane scrollPane = (ScrollPane) getParent();\n\n\t\tif (cullingArea.contains(getCursorX(), cullingArea.y) == false) {\n\t\t\tscrollPane.setScrollPercentX(getCursorX() / getWidth());\n\t\t}\n\n\t\tif (cullingArea.contains(cullingArea.x, (getHeight() - getCursorY())) == false) {\n\t\t\tscrollPane.setScrollPercentY(getCursorY() / getHeight());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setCullingArea (Rectangle cullingArea) {\n\t\tthis.cullingArea = cullingArea;\n\t}\n\n\t/**\n\t * Creates scroll pane for this scrolling text area with best possible default settings. Note that text area\n\t * can belong to only one scroll pane, calling this multiple times will break previously created scroll pane.\n\t * The scroll pane should be embedded in container with fixed size or optionally grow property.\n\t * @return newly created scroll pane which can be added directly to container.\n\t */\n\tpublic ScrollPane createCompatibleScrollPane () {\n\t\tVisScrollPane scrollPane = new VisScrollPane(this);\n\t\tscrollPane.setOverscroll(false, false);\n\t\tscrollPane.setFlickScroll(false);\n\t\tscrollPane.setFadeScrollBars(false);\n\t\tscrollPane.setScrollbarsOnTop(true);\n\t\tscrollPane.setScrollingDisabled(true, false);\n\t\treturn scrollPane;\n\t}\n\n\t@Override\n\tprotected void sizeChanged () {\n\t\tsuper.sizeChanged();\n\t\tlinesShowing = 1000000000; //aka a lot, forces text area not to use its stupid 'scrolling'\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\treturn getLines() * style.font.getLineHeight();\n\t}\n\n\t@Override\n\tpublic void setText (String str) {\n\t\tsuper.setText(str);\n\t\tif (programmaticChangeEvents == false) { //changeText WILL NOT be called when programmaticChangeEvents are disabled\n\t\t\tupdateScrollLayout();\n\t\t}\n\t}\n\n\t@Override\n\tboolean changeText (String oldText, String newText) {\n\t\tboolean changed = super.changeText(oldText, newText);\n\t\tupdateScrollLayout();\n\t\treturn changed;\n\t}\n\n\tvoid updateScrollLayout () {\n\t\tinvalidateHierarchy();\n\t\tlayout();\n\t\tif (getParent() instanceof ScrollPane) ((ScrollPane) getParent()).layout();\n\t\tupdateScrollPosition();\n\t}\n\n\tpublic class ScrollTextAreaListener extends TextAreaListener {\n\t\t@Override\n\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\tupdateScrollPosition();\n\t\t\treturn super.keyDown(event, keycode);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean keyTyped (InputEvent event, char character) {\n\t\t\tupdateScrollPosition();\n\t\t\treturn super.keyTyped(event, character);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/Separator.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.scenes.scene2d.ui.Widget;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * A separator widget (horizontal or vertical bar) that can be used in menus, tables or other widgets, typically added\n * to new row with growX() (if creating horizontal separator) OR growY() (if creating vertical separator)\n * {@link PopupMenu} and {@link VisTable} provides utilities addSeparator() methods that adds new separator.\n * @author Kotcrab\n * @since 0.1.0\n */\npublic class Separator extends Widget {\n\tprivate SeparatorStyle style;\n\n\t/** New separator with default style */\n\tpublic Separator () {\n\t\tstyle = VisUI.getSkin().get(SeparatorStyle.class);\n\t}\n\n\tpublic Separator (String styleName) {\n\t\tstyle = VisUI.getSkin().get(styleName, SeparatorStyle.class);\n\t}\n\n\tpublic Separator (SeparatorStyle style) {\n\t\tthis.style = style;\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\treturn style.thickness;\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\treturn style.thickness;\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tColor c = getColor();\n\t\tbatch.setColor(c.r, c.g, c.b, c.a * parentAlpha);\n\t\tstyle.background.draw(batch, getX(), getY(), getWidth(), getHeight());\n\t}\n\n\tpublic SeparatorStyle getStyle () {\n\t\treturn style;\n\t}\n\n\tstatic public class SeparatorStyle {\n\t\tpublic Drawable background;\n\t\tpublic int thickness;\n\n\t\tpublic SeparatorStyle () {\n\t\t}\n\n\t\tpublic SeparatorStyle (SeparatorStyle style) {\n\t\t\tthis.background = style.background;\n\t\t\tthis.thickness = style.thickness;\n\t\t}\n\n\t\tpublic SeparatorStyle (Drawable bg, int thickness) {\n\t\t\tthis.background = bg;\n\t\t\tthis.thickness = thickness;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/Tooltip.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.math.Interpolation;\nimport com.badlogic.gdx.math.Vector2;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.EventListener;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.actions.Actions;\nimport com.badlogic.gdx.scenes.scene2d.ui.Cell;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.utils.Align;\nimport com.badlogic.gdx.utils.Array;\nimport com.badlogic.gdx.utils.Timer;\nimport com.badlogic.gdx.utils.Timer.Task;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.ActorUtils;\n\n/**\n * Tooltips are widgets that appear below other widget on mouse pointer hover. Each actor can have only one tooltip.\n * <p>\n * libGDX 1.6.4 introduced it's own systems of tooltips. VisUI tooltips existed before that and are unrelated and\n * incompatible with libGDX tooltips. VisUI tooltips will remain supported.\n * @author Kotcrab\n * @since 0.5.0\n */\npublic class Tooltip extends VisTable {\n\tpublic static float DEFAULT_FADE_TIME = 0.3f;\n\tpublic static float DEFAULT_APPEAR_DELAY_TIME = 0.6f;\n\t/**\n\t * Controls whether to fade out tooltip when mouse was moved. Changing this will not affect already existing tooltips.\n\t * @see #setMouseMoveFadeOut(boolean)\n\t */\n\tpublic static boolean MOUSE_MOVED_FADEOUT = false;\n\n\tprivate Actor target;\n\tprivate Actor content;\n\tprivate Cell<Actor> contentCell;\n\n\tprivate boolean mouseMoveFadeOut = MOUSE_MOVED_FADEOUT;\n\tprivate TooltipInputListener listener;\n\n\tprivate DisplayTask displayTask;\n\n\tprivate float fadeTime = DEFAULT_FADE_TIME;\n\tprivate float appearDelayTime = DEFAULT_APPEAR_DELAY_TIME;\n\n\tprivate Tooltip (Builder builder) {\n\t\tsuper(true);\n\n\t\tTooltipStyle style = builder.style;\n\t\tif (style == null) style = VisUI.getSkin().get(\"default\", TooltipStyle.class);\n\n\t\tinit(style, builder.target, builder.content);\n\t\tif (builder.width != -1) {\n\t\t\tcontentCell.width(builder.width);\n\t\t\tpack();\n\t\t}\n\t}\n\n\tpublic Tooltip () {\n\t\tthis(\"default\");\n\t}\n\n\tpublic Tooltip (String styleName) {\n\t\tsuper(true);\n\t\tinit(VisUI.getSkin().get(styleName, TooltipStyle.class), null, null);\n\t}\n\n\tpublic Tooltip (TooltipStyle style) {\n\t\tsuper(true);\n\t\tinit(style, null, null);\n\t}\n\n\t/**\n\t * Remove any attached tooltip from target actor\n\t * @param target that tooltips will be removed\n\t */\n\tpublic static void removeTooltip (Actor target) {\n\t\tArray<EventListener> listeners = target.getListeners();\n\t\tfor (EventListener listener : listeners) {\n\t\t\tif (listener instanceof TooltipInputListener) target.removeListener(listener);\n\t\t}\n\t}\n\n\tprivate void init (TooltipStyle style, Actor target, Actor content) {\n\t\tthis.target = target;\n\t\tthis.content = content;\n\t\tthis.listener = new TooltipInputListener();\n\t\tthis.displayTask = new DisplayTask();\n\n\t\tsetBackground(style.background);\n\n\t\tcontentCell = add(content).padLeft(3).padRight(3).padBottom(2);\n\t\tpack();\n\n\t\tif (target != null) attach();\n\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\ttoFront();\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void enter (InputEvent event, float x, float y, int pointer, Actor fromActor) {\n\t\t\t\tif (pointer == -1) {\n\t\t\t\t\tclearActions();\n\t\t\t\t\taddAction(Actions.sequence(Actions.fadeIn(fadeTime, Interpolation.fade)));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void exit (InputEvent event, float x, float y, int pointer, Actor toActor) {\n\t\t\t\tif (pointer == -1) {\n\t\t\t\t\tfadeOut();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Attaches tooltip to current target, must be called if tooltip listener was removed from target (for example by\n\t * calling target.clearListeners() )\n\t */\n\tpublic void attach () {\n\t\tif (target == null) return;\n\t\tArray<EventListener> listeners = target.getListeners();\n\t\tfor (EventListener listener : listeners) {\n\t\t\tif (listener instanceof TooltipInputListener) {\n\t\t\t\tthrow new IllegalStateException(\"More than one tooltip cannot be added to the same target!\");\n\t\t\t}\n\t\t}\n\n\t\ttarget.addListener(listener);\n\t}\n\n\t/**\n\t * Detaches tooltip form current target, does not change tooltip target meaning that this tooltip can be reattached to\n\t * same target by calling {@link Tooltip#attach()}\n\t */\n\tpublic void detach () {\n\t\tif (target == null) return;\n\t\ttarget.removeListener(listener);\n\t}\n\n\t/** Sets new target for this tooltip, tooltip will be automatically detached from old target. */\n\tpublic void setTarget (Actor newTarget) {\n\t\tdetach();\n\t\ttarget = newTarget;\n\t\tattach();\n\t}\n\n\tpublic Actor getTarget () {\n\t\treturn target;\n\t}\n\n\tprivate void fadeOut () {\n\t\tclearActions();\n\t\taddAction(Actions.sequence(Actions.fadeOut(fadeTime, Interpolation.fade), Actions.removeActor()));\n\t}\n\n\tprivate VisTable fadeIn () {\n\t\tclearActions();\n\t\tsetColor(1, 1, 1, 0);\n\t\taddAction(Actions.sequence(Actions.fadeIn(fadeTime, Interpolation.fade)));\n\t\treturn this;\n\t}\n\n\tpublic Actor getContent () {\n\t\treturn content;\n\t}\n\n\tpublic void setContent (Actor content) {\n\t\tthis.content = content;\n\t\tcontentCell.setActor(content);\n\t\tpack();\n\t}\n\n\tpublic Cell<Actor> getContentCell () {\n\t\treturn contentCell;\n\t}\n\n\t/**\n\t * Changes text tooltip to specified text. If tooltip content is not instance of VisLabel then previous tooltip content\n\t * will be replaced by VisLabel instance.\n\t * @param text next tooltip text\n\t */\n\tpublic void setText (String text) {\n\t\tif (content instanceof VisLabel) {\n\t\t\t((VisLabel) content).setText(text);\n\t\t} else {\n\t\t\tsetContent(new VisLabel(text));\n\t\t}\n\t\tpack();\n\t}\n\n\t@Override\n\tpublic void setPosition (float x, float y) {\n\t\tsuper.setPosition((int) x, (int) y);\n\t}\n\n\tpublic float getAppearDelayTime () {\n\t\treturn appearDelayTime;\n\t}\n\n\tpublic void setAppearDelayTime (float appearDelayTime) {\n\t\tthis.appearDelayTime = appearDelayTime;\n\t}\n\n\tpublic float getFadeTime () {\n\t\treturn fadeTime;\n\t}\n\n\tpublic void setFadeTime (float fadeTime) {\n\t\tthis.fadeTime = fadeTime;\n\t}\n\n\tpublic boolean isMouseMoveFadeOut () {\n\t\treturn mouseMoveFadeOut;\n\t}\n\n\t/**\n\t * @param mouseMoveFadeOut if true tooltip fill fade out when mouse was moved. If false tooltip will only fadeout on\n\t * mouse click or when mouse has exited target widget. Default is {@link Tooltip#MOUSE_MOVED_FADEOUT}.\n\t */\n\tpublic void setMouseMoveFadeOut (boolean mouseMoveFadeOut) {\n\t\tthis.mouseMoveFadeOut = mouseMoveFadeOut;\n\t}\n\n\tprivate class DisplayTask extends Task {\n\t\t@Override\n\t\tpublic void run () {\n\t\t\tif (target.getStage() == null) return;\n\t\t\ttarget.getStage().addActor(fadeIn());\n\t\t\tActorUtils.keepWithinStage(getStage(), Tooltip.this);\n\t\t}\n\t}\n\n\tprivate class TooltipInputListener extends InputListener {\n\t\t@Override\n\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\tdisplayTask.cancel();\n\t\t\tTooltip.this.toFront();\n\t\t\tfadeOut();\n\t\t\treturn true;\n\t\t}\n\n\t\t@Override\n\t\tpublic void enter (InputEvent event, float x, float y, int pointer, Actor fromActor) {\n\t\t\tif (pointer == -1) {\n\t\t\t\tVector2 targetPos = target.localToStageCoordinates(new Vector2());\n\n\t\t\t\tsetX(targetPos.x + (target.getWidth() - getWidth()) / 2);\n\n\t\t\t\tfloat tooltipY = targetPos.y - getHeight() - 6;\n\t\t\t\tfloat stageHeight = target.getStage().getHeight();\n\n\t\t\t\t//is there enough space to display above widget?\n\t\t\t\tif (stageHeight - tooltipY > stageHeight)\n\t\t\t\t\tsetY(targetPos.y + target.getHeight() + 6); //display above widget\n\t\t\t\telse\n\t\t\t\t\tsetY(tooltipY); //display below\n\n\t\t\t\tdisplayTask.cancel();\n\t\t\t\tTimer.schedule(displayTask, appearDelayTime);\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void exit (InputEvent event, float x, float y, int pointer, Actor toActor) {\n\t\t\tif (pointer == -1) {\n\t\t\t\tdisplayTask.cancel();\n\t\t\t\tfadeOut();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean mouseMoved (InputEvent event, float x, float y) {\n\t\t\tif (mouseMoveFadeOut && isVisible() && getActions().size == 0) fadeOut();\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic static class TooltipStyle {\n\t\tpublic Drawable background;\n\n\t\tpublic TooltipStyle () {\n\t\t}\n\n\t\tpublic TooltipStyle (TooltipStyle style) {\n\t\t\tthis.background = style.background;\n\t\t}\n\n\t\tpublic TooltipStyle (Drawable background) {\n\t\t\tthis.background = background;\n\t\t}\n\t}\n\n\tpublic static class Builder {\n\t\tprivate final Actor content;\n\n\t\tprivate Actor target = null;\n\t\tprivate TooltipStyle style = null;\n\t\tprivate float width = -1;\n\n\t\tpublic Builder (Actor content) {\n\t\t\tthis.content = content;\n\t\t}\n\n\t\tpublic Builder (String text) {\n\t\t\tthis(text, Align.center);\n\t\t}\n\n\t\tpublic Builder (String text, int textAlign) {\n\t\t\tVisLabel label = new VisLabel(text);\n\t\t\tlabel.setAlignment(textAlign);\n\t\t\tthis.content = label;\n\t\t}\n\n\t\tpublic Builder target (Actor target) {\n\t\t\tthis.target = target;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder style (String styleName) {\n\t\t\treturn style(VisUI.getSkin().get(styleName, TooltipStyle.class));\n\t\t}\n\n\t\tpublic Builder style (TooltipStyle style) {\n\t\t\tthis.style = style;\n\t\t\treturn this;\n\t\t}\n\n\t\t/** Sets tooltip width. If tooltip content is text only then calling this will automatically enable label wrapping. */\n\t\tpublic Builder width (float width) {\n\t\t\tif (width < 0) throw new IllegalArgumentException(\"width must be > 0\");\n\t\t\tthis.width = width;\n\t\t\tif (content instanceof VisLabel) {\n\t\t\t\t((VisLabel) content).setWrap(true);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Tooltip build () {\n\t\t\treturn new Tooltip(this);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisCheckBox.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.graphics.g2d.BitmapFont;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.ui.*;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.utils.Align;\nimport com.kotcrab.vis.ui.FocusManager;\nimport com.kotcrab.vis.ui.Focusable;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.BorderOwner;\n\n/**\n * A checkbox is a button that contains an image indicating the checked or unchecked state and a label.\n * This widget is different than scene2d.ui's {@link CheckBox}. Style supports more checkbox states, focus and error border.\n * {@link VisCheckBoxStyle} is significantly different than {@link CheckBox.CheckBoxStyle} here background and tick are\n * stored as separate drawables. Due to scope of changes made this widget is not compatible with {@link CheckBox}.\n * <p>\n * When listening for checkbox press {@link ChangeListener} should be always preferred (instead of {@link ClickListener}).\n * {@link ClickListener} does not support disabling checkbox and will still report checkbox presses.\n * @author Nathan Sweet\n * @author Kotcrab\n * @see CheckBox\n */\npublic class VisCheckBox extends TextButton implements Focusable, BorderOwner {\n\tprivate VisCheckBoxStyle style;\n\n\tprivate Image bgImage;\n\tprivate Image tickImage;\n\tprivate Stack imageStack;\n\tprivate Cell<Stack> imageStackCell;\n\n\tprivate boolean drawBorder;\n\tprivate boolean stateInvalid;\n\tprivate boolean focusBorderEnabled = true;\n\n\tpublic VisCheckBox (String text) {\n\t\tthis(text, VisUI.getSkin().get(VisCheckBoxStyle.class));\n\t}\n\n\tpublic VisCheckBox (String text, boolean checked) {\n\t\tthis(text, VisUI.getSkin().get(VisCheckBoxStyle.class));\n\t\tsetChecked(checked);\n\t}\n\n\tpublic VisCheckBox (String text, String styleName) {\n\t\tthis(text, VisUI.getSkin().get(styleName, VisCheckBoxStyle.class));\n\t}\n\n\tpublic VisCheckBox (String text, VisCheckBoxStyle style) {\n\t\tsuper(text, style);\n\t\tclearChildren();\n\n\t\tbgImage = new Image(style.checkBackground);\n\t\ttickImage = new Image(style.tick);\n\t\timageStackCell = add(imageStack = new Stack(bgImage, tickImage));\n\t\tLabel label = getLabel();\n\t\tadd(label).padLeft(5);\n\t\tlabel.setAlignment(Align.left);\n\t\tsetSize(getPrefWidth(), getPrefHeight());\n\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tif (isDisabled() == false) FocusManager.switchFocus(getStage(), VisCheckBox.this);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Returns the checkbox's style. Modifying the returned style may not have an effect until {@link #setStyle(ButtonStyle)} is\n\t * called.\n\t */\n\t@Override\n\tpublic VisCheckBoxStyle getStyle () {\n\t\treturn style;\n\t}\n\n\t@Override\n\tpublic void setStyle (ButtonStyle style) {\n\t\tif (style instanceof VisCheckBoxStyle == false)\n\t\t\tthrow new IllegalArgumentException(\"style must be a VisCheckBoxStyle.\");\n\t\tsuper.setStyle(style);\n\t\tthis.style = (VisCheckBoxStyle) style;\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tbgImage.setDrawable(getCheckboxBgImage());\n\t\ttickImage.setDrawable(getCheckboxTickImage());\n\t\tsuper.draw(batch, parentAlpha);\n\n\t\tif (isDisabled() == false && stateInvalid && style.errorBorder != null) {\n\t\t\tstyle.errorBorder.draw(batch, getX() + imageStack.getX(), getY() + imageStack.getY(), imageStack.getWidth(), imageStack.getHeight());\n\t\t} else if (focusBorderEnabled && drawBorder && style.focusBorder != null) {\n\t\t\tstyle.focusBorder.draw(batch, getX() + imageStack.getX(), getY() + imageStack.getY(), imageStack.getWidth(), imageStack.getHeight());\n\t\t}\n\t}\n\n\tprotected Drawable getCheckboxBgImage () {\n\t\tif (isDisabled()) return style.checkBackground;\n\t\tif (isPressed()) return style.checkBackgroundDown;\n\t\tif (isOver()) return style.checkBackgroundOver;\n\t\treturn style.checkBackground;\n\t}\n\n\tprotected Drawable getCheckboxTickImage () {\n\t\tif (isChecked()) {\n\t\t\treturn isDisabled() ? style.tickDisabled : style.tick;\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic Image getBackgroundImage () {\n\t\treturn bgImage;\n\t}\n\n\tpublic Image getTickImage () {\n\t\treturn tickImage;\n\t}\n\n\tpublic Stack getImageStack () {\n\t\treturn imageStack;\n\t}\n\n\tpublic Cell<Stack> getImageStackCell () {\n\t\treturn imageStackCell;\n\t}\n\n\t/** @param stateInvalid if true error border around this checkbox will be drawn. Does not affect any other properties */\n\tpublic void setStateInvalid (boolean stateInvalid) {\n\t\tthis.stateInvalid = stateInvalid;\n\t}\n\n\tpublic boolean setStateInvalid () {\n\t\treturn stateInvalid;\n\t}\n\n\t@Override\n\tpublic void focusLost () {\n\t\tdrawBorder = false;\n\t}\n\n\t@Override\n\tpublic void focusGained () {\n\t\tdrawBorder = true;\n\t}\n\n\t@Override\n\tpublic boolean isFocusBorderEnabled () {\n\t\treturn focusBorderEnabled;\n\t}\n\n\t@Override\n\tpublic void setFocusBorderEnabled (boolean focusBorderEnabled) {\n\t\tthis.focusBorderEnabled = focusBorderEnabled;\n\t}\n\n\tstatic public class VisCheckBoxStyle extends TextButtonStyle {\n\t\tpublic Drawable focusBorder;\n\t\tpublic Drawable errorBorder;\n\n\t\tpublic Drawable checkBackground;\n\t\tpublic Drawable checkBackgroundOver;\n\t\tpublic Drawable checkBackgroundDown;\n\t\tpublic Drawable tick;\n\t\tpublic Drawable tickDisabled;\n\n\t\tpublic VisCheckBoxStyle () {\n\t\t\tsuper();\n\t\t}\n\n\t\tpublic VisCheckBoxStyle (Drawable checkBackground, Drawable tick, BitmapFont font, Color fontColor) {\n\t\t\tthis.checkBackground = checkBackground;\n\t\t\tthis.tick = tick;\n\t\t\tthis.font = font;\n\t\t\tthis.fontColor = fontColor;\n\t\t}\n\n\t\tpublic VisCheckBoxStyle (VisCheckBoxStyle style) {\n\t\t\tsuper(style);\n\t\t\tthis.focusBorder = style.focusBorder;\n\t\t\tthis.errorBorder = style.errorBorder;\n\t\t\tthis.checkBackground = style.checkBackground;\n\t\t\tthis.checkBackgroundOver = style.checkBackgroundOver;\n\t\t\tthis.checkBackgroundDown = style.checkBackgroundDown;\n\t\t\tthis.tick = style.tick;\n\t\t\tthis.tickDisabled = style.tickDisabled;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisDialog.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.Input.Keys;\nimport com.badlogic.gdx.math.Interpolation;\nimport com.badlogic.gdx.scenes.scene2d.*;\nimport com.badlogic.gdx.scenes.scene2d.actions.Actions;\nimport com.badlogic.gdx.scenes.scene2d.ui.*;\nimport com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.FocusListener;\nimport com.badlogic.gdx.utils.ObjectMap;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.widget.VisTextButton.VisTextButtonStyle;\n\nimport static com.badlogic.gdx.scenes.scene2d.actions.Actions.sequence;\n\n/**\n * Displays a dialog, which is a modal window containing a content table with a button table underneath it. Methods are provided\n * to add a label to the content table and buttons to the button table, but any widgets can be added. When a button is clicked,\n * {@link #result(Object)} is called and the dialog is removed from the stage.\n * <p>\n * Due to scope of changes made this widget is not compatible with standard {@link Dialog}.\n * @author Nathan Sweet\n * @author Kotcrab\n */\npublic class VisDialog extends VisWindow {\n\tTable contentTable, buttonTable;\n\tprivate Skin skin;\n\t@SuppressWarnings({\"unchecked\", \"rawtypes\"})\n\tObjectMap<Actor, Object> values = new ObjectMap();\n\tboolean cancelHide;\n\tActor previousKeyboardFocus, previousScrollFocus;\n\tFocusListener focusListener;\n\n\tprotected InputListener ignoreTouchDown = new InputListener() {\n\t\t@Override\n\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\tevent.cancel();\n\t\t\treturn false;\n\t\t}\n\t};\n\n\tpublic VisDialog (String title) {\n\t\tsuper(title);\n\t\tthis.skin = VisUI.getSkin();\n\t\tsetSkin(skin);\n\t\tinitialize();\n\t}\n\n\tpublic VisDialog (String title, String windowStyleName) {\n\t\tsuper(title, VisUI.getSkin().get(windowStyleName, WindowStyle.class));\n\t\tthis.skin = VisUI.getSkin();\n\t\tsetSkin(skin);\n\t\tinitialize();\n\t}\n\n\tpublic VisDialog (String title, WindowStyle windowStyle) {\n\t\tsuper(title, windowStyle);\n\t\tthis.skin = VisUI.getSkin();\n\t\tsetSkin(skin);\n\t\tinitialize();\n\t}\n\n\tprivate void initialize () {\n\t\tsetModal(true);\n\t\tgetTitleLabel().setAlignment(VisUI.getDefaultTitleAlign());\n\n\t\tdefaults().space(6);\n\t\tadd(contentTable = new Table(skin)).expand().fill();\n\t\trow();\n\t\tadd(buttonTable = new Table(skin));\n\n\t\tcontentTable.defaults().space(2).padLeft(3).padRight(3);\n\t\tbuttonTable.defaults().space(6).padBottom(3);\n\n\t\tbuttonTable.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tif (!values.containsKey(actor)) return;\n\t\t\t\twhile (actor.getParent() != buttonTable)\n\t\t\t\t\tactor = actor.getParent();\n\t\t\t\tresult(values.get(actor));\n\t\t\t\tif (!cancelHide) hide();\n\t\t\t\tcancelHide = false;\n\t\t\t}\n\t\t});\n\n\t\tfocusListener = new FocusListener() {\n\t\t\t@Override\n\t\t\tpublic void keyboardFocusChanged (FocusEvent event, Actor actor, boolean focused) {\n\t\t\t\tif (!focused) focusChanged(event);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void scrollFocusChanged (FocusEvent event, Actor actor, boolean focused) {\n\t\t\t\tif (!focused) focusChanged(event);\n\t\t\t}\n\n\t\t\tprivate void focusChanged (FocusEvent event) {\n\t\t\t\tStage stage = getStage();\n\t\t\t\tif (isModal() && stage != null && stage.getRoot().getChildren().size > 0\n\t\t\t\t\t\t&& stage.getRoot().getChildren().peek() == VisDialog.this) { // Dialog is top most actor.\n\t\t\t\t\tActor newFocusedActor = event.getRelatedActor();\n\t\t\t\t\tif (newFocusedActor != null && !newFocusedActor.isDescendantOf(VisDialog.this)) event.cancel();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t@Override\n\tprotected void setStage (Stage stage) {\n\t\tif (stage == null)\n\t\t\taddListener(focusListener);\n\t\telse\n\t\t\tremoveListener(focusListener);\n\t\tsuper.setStage(stage);\n\t}\n\n\tpublic Table getContentTable () {\n\t\treturn contentTable;\n\t}\n\n\tpublic Table getButtonsTable () {\n\t\treturn buttonTable;\n\t}\n\n\t/** Adds a label to the content table. The dialog must have been constructed with a skin to use this method. */\n\tpublic VisDialog text (String text) {\n\t\tif (skin == null)\n\t\t\tthrow new IllegalStateException(\"This method may only be used if the dialog was constructed with a Skin.\");\n\t\treturn text(text, skin.get(LabelStyle.class));\n\t}\n\n\t/** Adds a label to the content table. */\n\tpublic VisDialog text (String text, LabelStyle labelStyle) {\n\t\treturn text(new Label(text, labelStyle));\n\t}\n\n\t/** Adds the given Label to the content table */\n\tpublic VisDialog text (Label label) {\n\t\tcontentTable.add(label);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds a text button to the button table. Null will be passed to {@link #result(Object)} if this button is clicked. The dialog\n\t * must have been constructed with a skin to use this method.\n\t */\n\tpublic VisDialog button (String text) {\n\t\treturn button(text, null);\n\t}\n\n\t/**\n\t * Adds a text button to the button table. The dialog must have been constructed with a skin to use this method.\n\t * @param object The object that will be passed to {@link #result(Object)} if this button is clicked. May be null.\n\t */\n\tpublic VisDialog button (String text, Object object) {\n\t\tif (skin == null)\n\t\t\tthrow new IllegalStateException(\"This method may only be used if the dialog was constructed with a Skin.\");\n\t\treturn button(text, object, skin.get(VisTextButtonStyle.class));\n\t}\n\n\t/**\n\t * Adds a text button to the button table.\n\t * @param object The object that will be passed to {@link #result(Object)} if this button is clicked. May be null.\n\t */\n\tpublic VisDialog button (String text, Object object, VisTextButtonStyle buttonStyle) {\n\t\treturn button(new VisTextButton(text, buttonStyle), object);\n\t}\n\n\t/** Adds the given button to the button table. */\n\tpublic VisDialog button (Button button) {\n\t\treturn button(button, null);\n\t}\n\n\t/**\n\t * Adds the given button to the button table.\n\t * @param object The object that will be passed to {@link #result(Object)} if this button is clicked. May be null.\n\t */\n\tpublic VisDialog button (Button button, Object object) {\n\t\tbuttonTable.add(button);\n\t\tsetObject(button, object);\n\t\treturn this;\n\t}\n\n\t/** {@link #pack() Packs} the dialog and adds it to the stage with custom action which can be null for instant show */\n\tpublic VisDialog show (Stage stage, Action action) {\n\t\tclearActions();\n\t\tremoveCaptureListener(ignoreTouchDown);\n\n\t\tpreviousKeyboardFocus = null;\n\t\tActor actor = stage.getKeyboardFocus();\n\t\tif (actor != null && !actor.isDescendantOf(this)) previousKeyboardFocus = actor;\n\n\t\tpreviousScrollFocus = null;\n\t\tactor = stage.getScrollFocus();\n\t\tif (actor != null && !actor.isDescendantOf(this)) previousScrollFocus = actor;\n\n\t\tpack();\n\t\tstage.addActor(this);\n\t\tstage.setKeyboardFocus(this);\n\t\tstage.setScrollFocus(this);\n\t\tif (action != null) addAction(action);\n\n\t\treturn this;\n\t}\n\n\t/** {@link #pack() Packs} the dialog and adds it to the stage, centered with default fadeIn action */\n\tpublic VisDialog show (Stage stage) {\n\t\tshow(stage, sequence(Actions.alpha(0), Actions.fadeIn(0.4f, Interpolation.fade)));\n\t\tsetPosition(Math.round((stage.getWidth() - getWidth()) / 2), Math.round((stage.getHeight() - getHeight()) / 2));\n\t\treturn this;\n\t}\n\n\t/** Hides the dialog with the given action and then removes it from the stage. */\n\tpublic void hide (Action action) {\n\t\tStage stage = getStage();\n\t\tif (stage != null) {\n\t\t\tremoveListener(focusListener);\n\t\t\tif (previousKeyboardFocus != null && previousKeyboardFocus.getStage() == null) previousKeyboardFocus = null;\n\t\t\tActor actor = stage.getKeyboardFocus();\n\t\t\tif (actor == null || actor.isDescendantOf(this)) stage.setKeyboardFocus(previousKeyboardFocus);\n\n\t\t\tif (previousScrollFocus != null && previousScrollFocus.getStage() == null) previousScrollFocus = null;\n\t\t\tactor = stage.getScrollFocus();\n\t\t\tif (actor == null || actor.isDescendantOf(this)) stage.setScrollFocus(previousScrollFocus);\n\t\t}\n\t\tif (action != null) {\n\t\t\taddCaptureListener(ignoreTouchDown);\n\t\t\taddAction(sequence(action, Actions.removeListener(ignoreTouchDown, true), Actions.removeActor()));\n\t\t} else\n\t\t\tremove();\n\t}\n\n\t/**\n\t * Hides the dialog. Called automatically when a button is clicked. The default implementation fades out the dialog over 400\n\t * milliseconds and then removes it from the stage.\n\t */\n\tpublic void hide () {\n\t\thide(sequence(Actions.fadeOut(FADE_TIME, Interpolation.fade), Actions.removeListener(ignoreTouchDown, true),\n\t\t\t\tActions.removeActor()));\n\t}\n\n\tpublic void setObject (Actor actor, Object object) {\n\t\tvalues.put(actor, object);\n\t}\n\n\t/**\n\t * If this key is pressed, {@link #result(Object)} is called with the specified object.\n\t * @see Keys\n\t */\n\tpublic VisDialog key (final int keycode, final Object object) {\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean keyDown (InputEvent event, int keycode2) {\n\t\t\t\tif (keycode == keycode2) {\n\t\t\t\t\tresult(object);\n\t\t\t\t\tif (!cancelHide) hide();\n\t\t\t\t\tcancelHide = false;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Called when a button is clicked. The dialog will be hidden after this method returns unless {@link #cancel()} is called.\n\t * @param object The object specified when the button was added.\n\t */\n\tprotected void result (Object object) {\n\t}\n\n\tpublic void cancel () {\n\t\tcancelHide = true;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisImage.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.Texture;\nimport com.badlogic.gdx.graphics.g2d.NinePatch;\nimport com.badlogic.gdx.graphics.g2d.TextureRegion;\nimport com.badlogic.gdx.scenes.scene2d.ui.Image;\nimport com.badlogic.gdx.scenes.scene2d.ui.Skin;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;\nimport com.badlogic.gdx.utils.Scaling;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * Compatible with {@link Image}. Does not provide additional features.\n * @author Kotcrab\n * @see Image\n */\npublic class VisImage extends Image {\n\tpublic VisImage () {\n\t}\n\n\tpublic VisImage (NinePatch patch) {\n\t\tsuper(patch);\n\t}\n\n\tpublic VisImage (TextureRegion region) {\n\t\tsuper(region);\n\t}\n\n\tpublic VisImage (Texture texture) {\n\t\tsuper(texture);\n\t}\n\n\tpublic VisImage (String drawableName) {\n\t\tsuper(VisUI.getSkin(), drawableName);\n\t}\n\n\tpublic VisImage (Skin skin, String drawableName) {\n\t\tsuper(skin, drawableName);\n\t}\n\n\tpublic VisImage (Drawable drawable) {\n\t\tsuper(drawable);\n\t}\n\n\tpublic VisImage (Drawable drawable, Scaling scaling) {\n\t\tsuper(drawable, scaling);\n\t}\n\n\tpublic VisImage (Drawable drawable, Scaling scaling, int align) {\n\t\tsuper(drawable, scaling, align);\n\t}\n\n\tpublic void setDrawable (Texture texture) {\n\t\tsetDrawable(new TextureRegionDrawable(new TextureRegion(texture)));\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisImageButton.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.ui.Button;\nimport com.badlogic.gdx.scenes.scene2d.ui.Cell;\nimport com.badlogic.gdx.scenes.scene2d.ui.Image;\nimport com.badlogic.gdx.scenes.scene2d.ui.ImageButton;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.utils.Scaling;\nimport com.kotcrab.vis.ui.FocusManager;\nimport com.kotcrab.vis.ui.Focusable;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.BorderOwner;\n\n/**\n * Due to scope of changes made this widget is not compatible with standard {@link ImageButton}.\n * <p>\n * When listening for button press {@link ChangeListener} should be always preferred (instead of {@link ClickListener}).\n * {@link ClickListener} does not support disabling button and will still report button presses.\n * @author Kotcrab\n * @see ImageButton\n */\npublic class VisImageButton extends Button implements Focusable, BorderOwner {\n\tprivate Image image;\n\n\tprivate VisImageButtonStyle style;\n\n\tprivate boolean drawBorder;\n\tprivate boolean focusBorderEnabled = true;\n\n\tprivate boolean generateDisabledImage = false;\n\n\tpublic VisImageButton (Drawable imageUp) {\n\t\tthis(imageUp, null, null);\n\t}\n\n\tpublic VisImageButton (Drawable imageUp, String tooltipText) {\n\t\tthis(imageUp, null, null);\n\t\tif (tooltipText != null) new Tooltip.Builder(tooltipText).target(this).build();\n\t}\n\n\tpublic VisImageButton (Drawable imageUp, Drawable imageDown) {\n\t\tthis(imageUp, imageDown, null);\n\t}\n\n\tpublic VisImageButton (Drawable imageUp, Drawable imageDown, Drawable imageChecked) {\n\t\tthis(imageUp, imageDown, imageChecked, \"default\");\n\t}\n\n\tpublic VisImageButton (Drawable imageUp, Drawable imageDown, Drawable imageChecked, String styleName) {\n\t\tsuper(new VisImageButtonStyle(VisUI.getSkin().get(styleName, VisImageButtonStyle.class)));\n\t\tstyle.imageUp = imageUp;\n\t\tstyle.imageDown = imageDown;\n\t\tstyle.imageChecked = imageChecked;\n\n\t\tinit();\n\t}\n\n\tpublic VisImageButton (String styleName) {\n\t\tsuper(new VisImageButtonStyle(VisUI.getSkin().get(styleName, VisImageButtonStyle.class)));\n\t\tinit();\n\t}\n\n\tpublic VisImageButton (VisImageButtonStyle style) {\n\t\tsuper(style);\n\t\tinit();\n\t}\n\n\tprivate void init () {\n\t\timage = new Image();\n\t\timage.setScaling(Scaling.fit);\n\t\tadd(image);\n\t\tsetSize(getPrefWidth(), getPrefHeight());\n\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tif (isDisabled() == false) FocusManager.switchFocus(getStage(), VisImageButton.this);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\n\t\tupdateImage();\n\t}\n\n\t@Override\n\tpublic VisImageButtonStyle getStyle () {\n\t\treturn style;\n\t}\n\n\t@Override\n\tpublic void setStyle (ButtonStyle style) {\n\t\tif (!(style instanceof VisImageButtonStyle))\n\t\t\tthrow new IllegalArgumentException(\"style must be an ImageButtonStyle.\");\n\t\tsuper.setStyle(style);\n\t\tthis.style = (VisImageButtonStyle) style;\n\t\tif (image != null) updateImage();\n\t}\n\n\tprivate void updateImage () {\n\t\tDrawable drawable = null;\n\t\tif (isDisabled() && style.imageDisabled != null)\n\t\t\tdrawable = style.imageDisabled;\n\t\telse if (isPressed() && style.imageDown != null)\n\t\t\tdrawable = style.imageDown;\n\t\telse if (isChecked() && style.imageChecked != null)\n\t\t\tdrawable = (style.imageCheckedOver != null && isOver()) ? style.imageCheckedOver : style.imageChecked;\n\t\telse if (isOver() && style.imageOver != null)\n\t\t\tdrawable = style.imageOver;\n\t\telse if (style.imageUp != null)\n\t\t\tdrawable = style.imageUp;\n\t\timage.setDrawable(drawable);\n\n\t\tif (generateDisabledImage && style.imageDisabled == null) {\n\t\t\tif (isDisabled()) {\n\t\t\t\timage.setColor(Color.GRAY);\n\t\t\t} else {\n\t\t\t\timage.setColor(Color.WHITE);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tupdateImage();\n\t\tsuper.draw(batch, parentAlpha);\n\t\tif (focusBorderEnabled && drawBorder && style.focusBorder != null)\n\t\t\tstyle.focusBorder.draw(batch, getX(), getY(), getWidth(), getHeight());\n\t}\n\n\tpublic Image getImage () {\n\t\treturn image;\n\t}\n\n\tpublic Cell<?> getImageCell () {\n\t\treturn getCell(image);\n\t}\n\n\t@Override\n\tpublic void setDisabled (boolean disabled) {\n\t\tsuper.setDisabled(disabled);\n\t\tif (disabled) FocusManager.resetFocus(getStage(), this);\n\t}\n\n\t@Override\n\tpublic void focusLost () {\n\t\tdrawBorder = false;\n\t}\n\n\t@Override\n\tpublic void focusGained () {\n\t\tdrawBorder = true;\n\t}\n\n\t@Override\n\tpublic boolean isFocusBorderEnabled () {\n\t\treturn focusBorderEnabled;\n\t}\n\n\t@Override\n\tpublic void setFocusBorderEnabled (boolean focusBorderEnabled) {\n\t\tthis.focusBorderEnabled = focusBorderEnabled;\n\t}\n\n\tpublic boolean isGenerateDisabledImage () {\n\t\treturn generateDisabledImage;\n\t}\n\n\t/**\n\t * @param generate when set to true and button state is set to disabled then button image will be tinted with gray\n\t * color to better symbolize that button is disabled. This works best for white images.\n\t */\n\tpublic void setGenerateDisabledImage (boolean generate) {\n\t\tgenerateDisabledImage = generate;\n\t}\n\n\t/**\n\t * The style for an image button, see {@link ImageButton}.\n\t * @author Nathan Sweet\n\t */\n\tstatic public class VisImageButtonStyle extends ButtonStyle {\n\t\t/** Optional. */\n\t\tpublic Drawable imageUp, imageDown, imageOver, imageChecked, imageCheckedOver, imageDisabled;\n\t\tpublic Drawable focusBorder;\n\n\t\tpublic VisImageButtonStyle () {\n\t\t}\n\n\t\tpublic VisImageButtonStyle (Drawable up, Drawable down, Drawable checked, Drawable imageUp, Drawable imageDown,\n\t\t\t\t\t\t\t\t\tDrawable imageChecked) {\n\t\t\tsuper(up, down, checked);\n\t\t\tthis.imageUp = imageUp;\n\t\t\tthis.imageDown = imageDown;\n\t\t\tthis.imageChecked = imageChecked;\n\t\t}\n\n\t\tpublic VisImageButtonStyle (VisImageButtonStyle style) {\n\t\t\tsuper(style);\n\t\t\tthis.imageUp = style.imageUp;\n\t\t\tthis.imageDown = style.imageDown;\n\t\t\tthis.imageOver = style.imageOver;\n\t\t\tthis.imageChecked = style.imageChecked;\n\t\t\tthis.imageCheckedOver = style.imageCheckedOver;\n\t\t\tthis.imageDisabled = style.imageDisabled;\n\n\t\t\tthis.focusBorder = style.focusBorder;\n\t\t}\n\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisImageTextButton.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.graphics.g2d.BitmapFont;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.ui.*;\nimport com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.utils.Align;\nimport com.badlogic.gdx.utils.Null;\nimport com.badlogic.gdx.utils.Scaling;\nimport com.kotcrab.vis.ui.FocusManager;\nimport com.kotcrab.vis.ui.Focusable;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.BorderOwner;\nimport com.kotcrab.vis.ui.widget.VisTextButton.VisTextButtonStyle;\n\n/**\n * A button with a child {@link Image} and {@link Label}.\n * <p>\n * Due to scope of changes made this widget is not compatible with standard {@link ImageTextButton}.\n * <p>\n * When listening for button press {@link ChangeListener} should be always preferred (instead of {@link ClickListener}).\n * {@link ClickListener} does not support disabling button and will still report button presses.\n * @author Nathan Sweet\n * @author Kotcrab\n * @see ImageButton\n * @see TextButton\n * @see Button\n */\npublic class VisImageTextButton extends Button implements Focusable, BorderOwner {\n\tpublic enum Orientation { TEXT_RIGHT, TEXT_LEFT, TEXT_TOP, TEXT_BOTTOM }\n\n\tprivate Image image;\n\tprivate Label label;\n\n\tprivate boolean drawBorder;\n\tprivate boolean focusBorderEnabled = true;\n\n\tprivate boolean generateDisabledImage = false;\n\n\tprivate VisImageTextButtonStyle style;\n\tprivate Orientation orientation = Orientation.TEXT_RIGHT;\n\n\tpublic VisImageTextButton (String text, Drawable imageUp) {\n\t\tthis(text, \"default\", imageUp, null);\n\t}\n\n\tpublic VisImageTextButton (String text, String styleName, Drawable imageUp) {\n\t\tthis(text, styleName, imageUp, null);\n\t}\n\n\tpublic VisImageTextButton (String text, String styleName, Drawable imageUp, Drawable imageDown) {\n\t\tsuper(new VisImageTextButtonStyle(VisUI.getSkin().get(styleName, VisImageTextButtonStyle.class)));\n\t\tstyle.imageUp = imageUp;\n\t\tstyle.imageDown = imageDown;\n\n\t\tinit(text);\n\t}\n\n\tpublic VisImageTextButton (String text, String styleName) {\n\t\tsuper(new VisImageTextButtonStyle(VisUI.getSkin().get(styleName, VisImageTextButtonStyle.class)));\n\t\tinit(text);\n\t}\n\n\tpublic VisImageTextButton (String text, VisImageTextButtonStyle style) {\n\t\tsuper(style);\n\t\tinit(text);\n\t}\n\n\tprivate void init (String text) {\n\t\tdefaults().space(3);\n\n\t\timage = new Image();\n\t\timage.setScaling(Scaling.fit);\n\n\t\tlabel = new Label(text, new LabelStyle(style.font, style.fontColor));\n\t\tlabel.setAlignment(Align.center);\n\n\t\taddActorsBasedOnOrientation();\n\n\t\tsetStyle(style);\n\n\t\tsetSize(getPrefWidth(), getPrefHeight());\n\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tif (isDisabled() == false) FocusManager.switchFocus(getStage(), VisImageTextButton.this);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate void addActorsBasedOnOrientation() {\n\t\tswitch (orientation) {\n\t\t\tcase TEXT_RIGHT:\n\t\t\t\tadd(image);\n\t\t\t\tadd(label);\n\t\t\t\tbreak;\n\t\t\tcase TEXT_LEFT:\n\t\t\t\tadd(label);\n\t\t\t\tadd(image);\n\t\t\t\tbreak;\n\t\t\tcase TEXT_TOP:\n\t\t\t\tadd(label);\n\t\t\t\trow();\n\t\t\t\tadd(image);\n\t\t\t\tbreak;\n\t\t\tcase TEXT_BOTTOM:\n\t\t\t\tadd(image);\n\t\t\t\trow();\n\t\t\t\tadd(label);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setStyle (ButtonStyle style) {\n\t\tif (!(style instanceof VisImageTextButtonStyle))\n\t\t\tthrow new IllegalArgumentException(\"style must be a VisImageTextButtonStyle.\");\n\t\tsuper.setStyle(style);\n\t\tthis.style = (VisImageTextButtonStyle) style;\n\t\tif (image != null) updateImage();\n\t\tif (label != null) {\n\t\t\tVisImageTextButtonStyle textButtonStyle = (VisImageTextButtonStyle) style;\n\t\t\tLabelStyle labelStyle = label.getStyle();\n\t\t\tlabelStyle.font = textButtonStyle.font;\n\t\t\tlabelStyle.fontColor = textButtonStyle.fontColor;\n\t\t\tlabel.setStyle(labelStyle);\n\t\t}\n\t}\n\n\t@Override\n\tpublic VisImageTextButtonStyle getStyle () {\n\t\treturn style;\n\t}\n\n\tprivate void updateImage () {\n\t\tDrawable drawable = null;\n\t\tif (isDisabled() && style.imageDisabled != null)\n\t\t\tdrawable = style.imageDisabled;\n\t\telse if (isPressed() && style.imageDown != null)\n\t\t\tdrawable = style.imageDown;\n\t\telse if (isChecked() && style.imageChecked != null)\n\t\t\tdrawable = (style.imageCheckedOver != null && isOver()) ? style.imageCheckedOver : style.imageChecked;\n\t\telse if (isOver() && style.imageOver != null)\n\t\t\tdrawable = style.imageOver;\n\t\telse if (style.imageUp != null)\n\t\t\tdrawable = style.imageUp;\n\t\timage.setDrawable(drawable);\n\n\t\tif (generateDisabledImage && style.imageDisabled == null) {\n\t\t\tif (isDisabled()) {\n\t\t\t\timage.setColor(Color.GRAY);\n\t\t\t} else {\n\t\t\t\timage.setColor(Color.WHITE);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Returns the appropriate label font color from the style based on the current button state. */\n\tprotected @Null Color getFontColor () {\n\t\tif (isDisabled() && style.disabledFontColor != null) return style.disabledFontColor;\n\t\tif (isPressed()) {\n\t\t\tif (isChecked() && style.checkedDownFontColor != null) return style.checkedDownFontColor;\n\t\t\tif (style.downFontColor != null) return style.downFontColor;\n\t\t}\n\t\tif (isOver()) {\n\t\t\tif (isChecked()) {\n\t\t\t\tif (style.checkedOverFontColor != null) return style.checkedOverFontColor;\n\t\t\t} else {\n\t\t\t\tif (style.overFontColor != null) return style.overFontColor;\n\t\t\t}\n\t\t}\n\t\tboolean focused = hasKeyboardFocus();\n\t\tif (isChecked()) {\n\t\t\tif (focused && style.checkedFocusedFontColor != null) return style.checkedFocusedFontColor;\n\t\t\tif (style.checkedFontColor != null) return style.checkedFontColor;\n\t\t\tif (isOver() && style.overFontColor != null) return style.overFontColor;\n\t\t}\n\t\tif (focused && style.focusedFontColor != null) return style.focusedFontColor;\n\t\treturn style.fontColor;\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tupdateImage();\n\t\tColor fontColor = getFontColor();\n\t\tif (fontColor != null) label.getStyle().fontColor = fontColor;\n\t\tsuper.draw(batch, parentAlpha);\n\t\tif (focusBorderEnabled && drawBorder && style.focusBorder != null)\n\t\t\tstyle.focusBorder.draw(batch, getX(), getY(), getWidth(), getHeight());\n\t}\n\n\tpublic Orientation getOrientation() {\n\t\treturn orientation;\n\t}\n\n\tpublic void setOrientation(Orientation orientation) {\n\t\tthis.orientation = orientation;\n\t\tclearChildren();\n\t\taddActorsBasedOnOrientation();\n\t}\n\n\tpublic Image getImage () {\n\t\treturn image;\n\t}\n\n\tpublic Cell getImageCell () {\n\t\treturn getCell(image);\n\t}\n\n\tpublic Label getLabel () {\n\t\treturn label;\n\t}\n\n\tpublic Cell getLabelCell () {\n\t\treturn getCell(label);\n\t}\n\n\tpublic void setText (CharSequence text) {\n\t\tlabel.setText(text);\n\t}\n\n\tpublic CharSequence getText () {\n\t\treturn label.getText();\n\t}\n\n\tpublic String toString () {\n\t\treturn super.toString() + \": \" + label.getText();\n\t}\n\n\t@Override\n\tpublic void setDisabled (boolean disabled) {\n\t\tsuper.setDisabled(disabled);\n\t\tif (disabled) FocusManager.resetFocus(getStage(), this);\n\t}\n\n\t@Override\n\tpublic void focusLost () {\n\t\tdrawBorder = false;\n\t}\n\n\t@Override\n\tpublic void focusGained () {\n\t\tdrawBorder = true;\n\t}\n\n\t@Override\n\tpublic boolean isFocusBorderEnabled () {\n\t\treturn focusBorderEnabled;\n\t}\n\n\t@Override\n\tpublic void setFocusBorderEnabled (boolean focusBorderEnabled) {\n\t\tthis.focusBorderEnabled = focusBorderEnabled;\n\t}\n\n\tpublic boolean isGenerateDisabledImage () {\n\t\treturn generateDisabledImage;\n\t}\n\n\t/**\n\t * @param generate when set to true and button state is set to disabled then button image will be tinted with gray\n\t * color to better symbolize that button is disabled. This works best for white images.\n\t */\n\tpublic void setGenerateDisabledImage (boolean generate) {\n\t\tgenerateDisabledImage = generate;\n\t}\n\n\t/**\n\t * The style for an image text button, see {@link ImageTextButton}.\n\t * @author Nathan Sweet\n\t */\n\tstatic public class VisImageTextButtonStyle extends VisTextButtonStyle {\n\t\t/** Optional. */\n\t\tpublic Drawable imageUp, imageDown, imageOver, imageChecked, imageCheckedOver, imageDisabled;\n\n\t\tpublic VisImageTextButtonStyle () {\n\t\t}\n\n\t\tpublic VisImageTextButtonStyle (Drawable up, Drawable down, Drawable checked, BitmapFont font) {\n\t\t\tsuper(up, down, checked, font);\n\t\t}\n\n\t\tpublic VisImageTextButtonStyle (VisImageTextButtonStyle style) {\n\t\t\tsuper(style);\n\t\t\tif (style.imageUp != null) this.imageUp = style.imageUp;\n\t\t\tif (style.imageDown != null) this.imageDown = style.imageDown;\n\t\t\tif (style.imageOver != null) this.imageOver = style.imageOver;\n\t\t\tif (style.imageChecked != null) this.imageChecked = style.imageChecked;\n\t\t\tif (style.imageCheckedOver != null) this.imageCheckedOver = style.imageCheckedOver;\n\t\t\tif (style.imageDisabled != null) this.imageDisabled = style.imageDisabled;\n\t\t}\n\n\t\tpublic VisImageTextButtonStyle (VisTextButtonStyle style) {\n\t\t\tsuper(style);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisLabel.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.scenes.scene2d.ui.Label;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * Compatible with {@link Label}. Does not provide additional features.\n * @author Kotcrab\n * @see Label\n */\npublic class VisLabel extends Label {\n\tpublic VisLabel () {\n\t\tsuper(\"\", VisUI.getSkin());\n\t}\n\n\tpublic VisLabel (CharSequence text, Color textColor) {\n\t\tsuper(text, VisUI.getSkin());\n\t\tsetColor(textColor);\n\t}\n\n\tpublic VisLabel (CharSequence text, int alignment) {\n\t\tthis(text);\n\t\tsetAlignment(alignment);\n\t}\n\n\tpublic VisLabel (CharSequence text) {\n\t\tsuper(text, VisUI.getSkin());\n\t}\n\n\tpublic VisLabel (CharSequence text, LabelStyle style) {\n\t\tsuper(text, style);\n\t}\n\n\tpublic VisLabel (CharSequence text, String styleName) {\n\t\tsuper(text, VisUI.getSkin(), styleName);\n\t}\n\n\tpublic VisLabel (CharSequence text, String fontName, Color color) {\n\t\tsuper(text, VisUI.getSkin(), fontName, color);\n\t}\n\n\tpublic VisLabel (CharSequence text, String fontName, String colorName) {\n\t\tsuper(text, VisUI.getSkin(), fontName, colorName);\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisList.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.ui.List;\nimport com.kotcrab.vis.ui.FocusManager;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * Compatible with {@link List}. Does not provide additional features however for proper VisUI focus management List\n * should be always preferred.\n * @author Kotcrab\n * @see List\n */\npublic class VisList<T> extends List<T> {\n\n\tpublic VisList () {\n\t\tsuper(VisUI.getSkin());\n\t\tinit();\n\t}\n\n\tpublic VisList (String styleName) {\n\t\tsuper(VisUI.getSkin(), styleName);\n\t\tinit();\n\t}\n\n\tpublic VisList (ListStyle style) {\n\t\tsuper(style);\n\t\tinit();\n\t}\n\n\tprivate void init () {\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tFocusManager.resetFocus(getStage());\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisProgressBar.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.ProgressBar;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * Compatible with {@link ProgressBar}. Does not provide additional features.\n * @author Kotcrab\n * @see ProgressBar\n */\npublic class VisProgressBar extends ProgressBar {\n\tpublic VisProgressBar (float min, float max, float stepSize, boolean vertical) {\n\t\tthis(min, max, stepSize, vertical, VisUI.getSkin().get(\"default-\" + (vertical ? \"vertical\" : \"horizontal\"),\n\t\t\t\tProgressBarStyle.class));\n\t}\n\n\tpublic VisProgressBar (float min, float max, float stepSize, boolean vertical, String styleName) {\n\t\tthis(min, max, stepSize, vertical, VisUI.getSkin().get(styleName, ProgressBarStyle.class));\n\t}\n\n\tpublic VisProgressBar (float min, float max, float stepSize, boolean vertical, ProgressBarStyle style) {\n\t\tsuper(min, max, stepSize, vertical, style);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisRadioButton.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * Similar to {@link VisCheckBox} however uses round (instead of square) button {@link Drawable}. Note that if you\n * want to achieve 'select only one option' behaviour you need to use {@link ButtonGroup}.\n * <p>\n * When listening for button press {@link ChangeListener} should be always preferred (instead of {@link ClickListener}).\n * {@link ClickListener} does not support disabling button and will still report button presses.\n * @author Kotcrab\n * @see VisCheckBox\n */\npublic class VisRadioButton extends VisCheckBox {\n\tpublic VisRadioButton (String text) {\n\t\tthis(text, VisUI.getSkin().get(\"radio\", VisCheckBoxStyle.class));\n\t}\n\n\tpublic VisRadioButton (String text, VisCheckBoxStyle style) {\n\t\tsuper(text, style);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisScrollPane.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * Compatible with {@link ScrollPane}. Does not provide additional features.\n * @author Kotcrab\n * @see ScrollPane\n */\npublic class VisScrollPane extends ScrollPane {\n\tpublic VisScrollPane (Actor widget, ScrollPaneStyle style) {\n\t\tsuper(widget, style);\n\t}\n\n\tpublic VisScrollPane (Actor widget, String styleName) {\n\t\tsuper(widget, VisUI.getSkin(), styleName);\n\t}\n\n\tpublic VisScrollPane (Actor widget) {\n\t\tsuper(widget, VisUI.getSkin(), \"list\");\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisSelectBox.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.ui.SelectBox;\nimport com.kotcrab.vis.ui.FocusManager;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * Compatible with {@link SelectBox}. Does not provide additional features however for proper VisUI focus management VisSelectBox\n * should be always preferred.\n * @author Kotcrab\n * @see SelectBox\n */\npublic class VisSelectBox<T> extends SelectBox<T> {\n\tpublic VisSelectBox (SelectBoxStyle style) {\n\t\tsuper(style);\n\t\tinit();\n\t}\n\n\tpublic VisSelectBox (String styleName) {\n\t\tsuper(VisUI.getSkin(), styleName);\n\t\tinit();\n\t}\n\n\tpublic VisSelectBox () {\n\t\tsuper(VisUI.getSkin());\n\t\tinit();\n\t}\n\n\tprivate void init () {\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tFocusManager.resetFocus(getStage());\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisSlider.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Slider;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * Compatible with {@link Slider}. Does not provide additional features.\n * @author Kotcrab\n * @see Slider\n */\npublic class VisSlider extends Slider {\n\tpublic VisSlider (float min, float max, float stepSize, boolean vertical) {\n\t\tsuper(min, max, stepSize, vertical, VisUI.getSkin());\n\t}\n\n\tpublic VisSlider (float min, float max, float stepSize, boolean vertical, String styleName) {\n\t\tsuper(min, max, stepSize, vertical, VisUI.getSkin(), styleName);\n\t}\n\n\tpublic VisSlider (float min, float max, float stepSize, boolean vertical, SliderStyle style) {\n\t\tsuper(min, max, stepSize, vertical, style);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisSplitPane.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.math.Rectangle;\nimport com.badlogic.gdx.math.Vector2;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.ui.SplitPane;\nimport com.badlogic.gdx.scenes.scene2d.ui.SplitPane.SplitPaneStyle;\nimport com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.scenes.scene2d.utils.Layout;\nimport com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;\nimport com.badlogic.gdx.utils.GdxRuntimeException;\nimport com.kotcrab.vis.ui.FocusManager;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.widget.internal.SplitPaneCursorManager;\n\n/**\n * Extends functionality of standard {@link SplitPane}. Style supports handle over {@link Drawable}. Due to scope of\n * changes made this widget is not compatible with {@link SplitPane}.\n * @author mzechner\n * @author Nathan Sweet\n * @author Kotcrab\n * @see SplitPane\n */\npublic class VisSplitPane extends WidgetGroup {\n\tVisSplitPaneStyle style;\n\tprivate Actor firstWidget, secondWidget;\n\tboolean vertical;\n\tfloat splitAmount = 0.5f, minAmount, maxAmount = 1;\n\t// private float oldSplitAmount;\n\n\tprivate Rectangle firstWidgetBounds = new Rectangle();\n\tprivate Rectangle secondWidgetBounds = new Rectangle();\n\tRectangle handleBounds = new Rectangle();\n\tprivate Rectangle firstScissors = new Rectangle();\n\tprivate Rectangle secondScissors = new Rectangle();\n\n\tVector2 lastPoint = new Vector2();\n\tVector2 handlePosition = new Vector2();\n\n\tprivate boolean mouseOnHandle;\n\n\t/**\n\t * @param firstWidget May be null.\n\t * @param secondWidget May be null.\n\t */\n\tpublic VisSplitPane (Actor firstWidget, Actor secondWidget, boolean vertical) {\n\t\tthis(firstWidget, secondWidget, vertical, \"default-\" + (vertical ? \"vertical\" : \"horizontal\"));\n\t}\n\n\t/**\n\t * @param firstWidget May be null.\n\t * @param secondWidget May be null.\n\t */\n\tpublic VisSplitPane (Actor firstWidget, Actor secondWidget, boolean vertical, String styleName) {\n\t\tthis(firstWidget, secondWidget, vertical, VisUI.getSkin().get(styleName, VisSplitPaneStyle.class));\n\t}\n\n\t/**\n\t * @param firstWidget May be null.\n\t * @param secondWidget May be null.\n\t */\n\tpublic VisSplitPane (Actor firstWidget, Actor secondWidget, boolean vertical, VisSplitPaneStyle style) {\n\t\tthis.firstWidget = firstWidget;\n\t\tthis.secondWidget = secondWidget;\n\t\tthis.vertical = vertical;\n\t\tsetStyle(style);\n\t\tsetFirstWidget(firstWidget);\n\t\tsetSecondWidget(secondWidget);\n\t\tsetSize(getPrefWidth(), getPrefHeight());\n\t\tinitialize();\n\t}\n\n\tprivate void initialize () {\n\t\taddListener(new SplitPaneCursorManager(this, vertical) {\n\t\t\t@Override\n\t\t\tprotected boolean handleBoundsContains (float x, float y) {\n\t\t\t\treturn handleBounds.contains(x, y);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tprotected boolean contains (float x, float y) {\n\t\t\t\treturn firstWidgetBounds.contains(x, y) || secondWidgetBounds.contains(x, y) || handleBounds.contains(x, y);\n\t\t\t}\n\t\t});\n\n\t\taddListener(new InputListener() {\n\t\t\tint draggingPointer = -1;\n\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\t//TODO potential bug with libgdx scene2d?\n\t\t\t\t//fixes issue when split bar could be still dragged even when touchable is set to childrenOnly, probably scene2d issue\n\t\t\t\tif (isTouchable() == false) return false;\n\n\t\t\t\tif (draggingPointer != -1) return false;\n\t\t\t\tif (pointer == 0 && button != 0) return false;\n\t\t\t\tif (handleBounds.contains(x, y)) {\n\t\t\t\t\tFocusManager.resetFocus(getStage());\n\n\t\t\t\t\tdraggingPointer = pointer;\n\t\t\t\t\tlastPoint.set(x, y);\n\t\t\t\t\thandlePosition.set(handleBounds.x, handleBounds.y);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void touchUp (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tif (pointer == draggingPointer) draggingPointer = -1;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean mouseMoved (InputEvent event, float x, float y) {\n\t\t\t\tmouseOnHandle = handleBounds.contains(x, y);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void touchDragged (InputEvent event, float x, float y, int pointer) {\n\t\t\t\tif (pointer != draggingPointer) return;\n\n\t\t\t\tDrawable handle = style.handle;\n\t\t\t\tif (!vertical) {\n\t\t\t\t\tfloat delta = x - lastPoint.x;\n\t\t\t\t\tfloat availWidth = getWidth() - handle.getMinWidth();\n\t\t\t\t\tfloat dragX = handlePosition.x + delta;\n\t\t\t\t\thandlePosition.x = dragX;\n\t\t\t\t\tdragX = Math.max(0, dragX);\n\t\t\t\t\tdragX = Math.min(availWidth, dragX);\n\t\t\t\t\tsplitAmount = dragX / availWidth;\n\t\t\t\t\tif (splitAmount < minAmount) splitAmount = minAmount;\n\t\t\t\t\tif (splitAmount > maxAmount) splitAmount = maxAmount;\n\t\t\t\t\tlastPoint.set(x, y);\n\t\t\t\t} else {\n\t\t\t\t\tfloat delta = y - lastPoint.y;\n\t\t\t\t\tfloat availHeight = getHeight() - handle.getMinHeight();\n\t\t\t\t\tfloat dragY = handlePosition.y + delta;\n\t\t\t\t\thandlePosition.y = dragY;\n\t\t\t\t\tdragY = Math.max(0, dragY);\n\t\t\t\t\tdragY = Math.min(availHeight, dragY);\n\t\t\t\t\tsplitAmount = 1 - (dragY / availHeight);\n\t\t\t\t\tif (splitAmount < minAmount) splitAmount = minAmount;\n\t\t\t\t\tif (splitAmount > maxAmount) splitAmount = maxAmount;\n\t\t\t\t\tlastPoint.set(x, y);\n\t\t\t\t}\n\t\t\t\tinvalidate();\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Returns the split pane's style. Modifying the returned style may not have an effect until {@link #setStyle(VisSplitPaneStyle)}\n\t * is called.\n\t */\n\tpublic VisSplitPaneStyle getStyle () {\n\t\treturn style;\n\t}\n\n\tpublic void setStyle (VisSplitPaneStyle style) {\n\t\tthis.style = style;\n\t\tinvalidateHierarchy();\n\t}\n\n\t@Override\n\tpublic void layout () {\n\t\tif (!vertical)\n\t\t\tcalculateHorizBoundsAndPositions();\n\t\telse\n\t\t\tcalculateVertBoundsAndPositions();\n\n\t\tActor firstWidget = this.firstWidget;\n\t\tif (firstWidget != null) {\n\t\t\tRectangle firstWidgetBounds = this.firstWidgetBounds;\n\t\t\tfirstWidget.setBounds(firstWidgetBounds.x, firstWidgetBounds.y, firstWidgetBounds.width, firstWidgetBounds.height);\n\t\t\tif (firstWidget instanceof Layout) ((Layout) firstWidget).validate();\n\t\t}\n\t\tActor secondWidget = this.secondWidget;\n\t\tif (secondWidget != null) {\n\t\t\tRectangle secondWidgetBounds = this.secondWidgetBounds;\n\t\t\tsecondWidget.setBounds(secondWidgetBounds.x, secondWidgetBounds.y, secondWidgetBounds.width, secondWidgetBounds.height);\n\t\t\tif (secondWidget instanceof Layout) ((Layout) secondWidget).validate();\n\t\t}\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\tfloat width = 0;\n\t\tif (firstWidget != null)\n\t\t\twidth = firstWidget instanceof Layout ? ((Layout) firstWidget).getPrefWidth() : firstWidget.getWidth();\n\t\tif (secondWidget != null)\n\t\t\twidth += secondWidget instanceof Layout ? ((Layout) secondWidget).getPrefWidth() : secondWidget.getWidth();\n\t\tif (!vertical) width += style.handle.getMinWidth();\n\t\treturn width;\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\tfloat height = 0;\n\t\tif (firstWidget != null)\n\t\t\theight = firstWidget instanceof Layout ? ((Layout) firstWidget).getPrefHeight() : firstWidget.getHeight();\n\t\tif (secondWidget != null)\n\t\t\theight += secondWidget instanceof Layout ? ((Layout) secondWidget).getPrefHeight() : secondWidget.getHeight();\n\t\tif (vertical) height += style.handle.getMinHeight();\n\t\treturn height;\n\t}\n\n\t@Override\n\tpublic float getMinWidth () {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic float getMinHeight () {\n\t\treturn 0;\n\t}\n\n\t/** @return first widgets bounds, changing returned rectangle values does not have any effect */\n\tpublic Rectangle getFirstWidgetBounds () {\n\t\treturn new Rectangle(firstWidgetBounds);\n\t}\n\n\t/** @return seconds widgets bounds, changing returned rectangle values does not have any effect */\n\tpublic Rectangle getSecondWidgetBounds () {\n\t\treturn new Rectangle(secondWidgetBounds);\n\t}\n\n\tpublic void setVertical (boolean vertical) {\n\t\tthis.vertical = vertical;\n\t}\n\n\tprivate void calculateHorizBoundsAndPositions () {\n\t\tDrawable handle = style.handle;\n\n\t\tfloat height = getHeight();\n\n\t\tfloat availWidth = getWidth() - handle.getMinWidth();\n\t\tfloat leftAreaWidth = (int) (availWidth * splitAmount);\n\t\tfloat rightAreaWidth = availWidth - leftAreaWidth;\n\t\tfloat handleWidth = handle.getMinWidth();\n\n\t\tfirstWidgetBounds.set(0, 0, leftAreaWidth, height);\n\t\tsecondWidgetBounds.set(leftAreaWidth + handleWidth, 0, rightAreaWidth, height);\n\t\thandleBounds.set(leftAreaWidth, 0, handleWidth, height);\n\t}\n\n\tprivate void calculateVertBoundsAndPositions () {\n\t\tDrawable handle = style.handle;\n\n\t\tfloat width = getWidth();\n\t\tfloat height = getHeight();\n\n\t\tfloat availHeight = height - handle.getMinHeight();\n\t\tfloat topAreaHeight = (int) (availHeight * splitAmount);\n\t\tfloat bottomAreaHeight = availHeight - topAreaHeight;\n\t\tfloat handleHeight = handle.getMinHeight();\n\n\t\tfirstWidgetBounds.set(0, height - topAreaHeight, width, topAreaHeight);\n\t\tsecondWidgetBounds.set(0, 0, width, bottomAreaHeight);\n\t\thandleBounds.set(0, bottomAreaHeight, width, handleHeight);\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tvalidate();\n\n\t\tColor color = getColor();\n\n\t\tapplyTransform(batch, computeTransform());\n\t\t// Matrix4 transform = batch.getTransformMatrix();\n\t\tif (firstWidget != null) {\n\t\t\tgetStage().calculateScissors(firstWidgetBounds, firstScissors);\n\t\t\tif (ScissorStack.pushScissors(firstScissors)) {\n\t\t\t\tif (firstWidget.isVisible()) firstWidget.draw(batch, parentAlpha * color.a);\n\t\t\t\tbatch.flush();\n\t\t\t\tScissorStack.popScissors();\n\t\t\t}\n\t\t}\n\t\tif (secondWidget != null) {\n\t\t\tgetStage().calculateScissors(secondWidgetBounds, secondScissors);\n\t\t\tif (ScissorStack.pushScissors(secondScissors)) {\n\t\t\t\tif (secondWidget.isVisible()) secondWidget.draw(batch, parentAlpha * color.a);\n\t\t\t\tbatch.flush();\n\t\t\t\tScissorStack.popScissors();\n\t\t\t}\n\t\t}\n\n\t\tDrawable handle = style.handle;\n\t\tif (mouseOnHandle && isTouchable() && style.handleOver != null) handle = style.handleOver;\n\t\tbatch.setColor(color.r, color.g, color.b, parentAlpha * color.a);\n\t\thandle.draw(batch, handleBounds.x, handleBounds.y, handleBounds.width, handleBounds.height);\n\t\tresetTransform(batch);\n\n\t}\n\n\t@Override\n\tpublic Actor hit (float x, float y, boolean touchable) {\n\t\tif (touchable && getTouchable() == Touchable.disabled) return null;\n\t\tif (handleBounds.contains(x, y)) {\n\t\t\treturn this;\n\t\t} else {\n\t\t\treturn super.hit(x, y, touchable);\n\t\t}\n\t}\n\n\t/** @param split The split amount between the min and max amount. */\n\tpublic void setSplitAmount (float split) {\n\t\tthis.splitAmount = Math.max(Math.min(maxAmount, split), minAmount);\n\t\tinvalidate();\n\t}\n\n\tpublic float getSplit () {\n\t\treturn splitAmount;\n\t}\n\n\tpublic void setMinSplitAmount (float minAmount) {\n\t\tif (minAmount < 0) throw new GdxRuntimeException(\"minAmount has to be >= 0\");\n\t\tif (minAmount >= maxAmount) throw new GdxRuntimeException(\"minAmount has to be < maxAmount\");\n\t\tthis.minAmount = minAmount;\n\t}\n\n\tpublic void setMaxSplitAmount (float maxAmount) {\n\t\tif (maxAmount > 1) throw new GdxRuntimeException(\"maxAmount has to be >= 0\");\n\t\tif (maxAmount <= minAmount) throw new GdxRuntimeException(\"maxAmount has to be > minAmount\");\n\t\tthis.maxAmount = maxAmount;\n\t}\n\n\t/**\n\t * @param firstWidget May be null\n\t * @param secondWidget May be null\n\t */\n\tpublic void setWidgets (Actor firstWidget, Actor secondWidget) {\n\t\tsetFirstWidget(firstWidget);\n\t\tsetSecondWidget(secondWidget);\n\t}\n\n\t/** @param widget May be null. */\n\tpublic void setFirstWidget (Actor widget) {\n\t\tif (firstWidget != null) super.removeActor(firstWidget);\n\t\tfirstWidget = widget;\n\t\tif (widget != null) super.addActor(widget);\n\t\tinvalidate();\n\t}\n\n\t/** @param widget May be null. */\n\tpublic void setSecondWidget (Actor widget) {\n\t\tif (secondWidget != null) super.removeActor(secondWidget);\n\t\tsecondWidget = widget;\n\t\tif (widget != null) super.addActor(widget);\n\t\tinvalidate();\n\t}\n\n\t@Override\n\tpublic void addActor (Actor actor) {\n\t\tthrow new UnsupportedOperationException(\"Use ScrollPane#setWidget.\");\n\t}\n\n\t@Override\n\tpublic void addActorAt (int index, Actor actor) {\n\t\tthrow new UnsupportedOperationException(\"Use ScrollPane#setWidget.\");\n\t}\n\n\t@Override\n\tpublic void addActorBefore (Actor actorBefore, Actor actor) {\n\t\tthrow new UnsupportedOperationException(\"Use ScrollPane#setWidget.\");\n\t}\n\n\t@Override\n\tpublic boolean removeActor (Actor actor) {\n\t\tif (actor == null) throw new IllegalArgumentException(\"actor cannot be null.\");\n\t\tif (actor == firstWidget) {\n\t\t\tsetFirstWidget(null);\n\t\t\treturn true;\n\t\t}\n\t\tif (actor == secondWidget) {\n\t\t\tsetSecondWidget(null);\n\t\t\treturn true;\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean removeActor (Actor actor, boolean unfocus) {\n\t\tif (actor == null) throw new IllegalArgumentException(\"actor cannot be null.\");\n\t\tif (actor == firstWidget) {\n\t\t\tsuper.removeActor(actor, unfocus);\n\t\t\tfirstWidget = null;\n\t\t\tinvalidate();\n\t\t\treturn true;\n\t\t}\n\t\tif (actor == secondWidget) {\n\t\t\tsuper.removeActor(actor, unfocus);\n\t\t\tsecondWidget = null;\n\t\t\tinvalidate();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic static class VisSplitPaneStyle extends SplitPaneStyle {\n\t\t/** Optional **/\n\t\tpublic Drawable handleOver;\n\n\t\tpublic VisSplitPaneStyle () {\n\t\t}\n\n\t\tpublic VisSplitPaneStyle (VisSplitPaneStyle style) {\n\t\t\tsuper(style);\n\t\t\tthis.handleOver = style.handleOver;\n\t\t}\n\n\t\tpublic VisSplitPaneStyle (Drawable handle, Drawable handleOver) {\n\t\t\tsuper(handle);\n\t\t\tthis.handleOver = handleOver;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisTable.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Cell;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.TableUtils;\n\n/**\n * Extends functionality of standard {@link Table}, supports setting default VisUI spacing and has utilities method for adding\n * separators. Compatible with {@link Table}.\n * @author Kotcrab\n * @see Table\n */\npublic class VisTable extends Table {\n\tpublic VisTable () {\n\t\tsuper(VisUI.getSkin());\n\t}\n\n\t/** @param setVisDefaults if true default vis spacing defaults will be set */\n\tpublic VisTable (boolean setVisDefaults) {\n\t\tsuper(VisUI.getSkin());\n\t\tif (setVisDefaults) TableUtils.setSpacingDefaults(this);\n\t}\n\n\t/**\n\t * Adds vertical or horizontal {@link Separator} widget to table with padding top, bottom 2px with fill and expand properties.\n\t * If vertical == false then inserts new row after separator (not before!)\n\t */\n\tpublic Cell<Separator> addSeparator (boolean vertical) {\n\t\tCell<Separator> cell = add(new Separator(vertical ? \"vertical\" : \"default\")).padTop(2).padBottom(2);\n\n\t\tif (vertical)\n\t\t\tcell.fillY().expandY();\n\t\telse {\n\t\t\tcell.fillX().expandX();\n\t\t\trow();\n\t\t}\n\n\t\treturn cell;\n\t}\n\n\t/**\n\t * Adds horizontal {@link Separator} widget to table with padding top, bottom 2px with fillX and expandX properties and inserts new row\n\t * after separator (not before!)\n\t */\n\tpublic Cell<Separator> addSeparator () {\n\t\treturn addSeparator(false);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisTextArea.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.Input;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.graphics.g2d.BitmapFont;\nimport com.badlogic.gdx.graphics.g2d.GlyphLayout;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.Stage;\nimport com.badlogic.gdx.scenes.scene2d.ui.TextArea;\nimport com.badlogic.gdx.scenes.scene2d.ui.TextField;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.scenes.scene2d.utils.UIUtils;\nimport com.badlogic.gdx.utils.Align;\nimport com.badlogic.gdx.utils.IntArray;\nimport com.badlogic.gdx.utils.Pool;\nimport com.badlogic.gdx.utils.Pools;\n\n/**\n * A multiple-line text input field, entirely based on {@link TextField}.\n * @author Kotcrab (few modifications, orginal {@link TextArea} is missing authors)\n * @see TextArea\n */\npublic class VisTextArea extends VisTextField {\n\t/** Array storing lines breaks positions * */\n\tIntArray linesBreak;\n\n\t/** Last text processed. This attribute is used to avoid unnecessary computations while calculating offsets * */\n\tprivate String lastText;\n\n\t/** Current line for the cursor * */\n\tint cursorLine;\n\n\t/** Index of the first line showed by the text area * */\n\tint firstLineShowing;\n\n\t/** Number of lines showed by the text area * */\n\tint linesShowing;\n\n\t/** Variable to maintain the x offset of the cursor when moving up and down. If it's set to -1, the offset is reset * */\n\tfloat moveOffset;\n\n\tprivate float prefRows;\n\n\t/**\n\t * Allows to disable, enable disabling softwrapping. Note this isn't exposed property because TextArea can't handle it's by default.\n\t * You must have text area which can calculate its max width such as {@link HighlightTextArea}\n\t */\n\tboolean softwrap = true;\n\tfloat cursorX;\n\n\tpublic VisTextArea () {\n\t\tsuper();\n\t}\n\n\tpublic VisTextArea (String text, String styleName) {\n\t\tsuper(text, styleName);\n\t}\n\n\tpublic VisTextArea (String text, VisTextFieldStyle style) {\n\t\tsuper(text, style);\n\t}\n\n\tpublic VisTextArea (String text) {\n\t\tsuper(text);\n\t}\n\n\t@Override\n\tprotected void initialize () {\n\t\tsuper.initialize();\n\t\twriteEnters = true;\n\t\tlinesBreak = new IntArray();\n\t\tcursorLine = 0;\n\t\tfirstLineShowing = 0;\n\t\tmoveOffset = -1;\n\t\tlinesShowing = 0;\n\t}\n\n\t@Override\n\tprotected int letterUnderCursor (float x) {\n\t\tif (linesBreak.size > 0) {\n\t\t\tif (cursorLine * 2 >= linesBreak.size) {\n\t\t\t\treturn text.length();\n\t\t\t} else {\n\t\t\t\tfloat[] glyphPositions = this.glyphPositions.items;\n\t\t\t\tint start = linesBreak.items[cursorLine * 2];\n\t\t\t\tx += glyphPositions[start];\n\t\t\t\tint end = linesBreak.items[cursorLine * 2 + 1];\n\t\t\t\tint i = start;\n\t\t\t\tfor (; i < end; i++)\n\t\t\t\t\tif (glyphPositions[i] > x) break;\n\t\t\t\tif (i > 0 && glyphPositions[i] - x <= x - glyphPositions[i - 1]) {\n\t\t\t\t\treturn Math.min(i, text.length());\n\t\t\t\t}\n\t\t\t\treturn Math.max(0, i - 1);\n\t\t\t}\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\t/** Sets the preferred number of rows (lines) for this text area. Used to calculate preferred height */\n\tpublic void setPrefRows (float prefRows) {\n\t\tthis.prefRows = prefRows;\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\tif (prefRows <= 0) {\n\t\t\treturn super.getPrefHeight();\n\t\t} else {\n\t\t\tfloat prefHeight = textHeight * prefRows;\n\t\t\tif (style.background != null) {\n\t\t\t\tprefHeight = Math.max(prefHeight + style.background.getBottomHeight() + style.background.getTopHeight(),\n\t\t\t\t\t\tstyle.background.getMinHeight());\n\t\t\t}\n\t\t\treturn prefHeight;\n\t\t}\n\t}\n\n\t/** Returns total number of lines that the text occupies * */\n\tpublic int getLines () {\n\t\treturn linesBreak.size / 2 + (newLineAtEnd() ? 1 : 0);\n\t}\n\n\t/** Returns if there's a new line at then end of the text * */\n\tpublic boolean newLineAtEnd () {\n\t\treturn text.length() != 0\n\t\t\t\t&& (text.charAt(text.length() - 1) == ENTER_ANDROID || text.charAt(text.length() - 1) == ENTER_DESKTOP);\n\t}\n\n\t/** Moves the cursor to the given number line * */\n\tpublic void moveCursorLine (int line) {\n\t\tif (line < 0) {\n\t\t\tcursorLine = 0;\n\t\t\tcursor = 0;\n\t\t\tmoveOffset = -1;\n\t\t} else if (line >= getLines()) {\n\t\t\tint newLine = getLines() - 1;\n\t\t\tcursor = text.length();\n\t\t\tif (line > getLines() || newLine == cursorLine) {\n\t\t\t\tmoveOffset = -1;\n\t\t\t}\n\t\t\tcursorLine = newLine;\n\t\t} else if (line != cursorLine) {\n\t\t\tif (moveOffset < 0) {\n\t\t\t\tmoveOffset = linesBreak.size <= cursorLine * 2 ? 0\n\t\t\t\t\t\t: glyphPositions.get(cursor) - glyphPositions.get(linesBreak.get(cursorLine * 2));\n\t\t\t}\n\t\t\tcursorLine = line;\n\t\t\tcursor = cursorLine * 2 >= linesBreak.size ? text.length() : linesBreak.get(cursorLine * 2);\n\t\t\twhile (cursor < text.length() && cursor <= linesBreak.get(cursorLine * 2 + 1) - 1\n\t\t\t\t\t&& glyphPositions.get(cursor) - glyphPositions.get(linesBreak.get(cursorLine * 2)) < moveOffset) {\n\t\t\t\tcursor++;\n\t\t\t}\n\t\t\tshowCursor();\n\t\t}\n\t}\n\n\t/** Updates the current line, checking the cursor position in the text * */\n\tvoid updateCurrentLine () {\n\t\tint index = calculateCurrentLineIndex(cursor);\n\t\tint line = index / 2;\n\t\t// Special case when cursor moves to the beginning of the line from the end of another and a word\n\t\t// wider than the box\n\t\tif (index % 2 == 0 || index + 1 >= linesBreak.size || cursor != linesBreak.items[index]\n\t\t\t\t|| linesBreak.items[index + 1] != linesBreak.items[index]) {\n\t\t\tif (line < linesBreak.size / 2 || text.length() == 0 || text.charAt(text.length() - 1) == ENTER_ANDROID\n\t\t\t\t\t|| text.charAt(text.length() - 1) == ENTER_DESKTOP) {\n\t\t\t\tcursorLine = line;\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Scroll the text area to show the line of the cursor * */\n\tvoid showCursor () {\n\t\tupdateCurrentLine();\n\t\tif (cursorLine != firstLineShowing) {\n\t\t\tint step = cursorLine >= firstLineShowing ? 1 : -1;\n\t\t\twhile (firstLineShowing > cursorLine || firstLineShowing + linesShowing - 1 < cursorLine) {\n\t\t\t\tfirstLineShowing += step;\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Calculates the text area line for the given cursor position * */\n\tprivate int calculateCurrentLineIndex (int cursor) {\n\t\tint index = 0;\n\t\twhile (index < linesBreak.size && cursor > linesBreak.items[index]) {\n\t\t\tindex++;\n\t\t}\n\t\treturn index;\n\t}\n\n\t// OVERRIDE from TextField\n\n\t@Override\n\tprotected void sizeChanged () {\n\t\tlastText = null; // Cause calculateOffsets to recalculate the line breaks.\n\n\t\t// The number of lines showed must be updated whenever the height is updated\n\t\tBitmapFont font = style.font;\n\t\tDrawable background = style.background;\n\t\tfloat availableHeight = getHeight() - (background == null ? 0 : background.getBottomHeight() + background.getTopHeight());\n\t\tlinesShowing = (int) Math.floor(availableHeight / font.getLineHeight());\n\t}\n\n\t@Override\n\tprotected float getTextY (BitmapFont font, Drawable background) {\n\t\tfloat textY = getHeight();\n\t\tif (background != null) {\n\t\t\ttextY = (int) (textY - background.getTopHeight());\n\t\t}\n\t\treturn textY;\n\t}\n\n\t@Override\n\tprotected void drawSelection (Drawable selection, Batch batch, BitmapFont font, float x, float y) {\n\t\tint i = firstLineShowing * 2;\n\t\tfloat offsetY = 0;\n\t\tint minIndex = Math.min(cursor, selectionStart);\n\t\tint maxIndex = Math.max(cursor, selectionStart);\n\t\twhile (i + 1 < linesBreak.size && i < (firstLineShowing + linesShowing) * 2) {\n\n\t\t\tint lineStart = linesBreak.get(i);\n\t\t\tint lineEnd = linesBreak.get(i + 1);\n\n\t\t\tif (!((minIndex < lineStart && minIndex < lineEnd && maxIndex < lineStart && maxIndex < lineEnd)\n\t\t\t\t\t|| (minIndex > lineStart && minIndex > lineEnd && maxIndex > lineStart && maxIndex > lineEnd))) {\n\n\t\t\t\tint start = Math.max(linesBreak.get(i), minIndex);\n\t\t\t\tint end = Math.min(linesBreak.get(i + 1), maxIndex);\n\n\t\t\t\tfloat selectionX = glyphPositions.get(start) - glyphPositions.get(linesBreak.get(i));\n\t\t\t\tfloat selectionWidth = glyphPositions.get(end) - glyphPositions.get(start);\n\n\t\t\t\tselection.draw(batch, x + selectionX + fontOffset, y - textHeight - font.getDescent() - offsetY, selectionWidth,\n\t\t\t\t\t\tfont.getLineHeight());\n\t\t\t}\n\n\t\t\toffsetY += font.getLineHeight();\n\t\t\ti += 2;\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawText (Batch batch, BitmapFont font, float x, float y) {\n\t\tfloat offsetY = 0;\n\t\tfor (int i = firstLineShowing * 2; i < (firstLineShowing + linesShowing) * 2 && i < linesBreak.size; i += 2) {\n\t\t\tfont.draw(batch, displayText, x, y + offsetY, linesBreak.items[i], linesBreak.items[i + 1], 0, Align.left, false);\n\t\t\toffsetY -= font.getLineHeight();\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawCursor (Drawable cursorPatch, Batch batch, BitmapFont font, float x, float y) {\n\t\tfloat textOffset = cursor >= glyphPositions.size || cursorLine * 2 >= linesBreak.size ? 0\n\t\t\t\t: glyphPositions.get(cursor) - glyphPositions.get(linesBreak.items[cursorLine * 2]);\n\t\tcursorX = textOffset + fontOffset + font.getData().cursorX;\n\t\tcursorPatch.draw(batch, x + cursorX,\n\t\t\t\ty - font.getDescent() / 2 - (cursorLine - firstLineShowing + 1) * font.getLineHeight(), cursorPatch.getMinWidth(),\n\t\t\t\tfont.getLineHeight());\n\t}\n\n\t@Override\n\tprotected void calculateOffsets () {\n\t\tsuper.calculateOffsets();\n\t\tif (!this.text.equals(lastText)) {\n\t\t\tthis.lastText = text;\n\t\t\tBitmapFont font = style.font;\n\t\t\tfloat maxWidthLine = this.getWidth()\n\t\t\t\t\t- (style.background != null ? style.background.getLeftWidth() + style.background.getRightWidth() : 0);\n\t\t\tlinesBreak.clear();\n\t\t\tint lineStart = 0;\n\t\t\tint lastSpace = 0;\n\t\t\tchar lastCharacter;\n\t\t\tPool<GlyphLayout> layoutPool = Pools.get(GlyphLayout.class);\n\t\t\tGlyphLayout layout = layoutPool.obtain();\n\t\t\tfor (int i = 0; i < text.length(); i++) {\n\t\t\t\tlastCharacter = text.charAt(i);\n\t\t\t\tif (lastCharacter == ENTER_DESKTOP || lastCharacter == ENTER_ANDROID) {\n\t\t\t\t\tlinesBreak.add(lineStart);\n\t\t\t\t\tlinesBreak.add(i);\n\t\t\t\t\tlineStart = i + 1;\n\t\t\t\t} else {\n\t\t\t\t\tlastSpace = (continueCursor(i, 0) ? lastSpace : i);\n\t\t\t\t\tlayout.setText(font, text.subSequence(lineStart, i + 1));\n\t\t\t\t\tif (layout.width > maxWidthLine && softwrap) {\n\t\t\t\t\t\tif (lineStart >= lastSpace) {\n\t\t\t\t\t\t\tlastSpace = i - 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlinesBreak.add(lineStart);\n\t\t\t\t\t\tlinesBreak.add(lastSpace + 1);\n\t\t\t\t\t\tlineStart = lastSpace + 1;\n\t\t\t\t\t\tlastSpace = lineStart;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tlayoutPool.free(layout);\n\t\t\t// Add last line\n\t\t\tif (lineStart < text.length()) {\n\t\t\t\tlinesBreak.add(lineStart);\n\t\t\t\tlinesBreak.add(text.length());\n\t\t\t}\n\t\t\tshowCursor();\n\t\t}\n\t}\n\n\t@Override\n\tprotected InputListener createInputListener () {\n\t\treturn new TextAreaListener();\n\t}\n\n\t@Override\n\tpublic void setSelection (int selectionStart, int selectionEnd) {\n\t\tsuper.setSelection(selectionStart, selectionEnd);\n\t\tupdateCurrentLine();\n\t}\n\n\t@Override\n\tprotected void moveCursor (boolean forward, boolean jump) {\n\t\tint count = forward ? 1 : -1;\n\t\tint index = (cursorLine * 2) + count;\n\t\tif (index >= 0 && index + 1 < linesBreak.size && linesBreak.items[index] == cursor\n\t\t\t\t&& linesBreak.items[index + 1] == cursor) {\n\t\t\tcursorLine += count;\n\t\t\tif (jump) {\n\t\t\t\tsuper.moveCursor(forward, jump);\n\t\t\t}\n\t\t\tshowCursor();\n\t\t} else {\n\t\t\tsuper.moveCursor(forward, jump);\n\t\t}\n\t\tupdateCurrentLine();\n\t}\n\n\t@Override\n\tprotected boolean continueCursor (int index, int offset) {\n\t\tint pos = calculateCurrentLineIndex(index + offset);\n\t\treturn super.continueCursor(index, offset) && (pos < 0 || pos >= linesBreak.size - 2 || (linesBreak.items[pos + 1] != index)\n\t\t\t\t|| (linesBreak.items[pos + 1] == linesBreak.items[pos + 2]));\n\t}\n\n\tpublic int getCursorLine () {\n\t\treturn cursorLine;\n\t}\n\n\tpublic int getFirstLineShowing () {\n\t\treturn firstLineShowing;\n\t}\n\n\tpublic int getLinesShowing () {\n\t\treturn linesShowing;\n\t}\n\n\tpublic float getCursorX () {\n\t\treturn cursorX;\n\t}\n\n\tpublic float getCursorY () {\n\t\tBitmapFont font = style.font;\n\t\treturn -(-font.getDescent() / 2 - (cursorLine - firstLineShowing + 1) * font.getLineHeight());\n\t}\n\n\t/** Input listener for the text area **/\n\tpublic class TextAreaListener extends TextFieldClickListener {\n\n\t\t@Override\n\t\tprotected void setCursorPosition (float x, float y) {\n\t\t\tmoveOffset = -1;\n\n\t\t\tDrawable background = style.background;\n\t\t\tBitmapFont font = style.font;\n\n\t\t\tfloat height = getHeight();\n\n\t\t\tif (background != null) {\n\t\t\t\theight -= background.getTopHeight();\n\t\t\t\tx -= background.getLeftWidth();\n\t\t\t}\n\t\t\tx = Math.max(0, x);\n\t\t\tif (background != null) {\n\t\t\t\ty -= background.getTopHeight();\n\t\t\t}\n\n\t\t\tcursorLine = (int) Math.floor((height - y) / font.getLineHeight()) + firstLineShowing;\n\t\t\tcursorLine = Math.max(0, Math.min(cursorLine, getLines() - 1));\n\n\t\t\tsuper.setCursorPosition(x, y);\n\t\t\tupdateCurrentLine();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\tboolean result = super.keyDown(event, keycode);\n\t\t\tStage stage = getStage();\n\t\t\tif (stage != null && stage.getKeyboardFocus() == VisTextArea.this) {\n\t\t\t\tboolean repeat = false;\n\t\t\t\tboolean shift = UIUtils.shift();\n\t\t\t\tif (keycode == Input.Keys.DOWN) {\n\t\t\t\t\tif (shift) {\n\t\t\t\t\t\tif (!hasSelection) {\n\t\t\t\t\t\t\tselectionStart = cursor;\n\t\t\t\t\t\t\thasSelection = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclearSelection();\n\t\t\t\t\t}\n\t\t\t\t\tmoveCursorLine(cursorLine + 1);\n\t\t\t\t\trepeat = true;\n\n\t\t\t\t} else if (keycode == Input.Keys.UP) {\n\t\t\t\t\tif (shift) {\n\t\t\t\t\t\tif (!hasSelection) {\n\t\t\t\t\t\t\tselectionStart = cursor;\n\t\t\t\t\t\t\thasSelection = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclearSelection();\n\t\t\t\t\t}\n\t\t\t\t\tmoveCursorLine(cursorLine - 1);\n\t\t\t\t\trepeat = true;\n\n\t\t\t\t} else {\n\t\t\t\t\tmoveOffset = -1;\n\t\t\t\t}\n\t\t\t\tif (repeat) {\n\t\t\t\t\tscheduleKeyRepeatTask(keycode);\n\t\t\t\t}\n\t\t\t\tshowCursor();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean keyTyped (InputEvent event, char character) {\n\t\t\tboolean result = super.keyTyped(event, character);\n\t\t\tshowCursor();\n\t\t\treturn result;\n\t\t}\n\n\t\t@Override\n\t\tprotected void goHome (boolean jump) {\n\t\t\tif (jump) {\n\t\t\t\tcursor = 0;\n\t\t\t} else if (cursorLine * 2 < linesBreak.size) {\n\t\t\t\tcursor = linesBreak.get(cursorLine * 2);\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tprotected void goEnd (boolean jump) {\n\t\t\tif (jump || cursorLine >= getLines()) {\n\t\t\t\tcursor = text.length();\n\t\t\t} else if (cursorLine * 2 + 1 < linesBreak.size) {\n\t\t\t\tcursor = linesBreak.get(cursorLine * 2 + 1);\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisTextButton.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.graphics.g2d.BitmapFont;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.ui.TextButton;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.kotcrab.vis.ui.FocusManager;\nimport com.kotcrab.vis.ui.Focusable;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.BorderOwner;\n\n/**\n * Extends functionality of standard {@link TextButton}, supports focus border. Compatible with standard {@link TextButton}.\n * <p>\n * When listening for button press {@link ChangeListener} should be always preferred (instead of {@link ClickListener}).\n * {@link ClickListener} does not support disabling button and will still report button presses.\n * @author Kotcrab\n * @see TextButton\n */\npublic class VisTextButton extends TextButton implements Focusable, BorderOwner {\n\tprivate VisTextButtonStyle style;\n\n\tprivate boolean drawBorder;\n\tprivate boolean focusBorderEnabled = true;\n\n\tpublic VisTextButton (String text, String styleName) {\n\t\tsuper(text, VisUI.getSkin().get(styleName, VisTextButtonStyle.class));\n\t\tinit();\n\t}\n\n\tpublic VisTextButton (String text) {\n\t\tsuper(text, VisUI.getSkin().get(VisTextButtonStyle.class));\n\t\tinit();\n\t}\n\n\tpublic VisTextButton (String text, ChangeListener listener) {\n\t\tsuper(text, VisUI.getSkin().get(VisTextButtonStyle.class));\n\t\tinit();\n\t\taddListener(listener);\n\t}\n\n\tpublic VisTextButton (String text, String styleName, ChangeListener listener) {\n\t\tsuper(text, VisUI.getSkin().get(styleName, VisTextButtonStyle.class));\n\t\tinit();\n\t\taddListener(listener);\n\t}\n\n\tpublic VisTextButton (String text, VisTextButtonStyle buttonStyle) {\n\t\tsuper(text, buttonStyle);\n\t\tinit();\n\t}\n\n\tprivate void init () {\n\t\tstyle = (VisTextButtonStyle) getStyle();\n\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tif (isDisabled() == false) FocusManager.switchFocus(getStage(), VisTextButton.this);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tsuper.draw(batch, parentAlpha);\n\t\tif (focusBorderEnabled && drawBorder && style.focusBorder != null) {\n\t\t\tstyle.focusBorder.draw(batch, getX(), getY(), getWidth(), getHeight());\n\t\t}\n\t}\n\n\tstatic public class VisTextButtonStyle extends TextButtonStyle {\n\t\tpublic Drawable focusBorder;\n\n\t\tpublic VisTextButtonStyle () {\n\t\t\tsuper();\n\t\t}\n\n\t\tpublic VisTextButtonStyle (Drawable up, Drawable down, Drawable checked, BitmapFont font) {\n\t\t\tsuper(up, down, checked, font);\n\t\t}\n\n\t\tpublic VisTextButtonStyle (VisTextButtonStyle style) {\n\t\t\tsuper(style);\n\t\t\tthis.focusBorder = style.focusBorder;\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isFocusBorderEnabled () {\n\t\treturn focusBorderEnabled;\n\t}\n\n\t@Override\n\tpublic void setFocusBorderEnabled (boolean focusBorderEnabled) {\n\t\tthis.focusBorderEnabled = focusBorderEnabled;\n\t}\n\n\t@Override\n\tpublic void focusLost () {\n\t\tdrawBorder = false;\n\t}\n\n\t@Override\n\tpublic void focusGained () {\n\t\tdrawBorder = true;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisTextField.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.Input.Keys;\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.graphics.Cursor.SystemCursor;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.graphics.g2d.BitmapFont;\nimport com.badlogic.gdx.graphics.g2d.BitmapFont.BitmapFontData;\nimport com.badlogic.gdx.graphics.g2d.GlyphLayout;\nimport com.badlogic.gdx.graphics.g2d.GlyphLayout.GlyphRun;\nimport com.badlogic.gdx.math.MathUtils;\nimport com.badlogic.gdx.math.Vector2;\nimport com.badlogic.gdx.scenes.scene2d.*;\nimport com.badlogic.gdx.scenes.scene2d.ui.TextField;\nimport com.badlogic.gdx.scenes.scene2d.ui.TextField.DefaultOnscreenKeyboard;\nimport com.badlogic.gdx.scenes.scene2d.ui.TextField.OnscreenKeyboard;\nimport com.badlogic.gdx.scenes.scene2d.ui.TextField.TextFieldStyle;\nimport com.badlogic.gdx.scenes.scene2d.ui.Widget;\nimport com.badlogic.gdx.scenes.scene2d.ui.Window;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.ChangeEvent;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Disableable;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.scenes.scene2d.utils.UIUtils;\nimport com.badlogic.gdx.utils.*;\nimport com.badlogic.gdx.utils.Timer.Task;\nimport com.kotcrab.vis.ui.FocusManager;\nimport com.kotcrab.vis.ui.Focusable;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.BorderOwner;\nimport com.kotcrab.vis.ui.util.CursorManager;\n\nimport java.lang.StringBuilder;\n\n/**\n * Extends functionality of standard {@link TextField}. Style supports over, and focus border. Improved text input.\n * Due to scope of changes made this widget is not compatible with {@link TextField}.\n * @author mzechner\n * @author Nathan Sweet\n * @author Kotcrab\n * @see TextField\n */\npublic class VisTextField extends Widget implements Disableable, Focusable, BorderOwner {\n\tstatic private final char BACKSPACE = 8;\n\tstatic protected final char ENTER_DESKTOP = '\\r';\n\tstatic protected final char ENTER_ANDROID = '\\n';\n\tstatic private final char TAB = '\\t';\n\tstatic private final char DELETE = 127;\n\tstatic private final char BULLET = 8226;\n\n\tstatic private final Vector2 tmp1 = new Vector2();\n\tstatic private final Vector2 tmp2 = new Vector2();\n\tstatic private final Vector2 tmp3 = new Vector2();\n\n\tstatic public float keyRepeatInitialTime = 0.4f;\n\t/** Repeat times for keys handled by {@link InputListener#keyDown(InputEvent, int)} such as navigation arrows */\n\tstatic public float keyRepeatTime = 0.04f;\n\n\tprotected String text;\n\tprotected int cursor, selectionStart;\n\tprotected boolean hasSelection;\n\tprotected boolean writeEnters;\n\tprotected final GlyphLayout layout = new GlyphLayout();\n\tprotected final FloatArray glyphPositions = new FloatArray();\n\n\tprivate String messageText;\n\tprotected CharSequence displayText;\n\tClipboard clipboard;\n\tInputListener inputListener;\n\tTextFieldListener listener;\n\tTextFieldFilter filter;\n\tOnscreenKeyboard keyboard = new DefaultOnscreenKeyboard();\n\tboolean focusTraversal = true, onlyFontChars = true, disabled;\n\tboolean enterKeyFocusTraversal = false;\n\tprivate int textHAlign = Align.left;\n\tprivate float selectionX, selectionWidth;\n\n\tString undoText = \"\";\n\tint undoCursorPos = 0;\n\tlong lastChangeTime;\n\n\tboolean passwordMode;\n\tprivate StringBuilder passwordBuffer;\n\tprivate char passwordCharacter = BULLET;\n\n\tprotected float fontOffset, textHeight, textOffset;\n\tfloat renderOffset;\n\tprivate int visibleTextStart, visibleTextEnd;\n\tprivate int maxLength = 0;\n\n\tprivate float blinkTime = 0.45f;\n\tboolean cursorOn = true;\n\tlong lastBlink;\n\n\tKeyRepeatTask keyRepeatTask = new KeyRepeatTask();\n\tboolean programmaticChangeEvents;\n\n\t// vis fields\n\tVisTextFieldStyle style;\n\tprivate ClickListener clickListener;\n\tprivate boolean drawBorder;\n\tprivate boolean focusBorderEnabled = true;\n\tprivate boolean inputValid = true;\n\tprivate boolean ignoreEqualsTextChange = true;\n\tprivate boolean readOnly = false;\n\tprivate float cursorPercentHeight = 0.8f;\n\n\tpublic VisTextField () {\n\t\tthis(\"\", VisUI.getSkin().get(VisTextFieldStyle.class));\n\t}\n\n\tpublic VisTextField (String text) {\n\t\tthis(text, VisUI.getSkin().get(VisTextFieldStyle.class));\n\t}\n\n\tpublic VisTextField (String text, String styleName) {\n\t\tthis(text, VisUI.getSkin().get(styleName, VisTextFieldStyle.class));\n\t}\n\n\tpublic VisTextField (String text, VisTextFieldStyle style) {\n\t\tsetStyle(style);\n\t\tclipboard = Gdx.app.getClipboard();\n\t\tinitialize();\n\t\tsetText(text);\n\t\tsetSize(getPrefWidth(), getPrefHeight());\n\t}\n\n\tprotected void initialize () {\n\t\taddListener(inputListener = createInputListener());\n\t\taddListener(clickListener = new ClickListener() {\n\t\t\t@Override\n\t\t\tpublic void enter (InputEvent event, float x, float y, int pointer, Actor fromActor) {\n\t\t\t\tsuper.enter(event, x, y, pointer, fromActor);\n\t\t\t\tif (pointer == -1 && isDisabled() == false) {\n\t\t\t\t\tGdx.graphics.setSystemCursor(SystemCursor.Ibeam);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void exit (InputEvent event, float x, float y, int pointer, Actor toActor) {\n\t\t\t\tsuper.exit(event, x, y, pointer, toActor);\n\t\t\t\tif (pointer == -1) {\n\t\t\t\t\tCursorManager.restoreDefaultCursor();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tprotected InputListener createInputListener () {\n\t\treturn new TextFieldClickListener();\n\t}\n\n\tprotected int letterUnderCursor (float x) {\n\t\tx -= textOffset + fontOffset - style.font.getData().cursorX - glyphPositions.get(visibleTextStart);\n\t\tint n = this.glyphPositions.size;\n\t\tfloat[] glyphPositions = this.glyphPositions.items;\n\t\tfor (int i = 1; i < n; i++) {\n\t\t\tif (glyphPositions[i] > x) {\n\t\t\t\tif (glyphPositions[i] - x <= x - glyphPositions[i - 1]) return i;\n\t\t\t\treturn i - 1;\n\t\t\t}\n\t\t}\n\t\treturn n - 1;\n\t}\n\n\tprotected boolean isWordCharacter (char c) {\n\t\treturn Character.isLetterOrDigit(c);\n\t}\n\n\tprotected int[] wordUnderCursor (int at) {\n\t\tString text = this.text;\n\t\tint start = Math.min(text.length(), at), right = text.length(), left = 0, index = start;\n\t\tfor (; index < right; index++) {\n\t\t\tif (!isWordCharacter(text.charAt(index))) {\n\t\t\t\tright = index;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor (index = start - 1; index > -1; index--) {\n\t\t\tif (!isWordCharacter(text.charAt(index))) {\n\t\t\t\tleft = index + 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn new int[]{left, right};\n\t}\n\n\tint[] wordUnderCursor (float x) {\n\t\treturn wordUnderCursor(letterUnderCursor(x));\n\t}\n\n\tboolean withinMaxLength (int size) {\n\t\treturn maxLength <= 0 || size < maxLength;\n\t}\n\n\tpublic int getMaxLength () {\n\t\treturn this.maxLength;\n\t}\n\n\tpublic void setMaxLength (int maxLength) {\n\t\tthis.maxLength = maxLength;\n\t}\n\n\t/**\n\t * When false, text set by {@link #setText(String)} may contain characters not in the font, a space will be displayed instead.\n\t * When true (the default), characters not in the font are stripped by setText. Characters not in the font are always stripped\n\t * when typed or pasted.\n\t */\n\tpublic void setOnlyFontChars (boolean onlyFontChars) {\n\t\tthis.onlyFontChars = onlyFontChars;\n\t}\n\n\t/**\n\t * Returns the text field's style. Modifying the returned style may not have an effect until\n\t * {@link #setStyle(VisTextFieldStyle)} is called.\n\t */\n\tpublic VisTextFieldStyle getStyle () {\n\t\treturn style;\n\t}\n\n\tpublic void setStyle (VisTextFieldStyle style) {\n\t\tif (style == null) throw new IllegalArgumentException(\"style cannot be null.\");\n\t\tthis.style = style;\n\t\ttextHeight = style.font.getCapHeight() - style.font.getDescent() * 2;\n\t\tinvalidateHierarchy();\n\t}\n\n\t@Override\n\tpublic String toString () {\n\t\treturn getText();\n\t}\n\n\tprotected void calculateOffsets () {\n\t\tfloat visibleWidth = getWidth();\n\t\tif (style.background != null)\n\t\t\tvisibleWidth -= style.background.getLeftWidth() + style.background.getRightWidth();\n\n\t\tint glyphCount = glyphPositions.size;\n\t\tfloat[] glyphPositions = this.glyphPositions.items;\n\n\t\t// Check if the cursor has gone out the left or right side of the visible area and adjust renderOffset.\n\t\tfloat distance = glyphPositions[Math.max(0, cursor - 1)] + renderOffset;\n\t\tif (distance <= 0)\n\t\t\trenderOffset -= distance;\n\t\telse {\n\t\t\tint index = Math.min(glyphCount - 1, cursor + 1);\n\t\t\tfloat minX = glyphPositions[index] - visibleWidth;\n\t\t\tif (-renderOffset < minX) renderOffset = -minX;\n\t\t}\n\n\t\t// Prevent renderOffset from starting too close to the end, eg after text was deleted.\n\t\tfloat maxOffset = 0;\n\t\tfloat width = glyphPositions[glyphCount - 1];\n\t\tfor (int i = glyphCount - 2; i >= 0; i--) {\n\t\t\tfloat x = glyphPositions[i];\n\t\t\tif (width - x > visibleWidth) break;\n\t\t\tmaxOffset = x;\n\t\t}\n\t\tif (-renderOffset > maxOffset) renderOffset = -maxOffset;\n\n\t\t// calculate first visible char based on render offset\n\t\tvisibleTextStart = 0;\n\t\tfloat startX = 0;\n\t\tfor (int i = 0; i < glyphCount; i++) {\n\t\t\tif (glyphPositions[i] >= -renderOffset) {\n\t\t\t\tvisibleTextStart = Math.max(0, i);\n\t\t\t\tstartX = glyphPositions[i];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// calculate last visible char based on visible width and render offset\n\t\tint length = Math.min(displayText.length(), glyphPositions.length - 1);\n\t\tvisibleTextEnd = Math.min(length, cursor + 1);\n\t\tfor (; visibleTextEnd <= length; visibleTextEnd++)\n\t\t\tif (glyphPositions[visibleTextEnd] > startX + visibleWidth) break;\n\t\tvisibleTextEnd = Math.max(0, visibleTextEnd - 1);\n\n\t\tif ((textHAlign & Align.left) == 0) {\n\t\t\ttextOffset = visibleWidth - (glyphPositions[visibleTextEnd] - startX);\n\t\t\tif ((textHAlign & Align.center) != 0) textOffset = Math.round(textOffset * 0.5f);\n\t\t} else\n\t\t\ttextOffset = startX + renderOffset;\n\n\t\t// calculate selection x position and width\n\t\tif (hasSelection) {\n\t\t\tint minIndex = Math.min(cursor, selectionStart);\n\t\t\tint maxIndex = Math.max(cursor, selectionStart);\n\t\t\tfloat minX = Math.max(glyphPositions[minIndex] - glyphPositions[visibleTextStart], -textOffset);\n\t\t\tfloat maxX = Math.min(glyphPositions[maxIndex] - glyphPositions[visibleTextStart], visibleWidth - textOffset);\n\t\t\tselectionX = minX;\n\t\t\tselectionWidth = maxX - minX - style.font.getData().cursorX;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tStage stage = getStage();\n\t\tboolean focused = stage != null && stage.getKeyboardFocus() == this;\n\t\tif (!focused) keyRepeatTask.cancel();\n\n\t\tfinal BitmapFont font = style.font;\n\t\tfinal Color fontColor = (disabled && style.disabledFontColor != null) ? style.disabledFontColor\n\t\t\t\t: ((focused && style.focusedFontColor != null) ? style.focusedFontColor : style.fontColor);\n\t\tfinal Drawable selection = style.selection;\n\t\tfinal Drawable cursorPatch = style.cursor;\n\t\tDrawable background = (disabled && style.disabledBackground != null) ? style.disabledBackground\n\t\t\t\t: ((focused && style.focusedBackground != null) ? style.focusedBackground : style.background);\n\n\t\t// vis\n\t\tif (!disabled && style.backgroundOver != null && (clickListener.isOver() || focused)) {\n\t\t\tbackground = style.backgroundOver;\n\t\t}\n\n\t\tColor color = getColor();\n\t\tfloat x = getX();\n\t\tfloat y = getY();\n\t\tfloat width = getWidth();\n\t\tfloat height = getHeight();\n\n\t\tbatch.setColor(color.r, color.g, color.b, color.a * parentAlpha);\n\t\tfloat bgLeftWidth = 0, bgRightWidth = 0;\n\t\tif (background != null) {\n\t\t\tbackground.draw(batch, x, y, width, height);\n\t\t\tbgLeftWidth = background.getLeftWidth();\n\t\t\tbgRightWidth = background.getRightWidth();\n\t\t}\n\n\t\tfloat textY = getTextY(font, background);\n\t\tcalculateOffsets();\n\n\t\tif (focused && hasSelection && selection != null) {\n\t\t\tdrawSelection(selection, batch, font, x + bgLeftWidth, y + textY);\n\t\t}\n\n\t\tfloat yOffset = font.isFlipped() ? -textHeight : 0;\n\t\tif (displayText.length() == 0) {\n\t\t\tif (!focused && messageText != null) {\n\t\t\t\tif (style.messageFontColor != null) {\n\t\t\t\t\tfont.setColor(style.messageFontColor.r, style.messageFontColor.g, style.messageFontColor.b,\n\t\t\t\t\t\t\tstyle.messageFontColor.a * color.a * parentAlpha);\n\t\t\t\t} else\n\t\t\t\t\tfont.setColor(0.7f, 0.7f, 0.7f, color.a * parentAlpha);\n\t\t\t\tBitmapFont messageFont = style.messageFont != null ? style.messageFont : font;\n\t\t\t\tmessageFont.draw(batch, messageText, x + bgLeftWidth, y + textY + yOffset, 0, messageText.length(),\n\t\t\t\t\t\twidth - bgLeftWidth - bgRightWidth, textHAlign, false, \"...\");\n\t\t\t}\n\t\t} else {\n\t\t\tBitmapFontData data = font.getData();\n\t\t\tboolean markupEnabled = data.markupEnabled;\n\t\t\tdata.markupEnabled = false;\n\t\t\tfont.setColor(fontColor.r, fontColor.g, fontColor.b, fontColor.a * color.a * parentAlpha);\n\t\t\tdrawText(batch, font, x + bgLeftWidth, y + textY + yOffset);\n\t\t\tdata.markupEnabled = markupEnabled;\n\t\t}\n\t\tif (drawBorder && focused && !disabled) {\n\t\t\tblink();\n\t\t\tif (cursorOn && cursorPatch != null) {\n\t\t\t\tdrawCursor(cursorPatch, batch, font, x + bgLeftWidth, y + textY);\n\t\t\t}\n\t\t}\n\n\t\t// vis\n\t\tif (isDisabled() == false && inputValid == false && style.errorBorder != null)\n\t\t\tstyle.errorBorder.draw(batch, getX(), getY(), getWidth(), getHeight());\n\t\telse if (focusBorderEnabled && drawBorder && style.focusBorder != null)\n\t\t\tstyle.focusBorder.draw(batch, getX(), getY(), getWidth(), getHeight());\n\n\t}\n\n\tprotected float getTextY (BitmapFont font, Drawable background) {\n\t\tfloat height = getHeight();\n\t\tfloat textY = textHeight / 2 + font.getDescent();\n\t\tif (background != null) {\n\t\t\tfloat bottom = background.getBottomHeight();\n\t\t\ttextY = textY + (height - background.getTopHeight() - bottom) / 2 + bottom;\n\t\t} else {\n\t\t\ttextY = textY + height / 2;\n\t\t}\n\t\tif (font.usesIntegerPositions()) textY = (int) textY;\n\t\treturn textY;\n\t}\n\n\t/** Draws selection rectangle **/\n\tprotected void drawSelection (Drawable selection, Batch batch, BitmapFont font, float x, float y) {\n\t\tselection.draw(batch, x + selectionX + textOffset + fontOffset, y - textHeight - font.getDescent(), selectionWidth,\n\t\t\t\ttextHeight);\n\t}\n\n\tprotected void drawText (Batch batch, BitmapFont font, float x, float y) {\n\t\tfont.draw(batch, displayText, x + textOffset, y, visibleTextStart, visibleTextEnd, 0, Align.left, false);\n\t}\n\n\tprotected void drawCursor (Drawable cursorPatch, Batch batch, BitmapFont font, float x, float y) {\n\t\tfloat cursorHeight = textHeight * cursorPercentHeight;\n\t\tfloat cursorYPadding = (textHeight - cursorHeight) / 2;\n\t\tcursorPatch.draw(batch,\n\t\t\t\tx + textOffset + glyphPositions.get(cursor) - glyphPositions.get(visibleTextStart) + fontOffset + font.getData().cursorX,\n\t\t\t\ty - textHeight - font.getDescent() + cursorYPadding, cursorPatch.getMinWidth(), cursorHeight);\n\t}\n\n\tvoid updateDisplayText () {\n\t\tBitmapFont font = style.font;\n\t\tBitmapFontData data = font.getData();\n\t\tString text = this.text;\n\t\tint textLength = text.length();\n\n\t\tStringBuilder buffer = new StringBuilder();\n\t\tfor (int i = 0; i < textLength; i++) {\n\t\t\tchar c = text.charAt(i);\n\t\t\tbuffer.append(data.hasGlyph(c) ? c : ' ');\n\t\t}\n\t\tString newDisplayText = buffer.toString();\n\n\t\tif (passwordMode && data.hasGlyph(passwordCharacter)) {\n\t\t\tif (passwordBuffer == null) passwordBuffer = new StringBuilder(newDisplayText.length());\n\t\t\tif (passwordBuffer.length() > textLength)\n\t\t\t\tpasswordBuffer.setLength(textLength);\n\t\t\telse {\n\t\t\t\tfor (int i = passwordBuffer.length(); i < textLength; i++)\n\t\t\t\t\tpasswordBuffer.append(passwordCharacter);\n\t\t\t}\n\t\t\tdisplayText = passwordBuffer;\n\t\t} else\n\t\t\tdisplayText = newDisplayText;\n\n\t\tboolean markupEnabled = data.markupEnabled;\n\t\tdata.markupEnabled = false;\n\t\tlayout.setText(font, displayText.toString().replace('\\r', ' ').replace('\\n', ' '));\n\t\tdata.markupEnabled = markupEnabled;\n\n\t\tglyphPositions.clear();\n\t\tfloat x = 0;\n\t\tif (layout.runs.size > 0) {\n\t\t\tGlyphRun run = layout.runs.first();\n\t\t\tfontOffset = run.xAdvances.first();\n\n\t\t\tfor (GlyphRun glyphRun : layout.runs) {\n\t\t\t\tFloatArray xAdvances = glyphRun.xAdvances;\n\t\t\t\tfor (int i = 1, n = xAdvances.size; i < n; i++) {\n\t\t\t\t\tglyphPositions.add(x);\n\t\t\t\t\tx += xAdvances.get(i);\n\t\t\t\t}\n\t\t\t\tglyphPositions.add(x);\n\t\t\t}\n\t\t} else {\n\t\t\tfontOffset = 0;\n\t\t}\n\t\tglyphPositions.add(x);\n\n\t\tvisibleTextStart = Math.min(visibleTextStart, glyphPositions.size);\n\t\tvisibleTextEnd = MathUtils.clamp(visibleTextEnd, visibleTextStart, glyphPositions.size);\n\n\t\tif (selectionStart > newDisplayText.length()) selectionStart = textLength;\n\t}\n\n\tprivate void blink () {\n\t\tif (!Gdx.graphics.isContinuousRendering()) {\n\t\t\tcursorOn = true;\n\t\t\treturn;\n\t\t}\n\t\tlong time = TimeUtils.nanoTime();\n\t\tif ((time - lastBlink) / 1000000000.0f > blinkTime) {\n\t\t\tcursorOn = !cursorOn;\n\t\t\tlastBlink = time;\n\t\t}\n\t}\n\n\t/** Copies the contents of this TextField to the {@link Clipboard} implementation set on this TextField. */\n\tpublic void copy () {\n\t\tif (hasSelection && !passwordMode) {\n\t\t\tint beginIndex = Math.min(cursor, selectionStart);\n\t\t\tint endIndex = Math.max(cursor, selectionStart);\n\t\t\tclipboard.setContents(text.substring(Math.max(0, beginIndex), Math.min(text.length(), endIndex)));\n\t\t}\n\t}\n\n\t/**\n\t * Copies the selected contents of this TextField to the {@link Clipboard} implementation set on this TextField, then removes\n\t * it.\n\t */\n\tpublic void cut () {\n\t\tcut(programmaticChangeEvents);\n\t}\n\n\tvoid cut (boolean fireChangeEvent) {\n\t\tif (hasSelection && !passwordMode) {\n\t\t\tcopy();\n\t\t\tcursor = delete(fireChangeEvent);\n\t\t\tupdateDisplayText();\n\t\t}\n\t}\n\n\tvoid paste (String content, boolean fireChangeEvent) {\n\t\tif (content == null) return;\n\t\tStringBuilder buffer = new StringBuilder();\n\t\tint textLength = text.length();\n\t\tif (hasSelection) textLength -= Math.abs(cursor - selectionStart);\n\t\tBitmapFontData data = style.font.getData();\n\t\tfor (int i = 0, n = content.length(); i < n; i++) {\n\t\t\tif (!withinMaxLength(textLength + buffer.length())) break;\n\t\t\tchar c = content.charAt(i);\n\t\t\tif (!(writeEnters && (c == ENTER_ANDROID || c == ENTER_DESKTOP))) {\n\t\t\t\tif (c == '\\r' || c == '\\n') continue;\n\t\t\t\tif (onlyFontChars && !data.hasGlyph(c)) continue;\n\t\t\t\tif (filter != null && !filter.acceptChar(this, c)) continue;\n\t\t\t}\n\t\t\tbuffer.append(c);\n\t\t}\n\t\tcontent = buffer.toString();\n\n\t\tif (hasSelection) cursor = delete(fireChangeEvent);\n\t\tif (fireChangeEvent)\n\t\t\tchangeText(text, insert(cursor, content, text));\n\t\telse\n\t\t\ttext = insert(cursor, content, text);\n\t\tupdateDisplayText();\n\t\tcursor += content.length();\n\t}\n\n\tString insert (int position, CharSequence text, String to) {\n\t\tif (to.length() == 0) return text.toString();\n\t\treturn to.substring(0, position) + text + to.substring(position, to.length());\n\t}\n\n\tint delete (boolean fireChangeEvent) {\n\t\tint from = selectionStart;\n\t\tint to = cursor;\n\t\tint minIndex = Math.min(from, to);\n\t\tint maxIndex = Math.max(from, to);\n\t\tString newText = (minIndex > 0 ? text.substring(0, minIndex) : \"\")\n\t\t\t\t+ (maxIndex < text.length() ? text.substring(maxIndex, text.length()) : \"\");\n\t\tif (fireChangeEvent)\n\t\t\tchangeText(text, newText);\n\t\telse\n\t\t\ttext = newText;\n\t\tclearSelection();\n\t\treturn minIndex;\n\t}\n\n\t/**\n\t * Focuses the next TextField. If none is found, the keyboard is hidden. Does nothing if the text field is not in a stage.\n\t * @param up If true, the TextField with the same or next smallest y coordinate is found, else the next highest.\n\t */\n\tpublic void next (boolean up) {\n\t\tStage stage = getStage();\n\t\tif (stage == null) return;\n\t\tgetParent().localToStageCoordinates(tmp1.set(getX(), getY()));\n\t\tVisTextField textField = findNextTextField(stage.getActors(), null, tmp2, tmp1, up);\n\t\tif (textField == null) { // Try to wrap around.\n\t\t\tif (up)\n\t\t\t\ttmp1.set(Float.MIN_VALUE, Float.MIN_VALUE);\n\t\t\telse\n\t\t\t\ttmp1.set(Float.MAX_VALUE, Float.MAX_VALUE);\n\t\t\ttextField = findNextTextField(getStage().getActors(), null, tmp2, tmp1, up);\n\t\t}\n\t\tif (textField != null) {\n\t\t\ttextField.focusField();\n\t\t\ttextField.setCursorPosition(textField.getText().length());\n\t\t} else\n\t\t\tkeyboard.show(false);\n\t}\n\n\tprivate VisTextField findNextTextField (Array<Actor> actors, VisTextField best, Vector2 bestCoords, Vector2 currentCoords, boolean up) {\n\t\tWindow modalWindow = findModalWindow(this);\n\n\t\tfor (int i = 0, n = actors.size; i < n; i++) {\n\t\t\tActor actor = actors.get(i);\n\t\t\tif (actor == this) continue;\n\t\t\tif (actor instanceof VisTextField) {\n\t\t\t\tVisTextField textField = (VisTextField) actor;\n\n\t\t\t\tif (modalWindow != null) {\n\t\t\t\t\tWindow nextFieldModalWindow = findModalWindow(textField);\n\t\t\t\t\tif (nextFieldModalWindow != modalWindow) continue;\n\t\t\t\t}\n\n\t\t\t\tif (textField.isDisabled() || !textField.focusTraversal || isActorVisibleInStage(textField) == false)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tVector2 actorCoords = actor.getParent().localToStageCoordinates(tmp3.set(actor.getX(), actor.getY()));\n\t\t\t\tif ((actorCoords.y < currentCoords.y || (actorCoords.y == currentCoords.y && actorCoords.x > currentCoords.x)) ^ up) {\n\t\t\t\t\tif (best == null\n\t\t\t\t\t\t\t|| (actorCoords.y > bestCoords.y || (actorCoords.y == bestCoords.y && actorCoords.x < bestCoords.x)) ^ up) {\n\t\t\t\t\t\tbest = (VisTextField) actor;\n\t\t\t\t\t\tbestCoords.set(actorCoords);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (actor instanceof Group)\n\t\t\t\tbest = findNextTextField(((Group) actor).getChildren(), best, bestCoords, currentCoords, up);\n\t\t}\n\t\treturn best;\n\t}\n\n\t/**\n\t * Checks if actor is visible in stage acknowledging parent visibility.\n\t * If any parent returns false from isVisible then this method return false.\n\t * True is returned when this actor and all its parent are visible.\n\t */\n\tprivate boolean isActorVisibleInStage (Actor actor) {\n\t\tif (actor == null) return true;\n\t\tif (actor.isVisible() == false) return false;\n\t\treturn isActorVisibleInStage(actor.getParent());\n\t}\n\n\tprivate Window findModalWindow (Actor actor) {\n\t\tif (actor == null) return null;\n\t\tif (actor instanceof Window && ((Window) actor).isModal()) return (Window) actor;\n\t\treturn findModalWindow(actor.getParent());\n\t}\n\n\tpublic InputListener getDefaultInputListener () {\n\t\treturn inputListener;\n\t}\n\n\t/** @param listener May be null. */\n\tpublic void setTextFieldListener (TextFieldListener listener) {\n\t\tthis.listener = listener;\n\t}\n\n\t/** @param filter May be null. */\n\tpublic void setTextFieldFilter (TextFieldFilter filter) {\n\t\tthis.filter = filter;\n\t}\n\n\tpublic TextFieldFilter getTextFieldFilter () {\n\t\treturn filter;\n\t}\n\n\t/** If true (the default), tab/shift+tab will move to the next text field. */\n\tpublic void setFocusTraversal (boolean focusTraversal) {\n\t\tthis.focusTraversal = focusTraversal;\n\t}\n\n\t/**\n\t * If true, enter will move to the next text field with has focus traversal enabled.\n\t * False by default. Note that to enable or disable focus traversal completely you must\n\t * use {@link #setFocusTraversal(boolean)}\n\t */\n\tpublic void setEnterKeyFocusTraversal (boolean enterKeyFocusTraversal) {\n\t\tthis.enterKeyFocusTraversal = enterKeyFocusTraversal;\n\t}\n\n\t/** @return May be null. */\n\tpublic String getMessageText () {\n\t\treturn messageText;\n\t}\n\n\t/**\n\t * Sets the text that will be drawn in the text field if no text has been entered.\n\t * @param messageText may be null.\n\t */\n\tpublic void setMessageText (String messageText) {\n\t\tthis.messageText = messageText;\n\t}\n\n\t/** @param str If null, \"\" is used. */\n\tpublic void appendText (String str) {\n\t\tif (str == null) str = \"\";\n\n\t\tclearSelection();\n\t\tcursor = text.length();\n\t\tpaste(str, programmaticChangeEvents);\n\t}\n\n\t/** @param str If null, \"\" is used. */\n\tpublic void setText (String str) {\n\t\tif (str == null) str = \"\";\n\t\tif (ignoreEqualsTextChange && str.equals(text)) return;\n\n\t\tclearSelection();\n\t\tString oldText = text;\n\t\ttext = \"\";\n\t\tpaste(str, false);\n\t\tif (programmaticChangeEvents) changeText(oldText, text);\n\t\tcursor = 0;\n\t}\n\n\t/** @return Never null, might be an empty string. */\n\tpublic String getText () {\n\t\treturn text;\n\t}\n\n\t/**\n\t * @param oldText May be null.\n\t * @return True if the text was changed.\n\t */\n\tboolean changeText (String oldText, String newText) {\n\t\tif (ignoreEqualsTextChange && newText.equals(oldText)) return false;\n\t\ttext = newText;\n\t\tbeforeChangeEventFired();\n\t\tChangeEvent changeEvent = Pools.obtain(ChangeEvent.class);\n\t\tboolean cancelled = fire(changeEvent);\n\t\ttext = cancelled ? oldText : newText;\n\t\tPools.free(changeEvent);\n\t\treturn !cancelled;\n\t}\n\n\tvoid beforeChangeEventFired () {\n\n\t}\n\n\tpublic boolean getProgrammaticChangeEvents () {\n\t\treturn programmaticChangeEvents;\n\t}\n\n\t/**\n\t * If false, methods that change the text will not fire {@link ChangeEvent}, the event will be fired only when user changes\n\t * the text.\n\t */\n\tpublic void setProgrammaticChangeEvents (boolean programmaticChangeEvents) {\n\t\tthis.programmaticChangeEvents = programmaticChangeEvents;\n\t}\n\n\tpublic int getSelectionStart () {\n\t\treturn selectionStart;\n\t}\n\n\tpublic String getSelection () {\n\t\treturn hasSelection ? text.substring(Math.min(selectionStart, cursor), Math.max(selectionStart, cursor)) : \"\";\n\t}\n\n\tpublic boolean isTextSelected () {\n\t\treturn hasSelection;\n\t}\n\n\t/** Sets the selected text. */\n\tpublic void setSelection (int selectionStart, int selectionEnd) {\n\t\tif (selectionStart < 0) throw new IllegalArgumentException(\"selectionStart must be >= 0\");\n\t\tif (selectionEnd < 0) throw new IllegalArgumentException(\"selectionEnd must be >= 0\");\n\t\tselectionStart = Math.min(text.length(), selectionStart);\n\t\tselectionEnd = Math.min(text.length(), selectionEnd);\n\t\tif (selectionEnd == selectionStart) {\n\t\t\tclearSelection();\n\t\t\treturn;\n\t\t}\n\t\tif (selectionEnd < selectionStart) {\n\t\t\tint temp = selectionEnd;\n\t\t\tselectionEnd = selectionStart;\n\t\t\tselectionStart = temp;\n\t\t}\n\n\t\thasSelection = true;\n\t\tthis.selectionStart = selectionStart;\n\t\tcursor = selectionEnd;\n\t}\n\n\tpublic void selectAll () {\n\t\tsetSelection(0, text.length());\n\t}\n\n\tpublic void clearSelection () {\n\t\thasSelection = false;\n\t}\n\n\t/** Clears VisTextField text. If programmatic change events are disabled then this will not fire change event. */\n\tpublic void clearText () {\n\t\tsetText(\"\");\n\t}\n\n\t/** Sets the cursor position and clears any selection. */\n\tpublic void setCursorPosition (int cursorPosition) {\n\t\tif (cursorPosition < 0) throw new IllegalArgumentException(\"cursorPosition must be >= 0\");\n\t\tclearSelection();\n\t\tcursor = Math.min(cursorPosition, text.length());\n\t}\n\n\tpublic int getCursorPosition () {\n\t\treturn cursor;\n\t}\n\n\tpublic void setCursorAtTextEnd () {\n\t\tsetCursorPosition(0);\n\t\tcalculateOffsets();\n\t\tsetCursorPosition(getText().length());\n\t}\n\n\t/** @param cursorPercentHeight cursor size, value from 0..1 range */\n\tpublic void setCursorPercentHeight (float cursorPercentHeight) {\n\t\tif (cursorPercentHeight < 0 || cursorPercentHeight > 1)\n\t\t\tthrow new IllegalArgumentException(\"cursorPercentHeight must be >= 0 and <= 1\");\n\t\tthis.cursorPercentHeight = cursorPercentHeight;\n\t}\n\n\t/** Default is an instance of {@link DefaultOnscreenKeyboard}. */\n\tpublic OnscreenKeyboard getOnscreenKeyboard () {\n\t\treturn keyboard;\n\t}\n\n\tpublic void setOnscreenKeyboard (OnscreenKeyboard keyboard) {\n\t\tthis.keyboard = keyboard;\n\t}\n\n\tpublic void setClipboard (Clipboard clipboard) {\n\t\tthis.clipboard = clipboard;\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\treturn 150;\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\tfloat prefHeight = textHeight;\n\t\tif (style.background != null) {\n\t\t\tprefHeight = Math.max(prefHeight + style.background.getBottomHeight() + style.background.getTopHeight(),\n\t\t\t\t\tstyle.background.getMinHeight());\n\t\t}\n\t\treturn prefHeight;\n\t}\n\n\t/**\n\t * Sets text horizontal alignment (left, center or right).\n\t * @see Align\n\t */\n\tpublic void setAlignment (int alignment) {\n\t\tthis.textHAlign = alignment;\n\t}\n\n\t/**\n\t * If true, the text in this text field will be shown as bullet characters.\n\t * @see #setPasswordCharacter(char)\n\t */\n\tpublic void setPasswordMode (boolean passwordMode) {\n\t\tthis.passwordMode = passwordMode;\n\t\tupdateDisplayText();\n\t}\n\n\tpublic boolean isPasswordMode () {\n\t\treturn passwordMode;\n\t}\n\n\t/**\n\t * Sets the password character for the text field. The character must be present in the {@link BitmapFont}. Default is 149\n\t * (bullet).\n\t */\n\tpublic void setPasswordCharacter (char passwordCharacter) {\n\t\tthis.passwordCharacter = passwordCharacter;\n\t\tif (passwordMode) updateDisplayText();\n\t}\n\n\tpublic void setBlinkTime (float blinkTime) {\n\t\tthis.blinkTime = blinkTime;\n\t}\n\n\tpublic boolean isDisabled () {\n\t\treturn disabled;\n\t}\n\n\t@Override\n\tpublic void setDisabled (boolean disabled) {\n\t\tthis.disabled = disabled;\n\t\tif (disabled) {\n\t\t\tFocusManager.resetFocus(getStage(), this);\n\t\t\tkeyRepeatTask.cancel();\n\t\t}\n\t}\n\n\tpublic boolean isReadOnly () {\n\t\treturn readOnly;\n\t}\n\n\tpublic void setReadOnly (boolean readOnly) {\n\t\tthis.readOnly = readOnly;\n\t}\n\n\tprotected void moveCursor (boolean forward, boolean jump) {\n\t\tint limit = forward ? text.length() : 0;\n\t\tint charOffset = forward ? 0 : -1;\n\t\twhile ((forward ? ++cursor < limit : --cursor > limit) && jump) {\n\t\t\tif (!continueCursor(cursor, charOffset)) break;\n\t\t}\n\t}\n\n\tprotected boolean continueCursor (int index, int offset) {\n\t\tchar c = text.charAt(index + offset);\n\t\treturn isWordCharacter(c);\n\t}\n\n\t/** Focuses this field, field must be added to stage before this method can be called */\n\tpublic void focusField () {\n\t\tif (disabled) return;\n\t\tStage stage = getStage();\n\t\tFocusManager.switchFocus(stage, VisTextField.this);\n\t\tsetCursorPosition(0);\n\t\tselectionStart = 0;\n\t\t//make sure textOffset was updated, prevent issue when there was long text selected and it was changed to short text\n\t\t//and field was focused. Without it textOffset would stay at max value and only one last letter will be visible in field\n\t\tcalculateOffsets();\n\t\tif (stage != null) stage.setKeyboardFocus(VisTextField.this);\n\t\tkeyboard.show(true);\n\t\thasSelection = true;\n\t}\n\n\t@Override\n\tpublic void focusLost () {\n\t\tdrawBorder = false;\n\t}\n\n\t@Override\n\tpublic void focusGained () {\n\t\tdrawBorder = true;\n\t}\n\n\tpublic boolean isEmpty () {\n\t\treturn text.length() == 0;\n\t}\n\n\tpublic boolean isInputValid () {\n\t\treturn inputValid;\n\t}\n\n\tpublic void setInputValid (boolean inputValid) {\n\t\tthis.inputValid = inputValid;\n\t}\n\n\t@Override\n\tpublic boolean isFocusBorderEnabled () {\n\t\treturn focusBorderEnabled;\n\t}\n\n\t@Override\n\tpublic void setFocusBorderEnabled (boolean focusBorderEnabled) {\n\t\tthis.focusBorderEnabled = focusBorderEnabled;\n\t}\n\n\t/** @see #setIgnoreEqualsTextChange(boolean) */\n\tpublic boolean isIgnoreEqualsTextChange () {\n\t\treturn ignoreEqualsTextChange;\n\t}\n\n\t/**\n\t * Allows to control whether change event is sent when text field's text is changed to same same as was it before.\n\t * Eg. current text field is 'abc' and {@link #setText(String)} is called it with 'abc' again.\n\t * @param ignoreEqualsTextChange if true then setting text to the same as it was before will NOT fire change event.\n\t * Default is true however it is false default {@link VisValidatableTextField} to prevent form refreshment issues -\n\t * see issue VisEditor#165\n\t */\n\tpublic void setIgnoreEqualsTextChange (boolean ignoreEqualsTextChange) {\n\t\tthis.ignoreEqualsTextChange = ignoreEqualsTextChange;\n\t}\n\n\tstatic public class VisTextFieldStyle extends TextFieldStyle {\n\t\tpublic Drawable focusBorder;\n\t\tpublic Drawable errorBorder;\n\t\tpublic Drawable backgroundOver;\n\n\t\tpublic VisTextFieldStyle () {\n\t\t}\n\n\t\tpublic VisTextFieldStyle (BitmapFont font, Color fontColor, Drawable cursor, Drawable selection, Drawable background) {\n\t\t\tsuper(font, fontColor, cursor, selection, background);\n\t\t}\n\n\t\tpublic VisTextFieldStyle (VisTextFieldStyle style) {\n\t\t\tsuper(style);\n\t\t\tthis.focusBorder = style.focusBorder;\n\t\t\tthis.errorBorder = style.errorBorder;\n\t\t\tthis.backgroundOver = style.backgroundOver;\n\t\t}\n\t}\n\n\t/**\n\t * Interface for listening to typed characters.\n\t * @author mzechner\n\t */\n\tstatic public interface TextFieldListener {\n\t\tpublic void keyTyped (VisTextField textField, char c);\n\t}\n\n\t/**\n\t * Interface for filtering characters entered into the text field.\n\t * @author mzechner\n\t */\n\tstatic public interface TextFieldFilter {\n\t\tpublic boolean acceptChar (VisTextField textField, char c);\n\n\t\tstatic public class DigitsOnlyFilter implements TextFieldFilter {\n\t\t\t@Override\n\t\t\tpublic boolean acceptChar (VisTextField textField, char c) {\n\t\t\t\treturn Character.isDigit(c);\n\t\t\t}\n\n\t\t}\n\t}\n\n\tclass KeyRepeatTask extends Task {\n\t\tint keycode;\n\n\t\t@Override\n\t\tpublic void run () {\n\t\t\tinputListener.keyDown(null, keycode);\n\t\t}\n\t}\n\n\t/** Basic input listener for the text field */\n\tpublic class TextFieldClickListener extends ClickListener {\n\t\t@Override\n\t\tpublic void clicked (InputEvent event, float x, float y) {\n\t\t\tint count = getTapCount() % 4;\n\t\t\tif (count == 0) clearSelection();\n\t\t\tif (count == 2) {\n\t\t\t\tint[] array = wordUnderCursor(x);\n\t\t\t\tsetSelection(array[0], array[1]);\n\t\t\t}\n\t\t\tif (count == 3) selectAll();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\tif (!super.touchDown(event, x, y, pointer, button)) return false;\n\t\t\tif (pointer == 0 && button != 0) return false;\n\t\t\tif (disabled) return true;\n\t\t\tStage stage = getStage();\n\t\t\tFocusManager.switchFocus(stage, VisTextField.this);\n\t\t\tsetCursorPosition(x, y);\n\t\t\tselectionStart = cursor;\n\t\t\tif (stage != null) stage.setKeyboardFocus(VisTextField.this);\n\t\t\tif (readOnly == false) keyboard.show(true);\n\t\t\thasSelection = true;\n\t\t\treturn true;\n\t\t}\n\n\t\t@Override\n\t\tpublic void touchDragged (InputEvent event, float x, float y, int pointer) {\n\t\t\tsuper.touchDragged(event, x, y, pointer);\n\t\t\tsetCursorPosition(x, y);\n\t\t}\n\n\t\t@Override\n\t\tpublic void touchUp (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\tif (selectionStart == cursor) hasSelection = false;\n\t\t\tsuper.touchUp(event, x, y, pointer, button);\n\t\t}\n\n\t\tprotected void setCursorPosition (float x, float y) {\n\t\t\tlastBlink = 0;\n\t\t\tcursorOn = false;\n\t\t\tcursor = Math.min(letterUnderCursor(x), text.length());\n\t\t}\n\n\t\tprotected void goHome (boolean jump) {\n\t\t\tcursor = 0;\n\t\t}\n\n\t\tprotected void goEnd (boolean jump) {\n\t\t\tcursor = text.length();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\tif (disabled) return false;\n\n\t\t\tlastBlink = 0;\n\t\t\tcursorOn = false;\n\n\t\t\tStage stage = getStage();\n\t\t\tif (stage == null || stage.getKeyboardFocus() != VisTextField.this) return false;\n\t\t\tif (drawBorder == false) return false;\n\n\t\t\tboolean repeat = false;\n\t\t\tboolean ctrl = UIUtils.ctrl();\n\t\t\tboolean jump = ctrl && !passwordMode;\n\n\t\t\tif (ctrl) {\n\t\t\t\tif (keycode == Keys.V && readOnly == false) {\n\t\t\t\t\tpaste(clipboard.getContents(), true);\n\t\t\t\t\trepeat = true;\n\t\t\t\t}\n\t\t\t\tif (keycode == Keys.C || keycode == Keys.INSERT) {\n\t\t\t\t\tcopy();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (keycode == Keys.X && readOnly == false) {\n\t\t\t\t\tcut(true);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (keycode == Keys.A) {\n\t\t\t\t\tselectAll();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (keycode == Keys.Z && readOnly == false) {\n\t\t\t\t\tString oldText = text;\n\t\t\t\t\tint oldCursorPos = getCursorPosition();\n\t\t\t\t\tsetText(undoText);\n\t\t\t\t\tVisTextField.this.setCursorPosition(MathUtils.clamp(cursor, 0, undoText.length()));\n\t\t\t\t\tundoText = oldText;\n\t\t\t\t\tundoCursorPos = oldCursorPos;\n\t\t\t\t\tupdateDisplayText();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (UIUtils.shift()) {\n\t\t\t\tif (keycode == Keys.INSERT && readOnly == false) paste(clipboard.getContents(), true);\n\t\t\t\tif (keycode == Keys.FORWARD_DEL && readOnly == false) cut(true);\n\t\t\t\tselection:\n\t\t\t\t{\n\t\t\t\t\tint temp = cursor;\n\t\t\t\t\tkeys:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (keycode == Keys.LEFT) {\n\t\t\t\t\t\t\tmoveCursor(false, jump);\n\t\t\t\t\t\t\trepeat = true;\n\t\t\t\t\t\t\tbreak keys;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (keycode == Keys.RIGHT) {\n\t\t\t\t\t\t\tmoveCursor(true, jump);\n\t\t\t\t\t\t\trepeat = true;\n\t\t\t\t\t\t\tbreak keys;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (keycode == Keys.HOME) {\n\t\t\t\t\t\t\tgoHome(jump);\n\t\t\t\t\t\t\tbreak keys;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (keycode == Keys.END) {\n\t\t\t\t\t\t\tgoEnd(jump);\n\t\t\t\t\t\t\tbreak keys;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak selection;\n\t\t\t\t\t}\n\t\t\t\t\tif (!hasSelection) {\n\t\t\t\t\t\tselectionStart = temp;\n\t\t\t\t\t\thasSelection = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Cursor movement or other keys (kills selection).\n\t\t\t\tif (keycode == Keys.LEFT) {\n\t\t\t\t\tmoveCursor(false, jump);\n\t\t\t\t\tclearSelection();\n\t\t\t\t\trepeat = true;\n\t\t\t\t}\n\t\t\t\tif (keycode == Keys.RIGHT) {\n\t\t\t\t\tmoveCursor(true, jump);\n\t\t\t\t\tclearSelection();\n\t\t\t\t\trepeat = true;\n\t\t\t\t}\n\t\t\t\tif (keycode == Keys.HOME) {\n\t\t\t\t\tgoHome(jump);\n\t\t\t\t\tclearSelection();\n\t\t\t\t}\n\t\t\t\tif (keycode == Keys.END) {\n\t\t\t\t\tgoEnd(jump);\n\t\t\t\t\tclearSelection();\n\t\t\t\t}\n\t\t\t}\n\t\t\tcursor = MathUtils.clamp(cursor, 0, text.length());\n\n\t\t\tif (repeat) {\n\t\t\t\tscheduleKeyRepeatTask(keycode);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tprotected void scheduleKeyRepeatTask (int keycode) {\n\t\t\tif (!keyRepeatTask.isScheduled() || keyRepeatTask.keycode != keycode) {\n\t\t\t\tkeyRepeatTask.keycode = keycode;\n\t\t\t\tkeyRepeatTask.cancel();\n\t\t\t\tif (Gdx.input.isKeyPressed(keyRepeatTask.keycode)) { //issue #179\n\t\t\t\t\tTimer.schedule(keyRepeatTask, keyRepeatInitialTime, keyRepeatTime);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean keyUp (InputEvent event, int keycode) {\n\t\t\tif (disabled) return false;\n\t\t\tkeyRepeatTask.cancel();\n\t\t\treturn true;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean keyTyped (InputEvent event, char character) {\n\t\t\tif (disabled || readOnly) return false;\n\n\t\t\t// Disallow \"typing\" most ASCII control characters, which would show up as a space when onlyFontChars is true.\n\t\t\tswitch (character) {\n\t\t\t\tcase BACKSPACE:\n\t\t\t\tcase TAB:\n\t\t\t\tcase ENTER_ANDROID:\n\t\t\t\tcase ENTER_DESKTOP:\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tif (character < 32) return false;\n\t\t\t}\n\n\t\t\tStage stage = getStage();\n\t\t\tif (stage == null || stage.getKeyboardFocus() != VisTextField.this) return false;\n\n\t\t\tif (UIUtils.isMac && Gdx.input.isKeyPressed(Keys.SYM)) return true;\n\n\t\t\tif (focusTraversal && (character == TAB || (character == ENTER_ANDROID && enterKeyFocusTraversal))) {\n\t\t\t\tnext(UIUtils.shift());\n\t\t\t} else {\n\t\t\t\tboolean delete = character == DELETE;\n\t\t\t\tboolean backspace = character == BACKSPACE;\n\t\t\t\tboolean enter = character == ENTER_DESKTOP || character == ENTER_ANDROID;\n\t\t\t\tboolean add = enter ? writeEnters : (!onlyFontChars || style.font.getData().hasGlyph(character));\n\t\t\t\tboolean remove = backspace || delete;\n\t\t\t\tif (add || remove) {\n\t\t\t\t\tString oldText = text;\n\t\t\t\t\tint oldCursor = cursor;\n\t\t\t\t\tif (hasSelection)\n\t\t\t\t\t\tcursor = delete(false);\n\t\t\t\t\telse {\n\t\t\t\t\t\tif (backspace && cursor > 0) {\n\t\t\t\t\t\t\ttext = text.substring(0, cursor - 1) + text.substring(cursor--);\n\t\t\t\t\t\t\trenderOffset = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (delete && cursor < text.length()) {\n\t\t\t\t\t\t\ttext = text.substring(0, cursor) + text.substring(cursor + 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (add && !remove) {\n\t\t\t\t\t\t// Character may be added to the text.\n\t\t\t\t\t\tif (!enter && filter != null && !filter.acceptChar(VisTextField.this, character)) return true;\n\t\t\t\t\t\tif (!withinMaxLength(text.length())) return true;\n\t\t\t\t\t\tString insertion = enter ? \"\\n\" : String.valueOf(character);\n\t\t\t\t\t\ttext = insert(cursor++, insertion, text);\n\t\t\t\t\t}\n\t\t\t\t\tif (changeText(oldText, text)) {\n\t\t\t\t\t\tlong time = System.currentTimeMillis();\n\t\t\t\t\t\tif (time - 750 > lastChangeTime) {\n\t\t\t\t\t\t\tundoText = oldText;\n\t\t\t\t\t\t\tundoCursorPos = getCursorPosition() - 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlastChangeTime = time;\n\t\t\t\t\t} else\n\t\t\t\t\t\tcursor = oldCursor;\n\t\t\t\t\tupdateDisplayText();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (listener != null) listener.keyTyped(VisTextField.this, character);\n\t\t\treturn true;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisTree.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.ui.Tree;\nimport com.badlogic.gdx.scenes.scene2d.ui.Tree.Node;\nimport com.kotcrab.vis.ui.FocusManager;\nimport com.kotcrab.vis.ui.Focusable;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * Does not provide additional features over standard {@link Tree}, however for proper VisUI focus border management VisTree\n * should be always preferred. Compatible with standard {@link Tree}\n * @author Kotcrab\n * @see Tree\n */\npublic class VisTree<N extends Node, V> extends Tree<N, V> {\n\tpublic VisTree (String styleName) {\n\t\tsuper(VisUI.getSkin(), styleName);\n\t\tinit();\n\t}\n\n\tpublic VisTree () {\n\t\tsuper(VisUI.getSkin());\n\t\tinit();\n\t}\n\n\tpublic VisTree (TreeStyle style) {\n\t\tsuper(style);\n\t\tinit();\n\t}\n\n\tprivate void init () {\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tFocusable focusable = FocusManager.getFocusedWidget();\n\t\t\t\tif (focusable instanceof Actor == false || isAscendantOf((Actor) focusable) == false) {\n\t\t\t\t\tFocusManager.resetFocus(getStage());\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisValidatableTextField.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.utils.FocusListener;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.util.InputValidator;\nimport com.kotcrab.vis.ui.util.Validators;\n\n/**\n * Text field that input can be validated by custom input validators.\n * @author Kotcrab\n * @see InputValidator\n * @see Validators\n */\npublic class VisValidatableTextField extends VisTextField {\n\tprivate Array<InputValidator> validators = new Array<InputValidator>();\n\tprivate boolean validationEnabled = true;\n\n\tprivate LastValidFocusListener restoreFocusListener;\n\tprivate boolean restoreLastValid = false;\n\tprivate String lastValid;\n\n\tpublic VisValidatableTextField () {\n\t\tsuper();\n\t\tinit();\n\t}\n\n\tpublic VisValidatableTextField (String text) {\n\t\tsuper(text);\n\t\tinit();\n\t}\n\n\tpublic VisValidatableTextField (String text, String styleName) {\n\t\tsuper(text, styleName);\n\t\tinit();\n\t}\n\n\tpublic VisValidatableTextField (String text, VisTextFieldStyle style) {\n\t\tsuper(text, style);\n\t\tinit();\n\t}\n\n\tpublic VisValidatableTextField (InputValidator validator) {\n\t\tsuper();\n\t\taddValidator(validator);\n\t\tinit();\n\t}\n\n\tpublic VisValidatableTextField (InputValidator... validators) {\n\t\tsuper();\n\t\tfor (InputValidator validator : validators)\n\t\t\taddValidator(validator);\n\n\t\tinit();\n\t}\n\n\tpublic VisValidatableTextField (boolean restoreLastValid, InputValidator validator) {\n\t\tsuper();\n\t\taddValidator(validator);\n\t\tinit();\n\t\tsetRestoreLastValid(restoreLastValid);\n\t}\n\n\tpublic VisValidatableTextField (boolean restoreLastValid, InputValidator... validators) {\n\t\tsuper();\n\t\tfor (InputValidator validator : validators)\n\t\t\taddValidator(validator);\n\n\t\tinit();\n\t\tsetRestoreLastValid(restoreLastValid);\n\t}\n\n\tprivate void init () {\n\t\tsetProgrammaticChangeEvents(true);\n\t\tsetIgnoreEqualsTextChange(false);\n\t}\n\n\t@Override\n\tvoid beforeChangeEventFired () {\n\t\tvalidateInput();\n\t}\n\n\t@Override\n\tpublic void setText (String str) {\n\t\tsuper.setText(str);\n\t\tvalidateInput();\n\t}\n\n\tpublic void validateInput () {\n\t\tif (validationEnabled) {\n\t\t\tfor (InputValidator validator : validators) {\n\t\t\t\tif (validator.validateInput(getText()) == false) {\n\t\t\t\t\tsetInputValid(false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// validation not enabled or validators does not returned false (input was valid)\n\t\tsetInputValid(true);\n\t}\n\n\tpublic void addValidator (InputValidator validator) {\n\t\tvalidators.add(validator);\n\t\tvalidateInput();\n\t}\n\n\tpublic Array<InputValidator> getValidators () {\n\t\treturn validators;\n\t}\n\n\tpublic boolean isValidationEnabled () {\n\t\treturn validationEnabled;\n\t}\n\n\t/**\n\t * Enables or disables validation, after changing this setting validateInput() is called, if validationEnabled == false then\n\t * field is marked as valid otherwise standard validation is performed\n\t * @param validationEnabled enable or disable validation\n\t */\n\tpublic void setValidationEnabled (boolean validationEnabled) {\n\t\tthis.validationEnabled = validationEnabled;\n\t\tvalidateInput();\n\t}\n\n\tpublic boolean isRestoreLastValid () {\n\t\treturn restoreLastValid;\n\t}\n\n\t/**\n\t * If true this field will automatically restore last valid text if it loses keyboard focus during text edition.\n\t * This can't be called while field is selected, doing so will result in IllegalStateException. Default is false.\n\t */\n\tpublic void setRestoreLastValid (boolean restoreLastValid) {\n\t\tif (hasSelection)\n\t\t\tthrow new IllegalStateException(\"Last valid text restore can't be changed while filed has selection\");\n\n\t\tthis.restoreLastValid = restoreLastValid;\n\n\t\tif (restoreLastValid) {\n\t\t\tif (restoreFocusListener == null) restoreFocusListener = new LastValidFocusListener();\n\t\t\taddListener(restoreFocusListener);\n\t\t} else {\n\t\t\tremoveListener(restoreFocusListener);\n\t\t}\n\t}\n\n\tpublic void restoreLastValidText () {\n\t\tif (restoreLastValid == false)\n\t\t\tthrow new IllegalStateException(\"Restore last valid is not enabled, see #setRestoreLastValid(boolean)\");\n\n\t\t//use super.setText to skip input validation and do not fire programmatic change event\n\t\tVisValidatableTextField.super.setText(lastValid);\n\t\tsetInputValid(true);\n\t}\n\n\tprivate class LastValidFocusListener extends FocusListener {\n\t\t@Override\n\t\tpublic void keyboardFocusChanged (FocusEvent event, Actor actor, boolean focused) {\n\t\t\tif (focused && restoreLastValid) {\n\t\t\t\tlastValid = getText();\n\t\t\t}\n\n\t\t\tif (focused == false && isInputValid() == false && restoreLastValid) {\n\t\t\t\trestoreLastValidText();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/VisWindow.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget;\n\nimport com.badlogic.gdx.Input.Keys;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.math.Interpolation;\nimport com.badlogic.gdx.scenes.scene2d.*;\nimport com.badlogic.gdx.scenes.scene2d.actions.Actions;\nimport com.badlogic.gdx.scenes.scene2d.ui.Label;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.scenes.scene2d.ui.Window;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.badlogic.gdx.utils.Align;\nimport com.kotcrab.vis.ui.FocusManager;\nimport com.kotcrab.vis.ui.VisUI;\n\n/**\n * Extends functionality of standard scene2d.ui {@link Window}.\n * @author Kotcrab\n * @see Window\n */\npublic class VisWindow extends Window {\n\tpublic static float FADE_TIME = 0.3f;\n\n\tprivate boolean centerOnAdd;\n\tprivate boolean keepWithinParent = false;\n\n\tprivate boolean fadeOutActionRunning;\n\n\tpublic VisWindow (String title) {\n\t\tthis(title, true);\n\t\tgetTitleLabel().setAlignment(VisUI.getDefaultTitleAlign());\n\t}\n\n\tpublic VisWindow (String title, boolean showWindowBorder) {\n\t\tsuper(title, VisUI.getSkin(), showWindowBorder ? \"default\" : \"noborder\");\n\t\tgetTitleLabel().setAlignment(VisUI.getDefaultTitleAlign());\n\t}\n\n\tpublic VisWindow (String title, String styleName) {\n\t\tsuper(title, VisUI.getSkin(), styleName);\n\t\tgetTitleLabel().setAlignment(VisUI.getDefaultTitleAlign());\n\t}\n\n\tpublic VisWindow (String title, WindowStyle style) {\n\t\tsuper(title, style);\n\t\tgetTitleLabel().setAlignment(VisUI.getDefaultTitleAlign());\n\t}\n\n\t@Override\n\tpublic void setPosition (float x, float y) {\n\t\tsuper.setPosition((int) x, (int) y);\n\t}\n\n\t/**\n\t * Centers this window, if it has parent it will be done instantly, if it does not have parent it will be centered when it will\n\t * be added to stage\n\t * @return true when window was centered, false when window will be centered when added to stage\n\t */\n\tpublic boolean centerWindow () {\n\t\tGroup parent = getParent();\n\t\tif (parent == null) {\n\t\t\tcenterOnAdd = true;\n\t\t\treturn false;\n\t\t} else {\n\t\t\tmoveToCenter();\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t/**\n\t * @param centerOnAdd if true window position will be centered on screen after adding to stage\n\t * @see #centerWindow()\n\t */\n\tpublic void setCenterOnAdd (boolean centerOnAdd) {\n\t\tthis.centerOnAdd = centerOnAdd;\n\t}\n\n\t@Override\n\tprotected void setStage (Stage stage) {\n\t\tsuper.setStage(stage);\n\n\t\tif (stage != null) {\n\t\t\tstage.setKeyboardFocus(this); //issue #10, newly created window does not acquire keyboard focus\n\n\t\t\tif (centerOnAdd) {\n\t\t\t\tcenterOnAdd = false;\n\t\t\t\tmoveToCenter();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void moveToCenter () {\n\t\tStage parent = getStage();\n\t\tif (parent != null) setPosition((parent.getWidth() - getWidth()) / 2, (parent.getHeight() - getHeight()) / 2);\n\t}\n\n\t/**\n\t * Fade outs this window, when fade out animation is completed, window is removed from Stage. Calling this for the\n\t * second time won't have any effect if previous animation is still running.\n\t */\n\tpublic void fadeOut (float time) {\n\t\tif (fadeOutActionRunning) return;\n\t\tfadeOutActionRunning = true;\n\t\tfinal Touchable previousTouchable = getTouchable();\n\t\tsetTouchable(Touchable.disabled);\n\t\tStage stage = getStage();\n\t\tif (stage != null && stage.getKeyboardFocus() != null && stage.getKeyboardFocus().isDescendantOf(this)) {\n\t\t\tFocusManager.resetFocus(stage);\n\t\t}\n\t\taddAction(Actions.sequence(Actions.fadeOut(time, Interpolation.fade), new Action() {\n\t\t\t@Override\n\t\t\tpublic boolean act (float delta) {\n\t\t\t\tsetTouchable(previousTouchable);\n\t\t\t\tremove();\n\t\t\t\tgetColor().a = 1f;\n\t\t\t\tfadeOutActionRunning = false;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}));\n\t}\n\n\t/** @return this window for the purpose of chaining methods eg. stage.addActor(new MyWindow(stage).fadeIn(0.3f)); */\n\tpublic VisWindow fadeIn (float time) {\n\t\tsetColor(1, 1, 1, 0);\n\t\taddAction(Actions.fadeIn(time, Interpolation.fade));\n\t\treturn this;\n\t}\n\n\t/** Fade outs this window, when fade out animation is completed, window is removed from Stage */\n\tpublic void fadeOut () {\n\t\tfadeOut(FADE_TIME);\n\t}\n\n\t/** @return this window for the purpose of chaining methods eg. stage.addActor(new MyWindow(stage).fadeIn()); */\n\tpublic VisWindow fadeIn () {\n\t\treturn fadeIn(FADE_TIME);\n\t}\n\n\t/**\n\t * Called by window when close button was pressed (added using {@link #addCloseButton()})\n\t * or escape key was pressed (for close on escape {@link #closeOnEscape()} have to be called).\n\t * Default close behaviour is to fade out window, this can be changed by overriding this function.\n\t */\n\tprotected void close () {\n\t\tfadeOut();\n\t}\n\n\t/**\n\t * Adds close button to window, next to window title. After pressing that button, {@link #close()} is called. If nothing\n\t * else was added to title table, and current title alignment is center then the title will be automatically centered.\n\t */\n\tpublic void addCloseButton () {\n\t\tLabel titleLabel = getTitleLabel();\n\t\tTable titleTable = getTitleTable();\n\n\t\tVisImageButton closeButton = new VisImageButton(\"close-window\");\n\t\ttitleTable.add(closeButton).padRight(-getPadRight() + 0.7f);\n\t\tcloseButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tclose();\n\t\t\t}\n\t\t});\n\t\tcloseButton.addListener(new ClickListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tevent.cancel();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t});\n\n\t\tif (titleLabel.getLabelAlign() == Align.center && titleTable.getChildren().size == 2)\n\t\t\ttitleTable.getCell(titleLabel).padLeft(closeButton.getWidth() * 2);\n\t}\n\n\t/**\n\t * Will make this window close when escape key or back key was pressed. After pressing escape or back, {@link #close()} is called.\n\t * Back key is Android and iOS only\n\t */\n\tpublic void closeOnEscape () {\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\t\tif (keycode == Keys.ESCAPE) {\n\t\t\t\t\tclose();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean keyUp (InputEvent event, int keycode) {\n\t\t\t\tif (keycode == Keys.BACK) {\n\t\t\t\t\tclose();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic boolean isKeepWithinParent () {\n\t\treturn keepWithinParent;\n\t}\n\n\tpublic void setKeepWithinParent (boolean keepWithinParent) {\n\t\tthis.keepWithinParent = keepWithinParent;\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tif (keepWithinParent && getParent() != null) {\n\t\t\tfloat parentWidth = getParent().getWidth();\n\t\t\tfloat parentHeight = getParent().getHeight();\n\t\t\tif (getX() < 0) setX(0);\n\t\t\tif (getRight() > parentWidth) setX(parentWidth - getWidth());\n\t\t\tif (getY() < 0) setY(0);\n\t\t\tif (getTop() > parentHeight) setY(parentHeight - getHeight());\n\t\t}\n\t\tsuper.draw(batch, parentAlpha);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/BasicColorPicker.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.graphics.glutils.ShaderProgram;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.ui.Image;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.badlogic.gdx.utils.Disposable;\nimport com.kotcrab.vis.ui.FocusManager;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.ColorUtils;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.VisTextField;\nimport com.kotcrab.vis.ui.widget.VisTextField.TextFieldFilter;\nimport com.kotcrab.vis.ui.widget.VisValidatableTextField;\nimport com.kotcrab.vis.ui.widget.color.internal.AlphaImage;\nimport com.kotcrab.vis.ui.widget.color.internal.Palette;\nimport com.kotcrab.vis.ui.widget.color.internal.PickerCommons;\nimport com.kotcrab.vis.ui.widget.color.internal.VerticalChannelBar;\n\nimport static com.kotcrab.vis.ui.widget.color.internal.ColorPickerText.HEX;\n\n/**\n * Color Picker widget, allows user to select color. ColorPicker is relatively heavy widget and should be reused if possible.\n * Unlike other widgets, this one must be disposed when no longer needed!\n * <p>\n * Displays color pallet along with hue spectrum bar. Palette show all possible combination of saturation and value (SV\n * components of HSV color system) for given hue, spectrum bar shows all possible values of hue (H component). Displays\n * preview of current and new color and hex field that can be disabled. See {@link ExtendedColorPicker} if you need\n * more features.\n * <p>\n * Alpha channel can be only set from hex field and it disabled by default, use {@link #setAllowAlphaEdit(boolean)} to enable.\n * @author Kotcrab\n * @see ColorPicker\n * @see BasicColorPicker\n * @see ExtendedColorPicker\n * @since 0.9.3\n */\npublic class BasicColorPicker extends VisTable implements Disposable {\n\tpublic static final int FIELD_WIDTH = 50;\n\n\tpublic static final int PALETTE_SIZE = 160;\n\tpublic static final int BAR_WIDTH = 130;\n\tpublic static final int BAR_HEIGHT = 12;\n\n\tprivate static final float VERTICAL_BAR_WIDTH = 15;\n\n\tprivate static final int HEX_FIELD_WIDTH = 95;\n\tprivate static final int HEX_COLOR_LENGTH = 6;\n\tprivate static final int HEX_COLOR_LENGTH_WITH_ALPHA = 8;\n\n\tprotected ColorPickerWidgetStyle style;\n\tprotected Sizes sizes;\n\n\tprotected ColorPickerListener listener;\n\n\tColor oldColor;\n\tColor color;\n\n\tprotected PickerCommons commons;\n\n\tprotected Palette palette;\n\tprotected VerticalChannelBar verticalBar;\n\n\tprivate VisTable mainTable;\n\tprivate VisTable colorPreviewsTable;\n\tprivate VisTable hexTable;\n\tprivate VisValidatableTextField hexField;\n\n\tprivate Image currentColorImg;\n\tprivate Image newColorImg;\n\n\tprivate boolean allowAlphaEdit = false;\n\tprivate boolean showHexFields = true;\n\tprivate boolean showColorPreviews = true;\n\n\tprivate boolean disposed = false;\n\n\tpublic BasicColorPicker () {\n\t\tthis(null);\n\t}\n\n\tpublic BasicColorPicker (ColorPickerListener listener) {\n\t\tthis(\"default\", listener);\n\t}\n\n\tpublic BasicColorPicker (String styleName, ColorPickerListener listener) {\n\t\tthis(VisUI.getSkin().get(styleName, ColorPickerWidgetStyle.class), listener, false);\n\t}\n\n\tpublic BasicColorPicker (ColorPickerWidgetStyle style, ColorPickerListener listener) {\n\t\tthis(style, listener, false);\n\t}\n\n\tprotected BasicColorPicker (ColorPickerWidgetStyle style, ColorPickerListener listener, boolean loadExtendedShaders) {\n\t\tthis.listener = listener;\n\t\tthis.style = style;\n\t\tthis.sizes = VisUI.getSizes();\n\n\t\toldColor = new Color(Color.BLACK);\n\t\tcolor = new Color(Color.BLACK);\n\n\t\tcommons = new PickerCommons(style, sizes, loadExtendedShaders);\n\n\t\tcreateColorWidgets();\n\t\tcreateUI();\n\n\t\tupdateValuesFromCurrentColor();\n\t\tupdateUI();\n\t}\n\n\tprotected void createUI () {\n\t\tmainTable = new VisTable(true);\n\n\t\tcolorPreviewsTable = createColorsPreviewTable();\n\t\thexTable = createHexTable();\n\n\t\trebuildMainTable();\n\n\t\tadd(mainTable).top();\n\t}\n\n\tprivate void rebuildMainTable () {\n\t\tmainTable.clearChildren();\n\t\tmainTable.add(palette).size(PALETTE_SIZE * sizes.scaleFactor);\n\t\tmainTable.add(verticalBar).size(VERTICAL_BAR_WIDTH * sizes.scaleFactor, PALETTE_SIZE * sizes.scaleFactor).top();\n\n\t\tif (showColorPreviews) {\n\t\t\tmainTable.row();\n\t\t\tmainTable.add(colorPreviewsTable).colspan(2).expandX().fillX();\n\t\t}\n\n\t\tif (showHexFields) {\n\t\t\tmainTable.row();\n\t\t\tmainTable.add(hexTable).colspan(2).expandX().left();\n\t\t}\n\t}\n\n\tprivate VisTable createColorsPreviewTable () {\n\t\tVisTable table = new VisTable(false);\n\t\ttable.add(currentColorImg = new AlphaImage(commons, 5 * sizes.scaleFactor))\n\t\t\t\t.height(25 * sizes.scaleFactor).width(80 * sizes.scaleFactor).expandX().fillX();\n\t\ttable.add(new Image(style.iconArrowRight)).pad(0, 2, 0, 2);\n\t\ttable.add(newColorImg = new AlphaImage(commons, 5 * sizes.scaleFactor))\n\t\t\t\t.height(25 * sizes.scaleFactor).width(80 * sizes.scaleFactor).expandX().fillX();\n\n\t\tcurrentColorImg.setColor(color);\n\t\tnewColorImg.setColor(color);\n\n\t\tcurrentColorImg.addListener(new ClickListener() {\n\t\t\t@Override\n\t\t\tpublic void clicked (InputEvent event, float x, float y) {\n\t\t\t\trestoreLastColor();\n\t\t\t}\n\t\t});\n\n\t\treturn table;\n\t}\n\n\tprivate VisTable createHexTable () {\n\t\tVisTable table = new VisTable(true);\n\t\ttable.add(new VisLabel(HEX.get()));\n\t\ttable.add(hexField = new VisValidatableTextField(\"00000000\")).width(HEX_FIELD_WIDTH * sizes.scaleFactor);\n\t\ttable.row();\n\n\t\thexField.setMaxLength(HEX_COLOR_LENGTH);\n\t\thexField.setProgrammaticChangeEvents(false);\n\t\thexField.setTextFieldFilter(new TextFieldFilter() {\n\t\t\t@Override\n\t\t\tpublic boolean acceptChar (VisTextField textField, char c) {\n\t\t\t\treturn Character.isDigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');\n\t\t\t}\n\t\t});\n\n\t\thexField.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tif (hexField.getText().length() == (allowAlphaEdit ? HEX_COLOR_LENGTH_WITH_ALPHA : HEX_COLOR_LENGTH)) {\n\t\t\t\t\tsetColor(Color.valueOf(hexField.getText()), false);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn table;\n\t}\n\n\tpublic void focusHexField () {\n\t\tif (!isShowHexFields()) {\n\t\t\treturn;\n\t\t}\n\t\tFocusManager.switchFocus(getStage(), hexField);\n\t\tgetStage().setKeyboardFocus(hexField);\n\t}\n\n\tprotected void createColorWidgets () {\n\t\tPickerChangeListener pickerListener = new PickerChangeListener();\n\t\tpalette = new Palette(commons, 100, pickerListener);\n\t\tverticalBar = new VerticalChannelBar(commons, 360, pickerListener);\n\t}\n\n\tprotected void updateUI () {\n\t\tpalette.setPickerHue(verticalBar.getValue());\n\n\t\tnewColorImg.setColor(color);\n\n\t\thexField.setText(color.toString().toUpperCase());\n\t\thexField.setCursorPosition(hexField.getMaxLength());\n\n\t\tif (listener != null) listener.changed(color);\n\t}\n\n\t/** Updates picker ui from current color */\n\tprotected void updateValuesFromCurrentColor () {\n\t\tint[] hsv = ColorUtils.RGBtoHSV(color);\n\t\tint ch = hsv[0];\n\t\tint cs = hsv[1];\n\t\tint cv = hsv[2];\n\n\t\tverticalBar.setValue(ch);\n\t\tpalette.setValue(cs, cv);\n\t}\n\n\tprotected void updateValuesFromHSVFields () {\n\t\tcolor = ColorUtils.HSVtoRGB(verticalBar.getValue(), palette.getS(), palette.getV(), color.a);\n\t}\n\n\tpublic void restoreLastColor () {\n\t\tColor colorBeforeReset = new Color(color);\n\t\tsetColor(oldColor);\n\t\tif (listener != null) listener.reset(colorBeforeReset, color);\n\t}\n\n\t/** Sets current selected color in picker. */\n\t@Override\n\tpublic void setColor (Color newColor) {\n\t\tif (allowAlphaEdit == false) newColor.a = 1;\n\t\t//this method overrides setColor in Actor, not big deal we definitely don't need it\n\t\tsetColor(newColor, true);\n\t}\n\n\tprotected void setColor (Color newColor, boolean updateCurrentColor) {\n\t\tif (updateCurrentColor) {\n\t\t\tcurrentColorImg.setColor(new Color(newColor));\n\t\t\toldColor = new Color(newColor);\n\t\t}\n\t\tcolor = new Color(newColor);\n\t\tupdateValuesFromCurrentColor();\n\t\tupdateUI();\n\t}\n\n\tpublic ColorPickerListener getListener () {\n\t\treturn listener;\n\t}\n\n\tpublic void setListener (ColorPickerListener listener) {\n\t\tthis.listener = listener;\n\t}\n\n\t/**\n\t * @param allowAlphaEdit if false this picker will have disabled editing color alpha channel. If current picker color\n\t * has alpha it will be reset to 1. If true alpha editing will be re-enabled. For better UX this should not be called\n\t * while ColorPicker is visible.\n\t */\n\tpublic void setAllowAlphaEdit (boolean allowAlphaEdit) {\n\t\tthis.allowAlphaEdit = allowAlphaEdit;\n\n\t\thexField.setMaxLength(allowAlphaEdit ? HEX_COLOR_LENGTH_WITH_ALPHA : HEX_COLOR_LENGTH);\n\t\tif (allowAlphaEdit == false) {\n\t\t\tsetColor(new Color(color));\n\t\t}\n\t}\n\n\tpublic boolean isAllowAlphaEdit () {\n\t\treturn allowAlphaEdit;\n\t}\n\n\tpublic void setShowHexFields (boolean showHexFields) {\n\t\tthis.showHexFields = showHexFields;\n\t\thexTable.setVisible(showHexFields);\n\t\trebuildMainTable();\n\t}\n\n\tpublic boolean isShowHexFields () {\n\t\treturn showHexFields;\n\t}\n\n\tpublic void setShowColorPreviews(boolean showColorPreviews) {\n\t\tthis.showColorPreviews = showColorPreviews;\n\t\tcolorPreviewsTable.setVisible(showColorPreviews);\n\t\trebuildMainTable();\n\t}\n\n\tpublic boolean isShowColorPreviews() {\n\t\treturn showColorPreviews;\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tboolean wasPedantic = ShaderProgram.pedantic;\n\t\tShaderProgram.pedantic = false;\n\t\tsuper.draw(batch, parentAlpha);\n\t\tShaderProgram.pedantic = wasPedantic;\n\t}\n\n\tpublic boolean isDisposed () {\n\t\treturn disposed;\n\t}\n\n\t@Override\n\tpublic void dispose () {\n\t\tif (disposed) throw new IllegalStateException(\"ColorPicker can't be disposed twice!\");\n\t\tcommons.dispose();\n\t\tdisposed = true;\n\t}\n\n\t/** Internal default picker listener used to get events from color widgets */\n\tclass PickerChangeListener extends ChangeListener {\n\t\tprotected void updateLinkedWidget () {\n\n\t\t}\n\n\t\t@Override\n\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\tupdateLinkedWidget();\n\n\t\t\tupdateValuesFromHSVFields();\n\t\t\tupdateUI();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/ColorPicker.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.Stage;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.utils.Disposable;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.widget.ButtonBar;\nimport com.kotcrab.vis.ui.widget.ButtonBar.ButtonType;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.VisTextButton;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\nimport static com.kotcrab.vis.ui.widget.color.internal.ColorPickerText.*;\n\n/**\n * Color Picker dialog, allows user to select color. ColorPicker is relatively heavy dialog and should be reused whenever possible.\n * This dialog must be disposed when no longer needed! ColorPicker will be centered on screen after adding to Stage\n * use {@link #setCenterOnAdd(boolean)} to change this.\n * @author Kotcrab\n * @see ColorPicker\n * @see BasicColorPicker\n * @see ExtendedColorPicker\n * @since 0.6.0\n */\npublic class ColorPicker extends VisWindow implements Disposable {\n\tprivate ExtendedColorPicker picker;\n\n\tprivate ColorPickerListener listener;\n\n\tprivate VisTextButton restoreButton;\n\tprivate VisTextButton cancelButton;\n\tprivate VisTextButton okButton;\n\n\tprivate boolean closeAfterPickingFinished = true;\n\n\tprivate boolean fadeOutDueToCanceled;\n\n\tpublic ColorPicker () {\n\t\tthis((String) null);\n\t}\n\n\tpublic ColorPicker (String title) {\n\t\tthis(\"default\", title, null);\n\t}\n\n\tpublic ColorPicker (String title, ColorPickerListener listener) {\n\t\tthis(\"default\", title, listener);\n\t}\n\n\tpublic ColorPicker (ColorPickerListener listener) {\n\t\tthis(\"default\", null, listener);\n\t}\n\n\tpublic ColorPicker (String styleName, String title, ColorPickerListener listener) {\n\t\tsuper(title != null ? title : \"\", VisUI.getSkin().get(styleName, ColorPickerStyle.class));\n\t\tthis.listener = listener;\n\n\t\tColorPickerStyle style = (ColorPickerStyle) getStyle();\n\n\t\tif (title == null) getTitleLabel().setText(TITLE.get());\n\n\t\tsetModal(true);\n\t\tsetMovable(true);\n\n\t\taddCloseButton();\n\t\tcloseOnEscape();\n\n\t\tpicker = new ExtendedColorPicker(style.pickerStyle, listener);\n\n\t\tadd(picker);\n\t\trow();\n\t\tadd(createButtons()).pad(3).right().expandX().colspan(3);\n\n\t\tpack();\n\t\tcenterWindow();\n\n\t\tcreateListeners();\n\t}\n\n\tprivate VisTable createButtons () {\n\t\tButtonBar buttonBar = new ButtonBar();\n\t\tbuttonBar.setIgnoreSpacing(true);\n\t\tbuttonBar.setButton(ButtonType.LEFT, restoreButton = new VisTextButton(RESTORE.get()));\n\t\tbuttonBar.setButton(ButtonType.OK, okButton = new VisTextButton(OK.get()));\n\t\tbuttonBar.setButton(ButtonType.CANCEL, cancelButton = new VisTextButton(CANCEL.get()));\n\t\treturn buttonBar.createTable();\n\t}\n\n\tprivate void createListeners () {\n\t\trestoreButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tpicker.restoreLastColor();\n\t\t\t}\n\t\t});\n\n\t\tokButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tif (listener != null) listener.finished(new Color(picker.color));\n\t\t\t\tsetColor(picker.color);\n\t\t\t\tif (closeAfterPickingFinished) fadeOut();\n\t\t\t}\n\t\t});\n\n\t\tcancelButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tfadeOutDueToCanceled = true;\n\t\t\t\tclose();\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tprotected void setStage (Stage stage) {\n\t\tsuper.setStage(stage);\n\t\tif (stage == null && fadeOutDueToCanceled) {\n\t\t\tfadeOutDueToCanceled = false;\n\t\t\tsetColor(picker.oldColor);\n\t\t}\n\t}\n\n\t/**\n\t * Controls whether to fade out color picker after users finished color picking and has pressed OK button. If\n\t * this is set to false picker won't close after pressing OK button. Default is true.\n\t * Note that by default picker is a modal window so might also want to call {@code colorPicker.setModal(false)} to\n\t * disable it.\n\t */\n\tpublic void setCloseAfterPickingFinished (boolean closeAfterPickingFinished) {\n\t\tthis.closeAfterPickingFinished = closeAfterPickingFinished;\n\t}\n\n\t@Override\n\tprotected void close () {\n\t\tif (listener != null) listener.canceled(picker.oldColor);\n\t\tsuper.close();\n\t}\n\n\t@Override\n\tpublic void dispose () {\n\t\tpicker.dispose();\n\t}\n\n\t/** @return internal dialog color picker */\n\tpublic ExtendedColorPicker getPicker () {\n\t\treturn picker;\n\t}\n\n\t// ColorPicker delegates\n\n\tpublic boolean isShowHexFields () {\n\t\treturn picker.isShowHexFields();\n\t}\n\n\tpublic void setShowHexFields (boolean showHexFields) {\n\t\tpicker.setShowHexFields(showHexFields);\n\t}\n\n\tpublic boolean isDisposed () {\n\t\treturn picker.isDisposed();\n\t}\n\n\tpublic void setAllowAlphaEdit (boolean allowAlphaEdit) {\n\t\tpicker.setAllowAlphaEdit(allowAlphaEdit);\n\t}\n\n\tpublic boolean isAllowAlphaEdit () {\n\t\treturn picker.isAllowAlphaEdit();\n\t}\n\n\tpublic void restoreLastColor () {\n\t\tpicker.restoreLastColor();\n\t}\n\n\t@Override\n\tpublic void setColor (Color newColor) {\n\t\tpicker.setColor(newColor);\n\t}\n\n\tpublic void setListener (ColorPickerListener listener) {\n\t\tthis.listener = listener;\n\t\tpicker.setListener(listener);\n\t}\n\n\tpublic ColorPickerListener getListener () {\n\t\treturn picker.getListener();\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/ColorPickerAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color;\n\nimport com.badlogic.gdx.graphics.Color;\n\n/**\n * Empty implementation of {@link ColorPickerListener}.\n * @author Kotcrab\n */\npublic class ColorPickerAdapter implements ColorPickerListener {\n\t@Override\n\tpublic void canceled (Color oldColor) {\n\n\t}\n\n\t@Override\n\tpublic void changed (Color newColor) {\n\n\t}\n\n\t@Override\n\tpublic void reset (Color previousColor, Color newColor) {\n\n\t}\n\n\t@Override\n\tpublic void finished (Color newColor) {\n\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/ColorPickerListener.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color;\n\nimport com.badlogic.gdx.graphics.Color;\n\n/**\n * Listener for {@link ColorPicker}.\n * @author Kotcrab\n */\npublic interface ColorPickerListener {\n\t/**\n\t * Called when color selection was canceled by user (either by clicking cancel or closing the window). Note that this\n\t * event can only occur when using {@link ColorPicker} dialog.\n\t */\n\tvoid canceled (Color oldColor);\n\n\t/**\n\t * Called when currently selected color in picker has changed. This does not mean that user finished selecting color, if\n\t * you are only interested in that event use {@link #finished(Color)} or {@link #canceled(Color)}.\n\t */\n\tvoid changed (Color newColor);\n\n\t/**\n\t * Called when selected color in picker were reset to previously select one.\n\t * @param previousColor color that was set before reset.\n\t * @param newColor new picker color.\n\t */\n\tvoid reset (Color previousColor, Color newColor);\n\n\t/**\n\t * Called when user has finished selecting new color. Note that this\n\t * event can only occur when using {@link ColorPicker} dialog.\n\t */\n\tvoid finished (Color newColor);\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/ColorPickerStyle.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Window.WindowStyle;\n\n/** @author Kotcrab */\npublic class ColorPickerStyle extends WindowStyle {\n\tpublic ColorPickerWidgetStyle pickerStyle;\n\n\tpublic ColorPickerStyle () {\n\t}\n\n\tpublic ColorPickerStyle (ColorPickerStyle style) {\n\t\tsuper(style);\n\t\tif (style.pickerStyle != null) this.pickerStyle = new ColorPickerWidgetStyle(style.pickerStyle);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/ColorPickerWidgetStyle.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color;\n\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\n\n/**\n * Style used by {@link ExtendedColorPicker} and {@link BasicColorPicker}.\n * {@link ColorPicker} dialog is using {@link ColorPickerStyle}.\n * @author Kotcrab\n */\npublic class ColorPickerWidgetStyle {\n\tpublic Drawable barSelector;\n\tpublic Drawable cross;\n\tpublic Drawable verticalSelector;\n\tpublic Drawable horizontalSelector;\n\tpublic Drawable iconArrowRight;\n\n\tpublic ColorPickerWidgetStyle () {\n\t}\n\n\tpublic ColorPickerWidgetStyle (ColorPickerWidgetStyle other) {\n\t\tthis.barSelector = other.barSelector;\n\t\tthis.cross = other.cross;\n\t\tthis.verticalSelector = other.verticalSelector;\n\t\tthis.horizontalSelector = other.horizontalSelector;\n\t\tthis.iconArrowRight = other.iconArrowRight;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/ExtendedColorPicker.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color;\n\nimport com.badlogic.gdx.graphics.glutils.ShaderProgram;\nimport com.badlogic.gdx.math.MathUtils;\nimport com.badlogic.gdx.utils.Disposable;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.ColorUtils;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.color.internal.ChannelBar;\nimport com.kotcrab.vis.ui.widget.color.internal.ColorChannelWidget;\nimport com.kotcrab.vis.ui.widget.color.internal.Palette;\nimport com.kotcrab.vis.ui.widget.color.internal.VerticalChannelBar;\n\n/**\n * Color Picker widget, allows user to select color. ColorPicker is relatively heavy widget and should be reused if possible.\n * Unlike other widgets, this one must be disposed when no longer needed!\n * <p>\n * Extends {@link BasicColorPicker} functionality and additionally provides separate bars for H, S, V color components.\n * Additional 3 bars (R, G, B) for selecting colors using RGB systems and dedicated bar to alpha channel. Alpha edition\n * is enabled by default.\n * <p>\n * Used directly by {@link ColorPicker} dialog.\n * @author Kotcrab\n * @see BasicColorPicker\n * @see ColorPicker\n * @since 0.9.3\n */\npublic class ExtendedColorPicker extends BasicColorPicker implements Disposable {\n\tprivate ColorChannelWidget hBar;\n\tprivate ColorChannelWidget sBar;\n\tprivate ColorChannelWidget vBar;\n\n\tprivate ColorChannelWidget rBar;\n\tprivate ColorChannelWidget gBar;\n\tprivate ColorChannelWidget bBar;\n\n\tprivate ColorChannelWidget aBar;\n\n\tpublic ExtendedColorPicker () {\n\t\tthis(null);\n\t}\n\n\tpublic ExtendedColorPicker (ColorPickerListener listener) {\n\t\tthis(\"default\", listener);\n\t}\n\n\tpublic ExtendedColorPicker (String styleName, ColorPickerListener listener) {\n\t\tthis(VisUI.getSkin().get(styleName, ColorPickerWidgetStyle.class), listener);\n\t}\n\n\tpublic ExtendedColorPicker (ColorPickerWidgetStyle style, ColorPickerListener listener) {\n\t\tsuper(style, listener, true);\n\t\tsetAllowAlphaEdit(true);\n\t}\n\n\t@Override\n\tprotected void createUI () {\n\t\tsuper.createUI();\n\n\t\tVisTable extendedTable = new VisTable(true); //displayed next to mainTable\n\n\t\textendedTable.add(hBar).row();\n\t\textendedTable.add(sBar).row();\n\t\textendedTable.add(vBar).row();\n\n\t\textendedTable.add();\n\t\textendedTable.row();\n\n\t\textendedTable.add(rBar).row();\n\t\textendedTable.add(gBar).row();\n\t\textendedTable.add(bBar).row();\n\n\t\textendedTable.add();\n\t\textendedTable.row();\n\n\t\textendedTable.add(aBar).row();\n\n\t\tadd(extendedTable).expand().left().top().pad(0, 9, 4, 4);\n\t}\n\n\t@Override\n\tprotected void createColorWidgets () {\n\t\tpalette = new Palette(commons, 100, new PickerChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void updateLinkedWidget () {\n\t\t\t\tsBar.setValue(palette.getS());\n\t\t\t\tvBar.setValue(palette.getV());\n\t\t\t}\n\t\t});\n\n\t\tverticalBar = new VerticalChannelBar(commons, 360, new PickerChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void updateLinkedWidget () {\n\t\t\t\thBar.setValue(verticalBar.getValue());\n\t\t\t}\n\t\t});\n\n\t\tHsvChannelBarListener svListener = new HsvChannelBarListener() {\n\t\t\t@Override\n\t\t\tprotected void updateLinkedWidget () {\n\t\t\t\tpalette.setValue(sBar.getValue(), vBar.getValue());\n\t\t\t}\n\t\t};\n\n\t\thBar = new ColorChannelWidget(commons, \"H\", ChannelBar.MODE_H, 360, new HsvChannelBarListener() {\n\t\t\t@Override\n\t\t\tprotected void updateLinkedWidget () {\n\t\t\t\tverticalBar.setValue(hBar.getValue());\n\t\t\t}\n\t\t});\n\n\t\tsBar = new ColorChannelWidget(commons, \"S\", ChannelBar.MODE_S, 100, svListener);\n\t\tvBar = new ColorChannelWidget(commons, \"V\", ChannelBar.MODE_V, 100, svListener);\n\n\t\tRgbChannelBarListener rgbListener = new RgbChannelBarListener();\n\t\trBar = new ColorChannelWidget(commons, \"R\", ChannelBar.MODE_R, 255, rgbListener);\n\t\tgBar = new ColorChannelWidget(commons, \"G\", ChannelBar.MODE_G, 255, rgbListener);\n\t\tbBar = new ColorChannelWidget(commons, \"B\", ChannelBar.MODE_B, 255, rgbListener);\n\n\t\taBar = new ColorChannelWidget(commons, \"A\", ChannelBar.MODE_ALPHA, 255, new AlphaChannelBarListener());\n\t}\n\n\t@Override\n\tpublic void setAllowAlphaEdit (boolean allowAlphaEdit) {\n\t\taBar.setVisible(allowAlphaEdit);\n\t\tsuper.setAllowAlphaEdit(allowAlphaEdit);\n\t}\n\n\t@Override\n\tprotected void updateValuesFromCurrentColor () {\n\t\tint[] hsv = ColorUtils.RGBtoHSV(color);\n\t\tint ch = hsv[0];\n\t\tint cs = hsv[1];\n\t\tint cv = hsv[2];\n\n\t\tint cr = MathUtils.round(color.r * 255.0f);\n\t\tint cg = MathUtils.round(color.g * 255.0f);\n\t\tint cb = MathUtils.round(color.b * 255.0f);\n\t\tint ca = MathUtils.round(color.a * 255.0f);\n\n\t\thBar.setValue(ch);\n\t\tsBar.setValue(cs);\n\t\tvBar.setValue(cv);\n\n\t\trBar.setValue(cr);\n\t\tgBar.setValue(cg);\n\t\tbBar.setValue(cb);\n\n\t\taBar.setValue(ca);\n\n\t\tverticalBar.setValue(hBar.getValue());\n\t\tpalette.setValue(sBar.getValue(), vBar.getValue());\n\t}\n\n\t/** Updates picker from H, S and V bars */\n\t@Override\n\tprotected void updateValuesFromHSVFields () {\n\t\tint[] hsv = ColorUtils.RGBtoHSV(color);\n\t\tint h = hsv[0];\n\t\tint s = hsv[1];\n\t\tint v = hsv[2];\n\n\t\tif (hBar.isInputValid()) h = hBar.getValue();\n\t\tif (sBar.isInputValid()) s = sBar.getValue();\n\t\tif (vBar.isInputValid()) v = vBar.getValue();\n\n\t\tcolor = ColorUtils.HSVtoRGB(h, s, v, color.a);\n\n\t\tint cr = MathUtils.round(color.r * 255.0f);\n\t\tint cg = MathUtils.round(color.g * 255.0f);\n\t\tint cb = MathUtils.round(color.b * 255.0f);\n\n\t\trBar.setValue(cr);\n\t\tgBar.setValue(cg);\n\t\tbBar.setValue(cb);\n\t}\n\n\t/** Updates picker from R, G and B bars */\n\tprivate void updateValuesFromRGBFields () {\n\t\tint r = MathUtils.round(color.r * 255.0f);\n\t\tint g = MathUtils.round(color.g * 255.0f);\n\t\tint b = MathUtils.round(color.b * 255.0f);\n\n\t\tif (rBar.isInputValid()) r = rBar.getValue();\n\t\tif (gBar.isInputValid()) g = gBar.getValue();\n\t\tif (bBar.isInputValid()) b = bBar.getValue();\n\n\t\tcolor.set(r / 255.0f, g / 255.0f, b / 255.0f, color.a);\n\n\t\tint[] hsv = ColorUtils.RGBtoHSV(color);\n\t\tint ch = hsv[0];\n\t\tint cs = hsv[1];\n\t\tint cv = hsv[2];\n\n\t\thBar.setValue(ch);\n\t\tsBar.setValue(cs);\n\t\tvBar.setValue(cv);\n\n\t\tverticalBar.setValue(hBar.getValue());\n\t\tpalette.setValue(sBar.getValue(), vBar.getValue());\n\t}\n\n\tprivate class RgbChannelBarListener implements ChannelBar.ChannelBarListener {\n\t\t@Override\n\t\tpublic void updateFields () {\n\t\t\tupdateValuesFromRGBFields();\n\t\t\tupdateUI();\n\t\t}\n\n\t\t@Override\n\t\tpublic void setShaderUniforms (ShaderProgram shader) {\n\t\t\tshader.setUniformf(\"u_r\", color.r);\n\t\t\tshader.setUniformf(\"u_g\", color.g);\n\t\t\tshader.setUniformf(\"u_b\", color.b);\n\t\t}\n\t}\n\n\tprivate class AlphaChannelBarListener extends RgbChannelBarListener {\n\t\t@Override\n\t\tpublic void updateFields () {\n\t\t\tif (aBar.isInputValid()) color.a = aBar.getValue() / 255.0f;\n\t\t\tupdateUI();\n\t\t}\n\t}\n\n\tprivate abstract class HsvChannelBarListener implements ChannelBar.ChannelBarListener {\n\t\t@Override\n\t\tpublic void updateFields () {\n\t\t\tupdateLinkedWidget();\n\t\t\tupdateValuesFromHSVFields();\n\t\t\tupdateUI();\n\t\t}\n\n\t\t@Override\n\t\tpublic void setShaderUniforms (ShaderProgram shader) {\n\t\t\tshader.setUniformf(\"u_h\", hBar.getValue() / 360.0f);\n\t\t\tshader.setUniformf(\"u_s\", sBar.getValue() / 100.0f);\n\t\t\tshader.setUniformf(\"u_v\", vBar.getValue() / 100.0f);\n\t\t}\n\n\t\tprotected abstract void updateLinkedWidget ();\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/internal/AlphaChannelBar.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color.internal;\n\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\n\n/**\n * Channel bar intended for alpha channel, renders alpha grid below channel texture.\n * @author Kotcrab\n */\npublic class AlphaChannelBar extends ChannelBar {\n\tprivate GridSubImage gridImage;\n\n\tpublic AlphaChannelBar (PickerCommons commons, int mode, int maxValue, ChangeListener changeListener) {\n\t\tsuper(commons, mode, maxValue, changeListener);\n\t\tgridImage = new GridSubImage(commons.gridShader, commons.whiteTexture, 6 * commons.sizes.scaleFactor);\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tgridImage.draw(batch, this);\n\t\tsuper.draw(batch, parentAlpha);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/internal/AlphaImage.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color.internal;\n\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.kotcrab.vis.ui.widget.VisImage;\n\n/**\n * Image that displays checkerboard as background, used by ColorPicker to display selected colors with alphas. Note that for perfect grid\n * this image should have size which is multiplication of gridSize. Eg. if gridSize is equal to 5, this image can have size 65x100.\n * (because both 65 and 100 are divisible by 5)\n * @author Kotcrab\n */\npublic class AlphaImage extends VisImage {\n\tprivate GridSubImage gridImage;\n\n\tpublic AlphaImage (PickerCommons commons, float gridSize) {\n\t\tsuper(commons.whiteTexture);\n\t\tgridImage = new GridSubImage(commons.gridShader, commons.whiteTexture, gridSize);\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\t//don't draw grid if widget alpha is different than 1 because\n\t\t//this creates weird affect when window is fading in/out,\n\t\t//both parent image and grid is visible\n\t\tif (getColor().a != 1) gridImage.draw(batch, this);\n\t\tsuper.draw(batch, parentAlpha);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/internal/ChannelBar.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color.internal;\n\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.graphics.glutils.ShaderProgram;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.ChangeEvent;\nimport com.badlogic.gdx.utils.Pools;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.widget.color.BasicColorPicker;\nimport com.kotcrab.vis.ui.widget.color.ColorPickerWidgetStyle;\n\n/**\n * Used to display channel color bars in color picker.\n * @author Kotcrab\n */\npublic class ChannelBar extends ShaderImage {\n\tpublic static final int MODE_ALPHA = 0;\n\n\tpublic static final int MODE_R = 1;\n\tpublic static final int MODE_G = 2;\n\tpublic static final int MODE_B = 3;\n\n\tpublic static final int MODE_H = 4;\n\tpublic static final int MODE_S = 5;\n\tpublic static final int MODE_V = 6;\n\n\tprotected ColorPickerWidgetStyle style;\n\tprivate Sizes sizes;\n\n\tprivate int maxValue;\n\tprivate int value;\n\tprivate float selectorX;\n\n\tprivate int mode;\n\tprivate ChannelBarListener channelBarListener;\n\n\tpublic ChannelBar (PickerCommons commons, int mode, int maxValue, ChangeListener changeListener) {\n\t\tsuper(commons.getBarShader(mode), commons.whiteTexture);\n\t\tthis.style = commons.style;\n\t\tthis.sizes = commons.sizes;\n\t\tthis.mode = mode;\n\t\tthis.maxValue = maxValue;\n\n\t\tsetTouchable(Touchable.enabled);\n\t\tsetValue(value);\n\t\taddListener(changeListener);\n\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tupdateValueFromTouch(x);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void touchDragged (InputEvent event, float x, float y, int pointer) {\n\t\t\t\tupdateValueFromTouch(x);\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tsuper.draw(batch, parentAlpha);\n\t\tstyle.barSelector.draw(batch, getX() + selectorX - style.barSelector.getMinWidth() / 2, getY() - 1, style.barSelector.getMinWidth(), style.barSelector.getMinHeight());\n\t}\n\n\tpublic void setValue (int newValue) {\n\t\tthis.value = newValue;\n\t\tif (value < 0) value = 0;\n\t\tif (value > maxValue) value = maxValue;\n\n\t\tselectorX = ((float) value / maxValue) * BasicColorPicker.BAR_WIDTH * sizes.scaleFactor;\n\t}\n\n\tpublic int getValue () {\n\t\treturn value;\n\t}\n\n\tprivate void updateValueFromTouch (float x) {\n\t\tint newValue = (int) (x / BasicColorPicker.BAR_WIDTH * maxValue / sizes.scaleFactor);\n\t\tsetValue(newValue);\n\n\t\tChangeEvent changeEvent = Pools.obtain(ChangeEvent.class);\n\t\tfire(changeEvent);\n\t\tPools.free(changeEvent);\n\t}\n\n\t@Override\n\tprotected void setShaderUniforms (ShaderProgram shader) {\n\t\tshader.setUniformi(\"u_mode\", mode);\n\t\tchannelBarListener.setShaderUniforms(shader);\n\t}\n\n\tpublic void setChannelBarListener (ChannelBarListener channelBarListener) {\n\t\tthis.channelBarListener = channelBarListener;\n\t}\n\n\tpublic interface ChannelBarListener {\n\t\tvoid updateFields ();\n\n\t\tvoid setShaderUniforms (ShaderProgram shader);\n\t}\n}\n\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/internal/ColorChannelWidget.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color.internal;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.color.BasicColorPicker;\nimport com.kotcrab.vis.ui.widget.color.ColorPickerWidgetStyle;\nimport com.kotcrab.vis.ui.widget.color.internal.ColorInputField.ColorInputFieldListener;\n\n/**\n * Used to display one color channel (hue, saturation etc.) with label, ColorInputField and ChannelBar.\n * @author Kotcrab\n */\npublic class ColorChannelWidget extends VisTable {\n\tprivate PickerCommons commons;\n\tprivate ColorPickerWidgetStyle style;\n\tprivate Sizes sizes;\n\n\tprivate ChannelBar bar;\n\tprivate ChangeListener barListener;\n\tprivate ColorInputField inputField;\n\n\tprivate int mode;\n\tprivate int value;\n\tprivate int maxValue;\n\n\tpublic ColorChannelWidget (PickerCommons commons, String label, int mode, int maxValue, final ChannelBar.ChannelBarListener listener) {\n\t\tsuper(true);\n\t\tthis.commons = commons;\n\n\t\tthis.style = commons.style;\n\t\tthis.sizes = commons.sizes;\n\t\tthis.mode = mode;\n\t\tthis.maxValue = maxValue;\n\n\t\tbarListener = new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tvalue = bar.getValue();\n\t\t\t\tlistener.updateFields();\n\t\t\t\tinputField.setValue(value);\n\t\t\t}\n\t\t};\n\n\t\tadd(new VisLabel(label)).width(10 * sizes.scaleFactor).center();\n\t\tadd(inputField = new ColorInputField(maxValue, new ColorInputFieldListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (int newValue) {\n\t\t\t\tvalue = newValue;\n\t\t\t\tlistener.updateFields();\n\t\t\t\tbar.setValue(newValue);\n\t\t\t}\n\t\t})).width(BasicColorPicker.FIELD_WIDTH * sizes.scaleFactor);\n\t\tadd(bar = createBarImage()).size(BasicColorPicker.BAR_WIDTH * sizes.scaleFactor, BasicColorPicker.BAR_HEIGHT * sizes.scaleFactor);\n\t\tbar.setChannelBarListener(listener);\n\n\t\tinputField.setValue(0);\n\t}\n\n\tpublic int getValue () {\n\t\treturn value;\n\t}\n\n\tpublic void setValue (int value) {\n\t\tthis.value = value;\n\t\tinputField.setValue(value);\n\t\tbar.setValue(value);\n\t}\n\n\tprivate ChannelBar createBarImage () {\n\t\tif (mode == ChannelBar.MODE_ALPHA)\n\t\t\treturn new AlphaChannelBar(commons, mode, maxValue, barListener);\n\t\telse\n\t\t\treturn new ChannelBar(commons, mode, maxValue, barListener);\n\t}\n\n\tpublic ChannelBar getBar () {\n\t\treturn bar;\n\t}\n\n\tpublic boolean isInputValid () {\n\t\treturn inputField.isInputValid();\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/internal/ColorInputField.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color.internal;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.FocusListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.UIUtils;\nimport com.kotcrab.vis.ui.util.InputValidator;\nimport com.kotcrab.vis.ui.widget.VisTextField;\nimport com.kotcrab.vis.ui.widget.VisValidatableTextField;\n\n/**\n * Fields used to enter color numbers in color picker, verifies max allowed value\n * provides quick increment/decrement of current value by pressing [shift +] plus or minus on numpad\n * @author Kotcrab\n */\npublic class ColorInputField extends VisValidatableTextField {\n\tprivate int value;\n\tprivate int maxValue;\n\n\tpublic ColorInputField (final int maxValue, final ColorInputFieldListener listener) {\n\t\tsuper(new ColorFieldValidator(maxValue));\n\t\tthis.value = 0;\n\t\tthis.maxValue = maxValue;\n\n\t\tsetProgrammaticChangeEvents(false);\n\t\tsetMaxLength(3);\n\t\tsetTextFieldFilter(new NumberFilter());\n\n\t\taddListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tif (getText().length() > 0)\n\t\t\t\t\tvalue = Integer.valueOf(getText());\n\t\t\t}\n\t\t});\n\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean keyTyped (InputEvent event, char character) {\n\t\t\t\tColorInputField field = (ColorInputField) event.getListenerActor();\n\t\t\t\tif (character == '+') field.changeValue(UIUtils.shift() ? 10 : 1);\n\t\t\t\tif (character == '-') field.changeValue(UIUtils.shift() ? -10 : -1);\n\n\t\t\t\tif (character != 0) listener.changed(getValue());\n\n\t\t\t\treturn true;\n\t\t\t}\n\t\t});\n\n\t\taddListener(new FocusListener() {\n\t\t\t@Override\n\t\t\tpublic void keyboardFocusChanged (FocusEvent event, Actor actor, boolean focused) {\n\t\t\t\tif (focused == false && isInputValid() == false)\n\t\t\t\t\tsetValue(maxValue); //only possibility on invalid field is that entered value will be bigger than maxValue so we set field value to maxValue\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic void changeValue (int byValue) {\n\t\tthis.value += byValue;\n\n\t\tif (value > maxValue) value = maxValue;\n\t\tif (value < 0) value = 0;\n\n\t\tupdateUI();\n\t}\n\n\tpublic int getValue () {\n\t\treturn value;\n\t}\n\n\tpublic void setValue (int value) {\n\t\tthis.value = value;\n\t\tupdateUI();\n\t}\n\n\tprivate void updateUI () {\n\t\tsetText(String.valueOf(value));\n\t\tsetCursorPosition(getMaxLength());\n\t}\n\n\tpublic interface ColorInputFieldListener {\n\t\tvoid changed (int newValue);\n\t}\n\n\tprivate static class NumberFilter implements TextFieldFilter {\n\t\t@Override\n\t\tpublic boolean acceptChar (VisTextField textField, char c) {\n\t\t\treturn Character.isDigit(c);\n\t\t}\n\t}\n\n\tprivate static class ColorFieldValidator implements InputValidator {\n\t\tprivate int maxValue;\n\n\t\tpublic ColorFieldValidator (int maxValue) {\n\t\t\tthis.maxValue = maxValue;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean validateInput (String input) {\n\t\t\tif (input.equals(\"\")) return false;\n\n\t\t\tInteger number = Integer.parseInt(input);\n\t\t\tif (number > maxValue) return false;\n\n\t\t\treturn true;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/internal/ColorPickerText.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color.internal;\n\nimport com.badlogic.gdx.utils.I18NBundle;\nimport com.kotcrab.vis.ui.Locales;\nimport com.kotcrab.vis.ui.i18n.BundleText;\n\n/**\n * Contains texts for chooser access via I18NBundle.\n * @author Kotcrab\n * @since 0.7.0\n */\npublic enum ColorPickerText implements BundleText {\n\tTITLE(\"title\"),\n\tRESTORE(\"restore\"),\n\tCANCEL(\"cancel\"),\n\tOK(\"ok\"),\n\tHEX(\"hex\");\n\n\tprivate final String name;\n\n\tColorPickerText (final String name) {\n\t\tthis.name = name;\n\t}\n\n\tprivate static I18NBundle getBundle () {\n\t\treturn Locales.getColorPickerBundle();\n\t}\n\n\t@Override\n\tpublic final String getName () {\n\t\treturn name;\n\t}\n\n\t@Override\n\tpublic final String get () {\n\t\treturn getBundle().get(name);\n\t}\n\n\t@Override\n\tpublic final String format () {\n\t\treturn getBundle().format(name);\n\t}\n\n\t@Override\n\tpublic final String format (final Object... arguments) {\n\t\treturn getBundle().format(name, arguments);\n\t}\n\n\t@Override\n\tpublic final String toString () {\n\t\treturn get();\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/internal/GridSubImage.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color.internal;\n\nimport com.badlogic.gdx.graphics.Texture;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.graphics.glutils.ShaderProgram;\nimport com.badlogic.gdx.scenes.scene2d.ui.Image;\n\n/** @author Kotcrab */\npublic class GridSubImage {\n\tprivate ShaderProgram gridShader;\n\tprivate Texture whiteTexture;\n\tprivate float gridSize;\n\n\tpublic GridSubImage (ShaderProgram gridShader, Texture whiteTexture, float gridSize) {\n\t\tthis.gridShader = gridShader;\n\t\tthis.whiteTexture = whiteTexture;\n\t\tthis.gridSize = gridSize;\n\t}\n\n\tpublic void draw (Batch batch, Image parent) {\n\t\tShaderProgram originalShader = batch.getShader();\n\t\tbatch.setShader(gridShader);\n\t\tgridShader.setUniformf(\"u_width\", parent.getWidth());\n\t\tgridShader.setUniformf(\"u_height\", parent.getHeight());\n\t\tgridShader.setUniformf(\"u_gridSize\", gridSize);\n\t\tbatch.draw(whiteTexture, parent.getX() + parent.getImageX(), parent.getY() + parent.getImageY(),\n\t\t\t\tparent.getImageWidth() * parent.getScaleX(), parent.getImageHeight() * parent.getScaleY());\n\t\tbatch.setShader(originalShader);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/internal/Palette.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color.internal;\n\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.graphics.glutils.ShaderProgram;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.ChangeEvent;\nimport com.badlogic.gdx.utils.Pools;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.widget.color.BasicColorPicker;\nimport com.kotcrab.vis.ui.widget.color.ColorPickerWidgetStyle;\n\n/**\n * Colors palette used to display colors using all possible values of saturation and value.\n * @author Kotcrab\n */\npublic class Palette extends ShaderImage {\n\tprivate ColorPickerWidgetStyle style;\n\tprivate Sizes sizes;\n\n\tprivate int xV, yS;\n\tprivate int maxValue;\n\n\tprivate float selectorX;\n\tprivate float selectorY;\n\n\tprivate float pickerHue;\n\n\tpublic Palette (PickerCommons commons, int maxValue, ChangeListener listener) {\n\t\tsuper(commons.paletteShader, commons.whiteTexture);\n\t\tthis.style = commons.style;\n\t\tthis.sizes = commons.sizes;\n\t\tthis.maxValue = maxValue;\n\n\t\tsetTouchable(Touchable.enabled);\n\t\tsetValue(0, 0);\n\t\taddListener(listener);\n\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tupdateValueFromTouch(x, y);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void touchDragged (InputEvent event, float x, float y, int pointer) {\n\t\t\t\tupdateValueFromTouch(x, y);\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tsuper.draw(batch, parentAlpha);\n\n\t\tstyle.verticalSelector.draw(batch,\n\t\t\t\tgetX(),\n\t\t\t\tgetY() + selectorY - style.verticalSelector.getMinHeight() / 2 + 0.1f,\n\t\t\t\tgetImageWidth(), style.verticalSelector.getMinHeight());\n\n\t\tstyle.horizontalSelector.draw(batch,\n\t\t\t\tgetX() + selectorX - style.horizontalSelector.getMinWidth() / 2 + 0.1f,\n\t\t\t\tgetY(),\n\t\t\t\tstyle.horizontalSelector.getMinWidth(), getImageHeight());\n\n\t\tstyle.cross.draw(batch,\n\t\t\t\tgetX() + selectorX - style.cross.getMinWidth() / 2 + 0.1f,\n\t\t\t\tgetY() + selectorY - style.cross.getMinHeight() / 2 + 0.1f,\n\t\t\t\tstyle.cross.getMinWidth(), style.cross.getMinHeight());\n\t}\n\n\t@Override\n\tprotected void setShaderUniforms (ShaderProgram shader) {\n\t\tshader.setUniformf(\"u_h\", pickerHue);\n\t}\n\n\tpublic void setPickerHue (int pickerHue) {\n\t\tthis.pickerHue = pickerHue / 360.0f;\n\t}\n\n\tpublic void setValue (int s, int v) {\n\t\txV = v;\n\t\tyS = s;\n\n\t\tif (xV < 0) xV = 0;\n\t\tif (xV > maxValue) xV = maxValue;\n\n\t\tif (yS < 0) yS = 0;\n\t\tif (yS > maxValue) yS = maxValue;\n\n\t\tselectorX = ((float) xV / maxValue) * BasicColorPicker.PALETTE_SIZE * sizes.scaleFactor;\n\t\tselectorY = ((float) yS / maxValue) * BasicColorPicker.PALETTE_SIZE * sizes.scaleFactor;\n\t}\n\n\tprivate void updateValueFromTouch (float touchX, float touchY) {\n\t\tint newV = (int) (touchX / BasicColorPicker.PALETTE_SIZE * maxValue / sizes.scaleFactor);\n\t\tint newS = (int) (touchY / BasicColorPicker.PALETTE_SIZE * maxValue / sizes.scaleFactor);\n\n\t\tsetValue(newS, newV);\n\n\t\tChangeEvent changeEvent = Pools.obtain(ChangeEvent.class);\n\t\tfire(changeEvent);\n\t\tPools.free(changeEvent);\n\t}\n\n\tpublic int getV () {\n\t\treturn xV;\n\t}\n\n\tpublic int getS () {\n\t\treturn yS;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/internal/PickerCommons.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color.internal;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.graphics.Pixmap;\nimport com.badlogic.gdx.graphics.Pixmap.Format;\nimport com.badlogic.gdx.graphics.Texture;\nimport com.badlogic.gdx.graphics.Texture.TextureWrap;\nimport com.badlogic.gdx.graphics.glutils.ShaderProgram;\nimport com.badlogic.gdx.utils.Disposable;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.widget.color.ColorPickerWidgetStyle;\n\n/** @author Kotcrab */\npublic class PickerCommons implements Disposable {\n\tfinal ColorPickerWidgetStyle style;\n\tfinal Sizes sizes;\n\n\tprivate boolean loadExtendedShaders;\n\tShaderProgram paletteShader;\n\tShaderProgram verticalChannelShader;\n\tShaderProgram hsvShader;\n\tShaderProgram rgbShader;\n\tShaderProgram gridShader;\n\n\tTexture whiteTexture;\n\n\tpublic PickerCommons (ColorPickerWidgetStyle style, Sizes sizes, boolean loadExtendedShaders) {\n\t\tthis.style = style;\n\t\tthis.sizes = sizes;\n\t\tthis.loadExtendedShaders = loadExtendedShaders;\n\n\t\tcreatePixmap();\n\t\tloadShaders();\n\t}\n\n\tprivate void createPixmap () {\n\t\tPixmap whitePixmap = new Pixmap(2, 2, Format.RGB888);\n\t\twhitePixmap.setColor(Color.WHITE);\n\t\twhitePixmap.drawRectangle(0, 0, 2, 2);\n\t\twhiteTexture = new Texture(whitePixmap);\n\t\twhiteTexture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);\n\t\twhitePixmap.dispose();\n\t}\n\n\tprivate void loadShaders () {\n\t\tpaletteShader = loadShader(\"default.vert\", \"palette.frag\");\n\t\tverticalChannelShader = loadShader(\"default.vert\", \"verticalBar.frag\");\n\t\tgridShader = loadShader(\"default.vert\", \"checkerboard.frag\");\n\n\t\tif (loadExtendedShaders) {\n\t\t\thsvShader = loadShader(\"default.vert\", \"hsv.frag\");\n\t\t\trgbShader = loadShader(\"default.vert\", \"rgb.frag\");\n\t\t}\n\t}\n\n\tprivate ShaderProgram loadShader (String vertFile, String fragFile) {\n\t\tShaderProgram program = new ShaderProgram(\n\t\t\t\tGdx.files.classpath(\"com/kotcrab/vis/ui/widget/color/internal/\" + vertFile),\n\t\t\t\tGdx.files.classpath(\"com/kotcrab/vis/ui/widget/color/internal/\" + fragFile));\n\n\t\tif (program.isCompiled() == false) {\n\t\t\tthrow new IllegalStateException(\"ColorPicker shader compilation failed. Shader: \" + vertFile + \", \" + fragFile + \": \" + program.getLog());\n\t\t}\n\n\t\treturn program;\n\t}\n\n\tShaderProgram getBarShader (int mode) {\n\t\tswitch (mode) {\n\t\t\tcase ChannelBar.MODE_ALPHA:\n\t\t\tcase ChannelBar.MODE_R:\n\t\t\tcase ChannelBar.MODE_G:\n\t\t\tcase ChannelBar.MODE_B:\n\t\t\t\treturn rgbShader;\n\t\t\tcase ChannelBar.MODE_H:\n\t\t\tcase ChannelBar.MODE_S:\n\t\t\tcase ChannelBar.MODE_V:\n\t\t\t\treturn hsvShader;\n\t\t\tdefault:\n\t\t\t\tthrow new IllegalStateException(\"Unsupported mode: \" + mode);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void dispose () {\n\t\twhiteTexture.dispose();\n\n\t\tpaletteShader.dispose();\n\t\tverticalChannelShader.dispose();\n\t\tgridShader.dispose();\n\n\t\tif (loadExtendedShaders) {\n\t\t\thsvShader.dispose();\n\t\t\trgbShader.dispose();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/internal/ShaderImage.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color.internal;\n\nimport com.badlogic.gdx.graphics.Texture;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.graphics.glutils.ShaderProgram;\nimport com.kotcrab.vis.ui.widget.VisImage;\n\n/**\n * Allow to render standard {@link VisImage} with shader. Shaders uniforms can be set in {@link #setShaderUniforms(ShaderProgram)}\n * @author Kotcrab\n */\npublic class ShaderImage extends VisImage {\n\tprivate ShaderProgram shader;\n\n\tpublic ShaderImage (ShaderProgram shader, Texture texture) {\n\t\tsuper(texture);\n\t\tthis.shader = shader;\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tShaderProgram originalShader = batch.getShader();\n\t\tbatch.setShader(shader);\n\t\tsetShaderUniforms(shader);\n\n\t\tsuper.draw(batch, parentAlpha);\n\n\t\tbatch.setShader(originalShader);\n\t}\n\n\tprotected void setShaderUniforms (ShaderProgram shader) {\n\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/internal/VerticalChannelBar.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.color.internal;\n\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.ChangeEvent;\nimport com.badlogic.gdx.utils.Pools;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.widget.color.BasicColorPicker;\nimport com.kotcrab.vis.ui.widget.color.ColorPickerWidgetStyle;\n\n/**\n * Vertical channel bar is used to display vertical hue bar\n * @author Kotcrab\n */\npublic class VerticalChannelBar extends ShaderImage {\n\tprivate ColorPickerWidgetStyle style;\n\tprivate Sizes sizes;\n\tprivate int maxValue;\n\tprivate float selectorY;\n\tprivate int value;\n\n\tpublic VerticalChannelBar (PickerCommons commons, int maxValue, ChangeListener listener) {\n\t\tsuper(commons.verticalChannelShader, commons.whiteTexture);\n\t\tthis.style = commons.style;\n\t\tthis.sizes = commons.sizes;\n\t\tthis.maxValue = maxValue;\n\n\t\tsetTouchable(Touchable.enabled);\n\t\tsetValue(0);\n\t\taddListener(listener);\n\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tupdateValueFromTouch(y);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void touchDragged (InputEvent event, float x, float y, int pointer) {\n\t\t\t\tupdateValueFromTouch(y);\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tsuper.draw(batch, parentAlpha);\n\t\tstyle.verticalSelector.draw(batch, getX(), getY() + getImageY() + selectorY - 2.5f, getImageWidth(), style.verticalSelector.getMinHeight());\n\t}\n\n\tpublic void setValue (int newValue) {\n\t\tvalue = newValue;\n\t\tif (value < 0) value = 0;\n\t\tif (value > maxValue) value = maxValue;\n\n\t\tselectorY = ((float) value / maxValue) * BasicColorPicker.PALETTE_SIZE * sizes.scaleFactor;\n\t}\n\n\tprivate void updateValueFromTouch (float y) {\n\t\tint newValue = (int) (y / BasicColorPicker.PALETTE_SIZE * maxValue / sizes.scaleFactor);\n\t\tsetValue(newValue);\n\n\t\tChangeEvent changeEvent = Pools.obtain(ChangeEvent.class);\n\t\tfire(changeEvent);\n\t\tPools.free(changeEvent);\n\t}\n\n\tpublic int getValue () {\n\t\treturn value;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/color/internal/package-info.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal ColorPicker utilities. All files in this package are not considered as public VisUI API. Changes to those classes\n * won't be listed in CHANGES file.\n * @author Kotcrab\n */\npackage com.kotcrab.vis.ui.widget.color.internal;\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/FileChooser.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.Input.Buttons;\nimport com.badlogic.gdx.Input.Keys;\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.graphics.g2d.Batch;\nimport com.badlogic.gdx.math.Vector2;\nimport com.badlogic.gdx.scenes.scene2d.*;\nimport com.badlogic.gdx.scenes.scene2d.ui.*;\nimport com.badlogic.gdx.scenes.scene2d.utils.*;\nimport com.badlogic.gdx.utils.*;\nimport com.kotcrab.vis.ui.FocusManager;\nimport com.kotcrab.vis.ui.Focusable;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.layout.GridGroup;\nimport com.kotcrab.vis.ui.util.OsUtils;\nimport com.kotcrab.vis.ui.util.dialog.Dialogs;\nimport com.kotcrab.vis.ui.util.dialog.Dialogs.OptionDialogType;\nimport com.kotcrab.vis.ui.util.dialog.InputDialogAdapter;\nimport com.kotcrab.vis.ui.util.dialog.OptionDialogAdapter;\nimport com.kotcrab.vis.ui.util.value.ConstantIfVisibleValue;\nimport com.kotcrab.vis.ui.util.value.PrefHeightIfVisibleValue;\nimport com.kotcrab.vis.ui.util.value.PrefWidthIfVisibleValue;\nimport com.kotcrab.vis.ui.widget.*;\nimport com.kotcrab.vis.ui.widget.Tooltip;\nimport com.kotcrab.vis.ui.widget.ButtonBar.ButtonType;\nimport com.kotcrab.vis.ui.widget.file.internal.*;\nimport com.kotcrab.vis.ui.widget.file.internal.DriveCheckerService.DriveCheckerListener;\nimport com.kotcrab.vis.ui.widget.file.internal.DriveCheckerService.RootMode;\nimport com.kotcrab.vis.ui.widget.file.internal.FileChooserWinService.RootNameListener;\nimport com.kotcrab.vis.ui.widget.file.internal.FileHistoryManager.FileHistoryCallback;\nimport com.kotcrab.vis.ui.widget.file.internal.FilePopupMenu.FilePopupMenuCallback;\n\nimport java.io.File;\nimport java.io.FileFilter;\nimport java.io.IOException;\nimport java.lang.StringBuilder;\nimport java.text.SimpleDateFormat;\nimport java.util.Arrays;\nimport java.util.Comparator;\nimport java.util.Iterator;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static com.kotcrab.vis.ui.widget.file.internal.FileChooserText.*;\n\n/**\n * Widget allowing user to choose files. FileChooser is heavy widget and should be reused whenever possible, typically\n * one instance is enough for application. Chooser is platform dependent and can be only used on desktop.\n * <p>\n * FileChooser will be centered on screen after adding to Stage use {@link #setCenterOnAdd(boolean)} to change this.\n * @author Kotcrab\n * @since 0.1.0\n */\npublic class FileChooser extends VisWindow implements FileHistoryCallback {\n\tprivate static final long FILE_WATCHER_CHECK_DELAY_MILLIS = 2000;\n\tprivate static final ShortcutsComparator SHORTCUTS_COMPARATOR = new ShortcutsComparator();\n\tprivate static final Vector2 tmpVector = new Vector2();\n\n\tprivate static boolean saveLastDirectory = false;\n\n\tpublic static boolean focusFileScrollPaneOnShow = true;\n\tpublic static boolean focusSelectedFileTextFieldOnShow = true;\n\n\tprivate Mode mode;\n\tprivate ViewMode viewMode = ViewMode.DETAILS;\n\tprivate SelectionMode selectionMode = SelectionMode.FILES;\n\tprivate AtomicReference<FileSorting> sorting = new AtomicReference<FileSorting>(FileSorting.NAME);\n\tprivate AtomicBoolean sortingOrderAscending = new AtomicBoolean(true);\n\tprivate FileChooserListener listener = new FileChooserAdapter();\n\tprivate FileFilter fileFilter = new DefaultFileFilter(this);\n\tprivate FileDeleter fileDeleter = new DefaultFileDeleter();\n\tprivate FileTypeFilter fileTypeFilter = null;\n\tprivate FileTypeFilter.Rule activeFileTypeRule = null;\n\tprivate FileIconProvider iconProvider;\n\n\tprivate DriveCheckerService driveCheckerService = DriveCheckerService.getInstance();\n\tprivate Array<DriveCheckerListener> driveCheckerListeners = new Array<DriveCheckerListener>();\n\tprivate FileChooserWinService chooserWinService = FileChooserWinService.getInstance();\n\n\tprivate ExecutorService listDirExecutor = Executors.newSingleThreadExecutor(new ServiceThreadFactory(\"FileChooserListDirThread\"));\n\tprivate Future<?> listDirFuture;\n\tprivate ShowBusyBarTask showBusyBarTask = new ShowBusyBarTask();\n\n\tprivate SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyy-MM-dd HH:mm\");\n\n\tprivate boolean showSelectionCheckboxes = false;\n\tpublic static final int DEFAULT_KEY = -1;\n\tprivate boolean multiSelectionEnabled = false;\n\tprivate int groupMultiSelectKey = DEFAULT_KEY; //shift by default\n\tprivate int multiSelectKey = DEFAULT_KEY; //ctrl (or command on mac) by default\n\n\tprivate PreferencesIO preferencesIO;\n\tprivate Array<FileHandle> favorites;\n\tprivate Array<FileHandle> recentDirectories;\n\n\tprivate FileHandle currentDirectory;\n\tprivate Array<FileHandle> currentFiles = new Array<FileHandle>();\n\tprivate IdentityMap<FileHandle, FileHandleMetadata> currentFilesMetadata = new IdentityMap<FileHandle, FileHandleMetadata>();\n\tprivate FileListAdapter fileListAdapter;\n\tprivate Array<FileItem> selectedItems = new Array<FileItem>();\n\tprivate ShortcutItem selectedShortcut;\n\tprivate String defaultFileName;\n\n\tprivate boolean watchingFilesEnabled = true;\n\tprivate Thread fileWatcherThread;\n\tprivate boolean shortcutsListRebuildScheduled;\n\tprivate boolean filesListRebuildScheduled;\n\n\tprivate FileHistoryManager historyManager;\n\n\t// UI\n\tprivate FileChooserStyle style;\n\n\tprivate Sizes sizes;\n\n\tprivate VisSplitPane mainSplitPane;\n\n\tprivate VisTable shortcutsTable;\n\tprivate VerticalGroup shortcutsMainPanel;\n\tprivate VerticalGroup shortcutsRootsPanel;\n\tprivate VerticalGroup shortcutsFavoritesPanel;\n\tprivate ListView<FileHandle> fileListView;\n\tprivate float maxDateLabelWidth;\n\tprivate BusyBar fileListBusyBar;\n\n\tprivate VisImageButton favoriteFolderButton;\n\tprivate VisImageButton viewModeButton;\n\tprivate Tooltip favoriteFolderButtonTooltip;\n\tprivate VisTextField currentPath;\n\tprivate VisTextField selectedFileTextField;\n\tprivate VisSelectBox<FileTypeFilter.Rule> fileTypeSelectBox;\n\n\tprivate VisTextButton confirmButton;\n\tprivate FilePopupMenu fileMenu;\n\tprivate FileSuggestionPopup fileNameSuggestionPopup;\n\tprivate DirsSuggestionPopup dirsSuggestionPopup;\n\tprivate VisLabel fileTypeLabel;\n\tprivate PopupMenu viewModePopupMenu;\n\n\t/** @param mode whether this chooser will be used to open or save files */\n\tpublic FileChooser (Mode mode) {\n\t\tthis((FileHandle) null, mode);\n\t}\n\n\t/**\n\t * @param directory starting chooser directory\n\t * @param mode whether this chooser will be used to open or save files\n\t */\n\tpublic FileChooser (FileHandle directory, Mode mode) {\n\t\tsuper(\"\");\n\n\t\tthis.mode = mode;\n\n\t\tgetTitleLabel().setText(TITLE_CHOOSE_FILES.get());\n\n\t\tstyle = VisUI.getSkin().get(FileChooserStyle.class);\n\t\tsizes = VisUI.getSizes();\n\n\t\tinit(directory);\n\t}\n\n\t/**\n\t * @param title chooser window title\n\t * @param mode whether this chooser will be used to open or save files\n\t */\n\tpublic FileChooser (String title, Mode mode) {\n\t\tthis(\"default\", title, mode);\n\t}\n\n\t/**\n\t * @param styleName skin style name\n\t * @param title chooser window title\n\t * @param mode whether this chooser will be used to open or save files\n\t */\n\tpublic FileChooser (String styleName, String title, Mode mode) {\n\t\tsuper(title);\n\t\tthis.mode = mode;\n\n\t\tstyle = VisUI.getSkin().get(styleName, FileChooserStyle.class);\n\t\tsizes = VisUI.getSizes();\n\n\t\tinit(null);\n\t}\n\n\t/**\n\t * @param prefsName file name that will be used to store chooser preferences such as favorites or recent directories.\n\t * Should be your application package name with appended `.filechooser` e.g. com.seriouscompay.seriousprogram.filechooser.\n\t * This name should be unique and should not be reused with other preferences of your application to avoid key collisions.\n\t */\n\tpublic static void setDefaultPrefsName (String prefsName) {\n\t\tPreferencesIO.setDefaultPrefsName(prefsName);\n\t}\n\n\t/** @deprecated replaced by {@link #setDefaultPrefsName(String)} */\n\t@Deprecated\n\tpublic static void setFavoritesPrefsName (String name) {\n\t\tPreferencesIO.setDefaultPrefsName(name);\n\t}\n\n\tprivate void init (FileHandle directory) {\n\t\tsetModal(true);\n\t\tsetResizable(true);\n\t\tsetMovable(true);\n\t\taddCloseButton();\n\t\tcloseOnEscape();\n\n\t\ticonProvider = new DefaultFileIconProvider(this);\n\t\tpreferencesIO = new PreferencesIO();\n\t\treloadPreferences(false);\n\n\t\tcreateToolbar();\n\t\tviewModePopupMenu = new PopupMenu(style.popupMenuStyle);\n\t\tcreateViewModePopupMenu();\n\t\tcreateCenterContentPanel();\n\t\tcreateFileTextBox();\n\t\tcreateBottomButtons();\n\n\t\tcreateShortcutsMainPanel();\n\t\tshortcutsRootsPanel = new VerticalGroup();\n\t\tshortcutsFavoritesPanel = new VerticalGroup();\n\t\trebuildShortcutsFavoritesPanel();\n\n\t\tfileMenu = new FilePopupMenu(this, new FilePopupMenuCallback() {\n\t\t\t@Override\n\t\t\tpublic void showNewDirDialog () {\n\t\t\t\tshowNewDirectoryDialog();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void showFileDelDialog (FileHandle file) {\n\t\t\t\tshowFileDeleteDialog(file);\n\t\t\t}\n\t\t});\n\n\t\tfileNameSuggestionPopup = new FileSuggestionPopup(this);\n\t\tfileNameSuggestionPopup.setListener(new PopupMenu.PopupMenuListener() {\n\t\t\t@Override\n\t\t\tpublic void activeItemChanged (MenuItem newItem, boolean changedByKeyboard) {\n\t\t\t\tif (changedByKeyboard == false || newItem == null) return;\n\t\t\t\thighlightFiles(currentDirectory.child(newItem.getText().toString()));\n\t\t\t\tupdateSelectedFileFieldText(true);\n\t\t\t}\n\t\t});\n\n\t\trebuildShortcutsList();\n\n\t\tif (directory == null) {\n\t\t\tFileHandle startingDir = null;\n\t\t\tif (saveLastDirectory) startingDir = preferencesIO.loadLastDirectory();\n\t\t\tif (startingDir == null || startingDir.exists() == false)\n\t\t\t\tstartingDir = getDefaultStartingDirectory();\n\t\t\tsetDirectory(startingDir, HistoryPolicy.IGNORE);\n\t\t} else {\n\t\t\tsetDirectory(directory, HistoryPolicy.IGNORE);\n\t\t}\n\n\t\tsetSize(500, 600);\n\t\tcenterWindow();\n\n\t\tcreateListeners();\n\n\t\tsetFileTypeFilter(null);\n\t\tsetFavoriteFolderButtonVisible(false);\n\t}\n\n\tprivate void createToolbar () {\n\t\tVisTable toolbarTable = new VisTable(true);\n\t\ttoolbarTable.defaults().minWidth(30).right();\n\t\tadd(toolbarTable).fillX().expandX().pad(3).padRight(2);\n\n\t\thistoryManager = new FileHistoryManager(style, this);\n\n\t\tcurrentPath = new VisTextField();\n\t\tfinal VisImageButton showRecentDirButton = new VisImageButton(style.expandDropdown);\n\t\tshowRecentDirButton.setFocusBorderEnabled(false);\n\n\t\tdirsSuggestionPopup = new DirsSuggestionPopup(this, currentPath);\n\t\tdirsSuggestionPopup.setListener(new PopupMenu.PopupMenuListener() {\n\t\t\t@Override\n\t\t\tpublic void activeItemChanged (MenuItem newItem, boolean changedByKeyboard) {\n\t\t\t\tif (changedByKeyboard == false || newItem == null) return;\n\t\t\t\tsetCurrentPathFieldText(newItem.getText().toString());\n\t\t\t}\n\t\t});\n\n\t\tcurrentPath.addListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean keyTyped (InputEvent event, char character) {\n\t\t\t\tif (event.getKeyCode() == Keys.ENTER) {\n\t\t\t\t\tdirsSuggestionPopup.remove();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tfloat targetWidth = currentPath.getWidth() + showRecentDirButton.getWidth();\n\t\t\t\tdirsSuggestionPopup.pathFieldKeyTyped(getChooserStage(), targetWidth);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\t\tif (keycode == Keys.ENTER) {\n\t\t\t\t\tFileHandle file = Gdx.files.absolute(currentPath.getText());\n\t\t\t\t\tif (file.exists()) {\n\t\t\t\t\t\tif (file.isDirectory() == false) file = file.parent();\n\t\t\t\t\t\tsetDirectory(file, HistoryPolicy.ADD);\n\t\t\t\t\t\taddRecentDirectory(file);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tshowDialog(POPUP_DIRECTORY_DOES_NOT_EXIST.get());\n\t\t\t\t\t\tsetCurrentPathFieldText(currentDirectory.path());\n\t\t\t\t\t}\n\t\t\t\t\tevent.stop();\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\n\t\tcurrentPath.addListener(new FocusListener() {\n\t\t\t@Override\n\t\t\tpublic void keyboardFocusChanged (FocusEvent event, Actor actor, boolean focused) {\n\t\t\t\tif (focused == false) {\n\t\t\t\t\tsetCurrentPathFieldText(currentDirectory.path());\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tshowRecentDirButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tfloat targetWidth = currentPath.getWidth() + showRecentDirButton.getWidth();\n\t\t\t\tdirsSuggestionPopup.showRecentDirectories(getChooserStage(), recentDirectories, targetWidth);\n\t\t\t}\n\t\t});\n\n\t\tVisImageButton folderParentButton = new VisImageButton(style.iconFolderParent, PARENT_DIRECTORY.get());\n\t\tfavoriteFolderButton = new VisImageButton(style.iconStar);\n\t\tfavoriteFolderButtonTooltip = new Tooltip.Builder(CONTEXT_MENU_ADD_TO_FAVORITES.get()).target(favoriteFolderButton).build();\n\t\tviewModeButton = new VisImageButton(style.iconListSettings);\n\t\tnew Tooltip.Builder(CHANGE_VIEW_MODE.get()).target(viewModeButton).build();\n\t\tVisImageButton folderNewButton = new VisImageButton(style.iconFolderNew, NEW_DIRECTORY.get());\n\n\t\ttoolbarTable.add(historyManager.getButtonsTable());\n\t\ttoolbarTable.add(currentPath).spaceRight(0).expand().fill();\n\t\ttoolbarTable.add(showRecentDirButton).width(15 * sizes.scaleFactor).growY();\n\t\ttoolbarTable.add(folderParentButton);\n\t\ttoolbarTable.add(favoriteFolderButton).width(PrefWidthIfVisibleValue.INSTANCE).spaceRight(new ConstantIfVisibleValue(sizes.spacingRight));\n\t\ttoolbarTable.add(viewModeButton).width(PrefWidthIfVisibleValue.INSTANCE).spaceRight(new ConstantIfVisibleValue(sizes.spacingRight));\n\t\ttoolbarTable.add(folderNewButton);\n\n\t\tfolderParentButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tFileHandle parent = currentDirectory.parent();\n\n\t\t\t\t// if current directory is drive root (eg. \"C:/\") navigating to parent\n\t\t\t\t// would navigate to \"/\" which would work but it is bad for UX\n\t\t\t\tif (OsUtils.isWindows() && currentDirectory.path().endsWith(\":/\")) return;\n\n\t\t\t\tsetDirectory(parent, HistoryPolicy.ADD);\n\t\t\t}\n\t\t});\n\n\t\tfavoriteFolderButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tif (favorites.contains(currentDirectory, false)) {\n\t\t\t\t\tremoveFavorite(currentDirectory);\n\t\t\t\t} else {\n\t\t\t\t\taddFavorite(currentDirectory);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tfolderNewButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tshowNewDirectoryDialog();\n\t\t\t}\n\t\t});\n\n\t\taddListener(historyManager.getDefaultClickListener());\n\t}\n\n\tprivate void createViewModePopupMenu () {\n\t\trebuildViewModePopupMenu();\n\t\tviewModeButton.addListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\t//show menu on next frame, without it menu would be closed instantly it was opened\n\t\t\t\t//the other solution is to call event.stop but this could lead to some other PopupMenu not being closed\n\t\t\t\t//on touchDown event because event.stop stops event propagation\n\t\t\t\tGdx.app.postRunnable(new Runnable() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void run () {\n\t\t\t\t\t\tviewModePopupMenu.showMenu(getChooserStage(), viewModeButton);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate void rebuildViewModePopupMenu () {\n\t\tviewModePopupMenu.clear();\n\t\tfor (final ViewMode mode : ViewMode.values()) {\n\t\t\tif (mode.thumbnailMode && iconProvider.isThumbnailModesSupported() == false) continue;\n\t\t\tviewModePopupMenu.addItem(new MenuItem(mode.getBundleText(), new ChangeListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\tsetViewMode(mode);\n\t\t\t\t}\n\t\t\t}));\n\t\t}\n\t}\n\n\tprivate void updateFavoriteFolderButton () {\n\t\tVisLabel label = (VisLabel) favoriteFolderButtonTooltip.getContent();\n\n\t\tif (favorites.contains(currentDirectory, false)) {\n\t\t\tfavoriteFolderButton.getStyle().imageUp = style.iconStar;\n\t\t\tlabel.setText(CONTEXT_MENU_REMOVE_FROM_FAVORITES.get());\n\t\t} else {\n\t\t\tfavoriteFolderButton.getStyle().imageUp = style.iconStarOutline;\n\t\t\tlabel.setText(CONTEXT_MENU_ADD_TO_FAVORITES.get());\n\t\t}\n\n\t\tfavoriteFolderButtonTooltip.pack();\n\t}\n\n\tprivate void createCenterContentPanel () {\n\t\tfileListAdapter = new FileListAdapter(this, currentFiles);\n\t\tfileListView = new ListView<FileHandle>(fileListAdapter);\n\t\tsetupDefaultScrollPane(fileListView.getScrollPane());\n\n\t\tVisTable fileScrollPaneTable = new VisTable();\n\t\tfileListBusyBar = new BusyBar();\n\t\tfileListBusyBar.setVisible(false);\n\t\tfileScrollPaneTable.add(fileListBusyBar).space(0).height(PrefHeightIfVisibleValue.INSTANCE).growX().row();\n\t\tfileScrollPaneTable.add(fileListView.getMainTable()).pad(2).top().expand().fillX();\n\t\tfileScrollPaneTable.setTouchable(Touchable.enabled);\n\n\t\t// shortcutsTable is contained in shortcutsScrollPane contained in shortcutsScrollPaneTable contained in mainSplitPane\n\t\tshortcutsTable = new VisTable();\n\t\tfinal VisScrollPane shortcutsScrollPane = setupDefaultScrollPane(new VisScrollPane(shortcutsTable));\n\t\tVisTable shortcutsScrollPaneTable = new VisTable();\n\t\tshortcutsScrollPaneTable.add(shortcutsScrollPane).pad(2).top().expand().fillX();\n\n\t\tmainSplitPane = new VisSplitPane(shortcutsScrollPaneTable, fileScrollPaneTable, false) {\n\t\t\t@Override\n\t\t\tpublic void invalidate () {\n\t\t\t\tsuper.invalidate();\n\t\t\t\tinvalidateChildHierarchy(shortcutsScrollPane);\n\t\t\t}\n\t\t};\n\t\tmainSplitPane.setSplitAmount(0.3f);\n\t\tmainSplitPane.setMinSplitAmount(0.05f);\n\t\tmainSplitPane.setMaxSplitAmount(0.80f);\n\n\t\trow();\n\t\tadd(mainSplitPane).expand().fill();\n\t\trow();\n\n\t\tfileScrollPaneTable.addListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void touchUp (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tif (button == Buttons.RIGHT && fileMenu.isAddedToStage() == false) {\n\t\t\t\t\tfileMenu.build();\n\t\t\t\t\tfileMenu.showMenu(getChooserStage(), event.getStageX(), event.getStageY());\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate void invalidateChildHierarchy (WidgetGroup layout) {\n\t\tif (layout != null) {\n\t\t\tlayout.invalidate();\n\t\t\tfor (Actor actor : layout.getChildren()) {\n\t\t\t\tif (actor instanceof WidgetGroup)\n\t\t\t\t\tinvalidateChildHierarchy((WidgetGroup) actor);\n\t\t\t\telse if (actor instanceof Layout)\n\t\t\t\t\t((Layout) actor).invalidate();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void setCurrentPathFieldText (String text) {\n\t\tcurrentPath.setText(text);\n\t\tcurrentPath.setCursorAtTextEnd();\n\t}\n\n\tprivate void createFileTextBox () {\n\t\tVisTable table = new VisTable(true);\n\t\tVisLabel nameLabel = new VisLabel(FILE_NAME.get());\n\t\tselectedFileTextField = new VisTextField();\n\t\tselectedFileTextField.setProgrammaticChangeEvents(false);\n\n\t\tfileTypeLabel = new VisLabel(FILE_TYPE.get());\n\t\tfileTypeSelectBox = new VisSelectBox<FileTypeFilter.Rule>();\n\t\tfileTypeSelectBox.getSelection().setProgrammaticChangeEvents(false);\n\n\t\tfileTypeSelectBox.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tactiveFileTypeRule = fileTypeSelectBox.getSelected();\n\t\t\t\trebuildFileList();\n\t\t\t}\n\t\t});\n\n\t\ttable.defaults().left();\n\t\ttable.add(nameLabel).spaceBottom(new ConstantIfVisibleValue(fileTypeSelectBox, 5f));\n\t\ttable.add(selectedFileTextField).expandX().fillX()\n\t\t\t\t.spaceBottom(new ConstantIfVisibleValue(fileTypeSelectBox, 5f)).row();\n\t\ttable.add(fileTypeLabel).height(PrefHeightIfVisibleValue.INSTANCE)\n\t\t\t\t.spaceBottom(new ConstantIfVisibleValue(sizes.spacingBottom));\n\t\ttable.add(fileTypeSelectBox).height(PrefHeightIfVisibleValue.INSTANCE)\n\t\t\t\t.spaceBottom(new ConstantIfVisibleValue(sizes.spacingBottom)).expand().fill();\n\n\t\tselectedFileTextField.addListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\t\tif (keycode == Keys.ENTER) {\n\t\t\t\t\tselectionFinished();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tselectedFileTextField.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tdeselectAll(false);\n\t\t\t\tfileNameSuggestionPopup.pathFieldKeyTyped(getChooserStage(), currentFiles, selectedFileTextField);\n\n\t\t\t\tFileHandle enteredFile = currentDirectory.child(selectedFileTextField.getText());\n\t\t\t\tif (currentFiles.contains(enteredFile, false)) {\n\t\t\t\t\thighlightFiles(enteredFile);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tadd(table).expandX().fillX().pad(3f).padRight(2f).padBottom(2f);\n\t\trow();\n\t}\n\n\tprivate void updateFileTypeSelectBox () {\n\t\tif (fileTypeFilter == null || selectionMode == SelectionMode.DIRECTORIES) {\n\t\t\tfileTypeLabel.setVisible(false);\n\t\t\tfileTypeSelectBox.setVisible(false);\n\t\t\tfileTypeSelectBox.invalidateHierarchy();\n\t\t\treturn;\n\t\t} else {\n\t\t\tfileTypeLabel.setVisible(true);\n\t\t\tfileTypeSelectBox.setVisible(true);\n\t\t\tfileTypeSelectBox.invalidateHierarchy();\n\t\t}\n\n\t\tArray<FileTypeFilter.Rule> rules = new Array<FileTypeFilter.Rule>(fileTypeFilter.getRules());\n\t\tif (fileTypeFilter.isAllTypesAllowed()) {\n\t\t\tFileTypeFilter.Rule allTypesRule = new FileTypeFilter.Rule(ALL_FILES.get());\n\t\t\trules.add(allTypesRule);\n\t\t}\n\n\t\tfileTypeSelectBox.setItems(rules);\n\t\tfileTypeSelectBox.setSelected(activeFileTypeRule);\n\t}\n\n\tprivate void createBottomButtons () {\n\t\tVisTextButton cancelButton = new VisTextButton(CANCEL.get());\n\t\tconfirmButton = new VisTextButton(mode == Mode.OPEN ? OPEN.get() : SAVE.get());\n\n\t\tVisTable buttonTable = new VisTable(true);\n\t\tbuttonTable.defaults().minWidth(70).right();\n\t\tadd(buttonTable).padTop(3).padBottom(3).padRight(2).fillX().expandX();\n\n\t\tButtonBar buttonBar = new ButtonBar();\n\t\tbuttonBar.setIgnoreSpacing(true);\n\t\tbuttonBar.setButton(ButtonType.CANCEL, cancelButton);\n\t\tbuttonBar.setButton(ButtonType.OK, confirmButton);\n\t\tbuttonTable.add(buttonBar.createTable()).expand().right();\n\n\t\tcancelButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tfadeOut();\n\t\t\t\tlistener.canceled();\n\t\t\t}\n\t\t});\n\n\t\tconfirmButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tselectionFinished();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate void createShortcutsMainPanel () {\n\t\tshortcutsMainPanel = new VerticalGroup();\n\t\tString userHome = System.getProperty(\"user.home\");\n\t\tString userName = System.getProperty(\"user.name\");\n\t\tFile userDesktop = new File(userHome + \"/Desktop\");\n\n\t\tif (userDesktop.exists())\n\t\t\tshortcutsMainPanel.addActor(new ShortcutItem(userDesktop, DESKTOP.get(), style.iconFolder));\n\t\tshortcutsMainPanel.addActor(new ShortcutItem(new File(userHome), userName, style.iconFolder));\n\t}\n\n\tprivate void createListeners () {\n\t\taddListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\t\tif (keycode == Keys.A && UIUtils.ctrl() && getChooserStage().getKeyboardFocus() instanceof VisTextField == false) {\n\t\t\t\t\tselectAll();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean keyTyped (InputEvent event, char character) {\n\t\t\t\tif (getChooserStage().getKeyboardFocus() instanceof VisTextField) return false;\n\t\t\t\tif (Character.isLetterOrDigit(character) == false) return false;\n\t\t\t\tString name = String.valueOf(character);\n\t\t\t\tfor (FileHandle file : currentFiles) {\n\t\t\t\t\tif (file.name().toLowerCase().startsWith(name)) {\n\t\t\t\t\t\tdeselectAll();\n\t\t\t\t\t\thighlightFiles(file);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate void selectionFinished () {\n\t\tif (selectedItems.size == 1) {\n\t\t\t// only files allowed but directory is selected?\n\t\t\t// navigate to that directory!\n\t\t\tif (selectionMode == SelectionMode.FILES) {\n\t\t\t\tFileHandle selected = selectedItems.get(0).getFile();\n\t\t\t\tif (selected.isDirectory()) {\n\t\t\t\t\tsetDirectory(selected, HistoryPolicy.ADD);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// only directories allowed but file is selected?\n\t\t\t// display dialog :(\n\t\t\tif (selectionMode == SelectionMode.DIRECTORIES) {\n\t\t\t\tFileHandle selected = selectedItems.get(0).getFile();\n\t\t\t\tif (selected.isDirectory() == false) {\n\t\t\t\t\tshowDialog(POPUP_ONLY_DIRECTORIES.get());\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (selectedItems.size > 0 || mode == Mode.SAVE) {\n\t\t\tArray<FileHandle> files = getFileListFromSelected();\n\t\t\tnotifyListenerAndCloseDialog(files);\n\t\t} else {\n\t\t\tif (selectionMode == SelectionMode.FILES) {\n\t\t\t\tshowDialog(POPUP_CHOOSE_FILE.get());\n\t\t\t} else {\n\t\t\t\tArray<FileHandle> files = new Array<FileHandle>();\n\t\t\t\tif (selectedFileTextField.getText().length() != 0) {\n\t\t\t\t\tfiles.add(currentDirectory.child(selectedFileTextField.getText()));\n\t\t\t\t} else {\n\t\t\t\t\t// this part is executed when nothing is selected but selection mode is `directories` or `files and directories`\n\t\t\t\t\t// it is perfectly valid, nothing is selected so that means the current chooser directory have to be\n\t\t\t\t\t// selected and passed to listener\n\t\t\t\t\tfiles.add(currentDirectory);\n\t\t\t\t}\n\t\t\t\tnotifyListenerAndCloseDialog(files);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void close () {\n\t\tlistener.canceled();\n\t\tsuper.close();\n\t}\n\n\tprivate void notifyListenerAndCloseDialog (Array<FileHandle> files) {\n\t\tif (files == null) return;\n\n\t\tif (mode == Mode.OPEN) {\n\t\t\tfor (FileHandle file : files) {\n\t\t\t\tif (file.exists() == false) {\n\t\t\t\t\tshowDialog(POPUP_SELECTED_FILE_DOES_NOT_EXIST.get());\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (files.size != 0) {\n\t\t\tlistener.selected(files);\n\n\t\t\tif (saveLastDirectory) {\n\t\t\t\tpreferencesIO.saveLastDirectory(currentDirectory);\n\t\t\t}\n\t\t}\n\n\t\tfadeOut();\n\t}\n\n\t@Override\n\tpublic void fadeOut (float time) {\n\t\tsuper.fadeOut(time);\n\t\tfileMenu.remove();\n\t\tdirsSuggestionPopup.remove();\n\t\tfileNameSuggestionPopup.remove();\n\t\tviewModePopupMenu.remove();\n\t}\n\n\tprotected VisScrollPane setupDefaultScrollPane (VisScrollPane scrollPane) {\n\t\tscrollPane.setOverscroll(false, false);\n\t\tscrollPane.setFlickScroll(false);\n\t\tscrollPane.setFadeScrollBars(false);\n\t\tscrollPane.setScrollingDisabled(true, false);\n\t\treturn scrollPane;\n\t}\n\n\tprivate Array<FileHandle> getFileListFromSelected () {\n\t\tArray<FileHandle> list = new Array<FileHandle>();\n\n\t\tif (mode == Mode.OPEN) {\n\t\t\tfor (FileItem item : selectedItems)\n\t\t\t\tlist.add(item.getFile());\n\n\t\t\treturn list;\n\t\t} else if (selectedItems.size > 0) {\n\t\t\tfor (FileItem item : selectedItems)\n\t\t\t\tlist.add(item.getFile());\n\n\t\t\tshowOverwriteQuestion(list);\n\t\t\treturn null;\n\t\t} else {\n\t\t\tString fileName = selectedFileTextField.getText();\n\t\t\tFileHandle file = currentDirectory.child(fileName);\n\n\t\t\tif (FileUtils.isValidFileName(fileName) == false) {\n\t\t\t\tshowDialog(POPUP_FILENAME_INVALID.get());\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (file.exists()) {\n\t\t\t\tlist.add(file);\n\t\t\t\tshowOverwriteQuestion(list);\n\n\t\t\t\treturn null;\n\t\t\t} else {\n\t\t\t\t//if user typed no extension or extension is wrong and there is active file type rule\n\t\t\t\t//then the first extension rule will be appended/replaced automatically to entered file name\n\t\t\t\tif (activeFileTypeRule != null) {\n\t\t\t\t\tArray<String> ruleExts = activeFileTypeRule.getExtensions();\n\t\t\t\t\tif (ruleExts.size > 0 && ruleExts.contains(file.extension(), false) == false) {\n\t\t\t\t\t\tfile = file.sibling(file.nameWithoutExtension() + \".\" + ruleExts.first());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlist.add(file);\n\t\t\t\tif (file.exists()) {\n\t\t\t\t\tshowOverwriteQuestion(list);\n\t\t\t\t\treturn null;\n\t\t\t\t} else {\n\t\t\t\t\treturn list;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n\tprivate void showDialog (String text) {\n\t\tDialogs.showOKDialog(getChooserStage(), POPUP_TITLE.get(), text);\n\t}\n\n\tprivate void showOverwriteQuestion (final Array<FileHandle> filesList) {\n\t\tString text = filesList.size == 1 ? POPUP_FILE_EXIST_OVERWRITE.get() : POPUP_MULTIPLE_FILE_EXIST_OVERWRITE.get();\n\t\tDialogs.showOptionDialog(getChooserStage(), POPUP_TITLE.get(), text, OptionDialogType.YES_NO, new OptionDialogAdapter() {\n\t\t\t@Override\n\t\t\tpublic void yes () {\n\t\t\t\tnotifyListenerAndCloseDialog(filesList);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate void rebuildShortcutsList (boolean rebuildRootCache) {\n\t\tshortcutsTable.clear();\n\n\t\tshortcutsTable.add(shortcutsMainPanel).left().row();\n\t\tshortcutsTable.addSeparator();\n\n\t\tif (rebuildRootCache) rebuildFileRootsCache();\n\n\t\tshortcutsTable.add(shortcutsRootsPanel).left().row();\n\n\t\tif (shortcutsFavoritesPanel.getChildren().size > 0)\n\t\t\tshortcutsTable.addSeparator();\n\t\tshortcutsTable.add(shortcutsFavoritesPanel).left().row();\n\t}\n\n\tprivate void rebuildShortcutsList () {\n\t\tshortcutsListRebuildScheduled = false;\n\t\trebuildShortcutsList(true);\n\t}\n\n\tprivate void rebuildFileRootsCache () {\n\t\tshortcutsRootsPanel.clear();\n\t\tFile[] roots = File.listRoots();\n\n\t\tdriveCheckerListeners.clear();\n\t\tfor (final File root : roots) {\n\t\t\tDriveCheckerListener listener = new DriveCheckerListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void rootMode (File root, RootMode mode) {\n\t\t\t\t\tif (driveCheckerListeners.removeValue(this, true) == false) return;\n\t\t\t\t\tString initialName = root.toString();\n\n\t\t\t\t\tif (initialName.equals(\"/\")) initialName = COMPUTER.get();\n\n\t\t\t\t\tfinal ShortcutItem item = new ShortcutItem(root, initialName, style.iconDrive);\n\n\t\t\t\t\tif (OsUtils.isWindows()) chooserWinService.addListener(root, item);\n\n\t\t\t\t\tshortcutsRootsPanel.addActor(item);\n\t\t\t\t\tshortcutsRootsPanel.getChildren().sort(SHORTCUTS_COMPARATOR);\n\t\t\t\t}\n\t\t\t};\n\t\t\tdriveCheckerListeners.add(listener);\n\t\t\tdriveCheckerService.addListener(root, mode == Mode.OPEN ? RootMode.READABLE : RootMode.WRITABLE, listener);\n\t\t}\n\t}\n\n\tprivate void rebuildShortcutsFavoritesPanel () {\n\t\tshortcutsFavoritesPanel.clear();\n\t\tif (favorites.size > 0) {\n\t\t\tfor (FileHandle f : favorites)\n\t\t\t\tshortcutsFavoritesPanel.addActor(new ShortcutItem(f.file(), f.name(), style.iconFolder));\n\t\t}\n\t}\n\n\tprivate void rebuildFileList () {\n\t\trebuildFileList(false);\n\t}\n\n\tprivate void rebuildFileList (final boolean stageChanged) {\n\t\tfilesListRebuildScheduled = false;\n\t\tfinal FileHandle[] selectedFiles = new FileHandle[selectedItems.size];\n\t\tfor (int i = 0; i < selectedFiles.length; i++) {\n\t\t\tselectedFiles[i] = selectedItems.get(i).getFile();\n\t\t}\n\t\tdeselectAll();\n\n\t\tsetCurrentPathFieldText(currentDirectory.path());\n\n\t\tif (showBusyBarTask.isScheduled() == false) {\n\t\t\tTimer.schedule(showBusyBarTask, 0.2f); //quiet period before busy bar is shown\n\t\t}\n\n\t\tif (listDirFuture != null) listDirFuture.cancel(true);\n\t\tlistDirFuture = listDirExecutor.submit(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run () {\n\t\t\t\tif (currentDirectory.exists() == false || currentDirectory.isDirectory() == false) {\n\t\t\t\t\tGdx.app.postRunnable(new Runnable() {\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void run () {\n\t\t\t\t\t\t\tsetDirectory(getDefaultStartingDirectory(), HistoryPolicy.ADD);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tfinal Array<FileHandle> files = FileUtils.sortFiles(listFilteredCurrentDirectory(), sorting.get().comparator, !sortingOrderAscending.get());\n\t\t\t\tif (Thread.currentThread().isInterrupted()) return;\n\t\t\t\tfinal IdentityMap<FileHandle, FileHandleMetadata> metadata = new IdentityMap<FileHandle, FileHandleMetadata>(files.size);\n\t\t\t\tfor (FileHandle file : files) {\n\t\t\t\t\tmetadata.put(file, FileHandleMetadata.of(file));\n\t\t\t\t}\n\n\t\t\t\tif (Thread.currentThread().isInterrupted()) return;\n\t\t\t\tGdx.app.postRunnable(new Runnable() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void run () {\n\t\t\t\t\t\tbuildFileList(files, metadata, selectedFiles, stageChanged);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate void buildFileList (Array<FileHandle> files, IdentityMap<FileHandle, FileHandleMetadata> metadata, FileHandle[] selectedFiles, boolean stageChanged) {\n\t\tcurrentFiles.clear();\n\t\tcurrentFilesMetadata.clear();\n\t\tshowBusyBarTask.cancel();\n\t\tfileListBusyBar.setVisible(false);\n\n\t\tif (files.size == 0) {\n\t\t\tfileListAdapter.itemsChanged();\n\t\t\treturn;\n\t\t}\n\n\t\tmaxDateLabelWidth = 0;\n\n\t\tcurrentFiles.addAll(files);\n\t\tcurrentFilesMetadata = metadata;\n\t\tfileListAdapter.itemsChanged();\n\n\t\tfileListView.getScrollPane().setScrollX(0);\n\t\tfileListView.getScrollPane().setScrollY(0);\n\t\thighlightFiles(selectedFiles);\n\n\t\tif (stageChanged && selectedFiles.length == 0 && defaultFileName != null) {\n\t\t\tselectedFileTextField.setText(defaultFileName);\n\t\t\tFileHandle enteredFile = currentDirectory.child(selectedFileTextField.getText());\n\t\t\tif (currentFiles.contains(enteredFile, false)) {\n\t\t\t\thighlightFiles(enteredFile);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets chooser selected files. All files that are invalid for current selection won't be selected. Files that doesn't\n\t * exist will be ignored.\n\t * @param files absolute {@link FileHandle}s of files to be selected\n\t */\n\tpublic void setSelectedFiles (FileHandle... files) {\n\t\tdeselectAll(false);\n\n\t\tfor (FileHandle file : files) {\n\t\t\tFileItem item = fileListAdapter.getViews().get(file);\n\t\t\tif (item != null) {\n\t\t\t\titem.select(false);\n\t\t\t}\n\t\t}\n\n\t\tremoveInvalidSelections();\n\t\tupdateSelectedFileFieldText();\n\t}\n\n\t/**\n\t * Changes default file name that will be displayed in file name text field after chooser is added to stage.\n\t * This for example can be used to suggest default file name when chooser is in SAVE mode.\n\t * <p>\n\t * Note that when chooser is in OPEN mode and file with such name doesn't exist then pressing \"Open\" button\n\t * will still display message that selected file does not exist.\n\t * <p>\n\t * Default file name is only used after chooser is added to {@link Stage} and no other file was selected by\n\t * {@link #setSelectedFiles(FileHandle...)} or user.\n\t * <p>\n\t * This will automatically highlight matching file in file list (if file already exist).\n\t * @param text new default file name, may be null\n\t */\n\tpublic void setDefaultFileName (String text) {\n\t\tdefaultFileName = text;\n\t}\n\n\t/** Refresh chooser lists content */\n\tpublic void refresh () {\n\t\trefresh(false);\n\t}\n\n\tprivate void refresh (boolean stageChanged) {\n\t\trebuildShortcutsList();\n\t\trebuildFileList(stageChanged);\n\t}\n\n\t/**\n\t * Adds favorite to favorite list\n\t * @param favourite to be added\n\t */\n\tpublic void addFavorite (FileHandle favourite) {\n\t\tfavorites.add(favourite);\n\t\tpreferencesIO.saveFavorites(favorites);\n\t\trebuildShortcutsFavoritesPanel();\n\t\trebuildShortcutsList(false);\n\t\tupdateFavoriteFolderButton();\n\t}\n\n\t/**\n\t * Removes favorite from current favorite list\n\t * @param favorite to be removed (path to favorite)\n\t * @return true if favorite was removed, false otherwise\n\t */\n\tpublic boolean removeFavorite (FileHandle favorite) {\n\t\tboolean removed = favorites.removeValue(favorite, false);\n\t\tpreferencesIO.saveFavorites(favorites);\n\t\trebuildShortcutsFavoritesPanel();\n\t\trebuildShortcutsList(false);\n\t\tupdateFavoriteFolderButton();\n\t\treturn removed;\n\t}\n\n\tprivate void addRecentDirectory (FileHandle file) {\n\t\tif (recentDirectories.contains(file, false)) return;\n\t\trecentDirectories.insert(0, file);\n\t\tif (recentDirectories.size > AbstractSuggestionPopup.MAX_SUGGESTIONS) recentDirectories.pop();\n\t\tpreferencesIO.saveRecentDirectories(recentDirectories);\n\t}\n\n\tpublic void clearRecentDirectories () {\n\t\trecentDirectories.clear();\n\t\tpreferencesIO.saveRecentDirectories(recentDirectories);\n\t}\n\n\t@Override\n\tpublic void setVisible (boolean visible) {\n\t\tif (isVisible() == false && visible)\n\t\t\tdeselectAll(); // reset selected item when dialog is changed from invisible to visible\n\n\t\tsuper.setVisible(visible);\n\t}\n\n\tprivate void deselectAll () {\n\t\tdeselectAll(true);\n\t}\n\n\tprivate void deselectAll (boolean updateTextField) {\n\t\tfor (FileItem item : selectedItems)\n\t\t\titem.deselect(false);\n\n\t\tselectedItems.clear();\n\t\tif (updateTextField) updateSelectedFileFieldText();\n\t}\n\n\tprivate void selectAll () {\n\t\tfor (FileItem item : fileListAdapter.getOrderedViews())\n\t\t\titem.select(false);\n\n\t\tremoveInvalidSelections();\n\t\tupdateSelectedFileFieldText();\n\t}\n\n\t/**\n\t * Sets chooser selected files. Compared to {@link #setSelectedFiles(FileHandle...)} does not remove invalid files\n\t * from selection.\n\t */\n\tpublic void highlightFiles (FileHandle... files) {\n\t\tfor (FileHandle file : files) {\n\t\t\tFileItem item = fileListAdapter.getViews().get(file);\n\t\t\tif (item != null) {\n\t\t\t\titem.select(false);\n\t\t\t}\n\t\t}\n\t\tif (files.length > 0) {\n\t\t\tFileItem item = fileListAdapter.getViews().get(files[0]);\n\t\t\tif (item != null) {\n\t\t\t\tif (item.getParent() instanceof Table) { //table at this point may need additional layout to calculate proper target scroll cords\n\t\t\t\t\t((Table) item.getParent()).layout();\n\t\t\t\t}\n\t\t\t\titem.localToParentCoordinates(tmpVector.setZero());\n\t\t\t\tfileListView.getScrollPane().scrollTo(tmpVector.x, tmpVector.y, item.getWidth(), item.getHeight(), false, true);\n\t\t\t}\n\t\t}\n\t\tupdateSelectedFileFieldText();\n\t}\n\n\tprivate void updateSelectedFileFieldText () {\n\t\tupdateSelectedFileFieldText(false);\n\t}\n\n\tprivate void updateSelectedFileFieldText (boolean ignoreKeyboardFocus) {\n\t\tif (ignoreKeyboardFocus == false && getChooserStage() != null) {\n\t\t\tif (getChooserStage().getKeyboardFocus() == selectedFileTextField) return;\n\t\t}\n\t\tif (selectedItems.size == 0) {\n\t\t\tselectedFileTextField.setText(\"\");\n\t\t} else if (selectedItems.size == 1) {\n\t\t\tselectedFileTextField.setText(selectedItems.get(0).getFile().name());\n\t\t} else {\n\t\t\tStringBuilder builder = new StringBuilder();\n\n\t\t\tfor (FileItem item : selectedItems) {\n\t\t\t\tbuilder.append('\"');\n\t\t\t\tbuilder.append(item.file.name());\n\t\t\t\tbuilder.append(\"\\\" \");\n\t\t\t}\n\n\t\t\tselectedFileTextField.setText(builder.toString());\n\t\t}\n\t\tselectedFileTextField.setCursorAtTextEnd();\n\t}\n\n\tprivate void removeInvalidSelections () {\n\t\tif (selectionMode == SelectionMode.FILES) {\n\t\t\tIterator<FileItem> it = selectedItems.iterator();\n\t\t\twhile (it.hasNext()) {\n\t\t\t\tFileItem item = it.next();\n\n\t\t\t\tif (item.file.isDirectory()) {\n\t\t\t\t\titem.deselect(false);\n\t\t\t\t\tit.remove();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (selectionMode == SelectionMode.DIRECTORIES) {\n\t\t\tIterator<FileItem> it = selectedItems.iterator();\n\t\t\twhile (it.hasNext()) {\n\t\t\t\tFileItem item = it.next();\n\n\t\t\t\tif (item.file.isDirectory() == false) {\n\t\t\t\t\titem.deselect(false);\n\t\t\t\t\tit.remove();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic Mode getMode () {\n\t\treturn mode;\n\t}\n\n\tpublic void setMode (Mode mode) {\n\t\tthis.mode = mode;\n\t\tconfirmButton.setText(mode == Mode.OPEN ? OPEN.get() : SAVE.get());\n\t\trefresh();\n\t}\n\n\tpublic ViewMode getViewMode () {\n\t\treturn viewMode;\n\t}\n\n\tpublic void setViewMode (ViewMode viewMode) {\n\t\tif (this.viewMode == viewMode) return;\n\t\tthis.viewMode = viewMode;\n\t\ticonProvider.viewModeChanged(viewMode);\n\t\trebuildFileList();\n\t}\n\n\tpublic void setDirectory (String directory) {\n\t\tsetDirectory(Gdx.files.absolute(directory), HistoryPolicy.CLEAR);\n\t}\n\n\tpublic void setDirectory (File directory) {\n\t\tsetDirectory(Gdx.files.absolute(directory.getAbsolutePath()), HistoryPolicy.CLEAR);\n\t}\n\n\tpublic void setDirectory (FileHandle directory) {\n\t\tsetDirectory(directory, HistoryPolicy.CLEAR);\n\t}\n\n\t/**\n\t * Changes file chooser active directory.\n\t * Warning: To avoid hanging listing directory is performed asynchronously. In case of passing invalid file handle\n\t * file chooser will fallback to default one.\n\t */\n\t@Override\n\tpublic void setDirectory (FileHandle directory, HistoryPolicy historyPolicy) {\n\t\tif (directory.equals(currentDirectory)) return;\n\t\tif (historyPolicy == HistoryPolicy.ADD) historyManager.historyAdd();\n\n\t\tcurrentDirectory = directory;\n\t\ticonProvider.directoryChanged(directory);\n\n\t\trebuildFileList();\n\n\t\tif (historyPolicy == HistoryPolicy.CLEAR) historyManager.historyClear();\n\n\t\tupdateFavoriteFolderButton();\n\t}\n\n\t@Override\n\tpublic FileHandle getCurrentDirectory () {\n\t\treturn currentDirectory;\n\t}\n\n\tprivate FileHandle getDefaultStartingDirectory () {\n\t\treturn Gdx.files.absolute(System.getProperty(\"user.home\"));\n\t}\n\n\t/** List currently set directory with all active filters */\n\tprivate FileHandle[] listFilteredCurrentDirectory () {\n\t\tFileHandle[] files = currentDirectory.list(fileFilter);\n\t\tif (fileTypeFilter == null || activeFileTypeRule == null) return files;\n\n\t\tFileHandle[] filtered = new FileHandle[files.length];\n\n\t\tint count = 0;\n\t\tfor (FileHandle file : files) {\n\t\t\tif (file.isDirectory() == false && activeFileTypeRule.accept(file) == false) continue;\n\t\t\tfiltered[count++] = file;\n\t\t}\n\n\t\tif (count == 0) return new FileHandle[0];\n\n\t\tFileHandle[] newFiltered = new FileHandle[count];\n\t\tSystem.arraycopy(filtered, 0, newFiltered, 0, count);\n\t\treturn newFiltered;\n\t}\n\n\tpublic FileFilter getFileFilter () {\n\t\treturn fileFilter;\n\t}\n\n\tpublic void setFileFilter (FileFilter fileFilter) {\n\t\tthis.fileFilter = fileFilter;\n\t\trebuildFileList();\n\t}\n\n\t/**\n\t * Sets new {@link FileTypeFilter}. Note that if you modify {@link FileTypeFilter} you must call this method again with\n\t * modified instance to apply changes. Setting file type filter won't have any effect when selection mode is set to\n\t * directories.\n\t */\n\tpublic void setFileTypeFilter (FileTypeFilter fileTypeFilter) {\n\t\tif (fileTypeFilter == null) {\n\t\t\tthis.fileTypeFilter = null;\n\t\t\tthis.activeFileTypeRule = null;\n\t\t} else {\n\t\t\tif (fileTypeFilter.getRules().size == 0)\n\t\t\t\tthrow new IllegalArgumentException(\"FileTypeFilter doesn't have any rules added\");\n\t\t\tthis.fileTypeFilter = new FileTypeFilter(fileTypeFilter);\n\t\t\tthis.activeFileTypeRule = this.fileTypeFilter.getRules().first();\n\t\t}\n\n\t\tupdateFileTypeSelectBox();\n\t\trebuildFileList();\n\t}\n\n\tpublic FileTypeFilter.Rule getActiveFileTypeFilterRule () {\n\t\treturn activeFileTypeRule;\n\t}\n\n\tpublic SelectionMode getSelectionMode () {\n\t\treturn selectionMode;\n\t}\n\n\t/**\n\t * Changes selection mode, also updates the title of this file chooser to match current selection mode (eg. Choose file, Choose\n\t * directory etc.)\n\t */\n\tpublic void setSelectionMode (SelectionMode selectionMode) {\n\t\tif (selectionMode == null) selectionMode = SelectionMode.FILES;\n\t\tthis.selectionMode = selectionMode;\n\n\t\tswitch (selectionMode) {\n\t\t\tcase FILES:\n\t\t\t\tgetTitleLabel().setText(TITLE_CHOOSE_FILES.get());\n\t\t\t\tbreak;\n\t\t\tcase DIRECTORIES:\n\t\t\t\tgetTitleLabel().setText(TITLE_CHOOSE_DIRECTORIES.get());\n\t\t\t\tbreak;\n\t\t\tcase FILES_AND_DIRECTORIES:\n\t\t\t\tgetTitleLabel().setText(TITLE_CHOOSE_FILES_AND_DIRECTORIES.get());\n\t\t\t\tbreak;\n\t\t}\n\t\tupdateFileTypeSelectBox();\n\t\trebuildFileList();\n\t}\n\n\tpublic FileSorting getSorting () {\n\t\treturn sorting.get();\n\t}\n\n\tpublic void setSorting (FileSorting sorting, boolean sortingOrderAscending) {\n\t\tthis.sorting.set(sorting);\n\t\tthis.sortingOrderAscending.set(sortingOrderAscending);\n\t\trebuildFileList();\n\t}\n\n\tpublic void setSorting (FileSorting sorting) {\n\t\tthis.sorting.set(sorting);\n\t\trebuildFileList();\n\t}\n\n\tpublic boolean isSortingOrderAscending () {\n\t\treturn sortingOrderAscending.get();\n\t}\n\n\tpublic void setSortingOrderAscending (boolean sortingOrderAscending) {\n\t\tthis.sortingOrderAscending.set(sortingOrderAscending);\n\t\trebuildFileList();\n\t}\n\n\tpublic void setFavoriteFolderButtonVisible (boolean favoriteFolderButtonVisible) {\n\t\tfavoriteFolderButton.setVisible(favoriteFolderButtonVisible);\n\t}\n\n\tpublic boolean isFavoriteFolderButtonVisible () {\n\t\treturn favoriteFolderButton.isVisible();\n\t}\n\n\tpublic void setViewModeButtonVisible (boolean viewModeButtonVisible) {\n\t\tviewModeButton.setVisible(viewModeButtonVisible);\n\t}\n\n\tpublic boolean isViewModeButtonVisible () {\n\t\treturn viewModeButton.isVisible();\n\t}\n\n\tpublic boolean isMultiSelectionEnabled () {\n\t\treturn multiSelectionEnabled;\n\t}\n\n\tpublic void setMultiSelectionEnabled (boolean multiSelectionEnabled) {\n\t\tthis.multiSelectionEnabled = multiSelectionEnabled;\n\t}\n\n\tpublic void setListener (FileChooserListener newListener) {\n\t\tthis.listener = newListener;\n\t\tif (listener == null) listener = new FileChooserAdapter();\n\t}\n\n\tpublic boolean isShowSelectionCheckboxes () {\n\t\treturn showSelectionCheckboxes;\n\t}\n\n\tpublic void setShowSelectionCheckboxes (boolean showSelectionCheckboxes) {\n\t\tthis.showSelectionCheckboxes = showSelectionCheckboxes;\n\t\trebuildFileList();\n\t}\n\n\tpublic int getMultiSelectKey () {\n\t\treturn multiSelectKey;\n\t}\n\n\t/** @param multiSelectKey from {@link Keys} or {@link FileChooser#DEFAULT_KEY} to restore default */\n\tpublic void setMultiSelectKey (int multiSelectKey) {\n\t\tthis.multiSelectKey = multiSelectKey;\n\t}\n\n\tpublic int getGroupMultiSelectKey () {\n\t\treturn groupMultiSelectKey;\n\t}\n\n\t/** @param groupMultiSelectKey from {@link Keys} or {@link FileChooser#DEFAULT_KEY} to restore default */\n\tpublic void setGroupMultiSelectKey (int groupMultiSelectKey) {\n\t\tthis.groupMultiSelectKey = groupMultiSelectKey;\n\t}\n\n\tprivate boolean isMultiSelectKeyPressed () {\n\t\tif (multiSelectKey == DEFAULT_KEY)\n\t\t\treturn UIUtils.ctrl();\n\t\telse\n\t\t\treturn Gdx.input.isKeyPressed(multiSelectKey);\n\t}\n\n\tprivate boolean isGroupMultiSelectKeyPressed () {\n\t\tif (groupMultiSelectKey == DEFAULT_KEY)\n\t\t\treturn UIUtils.shift();\n\t\telse\n\t\t\treturn Gdx.input.isKeyPressed(groupMultiSelectKey);\n\t}\n\n\tpublic FileChooserStyle getChooserStyle () {\n\t\treturn style;\n\t}\n\n\tpublic Sizes getSizes () {\n\t\treturn sizes;\n\t}\n\n\tprivate Stage getChooserStage () {\n\t\treturn getStage();\n\t}\n\n\t/**\n\t * If false file chooser won't pool directories for changes, adding new files or connecting new drive won't refresh file list.\n\t * This must be called when file chooser is not added to Stage\n\t */\n\tpublic void setWatchingFilesEnabled (boolean watchingFilesEnabled) {\n\t\tif (getChooserStage() != null)\n\t\t\tthrow new IllegalStateException(\"Pooling setting cannot be changed when file chooser is added to Stage!\");\n\n\t\tthis.watchingFilesEnabled = watchingFilesEnabled;\n\t}\n\n\tpublic void setPrefsName (String prefsName) {\n\t\tpreferencesIO = new PreferencesIO(prefsName);\n\t\treloadPreferences(true);\n\t}\n\n\tprivate void reloadPreferences (boolean rebuildUI) {\n\t\tfavorites = preferencesIO.loadFavorites();\n\t\trecentDirectories = preferencesIO.loadRecentDirectories();\n\t\tif (rebuildUI) rebuildShortcutsFavoritesPanel();\n\t}\n\n\t@Override\n\tpublic void draw (Batch batch, float parentAlpha) {\n\t\tsuper.draw(batch, parentAlpha);\n\n\t\tif (shortcutsListRebuildScheduled) rebuildShortcutsList();\n\t\tif (filesListRebuildScheduled) rebuildFileList();\n\t}\n\n\t@Override\n\tprotected void setStage (Stage stage) {\n\t\tsuper.setStage(stage);\n\n\t\tif (stage != null) {\n\t\t\trefresh(true);\n\t\t\trebuildShortcutsFavoritesPanel(); //if by any chance multiple choosers changed favorites\n\t\t\tdeselectAll();\n\t\t\tif (focusFileScrollPaneOnShow) {\n\t\t\t\tstage.setScrollFocus(fileListView.getScrollPane());\n\t\t\t}\n\t\t\tif (focusSelectedFileTextFieldOnShow) {\n\t\t\t\tFocusManager.switchFocus(stage, selectedFileTextField);\n\t\t\t\tstage.setKeyboardFocus(selectedFileTextField);\n\t\t\t}\n\t\t}\n\n\t\tif (watchingFilesEnabled) {\n\t\t\tif (stage != null) {\n\t\t\t\tstartFileWatcher();\n\t\t\t} else {\n\t\t\t\tstopFileWatcher();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void startFileWatcher () {\n\t\tif (fileWatcherThread != null) return;\n\n\t\tfileWatcherThread = new Thread(new Runnable() {\n\t\t\tFile[] lastRoots;\n\n\t\t\tFileHandle lastCurrentDirectory;\n\t\t\tFileHandle[] lastCurrentFiles;\n\n\t\t\t@Override\n\t\t\tpublic void run () {\n\t\t\t\tlastRoots = File.listRoots();\n\n\t\t\t\tlastCurrentDirectory = currentDirectory;\n\t\t\t\tlastCurrentFiles = currentDirectory.list();\n\n\t\t\t\twhile (fileWatcherThread != null) {\n\t\t\t\t\tFile[] roots = File.listRoots();\n\n\t\t\t\t\tif (roots.length != lastRoots.length || Arrays.equals(lastRoots, roots) == false)\n\t\t\t\t\t\tshortcutsListRebuildScheduled = true;\n\n\t\t\t\t\tlastRoots = roots;\n\n\t\t\t\t\t// if current directory changed during pools then our lastCurrentDirectoryFiles list is outdated and we shouldn't\n\t\t\t\t\t// schedule files list rebuild\n\t\t\t\t\tif (lastCurrentDirectory.equals(currentDirectory) == true) {\n\t\t\t\t\t\tFileHandle[] currentFiles = currentDirectory.list();\n\n\t\t\t\t\t\tif (lastCurrentFiles.length != currentFiles.length || Arrays.equals(lastCurrentFiles, currentFiles) == false)\n\t\t\t\t\t\t\tfilesListRebuildScheduled = true;\n\n\t\t\t\t\t\tlastCurrentFiles = currentFiles;\n\t\t\t\t\t} else\n\t\t\t\t\t\tlastCurrentFiles = currentDirectory.list(); // if list is outdated, refresh it\n\n\t\t\t\t\tlastCurrentDirectory = currentDirectory;\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tThread.sleep(FILE_WATCHER_CHECK_DELAY_MILLIS);\n\t\t\t\t\t} catch (InterruptedException ignored) {\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}, \"FileWatcherThread\");\n\n\t\tfileWatcherThread.setDaemon(true);\n\t\tfileWatcherThread.start();\n\t}\n\n\tprivate void stopFileWatcher () {\n\t\tif (fileWatcherThread == null) return;\n\t\tfileWatcherThread.interrupt();\n\t\tfileWatcherThread = null;\n\t}\n\n\tprivate void showNewDirectoryDialog () {\n\t\tDialogs.showInputDialog(getChooserStage(), NEW_DIRECTORY_DIALOG_TITLE.get(), NEW_DIRECTORY_DIALOG_TEXT.get(), true, new InputDialogAdapter() {\n\t\t\t@Override\n\t\t\tpublic void finished (String input) {\n\t\t\t\tif (FileUtils.isValidFileName(input) == false) {\n\t\t\t\t\tDialogs.showErrorDialog(getChooserStage(), NEW_DIRECTORY_DIALOG_ILLEGAL_CHARACTERS.get());\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tfor (FileHandle file : currentDirectory.list()) {\n\t\t\t\t\tif (file.name().equals(input)) {\n\t\t\t\t\t\tDialogs.showErrorDialog(getChooserStage(), NEW_DIRECTORY_DIALOG_ALREADY_EXISTS.get());\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tFileHandle newDir = currentDirectory.child(input);\n\t\t\t\tnewDir.mkdirs();\n\t\t\t\trefresh();\n\t\t\t\thighlightFiles(newDir);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate void showFileDeleteDialog (final FileHandle fileToDelete) {\n\t\tDialogs.showOptionDialog(getChooserStage(), POPUP_TITLE.get(),\n\t\t\t\tfileDeleter.hasTrash() ? CONTEXT_MENU_MOVE_TO_TRASH_WARNING.get() : CONTEXT_MENU_DELETE_WARNING.get(),\n\t\t\t\tOptionDialogType.YES_NO, new OptionDialogAdapter() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void yes () {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tboolean success = fileDeleter.delete(fileToDelete);\n\t\t\t\t\t\t\tif (success == false) {\n\t\t\t\t\t\t\t\tDialogs.showErrorDialog(getChooserStage(), POPUP_DELETE_FILE_FAILED.get());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (IOException e) {\n\t\t\t\t\t\t\tDialogs.showErrorDialog(getChooserStage(), POPUP_DELETE_FILE_FAILED.get(), e);\n\t\t\t\t\t\t\te.printStackTrace();\n\t\t\t\t\t\t}\n\t\t\t\t\t\trefresh();\n\t\t\t\t\t}\n\t\t\t\t});\n\t}\n\n\t/**\n\t * Sets {@link FileChooser.FileDeleter} that will be used for deleting files. You SHOULD NOT set your own file deleter.\n\t * You should use either {@link DefaultFileDeleter} or JNAFileDeleter from vis-ui-contrib project. JNAFileDeleter\n\t * supports moving file to system trash instead of deleting it permanently, however it requires JNA library in your\n\t * project classpath.\n\t */\n\tpublic void setFileDeleter (FileDeleter fileDeleter) {\n\t\tif (fileDeleter == null) throw new IllegalStateException(\"fileDeleter can't be null\");\n\t\tthis.fileDeleter = fileDeleter;\n\t\tfileMenu.fileDeleterChanged(fileDeleter.hasTrash());\n\t}\n\n\tpublic void setIconProvider (FileIconProvider iconProvider) {\n\t\tthis.iconProvider = iconProvider;\n\t\trebuildViewModePopupMenu();\n\t}\n\n\tpublic FileIconProvider getIconProvider () {\n\t\treturn iconProvider;\n\t}\n\n\tpublic static boolean isSaveLastDirectory () {\n\t\treturn saveLastDirectory;\n\t}\n\n\t/**\n\t * @param saveLastDirectory if true then chooser will store last directory user browsed in preferences file. Note that\n\t * this only applies to using chooser between separate app launches. When single instance of chooser is reused in single\n\t * app session then last directory is always remembered. Default is false. This must be called before creating FileChooser.\n\t */\n\tpublic static void setSaveLastDirectory (boolean saveLastDirectory) {\n\t\tFileChooser.saveLastDirectory = saveLastDirectory;\n\t}\n\n\tpublic enum Mode {\n\t\tOPEN, SAVE\n\t}\n\n\tpublic enum SelectionMode {\n\t\tFILES, DIRECTORIES, FILES_AND_DIRECTORIES\n\t}\n\n\tpublic enum FileSorting {\n\t\tNAME(FileUtils.FILE_NAME_COMPARATOR),\n\t\tMODIFIED_DATE(FileUtils.FILE_MODIFIED_DATE_COMPARATOR),\n\t\tSIZE(FileUtils.FILE_SIZE_COMPARATOR);\n\n\t\tprivate final Comparator<FileHandle> comparator;\n\n\t\tFileSorting (Comparator<FileHandle> comparator) {\n\t\t\tthis.comparator = comparator;\n\t\t}\n\t}\n\n\tpublic enum HistoryPolicy {\n\t\tADD, CLEAR, IGNORE\n\t}\n\n\tpublic enum ViewMode {\n\t\tDETAILS(false, VIEW_MODE_DETAILS),\n\n\t\tBIG_ICONS(true, VIEW_MODE_BIG_ICONS),\n\t\tMEDIUM_ICONS(true, VIEW_MODE_MEDIUM_ICONS),\n\t\tSMALL_ICONS(true, VIEW_MODE_SMALL_ICONS),\n\n\t\tLIST(false, VIEW_MODE_LIST);\n\n\t\tprivate final FileChooserText bundleText;\n\t\tprivate final boolean thumbnailMode;\n\n\t\tViewMode (boolean thumbnailMode, FileChooserText bundleText) {\n\t\t\tthis.thumbnailMode = thumbnailMode;\n\t\t\tthis.bundleText = bundleText;\n\t\t}\n\n\t\tpublic String getBundleText () {\n\t\t\treturn bundleText.get();\n\t\t}\n\n\t\tpublic void setupGridGroup (Sizes sizes, GridGroup group) {\n\t\t\tif (isGridMode() == false) return;\n\t\t\tfloat gridSize = getGridSize(sizes);\n\t\t\tif (gridSize < 0) {\n\t\t\t\tthrow new IllegalStateException(\"FileChooser's ViewMode \" + this.toString() + \" has invalid size defined in Sizes. \" +\n\t\t\t\t\t\t\"Expected value greater than 0, got: \" + gridSize + \". Check your skin Sizes definition.\");\n\t\t\t}\n\t\t\tif (this == LIST) {\n\t\t\t\tgroup.setItemSize(gridSize, 22 * sizes.scaleFactor);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tgroup.setItemSize(gridSize);\n\t\t}\n\n\t\tpublic boolean isGridMode () {\n\t\t\treturn isThumbnailMode() || this == LIST;\n\t\t}\n\n\t\tpublic boolean isThumbnailMode () {\n\t\t\treturn thumbnailMode;\n\t\t}\n\n\t\tpublic float getGridSize (Sizes sizes) {\n\t\t\tswitch (this) {\n\t\t\t\tcase DETAILS:\n\t\t\t\t\treturn -1;\n\t\t\t\tcase BIG_ICONS:\n\t\t\t\t\treturn sizes.fileChooserViewModeBigIconsSize;\n\t\t\t\tcase MEDIUM_ICONS:\n\t\t\t\t\treturn sizes.fileChooserViewModeMediumIconsSize;\n\t\t\t\tcase SMALL_ICONS:\n\t\t\t\t\treturn sizes.fileChooserViewModeSmallIconsSize;\n\t\t\t\tcase LIST:\n\t\t\t\t\treturn sizes.fileChooserViewModeListWidthSize;\n\t\t\t\tdefault:\n\t\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Provides icons that will be used for file thumbnail on file list. If not set default is used that supports\n\t * directories and few basic file types. If you want to add your custom icon your should extend {@link DefaultFileIconProvider}\n\t */\n\tpublic interface FileIconProvider {\n\t\t/** @return icon that will be used for this file or null if no icon should be displayed */\n\t\tDrawable provideIcon (FileItem item);\n\n\t\t/**\n\t\t * @return true if this icon provider can supply proper icons for {@link ViewMode#BIG_ICONS}, {@link ViewMode#MEDIUM_ICONS}\n\t\t * and {@link ViewMode#SMALL_ICONS} view modes, false otherwise. If false thumbnail view modes won't be available for selection.\n\t\t */\n\t\tboolean isThumbnailModesSupported ();\n\n\t\tvoid directoryChanged (FileHandle newDirectory);\n\n\t\tvoid viewModeChanged (ViewMode newViewMode);\n\t}\n\n\tpublic static class DefaultFileIconProvider implements FileIconProvider {\n\t\tprotected FileChooser chooser;\n\t\tprotected FileChooserStyle style;\n\n\t\tpublic DefaultFileIconProvider (FileChooser chooser) {\n\t\t\tthis.chooser = chooser;\n\t\t\tthis.style = chooser.style;\n\t\t}\n\n\t\t@Override\n\t\tpublic Drawable provideIcon (FileItem item) {\n\t\t\tif (item.isDirectory()) return getDirIcon(item);\n\t\t\tString ext = item.getFile().extension().toLowerCase();\n\t\t\tif (ext.equals(\"jpg\") || ext.equals(\"jpeg\") || ext.equals(\"png\") || ext.equals(\"bmp\"))\n\t\t\t\treturn getImageIcon(item);\n\t\t\tif (ext.equals(\"wav\") || ext.equals(\"ogg\") || ext.equals(\"mp3\")) return getAudioIcon(item);\n\t\t\tif (ext.equals(\"pdf\")) return getPdfIcon(item);\n\t\t\tif (ext.equals(\"txt\")) return getTextIcon(item);\n\t\t\treturn getDefaultIcon(item);\n\t\t}\n\n\t\tprotected Drawable getDirIcon (FileItem item) {\n\t\t\treturn style.iconFolder;\n\t\t}\n\n\t\tprotected Drawable getImageIcon (FileItem item) {\n\t\t\treturn style.iconFileImage;\n\t\t}\n\n\t\tprotected Drawable getAudioIcon (FileItem item) {\n\t\t\treturn style.iconFileAudio;\n\t\t}\n\n\t\tprotected Drawable getPdfIcon (FileItem item) {\n\t\t\treturn style.iconFilePdf;\n\t\t}\n\n\t\tprotected Drawable getTextIcon (FileItem item) {\n\t\t\treturn style.iconFileText;\n\t\t}\n\n\t\tprotected Drawable getDefaultIcon (FileItem item) {\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isThumbnailModesSupported () {\n\t\t\treturn false;\n\t\t}\n\n\t\t@Override\n\t\tpublic void directoryChanged (FileHandle newDirectory) {\n\n\t\t}\n\n\t\t@Override\n\t\tpublic void viewModeChanged (ViewMode newViewMode) {\n\n\t\t}\n\t}\n\n\tpublic static class DefaultFileFilter implements FileFilter {\n\t\tprivate FileChooser chooser;\n\t\tprivate boolean ignoreChooserSelectionMode = false;\n\n\t\tpublic DefaultFileFilter (FileChooser chooser) {\n\t\t\tthis.chooser = chooser;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean accept (File f) {\n\t\t\tif (f.isHidden()) return false;\n\t\t\tif (chooser.getMode() == Mode.OPEN ? f.canRead() == false : f.canWrite() == false) return false;\n\t\t\tif (ignoreChooserSelectionMode == false && f.isDirectory() == false &&\n\t\t\t\t\tchooser.getSelectionMode() == SelectionMode.DIRECTORIES) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\tpublic boolean isIgnoreChooserSelectionMode () {\n\t\t\treturn ignoreChooserSelectionMode;\n\t\t}\n\n\t\tpublic void setIgnoreChooserSelectionMode (boolean ignoreChooserSelectionMode) {\n\t\t\tthis.ignoreChooserSelectionMode = ignoreChooserSelectionMode;\n\t\t}\n\t}\n\n\tpublic interface FileDeleter {\n\t\tboolean hasTrash ();\n\n\t\tboolean delete (FileHandle file) throws IOException;\n\t}\n\n\tpublic static final class DefaultFileDeleter implements FileDeleter {\n\t\t@Override\n\t\tpublic boolean hasTrash () {\n\t\t\treturn false;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean delete (FileHandle file) {\n\t\t\treturn file.deleteDirectory();\n\t\t}\n\t}\n\n\tprivate class ShowBusyBarTask extends Timer.Task {\n\t\t@Override\n\t\tpublic void run () {\n\t\t\tfileListBusyBar.resetSegment();\n\t\t\tfileListBusyBar.setVisible(true);\n\t\t\tcurrentFiles.clear();\n\t\t\tcurrentFilesMetadata.clear();\n\t\t\tfileListAdapter.itemsChanged();\n\t\t}\n\n\t\t@Override\n\t\tpublic synchronized void cancel () {\n\t\t\tsuper.cancel();\n\t\t\tfileListBusyBar.setVisible(false);\n\t\t}\n\t}\n\n\t/** Internal FileChooser API. */\n\tpublic class FileItem extends Table implements Focusable {\n\t\tprivate FileHandle file;\n\t\tprivate FileHandleMetadata metadata;\n\n\t\tprivate VisCheckBox selectCheckBox;\n\t\tprivate VisImage iconImage;\n\n\t\tpublic FileItem (final FileHandle file, ViewMode viewMode) {\n\t\t\tthis.file = file;\n\t\t\tthis.metadata = currentFilesMetadata.get(file);\n\t\t\tif (metadata == null) metadata = FileHandleMetadata.of(file); //fallback, should not ever happen\n\t\t\tsetTouchable(Touchable.enabled);\n\n\t\t\tVisLabel name = new VisLabel(metadata.name(), viewMode == ViewMode.SMALL_ICONS ? \"small\" : \"default\");\n\t\t\tname.setEllipsis(true);\n\t\t\tDrawable icon = iconProvider.provideIcon(this);\n\n\t\t\tselectCheckBox = new VisCheckBox(\"\");\n\t\t\tselectCheckBox.setFocusBorderEnabled(false);\n\t\t\tselectCheckBox.setProgrammaticChangeEvents(false);\n\t\t\tboolean shouldShowItemShowCheckBox = showSelectionCheckboxes && (\n\t\t\t\t\t(selectionMode == SelectionMode.FILES_AND_DIRECTORIES)\n\t\t\t\t\t\t\t|| (selectionMode == SelectionMode.FILES && metadata.isDirectory() == false)\n\t\t\t\t\t\t\t|| (selectionMode == SelectionMode.DIRECTORIES && metadata.isDirectory())\n\t\t\t);\n\n\t\t\tleft();\n\t\t\tif (viewMode.isThumbnailMode()) {\n\t\t\t\tif (shouldShowItemShowCheckBox) {\n\t\t\t\t\tIconStack stack = new IconStack(iconImage = new VisImage(icon, Scaling.none), selectCheckBox);\n\t\t\t\t\tadd(stack).padTop(3).grow().row();\n\t\t\t\t\tadd(name).minWidth(1);\n\t\t\t\t} else {\n\t\t\t\t\tadd(iconImage = new VisImage(icon, Scaling.none)).padTop(3).grow().row();\n\t\t\t\t\tadd(name).minWidth(1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (shouldShowItemShowCheckBox) add(selectCheckBox).padLeft(3);\n\t\t\t\tadd(iconImage = new VisImage(icon)).padTop(3).minWidth(22 * sizes.scaleFactor);\n\t\t\t\tadd(name).minWidth(1).growX().padRight(10);\n\n\t\t\t\tVisLabel size = new VisLabel(isDirectory() ? \"\" : metadata.readableFileSize(), \"small\");\n\t\t\t\tVisLabel dateLabel = new VisLabel(dateFormat.format(metadata.lastModified()), \"small\");\n\t\t\t\tsize.setAlignment(Align.right);\n\n\t\t\t\tif (viewMode == ViewMode.DETAILS) {\n\t\t\t\t\tmaxDateLabelWidth = Math.max(dateLabel.getWidth(), maxDateLabelWidth);\n\t\t\t\t\tadd(size).right().padRight(isDirectory() ? 0 : 10);\n\t\t\t\t\tadd(dateLabel).padRight(6).width(new Value() {\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic float get (Actor context) {\n\t\t\t\t\t\t\treturn maxDateLabelWidth;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\taddListeners();\n\t\t}\n\n\t\t/**\n\t\t * Updates file item icon, can be used for asynchronous icon loading. Note that icon provided must not return null\n\t\t * even if this item icon will be loaded later.\n\t\t */\n\t\tpublic void setIcon (Drawable icon, Scaling scaling) {\n\t\t\ticonImage.setDrawable(icon);\n\t\t\ticonImage.setScaling(scaling);\n\t\t\ticonImage.invalidateHierarchy();\n\t\t}\n\n\t\tprivate void addListeners () {\n\t\t\taddListener(new InputListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\t\tFocusManager.switchFocus(getChooserStage(), FileItem.this);\n\t\t\t\t\tgetChooserStage().setKeyboardFocus(FileItem.this);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void touchUp (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\t\tif (event.getButton() == Buttons.RIGHT) {\n\t\t\t\t\t\tfileMenu.build(favorites, file);\n\t\t\t\t\t\tfileMenu.showMenu(getChooserStage(), event.getStageX(), event.getStageY());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\t\t\tif (keycode == Keys.FORWARD_DEL) {\n\t\t\t\t\t\tshowFileDeleteDialog(file);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\taddListener(new ClickListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\t\t// very fast selecting and deselecting folder would navigate to that folder\n\t\t\t\t\t// return false will protect against that (tap count won't be increased)\n\t\t\t\t\tif (handleSelectClick(false) == false) return false;\n\n\t\t\t\t\treturn super.touchDown(event, x, y, pointer, button);\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void clicked (InputEvent event, float x, float y) {\n\t\t\t\t\tsuper.clicked(event, x, y);\n\t\t\t\t\tif (getTapCount() == 2 && selectedItems.contains(FileItem.this, true)) {\n\t\t\t\t\t\tif (file.isDirectory()) {\n\t\t\t\t\t\t\tsetDirectory(file, HistoryPolicy.ADD);\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\tselectionFinished();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t});\n\n\t\t\tselectCheckBox.addListener(new InputListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\t\tevent.stop();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t});\n\t\t\tselectCheckBox.addListener(new ChangeListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\tevent.stop();\n\t\t\t\t\thandleSelectClick(true);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tprivate boolean handleSelectClick (boolean checkboxClicked) {\n\t\t\tif (selectedShortcut != null) selectedShortcut.deselect();\n\n\t\t\tif (checkboxClicked) {\n\t\t\t\tif (multiSelectionEnabled == false && selectedItems.contains(FileItem.this, true) == false)\n\t\t\t\t\tdeselectAll();\n\t\t\t} else {\n\t\t\t\tif (multiSelectionEnabled == false || (isMultiSelectKeyPressed() == false && isGroupMultiSelectKeyPressed() == false))\n\t\t\t\t\tdeselectAll();\n\t\t\t}\n\n\t\t\tboolean itemSelected = select();\n\n\t\t\tif (selectedItems.size > 1 && multiSelectionEnabled && isGroupMultiSelectKeyPressed())\n\t\t\t\tselectGroup();\n\n\t\t\tif (selectedItems.size > 1) removeInvalidSelections();\n\n\t\t\tupdateSelectedFileFieldText();\n\n\t\t\treturn itemSelected;\n\t\t}\n\n\t\tprivate void selectGroup () {\n\t\t\tArray<FileItem> actors = fileListAdapter.getOrderedViews();\n\n\t\t\tint thisSelectionIndex = getItemId(actors, FileItem.this);\n\t\t\tint lastSelectionIndex = getItemId(actors, selectedItems.get(selectedItems.size - 2));\n\n\t\t\tint start;\n\t\t\tint end;\n\n\t\t\tif (thisSelectionIndex > lastSelectionIndex) {\n\t\t\t\tstart = lastSelectionIndex;\n\t\t\t\tend = thisSelectionIndex;\n\t\t\t} else {\n\t\t\t\tstart = thisSelectionIndex;\n\t\t\t\tend = lastSelectionIndex;\n\t\t\t}\n\n\t\t\tfor (int i = start; i < end; i++) {\n\t\t\t\tFileItem item = actors.get(i);\n\t\t\t\titem.select(false);\n\t\t\t}\n\t\t}\n\n\t\tprivate int getItemId (Array<FileItem> actors, FileItem item) {\n\t\t\tfor (int i = 0; i < actors.size; i++) {\n\t\t\t\tif (actors.get(i) == item) return i;\n\t\t\t}\n\n\t\t\tthrow new IllegalStateException(\"Item not found in cells\");\n\t\t}\n\n\t\t/** Selects this items, if item is already in selectedList it will be deselected */\n\t\tprivate boolean select () {\n\t\t\treturn select(true);\n\t\t}\n\n\t\tprivate boolean select (boolean deselectIfAlreadySelected) {\n\t\t\tif (deselectIfAlreadySelected && selectedItems.contains(this, true)) {\n\t\t\t\tdeselect();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tsetBackground(style.highlight);\n\t\t\tselectCheckBox.setChecked(true);\n\t\t\tif (selectedItems.contains(this, true) == false) selectedItems.add(this);\n\t\t\treturn true;\n\t\t}\n\n\t\tprivate void deselect () {\n\t\t\tdeselect(true);\n\t\t}\n\n\t\tprivate void deselect (boolean removeFromList) {\n\t\t\tsetBackground((Drawable) null);\n\t\t\tselectCheckBox.setChecked(false);\n\t\t\tif (removeFromList) selectedItems.removeValue(this, true);\n\t\t}\n\n\t\t@Override\n\t\tpublic void focusLost () {\n\n\t\t}\n\n\t\t@Override\n\t\tpublic void focusGained () {\n\n\t\t}\n\n\t\tpublic FileHandle getFile () {\n\t\t\treturn file;\n\t\t}\n\n\t\tpublic boolean isDirectory () {\n\t\t\treturn metadata.isDirectory();\n\t\t}\n\t}\n\n\tprivate class ShortcutItem extends Table implements RootNameListener, Focusable {\n\t\tpublic File file;\n\t\tprivate VisLabel name;\n\n\t\t/** Used only by shortcuts panel */\n\t\tpublic ShortcutItem (final File file, String customName, Drawable icon) {\n\t\t\tthis.file = file;\n\t\t\tname = new VisLabel(customName);\n\t\t\tname.setEllipsis(true);\n\t\t\tadd(new Image(icon)).padTop(3);\n\t\t\tCell<VisLabel> labelCell = add(name).padRight(6);\n\t\t\tlabelCell.width(new Value() {\n\t\t\t\t@Override\n\t\t\t\tpublic float get (Actor context) {\n\t\t\t\t\treturn mainSplitPane.getFirstWidgetBounds().width - 30;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\taddListener();\n\t\t}\n\n\t\tprivate void addListener () {\n\t\t\taddListener(new InputListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\t\tFocusManager.switchFocus(getChooserStage(), ShortcutItem.this);\n\t\t\t\t\tgetChooserStage().setKeyboardFocus(ShortcutItem.this);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void touchUp (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\t\tif (event.getButton() == Buttons.RIGHT) {\n\t\t\t\t\t\tfileMenu.buildForFavorite(favorites, file);\n\t\t\t\t\t\tfileMenu.showMenu(getChooserStage(), event.getStageX(), event.getStageY());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\t\t\tif (keycode == Keys.FORWARD_DEL) {\n\t\t\t\t\t\tFileHandle gdxFile = Gdx.files.absolute(file.getAbsolutePath());\n\t\t\t\t\t\tif (favorites.contains(gdxFile, false)) {\n\t\t\t\t\t\t\tremoveFavorite(gdxFile);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\taddListener(new ClickListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\t\tdeselectAll();\n\t\t\t\t\tupdateSelectedFileFieldText();\n\t\t\t\t\tselect();\n\t\t\t\t\treturn super.touchDown(event, x, y, pointer, button);\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void clicked (InputEvent event, float x, float y) {\n\t\t\t\t\tsuper.clicked(event, x, y);\n\n\t\t\t\t\tif (getTapCount() == 1) {\n\t\t\t\t\t\tFile file = ShortcutItem.this.file;\n\t\t\t\t\t\tif (file.exists() == false) {\n\t\t\t\t\t\t\tshowDialog(POPUP_DIRECTORY_DOES_NOT_EXIST.get());\n\t\t\t\t\t\t\trefresh();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (file.isDirectory()) {\n\t\t\t\t\t\t\tsetDirectory(Gdx.files.absolute(file.getAbsolutePath()), HistoryPolicy.ADD);\n\t\t\t\t\t\t\tgetChooserStage().setScrollFocus(fileListView.getScrollPane());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tpublic void setLabelText (String text) {\n\t\t\tname.setText(text);\n\t\t}\n\n\t\tpublic String getLabelText () {\n\t\t\treturn name.getText().toString();\n\t\t}\n\n\t\tprivate void select () {\n\t\t\tif (selectedShortcut != null) selectedShortcut.deselect();\n\t\t\tselectedShortcut = ShortcutItem.this;\n\t\t\tsetBackground(style.highlight);\n\t\t}\n\n\t\tprivate void deselect () {\n\t\t\tsetBackground((Drawable) null);\n\t\t}\n\n\t\t@Override\n\t\tpublic void setRootName (String newName) {\n\t\t\tsetLabelText(newName);\n\t\t}\n\n\t\t@Override\n\t\tpublic void focusGained () {\n\t\t}\n\n\t\t@Override\n\t\tpublic void focusLost () {\n\t\t}\n\t}\n\n\tprivate static class ShortcutsComparator implements Comparator<Actor> {\n\t\t@Override\n\t\tpublic int compare (Actor o1, Actor o2) {\n\t\t\tShortcutItem s1 = (ShortcutItem) o1;\n\t\t\tShortcutItem s2 = (ShortcutItem) o2;\n\t\t\treturn s1.getLabelText().compareTo(s2.getLabelText());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/FileChooserAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file;\n\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.utils.Array;\n\n/**\n * Empty implementation of {@link FileChooserListener}.\n * @author Kotcrab\n */\npublic class FileChooserAdapter implements FileChooserListener {\n\t@Override\n\tpublic void canceled () {\n\n\t}\n\n\t@Override\n\tpublic void selected (Array<FileHandle> files) {\n\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/FileChooserListener.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file;\n\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.utils.Array;\n\n/**\n * Used to get events from {@link FileChooser}.\n * @author Kotcrab\n */\npublic interface FileChooserListener {\n\t/** Called when user finished selecting files. It is guaranteed that array will contain at least one file. */\n\tvoid selected (Array<FileHandle> files);\n\n\t/** Called when selection dialog was canceled by user. */\n\tvoid canceled ();\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/FileChooserStyle.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file;\n\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.kotcrab.vis.ui.widget.PopupMenu.PopupMenuStyle;\n\n/** @author Kotcrab */\npublic class FileChooserStyle {\n\tpublic PopupMenuStyle popupMenuStyle;\n\n\tpublic Drawable highlight;\n\tpublic Drawable iconArrowLeft;\n\tpublic Drawable iconArrowRight;\n\tpublic Drawable iconFolder;\n\tpublic Drawable iconFolderParent;\n\tpublic Drawable iconFolderStar;\n\tpublic Drawable iconFolderNew;\n\tpublic Drawable iconDrive;\n\tpublic Drawable iconTrash;\n\tpublic Drawable iconStar;\n\tpublic Drawable iconStarOutline;\n\tpublic Drawable iconRefresh;\n\tpublic Drawable iconListSettings;\n\n\tpublic Drawable iconFileText;\n\tpublic Drawable iconFileImage;\n\tpublic Drawable iconFilePdf;\n\tpublic Drawable iconFileAudio;\n\n\tpublic Drawable contextMenuSelectedItem;\n\tpublic Drawable expandDropdown;\n\n\tpublic FileChooserStyle () {\n\t}\n\n\tpublic FileChooserStyle (FileChooserStyle style) {\n\t\tthis.popupMenuStyle = style.popupMenuStyle;\n\t\tthis.highlight = style.highlight;\n\t\tthis.iconArrowLeft = style.iconArrowLeft;\n\t\tthis.iconArrowRight = style.iconArrowRight;\n\t\tthis.iconFolder = style.iconFolder;\n\t\tthis.iconFolderParent = style.iconFolderParent;\n\t\tthis.iconFolderStar = style.iconFolderStar;\n\t\tthis.iconFolderNew = style.iconFolderNew;\n\t\tthis.iconDrive = style.iconDrive;\n\t\tthis.iconTrash = style.iconTrash;\n\t\tthis.iconStar = style.iconStar;\n\t\tthis.iconStarOutline = style.iconStarOutline;\n\t\tthis.iconRefresh = style.iconRefresh;\n\t\tthis.iconListSettings = style.iconListSettings;\n\t\tthis.iconFileText = style.iconFileText;\n\t\tthis.iconFileImage = style.iconFileImage;\n\t\tthis.iconFilePdf = style.iconFilePdf;\n\t\tthis.iconFileAudio = style.iconFileAudio;\n\t\tthis.contextMenuSelectedItem = style.contextMenuSelectedItem;\n\t\tthis.expandDropdown = style.expandDropdown;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/FileTypeFilter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file;\n\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.utils.Array;\n\nimport java.io.FileFilter;\n\n/**\n * FileTypeFilter is used to limit {@link FileChooser} selection only to specified set of extensions. User can use file\n * chooser's select box to select that extension or all types (if it is allowed).\n * <p>\n * This class is not replacement for {@link FileChooser#setFileFilter(FileFilter)}. While the main file chooser\n * filter does general filtering (such as removing hidden or inaccessible files), FileTypeFilter is used to limit extensions\n * of files than user can select.\n * <p>\n * This filter works by adding rules. Each rule has a description (showed in file chooser's filter select box) and a\n * list of extensions that it accepts. During selection user can switch active rule via select box. Additionally each\n * FileTypeFilter can support 'all types allowed' where all files are accepted regardless of their extension.\n * @author Kotcrab\n * @since 1.1.0\n */\npublic class FileTypeFilter {\n\tprivate boolean allTypesAllowed;\n\tprivate Array<Rule> rules = new Array<Rule>();\n\n\tpublic FileTypeFilter (FileTypeFilter other) {\n\t\tthis.allTypesAllowed = other.allTypesAllowed;\n\t\tthis.rules = new Array<Rule>(other.rules);\n\t}\n\n\t/** @param allTypesAllowed if true then user can choose \"All types\" in file chooser's filter select box. In that mode all files are shown */\n\tpublic FileTypeFilter (boolean allTypesAllowed) {\n\t\tthis.allTypesAllowed = allTypesAllowed;\n\t}\n\n\t/**\n\t * Adds new rule to {@link FileTypeFilter}\n\t * @param description rule description used in FileChooser's file type select box\n\t * @param extensions list of extensions without leading dot, eg. 'jpg', 'png' etc.\n\t */\n\tpublic void addRule (String description, String... extensions) {\n\t\trules.add(new Rule(description, extensions));\n\t}\n\n\tpublic Array<Rule> getRules () {\n\t\treturn rules;\n\t}\n\n\t/**\n\t * Controls whether to allow 'all types allowed' mode, where all file types are shown.\n\t * @param allTypesAllowed if true then user can choose \"All types\" in file chooser's filter select box where all files are shown\n\t */\n\tpublic void setAllTypesAllowed (boolean allTypesAllowed) {\n\t\tthis.allTypesAllowed = allTypesAllowed;\n\t}\n\n\tpublic boolean isAllTypesAllowed () {\n\t\treturn allTypesAllowed;\n\t}\n\n\t/** Defines single rule for {@link FileTypeFilter}. Rule instances are immutable. */\n\tpublic static class Rule {\n\t\tprivate final String description;\n\t\tprivate final Array<String> extensions = new Array<String>();\n\t\tprivate final boolean allowAll;\n\n\t\tpublic Rule (String description) {\n\t\t\tif (description == null) throw new IllegalArgumentException(\"description can't be null\");\n\t\t\tthis.description = description;\n\t\t\tthis.allowAll = true;\n\t\t}\n\n\t\tpublic Rule (String description, String... extensionList) {\n\t\t\tif (description == null) throw new IllegalArgumentException(\"description can't be null\");\n\t\t\tif (extensionList == null || extensionList.length == 0)\n\t\t\t\tthrow new IllegalArgumentException(\"extensionList can't be null nor empty\");\n\t\t\tthis.description = description;\n\t\t\tthis.allowAll = false;\n\t\t\tfor (String ext : extensionList) {\n\t\t\t\tif (ext.startsWith(\".\")) ext = ext.substring(1);\n\t\t\t\textensions.add(ext.toLowerCase());\n\t\t\t}\n\t\t}\n\n\t\tpublic boolean accept (FileHandle file) {\n\t\t\tif (allowAll) return true;\n\t\t\tString ext = file.extension().toLowerCase();\n\t\t\treturn extensions.contains(ext, false);\n\t\t}\n\n\t\tpublic String getDescription () {\n\t\t\treturn description;\n\t\t}\n\n\t\t/** @return copy of extension list. */\n\t\tpublic Array<String> getExtensions () {\n\t\t\treturn new Array<String>(extensions);\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString () {\n\t\t\treturn description;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/FileUtils.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.utils.Array;\nimport com.badlogic.gdx.utils.Sort;\nimport com.kotcrab.vis.ui.util.OsUtils;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.lang.reflect.InvocationTargetException;\nimport java.text.DecimalFormat;\nimport java.util.Comparator;\n\n/**\n * File related utils. Note that FileUtils are not available on GWT.\n * @author Kotcrab\n */\npublic class FileUtils {\n\n\tprivate static final String[] UNITS = new String[]{\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"};\n\n\t/** Sorts file by names ignoring upper case */\n\tpublic static final Comparator<FileHandle> FILE_NAME_COMPARATOR = new Comparator<FileHandle>() {\n\t\t@Override\n\t\tpublic int compare (FileHandle f1, FileHandle f2) {\n\t\t\treturn f1.name().toLowerCase().compareTo(f2.name().toLowerCase());\n\t\t}\n\t};\n\n\t/** Sorts file by modified date then by name. */\n\tpublic static final Comparator<FileHandle> FILE_MODIFIED_DATE_COMPARATOR = new Comparator<FileHandle>() {\n\t\t@Override\n\t\tpublic int compare (FileHandle f1, FileHandle f2) {\n\t\t\tlong l1 = f1.lastModified();\n\t\t\tlong l2 = f2.lastModified();\n\t\t\treturn l1 > l2 ? 1 : (l1 == l2 ? FILE_NAME_COMPARATOR.compare(f1, f2) : -1);\n\t\t}\n\t};\n\n\t/** Sorts file by their size then by name. */\n\tpublic static final Comparator<FileHandle> FILE_SIZE_COMPARATOR = new Comparator<FileHandle>() {\n\t\t@Override\n\t\tpublic int compare (FileHandle f1, FileHandle f2) {\n\t\t\tlong l1 = f1.length();\n\t\t\tlong l2 = f2.length();\n\t\t\treturn l1 > l2 ? -1 : (l1 == l2 ? FILE_NAME_COMPARATOR.compare(f1, f2) : 1);\n\t\t}\n\t};\n\n\t/**\n\t * Converts byte file size to human readable, eg:<br>\n\t * 500 becomes 500 B<br>\n\t * 1024 becomes 1 KB<br>\n\t * 123456 becomes 120.6 KB<br>\n\t * 10000000000 becomes 9.3 GB<br>\n\t * Max supported unit is yottabyte (YB).\n\t * @param size file size in bytes.\n\t * @return human readable file size.\n\t */\n\tpublic static String readableFileSize (long size) {\n\t\tif (size <= 0) return \"0 B\";\n\t\tint digitGroups = (int) (Math.log10(size) / Math.log10(1024));\n\t\treturn new DecimalFormat(\"#,##0.#\").format(size / Math.pow(1024, digitGroups)).replace(\",\", \".\") + \" \" + UNITS[digitGroups];\n\t}\n\n\t/**\n\t * Sorts file list, using this rules: directories first, sorted by names ignoring uppercase, then files sorted by names\n\t * ignoring uppercase.\n\t * @param files list to sort\n\t * @return sorted file list\n\t */\n\tpublic static Array<FileHandle> sortFiles (FileHandle[] files) {\n\t\treturn sortFiles(files, FILE_NAME_COMPARATOR);\n\t}\n\n\t/**\n\t * Sorts file list, using this rules: directories first, sorted using provided comparator, then files sorted using provided comparator.\n\t * @param files list to sort\n\t * @param comparator comparator used to sort files and directories list\n\t * @return sorted file list\n\t */\n\tpublic static Array<FileHandle> sortFiles (FileHandle[] files, Comparator<FileHandle> comparator) {\n\t\treturn sortFiles(files, comparator, false);\n\t}\n\n\t/**\n\t * Sorts file list, using this rules: directories first, sorted using provided comparator, then files sorted using provided comparator.\n\t * @param files list to sort\n\t * @param comparator comparator used to sort files list\n\t * @param descending if true then sorted list will be in reversed order\n\t * @return sorted file list\n\t */\n\tpublic static Array<FileHandle> sortFiles (FileHandle[] files, Comparator<FileHandle> comparator, boolean descending) {\n\t\tArray<FileHandle> directoriesList = new Array<FileHandle>();\n\t\tArray<FileHandle> filesList = new Array<FileHandle>();\n\n\t\tfor (FileHandle f : files) {\n\t\t\tif (f.isDirectory()) {\n\t\t\t\tdirectoriesList.add(f);\n\t\t\t} else {\n\t\t\t\tfilesList.add(f);\n\t\t\t}\n\t\t}\n\n\t\tSort sorter = new Sort();\n\t\tsorter.sort(directoriesList, comparator);\n\t\tsorter.sort(filesList, comparator);\n\n\t\tif (descending) {\n\t\t\tdirectoriesList.reverse();\n\t\t\tfilesList.reverse();\n\t\t}\n\n\t\tdirectoriesList.addAll(filesList); // combine lists\n\t\treturn directoriesList;\n\t}\n\n\t/**\n\t * Checks whether given name is valid for current user OS.\n\t * @param name that will be checked\n\t * @return true if name is valid, false otherwise\n\t */\n\tpublic static boolean isValidFileName (String name) {\n\t\ttry {\n\t\t\tif (OsUtils.isWindows()) {\n\t\t\t\tif (name.contains(\">\") || name.contains(\"<\")) return false;\n\t\t\t\tname = name.toLowerCase(); //Windows is case insensitive\n\t\t\t}\n\t\t\treturn new File(name).getCanonicalFile().getName().equals(name);\n\t\t} catch (Exception e) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/** Converts {@link File} to absolute {@link FileHandle}. */\n\tpublic static FileHandle toFileHandle (File file) {\n\t\treturn Gdx.files.absolute(file.getAbsolutePath());\n\t}\n\n\t/** Shows given directory in system explorer window. */\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static void showDirInExplorer (FileHandle dir) throws IOException {\n\t\tFile dirToShow;\n\t\tif (dir.isDirectory()) {\n\t\t\tdirToShow = dir.file();\n\t\t} else {\n\t\t\tdirToShow = dir.parent().file();\n\t\t}\n\n\t\ttry {\n\t\t\t// Using reflection to avoid importing AWT desktop which would trigger Android Lint errors\n\t\t\t// This is desktop only, rarely called, performance drop is negligible\n\t\t\t// Basically 'Desktop.getDesktop().open(dirToShow);'\n\t\t\tClass desktopClass = Class.forName(\"java.awt.Desktop\");\n\t\t\tObject desktop = desktopClass.getMethod(\"getDesktop\").invoke(null);\n\t\t\ttry {\n\t\t\t\t// browseFileDirectory was introduced in JDK 9\n\t\t\t\tdesktopClass.getMethod(\"browseFileDirectory\", File.class).invoke(desktop, dirToShow);\n\t\t\t} catch (NoSuchMethodException | InvocationTargetException e) {\n\t\t\t\t// browseFileDirectory throws UnsupportedOperationException on some platforms, which is then\n\t\t\t\t// wrapped in InvocationTargetException because it's accessed via reflection.\n\t\t\t\t// throw again all other exceptions we didn't expect\n\t\t\t\tif (e instanceof InvocationTargetException && !(e.getCause() instanceof UnsupportedOperationException)) {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t\tdesktopClass.getMethod(\"open\", File.class).invoke(desktop, dirToShow);\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tGdx.app.log(\"VisUI\", \"Can't open file \" + dirToShow.getPath(), e);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/SingleFileChooserListener.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file;\n\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.widget.file.FileChooser.SelectionMode;\n\n/**\n * Implementation of {@link FileChooserListener} that can be used when user picks only one file. Provides convenient\n * {@link #selected(FileHandle)} method. If user picked more than one file (note that chooser must be in multiple select\n * mode for that to happen, see {@link FileChooser#setSelectionMode(SelectionMode)}), that method\n * will be called only for first selected file and remaining files will be ignored.\n * @author Kotcrab\n * @since 1.0.0\n */\npublic abstract class SingleFileChooserListener implements FileChooserListener {\n\t@Override\n\tpublic final void selected (Array<FileHandle> files) {\n\t\tselected(files.first());\n\t}\n\n\t/** Called for first file in selection. See {@link SingleFileChooserListener}. */\n\tprotected abstract void selected (FileHandle file);\n\n\t@Override\n\tpublic void canceled () {\n\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/StreamingFileChooserListener.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file;\n\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.utils.Array;\n\n/**\n * Implementation of {@link FileChooserListener} that streams chooser selection. Provides convenient\n * {@link #selected(FileHandle)} method that will be called for every selected file after user finished choosing files.\n * Before streaming starts {@link #begin()} is called, after streaming has finished {@link #end()} is called.\n * @author Kotcrab\n * @since 1.0.0\n */\npublic abstract class StreamingFileChooserListener implements FileChooserListener {\n\t@Override\n\tpublic final void selected (Array<FileHandle> files) {\n\t\tbegin();\n\n\t\tfor (FileHandle file : files) {\n\t\t\tselected(file);\n\t\t}\n\n\t\tend();\n\t}\n\n\t/**\n\t * Called after user finished selecting files. If user picked multiple files this will be called separately\n\t * for every selected file.\n\t */\n\tpublic abstract void selected (FileHandle file);\n\n\t/** Called after user finished selecting files, before streaming started. */\n\tpublic void begin () {\n\n\t}\n\n\t/** Called after file selection streaming has finished. */\n\tpublic void end () {\n\n\t}\n\n\t@Override\n\tpublic void canceled () {\n\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/AbstractSuggestionPopup.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport com.kotcrab.vis.ui.widget.MenuItem;\nimport com.kotcrab.vis.ui.widget.PopupMenu;\nimport com.kotcrab.vis.ui.widget.file.FileChooser;\n\n/** @author Kotcrab */\npublic class AbstractSuggestionPopup extends PopupMenu {\n\tpublic static final int MAX_SUGGESTIONS = 10;\n\n\tfinal FileChooser chooser;\n\n\tpublic AbstractSuggestionPopup (FileChooser chooser) {\n\t\tsuper(chooser.getChooserStyle().popupMenuStyle);\n\t\tthis.chooser = chooser;\n\t}\n\n\tprotected MenuItem createMenuItem (String name) {\n\t\tMenuItem item = new MenuItem(name);\n\t\titem.getImageCell().size(0);\n\t\titem.getShortcutCell().space(0).pad(0);\n\t\titem.getSubMenuIconCell().size(0).space(0).pad(0);\n\t\treturn item;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/DirsSuggestionPopup.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.Stage;\nimport com.badlogic.gdx.scenes.scene2d.actions.Actions;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.widget.MenuItem;\nimport com.kotcrab.vis.ui.widget.VisTextField;\nimport com.kotcrab.vis.ui.widget.file.FileChooser;\n\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\n\n/** @author Kotcrab */\npublic class DirsSuggestionPopup extends AbstractSuggestionPopup {\n\tprivate final VisTextField pathField;\n\n\tprivate ExecutorService listDirExecutor = Executors.newSingleThreadExecutor(new ServiceThreadFactory(\"FileChooserListDirThread\"));\n\tprivate Future<?> listDirFuture;\n\n\tpublic DirsSuggestionPopup (FileChooser chooser, VisTextField pathField) {\n\t\tsuper(chooser);\n\t\tthis.pathField = pathField;\n\t}\n\n\tpublic void pathFieldKeyTyped (Stage stage, float width) {\n\t\tif (pathField.getText().length() == 0) {\n\t\t\tremove();\n\t\t\treturn;\n\t\t}\n\t\tcreateDirSuggestions(stage, width);\n\t}\n\n\tprivate void createDirSuggestions (final Stage stage, final float width) {\n\t\tfinal String pathFieldText = pathField.getText();\n\t\t//quiet period before listing files takes too long and popup will be removed\n\t\taddAction(Actions.sequence(Actions.delay(0.2f, Actions.removeActor())));\n\n\t\tif (listDirFuture != null) listDirFuture.cancel(true);\n\t\tlistDirFuture = listDirExecutor.submit(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run () {\n\t\t\t\tFileHandle enteredDir = Gdx.files.absolute(pathFieldText);\n\t\t\t\tfinal FileHandle listDir;\n\t\t\t\tfinal String partialPath;\n\t\t\t\tif (enteredDir.exists()) {\n\t\t\t\t\tlistDir = enteredDir;\n\t\t\t\t\tpartialPath = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tlistDir = enteredDir.parent();\n\t\t\t\t\tpartialPath = enteredDir.name();\n\t\t\t\t}\n\n\t\t\t\tfinal FileHandle[] files = listDir.list(chooser.getFileFilter());\n\t\t\t\tif (Thread.currentThread().isInterrupted()) return;\n\t\t\t\tGdx.app.postRunnable(new Runnable() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void run () {\n\t\t\t\t\t\tclearChildren();\n\t\t\t\t\t\tclearActions();\n\t\t\t\t\t\tint suggestions = 0;\n\n\t\t\t\t\t\tfor (final FileHandle file : files) {\n\t\t\t\t\t\t\tif (file.exists() == false || file.isDirectory() == false) continue;\n\t\t\t\t\t\t\tif (file.name().startsWith(partialPath) == false || file.name().equals(partialPath))\n\t\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\t\tMenuItem item = createMenuItem(file.path());\n\t\t\t\t\t\t\titem.getLabel().setEllipsis(true);\n\t\t\t\t\t\t\titem.getLabelCell().width(width - 20);\n\t\t\t\t\t\t\taddItem(item);\n\n\t\t\t\t\t\t\titem.addListener(new ChangeListener() {\n\t\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\t\t\t\t\tchooser.setDirectory(file, FileChooser.HistoryPolicy.ADD);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tsuggestions++;\n\t\t\t\t\t\t\tif (suggestions == MAX_SUGGESTIONS) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (suggestions == 0) {\n\t\t\t\t\t\t\tremove();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tshowMenu(stage, pathField);\n\t\t\t\t\t\tsetWidth(width);\n\t\t\t\t\t\tlayout();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic void showRecentDirectories (Stage stage, Array<FileHandle> recentDirectories, float width) {\n\t\tint suggestions = createRecentDirSuggestions(recentDirectories, width);\n\t\tif (suggestions == 0) {\n\t\t\tremove();\n\t\t\treturn;\n\t\t}\n\t\tshowMenu(stage, pathField);\n\t\tsetWidth(width);\n\t\tlayout();\n\t}\n\n\tprivate int createRecentDirSuggestions (Array<FileHandle> files, float width) {\n\t\tclearChildren();\n\t\tint suggestions = 0;\n\t\tfor (final FileHandle file : files) {\n\t\t\tif (file.exists() == false) continue;\n\n\t\t\tMenuItem item = createMenuItem(file.path());\n\t\t\titem.getLabel().setEllipsis(true);\n\t\t\titem.getLabelCell().width(width - 20);\n\t\t\taddItem(item);\n\n\t\t\titem.addListener(new ChangeListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\tchooser.setDirectory(file, FileChooser.HistoryPolicy.ADD);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tsuggestions++;\n\t\t\tif (suggestions == MAX_SUGGESTIONS) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn suggestions;\n\t}\n}\n\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/DriveCheckerService.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.utils.Array;\n\nimport java.io.File;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\n/**\n * Used to check whether file system root is readable or writeable.\n * @author Kotcrab\n */\npublic class DriveCheckerService {\n\tprivate static DriveCheckerService instance;\n\n\tprivate final ExecutorService pool;\n\n\tprivate Array<File> readableRoots = new Array<File>();\n\tprivate Array<File> writableRoots = new Array<File>();\n\n\tprivate Map<File, ListenerSet> readableListeners = new HashMap<File, ListenerSet>();\n\tprivate Map<File, ListenerSet> writableListeners = new HashMap<File, ListenerSet>();\n\n\tpublic static synchronized DriveCheckerService getInstance () {\n\t\tif (instance == null) instance = new DriveCheckerService();\n\t\treturn instance;\n\t}\n\n\tpublic DriveCheckerService () {\n\t\tpool = Executors.newFixedThreadPool(3, new ServiceThreadFactory(\"DriveStatusChecker\"));\n\n\t\tFile[] roots = File.listRoots();\n\n\t\tfor (File root : roots) {\n\t\t\tprocessRoot(root);\n\t\t}\n\t}\n\n\tprivate void processRoot (final File root) {\n\t\tpool.execute(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run () {\n\t\t\t\tprocessResults(root, root.canRead(), root.canWrite());\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate void processResults (final File root, final boolean readable, final boolean writable) {\n\t\tGdx.app.postRunnable(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run () {\n\t\t\t\tif (readable) {\n\t\t\t\t\treadableRoots.add(root);\n\t\t\t\t\tListenerSet set = readableListeners.get(root);\n\t\t\t\t\tif (set != null) {\n\t\t\t\t\t\tset.notifyListeners(root, RootMode.READABLE);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (writable) {\n\t\t\t\t\twritableRoots.add(root);\n\t\t\t\t\tListenerSet set = writableListeners.get(root);\n\t\t\t\t\tif (set != null) {\n\t\t\t\t\t\tset.notifyListeners(root, RootMode.WRITABLE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic void addListener (File root, RootMode mode, DriveCheckerListener listener) {\n\t\tswitch (mode) {\n\t\t\tcase READABLE:\n\t\t\t\taddListener(root, mode, listener, readableRoots, readableListeners);\n\t\t\t\tbreak;\n\t\t\tcase WRITABLE:\n\t\t\t\taddListener(root, mode, listener, writableRoots, writableListeners);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate void addListener (File root, RootMode mode, DriveCheckerListener listener, Array<File> cachedRoots, Map<File, ListenerSet> listeners) {\n\t\tif (cachedRoots.contains(root, false)) {\n\t\t\tlistener.rootMode(root, mode);\n\t\t\treturn;\n\t\t}\n\n\t\tListenerSet set = listeners.get(root);\n\n\t\tif (set == null) {\n\t\t\tset = new ListenerSet();\n\t\t\tlisteners.put(root, set);\n\t\t}\n\n\t\tset.add(listener);\n\t\tprocessRoot(root);\n\t}\n\n\tpublic enum RootMode {\n\t\tREADABLE, WRITABLE\n\t}\n\n\tpublic interface DriveCheckerListener {\n\t\tvoid rootMode (File root, RootMode mode);\n\t}\n\n\tpublic class ListenerSet {\n\t\tArray<DriveCheckerListener> list = new Array<DriveCheckerListener>();\n\n\t\tpublic void add (DriveCheckerListener listener) {\n\t\t\tlist.add(listener);\n\t\t}\n\n\t\tpublic void notifyListeners (File root, RootMode mode) {\n\t\t\tIterator<DriveCheckerListener> it = list.iterator();\n\n\t\t\twhile (it.hasNext()) {\n\t\t\t\tDriveCheckerListener listener = it.next();\n\t\t\t\tlistener.rootMode(root, mode);\n\t\t\t\tit.remove();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/FileChooserText.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport com.badlogic.gdx.utils.I18NBundle;\nimport com.kotcrab.vis.ui.Locales;\nimport com.kotcrab.vis.ui.i18n.BundleText;\n\n/**\n * Contains texts for chooser access via I18NBundle.\n * @author Kotcrab\n * @since 0.7.0\n */\npublic enum FileChooserText implements BundleText {\n\tTITLE_CHOOSE_FILES(\"titleChooseFiles\"),\n\tTITLE_CHOOSE_DIRECTORIES(\"titleChooseDirectories\"),\n\tTITLE_CHOOSE_FILES_AND_DIRECTORIES(\"titleChooseFilesAndDirectories\"),\n\n\tCANCEL(\"cancel\"),\n\tFILE_NAME(\"fileName\"),\n\tFILE_TYPE(\"fileType\"),\n\tALL_FILES(\"allFiles\"),\n\tDESKTOP(\"desktop\"),\n\tCOMPUTER(\"computer\"),\n\n\tOPEN(\"open\"),\n\tSAVE(\"save\"),\n\n\tBACK(\"back\"),\n\tFORWARD(\"forward\"),\n\tPARENT_DIRECTORY(\"parentDirectory\"),\n\tNEW_DIRECTORY(\"newDirectory\"),\n\n\tDIRECTORY_NO_LONGER_EXISTS(\"directoryNoLongerExists\"),\n\n\tPOPUP_TITLE(\"popupTitle\"),\n\tPOPUP_CHOOSE_FILE(\"popupChooseFile\"),\n\tPOPUP_SELECTED_FILE_DOES_NOT_EXIST(\"popupSelectedFileDoesNotExist\"),\n\tPOPUP_DIRECTORY_DOES_NOT_EXIST(\"popupDirectoryDoesNotExist\"),\n\tPOPUP_ONLY_DIRECTORIES(\"popupOnlyDirectories\"),\n\tPOPUP_FILENAME_INVALID(\"popupFilenameInvalid\"),\n\tPOPUP_FILE_EXIST_OVERWRITE(\"popupFileExistOverwrite\"),\n\tPOPUP_MULTIPLE_FILE_EXIST_OVERWRITE(\"popupMultipleFileExistOverwrite\"),\n\tPOPUP_DELETE_FILE_FAILED(\"popupDeleteFileFailed\"),\n\n\tCONTEXT_MENU_DELETE(\"contextMenuDelete\"),\n\tCONTEXT_MENU_MOVE_TO_TRASH(\"contextMenuMoveToTrash\"),\n\tCONTEXT_MENU_SHOW_IN_EXPLORER(\"contextMenuShowInExplorer\"),\n\tCONTEXT_MENU_REFRESH(\"contextMenuRefresh\"),\n\tCONTEXT_MENU_ADD_TO_FAVORITES(\"contextMenuAddToFavorites\"),\n\tCONTEXT_MENU_REMOVE_FROM_FAVORITES(\"contextMenuRemoveFromFavorites\"),\n\tCONTEXT_MENU_DELETE_WARNING(\"contextMenuDeleteWarning\"),\n\tCONTEXT_MENU_MOVE_TO_TRASH_WARNING(\"contextMenuMoveToTrashWarning\"),\n\tCONTEXT_MENU_NEW_DIRECTORY(\"contextMenuNewDirectory\"),\n\tCONTEXT_MENU_SORT_BY(\"contextMenuSortBy\"),\n\n\tSORT_BY_NAME(\"sortByName\"),\n\tSORT_BY_DATE(\"sortByDate\"),\n\tSORT_BY_SIZE(\"sortBySize\"),\n\tSORT_BY_ASCENDING(\"sortByAscending\"),\n\tSORT_BY_DESCENDING(\"sortByDescending\"),\n\n\tNEW_DIRECTORY_DIALOG_TITLE(\"newDirectoryDialogTitle\"),\n\tNEW_DIRECTORY_DIALOG_TEXT(\"newDirectoryDialogText\"),\n\tNEW_DIRECTORY_DIALOG_ILLEGAL_CHARACTERS(\"newDirectoryDialogIllegalCharacters\"),\n\tNEW_DIRECTORY_DIALOG_ALREADY_EXISTS(\"newDirectoryDialogAlreadyExists\"),\n\n\tCHANGE_VIEW_MODE(\"changeViewMode\"),\n\tVIEW_MODE_LIST(\"viewModeList\"),\n\tVIEW_MODE_DETAILS(\"viewModeDetails\"),\n\tVIEW_MODE_BIG_ICONS(\"viewModeBigIcons\"),\n\tVIEW_MODE_MEDIUM_ICONS(\"viewModeMediumIcons\"),\n\tVIEW_MODE_SMALL_ICONS(\"viewModeSmallIcons\");\n\n\tprivate final String name;\n\n\tFileChooserText (final String name) {\n\t\tthis.name = name;\n\t}\n\n\tprivate static I18NBundle getBundle () {\n\t\treturn Locales.getFileChooserBundle();\n\t}\n\n\t@Override\n\tpublic final String getName () {\n\t\treturn name;\n\t}\n\n\t@Override\n\tpublic final String get () {\n\t\treturn getBundle().get(name);\n\t}\n\n\t@Override\n\tpublic final String format () {\n\t\treturn getBundle().format(name);\n\t}\n\n\t@Override\n\tpublic final String format (final Object... arguments) {\n\t\treturn getBundle().format(name, arguments);\n\t}\n\n\t@Override\n\tpublic final String toString () {\n\t\treturn get();\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/FileChooserWinService.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.utils.Array;\nimport com.badlogic.gdx.utils.ObjectMap;\nimport com.kotcrab.vis.ui.util.OsUtils;\n\nimport java.io.File;\nimport java.lang.ref.WeakReference;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\n/**\n * Used to get system drive name. Only used on Windows.\n * @author Kotcrab\n */\npublic class FileChooserWinService {\n\tprivate static FileChooserWinService instance;\n\n\tprivate ObjectMap<File, String> nameCache = new ObjectMap<File, String>();\n\n\tprivate Map<File, ListenerSet> listeners = new HashMap<File, ListenerSet>();\n\tprivate final ExecutorService pool;\n\n\tprivate boolean shellFolderSupported = false;\n\tprivate Method getShellFolderMethod;\n\tprivate Method getShellFolderDisplayNameMethod;\n\n\tpublic static synchronized FileChooserWinService getInstance () {\n\t\tif (OsUtils.isWindows() == false) return null;\n\t\tif (instance == null) instance = new FileChooserWinService();\n\t\treturn instance;\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tprotected FileChooserWinService () {\n\t\tpool = Executors.newFixedThreadPool(3, new ServiceThreadFactory(\"SystemDisplayNameGetter\"));\n\n\t\ttry {\n\t\t\tClass shellFolderClass = Class.forName(\"sun.awt.shell.ShellFolder\");\n\t\t\tgetShellFolderMethod = shellFolderClass.getMethod(\"getShellFolder\", File.class);\n\t\t\tgetShellFolderDisplayNameMethod = shellFolderClass.getMethod(\"getDisplayName\");\n\t\t\tshellFolderSupported = true;\n\t\t} catch (ClassNotFoundException ignored) { //ShellFolder not supported on current JVM, ignoring\n\t\t} catch (NoSuchMethodException ignored) {\n\t\t}\n\n\t\tFile[] roots = File.listRoots();\n\n\t\tfor (File root : roots) {\n\t\t\tprocessRoot(root);\n\t\t}\n\t}\n\n\tprivate void processRoot (final File root) {\n\t\tpool.execute(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run () {\n\t\t\t\tprocessResult(root, getSystemDisplayName(root));\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate void processResult (final File root, final String name) {\n\t\tGdx.app.postRunnable(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run () {\n\t\t\t\tif (name != null)\n\t\t\t\t\tnameCache.put(root, name);\n\t\t\t\telse\n\t\t\t\t\tnameCache.put(root, root.toString());\n\n\t\t\t\tListenerSet set = listeners.get(root);\n\t\t\t\tif (set != null) set.notifyListeners(name);\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic void addListener (File root, RootNameListener listener) {\n\t\tString cachedName = nameCache.get(root);\n\t\tif (cachedName != null) {\n\t\t\tlistener.setRootName(cachedName);\n\t\t\treturn;\n\t\t}\n\n\t\tListenerSet set = listeners.get(root);\n\n\t\tif (set == null) {\n\t\t\tset = new ListenerSet();\n\t\t\tlisteners.put(root, set);\n\t\t}\n\n\t\tset.add(listener);\n\t\tprocessRoot(root);\n\t}\n\n\tprivate String getSystemDisplayName (File f) {\n\t\tif (shellFolderSupported == false) return null;\n\t\tString name;\n\n\t\ttry {\n\t\t\t//name = ShellFolder.getShellFolder(f).getDisplayName();\n\t\t\tObject shellFolder = getShellFolderMethod.invoke(null, f);\n\t\t\tname = (String) getShellFolderDisplayNameMethod.invoke(shellFolder);\n\t\t} catch (InvocationTargetException e) {\n\t\t\treturn null;\n\t\t} catch (IllegalAccessException e) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (name == null || name.length() == 0) {\n\t\t\tname = f.getPath(); // the \"/\" directory\n\t\t}\n\n\t\treturn name;\n\t}\n\n\tpublic interface RootNameListener {\n\t\tvoid setRootName (String newName);\n\t}\n\n\tprivate static class ListenerSet {\n\t\tArray<WeakReference<RootNameListener>> list = new Array<WeakReference<RootNameListener>>();\n\n\t\tpublic void add (RootNameListener listener) {\n\t\t\tlist.add(new WeakReference<RootNameListener>(listener));\n\t\t}\n\n\t\tpublic void notifyListeners (String newName) {\n\t\t\tIterator<WeakReference<RootNameListener>> it = list.iterator();\n\n\t\t\twhile (it.hasNext()) {\n\t\t\t\tRootNameListener listener = it.next().get();\n\n\t\t\t\tif (listener == null) {\n\t\t\t\t\tit.remove();\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tlistener.setRootName(newName);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/FileHandleMetadata.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport com.badlogic.gdx.files.FileHandle;\nimport com.kotcrab.vis.ui.widget.file.FileUtils;\n\npublic class FileHandleMetadata {\n\tprivate final String name;\n\tprivate final boolean directory;\n\tprivate final long lastModified;\n\tprivate final long length;\n\tprivate final String readableFileSize;\n\n\tpublic static FileHandleMetadata of (FileHandle file) {\n\t\treturn new FileHandleMetadata(file);\n\t}\n\n\tprivate FileHandleMetadata (FileHandle file) {\n\t\tthis.name = file.name();\n\t\tthis.directory = file.isDirectory();\n\t\tthis.lastModified = file.lastModified();\n\t\tthis.length = file.length();\n\t\tthis.readableFileSize = FileUtils.readableFileSize(length);\n\t}\n\n\tpublic String name () {\n\t\treturn name;\n\t}\n\n\tpublic boolean isDirectory () {\n\t\treturn directory;\n\t}\n\n\tpublic long lastModified () {\n\t\treturn lastModified;\n\t}\n\n\tpublic long length () {\n\t\treturn length;\n\t}\n\n\tpublic String readableFileSize () {\n\t\treturn readableFileSize;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/FileHistoryManager.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport com.badlogic.gdx.Input.Buttons;\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.Stage;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.util.dialog.Dialogs;\nimport com.kotcrab.vis.ui.widget.VisImageButton;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.file.FileChooser;\nimport com.kotcrab.vis.ui.widget.file.FileChooser.HistoryPolicy;\nimport com.kotcrab.vis.ui.widget.file.FileChooserStyle;\n\nimport static com.kotcrab.vis.ui.widget.file.internal.FileChooserText.*;\n\n/**\n * Manages {@link FileChooser} history of directories that user navigated into. This is internal VisUI API however this class\n * is also reused by VisEditor.\n * @author Kotcrab\n */\npublic class FileHistoryManager {\n\tprivate final FileHistoryCallback callback;\n\n\tprivate Array<FileHandle> history = new Array<FileHandle>();\n\tprivate Array<FileHandle> historyForward = new Array<FileHandle>();\n\n\tprivate VisTable buttonsTable;\n\tprivate VisImageButton backButton;\n\tprivate VisImageButton forwardButton;\n\n\tpublic FileHistoryManager (FileChooserStyle style, FileHistoryCallback callback) {\n\t\tthis.callback = callback;\n\t\tbackButton = new VisImageButton(style.iconArrowLeft, BACK.get());\n\t\tbackButton.setGenerateDisabledImage(true);\n\t\tbackButton.setDisabled(true);\n\t\tforwardButton = new VisImageButton(style.iconArrowRight, FORWARD.get());\n\t\tforwardButton.setGenerateDisabledImage(true);\n\t\tforwardButton.setDisabled(true);\n\n\t\tbuttonsTable = new VisTable(true);\n\t\tbuttonsTable.add(backButton);\n\t\tbuttonsTable.add(forwardButton);\n\n\t\tbackButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\thistoryBack();\n\t\t\t}\n\t\t});\n\n\t\tforwardButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\thistoryForward();\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic ClickListener getDefaultClickListener () {\n\t\treturn new ClickListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tif (button == Buttons.BACK || button == Buttons.FORWARD) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn super.touchDown(event, x, y, pointer, button);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void touchUp (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tif (button == Buttons.BACK && hasHistoryBack()) {\n\t\t\t\t\thistoryBack();\n\t\t\t\t} else if (button == Buttons.FORWARD && hasHistoryForward()) {\n\t\t\t\t\thistoryForward();\n\t\t\t\t} else {\n\t\t\t\t\tsuper.touchUp(event, x, y, pointer, button);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tpublic VisTable getButtonsTable () {\n\t\treturn buttonsTable;\n\t}\n\n\tpublic void historyClear () {\n\t\thistory.clear();\n\t\thistoryForward.clear();\n\t\tforwardButton.setDisabled(true);\n\t\tbackButton.setDisabled(true);\n\t}\n\n\tpublic void historyAdd () {\n\t\thistory.add(callback.getCurrentDirectory());\n\t\thistoryForward.clear();\n\t\tbackButton.setDisabled(false);\n\t\tforwardButton.setDisabled(true);\n\t}\n\n\tpublic void historyBack () {\n\t\tFileHandle dir = history.pop();\n\t\thistoryForward.add(callback.getCurrentDirectory());\n\n\t\tif (setDirectoryFromHistory(dir) == false)\n\t\t\thistoryForward.pop();\n\n\t\tif (!hasHistoryBack()) backButton.setDisabled(true);\n\n\t\tforwardButton.setDisabled(false);\n\t}\n\n\tpublic void historyForward () {\n\t\tFileHandle dir = historyForward.pop();\n\t\thistory.add(callback.getCurrentDirectory());\n\n\t\tif (setDirectoryFromHistory(dir) == false)\n\t\t\thistory.pop();\n\n\t\tif (!hasHistoryForward()) forwardButton.setDisabled(true);\n\n\t\tbackButton.setDisabled(false);\n\t}\n\n\tprivate boolean setDirectoryFromHistory (FileHandle dir) {\n\t\tif (dir.exists()) {\n\t\t\tcallback.setDirectory(dir, HistoryPolicy.IGNORE);\n\t\t\treturn true;\n\t\t} else {\n\t\t\tDialogs.showErrorDialog(callback.getStage(), DIRECTORY_NO_LONGER_EXISTS.get());\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/** @return returns {@code true} if a forward-history is available */\n\tprivate boolean hasHistoryForward () {\n\t\treturn historyForward.size != 0;\n\t}\n\n\t/** @return returns {@code true} if a back-history is available */\n\tprivate boolean hasHistoryBack () {\n\t\treturn history.size != 0;\n\t}\n\n\tpublic interface FileHistoryCallback {\n\t\tFileHandle getCurrentDirectory ();\n\n\t\tvoid setDirectory (FileHandle directory, HistoryPolicy policy);\n\n\t\tStage getStage ();\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/FileListAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.utils.Array;\nimport com.badlogic.gdx.utils.ObjectMap;\nimport com.kotcrab.vis.ui.layout.GridGroup;\nimport com.kotcrab.vis.ui.util.adapter.ArrayAdapter;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.file.FileChooser;\n\n/** @author Kotcrab */\npublic class FileListAdapter extends ArrayAdapter<FileHandle, FileChooser.FileItem> {\n\tprivate final FileChooser chooser;\n\tprivate final Array<FileChooser.FileItem> orderedViews = new Array<FileChooser.FileItem>();\n\tprivate GridGroup gridGroup;\n\n\tpublic FileListAdapter (FileChooser chooser, Array<FileHandle> files) {\n\t\tsuper(files);\n\t\tthis.chooser = chooser;\n\t\tgridGroup = new GridGroup(128f, 2f);\n\t}\n\n\t@Override\n\tprotected FileChooser.FileItem createView (FileHandle item) {\n\t\treturn chooser.new FileItem(item, chooser.getViewMode());\n\t}\n\n\t@Override\n\tpublic void fillTable (VisTable itemsTable) {\n\t\tgetViews().clear(); //clear cache\n\t\torderedViews.clear();\n\t\tgridGroup.clear();\n\n\t\tif (getItemsSorter() != null) sort(getItemsSorter());\n\n\t\tFileChooser.ViewMode viewMode = chooser.getViewMode();\n\n\t\tif (viewMode.isGridMode()) {\n\t\t\tviewMode.setupGridGroup(chooser.getSizes(), gridGroup);\n\t\t\tfor (final FileHandle item : iterable()) {\n\t\t\t\tfinal FileChooser.FileItem view = getView(item);\n\t\t\t\torderedViews.add(view);\n\t\t\t\tprepareViewBeforeAddingToTable(item, view);\n\t\t\t\tgridGroup.addActor(view);\n\t\t\t}\n\n\t\t\titemsTable.add(gridGroup).growX().minWidth(0);\n\t\t} else {\n\t\t\tfor (final FileHandle item : iterable()) {\n\t\t\t\tfinal FileChooser.FileItem view = getView(item);\n\t\t\t\torderedViews.add(view);\n\t\t\t\tprepareViewBeforeAddingToTable(item, view);\n\t\t\t\titemsTable.add(view).growX();\n\t\t\t\titemsTable.row();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic ObjectMap<FileHandle, FileChooser.FileItem> getViews () {\n\t\treturn super.getViews();\n\t}\n\n\tpublic Array<FileChooser.FileItem> getOrderedViews () {\n\t\treturn orderedViews;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/FilePopupMenu.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport com.badlogic.gdx.Files.FileType;\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.widget.MenuItem;\nimport com.kotcrab.vis.ui.widget.PopupMenu;\nimport com.kotcrab.vis.ui.widget.file.FileChooser;\nimport com.kotcrab.vis.ui.widget.file.FileChooserStyle;\nimport com.kotcrab.vis.ui.widget.file.FileUtils;\n\nimport java.io.File;\nimport java.io.IOException;\n\nimport static com.kotcrab.vis.ui.widget.file.internal.FileChooserText.*;\n\n/** @author Kotcrab */\npublic class FilePopupMenu extends PopupMenu {\n\tprivate final FileChooserStyle style;\n\n\tprivate SortingPopupMenu sortingPopupMenu;\n\n\tprivate FileHandle file;\n\n\tprivate MenuItem delete;\n\tprivate MenuItem newDirectory;\n\tprivate MenuItem showInExplorer;\n\tprivate MenuItem refresh;\n\tprivate MenuItem addToFavorites;\n\tprivate MenuItem removeFromFavorites;\n\tprivate MenuItem sortBy;\n\n\tpublic FilePopupMenu (final FileChooser chooser, final FilePopupMenuCallback callback) {\n\t\tsuper(chooser.getChooserStyle().popupMenuStyle);\n\t\tthis.style = chooser.getChooserStyle();\n\n\t\tsortingPopupMenu = new SortingPopupMenu(chooser);\n\n\t\tdelete = new MenuItem(CONTEXT_MENU_DELETE.get(), style.iconTrash);\n\t\tnewDirectory = new MenuItem(CONTEXT_MENU_NEW_DIRECTORY.get(), style.iconFolderNew);\n\t\tshowInExplorer = new MenuItem(CONTEXT_MENU_SHOW_IN_EXPLORER.get());\n\t\trefresh = new MenuItem(CONTEXT_MENU_REFRESH.get(), style.iconRefresh);\n\t\taddToFavorites = new MenuItem(CONTEXT_MENU_ADD_TO_FAVORITES.get(), style.iconFolderStar);\n\t\tremoveFromFavorites = new MenuItem(CONTEXT_MENU_REMOVE_FROM_FAVORITES.get(), style.iconFolderStar);\n\t\tsortBy = new MenuItem(CONTEXT_MENU_SORT_BY.get());\n\t\tsortBy.setSubMenu(sortingPopupMenu);\n\n\t\tdelete.addListener(new ClickListener() {\n\t\t\t@Override\n\t\t\tpublic void clicked (InputEvent event, float x, float y) {\n\t\t\t\tcallback.showFileDelDialog(file);\n\t\t\t}\n\t\t});\n\n\t\tnewDirectory.addListener(new ClickListener() {\n\t\t\t@Override\n\t\t\tpublic void clicked (InputEvent event, float x, float y) {\n\t\t\t\tcallback.showNewDirDialog();\n\t\t\t}\n\t\t});\n\n\t\tshowInExplorer.addListener(new ClickListener() {\n\t\t\t@Override\n\t\t\tpublic void clicked (InputEvent event, float x, float y) {\n\t\t\t\ttry {\n\t\t\t\t\tFileUtils.showDirInExplorer(file);\n\t\t\t\t} catch (IOException e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\trefresh.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tchooser.refresh();\n\t\t\t}\n\t\t});\n\n\t\taddToFavorites.addListener(new ClickListener() {\n\t\t\t@Override\n\t\t\tpublic void clicked (InputEvent event, float x, float y) {\n\t\t\t\tchooser.addFavorite(file);\n\t\t\t}\n\t\t});\n\n\t\tremoveFromFavorites.addListener(new ClickListener() {\n\t\t\t@Override\n\t\t\tpublic void clicked (InputEvent event, float x, float y) {\n\t\t\t\tchooser.removeFavorite(file);\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic void build () {\n\t\tsortingPopupMenu.build();\n\t\tclearChildren();\n\t\taddItem(newDirectory);\n\t\taddItem(sortBy);\n\t\taddItem(refresh);\n\t}\n\n\tpublic void build (Array<FileHandle> favorites, FileHandle file) {\n\t\tsortingPopupMenu.build();\n\t\tthis.file = file;\n\n\t\tclearChildren();\n\n\t\taddItem(newDirectory);\n\t\taddItem(sortBy);\n\t\taddItem(refresh);\n\t\taddSeparator();\n\n\t\tif (file.type() == FileType.Absolute || file.type() == FileType.External) addItem(delete);\n\n\t\tif (file.type() == FileType.Absolute) {\n\t\t\taddItem(showInExplorer);\n\n\t\t\tif (file.isDirectory()) {\n\t\t\t\tif (favorites.contains(file, false))\n\t\t\t\t\taddItem(removeFromFavorites);\n\t\t\t\telse\n\t\t\t\t\taddItem(addToFavorites);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void buildForFavorite (Array<FileHandle> favorites, File file) {\n\t\tthis.file = Gdx.files.absolute(file.getAbsolutePath());\n\n\t\tclearChildren();\n\n\t\taddItem(showInExplorer);\n\n\t\tif (favorites.contains(this.file, false)) addItem(removeFromFavorites);\n\t}\n\n\tpublic boolean isAddedToStage () {\n\t\treturn getStage() != null;\n\t}\n\n\tpublic void fileDeleterChanged (boolean trashAvailable) {\n\t\tdelete.setText(trashAvailable ? CONTEXT_MENU_MOVE_TO_TRASH.get() : CONTEXT_MENU_DELETE.get());\n\t}\n\n\tpublic interface FilePopupMenuCallback {\n\t\tvoid showNewDirDialog ();\n\n\t\tvoid showFileDelDialog (FileHandle file);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/FileSuggestionPopup.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.Stage;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.widget.MenuItem;\nimport com.kotcrab.vis.ui.widget.VisTextField;\nimport com.kotcrab.vis.ui.widget.file.FileChooser;\nimport com.kotcrab.vis.ui.widget.file.FileTypeFilter;\n\n/** @author Kotcrab */\npublic class FileSuggestionPopup extends AbstractSuggestionPopup {\n\tpublic FileSuggestionPopup (FileChooser chooser) {\n\t\tsuper(chooser);\n\t}\n\n\tpublic void pathFieldKeyTyped (Stage stage, Array<FileHandle> files, VisTextField pathField) {\n\t\tif (pathField.getText().length() == 0) {\n\t\t\tremove();\n\t\t\treturn;\n\t\t}\n\n\t\tint suggestions = createSuggestions(files, pathField);\n\t\tif (suggestions == 0) {\n\t\t\tremove();\n\t\t\treturn;\n\t\t}\n\n\t\tshowMenu(stage, pathField);\n\t}\n\n\tprivate int createSuggestions (Array<FileHandle> files, final VisTextField fileNameField) {\n\t\tclearChildren();\n\t\tint suggestions = 0;\n\t\tfor (final FileHandle file : files) {\n\t\t\tif (file.name().startsWith(fileNameField.getText()) && file.name().equals(fileNameField.getText()) == false) {\n\t\t\t\tMenuItem item = createMenuItem(getTrimmedName(file.name()));\n\t\t\t\titem.addListener(new ChangeListener() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\t\tchooser.highlightFiles(file);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\taddItem(item);\n\t\t\t\tsuggestions++;\n\t\t\t}\n\n\t\t\tif (suggestions == MAX_SUGGESTIONS) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (chooser.getMode() == FileChooser.Mode.SAVE && suggestions == 0 //don't show matches when there are files that actually exist and matched previous search\n\t\t\t\t&& chooser.getActiveFileTypeFilterRule() != null && fileNameField.getText().matches(\".*\\\\.\")) {\n\t\t\tFileTypeFilter.Rule rule = chooser.getActiveFileTypeFilterRule();\n\n\t\t\tfor (String extension : rule.getExtensions()) {\n\t\t\t\tMenuItem item = createMenuItem(fileNameField.getText() + extension);\n\t\t\t\tfinal String arbitraryPath = fileNameField.getText() + extension;\n\t\t\t\titem.addListener(new ChangeListener() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\t\tfileNameField.setText(arbitraryPath);\n\t\t\t\t\t\tfileNameField.setCursorAtTextEnd();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\taddItem(item);\n\t\t\t\tsuggestions++;\n\t\t\t}\n\t\t}\n\n\t\treturn suggestions;\n\t}\n\n\tprivate String getTrimmedName (String name) {\n\t\tif (name.length() > 40) {\n\t\t\treturn name.substring(0, 40) + \"...\";\n\t\t} else {\n\t\t\treturn name;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/IconStack.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;\nimport com.badlogic.gdx.scenes.scene2d.utils.Layout;\nimport com.badlogic.gdx.utils.SnapshotArray;\nimport com.kotcrab.vis.ui.widget.VisCheckBox;\nimport com.kotcrab.vis.ui.widget.VisImage;\n\n/** @author Kotcrab */\npublic class IconStack extends WidgetGroup {\n\tprivate float prefWidth, prefHeight, minWidth, minHeight, maxWidth, maxHeight;\n\tprivate boolean sizeInvalid = true;\n\tprivate VisImage icon;\n\tprivate VisCheckBox checkBox;\n\n\tpublic IconStack (VisImage icon, VisCheckBox checkBox) {\n\t\tthis.icon = icon;\n\t\tthis.checkBox = checkBox;\n\t\tsetTransform(false);\n\t\tsetTouchable(Touchable.childrenOnly);\n\t\taddActor(icon);\n\t\taddActor(checkBox);\n\t}\n\n\t@Override\n\tpublic void invalidate () {\n\t\tsuper.invalidate();\n\t\tsizeInvalid = true;\n\t}\n\n\tprivate void computeSize () {\n\t\tsizeInvalid = false;\n\t\tprefWidth = 0;\n\t\tprefHeight = 0;\n\t\tminWidth = 0;\n\t\tminHeight = 0;\n\t\tmaxWidth = 0;\n\t\tmaxHeight = 0;\n\t\tSnapshotArray<Actor> children = getChildren();\n\t\tfor (int i = 0, n = children.size; i < n; i++) {\n\t\t\tActor child = children.get(i);\n\t\t\tfloat childMaxWidth, childMaxHeight;\n\t\t\tif (child instanceof Layout) {\n\t\t\t\tLayout layout = (Layout) child;\n\t\t\t\tprefWidth = Math.max(prefWidth, layout.getPrefWidth());\n\t\t\t\tprefHeight = Math.max(prefHeight, layout.getPrefHeight());\n\t\t\t\tminWidth = Math.max(minWidth, layout.getMinWidth());\n\t\t\t\tminHeight = Math.max(minHeight, layout.getMinHeight());\n\t\t\t\tchildMaxWidth = layout.getMaxWidth();\n\t\t\t\tchildMaxHeight = layout.getMaxHeight();\n\t\t\t} else {\n\t\t\t\tprefWidth = Math.max(prefWidth, child.getWidth());\n\t\t\t\tprefHeight = Math.max(prefHeight, child.getHeight());\n\t\t\t\tminWidth = Math.max(minWidth, child.getWidth());\n\t\t\t\tminHeight = Math.max(minHeight, child.getHeight());\n\t\t\t\tchildMaxWidth = 0;\n\t\t\t\tchildMaxHeight = 0;\n\t\t\t}\n\t\t\tif (childMaxWidth > 0) maxWidth = maxWidth == 0 ? childMaxWidth : Math.min(maxWidth, childMaxWidth);\n\t\t\tif (childMaxHeight > 0) maxHeight = maxHeight == 0 ? childMaxHeight : Math.min(maxHeight, childMaxHeight);\n\t\t}\n\t}\n\n\tpublic void add (Actor actor) {\n\t\taddActor(actor);\n\t}\n\n\t@Override\n\tpublic void layout () {\n\t\tif (sizeInvalid) computeSize();\n\t\tfloat width = getWidth(), height = getHeight();\n\t\ticon.setBounds(0, 0, width, height);\n\t\ticon.validate();\n\t\tfloat checkHeight = checkBox.getStyle().checkBackground.getMinHeight();\n\t\tcheckBox.setBounds(3, height - checkHeight - 3, checkBox.getPrefWidth(), checkBox.getPrefHeight());\n\t\tcheckBox.validate();\n\t}\n\n\t@Override\n\tpublic float getPrefWidth () {\n\t\tif (sizeInvalid) computeSize();\n\t\treturn prefWidth;\n\t}\n\n\t@Override\n\tpublic float getPrefHeight () {\n\t\tif (sizeInvalid) computeSize();\n\t\treturn prefHeight;\n\t}\n\n\t@Override\n\tpublic float getMinWidth () {\n\t\tif (sizeInvalid) computeSize();\n\t\treturn minWidth;\n\t}\n\n\t@Override\n\tpublic float getMinHeight () {\n\t\tif (sizeInvalid) computeSize();\n\t\treturn minHeight;\n\t}\n\n\t@Override\n\tpublic float getMaxWidth () {\n\t\tif (sizeInvalid) computeSize();\n\t\treturn maxWidth;\n\t}\n\n\t@Override\n\tpublic float getMaxHeight () {\n\t\tif (sizeInvalid) computeSize();\n\t\treturn maxHeight;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/PreferencesIO.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport com.badlogic.gdx.Files.FileType;\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.Preferences;\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.utils.Array;\nimport com.badlogic.gdx.utils.Json;\n\n/** @author Kotcrab */\npublic class PreferencesIO {\n\tprivate static final String VIS_DEFAULT_PREFS_NAME = \"com.kotcrab.vis.ui.widget.file.filechooser_favorites\";\n\tprivate static String defaultPrefsName = VIS_DEFAULT_PREFS_NAME;\n\n\tprivate String favoritesKeyName = \"favorites\";\n\tprivate String recentDirKeyName = \"recentDirectories\";\n\tprivate String lastDirKeyName = \"lastDirectory\";\n\n\tprivate Preferences prefs;\n\tprivate Json json = new Json();\n\n\tpublic PreferencesIO () {\n\t\tthis(defaultPrefsName);\n\t}\n\n\tpublic PreferencesIO (String prefsName) {\n\t\tprefs = Gdx.app.getPreferences(prefsName);\n\t\tcheckIfUsingDefaultName();\n\t}\n\n\tpublic void checkIfUsingDefaultName () {\n\t\tif (defaultPrefsName.equals(VIS_DEFAULT_PREFS_NAME)) {\n\t\t\tGdx.app.log(\"VisUI\", \"Warning, using default preferences file name for file chooser! (see FileChooser.setDefaultPrefsName(String))\");\n\t\t}\n\t}\n\n\tpublic static void setDefaultPrefsName (String prefsName) {\n\t\tif (prefsName == null) throw new IllegalStateException(\"prefsName can't be null\");\n\t\tPreferencesIO.defaultPrefsName = prefsName;\n\t}\n\n\tpublic Array<FileHandle> loadFavorites () {\n\t\tString data = prefs.getString(favoritesKeyName, null);\n\t\tif (data == null)\n\t\t\treturn new Array<FileHandle>();\n\t\telse\n\t\t\treturn json.fromJson(FileArrayData.class, data).toFileHandleArray();\n\t}\n\n\tpublic void saveFavorites (Array<FileHandle> favorites) {\n\t\tprefs.putString(favoritesKeyName, json.toJson(new FileArrayData(favorites)));\n\t\tprefs.flush();\n\t}\n\n\tpublic Array<FileHandle> loadRecentDirectories () {\n\t\tString data = prefs.getString(recentDirKeyName, null);\n\t\tif (data == null)\n\t\t\treturn new Array<FileHandle>();\n\t\telse\n\t\t\treturn json.fromJson(FileArrayData.class, data).toFileHandleArray();\n\t}\n\n\tpublic void saveRecentDirectories (Array<FileHandle> recentDirs) {\n\t\tprefs.putString(recentDirKeyName, json.toJson(new FileArrayData(recentDirs)));\n\t\tprefs.flush();\n\t}\n\n\tpublic FileHandle loadLastDirectory () {\n\t\tString data = prefs.getString(lastDirKeyName, null);\n\t\tif (data == null) return null;\n\t\treturn json.fromJson(FileHandleData.class, data).toFileHandle();\n\t}\n\n\tpublic void saveLastDirectory (FileHandle file) {\n\t\tprefs.putString(lastDirKeyName, json.toJson(new FileHandleData(file)));\n\t\tprefs.flush();\n\t}\n\n\tprivate static class FileArrayData {\n\t\tpublic Array<FileHandleData> data;\n\n\t\tpublic FileArrayData () {\n\n\t\t}\n\n\t\tpublic FileArrayData (Array<FileHandle> favourites) {\n\t\t\tdata = new Array<FileHandleData>();\n\t\t\tfor (FileHandle file : favourites)\n\t\t\t\tdata.add(new FileHandleData(file));\n\t\t}\n\n\t\tpublic Array<FileHandle> toFileHandleArray () {\n\t\t\tArray<FileHandle> files = new Array<FileHandle>();\n\n\t\t\tfor (FileHandleData fileData : data) {\n\t\t\t\tfiles.add(fileData.toFileHandle());\n\t\t\t}\n\n\t\t\treturn files;\n\t\t}\n\t}\n\n\tprivate static class FileHandleData {\n\t\tpublic FileType type;\n\t\tpublic String path;\n\n\t\tpublic FileHandleData () {\n\t\t}\n\n\t\tpublic FileHandleData (FileHandle file) {\n\t\t\ttype = file.type();\n\t\t\tpath = file.path();\n\t\t}\n\n\t\tpublic FileHandle toFileHandle () {\n\t\t\tswitch (type) {\n\t\t\t\tcase Absolute:\n\t\t\t\t\treturn Gdx.files.absolute(path);\n\t\t\t\tcase Classpath:\n\t\t\t\t\treturn Gdx.files.classpath(path);\n\t\t\t\tcase External:\n\t\t\t\t\treturn Gdx.files.external(path);\n\t\t\t\tcase Internal:\n\t\t\t\t\treturn Gdx.files.internal(path);\n\t\t\t\tcase Local:\n\t\t\t\t\treturn Gdx.files.local(path);\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new IllegalStateException(\"Unknown file type!\");\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/ServiceThreadFactory.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/** @author Kotcrab */\npublic class ServiceThreadFactory implements ThreadFactory {\n\tprivate final AtomicLong count = new AtomicLong(0);\n\tprivate final String threadPrefix;\n\n\tpublic ServiceThreadFactory (String threadPrefix) {\n\t\tsuper();\n\t\tthis.threadPrefix = threadPrefix + \"-\";\n\t}\n\n\t@Override\n\tpublic Thread newThread (Runnable runnable) {\n\t\tThread thread = Executors.defaultThreadFactory().newThread(runnable);\n\t\tthread.setName(threadPrefix + count.getAndIncrement());\n\t\tthread.setDaemon(true);\n\t\treturn thread;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/SortingPopupMenu.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.file.internal;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Image;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.utils.Scaling;\nimport com.kotcrab.vis.ui.widget.MenuItem;\nimport com.kotcrab.vis.ui.widget.PopupMenu;\nimport com.kotcrab.vis.ui.widget.file.FileChooser;\n\nimport static com.kotcrab.vis.ui.widget.file.internal.FileChooserText.*;\n\n/** @author Kotcrab */\npublic class SortingPopupMenu extends PopupMenu {\n\tprivate final FileChooser chooser;\n\tprivate final Drawable selectedMenuItem;\n\n\tprivate MenuItem sortByName;\n\tprivate MenuItem sortByDate;\n\tprivate MenuItem sortBySize;\n\tprivate MenuItem sortByAscending;\n\tprivate MenuItem sortByDescending;\n\n\tprivate Image sortByNameImage;\n\tprivate Image sortByDateImage;\n\tprivate Image sortBySizeImage;\n\tprivate Image sortByAscendingImage;\n\tprivate Image sortByDescendingImage;\n\n\tpublic SortingPopupMenu (final FileChooser chooser) {\n\t\tselectedMenuItem = chooser.getChooserStyle().contextMenuSelectedItem;\n\t\tthis.chooser = chooser;\n\n\t\taddItem(sortByName = new MenuItem(SORT_BY_NAME.get(), selectedMenuItem, new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tchooser.setSorting(FileChooser.FileSorting.NAME, true);\n\t\t\t}\n\t\t}));\n\t\taddItem(sortByDate = new MenuItem(SORT_BY_DATE.get(), selectedMenuItem, new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tchooser.setSorting(FileChooser.FileSorting.MODIFIED_DATE, false);\n\t\t\t}\n\t\t}));\n\t\taddItem(sortBySize = new MenuItem(SORT_BY_SIZE.get(), selectedMenuItem, new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tchooser.setSorting(FileChooser.FileSorting.SIZE, true);\n\t\t\t}\n\t\t}));\n\n\t\taddSeparator();\n\n\t\taddItem(sortByAscending = new MenuItem(SORT_BY_ASCENDING.get(), selectedMenuItem, new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tchooser.setSortingOrderAscending(true);\n\t\t\t}\n\t\t}));\n\t\taddItem(sortByDescending = new MenuItem(SORT_BY_DESCENDING.get(), selectedMenuItem, new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tchooser.setSortingOrderAscending(false);\n\t\t\t}\n\t\t}));\n\n\t\tsortByNameImage = sortByName.getImage();\n\t\tsortByDateImage = sortByDate.getImage();\n\t\tsortBySizeImage = sortBySize.getImage();\n\t\tsortByAscendingImage = sortByAscending.getImage();\n\t\tsortByDescendingImage = sortByDescending.getImage();\n\n\t\tsortByNameImage.setScaling(Scaling.none);\n\t\tsortByDateImage.setScaling(Scaling.none);\n\t\tsortBySizeImage.setScaling(Scaling.none);\n\t\tsortByAscendingImage.setScaling(Scaling.none);\n\t\tsortByDescendingImage.setScaling(Scaling.none);\n\t}\n\n\tpublic void build () {\n\t\tsortByNameImage.setDrawable(null);\n\t\tsortByDateImage.setDrawable(null);\n\t\tsortBySizeImage.setDrawable(null);\n\t\tsortByAscendingImage.setDrawable(null);\n\t\tsortByDescendingImage.setDrawable(null);\n\t\tswitch (chooser.getSorting()) {\n\t\t\tcase NAME:\n\t\t\t\tsortByNameImage.setDrawable(selectedMenuItem);\n\t\t\t\tbreak;\n\t\t\tcase MODIFIED_DATE:\n\t\t\t\tsortByDateImage.setDrawable(selectedMenuItem);\n\t\t\t\tbreak;\n\t\t\tcase SIZE:\n\t\t\t\tsortBySizeImage.setDrawable(selectedMenuItem);\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (chooser.isSortingOrderAscending()) {\n\t\t\tsortByAscendingImage.setDrawable(selectedMenuItem);\n\t\t} else {\n\t\t\tsortByDescendingImage.setDrawable(selectedMenuItem);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/file/internal/package-info.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal FileChooser utilities. All files in this package are not considered as public VisUI API. Changes to those classes\n * won't be listed in CHANGES file.\n * @author Kotcrab\n */\npackage com.kotcrab.vis.ui.widget.file.internal;\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/internal/SplitPaneCursorManager.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.internal;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.graphics.Cursor;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.utils.ClickListener;\nimport com.kotcrab.vis.ui.util.CursorManager;\n\n/**\n * Manages setting custom cursor for split panes.\n * This is VisUI internal class\n * @author Kotcrab\n * @since 1.4.0\n */\npublic abstract class SplitPaneCursorManager extends ClickListener {\n\tprivate Actor owner;\n\tprivate boolean vertical;\n\n\tprivate Cursor.SystemCursor currentCursor;\n\n\tpublic SplitPaneCursorManager (Actor owner, boolean vertical) {\n\t\tthis.owner = owner;\n\t\tthis.vertical = vertical;\n\t}\n\n\t@Override\n\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\treturn handleBoundsContains(x, y);\n\t}\n\n\t@Override\n\tpublic void touchDragged (InputEvent event, float x, float y, int pointer) {\n\t\tsuper.touchDragged(event, x, y, pointer); //handles setting cursor when mouse returned to widget after exiting it while dragged\n\t\tif (contains(x, y)) {\n\t\t\tsetCustomCursor();\n\t\t} else {\n\t\t\tclearCustomCursor();\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean mouseMoved (InputEvent event, float x, float y) {\n\t\tsuper.mouseMoved(event, x, y);\n\t\tif (handleBoundsContains(x, y)) {\n\t\t\tsetCustomCursor();\n\t\t} else {\n\t\t\tclearCustomCursor();\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void exit (InputEvent event, float x, float y, int pointer, Actor toActor) {\n\t\tsuper.exit(event, x, y, pointer, toActor);\n\t\tif (pointer == -1 && (toActor == null || toActor.isDescendantOf(owner) == false)) {\n\t\t\tclearCustomCursor();\n\t\t}\n\t}\n\n\tprivate void setCustomCursor () {\n\t\tCursor.SystemCursor targetCursor;\n\t\tif (vertical) {\n\t\t\ttargetCursor = Cursor.SystemCursor.VerticalResize;\n\t\t} else {\n\t\t\ttargetCursor = Cursor.SystemCursor.HorizontalResize;\n\t\t}\n\n\t\tif (currentCursor != targetCursor) {\n\t\t\tGdx.graphics.setSystemCursor(targetCursor);\n\t\t\tcurrentCursor = targetCursor;\n\t\t}\n\t}\n\n\tprivate void clearCustomCursor () {\n\t\tif (currentCursor != null) {\n\t\t\tCursorManager.restoreDefaultCursor();\n\t\t\tcurrentCursor = null;\n\t\t}\n\t}\n\n\tprotected abstract boolean handleBoundsContains (float x, float y);\n\n\tprotected abstract boolean contains (float x, float y);\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/spinner/AbstractSpinnerModel.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.spinner;\n\n/**\n * Basic implementation of {@link SpinnerModel} simplifying event handling for custom models.\n * @author Kotcrab\n * @see SpinnerModel\n * @see IntSpinnerModel\n * @see FloatSpinnerModel\n * @see SimpleFloatSpinnerModel\n * @see ArraySpinnerModel\n * @since 1.0.2\n */\npublic abstract class AbstractSpinnerModel implements SpinnerModel {\n\tprotected Spinner spinner;\n\n\tprivate boolean allowRebind;\n\tprivate boolean wrap;\n\n\tpublic AbstractSpinnerModel (boolean allowRebind) {\n\t\tthis.allowRebind = allowRebind;\n\t}\n\n\t@Override\n\tpublic void bind (Spinner spinner) {\n\t\tif (this.spinner != null && allowRebind == false)\n\t\t\tthrow new IllegalStateException(\"this spinner model can't be reused\");\n\t\tthis.spinner = spinner;\n\t}\n\n\t/**\n\t * Step model up by one. Event and spinner update will be handled by {@link AbstractSpinnerModel}.\n\t * @return true if value was changed, false otherwise.\n\t */\n\tprotected abstract boolean incrementModel ();\n\n\t/**\n\t * Step model down by one. Event and spinner update will be handled by {@link AbstractSpinnerModel}.\n\t * @return true if value was changed, false otherwise.\n\t */\n\tprotected abstract boolean decrementModel ();\n\n\t@Override\n\tpublic final boolean increment () {\n\t\treturn increment(spinner.isProgrammaticChangeEvents());\n\t}\n\n\t@Override\n\tpublic final boolean increment (boolean fireEvent) {\n\t\tboolean valueChanged = incrementModel();\n\t\tif (valueChanged) spinner.notifyValueChanged(fireEvent);\n\t\treturn valueChanged;\n\t}\n\n\t@Override\n\tpublic final boolean decrement () {\n\t\treturn decrement(spinner.isProgrammaticChangeEvents());\n\t}\n\n\t@Override\n\tpublic final boolean decrement (boolean fireEvent) {\n\t\tboolean valueChanged = decrementModel();\n\t\tif (valueChanged) spinner.notifyValueChanged(fireEvent);\n\t\treturn valueChanged;\n\t}\n\n\t@Override\n\tpublic boolean isWrap () {\n\t\treturn wrap;\n\t}\n\n\t@Override\n\tpublic void setWrap (boolean wrap) {\n\t\tthis.wrap = wrap;\n\t}\n\n\t/** @return true if this model can be reused with different spinner, false otherwise */\n\tpublic boolean isAllowRebind () {\n\t\treturn allowRebind;\n\t}\n\n\tprotected void setAllowRebind (boolean allowRebind) {\n\t\tthis.allowRebind = allowRebind;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/spinner/ArraySpinnerModel.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.spinner;\n\nimport com.badlogic.gdx.math.MathUtils;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.util.InputValidator;\nimport com.kotcrab.vis.ui.widget.VisValidatableTextField;\n\n/**\n * {@link Spinner} model allowing to browse through items from object {@link Array}.\n * <p>\n * Note that this (by default) uses item's toString() method to get string representation of objects used to validate\n * that user has entered valid value which due to {@link VisValidatableTextField} nature has to be done for every\n * entered letter. Item's toString() should cache it's result internally to optimize this check. To customize how string\n * representation is obtained override {@link #itemToString(Object)}.\n * @author Kotcrab\n * @since 1.0.2\n */\npublic class ArraySpinnerModel<T> extends AbstractSpinnerModel {\n\tprivate Array<T> items = new Array<T>();\n\tprivate T current;\n\tprivate int currentIndex;\n\n\t/**\n\t * Creates empty instance with no items set. Note that spinner with empty array model will be always treated as in\n\t * invalid state.\n\t */\n\tpublic ArraySpinnerModel () {\n\t\tsuper(false);\n\t}\n\n\t/**\n\t * Creates new instance of {@link ArraySpinnerModel} using provided items.\n\t * @param items array containing items for the model. It is copied to new array in order to prevent accidental\n\t * modification. Array may be empty however in such case spinner will be always in invalid input state.\n\t */\n\tpublic ArraySpinnerModel (Array<T> items) {\n\t\tsuper(false);\n\t\tthis.items.addAll(items);\n\t}\n\n\t@Override\n\tpublic void bind (Spinner spinner) {\n\t\tsuper.bind(spinner);\n\t\tupdateCurrentItem(0);\n\t\tspinner.getTextField().addValidator(new InputValidator() {\n\t\t\t@Override\n\t\t\tpublic boolean validateInput (String input) {\n\t\t\t\treturn getItemIndexForText(input) != -1;\n\t\t\t}\n\t\t});\n\t\tspinner.notifyValueChanged(true);\n\t}\n\n\t/**\n\t * Creates string representation displayed in {@link Spinner} for given object. By default toString() is used.\n\t * @param item that string representation should be created. It is necessary to check if item is null!\n\t * @return string representation of item\n\t */\n\tprotected String itemToString (T item) {\n\t\tif (item == null) return \"\";\n\t\treturn item.toString();\n\t}\n\n\tprivate int getItemIndexForText (String text) {\n\t\tfor (int i = 0; i < items.size; i++) {\n\t\t\tT item = items.get(i);\n\t\t\tif (itemToString(item).equals(text)) return i;\n\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\t@Override\n\tpublic void textChanged () {\n\t\tString text = spinner.getTextField().getText();\n\t\tint index = getItemIndexForText(text);\n\t\tif (index == -1) return;\n\t\tupdateCurrentItem(index);\n\t}\n\n\t@Override\n\tpublic boolean incrementModel () {\n\t\tif (currentIndex + 1 >= items.size) {\n\t\t\tif (isWrap()) {\n\t\t\t\tupdateCurrentItem(0);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\t\tupdateCurrentItem(currentIndex + 1);\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean decrementModel () {\n\t\tif (currentIndex - 1 < 0) {\n\t\t\tif (isWrap()) {\n\t\t\t\tupdateCurrentItem(items.size - 1);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\t\tupdateCurrentItem(currentIndex - 1);\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String getText () {\n\t\treturn itemToString(current);\n\t}\n\n\t/** Notifies model that items has changed and view must be refreshed. This will trigger a change event. */\n\tpublic void invalidateDataSet () {\n\t\tupdateCurrentItem(MathUtils.clamp(currentIndex, 0, items.size - 1));\n\t\tspinner.notifyValueChanged(true);\n\t}\n\n\t/** @return array containing model items. If you modify returned array you must call {@link #invalidateDataSet()}. */\n\tpublic Array<T> getItems () {\n\t\treturn items;\n\t}\n\n\t/** Changes items of this model. Current index is not preserved. This will trigger a change event. */\n\tpublic void setItems (Array<T> newItems) {\n\t\titems.clear();\n\t\titems.addAll(newItems);\n\t\tcurrentIndex = 0;\n\t\tinvalidateDataSet();\n\t}\n\n\t/** @return current item index or -1 if items array is empty */\n\tpublic int getCurrentIndex () {\n\t\treturn currentIndex;\n\t}\n\n\t/** @return current item or null if items array is empty */\n\tpublic T getCurrent () {\n\t\treturn current;\n\t}\n\n\t/** Sets current item. If array is empty then current value will be set to null. */\n\tpublic void setCurrent (int newIndex) {\n\t\tsetCurrent(newIndex, spinner.isProgrammaticChangeEvents());\n\t}\n\n\t/** Sets current item. If array is empty then current value will be set to null. */\n\tpublic void setCurrent (int newIndex, boolean fireEvent) {\n\t\tupdateCurrentItem(newIndex);\n\t\tspinner.notifyValueChanged(fireEvent);\n\t}\n\n\t/** @param item if does not exist in items array, model item will be set to first item. */\n\tpublic void setCurrent (T item) {\n\t\tsetCurrent(item, spinner.isProgrammaticChangeEvents());\n\t}\n\n\t/** @param item if does not exist in items array, model item will be set to first item. */\n\tpublic void setCurrent (T item, boolean fireEvent) {\n\t\tint index = items.indexOf(item, true);\n\t\tif (index == -1) {\n\t\t\tsetCurrent(0, fireEvent);\n\t\t} else {\n\t\t\tsetCurrent(index, fireEvent);\n\t\t}\n\t}\n\n\tprivate void updateCurrentItem (int newIndex) {\n\t\tif (items.size == 0) {\n\t\t\tcurrent = null;\n\t\t\tcurrentIndex = -1;\n\t\t} else {\n\t\t\tcurrentIndex = newIndex;\n\t\t\tcurrent = items.get(newIndex);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/spinner/FloatSpinnerModel.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.spinner;\n\nimport com.kotcrab.vis.ui.util.*;\nimport com.kotcrab.vis.ui.widget.VisValidatableTextField;\n\nimport java.math.BigDecimal;\n\n/**\n * Spinner model allowing to select float values. Uses {@link BigDecimal} to support high precession and support large numbers.\n * Consider using {@link SimpleFloatSpinnerModel} when such high precision is not needed as it will be faster and simpler to use.\n * @author Kotcrab\n * @see FloatSpinnerModel\n * @see IntSpinnerModel\n * @since 1.0.2\n */\npublic class FloatSpinnerModel extends AbstractSpinnerModel {\n\tprivate InputValidator boundsValidator = new BoundsValidator();\n\tprivate NumberDigitsTextFieldFilter textFieldFilter;\n\n\tprivate BigDecimal max;\n\tprivate BigDecimal min;\n\tprivate BigDecimal step;\n\tprivate BigDecimal current;\n\tprivate int scale = 0;\n\n\tpublic FloatSpinnerModel (String initialValue, String min, String max) {\n\t\tthis(initialValue, min, max, \"1\", 1);\n\t}\n\n\tpublic FloatSpinnerModel (String initialValue, String min, String max, String step) {\n\t\tthis(initialValue, min, max, step, 1);\n\t}\n\n\tpublic FloatSpinnerModel (String initialValue, String min, String max, String step, int scale) {\n\t\tthis(new BigDecimal(initialValue), new BigDecimal(min), new BigDecimal(max), new BigDecimal(step), scale);\n\t}\n\n\tpublic FloatSpinnerModel (BigDecimal initialValue, BigDecimal min, BigDecimal max, BigDecimal step, int scale) {\n\t\tsuper(false);\n\t\tthis.current = initialValue;\n\t\tthis.max = max;\n\t\tthis.min = min;\n\t\tthis.step = step;\n\t\tthis.scale = scale;\n\n\t\tif (this.min.compareTo(this.max) > 0) throw new IllegalArgumentException(\"min can't be > max\");\n\t\tif (this.step.compareTo(BigDecimal.ZERO) <= 0) throw new IllegalArgumentException(\"step must be > 0\");\n\t\tif (scale < 0) throw new IllegalArgumentException(\"scale must be >= 0\");\n\t}\n\n\t@Override\n\tpublic void bind (Spinner spinner) {\n\t\tsuper.bind(spinner);\n\t\tsetScale(scale, false);\n\t\tspinner.notifyValueChanged(true);\n\t}\n\n\t@Override\n\tpublic void textChanged () {\n\t\tString text = spinner.getTextField().getText();\n\t\tif (text.equals(\"\")) {\n\t\t\tcurrent = min.setScale(scale, BigDecimal.ROUND_HALF_UP);\n\t\t} else if (checkInputBounds(text)) {\n\t\t\tcurrent = new BigDecimal(text);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean incrementModel () {\n\t\tif (current.add(step).compareTo(max) > 0) {\n\t\t\tif (current.compareTo(max) == 0) {\n\t\t\t\tif (isWrap()) {\n\t\t\t\t\tcurrent = min.setScale(scale, BigDecimal.ROUND_HALF_UP);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tcurrent = max.setScale(scale, BigDecimal.ROUND_HALF_UP);\n\t\t} else {\n\t\t\tcurrent = current.add(step);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean decrementModel () {\n\t\tif (current.subtract(step).compareTo(min) < 0) {\n\t\t\tif (current.compareTo(min) == 0) {\n\t\t\t\tif (isWrap()) {\n\t\t\t\t\tcurrent = max.setScale(scale, BigDecimal.ROUND_HALF_UP);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tcurrent = min.setScale(scale, BigDecimal.ROUND_HALF_UP);\n\t\t} else {\n\t\t\tcurrent = current.subtract(step);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String getText () {\n\t\treturn current.toPlainString();\n\t}\n\n\tpublic int getScale () {\n\t\treturn scale;\n\t}\n\n\t/**\n\t * Sets scale of this selector. Scale defines how many digits after decimal point can be entered. By default\n\t * this is set to 0, meaning that only integers are allowed. Setting scale to 1 would allow 0.0, scale = 2 would\n\t * allow 0.00 and etc.\n\t */\n\tpublic void setScale (final int scale) {\n\t\tsetScale(scale, true);\n\t}\n\n\tprivate void setScale (final int scale, boolean notifySpinner) {\n\t\tif (scale < 0) throw new IllegalStateException(\"Scale can't be < 0\");\n\t\tthis.scale = scale;\n\t\tcurrent = current.setScale(scale, BigDecimal.ROUND_HALF_UP);\n\n\t\tVisValidatableTextField valueText = spinner.getTextField();\n\t\tvalueText.getValidators().clear();\n\t\tvalueText.addValidator(boundsValidator); //Both need the bounds check\n\t\tif (scale == 0) {\n\t\t\tvalueText.addValidator(Validators.INTEGERS);\n\t\t\tvalueText.setTextFieldFilter(textFieldFilter = new IntDigitsOnlyFilter(true));\n\t\t} else {\n\t\t\tvalueText.addValidator(Validators.FLOATS);\n\t\t\tvalueText.addValidator(new InputValidator() {\n\t\t\t\t@Override\n\t\t\t\tpublic boolean validateInput (String input) {\n\t\t\t\t\tint dotIndex = input.indexOf('.');\n\t\t\t\t\tif (dotIndex == -1) return true;\n\t\t\t\t\treturn input.length() - input.indexOf('.') - 1 <= scale;\n\t\t\t\t}\n\t\t\t});\n\t\t\tvalueText.setTextFieldFilter(textFieldFilter = new FloatDigitsOnlyFilter(true));\n\t\t}\n\n\t\ttextFieldFilter.setUseFieldCursorPosition(true);\n\t\tif (min.compareTo(BigDecimal.ZERO) >= 0) {\n\t\t\ttextFieldFilter.setAcceptNegativeValues(false);\n\t\t} else {\n\t\t\ttextFieldFilter.setAcceptNegativeValues(true);\n\t\t}\n\n\t\tif (notifySpinner) {\n\t\t\tspinner.notifyValueChanged(spinner.isProgrammaticChangeEvents());\n\t\t}\n\t}\n\n\tpublic void setValue (BigDecimal newValue) {\n\t\tsetValue(newValue, spinner.isProgrammaticChangeEvents());\n\t}\n\n\tpublic void setValue (BigDecimal newValue, boolean fireEvent) {\n\t\tif (newValue.compareTo(max) > 0) {\n\t\t\tcurrent = max.setScale(scale, BigDecimal.ROUND_HALF_UP);\n\t\t} else if (newValue.compareTo(min) < 0) {\n\t\t\tcurrent = min.setScale(scale, BigDecimal.ROUND_HALF_UP);\n\t\t} else {\n\t\t\tcurrent = newValue.setScale(scale, BigDecimal.ROUND_HALF_UP);\n\t\t}\n\n\t\tspinner.notifyValueChanged(fireEvent);\n\t}\n\n\tpublic BigDecimal getValue () {\n\t\treturn current;\n\t}\n\n\tpublic BigDecimal getMin () {\n\t\treturn min;\n\t}\n\n\t/** Sets min value. If current is lesser than min, the current value is set to min value */\n\tpublic void setMin (BigDecimal min) {\n\t\tif (min.compareTo(max) > 0) throw new IllegalArgumentException(\"min can't be > max\");\n\n\t\tthis.min = min;\n\n\t\tif (min.compareTo(BigDecimal.ZERO) >= 0) {\n\t\t\ttextFieldFilter.setAcceptNegativeValues(false);\n\t\t} else {\n\t\t\ttextFieldFilter.setAcceptNegativeValues(true);\n\t\t}\n\n\t\tif (current.compareTo(min) < 0) {\n\t\t\tcurrent = min.setScale(scale, BigDecimal.ROUND_HALF_UP);\n\t\t\tspinner.notifyValueChanged(spinner.isProgrammaticChangeEvents());\n\t\t}\n\t}\n\n\tpublic BigDecimal getMax () {\n\t\treturn max;\n\t}\n\n\t/** Sets max value. If current is greater than max, the current value is set to max value. */\n\tpublic void setMax (BigDecimal max) {\n\t\tif (min.compareTo(max) > 0) throw new IllegalArgumentException(\"min can't be > max\");\n\n\t\tthis.max = max;\n\n\t\tif (current.compareTo(max) > 0) {\n\t\t\tcurrent = max.setScale(scale, BigDecimal.ROUND_HALF_UP);\n\t\t\tspinner.notifyValueChanged(spinner.isProgrammaticChangeEvents());\n\t\t}\n\t}\n\n\tpublic BigDecimal getStep () {\n\t\treturn step;\n\t}\n\n\tpublic void setStep (BigDecimal step) {\n\t\tif (step.compareTo(BigDecimal.ZERO) <= 0) throw new IllegalArgumentException(\"step must be > 0\");\n\t\tthis.step = step;\n\t}\n\n\tprivate boolean checkInputBounds (String input) {\n\t\ttry {\n\t\t\tBigDecimal x = new BigDecimal(input);\n\t\t\treturn x.compareTo(min) >= 0 && x.compareTo(max) <= 0;\n\t\t} catch (NumberFormatException e) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate class BoundsValidator implements InputValidator {\n\t\t@Override\n\t\tpublic boolean validateInput (String input) {\n\t\t\treturn checkInputBounds(input);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/spinner/IntSpinnerModel.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.spinner;\n\nimport com.kotcrab.vis.ui.util.InputValidator;\nimport com.kotcrab.vis.ui.util.IntDigitsOnlyFilter;\nimport com.kotcrab.vis.ui.util.Validators;\nimport com.kotcrab.vis.ui.widget.VisValidatableTextField;\n\n/**\n * Spinner models allowing to select int values.\n * @author Kotcrab\n * @see SimpleFloatSpinnerModel\n * @see FloatSpinnerModel\n * @since 1.0.2\n */\npublic class IntSpinnerModel extends AbstractSpinnerModel {\n\tprivate BoundsValidator boundsValidator = new BoundsValidator();\n\tprivate IntDigitsOnlyFilter textFieldFilter;\n\n\tprivate int max;\n\tprivate int min;\n\tprivate int step;\n\tprivate int current;\n\n\tpublic IntSpinnerModel (int initialValue, int min, int max) {\n\t\tthis(initialValue, min, max, 1);\n\t}\n\n\tpublic IntSpinnerModel (int initialValue, int min, int max, int step) {\n\t\tsuper(false);\n\t\tif (min > max) throw new IllegalArgumentException(\"min can't be > max\");\n\t\tif (step <= 0) throw new IllegalArgumentException(\"step must be > 0\");\n\n\t\tthis.current = initialValue;\n\t\tthis.max = max;\n\t\tthis.min = min;\n\t\tthis.step = step;\n\t}\n\n\t@Override\n\tpublic void bind (Spinner spinner) {\n\t\tsuper.bind(spinner);\n\n\t\tVisValidatableTextField valueText = spinner.getTextField();\n\t\tvalueText.getValidators().clear();\n\t\tvalueText.addValidator(boundsValidator);\n\t\tvalueText.addValidator(Validators.INTEGERS);\n\t\tvalueText.setTextFieldFilter(textFieldFilter = new IntDigitsOnlyFilter(true));\n\n\t\ttextFieldFilter.setUseFieldCursorPosition(true);\n\t\tif (min >= 0) {\n\t\t\ttextFieldFilter.setAcceptNegativeValues(false);\n\t\t} else {\n\t\t\ttextFieldFilter.setAcceptNegativeValues(true);\n\t\t}\n\n\t\tspinner.notifyValueChanged(true);\n\t}\n\n\t@Override\n\tpublic void textChanged () {\n\t\tString text = spinner.getTextField().getText();\n\t\tif (text.equals(\"\")) {\n\t\t\tcurrent = min;\n\t\t} else if (checkInputBounds(text)) {\n\t\t\tcurrent = Integer.parseInt(text);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean incrementModel () {\n\t\tif (current + step > max) {\n\t\t\tif (current == max) {\n\t\t\t\tif (isWrap()) {\n\t\t\t\t\tcurrent = min;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tcurrent = max;\n\t\t} else {\n\t\t\tcurrent += step;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean decrementModel () {\n\t\tif (current - step < min) {\n\t\t\tif (current == min) {\n\t\t\t\tif (isWrap()) {\n\t\t\t\t\tcurrent = max;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tcurrent = min;\n\t\t} else {\n\t\t\tcurrent -= step;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String getText () {\n\t\treturn String.valueOf(current);\n\t}\n\n\tpublic void setValue (int newValue) {\n\t\tsetValue(newValue, spinner.isProgrammaticChangeEvents());\n\t}\n\n\tpublic void setValue (int newValue, boolean fireEvent) {\n\t\tif (newValue > max) {\n\t\t\tcurrent = max;\n\t\t} else if (newValue < min) {\n\t\t\tcurrent = min;\n\t\t} else {\n\t\t\tcurrent = newValue;\n\t\t}\n\n\t\tspinner.notifyValueChanged(fireEvent);\n\t}\n\n\tpublic int getValue () {\n\t\treturn current;\n\t}\n\n\tpublic int getMin () {\n\t\treturn min;\n\t}\n\n\t/** Sets min value. If current is lesser than min, the current value is set to min value. */\n\tpublic void setMin (int min) {\n\t\tif (min > max) throw new IllegalArgumentException(\"min can't be > max\");\n\n\t\tthis.min = min;\n\n\t\tif (min >= 0) {\n\t\t\ttextFieldFilter.setAcceptNegativeValues(false);\n\t\t} else {\n\t\t\ttextFieldFilter.setAcceptNegativeValues(true);\n\t\t}\n\n\t\tif (current < min) {\n\t\t\tcurrent = min;\n\t\t\tspinner.notifyValueChanged(spinner.isProgrammaticChangeEvents());\n\t\t}\n\t}\n\n\tpublic int getMax () {\n\t\treturn max;\n\t}\n\n\t/** Sets max value. If current is greater than max, the current value is set to max value. */\n\tpublic void setMax (int max) {\n\t\tif (min > max) throw new IllegalArgumentException(\"min can't be > max\");\n\n\t\tthis.max = max;\n\n\t\tif (current > max) {\n\t\t\tcurrent = max;\n\t\t\tspinner.notifyValueChanged(spinner.isProgrammaticChangeEvents());\n\t\t}\n\t}\n\n\tpublic int getStep () {\n\t\treturn step;\n\t}\n\n\tpublic void setStep (int step) {\n\t\tif (step <= 0) throw new IllegalArgumentException(\"step must be > 0\");\n\n\t\tthis.step = step;\n\t}\n\n\tprivate boolean checkInputBounds (String input) {\n\t\ttry {\n\t\t\tfloat x = Integer.parseInt(input);\n\t\t\treturn x >= min && x <= max;\n\t\t} catch (NumberFormatException e) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate class BoundsValidator implements InputValidator {\n\t\t@Override\n\t\tpublic boolean validateInput (String input) {\n\t\t\treturn checkInputBounds(input);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/spinner/SimpleFloatSpinnerModel.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.spinner;\n\nimport com.kotcrab.vis.ui.util.*;\nimport com.kotcrab.vis.ui.widget.VisValidatableTextField;\n\nimport java.math.BigDecimal;\n\n/**\n * Spinner models allowing to select float values. Uses float to store values, good for small numbers\n * with low precession. If high precession is required or very big numbers are used then {@link FloatSpinnerModel} should be used.\n * If only ints are needed then {@link IntSpinnerModel} should be used.\n * @author Kotcrab\n * @see FloatSpinnerModel\n * @see IntSpinnerModel\n * @since 1.0.2\n */\npublic class SimpleFloatSpinnerModel extends AbstractSpinnerModel {\n\tprivate InputValidator boundsValidator = new BoundsValidator();\n\tprivate NumberDigitsTextFieldFilter textFieldFilter;\n\n\tprivate float max;\n\tprivate float min;\n\tprivate float step;\n\tprivate float current;\n\tprivate int precision = 0;\n\n\tpublic SimpleFloatSpinnerModel (float initialValue, float min, float max) {\n\t\tthis(initialValue, min, max, 1, 1);\n\t}\n\n\tpublic SimpleFloatSpinnerModel (float initialValue, float min, float max, float step) {\n\t\tthis(initialValue, min, max, step, 1);\n\t}\n\n\tpublic SimpleFloatSpinnerModel (float initialValue, float min, float max, float step, int precision) {\n\t\tsuper(false);\n\t\tif (min > max) throw new IllegalArgumentException(\"min can't be > max\");\n\t\tif (step <= 0) throw new IllegalArgumentException(\"step must be > 0\");\n\t\tif (precision < 0) throw new IllegalArgumentException(\"precision must be >= 0\");\n\n\t\tthis.current = initialValue;\n\t\tthis.max = max;\n\t\tthis.min = min;\n\t\tthis.step = step;\n\t\tthis.precision = precision;\n\t}\n\n\t@Override\n\tpublic void bind (Spinner spinner) {\n\t\tsuper.bind(spinner);\n\t\tsetPrecision(precision, false);\n\t\tspinner.notifyValueChanged(true);\n\t}\n\n\t@Override\n\tpublic void textChanged () {\n\t\tString text = spinner.getTextField().getText();\n\t\tif (text.equals(\"\")) {\n\t\t\tcurrent = min;\n\t\t} else if (checkInputBounds(text)) {\n\t\t\tcurrent = Float.parseFloat(text);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean incrementModel () {\n\t\tif (current + step > max) {\n\t\t\tif (current == max) {\n\t\t\t\tif (isWrap()) {\n\t\t\t\t\tcurrent = min;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tcurrent = max;\n\t\t} else {\n\t\t\tcurrent += step;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean decrementModel () {\n\t\tif (current - step < min) {\n\t\t\tif (current == min) {\n\t\t\t\tif (isWrap()) {\n\t\t\t\t\tcurrent = max;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tcurrent = min;\n\t\t} else {\n\t\t\tthis.current -= step;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String getText () {\n\t\tif (precision >= 1) {\n\t\t\t//dealing with float rounding errors\n\t\t\tBigDecimal bd = new BigDecimal(String.valueOf(current));\n\t\t\tbd = bd.setScale(precision, BigDecimal.ROUND_HALF_UP);\n\t\t\treturn String.valueOf(bd.floatValue());\n\t\t} else {\n\t\t\treturn String.valueOf((int) current);\n\t\t}\n\t}\n\n\tpublic int getPrecision () {\n\t\treturn precision;\n\t}\n\n\t/**\n\t * Sets precision of this selector. Precision defines how many digits after decimal point can be entered. By default\n\t * this is set to 0, meaning that only integers are allowed. Setting precision to 1 would allow 0.0, precision = 2 would\n\t * allow 0.00 and etc.\n\t */\n\tpublic void setPrecision (final int precision) {\n\t\tsetPrecision(precision, true);\n\t}\n\n\tprivate void setPrecision (final int precision, boolean notifySpinner) {\n\t\tif (precision < 0) throw new IllegalStateException(\"Precision can't be < 0\");\n\t\tthis.precision = precision;\n\n\t\tVisValidatableTextField valueText = spinner.getTextField();\n\t\tvalueText.getValidators().clear();\n\t\tvalueText.addValidator(boundsValidator); //Both need the bounds check\n\t\tif (precision == 0) {\n\t\t\tvalueText.addValidator(Validators.INTEGERS);\n\t\t\tvalueText.setTextFieldFilter(textFieldFilter = new IntDigitsOnlyFilter(true));\n\t\t} else {\n\t\t\tvalueText.addValidator(Validators.FLOATS);\n\t\t\tvalueText.addValidator(new InputValidator() {\n\t\t\t\t@Override\n\t\t\t\tpublic boolean validateInput (String input) {\n\t\t\t\t\tint dotIndex = input.indexOf('.');\n\t\t\t\t\tif (dotIndex == -1) return true;\n\t\t\t\t\treturn input.length() - input.indexOf('.') - 1 <= precision;\n\t\t\t\t}\n\t\t\t});\n\t\t\tvalueText.setTextFieldFilter(textFieldFilter = new FloatDigitsOnlyFilter(true));\n\t\t}\n\n\t\ttextFieldFilter.setUseFieldCursorPosition(true);\n\t\tif (min >= 0) {\n\t\t\ttextFieldFilter.setAcceptNegativeValues(false);\n\t\t} else {\n\t\t\ttextFieldFilter.setAcceptNegativeValues(true);\n\t\t}\n\n\t\tif (notifySpinner) {\n\t\t\tspinner.notifyValueChanged(spinner.isProgrammaticChangeEvents());\n\t\t}\n\t}\n\n\tpublic void setValue (float newValue) {\n\t\tsetValue(newValue, spinner.isProgrammaticChangeEvents());\n\t}\n\n\tpublic void setValue (float newValue, boolean fireEvent) {\n\t\tif (newValue > max) {\n\t\t\tcurrent = max;\n\t\t} else if (newValue < min) {\n\t\t\tcurrent = min;\n\t\t} else {\n\t\t\tcurrent = newValue;\n\t\t}\n\n\t\tspinner.notifyValueChanged(fireEvent);\n\t}\n\n\tpublic float getValue () {\n\t\treturn current;\n\t}\n\n\tpublic float getMin () {\n\t\treturn min;\n\t}\n\n\t/** Sets min value, if current is lesser than min, the current value is set to min value */\n\tpublic void setMin (float min) {\n\t\tif (min > max) throw new IllegalArgumentException(\"min can't be > max\");\n\n\t\tthis.min = min;\n\n\t\tif (min >= 0) {\n\t\t\ttextFieldFilter.setAcceptNegativeValues(false);\n\t\t} else {\n\t\t\ttextFieldFilter.setAcceptNegativeValues(true);\n\t\t}\n\n\t\tif (current < min) {\n\t\t\tcurrent = min;\n\t\t\tspinner.notifyValueChanged(spinner.isProgrammaticChangeEvents());\n\t\t}\n\t}\n\n\tpublic float getMax () {\n\t\treturn max;\n\t}\n\n\t/** Sets max value. If current is greater than max, the current value is set to max value. */\n\tpublic void setMax (float max) {\n\t\tif (min > max) throw new IllegalArgumentException(\"min can't be > max\");\n\n\t\tthis.max = max;\n\n\t\tif (current > max) {\n\t\t\tcurrent = max;\n\t\t\tspinner.notifyValueChanged(spinner.isProgrammaticChangeEvents());\n\t\t}\n\t}\n\n\tpublic float getStep () {\n\t\treturn step;\n\t}\n\n\tpublic void setStep (float step) {\n\t\tif (step <= 0) throw new IllegalArgumentException(\"step must be > 0\");\n\n\t\tthis.step = step;\n\t}\n\n\tprivate boolean checkInputBounds (String input) {\n\t\ttry {\n\t\t\tfloat x = Float.parseFloat(input);\n\t\t\treturn x >= min && x <= max;\n\t\t} catch (NumberFormatException e) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate class BoundsValidator implements InputValidator {\n\t\t@Override\n\t\tpublic boolean validateInput (String input) {\n\t\t\treturn checkInputBounds(input);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/spinner/Spinner.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.spinner;\n\nimport com.badlogic.gdx.Input.Keys;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.ui.Cell;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Disableable;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.scenes.scene2d.utils.FocusListener;\nimport com.badlogic.gdx.utils.Pools;\nimport com.badlogic.gdx.utils.Timer;\nimport com.badlogic.gdx.utils.Timer.Task;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.widget.*;\n\n/**\n * Spinner can be used to select number or object using up and down buttons or by entering value into text field.\n * Supports custom models that allows selecting either int, floats or even custom objects.\n * <p>\n * Fires {@link ChangeListener.ChangeEvent} when value has changed however unlike some other widgets canceling the event\n * won't undo value change.\n * @author Kotcrab\n * @see SimpleFloatSpinnerModel\n * @see FloatSpinnerModel\n * @see IntSpinnerModel\n * @see ArraySpinnerModel\n * @since 1.0.2\n */\npublic class Spinner extends VisTable implements Disableable {\n\tprivate final Sizes sizes;\n\n\tprivate SpinnerModel model;\n\n\t//task is shared between two buttons\n\tprivate ButtonRepeatTask buttonRepeatTask = new ButtonRepeatTask();\n\n\tprivate VisImageButton upButton;\n\tprivate VisImageButton downButton;\n\tprivate Cell<VisValidatableTextField> textFieldCell;\n\tprivate Cell<VisLabel> labelCell;\n\n\tprivate TextFieldEventPolicy textFieldEventPolicy = TextFieldEventPolicy.ON_FOCUS_LOST;\n\tprivate boolean programmaticChangeEvents = true;\n\tprivate boolean disabled;\n\n\tpublic Spinner (String name, SpinnerModel model) {\n\t\tthis(\"default\", name, model);\n\t}\n\n\tpublic Spinner (String styleName, String name, SpinnerModel model) {\n\t\tthis(VisUI.getSkin().get(styleName, SpinnerStyle.class), VisUI.getSizes(), name, model);\n\t}\n\n\tpublic Spinner (SpinnerStyle style, Sizes sizes, String name, SpinnerModel model) {\n\t\tthis.sizes = sizes;\n\t\tthis.model = model;\n\n\t\tVisTable buttonsTable = new VisTable();\n\t\tVisValidatableTextField textField = createTextField();\n\t\tupButton = new VisImageButton(style.up);\n\t\tdownButton = new VisImageButton(style.down);\n\t\tbuttonsTable.add(upButton).height(sizes.spinnerButtonHeight).row();\n\t\tbuttonsTable.add(downButton).height(sizes.spinnerButtonHeight);\n\n\t\tlabelCell = add(new VisLabel(\"\"));\n\t\tsetSelectorName(name);\n\n\t\ttextFieldCell = add(textField).height(sizes.spinnerButtonHeight * 2).growX();\n\t\tadd(buttonsTable);\n\n\t\taddButtonsListeners(upButton, downButton);\n\n\t\tmodel.bind(this);\n\t}\n\n\tprivate VisValidatableTextField createTextField () {\n\t\tVisValidatableTextField textField = new VisValidatableTextField() {\n\t\t\t@Override\n\t\t\tpublic float getPrefWidth () {\n\t\t\t\treturn sizes.spinnerFieldSize;\n\t\t\t}\n\t\t};\n\t\ttextField.setRestoreLastValid(true);\n\t\ttextField.setProgrammaticChangeEvents(false);\n\t\taddTextFieldListeners(textField);\n\t\treturn textField;\n\t}\n\n\tpublic void setModel (SpinnerModel model) {\n\t\tthis.model = model;\n\t\ttextFieldCell.setActor(createTextField());\n\t\tmodel.bind(this);\n\t}\n\n\tprivate void addButtonsListeners (VisImageButton upButton, VisImageButton downButton) {\n\t\tupButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tevent.stop();\n\t\t\t\tgetStage().setScrollFocus(getTextField());\n\t\t\t\tincrement(true);\n\t\t\t}\n\t\t});\n\n\t\tdownButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tevent.stop();\n\t\t\t\tgetStage().setScrollFocus(getTextField());\n\t\t\t\tdecrement(true);\n\t\t\t}\n\t\t});\n\n\t\tupButton.addListener(new ButtonInputListener(true));\n\t\tdownButton.addListener(new ButtonInputListener(false));\n\t}\n\n\tprivate void addTextFieldListeners (final VisTextField textField) {\n\t\ttextField.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tevent.stop();\n\t\t\t\tmodel.textChanged();\n\t\t\t\tif (textField.isInputValid() && textFieldEventPolicy == TextFieldEventPolicy.ON_KEY_TYPED) {\n\t\t\t\t\tnotifyValueChanged(true);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\ttextField.addListener(new FocusListener() {\n\t\t\t@Override\n\t\t\tpublic void keyboardFocusChanged (FocusEvent event, Actor actor, boolean focused) {\n\t\t\t\tif (focused == false) {\n\t\t\t\t\tgetStage().setScrollFocus(null);\n\t\t\t\t\tif (textFieldEventPolicy == TextFieldEventPolicy.ON_FOCUS_LOST) {\n\t\t\t\t\t\tnotifyValueChanged(true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\ttextField.addListener(new InputListener() {\n\t\t\t@Override\n\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\tgetStage().setScrollFocus(getTextField());\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean scrolled (InputEvent event, float x, float y, float amountX, float amountY) {\n\t\t\t\tif (disabled) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif (amountY >= 1) {\n\t\t\t\t\tdecrement(true);\n\t\t\t\t} else if (amountY <= -1) {\n\t\t\t\t\tincrement(true);\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\t\tif (keycode == Keys.ENTER) {\n\t\t\t\t\tnotifyValueChanged(true);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void setDisabled (boolean disabled) {\n\t\tthis.disabled = disabled;\n\t\tupButton.setDisabled(disabled);\n\t\tdownButton.setDisabled(disabled);\n\t\tgetTextField().setDisabled(disabled);\n\t}\n\n\t@Override\n\tpublic boolean isDisabled () {\n\t\treturn disabled;\n\t}\n\n\tpublic void setSelectorName (String name) {\n\t\tlabelCell.getActor().setText(name);\n\t\tif (name == null || name.length() == 0) {\n\t\t\tlabelCell.padRight(0);\n\t\t} else {\n\t\t\tlabelCell.padRight(6);\n\t\t}\n\t}\n\n\tpublic String getSelectorName () {\n\t\treturn labelCell.getActor().getText().toString();\n\t}\n\n\tpublic void increment () {\n\t\tmodel.increment(programmaticChangeEvents);\n\t}\n\n\tprivate void increment (boolean fireEvent) {\n\t\tmodel.increment(fireEvent);\n\t}\n\n\tpublic void decrement () {\n\t\tmodel.decrement(programmaticChangeEvents);\n\t}\n\n\tprivate void decrement (boolean fireEvent) {\n\t\tmodel.decrement(fireEvent);\n\t}\n\n\t/** If false, methods changing spinner value form code won't trigger change event, it will be fired only when user has changed value. */\n\tpublic void setProgrammaticChangeEvents (boolean programmaticChangeEvents) {\n\t\tthis.programmaticChangeEvents = programmaticChangeEvents;\n\t}\n\n\tpublic boolean isProgrammaticChangeEvents () {\n\t\treturn programmaticChangeEvents;\n\t}\n\n\tpublic void setTextFieldEventPolicy (TextFieldEventPolicy textFieldEventPolicy) {\n\t\tthis.textFieldEventPolicy = textFieldEventPolicy;\n\t}\n\n\tpublic TextFieldEventPolicy getTextFieldEventPolicy () {\n\t\treturn textFieldEventPolicy;\n\t}\n\n\tpublic int getMaxLength () {\n\t\treturn getTextField().getMaxLength();\n\t}\n\n\tpublic void setMaxLength (int maxLength) {\n\t\tgetTextField().setMaxLength(maxLength);\n\t}\n\n\tpublic SpinnerModel getModel () {\n\t\treturn model;\n\t}\n\n\t/**\n\t * Called by {@link SpinnerModel}. Notifies when underlying model value has changed and spinner text field must updated.\n\t * Typically there is no need to call this method manually.\n\t * @param fireEvent if true then {@link ChangeListener.ChangeEvent} will be fired\n\t */\n\tpublic void notifyValueChanged (boolean fireEvent) {\n\t\tVisValidatableTextField textField = getTextField();\n\t\tint cursor = textField.getCursorPosition();\n\t\ttextField.setCursorPosition(0);\n\t\ttextField.setText(model.getText());\n\t\ttextField.setCursorPosition(cursor);\n\n\t\tif (fireEvent) {\n\t\t\tChangeListener.ChangeEvent changeEvent = Pools.obtain(ChangeListener.ChangeEvent.class);\n\t\t\tfire(changeEvent);\n\t\t\tPools.free(changeEvent);\n\t\t}\n\t}\n\n\tpublic VisValidatableTextField getTextField () {\n\t\treturn textFieldCell.getActor();\n\t}\n\n\tpublic static class SpinnerStyle {\n\t\tpublic Drawable up;\n\t\tpublic Drawable down;\n\n\t\tpublic SpinnerStyle () {\n\t\t}\n\n\t\tpublic SpinnerStyle (SpinnerStyle style) {\n\t\t\tthis.up = style.up;\n\t\t\tthis.down = style.down;\n\t\t}\n\n\t\tpublic SpinnerStyle (Drawable up, Drawable down) {\n\t\t\tthis.up = up;\n\t\t\tthis.down = down;\n\t\t}\n\t}\n\n\tprivate class ButtonRepeatTask extends Task {\n\t\tboolean advance;\n\n\t\t@Override\n\t\tpublic void run () {\n\t\t\tif (advance) {\n\t\t\t\tincrement(true);\n\t\t\t} else {\n\t\t\t\tdecrement(true);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Allows to configure how {@link Spinner} will fire {@link ChangeListener.ChangeEvent} after user interaction with\n\t * Spinner text field.\n\t * @since 1.1.6\n\t */\n\tpublic enum TextFieldEventPolicy {\n\t\t/**\n\t\t * Spinner change event will be only fired after user has pressed enter in text field. This mode is the default\n\t\t * one prior to VisUI 1.1.6\n\t\t */\n\t\tON_ENTER_ONLY,\n\t\t/**\n\t\t * Spinner change event will be always fired after text field has lost focus and entered value is valid. Note\n\t\t * that event will be fired even if user has not changed actual value of spinner. Event won't be fired\n\t\t * if current model determined that entered value is invalid. This mode is the default one.\n\t\t */\n\t\tON_FOCUS_LOST,\n\t\t/**\n\t\t * Spinner change event will be fired right after user has typed something in the text field and model has\n\t\t * determined that entered value is valid. Event won't be fired if entered value is invalid.\n\t\t */\n\t\tON_KEY_TYPED\n\t}\n\n\tprivate class ButtonInputListener extends InputListener {\n\t\tprivate float buttonRepeatInitialTime = 0.4f;\n\t\tprivate float buttonRepeatTime = 0.08f;\n\n\t\tprivate boolean advance;\n\n\t\tpublic ButtonInputListener (boolean advance) {\n\t\t\tthis.advance = advance;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\tif (buttonRepeatTask.isScheduled() == false) {\n\t\t\t\tbuttonRepeatTask.advance = advance;\n\t\t\t\tbuttonRepeatTask.cancel();\n\t\t\t\tTimer.schedule(buttonRepeatTask, buttonRepeatInitialTime, buttonRepeatTime);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\t@Override\n\t\tpublic void touchUp (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\tbuttonRepeatTask.cancel();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/spinner/SpinnerModel.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.spinner;\n\n/**\n * Classes implementing this interface represent model that can be used with {@link Spinner}. Model defines what is scrolled\n * in spinner (eg. int numbers, floats or some arbitrary strings), set-ups input validation and updates it's value if user\n * changed text in spinner value text field.\n * <p>\n * Classes wanting to implement this interface should inherit from {@link AbstractSpinnerModel} to simplify event handling.\n * @author Kotcrab\n * @see AbstractSpinnerModel\n * @see IntSpinnerModel\n * @see FloatSpinnerModel\n * @see SimpleFloatSpinnerModel\n * @see ArraySpinnerModel\n * @since 1.0.2\n */\npublic interface SpinnerModel {\n\t/**\n\t * Called when model is assigned to {@link Spinner}. When this is called Spinner has been initialised so it's safe to\n\t * do operation on it such as adding custom validators to text field.\n\t * <p>\n\t * If this model can't be reused then in this function it should verify that it is not being bound for the second time.\n\t * <p>\n\t * After model has finished it's setup it should call {@link Spinner#notifyValueChanged(boolean)} with true to perform\n\t * first update and set initial spinner value.\n\t * @param spinner that this model was assigned to\n\t */\n\tvoid bind (Spinner spinner);\n\n\t/**\n\t * Called when spinner text has changed. Usually this is the moment when model has to update it's current value variable.\n\t * If input is invalid when this it called then it should simply be ignored. If field loses focus while it is in\n\t * invalid state then last valid value will be automatically restored. This should NOT call {@link Spinner#notifyValueChanged(boolean)}.\n\t */\n\tvoid textChanged ();\n\n\t/**\n\t * Steps model up by one. Depending of the implementation this could move model to next item or increment it's value by\n\t * arbitrary amount. Implementation class MUST call {@link Spinner#notifyValueChanged(boolean)} with fireEvent param set to\n\t * {@link Spinner#isProgrammaticChangeEvents()}\n\t * <p>\n\t * @return true when value was changed, false otherwise\n\t */\n\tboolean increment ();\n\n\t/**\n\t * Steps model up by one. Depending of the implementation this could move model to next item or increment it's value by\n\t * arbitrary amount. Implementation class MUST call {@link Spinner#notifyValueChanged(boolean)} using fireEvent param as argument.\n\t * <p>\n\t * @return true when value was changed, false otherwise\n\t */\n\tboolean increment (boolean fireEvent);\n\n\t/**\n\t * Steps model down by one. Depending of the implementation this could move model to previous item or decrement it's value by\n\t * arbitrary amount. Implementation class MUST call {@link Spinner#notifyValueChanged(boolean)} with fireEvent param set to\n\t * {@link Spinner#isProgrammaticChangeEvents()}\n\t * <p>\n\t * @return true when value was changed, false otherwise\n\t */\n\tboolean decrement ();\n\n\t/**\n\t * Steps model down by one. Depending of the implementation this could move model to previous item or decrement it's value by\n\t * arbitrary amount. Implementation class MUST call {@link Spinner#notifyValueChanged(boolean)} using fireEvent param as argument.\n\t * <p>\n\t * @return true when value was changed, false otherwise\n\t */\n\tboolean decrement (boolean fireEvent);\n\n\t/**\n\t * Allows to enable model wrapping: if last element of model is reached and {@link #decrement()} was called then it\n\t * will be looped to first element. Same applies for last element and {@link #increment()}\n\t * @param wrap whether to wrap this model or not\n\t */\n\tvoid setWrap (boolean wrap);\n\n\t/** @return true if model wrapping is enabled, false otherwise. See {@link #setWrap(boolean)} */\n\tboolean isWrap ();\n\n\t/** @return text representation of current model value */\n\tString getText ();\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/tabbedpane/Tab.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.tabbedpane;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.utils.Disposable;\n\n/**\n * Base class for tabs used in TabbedPane. Tab can be savable, meaning that it can be saved and will display warning\n * dialog 'do you want to save changes' before closing. Tab can be also closeable by user meaning that user can close\n * this tab manually from tabbed pane (using 'X' button or by pressing mouse wheel on tab).\n * @author Kotcrab\n */\npublic abstract class Tab implements Disposable {\n\tprivate boolean activeTab;\n\tprivate TabbedPane pane;\n\n\tprivate boolean closeableByUser = true;\n\tprivate boolean savable = false;\n\tprivate boolean dirty = false;\n\n\tpublic Tab () {\n\t}\n\n\t/** @param savable if true tab can be saved and marked as dirty. */\n\tpublic Tab (boolean savable) {\n\t\tthis.savable = savable;\n\t}\n\n\t/**\n\t * @param savable if true tab can be saved and marked as dirty.\n\t * @param closeableByUser if true tab can be closed by user from tabbed pane.\n\t */\n\tpublic Tab (boolean savable, boolean closeableByUser) {\n\t\tthis.savable = savable;\n\t\tthis.closeableByUser = closeableByUser;\n\t}\n\n\t/** @return tab title used by tabbed pane. */\n\tpublic abstract String getTabTitle ();\n\n\t/**\n\t * @return table that contains this tab view, will be passed to tabbed pane listener. Should\n\t * return same table every time this is called.\n\t */\n\tpublic abstract Table getContentTable ();\n\n\t/** Called by pane when this tab becomes shown. Class overriding this should call super.onShow(). */\n\tpublic void onShow () {\n\t\tactiveTab = true;\n\t}\n\n\t/** Called by pane when this tab becomes hidden. Class overriding this should call super.onHide(). */\n\tpublic void onHide () {\n\t\tactiveTab = false;\n\t}\n\n\t/** @return true is this tab is currently active. */\n\tpublic boolean isActiveTab () {\n\t\treturn activeTab;\n\t}\n\n\t/** @return pane that this tab belongs to, or null. */\n\tpublic TabbedPane getPane () {\n\t\treturn pane;\n\t}\n\n\t/** Should be called by TabbedPane only, when tab is added to pane. */\n\tpublic void setPane (TabbedPane pane) {\n\t\tthis.pane = pane;\n\t}\n\n\tpublic boolean isSavable () {\n\t\treturn savable;\n\t}\n\n\tpublic boolean isCloseableByUser () {\n\t\treturn closeableByUser;\n\t}\n\n\tpublic boolean isDirty () {\n\t\treturn dirty;\n\t}\n\n\tpublic void setDirty (boolean dirty) {\n\t\tcheckSavable();\n\n\t\tboolean update = (dirty != this.dirty);\n\n\t\tif (update) {\n\t\t\tthis.dirty = dirty;\n\t\t\tif (pane != null) getPane().updateTabTitle(this);\n\t\t}\n\t}\n\n\t/** Marks this tab as dirty */\n\tpublic void dirty () {\n\t\tsetDirty(true);\n\t}\n\n\t/**\n\t * Called when this tab should save its own state. After saving setDirty(false) must be called manually to remove dirty state.\n\t * @return true when save succeeded, false otherwise.\n\t */\n\tpublic boolean save () {\n\t\tcheckSavable();\n\n\t\treturn false;\n\t}\n\n\tprivate void checkSavable () {\n\t\tif (isSavable() == false) throw new IllegalStateException(\"Tab \" + getTabTitle() + \" is not savable!\");\n\t}\n\n\t/** Removes this tab from pane (if any). */\n\tpublic void removeFromTabPane () {\n\t\tif (pane != null) pane.remove(this);\n\t}\n\n\t/** Called when tab is being removed from scene. */\n\t@Override\n\tpublic void dispose () {\n\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/tabbedpane/TabbedPane.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.tabbedpane;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.Input.Buttons;\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.math.Rectangle;\nimport com.badlogic.gdx.math.Vector2;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.InputEvent;\nimport com.badlogic.gdx.scenes.scene2d.InputListener;\nimport com.badlogic.gdx.scenes.scene2d.Touchable;\nimport com.badlogic.gdx.scenes.scene2d.ui.Button;\nimport com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup;\nimport com.badlogic.gdx.scenes.scene2d.ui.Cell;\nimport com.badlogic.gdx.scenes.scene2d.ui.Image;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.scenes.scene2d.utils.UIUtils;\nimport com.badlogic.gdx.utils.Array;\nimport com.badlogic.gdx.utils.I18NBundle;\nimport com.badlogic.gdx.utils.IdentityMap;\nimport com.badlogic.gdx.utils.ObjectMap.Entry;\nimport com.badlogic.gdx.utils.Scaling;\nimport com.kotcrab.vis.ui.Locales;\nimport com.kotcrab.vis.ui.Sizes;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.i18n.BundleText;\nimport com.kotcrab.vis.ui.layout.DragPane;\nimport com.kotcrab.vis.ui.layout.HorizontalFlowGroup;\nimport com.kotcrab.vis.ui.layout.VerticalFlowGroup;\nimport com.kotcrab.vis.ui.util.dialog.Dialogs;\nimport com.kotcrab.vis.ui.util.dialog.Dialogs.OptionDialogType;\nimport com.kotcrab.vis.ui.util.dialog.OptionDialogAdapter;\nimport com.kotcrab.vis.ui.widget.Draggable;\nimport com.kotcrab.vis.ui.widget.VisImageButton;\nimport com.kotcrab.vis.ui.widget.VisImageButton.VisImageButtonStyle;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.VisTextButton;\nimport com.kotcrab.vis.ui.widget.VisTextButton.VisTextButtonStyle;\n\n/**\n * A tabbed pane, allows to have multiple tabs open and switch between them. TabbedPane does not handle displaying tab content,\n * you have to do that manually using tabbed pane listener to get tab content table (see {@link Tab#getContentTable()} and\n * {@link TabbedPaneListener}). All tabs must extend {@link Tab} class.\n * <p>\n * Since 0.9.3, tabbed pane uses an internal {@link DragPane} to make the tabs draggable. You can completely turn off this\n * functionality by setting {@link TabbedPaneStyle#draggable} to false. To turn off the drag listener at runtime, use\n * {@link #getTabsPane()} method to get a reference of {@link DragPane}, and invoke {@link DragPane#setDraggable(Draggable)} with\n * null argument - this will clear draggable listener from all tabs' buttons; naturally, setting this value to non-null\n * {@link Draggable} listener will also add it to all buttons.\n * @author Kotcrab\n * @author MJ\n * @since 0.7.0\n */\npublic class TabbedPane {\n\tprivate static final Vector2 tmpVector = new Vector2();\n\tprivate static final Rectangle tmpRect = new Rectangle();\n\n\tprivate TabbedPaneStyle style;\n\tprivate Sizes sizes;\n\tprivate VisImageButtonStyle sharedCloseActiveButtonStyle;\n\n\tprivate DragPane tabsPane;\n\tprivate TabbedPaneTable mainTable;\n\n\tprivate Array<Tab> tabs;\n\tprivate IdentityMap<Tab, TabButtonTable> tabsButtonMap;\n\tprivate ButtonGroup<Button> group;\n\n\tprivate Tab activeTab;\n\n\tprivate Array<TabbedPaneListener> listeners;\n\tprivate boolean allowTabDeselect;\n\n\tpublic TabbedPane () {\n\t\tthis(VisUI.getSkin().get(TabbedPaneStyle.class));\n\t}\n\n\tpublic TabbedPane (String styleName) {\n\t\tthis(VisUI.getSkin().get(styleName, TabbedPaneStyle.class));\n\t}\n\n\tpublic TabbedPane (TabbedPaneStyle style) {\n\t\tthis(style, VisUI.getSizes());\n\t}\n\n\tpublic TabbedPane (TabbedPaneStyle style, Sizes sizes) {\n\t\tthis.style = style;\n\t\tthis.sizes = sizes;\n\t\tlisteners = new Array<TabbedPaneListener>();\n\n\t\tsharedCloseActiveButtonStyle = VisUI.getSkin().get(\"close-active-tab\", VisImageButtonStyle.class);\n\n\t\tgroup = new ButtonGroup<Button>();\n\n\t\tmainTable = new TabbedPaneTable(this);\n\t\ttabsPane = new DragPane(style.vertical ? new VerticalFlowGroup() : new HorizontalFlowGroup());\n\t\tconfigureDragPane(style);\n\n\t\tmainTable.setBackground(style.background);\n\n\t\ttabs = new Array<Tab>();\n\t\ttabsButtonMap = new IdentityMap<Tab, TabButtonTable>();\n\n\t\tCell<DragPane> tabsPaneCell = mainTable.add(tabsPane);\n\t\tCell<Image> separatorCell = null;\n\n\t\tif (style.vertical) {\n\t\t\ttabsPaneCell.top().growY().minSize(0, 0);\n\t\t} else {\n\t\t\ttabsPaneCell.left().growX().minSize(0, 0);\n\t\t}\n\n\t\t//note: if separatorBar height/width is not set explicitly it may sometimes disappear\n\t\tif (style.separatorBar != null) {\n\t\t\tif (style.vertical) {\n\t\t\t\tseparatorCell = mainTable.add(new Image(style.separatorBar)).growY().width(style.separatorBar.getMinWidth());\n\t\t\t} else {\n\t\t\t\tmainTable.row();\n\t\t\t\tseparatorCell = mainTable.add(new Image(style.separatorBar)).growX().height(style.separatorBar.getMinHeight());\n\t\t\t}\n\t\t} else {\n\t\t\t//make sure that tab will fill available space even when there is no separatorBar image set\n\t\t\tif (style.vertical) {\n\t\t\t\tmainTable.add().growY();\n\t\t\t} else {\n\t\t\t\tmainTable.add().growX();\n\t\t\t}\n\t\t}\n\n\t\tmainTable.setPaneCells(tabsPaneCell, separatorCell);\n\t}\n\n\tprivate void configureDragPane (TabbedPaneStyle style) {\n\t\ttabsPane.setTouchable(Touchable.childrenOnly);\n\t\ttabsPane.setListener(new DragPane.DragPaneListener.AcceptOwnChildren());\n\t\tif (style.draggable) {\n\t\t\tDraggable draggable = new Draggable();\n\t\t\tdraggable.setInvisibleWhenDragged(true);\n\t\t\tdraggable.setKeepWithinParent(true);\n\t\t\tdraggable.setBlockInput(true);\n\t\t\tdraggable.setFadingTime(0f);\n\t\t\tdraggable.setListener(new DragPane.DefaultDragListener() {\n\t\t\t\tpublic boolean dragged;\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean onStart (Draggable draggable, Actor actor, float stageX, float stageY) {\n\t\t\t\t\tdragged = false;\n\t\t\t\t\tif (actor instanceof TabButtonTable) {\n\t\t\t\t\t\tif (((TabButtonTable) actor).closeButton.isOver()) return CANCEL;\n\t\t\t\t\t}\n\t\t\t\t\treturn super.onStart(draggable, actor, stageX, stageY);\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void onDrag (Draggable draggable, Actor actor, float stageX, float stageY) {\n\t\t\t\t\tsuper.onDrag(draggable, actor, stageX, stageY);\n\t\t\t\t\tdragged = true;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean onEnd (Draggable draggable, Actor actor, float stageX, float stageY) {\n\t\t\t\t\tboolean result = super.onEnd(draggable, actor, stageX, stageY);\n\t\t\t\t\tif (result == APPROVE) return APPROVE;\n\t\t\t\t\tif (dragged == false) return CANCEL;\n\n\t\t\t\t\t// check if any actor corner is over some other tab\n\t\t\t\t\ttabsPane.stageToLocalCoordinates(tmpVector.set(stageX, stageY));\n\t\t\t\t\tif (tabsPane.hit(tmpVector.x, tmpVector.y, true) != null) return CANCEL;\n\t\t\t\t\tif (tabsPane.hit(tmpVector.x + actor.getWidth(), tmpVector.y, true) != null) return CANCEL;\n\t\t\t\t\tif (tabsPane.hit(tmpVector.x, tmpVector.y - actor.getHeight(), true) != null) return CANCEL;\n\t\t\t\t\tif (tabsPane.hit(tmpVector.x + actor.getWidth(), tmpVector.y - actor.getHeight(), true) != null)\n\t\t\t\t\t\treturn CANCEL;\n\n\t\t\t\t\tVector2 stagePos = tabsPane.localToStageCoordinates(tmpVector.setZero());\n\t\t\t\t\ttmpRect.set(stagePos.x, stagePos.y, tabsPane.getGroup().getWidth(), tabsPane.getGroup().getHeight());\n\t\t\t\t\tif (tmpRect.contains(stageX, stageY) == false) return CANCEL;\n\t\t\t\t\tif (tabsPane.isHorizontalFlow() || tabsPane.isVerticalFlow()) {\n\t\t\t\t\t\tDRAG_POSITION.set(stageX, stageY);\n\t\t\t\t\t\ttabsPane.addActor(actor);\n\t\t\t\t\t\treturn APPROVE;\n\t\t\t\t\t}\n\t\t\t\t\treturn CANCEL;\n\t\t\t\t}\n\t\t\t});\n\t\t\ttabsPane.setDraggable(draggable);\n\t\t}\n\t}\n\n\t/** @return a direct reference to internal {@link DragPane}. Allows to manage {@link Draggable} settings. */\n\tpublic DragPane getTabsPane () {\n\t\treturn tabsPane;\n\t}\n\n\t/**\n\t * @param allowTabDeselect if true user may deselect tab, meaning that there won't be any active tab. Allows to create similar\n\t * behaviour like in Intellij IDEA bottom quick access bar\n\t */\n\tpublic void setAllowTabDeselect (boolean allowTabDeselect) {\n\t\tthis.allowTabDeselect = allowTabDeselect;\n\t\tif (allowTabDeselect) {\n\t\t\tgroup.setMinCheckCount(0);\n\t\t} else {\n\t\t\tgroup.setMinCheckCount(1);\n\t\t}\n\t}\n\n\tpublic boolean isAllowTabDeselect () {\n\t\treturn allowTabDeselect;\n\t}\n\n\tpublic void add (Tab tab) {\n\t\ttab.setPane(this);\n\t\ttabs.add(tab);\n\n\t\taddTab(tab, tabsPane.getChildren().size);\n\t\tswitchTab(tab);\n\t}\n\n\tpublic void insert (int index, Tab tab) {\n\t\ttab.setPane(this);\n\t\ttabs.insert(index, tab);\n\t\taddTab(tab, index);\n\t}\n\n\t/**\n\t * @param tab will be added in the selected index.\n\t * @param index index of the tab, starting from zero.\n\t */\n\tprotected void addTab (Tab tab, int index) {\n\t\tTabButtonTable buttonTable = tabsButtonMap.get(tab);\n\t\tif (buttonTable == null) {\n\t\t\tbuttonTable = new TabButtonTable(tab);\n\t\t\ttabsButtonMap.put(tab, buttonTable);\n\t\t}\n\n\t\tbuttonTable.setTouchable(Touchable.enabled);\n\t\tif (index >= tabsPane.getChildren().size) {\n\t\t\ttabsPane.addActor(buttonTable);\n\t\t} else {\n\t\t\ttabsPane.addActorAt(index, buttonTable);\n\t\t}\n\t\tgroup.add(buttonTable.button);\n\n\t\tif (tabs.size == 1 && activeTab != null) {\n\t\t\tbuttonTable.select();\n\t\t\tnotifyListenersSwitched(tab);\n\t\t} else if (tab == activeTab) {\n\t\t\tbuttonTable.select(); // maintains currently selected tab while rebuilding\n\t\t}\n\t}\n\n\t/**\n\t * Disables or enables given tab.\n\t * <p>\n\t * When disabling, if tab is currently selected, TabbedPane will switch to first available enabled Tab. If there is no any\n\t * other enabled Tab, listener {@link TabbedPaneListener#switchedTab(Tab)} with null Tab will be called.\n\t * <p>\n\t * When enabling Tab and there isn't any others Tab enabled and {@link #setAllowTabDeselect(boolean)} was set to false, passed\n\t * Tab will be selected. If {@link #setAllowTabDeselect(boolean)} is set to true nothing will be selected, all tabs will remain\n\t * unselected.\n\t * @param tab tab to change its state\n\t * @param disable controls whether to disable or enable this tab\n\t * @throws IllegalArgumentException if tab does not belong to this TabbedPane\n\t */\n\tpublic void disableTab (Tab tab, boolean disable) {\n\t\tcheckIfTabsBelongsToThisPane(tab);\n\n\t\tTabButtonTable buttonTable = tabsButtonMap.get(tab);\n\t\tbuttonTable.button.setDisabled(disable);\n\n\t\tif (activeTab == tab && disable) {\n\t\t\tif (selectFirstEnabledTab()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// there isn't any tab we can switch to\n\t\t\tactiveTab = null;\n\t\t\tnotifyListenersSwitched(null);\n\t\t}\n\n\t\tif (activeTab == null && allowTabDeselect == false) {\n\t\t\tselectFirstEnabledTab();\n\t\t}\n\t}\n\n\tpublic boolean isTabDisabled (Tab tab) {\n\t\tTabButtonTable table = tabsButtonMap.get(tab);\n\t\tif (table == null) {\n\t\t\tthrowNotBelongingTabException(tab);\n\t\t}\n\t\treturn table.button.isDisabled();\n\t}\n\n\tprivate boolean selectFirstEnabledTab () {\n\t\tfor (Entry<Tab, TabButtonTable> entry : tabsButtonMap) {\n\t\t\tif (entry.value.button.isDisabled() == false) {\n\t\t\t\tswitchTab(entry.key);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate void checkIfTabsBelongsToThisPane (Tab tab) {\n\t\tif (tabs.contains(tab, true) == false) {\n\t\t\tthrowNotBelongingTabException(tab);\n\t\t}\n\t}\n\n\tprotected void throwNotBelongingTabException (Tab tab) {\n\t\tthrow new IllegalArgumentException(\"Tab '\" + tab.getTabTitle() + \"' does not belong to this TabbedPane\");\n\t}\n\n\t/**\n\t * Removes tab from pane, if tab is dirty this won't cause to display \"Unsaved changes\" dialog!\n\t * @param tab to be removed\n\t * @return true if tab was removed, false if that tab wasn't added to this pane\n\t */\n\tpublic boolean remove (Tab tab) {\n\t\treturn remove(tab, true);\n\t}\n\n\t/**\n\t * Removes tab from pane, if tab is dirty and 'ignoreTabDirty == false' this will cause to display \"Unsaved changes\" dialog!\n\t * @return true if tab was removed, false if that tab wasn't added to this pane or \"Unsaved changes\" dialog was started\n\t */\n\tpublic boolean remove (final Tab tab, boolean ignoreTabDirty) {\n\t\tcheckIfTabsBelongsToThisPane(tab);\n\n\t\tif (ignoreTabDirty) {\n\t\t\treturn removeTab(tab);\n\t\t}\n\n\t\tif (tab.isDirty() && mainTable.getStage() != null) {\n\t\t\tDialogs.showOptionDialog(mainTable.getStage(), Text.UNSAVED_DIALOG_TITLE.get(), Text.UNSAVED_DIALOG_TEXT.get(),\n\t\t\t\t\tOptionDialogType.YES_NO_CANCEL, new OptionDialogAdapter() {\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void yes () {\n\t\t\t\t\t\t\ttab.save();\n\t\t\t\t\t\t\tremoveTab(tab);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void no () {\n\t\t\t\t\t\t\tremoveTab(tab);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t} else {\n\t\t\treturn removeTab(tab);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate boolean removeTab (Tab tab) {\n\t\tint index = tabs.indexOf(tab, true);\n\t\tboolean success = tabs.removeValue(tab, true);\n\n\t\tif (success) {\n\t\t\tTabButtonTable buttonTable = tabsButtonMap.get(tab);\n\t\t\ttabsPane.removeActor(buttonTable, true);\n\t\t\ttabsPane.invalidateHierarchy();\n\t\t\ttabsButtonMap.remove(tab);\n\t\t\tgroup.remove(buttonTable.button);\n\n\t\t\ttab.setPane(null);\n\t\t\ttab.onHide();\n\t\t\ttab.dispose();\n\t\t\tnotifyListenersRemoved(tab);\n\n\t\t\tif (tabs.size == 0) {\n\t\t\t\t// all tabs were removed so notify listener\n\t\t\t\tactiveTab = null;\n\t\t\t\tnotifyListenersRemovedAll();\n\t\t\t} else if (activeTab == tab) {\n\t\t\t\tif (index > 0) {\n\t\t\t\t\t// switch to previous tab\n\t\t\t\t\tswitchTab(--index);\n\t\t\t\t} else {\n\t\t\t\t\t// Switching to the next tab, currently having our removed tab index.\n\t\t\t\t\tswitchTab(index);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn success;\n\t}\n\n\t/** Removes all tabs, ignores if tab is dirty */\n\tpublic void removeAll () {\n\t\tfor (Tab tab : tabs) {\n\t\t\ttab.setPane(null);\n\t\t\ttab.onHide();\n\t\t\ttab.dispose();\n\t\t}\n\n\t\ttabs.clear();\n\t\ttabsButtonMap.clear();\n\t\ttabsPane.clear();\n\t\tactiveTab = null;\n\n\t\tnotifyListenersRemovedAll();\n\t}\n\n\tpublic void switchTab (int index) {\n\t\ttabsButtonMap.get(tabs.get(index)).select();\n\t}\n\n\tpublic void switchTab (Tab tab) {\n\t\tTabButtonTable table = tabsButtonMap.get(tab);\n\t\tif (table == null) {\n\t\t\tthrowNotBelongingTabException(tab);\n\t\t}\n\t\ttable.select();\n\t}\n\n\t/**\n\t * Must be called when you want to update tab title. If tab is dirty an '*' is added before title. This is called automatically\n\t * if using {@link Tab#setDirty(boolean)}\n\t * @param tab that title will be updated\n\t */\n\tpublic void updateTabTitle (Tab tab) {\n\t\tTabButtonTable table = tabsButtonMap.get(tab);\n\t\tif (table == null) {\n\t\t\tthrowNotBelongingTabException(tab);\n\t\t}\n\t\ttable.button.setText(getTabTitle(tab));\n\t}\n\n\tprotected String getTabTitle (Tab tab) {\n\t\treturn tab.isDirty() ? \"*\" + tab.getTabTitle() : tab.getTabTitle();\n\t}\n\n\tpublic TabbedPaneTable getTable () {\n\t\treturn mainTable;\n\t}\n\n\t/** @return active tab or null if no tab is selected. */\n\tpublic Tab getActiveTab () {\n\t\treturn activeTab;\n\t}\n\n\tpublic void addListener (TabbedPaneListener listener) {\n\t\tlisteners.add(listener);\n\t}\n\n\tpublic boolean removeListener (TabbedPaneListener listener) {\n\t\treturn listeners.removeValue(listener, true);\n\t}\n\n\tprivate void notifyListenersSwitched (Tab tab) {\n\t\tfor (TabbedPaneListener listener : listeners) {\n\t\t\tlistener.switchedTab(tab);\n\t\t}\n\t}\n\n\tprivate void notifyListenersRemoved (Tab tab) {\n\t\tfor (TabbedPaneListener listener : listeners) {\n\t\t\tlistener.removedTab(tab);\n\t\t}\n\t}\n\n\tprivate void notifyListenersRemovedAll () {\n\t\tfor (TabbedPaneListener listener : listeners) {\n\t\t\tlistener.removedAllTabs();\n\t\t}\n\t}\n\n\t/** Returns tabs in order in which they are stored in tabbed pane, sorted by their index and ignoring their order in UI. */\n\tpublic Array<Tab> getTabs () {\n\t\treturn tabs;\n\t}\n\n\t/**\n\t * Returns tabs in order in which they are displayed in the UI - user may drag and move tabs which DOES NOT affect\n\t * their index. Use {@link #getTabs()} if you don't care about UI order. This creates new array every time it's called!\n\t */\n\tpublic Array<Tab> getUIOrderedTabs () {\n\t\tArray<Tab> tabs = new Array<Tab>();\n\t\tfor (Actor actor : getTabsPane().getChildren()) {\n\t\t\tif (actor instanceof TabButtonTable) {\n\t\t\t\ttabs.add(((TabButtonTable) actor).tab);\n\t\t\t}\n\t\t}\n\t\treturn tabs;\n\t}\n\n\tpublic static class TabbedPaneStyle {\n\t\tpublic Drawable background;\n\t\tpublic VisTextButtonStyle buttonStyle;\n\t\t/** Optional. */\n\t\tpublic Drawable separatorBar;\n\t\t/** Optional, defaults to false. */\n\t\tpublic boolean vertical = false;\n\t\t/** Optional, defaults to true. */\n\t\tpublic boolean draggable = true;\n\n\t\tpublic TabbedPaneStyle () {\n\t\t}\n\n\t\tpublic TabbedPaneStyle (TabbedPaneStyle style) {\n\t\t\tthis.background = style.background;\n\t\t\tthis.buttonStyle = style.buttonStyle;\n\t\t\tthis.separatorBar = style.separatorBar;\n\t\t\tthis.vertical = style.vertical;\n\t\t\tthis.draggable = style.draggable;\n\t\t}\n\n\t\tpublic TabbedPaneStyle (Drawable background, Drawable separatorBar, VisTextButtonStyle buttonStyle) {\n\t\t\tthis.background = background;\n\t\t\tthis.separatorBar = separatorBar;\n\t\t\tthis.buttonStyle = buttonStyle;\n\t\t}\n\n\t\tpublic TabbedPaneStyle (Drawable separatorBar, Drawable background, VisTextButtonStyle buttonStyle, boolean vertical, boolean draggable) {\n\t\t\tthis.separatorBar = separatorBar;\n\t\t\tthis.background = background;\n\t\t\tthis.buttonStyle = buttonStyle;\n\t\t\tthis.vertical = vertical;\n\t\t\tthis.draggable = draggable;\n\t\t}\n\t}\n\n\tpublic static class TabbedPaneTable extends VisTable {\n\t\tprivate TabbedPane tabbedPane;\n\t\tprivate Cell<DragPane> tabsPaneCell;\n\t\tprivate Cell<Image> separatorCell;\n\n\t\tpublic TabbedPaneTable (TabbedPane tabbedPane) {\n\t\t\tthis.tabbedPane = tabbedPane;\n\t\t}\n\n\t\tprivate void setPaneCells (Cell<DragPane> tabsPaneCell, Cell<Image> separatorCell) {\n\t\t\tthis.tabsPaneCell = tabsPaneCell;\n\t\t\tthis.separatorCell = separatorCell;\n\t\t}\n\n\t\tpublic Cell<DragPane> getTabsPaneCell () {\n\t\t\treturn tabsPaneCell;\n\t\t}\n\n\t\t/** @return separator cell or null if separator is not used */\n\t\tpublic Cell<Image> getSeparatorCell () {\n\t\t\treturn separatorCell;\n\t\t}\n\n\t\tpublic TabbedPane getTabbedPane () {\n\t\t\treturn tabbedPane;\n\t\t}\n\t}\n\n\tprivate class TabButtonTable extends VisTable {\n\t\tpublic VisTextButton button;\n\t\tpublic VisImageButton closeButton;\n\t\tprivate Tab tab;\n\n\t\tprivate VisTextButtonStyle buttonStyle;\n\t\tprivate VisImageButtonStyle closeButtonStyle;\n\t\tprivate Drawable up;\n\n\t\tpublic TabButtonTable (Tab tab) {\n\t\t\tthis.tab = tab;\n\t\t\tbutton = new VisTextButton(getTabTitle(tab), style.buttonStyle) {\n\t\t\t\t@Override\n\t\t\t\tpublic void setDisabled (boolean isDisabled) {\n\t\t\t\t\tsuper.setDisabled(isDisabled);\n\t\t\t\t\tcloseButton.setDisabled(isDisabled);\n\t\t\t\t\tdeselect();\n\t\t\t\t}\n\t\t\t};\n\t\t\tbutton.setFocusBorderEnabled(false);\n\t\t\tbutton.setProgrammaticChangeEvents(false);\n\n\t\t\tcloseButtonStyle = new VisImageButtonStyle(VisUI.getSkin().get(\"close\", VisImageButtonStyle.class));\n\n\t\t\tcloseButton = new VisImageButton(closeButtonStyle);\n\t\t\tcloseButton.setGenerateDisabledImage(true);\n\t\t\tcloseButton.getImage().setScaling(Scaling.fill);\n\t\t\tcloseButton.getImage().setColor(Color.RED);\n\n\t\t\taddListeners();\n\n\t\t\tbuttonStyle = new VisTextButtonStyle((VisTextButtonStyle) button.getStyle());\n\t\t\tbutton.setStyle(buttonStyle);\n\t\t\tcloseButtonStyle = closeButton.getStyle();\n\t\t\tup = buttonStyle.up;\n\n\t\t\tadd(button);\n\t\t\tif (tab.isCloseableByUser()) {\n\t\t\t\tadd(closeButton).size(14 * sizes.scaleFactor, button.getHeight());\n\t\t\t}\n\t\t}\n\n\t\tprivate void addListeners () {\n\t\t\tcloseButton.addListener(new ChangeListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\tcloseTabAsUser();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tbutton.addListener(new InputListener() {\n\t\t\t\tprivate boolean isDown;\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean touchDown (InputEvent event, float x, float y, int pointer, int mouseButton) {\n\t\t\t\t\tif (button.isDisabled()) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tisDown = true;\n\t\t\t\t\tif (UIUtils.left()) {\n\t\t\t\t\t\tsetDraggedUpImage();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (mouseButton == Buttons.MIDDLE) {\n\t\t\t\t\t\tcloseTabAsUser();\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void touchUp (InputEvent event, float x, float y, int pointer, int button) {\n\t\t\t\t\tsetDefaultUpImage();\n\t\t\t\t\tisDown = false;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean mouseMoved (InputEvent event, float x, float y) {\n\t\t\t\t\tif (!button.isDisabled() && activeTab != tab) {\n\t\t\t\t\t\tsetCloseButtonOnMouseMove();\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void exit (InputEvent event, float x, float y, int pointer, Actor toActor) {\n\t\t\t\t\tif (!button.isDisabled() && !isDown && activeTab != tab && pointer == -1) {\n\t\t\t\t\t\tsetDefaultUpImage();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void enter (InputEvent event, float x, float y, int pointer, Actor fromActor) {\n\t\t\t\t\tif (!button.isDisabled() && activeTab != tab && Gdx.input.justTouched() == false && pointer == -1) {\n\t\t\t\t\t\tsetCloseButtonOnMouseMove();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tprivate void setCloseButtonOnMouseMove () {\n\t\t\t\t\tif (isDown) {\n\t\t\t\t\t\tcloseButtonStyle.up = buttonStyle.down;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcloseButtonStyle.up = buttonStyle.over;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tprivate void setDraggedUpImage () {\n\t\t\t\t\tcloseButtonStyle.up = buttonStyle.down;\n\t\t\t\t\tbuttonStyle.up = buttonStyle.down;\n\t\t\t\t}\n\n\t\t\t\tprivate void setDefaultUpImage () {\n\t\t\t\t\tcloseButtonStyle.up = up;\n\t\t\t\t\tbuttonStyle.up = up;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tbutton.addListener(new ChangeListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\tswitchToNewTab();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tprivate void switchToNewTab () {\n\t\t\t// there was some previous tab, deselect it\n\t\t\tif (activeTab != null && activeTab != tab) {\n\t\t\t\tTabButtonTable table = tabsButtonMap.get(activeTab);\n\t\t\t\t// table may no longer exists if tab was removed, no big deal since this only changes\n\t\t\t\t// button style, tab.onHide() will be already called by remove() method\n\t\t\t\tif (table != null) {\n\t\t\t\t\ttable.deselect();\n\t\t\t\t\tactiveTab.onHide();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (button.isChecked() && tab != activeTab) { // switch to new tab\n\t\t\t\tactiveTab = tab;\n\t\t\t\tnotifyListenersSwitched(tab);\n\t\t\t\ttab.onShow();\n\t\t\t\tcloseButton.setStyle(sharedCloseActiveButtonStyle);\n\t\t\t} else if (group.getCheckedIndex() == -1) { // no tab selected (allowTabDeselect == true)\n\t\t\t\tactiveTab = null;\n\t\t\t\tnotifyListenersSwitched(null);\n\t\t\t}\n\n\t\t}\n\n\t\t/** Closes tab, does nothing if Tab is not closeable by user */\n\t\tprivate void closeTabAsUser () {\n\t\t\tif (tab.isCloseableByUser()) {\n\t\t\t\tTabbedPane.this.remove(tab, false);\n\t\t\t}\n\t\t}\n\n\t\tprivate void select () {\n\t\t\tbutton.setChecked(true);\n\t\t\tswitchToNewTab();\n\t\t}\n\n\t\tprivate void deselect () {\n\t\t\tcloseButton.setStyle(closeButtonStyle);\n\t\t}\n\t}\n\n\tprivate enum Text implements BundleText {\n\t\tUNSAVED_DIALOG_TITLE(\"unsavedDialogTitle\"), UNSAVED_DIALOG_TEXT(\"unsavedDialogText\");\n\n\t\tprivate final String name;\n\n\t\tText (final String name) {\n\t\t\tthis.name = name;\n\t\t}\n\n\t\tprivate static I18NBundle getBundle () {\n\t\t\treturn Locales.getTabbedPaneBundle();\n\t\t}\n\n\t\t@Override\n\t\tpublic final String getName () {\n\t\t\treturn name;\n\t\t}\n\n\t\t@Override\n\t\tpublic final String get () {\n\t\t\treturn getBundle().get(name);\n\t\t}\n\n\t\t@Override\n\t\tpublic final String format () {\n\t\t\treturn getBundle().format(name);\n\t\t}\n\n\t\t@Override\n\t\tpublic final String format (final Object... arguments) {\n\t\t\treturn getBundle().format(name, arguments);\n\t\t}\n\n\t\t@Override\n\t\tpublic final String toString () {\n\t\t\treturn get();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/tabbedpane/TabbedPaneAdapter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.tabbedpane;\n\n/**\n * Empty implementation of {@link TabbedPaneListener}.\n * @author Kotcrab\n */\npublic class TabbedPaneAdapter implements TabbedPaneListener {\n\t@Override\n\tpublic void switchedTab (Tab tab) {\n\n\t}\n\n\t@Override\n\tpublic void removedTab (Tab tab) {\n\n\t}\n\n\t@Override\n\tpublic void removedAllTabs () {\n\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/tabbedpane/TabbedPaneListener.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.tabbedpane;\n\n/**\n * Listener used to get events from {@link TabbedPane}.\n * @author Kotcrab\n */\npublic interface TabbedPaneListener {\n\t/**\n\t * Called when TabbedPane switched to new tab.\n\t * @param tab that TabbedPane switched to. May be null if all tabs were disabled or if {@link TabbedPane#setAllowTabDeselect(boolean)} was set to\n\t * true and all tabs were deselected.\n\t */\n\tvoid switchedTab (Tab tab);\n\n\t/**\n\t * Called when Tab was removed TabbedPane.\n\t * @param tab that was removed.\n\t */\n\tvoid removedTab (Tab tab);\n\n\t/** Called when all tabs were removed from TabbedPane. */\n\tvoid removedAllTabs ();\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/toast/MessageToast.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.toast;\n\nimport com.kotcrab.vis.ui.widget.LinkLabel;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisTable;\n\n/**\n * Toast with provided user message and arbitrary amount of {@link LinkLabel} below it acting as action buttons.\n * @author Kotcrab\n * @see ToastTable\n * @since 1.1.0\n */\npublic class MessageToast extends ToastTable {\n\tprivate VisTable linkLabelTable = new VisTable();\n\n\tpublic MessageToast (String message) {\n\t\tsuper();\n\t\tadd(new VisLabel(message)).left().row();\n\t\tadd(linkLabelTable).right();\n\t}\n\n\t/**\n\t * Adds new link label below toast message.\n\t * @param text link label text\n\t * @param labelListener will be called upon label click. Note that toast won't be closed automatically so {@link Toast#fadeOut()}\n\t * must be called\n\t */\n\tpublic void addLinkLabel (String text, LinkLabel.LinkLabelListener labelListener) {\n\t\tLinkLabel label = new LinkLabel(text);\n\t\tlabel.setListener(labelListener);\n\t\tlinkLabelTable.add(label).spaceRight(12);\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/toast/Toast.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.toast;\n\nimport com.badlogic.gdx.math.Interpolation;\nimport com.badlogic.gdx.scenes.scene2d.Action;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.actions.Actions;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.ToastManager;\nimport com.kotcrab.vis.ui.widget.VisImageButton;\nimport com.kotcrab.vis.ui.widget.VisImageButton.VisImageButtonStyle;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\n/**\n * Base class for all toasts. Toast is a wrapper around actual toast content table. It has close button and reference to\n * {@link ToastManager}. To create your own toast you should generally extend {@link ToastTable} class.\n * <p>\n * If you want further customization and modify other aspects of toast (such as close button) override\n * {@link #createMainTable()}.\n * @author Kotcrab\n * @see MessageToast\n * @see ToastTable\n * @since 1.1.0\n */\npublic class Toast {\n\tprivate ToastStyle style;\n\n\tprivate ToastManager toastManager;\n\n\tprivate Table mainTable;\n\tprivate Table contentTable;\n\n\t/** @param content table content, preferably instance of {@link ToastTable} */\n\tpublic Toast (Table content) {\n\t\tthis(\"default\", content);\n\t}\n\n\t/** @param content table content, preferably instance of {@link ToastTable} */\n\tpublic Toast (String styleName, Table content) {\n\t\tthis(VisUI.getSkin().get(styleName, ToastStyle.class), content);\n\t}\n\n\t/** @param content table content, preferably instance of {@link ToastTable} */\n\tpublic Toast (ToastStyle style, Table content) {\n\t\tthis.style = style;\n\t\tthis.contentTable = content;\n\t\tif (content instanceof ToastTable) {\n\t\t\t((ToastTable) content).setToast(this);\n\t\t}\n\t\tcreateMainTable();\n\t}\n\n\tprotected void createMainTable () {\n\t\tmainTable = new VisTable();\n\t\tmainTable.setBackground(style.background);\n\n\t\tVisImageButton closeButton = new VisImageButton(style.closeButtonStyle);\n\t\tcloseButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tclose();\n\t\t\t}\n\t\t});\n\n\t\tmainTable.add(contentTable).pad(3).fill().expand();\n\t\tmainTable.add(closeButton).top();\n\t}\n\n\t/** Called when close button was pressed by default call {@link #fadeOut()} */\n\tprotected void close () {\n\t\tfadeOut();\n\t}\n\n\tpublic void fadeOut () {\n\t\tmainTable.addAction(Actions.sequence(Actions.fadeOut(VisWindow.FADE_TIME, Interpolation.fade), new Action() {\n\t\t\t@Override\n\t\t\tpublic boolean act (float delta) {\n\t\t\t\ttoastManager.remove(Toast.this);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}));\n\t}\n\n\tpublic Table fadeIn () {\n\t\tmainTable.setColor(1, 1, 1, 0);\n\t\tmainTable.addAction(Actions.fadeIn(VisWindow.FADE_TIME, Interpolation.fade));\n\t\treturn mainTable;\n\t}\n\n\tpublic Table getContentTable () {\n\t\treturn contentTable;\n\t}\n\n\tpublic Table getMainTable () {\n\t\treturn mainTable;\n\t}\n\n\tpublic void setToastManager (ToastManager toastManager) {\n\t\tthis.toastManager = toastManager;\n\t}\n\n\tpublic ToastManager getToastManager () {\n\t\treturn toastManager;\n\t}\n\n\tpublic static class ToastStyle {\n\t\tpublic Drawable background;\n\t\tpublic VisImageButtonStyle closeButtonStyle;\n\n\t\tpublic ToastStyle () {\n\t\t}\n\n\t\tpublic ToastStyle (ToastStyle style) {\n\t\t\tthis.background = style.background;\n\t\t\tthis.closeButtonStyle = style.closeButtonStyle;\n\t\t}\n\n\t\tpublic ToastStyle (Drawable background, VisImageButtonStyle closeButtonStyle) {\n\t\t\tthis.background = background;\n\t\t\tthis.closeButtonStyle = closeButtonStyle;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/java/com/kotcrab/vis/ui/widget/toast/ToastTable.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.widget.toast;\n\nimport com.kotcrab.vis.ui.widget.VisTable;\n\n/**\n * Base class for all toast content tables. Note that using this class is not required ({@link VisTable} can be used directly)\n * however it's preferred because it provides access to {@link Toast} instance and {@link #fadeOut()} method. Using ToastTable\n * also allows to reuse {@link Toast} instance instead of creating new one everytime you want to show toast.\n * @author Kotcrab\n * @since 1.1.0\n */\npublic class ToastTable extends VisTable {\n\tprotected Toast toast;\n\n\tpublic ToastTable () {\n\t}\n\n\tpublic ToastTable (boolean setVisDefaults) {\n\t\tsuper(setVisDefaults);\n\t}\n\n\tpublic void fadeOut () {\n\t\tif (toast == null)\n\t\t\tthrow new IllegalStateException(\"fadeOut can't be called before toast was shown by ToastManager\");\n\t\ttoast.fadeOut();\n\t}\n\n\t/** Called by framework when this ToastTable was assigned to it's toast container. */\n\tpublic void setToast (Toast toast) {\n\t\tthis.toast = toast;\n\t}\n\n\t/** @return toast that this table belongs to or null if none */\n\tpublic Toast getToast () {\n\t\treturn toast;\n\t}\n}\n"
  },
  {
    "path": "ui/src/main/resources/META-INF/robovm/ios/robovm.xml",
    "content": "<!--\n  ~ Copyright 2014-2016 See AUTHORS file.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~ http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n\n<config>\n    <forceLinkClasses>\n        <pattern>com.kotcrab.vis.ui.Sizes</pattern>\n        <pattern>com.kotcrab.vis.ui.widget.**</pattern>\n        <pattern>com.kotcrab.vis.ui.util.form.**</pattern>\n        <pattern>com.kotcrab.vis.ui.util.adapter.SimpleListAdapter</pattern>\n    </forceLinkClasses>\n</config>\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/i18n/ButtonBar.properties",
    "content": "#\n# Copyright 2014-2017 See AUTHORS file.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n#ButtonBar I18N file\n#Since 1.0.0\n\nleft=Left\nright=Right\nhelp=Help\nno=No\nyes=Yes\ncancel=Cancel\nback=Back\nnext=Next\napply=Apply\nfinish=Finish\nok=Ok\ndone=Done\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/i18n/ColorPicker.properties",
    "content": "#\n# Copyright 2014-2017 See AUTHORS file.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n#ColorPicker I18N file\n\ntitle=Color Picker\nrestore=Restore\ncancel=Cancel\nok=OK\nhex=Hex\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/i18n/Common.properties",
    "content": "#\n# Copyright 2014-2017 See AUTHORS file.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\npleaseWait=Please wait...\nunknownErrorOccurred=Unknown error occurred\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/i18n/Dialogs.properties",
    "content": "#\n# Copyright 2014-2017 See AUTHORS file.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n#Dialogs I18N file\n\ndetails=Details\ndetailsColon=Details:\ncopy=Copy\ncopied=Copied\nerror=Error\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/i18n/FileChooser.properties",
    "content": "#\n# Copyright 2014-2017 See AUTHORS file.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n#FileChooser I18N file\n\ntitleChooseFiles=Choose file\ntitleChooseDirectories=Choose directory\ntitleChooseFilesAndDirectories=Choose directory or file\n\ncancel=Cancel\nfileName=File name\nfileType=File type\nallFiles=All files (*.*)\ndesktop=Desktop\ncomputer=Computer\n\n# Used on confirm button when dialog is in OPEN mode\nopen=Open\n# Used on confirm button when dialog is in SAVE mode\nsave=Save\n\n#Buttons tooltips texts\nback=Back\nforward=Forward\nparentDirectory=Parent directory\nnewDirectory=New directory\n\ndirectoryNoLongerExists=Directory does no longer exist!\n\npopupTitle=Message\npopupChooseFile=You must choose a file!\npopupSelectedFileDoesNotExist=Selected files does not exist!\npopupDirectoryDoesNotExist=This directory does not exist!\npopupOnlyDirectories=Only directories are allowed!\npopupFilenameInvalid=File name is invalid!\npopupFileExistOverwrite=This file already exist, do you want to overwrite it?\npopupMultipleFileExistOverwrite=Those files already exist, do you want to overwrite them?\npopupDeleteFileFailed=Error occurred while removing file\n\n#Used when file can't be moved to system trash and has to be deleted permanently\ncontextMenuDelete=Delete\n#Used when file can be moved to system trash\ncontextMenuMoveToTrash=Move to Trash\ncontextMenuNewDirectory=New Directory\ncontextMenuShowInExplorer=Show in Explorer\ncontextMenuRefresh=Refresh\ncontextMenuAddToFavorites=Add To Favorites\ncontextMenuRemoveFromFavorites=Remove From Favorites\ncontextMenuDeleteWarning=This file will be deleted permanently. Are you sure?\ncontextMenuMoveToTrashWarning=This file will be moved to trash. Are you sure?\ncontextMenuSortBy=Sort by\n\nsortByName=Name\nsortByDate=Date modified\nsortBySize=Size\nsortByAscending=Ascending\nsortByDescending=Descending\n\nnewDirectoryDialogTitle=New Directory\nnewDirectoryDialogText=Name:\nnewDirectoryDialogIllegalCharacters=Directory name contains illegal characters\nnewDirectoryDialogAlreadyExists=Directory with that name already exists\n\nchangeViewMode=Change view mode\nviewModeList=List\nviewModeDetails=Details\nviewModeBigIcons=Big icons\nviewModeMediumIcons=Medium icons\nviewModeSmallIcons=Small icons\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/i18n/TabbedPane.properties",
    "content": "#\n# Copyright 2014-2017 See AUTHORS file.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n#TabbedPane I18N file\n\nunsavedDialogTitle=Unsaved changes\nunsavedDialogText=Save changes?\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/skin/x1/default.fnt",
    "content": "info face=\"Vis Open Sans\" size=15 bold=0 italic=0 charset=\"\" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=0,0\ncommon lineHeight=21 base=16 scaleW=256 scaleH=256 pages=1 packed=0\npage id=0 file=\"default.png\"\nchars count=309\nchar id=32   x=0     y=0     width=0     height=0     xoffset=0     yoffset=16    xadvance=4     page=0  chnl=0 \nchar id=968   x=0     y=0     width=11     height=17     xoffset=2     yoffset=4    xadvance=11     page=0  chnl=0 \nchar id=942   x=11     y=0     width=8     height=17     xoffset=2     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=946   x=19     y=0     width=9     height=17     xoffset=2     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=1092   x=28     y=0     width=12     height=17     xoffset=1     yoffset=4    xadvance=11     page=0  chnl=0 \nchar id=124   x=40     y=0     width=3     height=17     xoffset=4     yoffset=4    xadvance=8     page=0  chnl=0 \nchar id=366   x=43     y=0     width=10     height=16     xoffset=2     yoffset=1    xadvance=11     page=0  chnl=0 \nchar id=253   x=53     y=0     width=9     height=16     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=958   x=62     y=0     width=8     height=16     xoffset=1     yoffset=4    xadvance=7     page=0  chnl=0 \nchar id=950   x=70     y=0     width=8     height=16     xoffset=1     yoffset=4    xadvance=7     page=0  chnl=0 \nchar id=199   x=78     y=0     width=10     height=16     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=350   x=88     y=0     width=9     height=16     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=287   x=97     y=0     width=9     height=16     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=106   x=106     y=0     width=5     height=16     xoffset=0     yoffset=5    xadvance=4     page=0  chnl=0 \nchar id=381   x=111     y=0     width=10     height=15     xoffset=1     yoffset=2    xadvance=9     page=0  chnl=0 \nchar id=221   x=121     y=0     width=9     height=15     xoffset=1     yoffset=2    xadvance=8     page=0  chnl=0 \nchar id=356   x=130     y=0     width=9     height=15     xoffset=1     yoffset=2    xadvance=8     page=0  chnl=0 \nchar id=352   x=139     y=0     width=9     height=15     xoffset=1     yoffset=2    xadvance=8     page=0  chnl=0 \nchar id=344   x=148     y=0     width=9     height=15     xoffset=2     yoffset=2    xadvance=9     page=0  chnl=0 \nchar id=327   x=157     y=0     width=10     height=15     xoffset=2     yoffset=2    xadvance=11     page=0  chnl=0 \nchar id=282   x=167     y=0     width=8     height=15     xoffset=2     yoffset=2    xadvance=8     page=0  chnl=0 \nchar id=270   x=175     y=0     width=11     height=15     xoffset=2     yoffset=2    xadvance=11     page=0  chnl=0 \nchar id=268   x=186     y=0     width=10     height=15     xoffset=1     yoffset=2    xadvance=9     page=0  chnl=0 \nchar id=1065   x=196     y=0     width=16     height=15     xoffset=2     yoffset=5    xadvance=16     page=0  chnl=0 \nchar id=1062   x=212     y=0     width=11     height=15     xoffset=2     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=1049   x=223     y=0     width=10     height=15     xoffset=2     yoffset=2    xadvance=11     page=0  chnl=0 \nchar id=1044   x=233     y=0     width=11     height=15     xoffset=1     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=217   x=244     y=0     width=10     height=15     xoffset=2     yoffset=2    xadvance=11     page=0  chnl=0 \nchar id=210   x=0     y=17     width=13     height=15     xoffset=1     yoffset=2    xadvance=12     page=0  chnl=0 \nchar id=204   x=13     y=17     width=4     height=15     xoffset=1     yoffset=2    xadvance=4     page=0  chnl=0 \nchar id=200   x=17     y=17     width=8     height=15     xoffset=2     yoffset=2    xadvance=8     page=0  chnl=0 \nchar id=192   x=25     y=17     width=11     height=15     xoffset=1     yoffset=2    xadvance=10     page=0  chnl=0 \nchar id=218   x=36     y=17     width=10     height=15     xoffset=2     yoffset=2    xadvance=11     page=0  chnl=0 \nchar id=205   x=46     y=17     width=4     height=15     xoffset=2     yoffset=2    xadvance=4     page=0  chnl=0 \nchar id=201   x=50     y=17     width=8     height=15     xoffset=2     yoffset=2    xadvance=8     page=0  chnl=0 \nchar id=193   x=58     y=17     width=11     height=15     xoffset=1     yoffset=2    xadvance=10     page=0  chnl=0 \nchar id=304   x=69     y=17     width=3     height=15     xoffset=2     yoffset=2    xadvance=4     page=0  chnl=0 \nchar id=286   x=72     y=17     width=11     height=15     xoffset=1     yoffset=2    xadvance=11     page=0  chnl=0 \nchar id=379   x=83     y=17     width=10     height=15     xoffset=1     yoffset=2    xadvance=9     page=0  chnl=0 \nchar id=377   x=93     y=17     width=10     height=15     xoffset=1     yoffset=2    xadvance=9     page=0  chnl=0 \nchar id=346   x=103     y=17     width=9     height=15     xoffset=1     yoffset=2    xadvance=8     page=0  chnl=0 \nchar id=211   x=112     y=17     width=13     height=15     xoffset=1     yoffset=2    xadvance=12     page=0  chnl=0 \nchar id=323   x=125     y=17     width=10     height=15     xoffset=2     yoffset=2    xadvance=11     page=0  chnl=0 \nchar id=280   x=135     y=17     width=8     height=15     xoffset=2     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=262   x=143     y=17     width=10     height=15     xoffset=1     yoffset=2    xadvance=9     page=0  chnl=0 \nchar id=260   x=153     y=17     width=11     height=15     xoffset=1     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=209   x=164     y=17     width=10     height=15     xoffset=2     yoffset=2    xadvance=11     page=0  chnl=0 \nchar id=74   x=174     y=17     width=7     height=15     xoffset=-1     yoffset=5    xadvance=4     page=0  chnl=0 \nchar id=1025   x=181     y=17     width=8     height=14     xoffset=2     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=220   x=189     y=17     width=10     height=14     xoffset=2     yoffset=3    xadvance=11     page=0  chnl=0 \nchar id=214   x=199     y=17     width=13     height=14     xoffset=1     yoffset=3    xadvance=12     page=0  chnl=0 \nchar id=196   x=212     y=17     width=11     height=14     xoffset=1     yoffset=3    xadvance=10     page=0  chnl=0 \nchar id=125   x=223     y=17     width=7     height=14     xoffset=1     yoffset=5    xadvance=6     page=0  chnl=0 \nchar id=123   x=230     y=17     width=7     height=14     xoffset=1     yoffset=5    xadvance=6     page=0  chnl=0 \nchar id=93   x=237     y=17     width=5     height=14     xoffset=1     yoffset=5    xadvance=5     page=0  chnl=0 \nchar id=91   x=242     y=17     width=5     height=14     xoffset=2     yoffset=5    xadvance=5     page=0  chnl=0 \nchar id=41   x=247     y=17     width=5     height=14     xoffset=1     yoffset=5    xadvance=4     page=0  chnl=0 \nchar id=40   x=0     y=32     width=5     height=14     xoffset=1     yoffset=5    xadvance=4     page=0  chnl=0 \nchar id=81   x=5     y=32     width=13     height=14     xoffset=1     yoffset=5    xadvance=12     page=0  chnl=0 \nchar id=367   x=18     y=32     width=8     height=13     xoffset=2     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=357   x=26     y=32     width=7     height=13     xoffset=1     yoffset=4    xadvance=5     page=0  chnl=0 \nchar id=271   x=33     y=32     width=13     height=13     xoffset=1     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=8679   x=46     y=32     width=9     height=13     xoffset=3     yoffset=4    xadvance=13     page=0  chnl=0 \nchar id=8984   x=55     y=32     width=14     height=13     xoffset=2     yoffset=4    xadvance=15     page=0  chnl=0 \nchar id=944   x=69     y=32     width=9     height=13     xoffset=2     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=912   x=78     y=32     width=6     height=13     xoffset=1     yoffset=4    xadvance=5     page=0  chnl=0 \nchar id=974   x=84     y=32     width=13     height=13     xoffset=1     yoffset=4    xadvance=12     page=0  chnl=0 \nchar id=967   x=97     y=32     width=10     height=13     xoffset=0     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=966   x=107     y=32     width=12     height=13     xoffset=1     yoffset=8    xadvance=11     page=0  chnl=0 \nchar id=973   x=119     y=32     width=9     height=13     xoffset=2     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=961   x=128     y=32     width=9     height=13     xoffset=2     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=972   x=137     y=32     width=10     height=13     xoffset=1     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=956   x=147     y=32     width=8     height=13     xoffset=2     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=955   x=155     y=32     width=10     height=13     xoffset=0     yoffset=4    xadvance=8     page=0  chnl=0 \nchar id=943   x=165     y=32     width=5     height=13     xoffset=2     yoffset=4    xadvance=5     page=0  chnl=0 \nchar id=952   x=170     y=32     width=10     height=13     xoffset=1     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=951   x=180     y=32     width=8     height=13     xoffset=2     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=941   x=188     y=32     width=8     height=13     xoffset=1     yoffset=4    xadvance=7     page=0  chnl=0 \nchar id=948   x=196     y=32     width=10     height=13     xoffset=1     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=947   x=206     y=32     width=9     height=13     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=940   x=215     y=32     width=10     height=13     xoffset=1     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=911   x=225     y=32     width=14     height=13     xoffset=0     yoffset=4    xadvance=12     page=0  chnl=0 \nchar id=910   x=239     y=32     width=12     height=13     xoffset=0     yoffset=4    xadvance=10     page=0  chnl=0 \nchar id=908   x=0     y=46     width=15     height=13     xoffset=0     yoffset=4    xadvance=12     page=0  chnl=0 \nchar id=906   x=15     y=46     width=6     height=13     xoffset=0     yoffset=4    xadvance=5     page=0  chnl=0 \nchar id=905   x=21     y=46     width=13     height=13     xoffset=0     yoffset=4    xadvance=12     page=0  chnl=0 \nchar id=904   x=34     y=46     width=11     height=13     xoffset=0     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=902   x=45     y=46     width=12     height=13     xoffset=0     yoffset=4    xadvance=10     page=0  chnl=0 \nchar id=1091   x=57     y=46     width=9     height=13     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=1088   x=66     y=46     width=9     height=13     xoffset=2     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=1073   x=75     y=46     width=10     height=13     xoffset=1     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=1051   x=85     y=46     width=11     height=13     xoffset=1     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=231   x=96     y=46     width=8     height=13     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=351   x=104     y=46     width=8     height=13     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=223   x=112     y=46     width=9     height=13     xoffset=2     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=322   x=121     y=46     width=7     height=13     xoffset=0     yoffset=4    xadvance=4     page=0  chnl=0 \nchar id=36   x=128     y=46     width=8     height=13     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=64   x=136     y=46     width=14     height=13     xoffset=1     yoffset=5    xadvance=13     page=0  chnl=0 \nchar id=121   x=150     y=46     width=9     height=13     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=113   x=159     y=46     width=9     height=13     xoffset=1     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=112   x=168     y=46     width=9     height=13     xoffset=2     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=108   x=177     y=46     width=3     height=13     xoffset=2     yoffset=4    xadvance=4     page=0  chnl=0 \nchar id=107   x=180     y=46     width=8     height=13     xoffset=2     yoffset=4    xadvance=8     page=0  chnl=0 \nchar id=104   x=188     y=46     width=8     height=13     xoffset=2     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=103   x=196     y=46     width=9     height=13     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=102   x=205     y=46     width=7     height=13     xoffset=1     yoffset=4    xadvance=5     page=0  chnl=0 \nchar id=100   x=212     y=46     width=9     height=13     xoffset=1     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=98   x=221     y=46     width=9     height=13     xoffset=2     yoffset=4    xadvance=9     page=0  chnl=0 \nchar id=382   x=230     y=46     width=8     height=12     xoffset=1     yoffset=5    xadvance=7     page=0  chnl=0 \nchar id=353   x=238     y=46     width=8     height=12     xoffset=1     yoffset=5    xadvance=7     page=0  chnl=0 \nchar id=345   x=246     y=46     width=7     height=12     xoffset=1     yoffset=5    xadvance=6     page=0  chnl=0 \nchar id=328   x=0     y=59     width=8     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=283   x=8     y=59     width=9     height=12     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=269   x=17     y=59     width=8     height=12     xoffset=1     yoffset=5    xadvance=7     page=0  chnl=0 \nchar id=962   x=25     y=59     width=8     height=12     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=937   x=33     y=59     width=13     height=12     xoffset=1     yoffset=5    xadvance=12     page=0  chnl=0 \nchar id=936   x=46     y=59     width=13     height=12     xoffset=1     yoffset=5    xadvance=12     page=0  chnl=0 \nchar id=935   x=59     y=59     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=934   x=69     y=59     width=13     height=12     xoffset=1     yoffset=5    xadvance=12     page=0  chnl=0 \nchar id=933   x=82     y=59     width=9     height=12     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=932   x=91     y=59     width=9     height=12     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=931   x=100     y=59     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=929   x=110     y=59     width=9     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=928   x=119     y=59     width=10     height=12     xoffset=2     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=927   x=129     y=59     width=13     height=12     xoffset=1     yoffset=5    xadvance=12     page=0  chnl=0 \nchar id=926   x=142     y=59     width=9     height=12     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=925   x=151     y=59     width=10     height=12     xoffset=2     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=924   x=161     y=59     width=13     height=12     xoffset=2     yoffset=5    xadvance=14     page=0  chnl=0 \nchar id=923   x=174     y=59     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=922   x=184     y=59     width=9     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=921   x=193     y=59     width=3     height=12     xoffset=2     yoffset=5    xadvance=4     page=0  chnl=0 \nchar id=920   x=196     y=59     width=13     height=12     xoffset=1     yoffset=5    xadvance=12     page=0  chnl=0 \nchar id=919   x=209     y=59     width=10     height=12     xoffset=2     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=918   x=219     y=59     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=917   x=229     y=59     width=8     height=12     xoffset=2     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=916   x=237     y=59     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=915   x=247     y=59     width=8     height=12     xoffset=2     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=914   x=0     y=71     width=10     height=12     xoffset=2     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=913   x=10     y=71     width=11     height=12     xoffset=1     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=1097   x=21     y=71     width=13     height=12     xoffset=2     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=1094   x=34     y=71     width=9     height=12     xoffset=2     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=1081   x=43     y=71     width=9     height=12     xoffset=2     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=1076   x=52     y=71     width=10     height=12     xoffset=1     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=1071   x=62     y=71     width=10     height=12     xoffset=1     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=1070   x=72     y=71     width=16     height=12     xoffset=2     yoffset=5    xadvance=16     page=0  chnl=0 \nchar id=1069   x=88     y=71     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=1068   x=98     y=71     width=10     height=12     xoffset=2     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=1067   x=108     y=71     width=12     height=12     xoffset=2     yoffset=5    xadvance=13     page=0  chnl=0 \nchar id=1066   x=120     y=71     width=11     height=12     xoffset=1     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=1064   x=131     y=71     width=14     height=12     xoffset=2     yoffset=5    xadvance=15     page=0  chnl=0 \nchar id=1063   x=145     y=71     width=9     height=12     xoffset=2     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=1061   x=154     y=71     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=1060   x=164     y=71     width=13     height=12     xoffset=1     yoffset=5    xadvance=12     page=0  chnl=0 \nchar id=1059   x=177     y=71     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=1058   x=187     y=71     width=9     height=12     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=1057   x=196     y=71     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=1056   x=206     y=71     width=9     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=1055   x=215     y=71     width=10     height=12     xoffset=2     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=1054   x=225     y=71     width=13     height=12     xoffset=1     yoffset=5    xadvance=12     page=0  chnl=0 \nchar id=1053   x=238     y=71     width=10     height=12     xoffset=2     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=1052   x=0     y=83     width=13     height=12     xoffset=2     yoffset=5    xadvance=14     page=0  chnl=0 \nchar id=1050   x=13     y=83     width=9     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=1048   x=22     y=83     width=10     height=12     xoffset=2     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=1047   x=32     y=83     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=1046   x=42     y=83     width=14     height=12     xoffset=1     yoffset=5    xadvance=13     page=0  chnl=0 \nchar id=1045   x=56     y=83     width=8     height=12     xoffset=2     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=1043   x=64     y=83     width=8     height=12     xoffset=2     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=1042   x=72     y=83     width=10     height=12     xoffset=2     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=1041   x=82     y=83     width=9     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=1040   x=91     y=83     width=11     height=12     xoffset=1     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=249   x=102     y=83     width=8     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=242   x=110     y=83     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=236   x=120     y=83     width=4     height=12     xoffset=1     yoffset=5    xadvance=4     page=0  chnl=0 \nchar id=232   x=124     y=83     width=9     height=12     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=224   x=133     y=83     width=8     height=12     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=250   x=141     y=83     width=8     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=237   x=149     y=83     width=4     height=12     xoffset=2     yoffset=5    xadvance=4     page=0  chnl=0 \nchar id=233   x=153     y=83     width=9     height=12     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=225   x=162     y=83     width=8     height=12     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=321   x=170     y=83     width=9     height=12     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=380   x=179     y=83     width=8     height=12     xoffset=1     yoffset=5    xadvance=7     page=0  chnl=0 \nchar id=378   x=187     y=83     width=8     height=12     xoffset=1     yoffset=5    xadvance=7     page=0  chnl=0 \nchar id=347   x=195     y=83     width=8     height=12     xoffset=1     yoffset=5    xadvance=7     page=0  chnl=0 \nchar id=243   x=203     y=83     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=324   x=213     y=83     width=8     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=281   x=221     y=83     width=9     height=12     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=263   x=230     y=83     width=8     height=12     xoffset=1     yoffset=5    xadvance=7     page=0  chnl=0 \nchar id=261   x=238     y=83     width=9     height=12     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=241   x=247     y=83     width=8     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=127   x=0     y=95     width=8     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=38   x=8     y=95     width=12     height=12     xoffset=1     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=35   x=20     y=95     width=11     height=12     xoffset=1     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=37   x=31     y=95     width=13     height=12     xoffset=1     yoffset=5    xadvance=12     page=0  chnl=0 \nchar id=165   x=44     y=95     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=8364   x=54     y=95     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=92   x=64     y=95     width=7     height=12     xoffset=1     yoffset=5    xadvance=6     page=0  chnl=0 \nchar id=47   x=71     y=95     width=7     height=12     xoffset=1     yoffset=5    xadvance=6     page=0  chnl=0 \nchar id=191   x=78     y=95     width=7     height=12     xoffset=1     yoffset=8    xadvance=6     page=0  chnl=0 \nchar id=63   x=85     y=95     width=7     height=12     xoffset=1     yoffset=5    xadvance=6     page=0  chnl=0 \nchar id=33   x=92     y=95     width=3     height=12     xoffset=2     yoffset=5    xadvance=4     page=0  chnl=0 \nchar id=48   x=95     y=95     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=57   x=105     y=95     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=56   x=115     y=95     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=55   x=125     y=95     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=54   x=135     y=95     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=53   x=145     y=95     width=9     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=52   x=154     y=95     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=51   x=164     y=95     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=50   x=174     y=95     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=49   x=184     y=95     width=6     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=105   x=190     y=95     width=3     height=12     xoffset=2     yoffset=5    xadvance=4     page=0  chnl=0 \nchar id=90   x=193     y=95     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=89   x=203     y=95     width=9     height=12     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=88   x=212     y=95     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=87   x=222     y=95     width=15     height=12     xoffset=1     yoffset=5    xadvance=14     page=0  chnl=0 \nchar id=86   x=237     y=95     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=85   x=0     y=107     width=10     height=12     xoffset=2     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=84   x=10     y=107     width=9     height=12     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=83   x=19     y=107     width=9     height=12     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=82   x=28     y=107     width=9     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=80   x=37     y=107     width=9     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=79   x=46     y=107     width=13     height=12     xoffset=1     yoffset=5    xadvance=12     page=0  chnl=0 \nchar id=78   x=59     y=107     width=10     height=12     xoffset=2     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=77   x=69     y=107     width=13     height=12     xoffset=2     yoffset=5    xadvance=14     page=0  chnl=0 \nchar id=76   x=82     y=107     width=8     height=12     xoffset=2     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=75   x=90     y=107     width=9     height=12     xoffset=2     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=73   x=99     y=107     width=3     height=12     xoffset=2     yoffset=5    xadvance=4     page=0  chnl=0 \nchar id=72   x=102     y=107     width=10     height=12     xoffset=2     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=71   x=112     y=107     width=11     height=12     xoffset=1     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=70   x=123     y=107     width=8     height=12     xoffset=2     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=69   x=131     y=107     width=8     height=12     xoffset=2     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=68   x=139     y=107     width=11     height=12     xoffset=2     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=67   x=150     y=107     width=10     height=12     xoffset=1     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=66   x=160     y=107     width=10     height=12     xoffset=2     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=65   x=170     y=107     width=11     height=12     xoffset=1     yoffset=5    xadvance=10     page=0  chnl=0 \nchar id=971   x=181     y=107     width=9     height=11     xoffset=2     yoffset=6    xadvance=9     page=0  chnl=0 \nchar id=970   x=190     y=107     width=6     height=11     xoffset=1     yoffset=6    xadvance=5     page=0  chnl=0 \nchar id=1105   x=196     y=107     width=9     height=11     xoffset=1     yoffset=6    xadvance=8     page=0  chnl=0 \nchar id=252   x=205     y=107     width=8     height=11     xoffset=2     yoffset=6    xadvance=9     page=0  chnl=0 \nchar id=246   x=213     y=107     width=10     height=11     xoffset=1     yoffset=6    xadvance=9     page=0  chnl=0 \nchar id=228   x=223     y=107     width=8     height=11     xoffset=1     yoffset=6    xadvance=8     page=0  chnl=0 \nchar id=59   x=231     y=107     width=4     height=11     xoffset=1     yoffset=8    xadvance=4     page=0  chnl=0 \nchar id=116   x=235     y=107     width=6     height=11     xoffset=1     yoffset=6    xadvance=5     page=0  chnl=0 \nchar id=8997   x=0     y=119     width=17     height=10     xoffset=2     yoffset=7    xadvance=17     page=0  chnl=0 \nchar id=43   x=17     y=119     width=9     height=10     xoffset=1     yoffset=6    xadvance=9     page=0  chnl=0 \nchar id=969   x=26     y=119     width=13     height=9     xoffset=1     yoffset=8    xadvance=12     page=0  chnl=0 \nchar id=965   x=39     y=119     width=9     height=9     xoffset=2     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=964   x=48     y=119     width=8     height=9     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=963   x=56     y=119     width=10     height=9     xoffset=1     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=960   x=66     y=119     width=11     height=9     xoffset=1     yoffset=8    xadvance=10     page=0  chnl=0 \nchar id=959   x=77     y=119     width=10     height=9     xoffset=1     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=957   x=87     y=119     width=9     height=9     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=954   x=96     y=119     width=8     height=9     xoffset=2     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=953   x=104     y=119     width=5     height=9     xoffset=2     yoffset=8    xadvance=5     page=0  chnl=0 \nchar id=949   x=109     y=119     width=8     height=9     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=945   x=117     y=119     width=10     height=9     xoffset=1     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=1103   x=127     y=119     width=8     height=9     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=1102   x=135     y=119     width=12     height=9     xoffset=2     yoffset=8    xadvance=12     page=0  chnl=0 \nchar id=1101   x=147     y=119     width=8     height=9     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=1100   x=155     y=119     width=9     height=9     xoffset=2     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=1099   x=164     y=119     width=11     height=9     xoffset=2     yoffset=8    xadvance=12     page=0  chnl=0 \nchar id=1098   x=175     y=119     width=11     height=9     xoffset=1     yoffset=8    xadvance=10     page=0  chnl=0 \nchar id=1096   x=186     y=119     width=12     height=9     xoffset=2     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=1095   x=198     y=119     width=8     height=9     xoffset=2     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=1093   x=206     y=119     width=9     height=9     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=1090   x=215     y=119     width=8     height=9     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=1089   x=223     y=119     width=8     height=9     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=1087   x=231     y=119     width=8     height=9     xoffset=2     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=1086   x=239     y=119     width=10     height=9     xoffset=1     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=1085   x=0     y=129     width=9     height=9     xoffset=2     yoffset=8    xadvance=10     page=0  chnl=0 \nchar id=1084   x=9     y=129     width=10     height=9     xoffset=2     yoffset=8    xadvance=11     page=0  chnl=0 \nchar id=1083   x=19     y=129     width=9     height=9     xoffset=1     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=1082   x=28     y=129     width=8     height=9     xoffset=2     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=1080   x=36     y=129     width=9     height=9     xoffset=2     yoffset=8    xadvance=10     page=0  chnl=0 \nchar id=1079   x=45     y=129     width=8     height=9     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=1078   x=53     y=129     width=12     height=9     xoffset=1     yoffset=8    xadvance=11     page=0  chnl=0 \nchar id=1077   x=65     y=129     width=9     height=9     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=1075   x=74     y=129     width=6     height=9     xoffset=2     yoffset=8    xadvance=6     page=0  chnl=0 \nchar id=1074   x=80     y=129     width=9     height=9     xoffset=2     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=1072   x=89     y=129     width=8     height=9     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=305   x=97     y=129     width=3     height=9     xoffset=2     yoffset=8    xadvance=4     page=0  chnl=0 \nchar id=58   x=100     y=129     width=3     height=9     xoffset=2     yoffset=8    xadvance=4     page=0  chnl=0 \nchar id=122   x=103     y=129     width=8     height=9     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=120   x=111     y=129     width=9     height=9     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=119   x=120     y=129     width=13     height=9     xoffset=1     yoffset=8    xadvance=12     page=0  chnl=0 \nchar id=118   x=133     y=129     width=9     height=9     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=117   x=142     y=129     width=8     height=9     xoffset=2     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=115   x=150     y=129     width=8     height=9     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=114   x=158     y=129     width=6     height=9     xoffset=2     yoffset=8    xadvance=6     page=0  chnl=0 \nchar id=111   x=164     y=129     width=10     height=9     xoffset=1     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=110   x=174     y=129     width=8     height=9     xoffset=2     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=109   x=182     y=129     width=13     height=9     xoffset=2     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=101   x=195     y=129     width=9     height=9     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=99   x=204     y=129     width=8     height=9     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=97   x=212     y=129     width=8     height=9     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=42   x=220     y=129     width=9     height=8     xoffset=1     yoffset=4    xadvance=8     page=0  chnl=0 \nchar id=94   x=229     y=129     width=9     height=8     xoffset=1     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=62   x=238     y=129     width=10     height=8     xoffset=1     yoffset=7    xadvance=9     page=0  chnl=0 \nchar id=60   x=0     y=138     width=10     height=8     xoffset=1     yoffset=7    xadvance=9     page=0  chnl=0 \nchar id=61   x=10     y=138     width=10     height=5     xoffset=1     yoffset=9    xadvance=9     page=0  chnl=0 \nchar id=44   x=20     y=138     width=4     height=5     xoffset=1     yoffset=14    xadvance=4     page=0  chnl=0 \nchar id=39   x=24     y=138     width=4     height=5     xoffset=1     yoffset=5    xadvance=3     page=0  chnl=0 \nchar id=34   x=28     y=138     width=7     height=5     xoffset=1     yoffset=5    xadvance=6     page=0  chnl=0 \nchar id=8226   x=35     y=138     width=5     height=5     xoffset=2     yoffset=9    xadvance=6     page=0  chnl=0 \nchar id=903   x=40     y=138     width=3     height=3     xoffset=2     yoffset=10    xadvance=4     page=0  chnl=0 \nchar id=126   x=43     y=138     width=10     height=3     xoffset=1     yoffset=10    xadvance=9     page=0  chnl=0 \nchar id=45   x=53     y=138     width=6     height=3     xoffset=1     yoffset=11    xadvance=5     page=0  chnl=0 \nchar id=46   x=59     y=138     width=3     height=3     xoffset=2     yoffset=14    xadvance=4     page=0  chnl=0 \nchar id=96   x=62     y=138     width=4     height=3     xoffset=4     yoffset=5    xadvance=9     page=0  chnl=0 \nchar id=95   x=66     y=138     width=10     height=2     xoffset=0     yoffset=17    xadvance=7     page=0  chnl=0 \n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/skin/x1/font-small.fnt",
    "content": "info face=\"Vis Open Sans\" size=12 bold=0 italic=0 charset=\"\" unicode=0 stretchH=100 smooth=1 aa=1 padding=1,0,0,0 spacing=0,0\ncommon lineHeight=18 base=13 scaleW=256 scaleH=128 pages=1 packed=0\npage id=0 file=\"font-small.png\"\nchars count=309\nchar id=32   x=0     y=0     width=0     height=0     xoffset=0     yoffset=13    xadvance=3     page=0  chnl=0 \nchar id=366   x=0     y=0     width=8     height=15     xoffset=2     yoffset=-1    xadvance=9     page=0  chnl=0 \nchar id=381   x=8     y=0     width=8     height=14     xoffset=1     yoffset=0    xadvance=7     page=0  chnl=0 \nchar id=221   x=16     y=0     width=8     height=14     xoffset=1     yoffset=0    xadvance=7     page=0  chnl=0 \nchar id=356   x=24     y=0     width=8     height=14     xoffset=1     yoffset=0    xadvance=7     page=0  chnl=0 \nchar id=352   x=32     y=0     width=8     height=14     xoffset=1     yoffset=0    xadvance=7     page=0  chnl=0 \nchar id=344   x=40     y=0     width=7     height=14     xoffset=2     yoffset=0    xadvance=7     page=0  chnl=0 \nchar id=327   x=47     y=0     width=8     height=14     xoffset=2     yoffset=0    xadvance=9     page=0  chnl=0 \nchar id=282   x=55     y=0     width=7     height=14     xoffset=2     yoffset=0    xadvance=7     page=0  chnl=0 \nchar id=270   x=62     y=0     width=9     height=14     xoffset=2     yoffset=0    xadvance=9     page=0  chnl=0 \nchar id=268   x=71     y=0     width=9     height=14     xoffset=1     yoffset=0    xadvance=8     page=0  chnl=0 \nchar id=253   x=80     y=0     width=7     height=14     xoffset=1     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=968   x=87     y=0     width=10     height=14     xoffset=1     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=942   x=97     y=0     width=8     height=14     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=946   x=105     y=0     width=8     height=14     xoffset=2     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=1092   x=113     y=0     width=10     height=14     xoffset=1     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=1049   x=123     y=0     width=8     height=14     xoffset=2     yoffset=0    xadvance=9     page=0  chnl=0 \nchar id=217   x=131     y=0     width=8     height=14     xoffset=2     yoffset=0    xadvance=9     page=0  chnl=0 \nchar id=210   x=139     y=0     width=10     height=14     xoffset=1     yoffset=0    xadvance=9     page=0  chnl=0 \nchar id=204   x=149     y=0     width=4     height=14     xoffset=1     yoffset=0    xadvance=3     page=0  chnl=0 \nchar id=200   x=153     y=0     width=7     height=14     xoffset=2     yoffset=0    xadvance=7     page=0  chnl=0 \nchar id=192   x=160     y=0     width=9     height=14     xoffset=1     yoffset=0    xadvance=8     page=0  chnl=0 \nchar id=218   x=169     y=0     width=8     height=14     xoffset=2     yoffset=0    xadvance=9     page=0  chnl=0 \nchar id=205   x=177     y=0     width=4     height=14     xoffset=2     yoffset=0    xadvance=3     page=0  chnl=0 \nchar id=201   x=181     y=0     width=7     height=14     xoffset=2     yoffset=0    xadvance=7     page=0  chnl=0 \nchar id=193   x=188     y=0     width=9     height=14     xoffset=1     yoffset=0    xadvance=8     page=0  chnl=0 \nchar id=199   x=197     y=0     width=9     height=14     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=350   x=206     y=0     width=8     height=14     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=287   x=214     y=0     width=8     height=14     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=286   x=222     y=0     width=10     height=14     xoffset=1     yoffset=0    xadvance=9     page=0  chnl=0 \nchar id=377   x=232     y=0     width=8     height=14     xoffset=1     yoffset=0    xadvance=7     page=0  chnl=0 \nchar id=346   x=240     y=0     width=8     height=14     xoffset=1     yoffset=0    xadvance=7     page=0  chnl=0 \nchar id=211   x=0     y=15     width=10     height=14     xoffset=1     yoffset=0    xadvance=9     page=0  chnl=0 \nchar id=323   x=10     y=15     width=8     height=14     xoffset=2     yoffset=0    xadvance=9     page=0  chnl=0 \nchar id=280   x=18     y=15     width=7     height=14     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=262   x=25     y=15     width=9     height=14     xoffset=1     yoffset=0    xadvance=8     page=0  chnl=0 \nchar id=260   x=34     y=15     width=9     height=14     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=209   x=43     y=15     width=8     height=14     xoffset=2     yoffset=0    xadvance=9     page=0  chnl=0 \nchar id=124   x=51     y=15     width=2     height=14     xoffset=4     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=106   x=53     y=15     width=5     height=14     xoffset=0     yoffset=3    xadvance=3     page=0  chnl=0 \nchar id=958   x=58     y=15     width=7     height=13     xoffset=1     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=950   x=65     y=15     width=7     height=13     xoffset=1     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=1065   x=72     y=15     width=12     height=13     xoffset=2     yoffset=3    xadvance=12     page=0  chnl=0 \nchar id=1062   x=84     y=15     width=9     height=13     xoffset=2     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=1025   x=93     y=15     width=7     height=13     xoffset=2     yoffset=1    xadvance=7     page=0  chnl=0 \nchar id=1044   x=100     y=15     width=9     height=13     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=304   x=109     y=15     width=4     height=13     xoffset=1     yoffset=1    xadvance=3     page=0  chnl=0 \nchar id=220   x=113     y=15     width=8     height=13     xoffset=2     yoffset=1    xadvance=9     page=0  chnl=0 \nchar id=214   x=121     y=15     width=10     height=13     xoffset=1     yoffset=1    xadvance=9     page=0  chnl=0 \nchar id=196   x=131     y=15     width=9     height=13     xoffset=1     yoffset=1    xadvance=8     page=0  chnl=0 \nchar id=379   x=140     y=15     width=8     height=13     xoffset=1     yoffset=1    xadvance=7     page=0  chnl=0 \nchar id=125   x=148     y=15     width=6     height=13     xoffset=1     yoffset=3    xadvance=5     page=0  chnl=0 \nchar id=123   x=154     y=15     width=6     height=13     xoffset=1     yoffset=3    xadvance=5     page=0  chnl=0 \nchar id=93   x=160     y=15     width=5     height=13     xoffset=1     yoffset=3    xadvance=4     page=0  chnl=0 \nchar id=91   x=165     y=15     width=5     height=13     xoffset=1     yoffset=3    xadvance=4     page=0  chnl=0 \nchar id=41   x=170     y=15     width=5     height=13     xoffset=1     yoffset=3    xadvance=4     page=0  chnl=0 \nchar id=40   x=175     y=15     width=5     height=13     xoffset=1     yoffset=3    xadvance=4     page=0  chnl=0 \nchar id=81   x=180     y=15     width=10     height=13     xoffset=1     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=74   x=190     y=15     width=5     height=13     xoffset=0     yoffset=3    xadvance=3     page=0  chnl=0 \nchar id=367   x=195     y=15     width=8     height=12     xoffset=1     yoffset=2    xadvance=7     page=0  chnl=0 \nchar id=8679   x=203     y=15     width=7     height=12     xoffset=3     yoffset=2    xadvance=10     page=0  chnl=0 \nchar id=8984   x=210     y=15     width=11     height=12     xoffset=2     yoffset=2    xadvance=12     page=0  chnl=0 \nchar id=36   x=221     y=15     width=8     height=12     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=64   x=229     y=15     width=12     height=12     xoffset=1     yoffset=3    xadvance=11     page=0  chnl=0 \nchar id=382   x=241     y=15     width=7     height=11     xoffset=1     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=357   x=248     y=15     width=6     height=11     xoffset=1     yoffset=3    xadvance=4     page=0  chnl=0 \nchar id=353   x=0     y=29     width=7     height=11     xoffset=1     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=345   x=7     y=29     width=6     height=11     xoffset=1     yoffset=3    xadvance=5     page=0  chnl=0 \nchar id=328   x=13     y=29     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=283   x=21     y=29     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=271   x=29     y=29     width=11     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=269   x=40     y=29     width=7     height=11     xoffset=1     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=944   x=47     y=29     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=912   x=55     y=29     width=6     height=11     xoffset=0     yoffset=3    xadvance=4     page=0  chnl=0 \nchar id=974   x=61     y=29     width=10     height=11     xoffset=1     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=967   x=71     y=29     width=9     height=11     xoffset=0     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=966   x=80     y=29     width=10     height=11     xoffset=1     yoffset=6    xadvance=9     page=0  chnl=0 \nchar id=973   x=90     y=29     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=961   x=98     y=29     width=8     height=11     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=972   x=106     y=29     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=956   x=114     y=29     width=8     height=11     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=955   x=122     y=29     width=8     height=11     xoffset=0     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=943   x=130     y=29     width=5     height=11     xoffset=1     yoffset=3    xadvance=4     page=0  chnl=0 \nchar id=952   x=135     y=29     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=951   x=143     y=29     width=8     height=11     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=941   x=151     y=29     width=7     height=11     xoffset=1     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=948   x=158     y=29     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=947   x=166     y=29     width=7     height=11     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=940   x=173     y=29     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=911   x=181     y=29     width=10     height=11     xoffset=1     yoffset=3    xadvance=10     page=0  chnl=0 \nchar id=937   x=191     y=29     width=10     height=11     xoffset=1     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=936   x=201     y=29     width=11     height=11     xoffset=1     yoffset=3    xadvance=10     page=0  chnl=0 \nchar id=935   x=212     y=29     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=934   x=220     y=29     width=11     height=11     xoffset=1     yoffset=3    xadvance=10     page=0  chnl=0 \nchar id=910   x=231     y=29     width=10     height=11     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=933   x=241     y=29     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=932   x=0     y=40     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=931   x=8     y=40     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=929   x=16     y=40     width=7     height=11     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=928   x=23     y=40     width=8     height=11     xoffset=2     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=908   x=31     y=40     width=10     height=11     xoffset=1     yoffset=3    xadvance=10     page=0  chnl=0 \nchar id=927   x=41     y=40     width=10     height=11     xoffset=1     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=926   x=51     y=40     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=925   x=59     y=40     width=8     height=11     xoffset=2     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=924   x=67     y=40     width=10     height=11     xoffset=2     yoffset=3    xadvance=11     page=0  chnl=0 \nchar id=923   x=77     y=40     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=922   x=85     y=40     width=7     height=11     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=906   x=92     y=40     width=5     height=11     xoffset=1     yoffset=3    xadvance=4     page=0  chnl=0 \nchar id=921   x=97     y=40     width=3     height=11     xoffset=2     yoffset=3    xadvance=3     page=0  chnl=0 \nchar id=920   x=100     y=40     width=10     height=11     xoffset=1     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=905   x=110     y=40     width=10     height=11     xoffset=1     yoffset=3    xadvance=10     page=0  chnl=0 \nchar id=919   x=120     y=40     width=8     height=11     xoffset=2     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=918   x=128     y=40     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=904   x=136     y=40     width=9     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=917   x=145     y=40     width=7     height=11     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=916   x=152     y=40     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=915   x=160     y=40     width=6     height=11     xoffset=2     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=914   x=166     y=40     width=8     height=11     xoffset=2     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=902   x=174     y=40     width=9     height=11     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=913   x=183     y=40     width=9     height=11     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=1091   x=192     y=40     width=7     height=11     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=1088   x=199     y=40     width=8     height=11     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=1081   x=207     y=40     width=7     height=11     xoffset=2     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=1073   x=214     y=40     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=1071   x=222     y=40     width=8     height=11     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=1070   x=230     y=40     width=13     height=11     xoffset=2     yoffset=3    xadvance=13     page=0  chnl=0 \nchar id=1069   x=243     y=40     width=9     height=11     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=1068   x=0     y=51     width=8     height=11     xoffset=2     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=1067   x=8     y=51     width=9     height=11     xoffset=2     yoffset=3    xadvance=10     page=0  chnl=0 \nchar id=1066   x=17     y=51     width=9     height=11     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=1064   x=26     y=51     width=11     height=11     xoffset=2     yoffset=3    xadvance=12     page=0  chnl=0 \nchar id=1063   x=37     y=51     width=8     height=11     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=1061   x=45     y=51     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=1060   x=53     y=51     width=11     height=11     xoffset=1     yoffset=3    xadvance=10     page=0  chnl=0 \nchar id=1059   x=64     y=51     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=1058   x=72     y=51     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=1057   x=80     y=51     width=9     height=11     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=1056   x=89     y=51     width=7     height=11     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=1055   x=96     y=51     width=8     height=11     xoffset=2     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=1054   x=104     y=51     width=10     height=11     xoffset=1     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=1053   x=114     y=51     width=8     height=11     xoffset=2     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=1052   x=122     y=51     width=10     height=11     xoffset=2     yoffset=3    xadvance=11     page=0  chnl=0 \nchar id=1051   x=132     y=51     width=8     height=11     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=1050   x=140     y=51     width=7     height=11     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=1048   x=147     y=51     width=8     height=11     xoffset=2     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=1047   x=155     y=51     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=1046   x=163     y=51     width=11     height=11     xoffset=1     yoffset=3    xadvance=10     page=0  chnl=0 \nchar id=1045   x=174     y=51     width=7     height=11     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=1043   x=181     y=51     width=6     height=11     xoffset=2     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=1042   x=187     y=51     width=8     height=11     xoffset=2     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=1041   x=195     y=51     width=7     height=11     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=1040   x=202     y=51     width=9     height=11     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=249   x=211     y=51     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=242   x=219     y=51     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=236   x=227     y=51     width=4     height=11     xoffset=0     yoffset=3    xadvance=3     page=0  chnl=0 \nchar id=232   x=231     y=51     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=224   x=239     y=51     width=7     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=250   x=246     y=51     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=237   x=0     y=62     width=4     height=11     xoffset=2     yoffset=3    xadvance=3     page=0  chnl=0 \nchar id=233   x=4     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=225   x=12     y=62     width=7     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=231   x=19     y=62     width=7     height=11     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=351   x=26     y=62     width=7     height=11     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=223   x=33     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=321   x=41     y=62     width=7     height=11     xoffset=1     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=378   x=48     y=62     width=7     height=11     xoffset=1     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=347   x=55     y=62     width=7     height=11     xoffset=1     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=243   x=62     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=324   x=70     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=322   x=78     y=62     width=6     height=11     xoffset=0     yoffset=3    xadvance=3     page=0  chnl=0 \nchar id=281   x=84     y=62     width=8     height=11     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=263   x=92     y=62     width=7     height=11     xoffset=1     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=261   x=99     y=62     width=7     height=11     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=241   x=106     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=127   x=114     y=62     width=6     height=11     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=38   x=120     y=62     width=10     height=11     xoffset=1     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=35   x=130     y=62     width=9     height=11     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=37   x=139     y=62     width=11     height=11     xoffset=1     yoffset=3    xadvance=10     page=0  chnl=0 \nchar id=165   x=150     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=8364   x=158     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=92   x=166     y=62     width=5     height=11     xoffset=1     yoffset=3    xadvance=4     page=0  chnl=0 \nchar id=47   x=171     y=62     width=5     height=11     xoffset=1     yoffset=3    xadvance=4     page=0  chnl=0 \nchar id=63   x=176     y=62     width=6     height=11     xoffset=1     yoffset=3    xadvance=5     page=0  chnl=0 \nchar id=33   x=182     y=62     width=4     height=11     xoffset=1     yoffset=3    xadvance=3     page=0  chnl=0 \nchar id=48   x=186     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=57   x=194     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=56   x=202     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=55   x=210     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=54   x=218     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=53   x=226     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=52   x=234     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=51   x=242     y=62     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=50   x=0     y=73     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=49   x=8     y=73     width=5     height=11     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=121   x=13     y=73     width=7     height=11     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=113   x=20     y=73     width=8     height=11     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=112   x=28     y=73     width=8     height=11     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=108   x=36     y=73     width=2     height=11     xoffset=2     yoffset=3    xadvance=3     page=0  chnl=0 \nchar id=107   x=38     y=73     width=7     height=11     xoffset=1     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=105   x=45     y=73     width=4     height=11     xoffset=1     yoffset=3    xadvance=3     page=0  chnl=0 \nchar id=104   x=49     y=73     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=103   x=57     y=73     width=8     height=11     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=102   x=65     y=73     width=6     height=11     xoffset=1     yoffset=3    xadvance=4     page=0  chnl=0 \nchar id=100   x=71     y=73     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=98   x=79     y=73     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=90   x=87     y=73     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=89   x=95     y=73     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=88   x=103     y=73     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=87   x=111     y=73     width=12     height=11     xoffset=1     yoffset=3    xadvance=11     page=0  chnl=0 \nchar id=86   x=123     y=73     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=85   x=131     y=73     width=8     height=11     xoffset=2     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=84   x=139     y=73     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=83   x=147     y=73     width=8     height=11     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=82   x=155     y=73     width=7     height=11     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=80   x=162     y=73     width=7     height=11     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=79   x=169     y=73     width=10     height=11     xoffset=1     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=78   x=179     y=73     width=8     height=11     xoffset=2     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=77   x=187     y=73     width=10     height=11     xoffset=2     yoffset=3    xadvance=11     page=0  chnl=0 \nchar id=76   x=197     y=73     width=6     height=11     xoffset=2     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=75   x=203     y=73     width=7     height=11     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=73   x=210     y=73     width=3     height=11     xoffset=2     yoffset=3    xadvance=3     page=0  chnl=0 \nchar id=72   x=213     y=73     width=8     height=11     xoffset=2     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=71   x=221     y=73     width=10     height=11     xoffset=1     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=70   x=231     y=73     width=6     height=11     xoffset=2     yoffset=3    xadvance=6     page=0  chnl=0 \nchar id=69   x=237     y=73     width=7     height=11     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=68   x=244     y=73     width=9     height=11     xoffset=2     yoffset=3    xadvance=9     page=0  chnl=0 \nchar id=67   x=0     y=84     width=9     height=11     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=66   x=9     y=84     width=8     height=11     xoffset=2     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=65   x=17     y=84     width=9     height=11     xoffset=1     yoffset=3    xadvance=8     page=0  chnl=0 \nchar id=971   x=26     y=84     width=8     height=10     xoffset=1     yoffset=4    xadvance=7     page=0  chnl=0 \nchar id=962   x=34     y=84     width=7     height=10     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=970   x=41     y=84     width=6     height=10     xoffset=0     yoffset=4    xadvance=4     page=0  chnl=0 \nchar id=1097   x=47     y=84     width=11     height=10     xoffset=2     yoffset=6    xadvance=11     page=0  chnl=0 \nchar id=1094   x=58     y=84     width=8     height=10     xoffset=2     yoffset=6    xadvance=8     page=0  chnl=0 \nchar id=1105   x=66     y=84     width=8     height=10     xoffset=1     yoffset=4    xadvance=7     page=0  chnl=0 \nchar id=1076   x=74     y=84     width=8     height=10     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=252   x=82     y=84     width=8     height=10     xoffset=1     yoffset=4    xadvance=7     page=0  chnl=0 \nchar id=246   x=90     y=84     width=8     height=10     xoffset=1     yoffset=4    xadvance=7     page=0  chnl=0 \nchar id=228   x=98     y=84     width=7     height=10     xoffset=1     yoffset=4    xadvance=7     page=0  chnl=0 \nchar id=380   x=105     y=84     width=7     height=10     xoffset=1     yoffset=4    xadvance=6     page=0  chnl=0 \nchar id=59   x=112     y=84     width=4     height=10     xoffset=1     yoffset=6    xadvance=3     page=0  chnl=0 \nchar id=191   x=116     y=84     width=6     height=10     xoffset=1     yoffset=6    xadvance=5     page=0  chnl=0 \nchar id=8997   x=122     y=84     width=14     height=9     xoffset=1     yoffset=5    xadvance=14     page=0  chnl=0 \nchar id=43   x=136     y=84     width=8     height=9     xoffset=1     yoffset=4    xadvance=7     page=0  chnl=0 \nchar id=116   x=144     y=84     width=5     height=9     xoffset=1     yoffset=5    xadvance=4     page=0  chnl=0 \nchar id=969   x=149     y=84     width=10     height=8     xoffset=1     yoffset=6    xadvance=9     page=0  chnl=0 \nchar id=965   x=159     y=84     width=8     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=964   x=167     y=84     width=7     height=8     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=963   x=174     y=84     width=8     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=960   x=182     y=84     width=9     height=8     xoffset=1     yoffset=6    xadvance=8     page=0  chnl=0 \nchar id=959   x=191     y=84     width=8     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=957   x=199     y=84     width=8     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=954   x=207     y=84     width=6     height=8     xoffset=2     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=953   x=213     y=84     width=5     height=8     xoffset=1     yoffset=6    xadvance=4     page=0  chnl=0 \nchar id=949   x=218     y=84     width=7     height=8     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=945   x=225     y=84     width=8     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=1103   x=233     y=84     width=7     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=1102   x=240     y=84     width=10     height=8     xoffset=2     yoffset=6    xadvance=10     page=0  chnl=0 \nchar id=1101   x=0     y=95     width=7     height=8     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=1100   x=7     y=95     width=7     height=8     xoffset=2     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=1099   x=14     y=95     width=8     height=8     xoffset=2     yoffset=6    xadvance=9     page=0  chnl=0 \nchar id=1098   x=22     y=95     width=9     height=8     xoffset=1     yoffset=6    xadvance=8     page=0  chnl=0 \nchar id=1096   x=31     y=95     width=10     height=8     xoffset=2     yoffset=6    xadvance=11     page=0  chnl=0 \nchar id=1095   x=41     y=95     width=8     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=1093   x=49     y=95     width=7     height=8     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=1090   x=56     y=95     width=7     height=8     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=1089   x=63     y=95     width=7     height=8     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=1087   x=70     y=95     width=8     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=1086   x=78     y=95     width=8     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=1085   x=86     y=95     width=7     height=8     xoffset=2     yoffset=6    xadvance=8     page=0  chnl=0 \nchar id=1084   x=93     y=95     width=8     height=8     xoffset=2     yoffset=6    xadvance=9     page=0  chnl=0 \nchar id=1083   x=101     y=95     width=7     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=1082   x=108     y=95     width=6     height=8     xoffset=2     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=1080   x=114     y=95     width=7     height=8     xoffset=2     yoffset=6    xadvance=8     page=0  chnl=0 \nchar id=1079   x=121     y=95     width=7     height=8     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=1078   x=128     y=95     width=10     height=8     xoffset=1     yoffset=6    xadvance=9     page=0  chnl=0 \nchar id=1077   x=138     y=95     width=8     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=1075   x=146     y=95     width=5     height=8     xoffset=2     yoffset=6    xadvance=5     page=0  chnl=0 \nchar id=1074   x=151     y=95     width=7     height=8     xoffset=2     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=1072   x=158     y=95     width=7     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=305   x=165     y=95     width=2     height=8     xoffset=2     yoffset=6    xadvance=3     page=0  chnl=0 \nchar id=94   x=167     y=95     width=8     height=8     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=62   x=175     y=95     width=8     height=8     xoffset=1     yoffset=5    xadvance=7     page=0  chnl=0 \nchar id=60   x=183     y=95     width=8     height=8     xoffset=1     yoffset=5    xadvance=7     page=0  chnl=0 \nchar id=58   x=191     y=95     width=4     height=8     xoffset=1     yoffset=6    xadvance=3     page=0  chnl=0 \nchar id=122   x=195     y=95     width=7     height=8     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=120   x=202     y=95     width=7     height=8     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=119   x=209     y=95     width=10     height=8     xoffset=1     yoffset=6    xadvance=9     page=0  chnl=0 \nchar id=118   x=219     y=95     width=7     height=8     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=117   x=226     y=95     width=8     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=115   x=234     y=95     width=7     height=8     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=114   x=241     y=95     width=5     height=8     xoffset=2     yoffset=6    xadvance=5     page=0  chnl=0 \nchar id=111   x=246     y=95     width=8     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=110   x=0     y=103     width=8     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=109   x=8     y=103     width=11     height=8     xoffset=2     yoffset=6    xadvance=11     page=0  chnl=0 \nchar id=101   x=19     y=103     width=8     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=99   x=27     y=103     width=7     height=8     xoffset=1     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=97   x=34     y=103     width=7     height=8     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=42   x=41     y=103     width=8     height=7     xoffset=1     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=61   x=49     y=103     width=8     height=5     xoffset=1     yoffset=6    xadvance=7     page=0  chnl=0 \nchar id=44   x=57     y=103     width=4     height=5     xoffset=1     yoffset=11    xadvance=3     page=0  chnl=0 \nchar id=39   x=61     y=103     width=3     height=5     xoffset=1     yoffset=3    xadvance=3     page=0  chnl=0 \nchar id=34   x=64     y=103     width=6     height=5     xoffset=1     yoffset=3    xadvance=5     page=0  chnl=0 \nchar id=8226   x=70     y=103     width=4     height=5     xoffset=2     yoffset=6    xadvance=5     page=0  chnl=0 \nchar id=903   x=74     y=103     width=4     height=4     xoffset=1     yoffset=7    xadvance=3     page=0  chnl=0 \nchar id=126   x=78     y=103     width=8     height=4     xoffset=1     yoffset=7    xadvance=7     page=0  chnl=0 \nchar id=46   x=86     y=103     width=4     height=4     xoffset=1     yoffset=10    xadvance=3     page=0  chnl=0 \nchar id=96   x=90     y=103     width=4     height=4     xoffset=3     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=95   x=94     y=103     width=8     height=3     xoffset=0     yoffset=13    xadvance=5     page=0  chnl=0 \nchar id=45   x=102     y=103     width=5     height=3     xoffset=1     yoffset=8    xadvance=4     page=0  chnl=0 \nkernings count=555\nkerning first=271  second=41  amount=1\nkerning first=950  second=45  amount=-1\nkerning first=929  second=46  amount=-2\nkerning first=34  second=1076  amount=-1\nkerning first=80  second=65  amount=-1\nkerning first=44  second=67  amount=-1\nkerning first=44  second=71  amount=-1\nkerning first=282  second=74  amount=1\nkerning first=44  second=79  amount=-1\nkerning first=44  second=81  amount=-1\nkerning first=46  second=86  amount=-1\nkerning first=192  second=89  amount=-1\nkerning first=77  second=105  amount=-1\nkerning first=84  second=109  amount=-1\nkerning first=89  second=111  amount=-1\nkerning first=84  second=112  amount=-1\nkerning first=84  second=114  amount=-1\nkerning first=84  second=117  amount=-1\nkerning first=271  second=125  amount=1\nkerning first=40  second=74  amount=1\nkerning first=84  second=192  amount=-1\nkerning first=221  second=193  amount=-1\nkerning first=221  second=196  amount=-1\nkerning first=46  second=199  amount=-1\nkerning first=44  second=211  amount=-1\nkerning first=46  second=214  amount=-1\nkerning first=1066  second=1066  amount=-1\nkerning first=89  second=225  amount=-1\nkerning first=356  second=228  amount=-1\nkerning first=84  second=231  amount=-1\nkerning first=39  second=233  amount=-1\nkerning first=77  second=236  amount=-1\nkerning first=77  second=237  amount=-1\nkerning first=356  second=246  amount=-1\nkerning first=84  second=250  amount=-1\nkerning first=356  second=252  amount=-1\nkerning first=39  second=260  amount=-1\nkerning first=84  second=261  amount=-1\nkerning first=46  second=262  amount=-1\nkerning first=84  second=263  amount=-1\nkerning first=44  second=268  amount=-1\nkerning first=34  second=269  amount=-1\nkerning first=221  second=271  amount=-1\nkerning first=34  second=281  amount=-1\nkerning first=221  second=283  amount=-1\nkerning first=46  second=286  amount=-1\nkerning first=1058  second=1105  amount=-1\nkerning first=84  second=351  amount=-1\nkerning first=46  second=81  amount=-1\nkerning first=933  second=902  amount=-1\nkerning first=932  second=913  amount=-1\nkerning first=39  second=916  amount=-1\nkerning first=913  second=932  amount=-1\nkerning first=923  second=933  amount=-1\nkerning first=932  second=934  amount=-1\nkerning first=932  second=940  amount=-1\nkerning first=932  second=941  amount=-1\nkerning first=932  second=942  amount=-1\nkerning first=915  second=944  amount=-1\nkerning first=910  second=945  amount=-1\nkerning first=915  second=949  amount=-1\nkerning first=915  second=951  amount=-1\nkerning first=915  second=954  amount=-1\nkerning first=915  second=956  amount=-1\nkerning first=933  second=959  amount=-1\nkerning first=932  second=961  amount=-1\nkerning first=915  second=962  amount=-1\nkerning first=915  second=965  amount=-1\nkerning first=932  second=968  amount=-1\nkerning first=932  second=969  amount=-1\nkerning first=915  second=971  amount=-1\nkerning first=915  second=973  amount=-1\nkerning first=932  second=974  amount=-1\nkerning first=44  second=1054  amount=-1\nkerning first=46  second=1057  amount=-1\nkerning first=44  second=1066  amount=-1\nkerning first=932  second=966  amount=-1\nkerning first=1058  second=1074  amount=-1\nkerning first=1058  second=1080  amount=-1\nkerning first=1058  second=1081  amount=-1\nkerning first=34  second=1083  amount=-1\nkerning first=1058  second=1084  amount=-1\nkerning first=1043  second=1088  amount=-1\nkerning first=39  second=1089  amount=-1\nkerning first=1098  second=1090  amount=-1\nkerning first=1043  second=1099  amount=-1\nkerning first=39  second=1105  amount=-1\nkerning first=65  second=74  amount=2\nkerning first=221  second=111  amount=-1\nkerning first=39  second=196  amount=-1\nkerning first=932  second=923  amount=-1\nkerning first=1100  second=39  amount=-1\nkerning first=1058  second=1089  amount=-1\nkerning first=89  second=44  amount=-1\nkerning first=77  second=224  amount=-1\nkerning first=356  second=243  amount=-1\nkerning first=221  second=44  amount=-1\nkerning first=321  second=34  amount=-1\nkerning first=1043  second=1094  amount=-1\nkerning first=915  second=913  amount=-1\nkerning first=34  second=271  amount=-1\nkerning first=1058  second=1102  amount=-1\nkerning first=221  second=101  amount=-1\nkerning first=1056  second=1051  amount=-1\nkerning first=260  second=34  amount=-1\nkerning first=1043  second=1097  amount=-1\nkerning first=1058  second=1044  amount=-1\nkerning first=34  second=232  amount=-1\nkerning first=80  second=192  amount=-1\nkerning first=221  second=192  amount=-1\nkerning first=915  second=945  amount=-1\nkerning first=86  second=44  amount=-1\nkerning first=89  second=261  amount=-1\nkerning first=356  second=233  amount=-1\nkerning first=1043  second=1075  amount=-1\nkerning first=1058  second=1076  amount=-1\nkerning first=933  second=940  amount=-1\nkerning first=89  second=196  amount=-1\nkerning first=46  second=211  amount=-1\nkerning first=193  second=221  amount=-1\nkerning first=221  second=263  amount=-1\nkerning first=932  second=956  amount=-1\nkerning first=65  second=84  amount=-1\nkerning first=916  second=932  amount=-1\nkerning first=77  second=233  amount=-1\nkerning first=356  second=249  amount=-1\nkerning first=1090  second=46  amount=-1\nkerning first=1058  second=1099  amount=-1\nkerning first=1058  second=1095  amount=-1\nkerning first=933  second=945  amount=-1\nkerning first=221  second=224  amount=-1\nkerning first=46  second=1090  amount=-1\nkerning first=89  second=193  amount=-1\nkerning first=84  second=281  amount=-1\nkerning first=46  second=71  amount=-1\nkerning first=44  second=199  amount=-1\nkerning first=1040  second=1058  amount=-1\nkerning first=84  second=232  amount=-1\nkerning first=65  second=39  amount=-1\nkerning first=913  second=34  amount=-1\nkerning first=1043  second=1084  amount=-1\nkerning first=192  second=39  amount=-1\nkerning first=260  second=221  amount=-1\nkerning first=221  second=228  amount=-1\nkerning first=356  second=324  amount=-1\nkerning first=80  second=46  amount=-2\nkerning first=89  second=283  amount=-1\nkerning first=932  second=963  amount=-1\nkerning first=221  second=269  amount=-1\nkerning first=1059  second=1051  amount=-1\nkerning first=34  second=1089  amount=-1\nkerning first=70  second=44  amount=-1\nkerning first=271  second=63  amount=1\nkerning first=196  second=356  amount=-1\nkerning first=76  second=39  amount=-1\nkerning first=34  second=1092  amount=-1\nkerning first=356  second=97  amount=-1\nkerning first=193  second=356  amount=-1\nkerning first=1043  second=1087  amount=-1\nkerning first=44  second=221  amount=-1\nkerning first=932  second=944  amount=-1\nkerning first=221  second=225  amount=-1\nkerning first=1059  second=46  amount=-1\nkerning first=196  second=221  amount=-1\nkerning first=34  second=1044  amount=-1\nkerning first=932  second=959  amount=-1\nkerning first=916  second=34  amount=-1\nkerning first=89  second=260  amount=-1\nkerning first=34  second=196  amount=-1\nkerning first=934  second=44  amount=-1\nkerning first=39  second=231  amount=-1\nkerning first=44  second=1058  amount=-1\nkerning first=1100  second=1090  amount=-1\nkerning first=201  second=74  amount=1\nkerning first=46  second=268  amount=-1\nkerning first=84  second=367  amount=-1\nkerning first=915  second=902  amount=-1\nkerning first=1075  second=44  amount=-1\nkerning first=221  second=65  amount=-1\nkerning first=936  second=46  amount=-1\nkerning first=39  second=283  amount=-1\nkerning first=84  second=99  amount=-1\nkerning first=34  second=1040  amount=-1\nkerning first=910  second=902  amount=-1\nkerning first=932  second=46  amount=-1\nkerning first=102  second=39  amount=1\nkerning first=65  second=356  amount=-1\nkerning first=39  second=271  amount=-1\nkerning first=193  second=84  amount=-1\nkerning first=1043  second=1081  amount=-1\nkerning first=1098  second=39  amount=-1\nkerning first=933  second=44  amount=-1\nkerning first=39  second=101  amount=-1\nkerning first=913  second=933  amount=-1\nkerning first=46  second=84  amount=-1\nkerning first=39  second=1092  amount=-1\nkerning first=84  second=225  amount=-1\nkerning first=84  second=246  amount=-1\nkerning first=39  second=111  amount=-1\nkerning first=34  second=283  amount=-1\nkerning first=1058  second=1051  amount=-1\nkerning first=1056  second=1044  amount=-1\nkerning first=39  second=193  amount=-1\nkerning first=910  second=44  amount=-1\nkerning first=34  second=100  amount=-1\nkerning first=89  second=231  amount=-1\nkerning first=1058  second=1088  amount=-1\nkerning first=955  second=39  amount=-1\nkerning first=932  second=962  amount=-1\nkerning first=80  second=44  amount=-2\nkerning first=89  second=271  amount=-1\nkerning first=1043  second=1040  amount=-1\nkerning first=356  second=242  amount=-1\nkerning first=221  second=243  amount=-1\nkerning first=915  second=966  amount=-1\nkerning first=356  second=114  amount=-1\nkerning first=39  second=263  amount=-1\nkerning first=44  second=934  amount=-1\nkerning first=929  second=902  amount=-1\nkerning first=44  second=936  amount=-1\nkerning first=1058  second=1096  amount=-1\nkerning first=193  second=89  amount=-1\nkerning first=932  second=916  amount=-1\nkerning first=89  second=101  amount=-1\nkerning first=196  second=89  amount=-1\nkerning first=39  second=242  amount=-1\nkerning first=34  second=923  amount=-1\nkerning first=193  second=39  amount=-1\nkerning first=84  second=115  amount=-1\nkerning first=39  second=224  amount=-1\nkerning first=356  second=192  amount=-1\nkerning first=356  second=287  amount=-1\nkerning first=193  second=74  amount=2\nkerning first=1043  second=1077  amount=-1\nkerning first=77  second=228  amount=-1\nkerning first=1058  second=1083  amount=-1\nkerning first=356  second=347  amount=-1\nkerning first=89  second=263  amount=-1\nkerning first=932  second=954  amount=-1\nkerning first=34  second=260  amount=-1\nkerning first=80  second=196  amount=-1\nkerning first=902  second=39  amount=-1\nkerning first=192  second=356  amount=-1\nkerning first=39  second=1076  amount=-1\nkerning first=84  second=100  amount=-1\nkerning first=221  second=46  amount=-1\nkerning first=356  second=250  amount=-1\nkerning first=89  second=281  amount=-1\nkerning first=916  second=933  amount=-1\nkerning first=39  second=1040  amount=-1\nkerning first=1043  second=1092  amount=-1\nkerning first=89  second=224  amount=-1\nkerning first=260  second=89  amount=-1\nkerning first=356  second=100  amount=-1\nkerning first=39  second=232  amount=-1\nkerning first=1058  second=1092  amount=-1\nkerning first=34  second=231  amount=-1\nkerning first=89  second=232  amount=-1\nkerning first=356  second=113  amount=-1\nkerning first=84  second=260  amount=-1\nkerning first=46  second=1066  amount=-1\nkerning first=192  second=74  amount=2\nkerning first=46  second=1095  amount=-1\nkerning first=34  second=916  amount=-1\nkerning first=44  second=286  amount=-1\nkerning first=933  second=966  amount=-1\nkerning first=356  second=46  amount=-1\nkerning first=91  second=74  amount=1\nkerning first=196  second=74  amount=2\nkerning first=89  second=269  amount=-1\nkerning first=1075  second=46  amount=-1\nkerning first=1058  second=1075  amount=-1\nkerning first=46  second=356  amount=-1\nkerning first=221  second=97  amount=-1\nkerning first=39  second=65  amount=-1\nkerning first=356  second=99  amount=-1\nkerning first=936  second=44  amount=-1\nkerning first=1090  second=44  amount=-1\nkerning first=44  second=89  amount=-1\nkerning first=356  second=281  amount=-1\nkerning first=34  second=246  amount=-1\nkerning first=1056  second=46  amount=-2\nkerning first=46  second=221  amount=-1\nkerning first=34  second=101  amount=-1\nkerning first=84  second=271  amount=-1\nkerning first=929  second=913  amount=-1\nkerning first=1043  second=44  amount=-1\nkerning first=1058  second=1082  amount=-1\nkerning first=910  second=46  amount=-1\nkerning first=69  second=74  amount=1\nkerning first=923  second=39  amount=-1\nkerning first=915  second=974  amount=-1\nkerning first=39  second=1077  amount=-1\nkerning first=915  second=941  amount=-1\nkerning first=89  second=65  amount=-1\nkerning first=46  second=1058  amount=-1\nkerning first=84  second=283  amount=-1\nkerning first=34  second=913  amount=-1\nkerning first=915  second=959  amount=-1\nkerning first=1058  second=1097  amount=-1\nkerning first=39  second=902  amount=-1\nkerning first=1043  second=1086  amount=-1\nkerning first=356  second=193  amount=-1\nkerning first=916  second=39  amount=-1\nkerning first=84  second=101  amount=-1\nkerning first=902  second=933  amount=-1\nkerning first=933  second=913  amount=-1\nkerning first=1066  second=1058  amount=-1\nkerning first=932  second=945  amount=-1\nkerning first=39  second=246  amount=-1\nkerning first=34  second=224  amount=-1\nkerning first=934  second=46  amount=-1\nkerning first=89  second=97  amount=-1\nkerning first=260  second=74  amount=2\nkerning first=46  second=87  amount=-1\nkerning first=70  second=46  amount=-1\nkerning first=39  second=1083  amount=-1\nkerning first=356  second=115  amount=-1\nkerning first=1056  second=44  amount=-2\nkerning first=77  second=225  amount=-1\nkerning first=929  second=916  amount=-1\nkerning first=356  second=351  amount=-1\nkerning first=44  second=1063  amount=-1\nkerning first=46  second=89  amount=-1\nkerning first=221  second=242  amount=-1\nkerning first=1040  second=1063  amount=-1\nkerning first=356  second=44  amount=-1\nkerning first=89  second=243  amount=-1\nkerning first=356  second=367  amount=-1\nkerning first=910  second=972  amount=-1\nkerning first=932  second=971  amount=-1\nkerning first=89  second=246  amount=-1\nkerning first=221  second=281  amount=-1\nkerning first=39  second=243  amount=-1\nkerning first=84  second=103  amount=-1\nkerning first=65  second=34  amount=-1\nkerning first=76  second=34  amount=-1\nkerning first=910  second=913  amount=-1\nkerning first=1058  second=1094  amount=-1\nkerning first=84  second=224  amount=-1\nkerning first=1058  second=1100  amount=-1\nkerning first=89  second=233  amount=-1\nkerning first=910  second=940  amount=-1\nkerning first=44  second=1057  amount=-1\nkerning first=1056  second=1040  amount=-1\nkerning first=84  second=111  amount=-1\nkerning first=84  second=46  amount=-1\nkerning first=46  second=1098  amount=-1\nkerning first=39  second=1086  amount=-1\nkerning first=356  second=196  amount=-1\nkerning first=913  second=39  amount=-1\nkerning first=915  second=916  amount=-1\nkerning first=321  second=39  amount=-1\nkerning first=221  second=233  amount=-1\nkerning first=192  second=34  amount=-1\nkerning first=39  second=100  amount=-1\nkerning first=933  second=972  amount=-1\nkerning first=84  second=269  amount=-1\nkerning first=77  second=232  amount=-1\nkerning first=39  second=113  amount=-1\nkerning first=260  second=84  amount=-1\nkerning first=1059  second=44  amount=-1\nkerning first=44  second=933  amount=-1\nkerning first=34  second=65  amount=-1\nkerning first=44  second=1095  amount=-1\nkerning first=77  second=281  amount=-1\nkerning first=39  second=923  amount=-1\nkerning first=1058  second=1087  amount=-1\nkerning first=260  second=39  amount=-1\nkerning first=1040  second=1066  amount=-1\nkerning first=46  second=79  amount=-1\nkerning first=221  second=232  amount=-1\nkerning first=915  second=968  amount=-1\nkerning first=1043  second=1105  amount=-1\nkerning first=44  second=84  amount=-1\nkerning first=65  second=221  amount=-1\nkerning first=221  second=113  amount=-1\nkerning first=34  second=1077  amount=-1\nkerning first=910  second=966  amount=-1\nkerning first=932  second=951  amount=-1\nkerning first=80  second=260  amount=-1\nkerning first=356  second=112  amount=-1\nkerning first=910  second=959  amount=-1\nkerning first=356  second=283  amount=-1\nkerning first=1043  second=1080  amount=-1\nkerning first=1058  second=46  amount=-1\nkerning first=1100  second=34  amount=-1\nkerning first=34  second=111  amount=-1\nkerning first=44  second=87  amount=-1\nkerning first=1100  second=1098  amount=-1\nkerning first=221  second=231  amount=-1\nkerning first=923  second=34  amount=-1\nkerning first=89  second=100  amount=-1\nkerning first=1043  second=1085  amount=-1\nkerning first=1040  second=39  amount=-1\nkerning first=1059  second=1044  amount=-1\nkerning first=221  second=99  amount=-1\nkerning first=1066  second=1063  amount=-1\nkerning first=1059  second=1040  amount=-1\nkerning first=1043  second=1083  amount=-1\nkerning first=87  second=46  amount=-1\nkerning first=356  second=261  amount=-1\nkerning first=915  second=942  amount=-1\nkerning first=356  second=260  amount=-1\nkerning first=44  second=262  amount=-1\nkerning first=915  second=44  amount=-1\nkerning first=84  second=110  amount=-1\nkerning first=1043  second=1076  amount=-1\nkerning first=915  second=972  amount=-1\nkerning first=1043  second=1102  amount=-1\nkerning first=910  second=963  amount=-1\nkerning first=34  second=192  amount=-1\nkerning first=196  second=39  amount=-1\nkerning first=192  second=221  amount=-1\nkerning first=923  second=932  amount=-1\nkerning first=46  second=932  amount=-1\nkerning first=46  second=934  amount=-1\nkerning first=46  second=67  amount=-1\nkerning first=34  second=233  amount=-1\nkerning first=34  second=1051  amount=-1\nkerning first=44  second=210  amount=-1\nkerning first=34  second=263  amount=-1\nkerning first=84  second=193  amount=-1\nkerning first=221  second=260  amount=-1\nkerning first=915  second=923  amount=-1\nkerning first=280  second=74  amount=1\nkerning first=44  second=214  amount=-1\nkerning first=84  second=97  amount=-1\nkerning first=260  second=356  amount=-1\nkerning first=1043  second=1082  amount=-1\nkerning first=80  second=193  amount=-1\nkerning first=39  second=192  amount=-1\nkerning first=915  second=961  amount=-1\nkerning first=84  second=113  amount=-1\nkerning first=46  second=1063  amount=-1\nkerning first=1068  second=1066  amount=-1\nkerning first=1043  second=1100  amount=-1\nkerning first=34  second=99  amount=-1\nkerning first=77  second=283  amount=-1\nkerning first=84  second=252  amount=-1\nkerning first=192  second=84  amount=-1\nkerning first=1043  second=46  amount=-1\nkerning first=915  second=969  amount=-1\nkerning first=123  second=74  amount=1\nkerning first=933  second=963  amount=-1\nkerning first=356  second=111  amount=-1\nkerning first=84  second=196  amount=-1\nkerning first=1068  second=1063  amount=-1\nkerning first=87  second=44  amount=-1\nkerning first=39  second=913  amount=-1\nkerning first=84  second=233  amount=-1\nkerning first=902  second=34  amount=-1\nkerning first=915  second=940  amount=-1\nkerning first=1058  second=1077  amount=-1\nkerning first=356  second=271  amount=-1\nkerning first=356  second=231  amount=-1\nkerning first=1043  second=1095  amount=-1\nkerning first=34  second=113  amount=-1\nkerning first=89  second=242  amount=-1\nkerning first=1058  second=44  amount=-1\nkerning first=44  second=86  amount=-1\nkerning first=34  second=902  amount=-1\nkerning first=193  second=34  amount=-1\nkerning first=932  second=949  amount=-1\nkerning first=1058  second=1040  amount=-1\nkerning first=221  second=246  amount=-1\nkerning first=44  second=1098  amount=-1\nkerning first=84  second=243  amount=-1\nkerning first=356  second=101  amount=-1\nkerning first=929  second=923  amount=-1\nkerning first=77  second=97  amount=-1\nkerning first=86  second=46  amount=-1\nkerning first=356  second=110  amount=-1\nkerning first=44  second=356  amount=-1\nkerning first=34  second=1086  amount=-1\nkerning first=356  second=103  amount=-1\nkerning first=932  second=965  amount=-1\nkerning first=34  second=1105  amount=-1\nkerning first=196  second=84  amount=-1\nkerning first=271  second=93  amount=1\nkerning first=89  second=192  amount=-1\nkerning first=932  second=973  amount=-1\nkerning first=221  second=261  amount=-1\nkerning first=84  second=228  amount=-1\nkerning first=1058  second=1085  amount=-1\nkerning first=46  second=933  amount=-1\nkerning first=356  second=109  amount=-1\nkerning first=933  second=46  amount=-1\nkerning first=1068  second=1058  amount=-1\nkerning first=34  second=193  amount=-1\nkerning first=200  second=74  amount=1\nkerning first=356  second=263  amount=-1\nkerning first=84  second=44  amount=-1\nkerning first=932  second=44  amount=-1\nkerning first=932  second=972  amount=-1\nkerning first=1098  second=1098  amount=-1\nkerning first=65  second=89  amount=-1\nkerning first=34  second=243  amount=-1\nkerning first=356  second=224  amount=-1\nkerning first=915  second=963  amount=-1\nkerning first=1043  second=1051  amount=-1\nkerning first=39  second=281  amount=-1\nkerning first=39  second=1044  amount=-1\nkerning first=46  second=936  amount=-1\nkerning first=1040  second=34  amount=-1\nkerning first=84  second=65  amount=-1\nkerning first=910  second=962  amount=-1\nkerning first=933  second=961  amount=-1\nkerning first=1056  second=1083  amount=-1\nkerning first=356  second=117  amount=-1\nkerning first=84  second=287  amount=-1\nkerning first=933  second=962  amount=-1\nkerning first=356  second=232  amount=-1\nkerning first=89  second=113  amount=-1\nkerning first=89  second=228  amount=-1\nkerning first=84  second=347  amount=-1\nkerning first=1043  second=1096  amount=-1\nkerning first=89  second=46  amount=-1\nkerning first=356  second=269  amount=-1\nkerning first=915  second=934  amount=-1\nkerning first=933  second=923  amount=-1\nkerning first=39  second=269  amount=-1\nkerning first=915  second=46  amount=-1\nkerning first=196  second=34  amount=-1\nkerning first=84  second=249  amount=-1\nkerning first=44  second=1090  amount=-1\nkerning first=902  second=932  amount=-1\nkerning first=221  second=100  amount=-1\nkerning first=910  second=916  amount=-1\nkerning first=1098  second=34  amount=-1\nkerning first=46  second=1054  amount=-1\nkerning first=89  second=99  amount=-1\nkerning first=34  second=242  amount=-1\nkerning first=933  second=916  amount=-1\nkerning first=44  second=932  amount=-1\nkerning first=77  second=261  amount=-1\nkerning first=1043  second=1089  amount=-1\nkerning first=932  second=902  amount=-1\nkerning first=356  second=225  amount=-1\nkerning first=910  second=961  amount=-1\nkerning first=1056  second=1076  amount=-1\nkerning first=84  second=324  amount=-1\nkerning first=1058  second=1086  amount=-1\nkerning first=102  second=34  amount=1\nkerning first=39  second=1051  amount=-1\nkerning first=955  second=34  amount=-1\nkerning first=1043  second=1074  amount=-1\nkerning first=1043  second=1044  amount=-1\nkerning first=46  second=210  amount=-1\nkerning first=929  second=44  amount=-2\nkerning first=77  second=101  amount=-1\nkerning first=356  second=65  amount=-1\nkerning first=84  second=242  amount=-1\nkerning first=910  second=923  amount=-1\nkerning first=39  second=99  amount=-1\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/skin/x1/uiskin.atlas",
    "content": "\nuiskin.png\nsize: 512,256\nformat: RGBA8888\nfilter: Nearest,Nearest\nrepeat: none\nborder\n  rotate: false\n  xy: 15, 1\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nborder-circle\n  rotate: false\n  xy: 362, 129\n  size: 14, 14\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\nborder-circle-error\n  rotate: false\n  xy: 377, 129\n  size: 14, 14\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\nborder-dark-blue\n  rotate: false\n  xy: 7, 1\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nborder-error\n  rotate: false\n  xy: 11, 1\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nbutton\n  rotate: false\n  xy: 175, 88\n  size: 12, 20\n  split: 5, 5, 5, 4\n  pad: 4, 4, 1, 1\n  orig: 12, 20\n  offset: 0, 0\n  index: -1\nbutton-blue\n  rotate: false\n  xy: 465, 123\n  size: 12, 20\n  split: 5, 5, 5, 4\n  pad: 4, 4, 1, 1\n  orig: 12, 20\n  offset: 0, 0\n  index: -1\nbutton-down\n  rotate: false\n  xy: 465, 123\n  size: 12, 20\n  split: 5, 5, 5, 4\n  pad: 4, 4, 1, 1\n  orig: 12, 20\n  offset: 0, 0\n  index: -1\nbutton-blue-down\n  rotate: false\n  xy: 29, 31\n  size: 12, 20\n  split: 5, 5, 5, 4\n  pad: 4, 4, 1, 1\n  orig: 12, 20\n  offset: 0, 0\n  index: -1\nbutton-blue-over\n  rotate: false\n  xy: 452, 123\n  size: 12, 20\n  split: 5, 5, 5, 4\n  pad: 4, 4, 1, 1\n  orig: 12, 20\n  offset: 0, 0\n  index: -1\nbutton-over\n  rotate: false\n  xy: 478, 123\n  size: 12, 20\n  split: 5, 5, 5, 4\n  pad: 4, 4, 1, 1\n  orig: 12, 20\n  offset: 0, 0\n  index: -1\nbutton-red\n  rotate: false\n  xy: 491, 123\n  size: 12, 20\n  split: 5, 5, 5, 4\n  pad: 4, 4, 1, 1\n  orig: 12, 20\n  offset: 0, 0\n  index: -1\nbutton-window-bg\n  rotate: false\n  xy: 162, 88\n  size: 12, 20\n  split: 5, 5, 5, 4\n  pad: 4, 4, 1, 1\n  orig: 12, 20\n  offset: 0, 0\n  index: -1\ncheck-off\n  rotate: false\n  xy: 392, 129\n  size: 14, 14\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\ntextfield\n  rotate: false\n  xy: 392, 129\n  size: 14, 14\n  split: 1, 1, 1, 1\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\nvis-check\n  rotate: false\n  xy: 392, 129\n  size: 14, 14\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\ncheck-on\n  rotate: false\n  xy: 407, 129\n  size: 14, 14\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\ncolor-picker-bar-selector\n  rotate: false\n  xy: 504, 129\n  size: 7, 14\n  orig: 7, 14\n  offset: 0, 0\n  index: -1\ncolor-picker-cross\n  rotate: false\n  xy: 51, 67\n  size: 5, 5\n  orig: 5, 5\n  offset: 0, 0\n  index: -1\ncolor-picker-selector-horizontal\n  rotate: false\n  xy: 280, 107\n  size: 3, 1\n  orig: 3, 1\n  offset: 0, 0\n  index: -1\ncolor-picker-selector-vertical\n  rotate: false\n  xy: 510, 208\n  size: 1, 3\n  orig: 1, 3\n  offset: 0, 0\n  index: -1\ncursor\n  rotate: false\n  xy: 510, 206\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\ndefault\n  rotate: false\n  xy: 1, 109\n  size: 254, 146\n  orig: 256, 256\n  offset: 0, 110\n  index: -1\ndefault-pane\n  rotate: false\n  xy: 1, 1\n  size: 5, 3\n  split: 1, 1, 1, 1\n  orig: 5, 3\n  offset: 0, 0\n  index: -1\ndefault-pane-noborder\n  rotate: false\n  xy: 510, 204\n  size: 1, 1\n  split: 0, 0, 0, 0\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\ndefault-select\n  rotate: false\n  xy: 29, 84\n  size: 27, 24\n  split: 4, 16, 0, 24\n  orig: 27, 24\n  offset: 0, 0\n  index: -1\ndefault-select-selection\n  rotate: false\n  xy: 295, 102\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nfont-small\n  rotate: false\n  xy: 256, 144\n  size: 253, 111\n  orig: 256, 128\n  offset: 0, 17\n  index: -1\ngrey\n  rotate: false\n  xy: 510, 202\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nmenu-bg\n  rotate: false\n  xy: 510, 202\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nicon-arrow-left\n  rotate: false\n  xy: 29, 68\n  size: 21, 15\n  orig: 22, 22\n  offset: 1, 4\n  index: -1\nicon-arrow-right\n  rotate: false\n  xy: 57, 93\n  size: 21, 15\n  orig: 22, 22\n  offset: 1, 4\n  index: -1\nicon-close\n  rotate: false\n  xy: 314, 109\n  size: 10, 10\n  orig: 22, 22\n  offset: 6, 6\n  index: -1\nicon-close-titlebar\n  rotate: false\n  xy: 325, 116\n  size: 10, 10\n  orig: 22, 22\n  offset: 6, 6\n  index: -1\nicon-drive\n  rotate: false\n  xy: 1, 5\n  size: 18, 5\n  orig: 22, 22\n  offset: 2, 8\n  index: -1\nicon-file-audio\n  rotate: false\n  xy: 422, 125\n  size: 14, 18\n  orig: 22, 22\n  offset: 4, 2\n  index: -1\nicon-file-image\n  rotate: false\n  xy: 117, 92\n  size: 14, 16\n  orig: 22, 22\n  offset: 4, 3\n  index: -1\nicon-file-pdf\n  rotate: false\n  xy: 437, 125\n  size: 14, 18\n  orig: 22, 22\n  offset: 4, 2\n  index: -1\nicon-file-text\n  rotate: false\n  xy: 132, 92\n  size: 14, 16\n  orig: 22, 22\n  offset: 4, 3\n  index: -1\nicon-folder\n  rotate: false\n  xy: 98, 95\n  size: 18, 13\n  orig: 22, 22\n  offset: 2, 6\n  index: -1\nicon-folder-new\n  rotate: false\n  xy: 29, 52\n  size: 18, 15\n  orig: 22, 22\n  offset: 2, 3\n  index: -1\nicon-folder-parent\n  rotate: false\n  xy: 79, 94\n  size: 18, 14\n  orig: 22, 22\n  offset: 2, 5\n  index: -1\nicon-folder-star\n  rotate: false\n  xy: 326, 129\n  size: 18, 14\n  orig: 22, 22\n  offset: 2, 4\n  index: -1\nicon-list-settings\n  rotate: false\n  xy: 1, 11\n  size: 20, 18\n  orig: 22, 22\n  offset: 2, 1\n  index: -1\nicon-maximize\n  rotate: false\n  xy: 29, 1\n  size: 12, 12\n  orig: 22, 22\n  offset: 5, 5\n  index: -1\nicon-minimize\n  rotate: false\n  xy: 236, 88\n  size: 10, 4\n  orig: 22, 22\n  offset: 6, 5\n  index: -1\nicon-refresh\n  rotate: false\n  xy: 147, 92\n  size: 14, 16\n  orig: 22, 22\n  offset: 4, 3\n  index: -1\nicon-restore\n  rotate: false\n  xy: 236, 93\n  size: 13, 15\n  orig: 22, 22\n  offset: 5, 3\n  index: -1\nicon-star\n  rotate: false\n  xy: 345, 129\n  size: 16, 14\n  orig: 22, 22\n  offset: 3, 4\n  index: -1\nicon-star-outline\n  rotate: false\n  xy: 307, 127\n  size: 18, 16\n  orig: 22, 22\n  offset: 2, 3\n  index: -1\nicon-trash\n  rotate: false\n  xy: 29, 14\n  size: 12, 16\n  orig: 22, 22\n  offset: 5, 3\n  index: -1\nlist-selection\n  rotate: false\n  xy: 510, 200\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nvis-blue\n  rotate: false\n  xy: 510, 200\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\npadded-list-selection\n  rotate: false\n  xy: 343, 127\n  size: 10, 1\n  split: 4, 4, 0, 1\n  orig: 10, 1\n  offset: 0, 0\n  index: -1\nprogressbar\n  rotate: false\n  xy: 510, 239\n  size: 1, 16\n  orig: 1, 16\n  offset: 0, 0\n  index: -1\nprogressbar-filled\n  rotate: false\n  xy: 510, 222\n  size: 1, 16\n  orig: 1, 16\n  offset: 0, 0\n  index: -1\nprogressbar-filled-vertical\n  rotate: false\n  xy: 326, 127\n  size: 16, 1\n  orig: 16, 1\n  offset: 0, 0\n  index: -1\nprogressbar-vertical\n  rotate: false\n  xy: 57, 84\n  size: 16, 1\n  orig: 16, 1\n  offset: 0, 0\n  index: -1\nradio-off\n  rotate: false\n  xy: 250, 94\n  size: 14, 14\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\nradio-on\n  rotate: false\n  xy: 265, 94\n  size: 14, 14\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\nscroll\n  rotate: false\n  xy: 307, 120\n  size: 17, 6\n  split: 2, 2, 2, 2\n  orig: 17, 6\n  offset: 0, 0\n  index: -1\nscroll-horizontal\n  rotate: false\n  xy: 22, 12\n  size: 6, 17\n  split: 2, 2, 0, 17\n  pad: -1, -1, 2, 2\n  orig: 6, 17\n  offset: 0, 0\n  index: -1\nscroll-knob-horizontal\n  rotate: false\n  xy: 42, 34\n  size: 6, 17\n  split: 2, 2, 0, 17\n  pad: -1, -1, 6, 6\n  orig: 6, 17\n  offset: 0, 0\n  index: -1\nscroll-knob-vertical\n  rotate: false\n  xy: 57, 86\n  size: 17, 6\n  split: 6, 6, 2, 2\n  orig: 17, 6\n  offset: 0, 0\n  index: -1\nselect-box-list-bg\n  rotate: false\n  xy: 510, 198\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nwindow-bg\n  rotate: false\n  xy: 510, 198\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nselect-down\n  rotate: false\n  xy: 504, 124\n  size: 7, 4\n  orig: 7, 4\n  offset: 0, 0\n  index: -1\nselect-up\n  rotate: false\n  xy: 504, 119\n  size: 7, 4\n  orig: 7, 4\n  offset: 0, 0\n  index: -1\nselection\n  rotate: false\n  xy: 510, 196\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nseparator\n  rotate: false\n  xy: 510, 194\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\ntree-over\n  rotate: false\n  xy: 510, 194\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nseparator-menu\n  rotate: false\n  xy: 510, 192\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nslider\n  rotate: false\n  xy: 510, 217\n  size: 1, 4\n  orig: 1, 4\n  offset: 0, 0\n  index: -1\nslider-knob\n  rotate: false\n  xy: 188, 86\n  size: 11, 22\n  orig: 11, 22\n  offset: 0, 0\n  index: -1\nslider-knob-disabled\n  rotate: false\n  xy: 200, 86\n  size: 11, 22\n  orig: 11, 22\n  offset: 0, 0\n  index: -1\nslider-knob-down\n  rotate: false\n  xy: 212, 86\n  size: 11, 22\n  orig: 11, 22\n  offset: 0, 0\n  index: -1\nslider-knob-over\n  rotate: false\n  xy: 224, 86\n  size: 11, 22\n  orig: 11, 22\n  offset: 0, 0\n  index: -1\nslider-vertical\n  rotate: false\n  xy: 19, 1\n  size: 4, 1\n  orig: 4, 1\n  offset: 0, 0\n  index: -1\nsplitpane\n  rotate: false\n  xy: 24, 1\n  size: 4, 1\n  orig: 4, 1\n  offset: 0, 0\n  index: -1\nsplitpane-over\n  rotate: false\n  xy: 42, 2\n  size: 4, 1\n  orig: 4, 1\n  offset: 0, 0\n  index: -1\nsplitpane-vertical\n  rotate: false\n  xy: 20, 6\n  size: 1, 4\n  orig: 1, 4\n  offset: 0, 0\n  index: -1\nsplitpane-vertical-over\n  rotate: false\n  xy: 510, 212\n  size: 1, 4\n  orig: 1, 4\n  offset: 0, 0\n  index: -1\nsub-menu\n  rotate: false\n  xy: 345, 119\n  size: 4, 7\n  orig: 4, 7\n  offset: 0, 0\n  index: -1\ntextfield-over\n  rotate: false\n  xy: 284, 106\n  size: 14, 14\n  split: 1, 1, 1, 1\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\nvis-check-over\n  rotate: false\n  xy: 284, 106\n  size: 14, 14\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\ntooltip-bg\n  rotate: false\n  xy: 75, 89\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\ntouchpad-knob\n  rotate: false\n  xy: 284, 121\n  size: 22, 22\n  orig: 22, 22\n  offset: 0, 0\n  index: -1\ntree-minus\n  rotate: false\n  xy: 57, 67\n  size: 5, 5\n  orig: 8, 8\n  offset: 1, 2\n  index: -1\ntree-plus\n  rotate: false\n  xy: 22, 3\n  size: 6, 8\n  orig: 8, 8\n  offset: 1, 0\n  index: -1\ntree-selection\n  rotate: false\n  xy: 79, 90\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nvis-check-down\n  rotate: false\n  xy: 280, 91\n  size: 14, 14\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\nvis-check-tick\n  rotate: false\n  xy: 51, 73\n  size: 10, 10\n  orig: 14, 14\n  offset: 2, 2\n  index: -1\nvis-check-tick-disabled\n  rotate: false\n  xy: 62, 73\n  size: 10, 10\n  orig: 14, 14\n  offset: 2, 2\n  index: -1\nvis-radio\n  rotate: false\n  xy: 42, 19\n  size: 14, 14\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\nvis-radio-down\n  rotate: false\n  xy: 42, 4\n  size: 14, 14\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\nvis-radio-over\n  rotate: false\n  xy: 299, 105\n  size: 14, 14\n  orig: 14, 14\n  offset: 0, 0\n  index: -1\nvis-radio-tick\n  rotate: false\n  xy: 336, 118\n  size: 8, 8\n  orig: 14, 14\n  offset: 3, 3\n  index: -1\nvis-radio-tick-disabled\n  rotate: false\n  xy: 325, 107\n  size: 8, 8\n  orig: 14, 14\n  offset: 3, 3\n  index: -1\nvis-red\n  rotate: false\n  xy: 510, 190\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nwhite\n  rotate: false\n  xy: 314, 105\n  size: 3, 3\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nwindow\n  rotate: false\n  xy: 1, 30\n  size: 27, 34\n  split: 5, 4, 26, 3\n  orig: 27, 34\n  offset: 0, 0\n  index: -1\nwindow-border-bg\n  rotate: false\n  xy: 350, 123\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nwindow-noborder\n  rotate: false\n  xy: 256, 109\n  size: 27, 34\n  split: 5, 4, 26, 3\n  orig: 27, 34\n  offset: 0, 0\n  index: -1\nwindow-resizable\n  rotate: false\n  xy: 1, 65\n  size: 27, 43\n  split: 5, 12, 3, 12\n  pad: 5, 5, 25, 3\n  orig: 27, 43\n  offset: 0, 0\n  index: -1\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/skin/x1/uiskin.json",
    "content": "{\ncom.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: {file: default.fnt },\n\tsmall-font: {file: font-small.fnt }\n},\ncom.badlogic.gdx.graphics.Color: {\n\tblack: {a: 1, b: 0, g: 0, r: 0 },\n\twhite: {a: 1, b: 1, g: 1, r: 1 },\n\tgreen: {a: 1, b: 0, g: 1, r: 0 },\n\tred: {a: 1, b: 0, g: 0, r: 1 },\n\tblue: {a: 1, b: 1, g: 0, r: 0 },\n\tgrey: {a: 1, b: 0.32, g: 0.32, r: 0.32 },\n\tvis-blue: {a: 1, b: 0.886, g: 0.631, r: 0.105 },\n\tvis-red: {a: 1, b: 0.047, g: 0, r: 0.862 },\n\tmenuitem: {a: 1, b: 0.65, g: 0.65, r: 0.65 },\n\tlink-label: {a: 1, b: 0.886, g: 0.631, r: 0.105 }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable: {\n\tdialogDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.45} }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: {\n\tdefault: {down: button-down, up: button },\n\tblue: {down: button-blue-down, up: button-blue },\n\ttoggle: {checked: button-down, down: button-down, up: button }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: {\n\tdefault: {over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, down: button-down, up: button },\n\tblue: {over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, down: button-blue-down, up: button-blue },\n\ttoggle: {font: default-font, fontColor: white, checked: button-down, down: button-down, up: button, over: button-over, disabled: button, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ImageButton$ImageButtonStyle: {\n\tdefault: {down: button-down, up: button },\n\tblue: {down: button-blue-down, up: button-blue },\n\ttoggle: {checked: button-down, down: button-down, up: button }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ImageTextButton$ImageTextButtonStyle: {\n\tdefault: {down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ScrollPane$ScrollPaneStyle: {\n\tlist: {vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal, corner: grey },\n\tdefault: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal, corner: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.SelectBox$SelectBoxStyle: {\n\tdefault: {background: default-select, scrollStyle: default, listStyle: {font: default-font, selection: padded-list-selection, background: select-box-list-bg}, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.SplitPane$SplitPaneStyle: {\n\tdefault-vertical: {handle: splitpane-vertical },\n\tdefault-horizontal: {handle: splitpane }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Window$WindowStyle: {\n\tdefault: {titleFont: default-font, background: window, titleFontColor: white },\n\tresizable: {background: window-resizable, titleFont: default-font, titleFontColor: white },\n\tnoborder: {background: window-noborder, titleFont: default-font, titleFontColor: white },\n\tdialog: {stageBackground: dialogDim, titleFont: default-font, background: window, titleFontColor: white }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ProgressBar$ProgressBarStyle: {\n\tdefault-horizontal: {background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled },\n\tdefault-vertical: {background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle: {\n\tdefault-horizontal: {background: slider, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled },\n\tdefault-vertical: {background: slider-vertical, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {\n\tdefault: {font: default-font, fontColor: white },\n\tlink-label: {fontColor: link-label, font: default-font },\n\tsmall: {font: small-font, fontColor: white },\n\tmenuitem-shortcut: {font: default-font, fontColor: menuitem }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextField$TextFieldStyle: {\n\tdefault: {font: default-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey },\n\tsmall: {font: small-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.CheckBox$CheckBoxStyle: {\n\tdefault: {checkboxOn: check-on, checkboxOff: check-off, font: default-font, fontColor: white, disabledFontColor: grey },\n\tradio: {checkboxOn: radio-on, checkboxOff: radio-off, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.List$ListStyle: {\n\tdefault: {fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Touchpad$TouchpadStyle: {\n\tdefault: {background: default-pane, knob: touchpad-knob }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Tree$TreeStyle: {\n\tdefault: {minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextTooltip$TextTooltipStyle: {\n\tdefault: {background: default-pane, label: {font: default-font, fontColor: white} }\n},\ncom.kotcrab.vis.ui.Sizes: {\n\tdefault: {scaleFactor: 1, spacingBottom: 8, spacingRight: 6, buttonBarSpacing: 10, menuItemIconSize: 22, borderSize: 1, spinnerButtonHeight: 12, spinnerFieldSize: 40, fileChooserViewModeBigIconsSize: 200, fileChooserViewModeMediumIconsSize: 128, fileChooserViewModeSmallIconsSize: 64, fileChooserViewModeListWidthSize: 155 },\n\tx2: {scaleFactor: 2, menuItemIconSize: 44, spinnerButtonHeight: 24, spinnerFieldSize: 80, spacingBottom: 8, spacingRight: 6, buttonBarSpacing: 10, borderSize: 1, fileChooserViewModeBigIconsSize: 200, fileChooserViewModeMediumIconsSize: 128, fileChooserViewModeSmallIconsSize: 64, fileChooserViewModeListWidthSize: 155 }\n},\ncom.kotcrab.vis.ui.widget.VisTextField$VisTextFieldStyle: {\n\tdefault: {focusBorder: border, errorBorder: border-error, font: default-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor },\n\ttextArea: {errorBorder: border-error, font: default-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, cursor: cursor },\n\tsmall: {focusBorder: border, errorBorder: border-error, font: small-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor },\n\tlabel: {selection: selection, errorBorder: border-error, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.VisTextButton$VisTextButtonStyle: {\n\tdefault: {focusBorder: border, down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle: {focusBorder: border, checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey },\n\tblue: {focusBorder: border-dark-blue, down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\tmenu-bar: {over: button-down, font: default-font, fontColor: white, down: button-down, up: button, disabled: button, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.VisImageButton$VisImageButtonStyle: {\n\tdefault: {down: button-down, up: button, over: button-over, disabled: button, focusBorder: border },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue, focusBorder: border-dark-blue },\n\ttoggle: {checked: button-down, focusBorder: border, down: button-down, up: button, over: button-over, disabled: button },\n\tclose: {down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button },\n\tclose-active-tab: {down: button-red, imageUp: icon-close, up: button-blue, over: button-blue-over, disabled: button-blue },\n\tclose-window: {up: button-window-bg, down: button-red, over: button-over, imageUp: icon-close, disabled: button },\n\tclose-titlebar: {imageUp: icon-close-titlebar, down: button-red, up: button, over: button-over, disabled: button }\n},\ncom.kotcrab.vis.ui.widget.VisImageTextButton$VisImageTextButtonStyle: {\n\tdefault: {down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, focusBorder: border },\n\ttoggle: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey, focusBorder: border },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, focusBorder: border-dark-blue },\n\tdefault-noborder: {down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle-noborder: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey },\n\tmenu-bar: {over: button-down, font: default-font, fontColor: white, down: button-down, up: button, disabled: button, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.VisCheckBox$VisCheckBoxStyle: {\n\tdefault: {checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled, focusBorder: border, errorBorder: border-error, font: default-font, fontColor: white, disabledFontColor: grey },\n\tradio: {checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled, focusBorder: border-circle, errorBorder: border-circle-error, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.PopupMenu$PopupMenuStyle: {\n\tnoborder: {background: button },\n\tdefault: {background: button, border: border }\n},\ncom.kotcrab.vis.ui.widget.Menu$MenuStyle: {\n\tdefault: {background: button, border: border, openButtonStyle: menu-bar },\n\tnoborder: {background: button, openButtonStyle: menu-bar }\n},\ncom.kotcrab.vis.ui.widget.MenuBar$MenuBarStyle: {\n\tdefault: {background: menu-bg }\n},\ncom.kotcrab.vis.ui.widget.Separator$SeparatorStyle: {\n\tdefault: {background: separator, thickness: 4 },\n\tvertical: {background: separator, thickness: 4 },\n\tmenu: {background: separator-menu, thickness: 3 }\n},\ncom.kotcrab.vis.ui.widget.VisSplitPane$VisSplitPaneStyle: {\n\tdefault-vertical: {handle: splitpane-vertical, handleOver: splitpane-vertical-over },\n\tdefault-horizontal: {handle: splitpane, handleOver: splitpane-over }\n},\ncom.kotcrab.vis.ui.widget.MultiSplitPane$MultiSplitPaneStyle: {\n\tdefault-vertical: {handle: splitpane-vertical, handleOver: splitpane-vertical-over },\n\tdefault-horizontal: {handle: splitpane, handleOver: splitpane-over }\n},\ncom.kotcrab.vis.ui.widget.MenuItem$MenuItemStyle: {\n\tdefault: {subMenu: sub-menu, down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey, subMenu: sub-menu }\n},\ncom.kotcrab.vis.ui.widget.Tooltip$TooltipStyle: {\n\tdefault: {background: tooltip-bg }\n},\ncom.kotcrab.vis.ui.widget.LinkLabel$LinkLabelStyle: {\n\tdefault: {fontColor: link-label, underline: white, font: default-font }\n},\ncom.kotcrab.vis.ui.widget.tabbedpane.TabbedPane$TabbedPaneStyle: {\n\tdefault: {background: menu-bg, separatorBar: list-selection, vertical: false, buttonStyle: {down: button-down, up: button, checked: button-down, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey} },\n\tvertical: {vertical: true, background: menu-bg, separatorBar: list-selection, buttonStyle: {down: button-down, up: button, checked: button-down, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey} }\n},\ncom.kotcrab.vis.ui.widget.spinner.Spinner$SpinnerStyle: {\n\tdefault: {down: select-down, up: select-up }\n},\ncom.kotcrab.vis.ui.widget.file.FileChooserStyle: {\n\tdefault: {highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right, iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive, iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh, iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio, iconListSettings: icon-list-settings, contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n},\ncom.kotcrab.vis.ui.widget.color.ColorPickerWidgetStyle: {\n\tdefault: {barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right, verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n},\ncom.kotcrab.vis.ui.widget.color.ColorPickerStyle: {\n\tdefault: {pickerStyle: {barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right, verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal}, titleFont: default-font, background: window, titleFontColor: white }\n},\ncom.kotcrab.vis.ui.widget.toast.Toast$ToastStyle: {\n\tdefault: {background: tooltip-bg, closeButtonStyle: close },\n\tdark: {background: window-border-bg, closeButtonStyle: close-window }\n},\ncom.kotcrab.vis.ui.widget.BusyBar$BusyBarStyle: {\n\tdefault: {height: 2, segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 },\n\tslim: {height: 1, segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 },\n\tthick: {height: 6, segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n},\ncom.kotcrab.vis.ui.widget.ListViewStyle: {\n\tdefault: {scrollPaneStyle: list }\n},\ncom.kotcrab.vis.ui.util.form.SimpleFormValidator$FormValidatorStyle: {\n\tdefault: {errorLabelColor: vis-red, validLabelColor: white },\n\tsmooth: {colorTransitionDuration: 0.3, errorLabelColor: vis-red, validLabelColor: white }\n},\ncom.kotcrab.vis.ui.util.adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\tdefault: {background: window-bg, selection: list-selection }\n}\n\n}"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/skin/x2/default.fnt",
    "content": "info face=\"Vis Open Sans\" size=30 bold=0 italic=0 charset=\"\" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=0,0\ncommon lineHeight=42 base=33 scaleW=512 scaleH=256 pages=1 packed=0\npage id=0 file=\"default.png\"\nchars count=309\nchar id=32   x=0     y=0     width=0     height=0     xoffset=0     yoffset=33    xadvance=8     page=0  chnl=0 \nchar id=942   x=0     y=0     width=15     height=32     xoffset=3     yoffset=9    xadvance=18     page=0  chnl=0 \nchar id=253   x=15     y=0     width=16     height=31     xoffset=1     yoffset=10    xadvance=15     page=0  chnl=0 \nchar id=968   x=31     y=0     width=21     height=31     xoffset=3     yoffset=10    xadvance=23     page=0  chnl=0 \nchar id=946   x=52     y=0     width=17     height=31     xoffset=3     yoffset=10    xadvance=19     page=0  chnl=0 \nchar id=1092   x=69     y=0     width=20     height=31     xoffset=2     yoffset=10    xadvance=21     page=0  chnl=0 \nchar id=124   x=89     y=0     width=4     height=31     xoffset=8     yoffset=10    xadvance=17     page=0  chnl=0 \nchar id=106   x=93     y=0     width=10     height=31     xoffset=-1     yoffset=10    xadvance=8     page=0  chnl=0 \nchar id=366   x=103     y=0     width=19     height=30     xoffset=3     yoffset=4    xadvance=22     page=0  chnl=0 \nchar id=958   x=122     y=0     width=14     height=30     xoffset=2     yoffset=10    xadvance=14     page=0  chnl=0 \nchar id=950   x=136     y=0     width=14     height=30     xoffset=2     yoffset=10    xadvance=14     page=0  chnl=0 \nchar id=287   x=150     y=0     width=17     height=30     xoffset=1     yoffset=11    xadvance=16     page=0  chnl=0 \nchar id=381   x=167     y=0     width=16     height=29     xoffset=2     yoffset=5    xadvance=17     page=0  chnl=0 \nchar id=221   x=183     y=0     width=18     height=29     xoffset=1     yoffset=5    xadvance=17     page=0  chnl=0 \nchar id=356   x=201     y=0     width=18     height=29     xoffset=1     yoffset=5    xadvance=17     page=0  chnl=0 \nchar id=352   x=219     y=0     width=15     height=29     xoffset=2     yoffset=5    xadvance=16     page=0  chnl=0 \nchar id=344   x=234     y=0     width=17     height=29     xoffset=4     yoffset=5    xadvance=19     page=0  chnl=0 \nchar id=327   x=251     y=0     width=18     height=29     xoffset=4     yoffset=5    xadvance=23     page=0  chnl=0 \nchar id=282   x=269     y=0     width=14     height=29     xoffset=4     yoffset=5    xadvance=17     page=0  chnl=0 \nchar id=270   x=283     y=0     width=20     height=29     xoffset=3     yoffset=5    xadvance=22     page=0  chnl=0 \nchar id=268   x=303     y=0     width=19     height=29     xoffset=2     yoffset=5    xadvance=19     page=0  chnl=0 \nchar id=1049   x=322     y=0     width=20     height=29     xoffset=3     yoffset=5    xadvance=23     page=0  chnl=0 \nchar id=217   x=342     y=0     width=19     height=29     xoffset=3     yoffset=5    xadvance=22     page=0  chnl=0 \nchar id=210   x=361     y=0     width=22     height=29     xoffset=2     yoffset=5    xadvance=23     page=0  chnl=0 \nchar id=204   x=383     y=0     width=8     height=29     xoffset=0     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=200   x=391     y=0     width=14     height=29     xoffset=4     yoffset=5    xadvance=17     page=0  chnl=0 \nchar id=192   x=405     y=0     width=20     height=29     xoffset=1     yoffset=5    xadvance=19     page=0  chnl=0 \nchar id=218   x=425     y=0     width=19     height=29     xoffset=3     yoffset=5    xadvance=22     page=0  chnl=0 \nchar id=205   x=444     y=0     width=8     height=29     xoffset=3     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=201   x=452     y=0     width=14     height=29     xoffset=4     yoffset=5    xadvance=17     page=0  chnl=0 \nchar id=193   x=466     y=0     width=20     height=29     xoffset=1     yoffset=5    xadvance=19     page=0  chnl=0 \nchar id=199   x=486     y=0     width=19     height=29     xoffset=2     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=350   x=0     y=32     width=15     height=29     xoffset=2     yoffset=12    xadvance=16     page=0  chnl=0 \nchar id=377   x=15     y=32     width=16     height=29     xoffset=2     yoffset=5    xadvance=17     page=0  chnl=0 \nchar id=346   x=31     y=32     width=15     height=29     xoffset=2     yoffset=5    xadvance=16     page=0  chnl=0 \nchar id=211   x=46     y=32     width=22     height=29     xoffset=2     yoffset=5    xadvance=23     page=0  chnl=0 \nchar id=323   x=68     y=32     width=18     height=29     xoffset=4     yoffset=5    xadvance=23     page=0  chnl=0 \nchar id=280   x=86     y=32     width=14     height=29     xoffset=4     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=262   x=100     y=32     width=19     height=29     xoffset=2     yoffset=5    xadvance=19     page=0  chnl=0 \nchar id=260   x=119     y=32     width=21     height=29     xoffset=1     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=1065   x=140     y=32     width=30     height=28     xoffset=3     yoffset=12    xadvance=31     page=0  chnl=0 \nchar id=1062   x=170     y=32     width=21     height=28     xoffset=3     yoffset=12    xadvance=22     page=0  chnl=0 \nchar id=1025   x=191     y=32     width=14     height=28     xoffset=4     yoffset=6    xadvance=17     page=0  chnl=0 \nchar id=1044   x=205     y=32     width=22     height=28     xoffset=1     yoffset=12    xadvance=21     page=0  chnl=0 \nchar id=304   x=227     y=32     width=5     height=28     xoffset=3     yoffset=6    xadvance=8     page=0  chnl=0 \nchar id=286   x=232     y=32     width=20     height=28     xoffset=2     yoffset=6    xadvance=22     page=0  chnl=0 \nchar id=220   x=252     y=32     width=19     height=28     xoffset=3     yoffset=6    xadvance=22     page=0  chnl=0 \nchar id=214   x=271     y=32     width=22     height=28     xoffset=2     yoffset=6    xadvance=23     page=0  chnl=0 \nchar id=196   x=293     y=32     width=20     height=28     xoffset=1     yoffset=6    xadvance=19     page=0  chnl=0 \nchar id=379   x=313     y=32     width=16     height=28     xoffset=2     yoffset=6    xadvance=17     page=0  chnl=0 \nchar id=209   x=329     y=32     width=18     height=28     xoffset=4     yoffset=6    xadvance=23     page=0  chnl=0 \nchar id=74   x=347     y=32     width=12     height=28     xoffset=-2     yoffset=12    xadvance=8     page=0  chnl=0 \nchar id=125   x=359     y=32     width=11     height=27     xoffset=2     yoffset=12    xadvance=11     page=0  chnl=0 \nchar id=123   x=370     y=32     width=11     height=27     xoffset=1     yoffset=12    xadvance=11     page=0  chnl=0 \nchar id=93   x=381     y=32     width=9     height=27     xoffset=1     yoffset=12    xadvance=10     page=0  chnl=0 \nchar id=91   x=390     y=32     width=9     height=27     xoffset=3     yoffset=12    xadvance=10     page=0  chnl=0 \nchar id=41   x=399     y=32     width=9     height=27     xoffset=1     yoffset=12    xadvance=9     page=0  chnl=0 \nchar id=40   x=408     y=32     width=9     height=27     xoffset=2     yoffset=12    xadvance=9     page=0  chnl=0 \nchar id=81   x=417     y=32     width=22     height=27     xoffset=2     yoffset=12    xadvance=23     page=0  chnl=0 \nchar id=944   x=439     y=32     width=16     height=26     xoffset=3     yoffset=8    xadvance=18     page=0  chnl=0 \nchar id=912   x=455     y=32     width=11     height=26     xoffset=1     yoffset=8    xadvance=10     page=0  chnl=0 \nchar id=36   x=466     y=32     width=16     height=26     xoffset=2     yoffset=10    xadvance=17     page=0  chnl=0 \nchar id=367   x=482     y=32     width=15     height=25     xoffset=3     yoffset=9    xadvance=18     page=0  chnl=0 \nchar id=974   x=0     y=61     width=22     height=25     xoffset=2     yoffset=9    xadvance=23     page=0  chnl=0 \nchar id=973   x=22     y=61     width=16     height=25     xoffset=3     yoffset=9    xadvance=18     page=0  chnl=0 \nchar id=972   x=38     y=61     width=17     height=25     xoffset=2     yoffset=9    xadvance=18     page=0  chnl=0 \nchar id=943   x=55     y=61     width=9     height=25     xoffset=3     yoffset=9    xadvance=10     page=0  chnl=0 \nchar id=941   x=64     y=61     width=13     height=25     xoffset=2     yoffset=9    xadvance=14     page=0  chnl=0 \nchar id=940   x=77     y=61     width=18     height=25     xoffset=2     yoffset=9    xadvance=18     page=0  chnl=0 \nchar id=64   x=95     y=61     width=26     height=25     xoffset=2     yoffset=12    xadvance=27     page=0  chnl=0 \nchar id=382   x=121     y=61     width=13     height=24     xoffset=2     yoffset=10    xadvance=14     page=0  chnl=0 \nchar id=357   x=134     y=61     width=12     height=24     xoffset=1     yoffset=10    xadvance=11     page=0  chnl=0 \nchar id=353   x=146     y=61     width=13     height=24     xoffset=2     yoffset=10    xadvance=14     page=0  chnl=0 \nchar id=345   x=159     y=61     width=12     height=24     xoffset=2     yoffset=10    xadvance=12     page=0  chnl=0 \nchar id=328   x=171     y=61     width=15     height=24     xoffset=3     yoffset=10    xadvance=18     page=0  chnl=0 \nchar id=283   x=186     y=61     width=16     height=24     xoffset=2     yoffset=10    xadvance=17     page=0  chnl=0 \nchar id=271   x=202     y=61     width=23     height=24     xoffset=2     yoffset=10    xadvance=18     page=0  chnl=0 \nchar id=269   x=225     y=61     width=14     height=24     xoffset=2     yoffset=10    xadvance=14     page=0  chnl=0 \nchar id=8679   x=239     y=61     width=17     height=24     xoffset=6     yoffset=10    xadvance=25     page=0  chnl=0 \nchar id=8984   x=256     y=61     width=25     height=24     xoffset=4     yoffset=10    xadvance=30     page=0  chnl=0 \nchar id=967   x=281     y=61     width=18     height=24     xoffset=0     yoffset=17    xadvance=16     page=0  chnl=0 \nchar id=966   x=299     y=61     width=21     height=24     xoffset=2     yoffset=17    xadvance=22     page=0  chnl=0 \nchar id=961   x=320     y=61     width=16     height=24     xoffset=3     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=956   x=336     y=61     width=16     height=24     xoffset=3     yoffset=17    xadvance=19     page=0  chnl=0 \nchar id=955   x=352     y=61     width=18     height=24     xoffset=0     yoffset=10    xadvance=16     page=0  chnl=0 \nchar id=952   x=370     y=61     width=17     height=24     xoffset=2     yoffset=10    xadvance=18     page=0  chnl=0 \nchar id=951   x=387     y=61     width=15     height=24     xoffset=3     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=948   x=402     y=61     width=17     height=24     xoffset=2     yoffset=10    xadvance=17     page=0  chnl=0 \nchar id=947   x=419     y=61     width=16     height=24     xoffset=1     yoffset=17    xadvance=15     page=0  chnl=0 \nchar id=911   x=435     y=61     width=25     height=24     xoffset=0     yoffset=10    xadvance=24     page=0  chnl=0 \nchar id=910   x=460     y=61     width=23     height=24     xoffset=0     yoffset=10    xadvance=21     page=0  chnl=0 \nchar id=908   x=483     y=61     width=25     height=24     xoffset=0     yoffset=10    xadvance=24     page=0  chnl=0 \nchar id=906   x=0     y=86     width=10     height=24     xoffset=0     yoffset=10    xadvance=11     page=0  chnl=0 \nchar id=905   x=10     y=86     width=24     height=24     xoffset=0     yoffset=10    xadvance=24     page=0  chnl=0 \nchar id=904   x=34     y=86     width=20     height=24     xoffset=0     yoffset=10    xadvance=19     page=0  chnl=0 \nchar id=902   x=54     y=86     width=20     height=24     xoffset=1     yoffset=10    xadvance=19     page=0  chnl=0 \nchar id=1091   x=74     y=86     width=16     height=24     xoffset=1     yoffset=17    xadvance=15     page=0  chnl=0 \nchar id=1088   x=90     y=86     width=16     height=24     xoffset=3     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=1081   x=106     y=86     width=16     height=24     xoffset=3     yoffset=10    xadvance=19     page=0  chnl=0 \nchar id=1073   x=122     y=86     width=17     height=24     xoffset=2     yoffset=10    xadvance=18     page=0  chnl=0 \nchar id=249   x=139     y=86     width=15     height=24     xoffset=3     yoffset=10    xadvance=18     page=0  chnl=0 \nchar id=242   x=154     y=86     width=17     height=24     xoffset=2     yoffset=10    xadvance=18     page=0  chnl=0 \nchar id=236   x=171     y=86     width=8     height=24     xoffset=0     yoffset=10    xadvance=8     page=0  chnl=0 \nchar id=232   x=179     y=86     width=16     height=24     xoffset=2     yoffset=10    xadvance=17     page=0  chnl=0 \nchar id=224   x=195     y=86     width=15     height=24     xoffset=2     yoffset=10    xadvance=17     page=0  chnl=0 \nchar id=250   x=210     y=86     width=15     height=24     xoffset=3     yoffset=10    xadvance=18     page=0  chnl=0 \nchar id=237   x=225     y=86     width=8     height=24     xoffset=3     yoffset=10    xadvance=8     page=0  chnl=0 \nchar id=233   x=233     y=86     width=16     height=24     xoffset=2     yoffset=10    xadvance=17     page=0  chnl=0 \nchar id=225   x=249     y=86     width=15     height=24     xoffset=2     yoffset=10    xadvance=17     page=0  chnl=0 \nchar id=231   x=264     y=86     width=14     height=24     xoffset=2     yoffset=17    xadvance=14     page=0  chnl=0 \nchar id=351   x=278     y=86     width=13     height=24     xoffset=2     yoffset=17    xadvance=14     page=0  chnl=0 \nchar id=223   x=291     y=86     width=17     height=24     xoffset=3     yoffset=10    xadvance=19     page=0  chnl=0 \nchar id=378   x=308     y=86     width=13     height=24     xoffset=2     yoffset=10    xadvance=14     page=0  chnl=0 \nchar id=347   x=321     y=86     width=13     height=24     xoffset=2     yoffset=10    xadvance=14     page=0  chnl=0 \nchar id=243   x=334     y=86     width=17     height=24     xoffset=2     yoffset=10    xadvance=18     page=0  chnl=0 \nchar id=324   x=351     y=86     width=15     height=24     xoffset=3     yoffset=10    xadvance=18     page=0  chnl=0 \nchar id=322   x=366     y=86     width=11     height=24     xoffset=0     yoffset=10    xadvance=8     page=0  chnl=0 \nchar id=281   x=377     y=86     width=16     height=24     xoffset=2     yoffset=17    xadvance=17     page=0  chnl=0 \nchar id=263   x=393     y=86     width=14     height=24     xoffset=2     yoffset=10    xadvance=14     page=0  chnl=0 \nchar id=261   x=407     y=86     width=16     height=24     xoffset=2     yoffset=17    xadvance=17     page=0  chnl=0 \nchar id=121   x=423     y=86     width=16     height=24     xoffset=1     yoffset=17    xadvance=15     page=0  chnl=0 \nchar id=113   x=439     y=86     width=16     height=24     xoffset=2     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=112   x=455     y=86     width=16     height=24     xoffset=3     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=108   x=471     y=86     width=5     height=24     xoffset=3     yoffset=10    xadvance=8     page=0  chnl=0 \nchar id=107   x=476     y=86     width=15     height=24     xoffset=3     yoffset=10    xadvance=16     page=0  chnl=0 \nchar id=105   x=491     y=86     width=5     height=24     xoffset=3     yoffset=10    xadvance=8     page=0  chnl=0 \nchar id=104   x=496     y=86     width=15     height=24     xoffset=3     yoffset=10    xadvance=18     page=0  chnl=0 \nchar id=103   x=0     y=110     width=17     height=24     xoffset=1     yoffset=17    xadvance=16     page=0  chnl=0 \nchar id=102   x=17     y=110     width=14     height=24     xoffset=1     yoffset=10    xadvance=10     page=0  chnl=0 \nchar id=100   x=31     y=110     width=16     height=24     xoffset=2     yoffset=10    xadvance=18     page=0  chnl=0 \nchar id=98   x=47     y=110     width=16     height=24     xoffset=3     yoffset=10    xadvance=18     page=0  chnl=0 \nchar id=971   x=63     y=110     width=16     height=23     xoffset=3     yoffset=11    xadvance=18     page=0  chnl=0 \nchar id=962   x=79     y=110     width=14     height=23     xoffset=2     yoffset=17    xadvance=14     page=0  chnl=0 \nchar id=970   x=93     y=110     width=11     height=23     xoffset=1     yoffset=11    xadvance=10     page=0  chnl=0 \nchar id=1097   x=104     y=110     width=26     height=23     xoffset=3     yoffset=17    xadvance=27     page=0  chnl=0 \nchar id=1094   x=130     y=110     width=18     height=23     xoffset=3     yoffset=17    xadvance=19     page=0  chnl=0 \nchar id=1105   x=148     y=110     width=16     height=23     xoffset=2     yoffset=11    xadvance=17     page=0  chnl=0 \nchar id=1076   x=164     y=110     width=18     height=23     xoffset=1     yoffset=17    xadvance=17     page=0  chnl=0 \nchar id=1051   x=182     y=110     width=20     height=23     xoffset=1     yoffset=12    xadvance=21     page=0  chnl=0 \nchar id=252   x=202     y=110     width=15     height=23     xoffset=3     yoffset=11    xadvance=18     page=0  chnl=0 \nchar id=246   x=217     y=110     width=17     height=23     xoffset=2     yoffset=11    xadvance=18     page=0  chnl=0 \nchar id=228   x=234     y=110     width=15     height=23     xoffset=2     yoffset=11    xadvance=17     page=0  chnl=0 \nchar id=380   x=249     y=110     width=13     height=23     xoffset=2     yoffset=11    xadvance=14     page=0  chnl=0 \nchar id=241   x=262     y=110     width=15     height=23     xoffset=3     yoffset=11    xadvance=18     page=0  chnl=0 \nchar id=191   x=277     y=110     width=14     height=23     xoffset=1     yoffset=17    xadvance=13     page=0  chnl=0 \nchar id=937   x=291     y=110     width=22     height=22     xoffset=2     yoffset=12    xadvance=23     page=0  chnl=0 \nchar id=936   x=313     y=110     width=23     height=22     xoffset=2     yoffset=12    xadvance=24     page=0  chnl=0 \nchar id=935   x=336     y=110     width=18     height=22     xoffset=1     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=934   x=354     y=110     width=23     height=22     xoffset=2     yoffset=12    xadvance=24     page=0  chnl=0 \nchar id=933   x=377     y=110     width=18     height=22     xoffset=1     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=932   x=395     y=110     width=18     height=22     xoffset=1     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=931   x=413     y=110     width=17     height=22     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=929   x=430     y=110     width=16     height=22     xoffset=3     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=928   x=446     y=110     width=19     height=22     xoffset=3     yoffset=12    xadvance=22     page=0  chnl=0 \nchar id=927   x=465     y=110     width=22     height=22     xoffset=2     yoffset=12    xadvance=23     page=0  chnl=0 \nchar id=926   x=487     y=110     width=16     height=22     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=925   x=0     y=134     width=18     height=22     xoffset=4     yoffset=12    xadvance=23     page=0  chnl=0 \nchar id=924   x=18     y=134     width=24     height=22     xoffset=3     yoffset=12    xadvance=27     page=0  chnl=0 \nchar id=923   x=42     y=134     width=19     height=22     xoffset=1     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=922   x=61     y=134     width=17     height=22     xoffset=3     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=921   x=78     y=134     width=5     height=22     xoffset=3     yoffset=12    xadvance=8     page=0  chnl=0 \nchar id=920   x=83     y=134     width=22     height=22     xoffset=2     yoffset=12    xadvance=23     page=0  chnl=0 \nchar id=919   x=105     y=134     width=19     height=22     xoffset=3     yoffset=12    xadvance=22     page=0  chnl=0 \nchar id=918   x=124     y=134     width=16     height=22     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=917   x=140     y=134     width=14     height=22     xoffset=4     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=916   x=154     y=134     width=18     height=22     xoffset=1     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=915   x=172     y=134     width=14     height=22     xoffset=4     yoffset=12    xadvance=16     page=0  chnl=0 \nchar id=914   x=186     y=134     width=17     height=22     xoffset=3     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=913   x=203     y=134     width=20     height=22     xoffset=1     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=1071   x=223     y=134     width=18     height=22     xoffset=1     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=1070   x=241     y=134     width=30     height=22     xoffset=3     yoffset=12    xadvance=32     page=0  chnl=0 \nchar id=1069   x=271     y=134     width=19     height=22     xoffset=1     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=1068   x=290     y=134     width=17     height=22     xoffset=3     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=1067   x=307     y=134     width=23     height=22     xoffset=3     yoffset=12    xadvance=26     page=0  chnl=0 \nchar id=1066   x=330     y=134     width=21     height=22     xoffset=1     yoffset=12    xadvance=21     page=0  chnl=0 \nchar id=1064   x=351     y=134     width=28     height=22     xoffset=3     yoffset=12    xadvance=31     page=0  chnl=0 \nchar id=1063   x=379     y=134     width=18     height=22     xoffset=3     yoffset=12    xadvance=21     page=0  chnl=0 \nchar id=1061   x=397     y=134     width=18     height=22     xoffset=1     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=1060   x=415     y=134     width=23     height=22     xoffset=2     yoffset=12    xadvance=24     page=0  chnl=0 \nchar id=1059   x=438     y=134     width=20     height=22     xoffset=1     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=1058   x=458     y=134     width=18     height=22     xoffset=1     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=1057   x=476     y=134     width=19     height=22     xoffset=2     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=1056   x=495     y=134     width=16     height=22     xoffset=3     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=1055   x=0     y=156     width=19     height=22     xoffset=3     yoffset=12    xadvance=22     page=0  chnl=0 \nchar id=1054   x=19     y=156     width=22     height=22     xoffset=2     yoffset=12    xadvance=23     page=0  chnl=0 \nchar id=1053   x=41     y=156     width=19     height=22     xoffset=3     yoffset=12    xadvance=22     page=0  chnl=0 \nchar id=1052   x=60     y=156     width=24     height=22     xoffset=3     yoffset=12    xadvance=27     page=0  chnl=0 \nchar id=1050   x=84     y=156     width=17     height=22     xoffset=3     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=1048   x=101     y=156     width=20     height=22     xoffset=3     yoffset=12    xadvance=23     page=0  chnl=0 \nchar id=1047   x=121     y=156     width=16     height=22     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=1046   x=137     y=156     width=26     height=22     xoffset=1     yoffset=12    xadvance=25     page=0  chnl=0 \nchar id=1045   x=163     y=156     width=14     height=22     xoffset=4     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=1043   x=177     y=156     width=14     height=22     xoffset=4     yoffset=12    xadvance=16     page=0  chnl=0 \nchar id=1042   x=191     y=156     width=17     height=22     xoffset=3     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=1041   x=208     y=156     width=16     height=22     xoffset=3     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=1040   x=224     y=156     width=20     height=22     xoffset=1     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=321   x=244     y=156     width=17     height=22     xoffset=1     yoffset=12    xadvance=16     page=0  chnl=0 \nchar id=127   x=261     y=156     width=13     height=22     xoffset=4     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=38   x=274     y=156     width=22     height=22     xoffset=2     yoffset=12    xadvance=22     page=0  chnl=0 \nchar id=35   x=296     y=156     width=20     height=22     xoffset=1     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=37   x=316     y=156     width=24     height=22     xoffset=2     yoffset=12    xadvance=25     page=0  chnl=0 \nchar id=165   x=340     y=156     width=18     height=22     xoffset=1     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=8364   x=358     y=156     width=19     height=22     xoffset=1     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=92   x=377     y=156     width=12     height=22     xoffset=1     yoffset=12    xadvance=11     page=0  chnl=0 \nchar id=47   x=389     y=156     width=12     height=22     xoffset=1     yoffset=12    xadvance=11     page=0  chnl=0 \nchar id=63   x=401     y=156     width=14     height=22     xoffset=1     yoffset=12    xadvance=13     page=0  chnl=0 \nchar id=33   x=415     y=156     width=5     height=22     xoffset=3     yoffset=12    xadvance=8     page=0  chnl=0 \nchar id=48   x=420     y=156     width=16     height=22     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=57   x=436     y=156     width=16     height=22     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=56   x=452     y=156     width=16     height=22     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=55   x=468     y=156     width=16     height=22     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=54   x=484     y=156     width=16     height=22     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=53   x=0     y=178     width=16     height=22     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=52   x=16     y=178     width=18     height=22     xoffset=1     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=51   x=34     y=178     width=16     height=22     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=50   x=50     y=178     width=16     height=22     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=49   x=66     y=178     width=10     height=22     xoffset=3     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=90   x=76     y=178     width=16     height=22     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=89   x=92     y=178     width=18     height=22     xoffset=1     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=88   x=110     y=178     width=18     height=22     xoffset=1     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=87   x=128     y=178     width=29     height=22     xoffset=1     yoffset=12    xadvance=28     page=0  chnl=0 \nchar id=86   x=157     y=178     width=19     height=22     xoffset=1     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=85   x=176     y=178     width=19     height=22     xoffset=3     yoffset=12    xadvance=22     page=0  chnl=0 \nchar id=84   x=195     y=178     width=18     height=22     xoffset=1     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=83   x=213     y=178     width=15     height=22     xoffset=2     yoffset=12    xadvance=16     page=0  chnl=0 \nchar id=82   x=228     y=178     width=17     height=22     xoffset=4     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=80   x=245     y=178     width=16     height=22     xoffset=3     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=79   x=261     y=178     width=22     height=22     xoffset=2     yoffset=12    xadvance=23     page=0  chnl=0 \nchar id=78   x=283     y=178     width=18     height=22     xoffset=4     yoffset=12    xadvance=23     page=0  chnl=0 \nchar id=77   x=301     y=178     width=24     height=22     xoffset=3     yoffset=12    xadvance=27     page=0  chnl=0 \nchar id=76   x=325     y=178     width=14     height=22     xoffset=4     yoffset=12    xadvance=16     page=0  chnl=0 \nchar id=75   x=339     y=178     width=17     height=22     xoffset=3     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=73   x=356     y=178     width=5     height=22     xoffset=3     yoffset=12    xadvance=8     page=0  chnl=0 \nchar id=72   x=361     y=178     width=19     height=22     xoffset=3     yoffset=12    xadvance=22     page=0  chnl=0 \nchar id=71   x=380     y=178     width=20     height=22     xoffset=2     yoffset=12    xadvance=22     page=0  chnl=0 \nchar id=70   x=400     y=178     width=14     height=22     xoffset=3     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=69   x=414     y=178     width=14     height=22     xoffset=4     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=68   x=428     y=178     width=20     height=22     xoffset=3     yoffset=12    xadvance=22     page=0  chnl=0 \nchar id=67   x=448     y=178     width=19     height=22     xoffset=2     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=66   x=467     y=178     width=17     height=22     xoffset=3     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=65   x=484     y=178     width=20     height=22     xoffset=1     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=59   x=504     y=178     width=7     height=21     xoffset=1     yoffset=17    xadvance=8     page=0  chnl=0 \nchar id=116   x=0     y=200     width=12     height=21     xoffset=1     yoffset=13    xadvance=11     page=0  chnl=0 \nchar id=8997   x=12     y=200     width=32     height=19     xoffset=3     yoffset=15    xadvance=35     page=0  chnl=0 \nchar id=969   x=44     y=200     width=22     height=17     xoffset=2     yoffset=17    xadvance=23     page=0  chnl=0 \nchar id=965   x=66     y=200     width=16     height=17     xoffset=3     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=964   x=82     y=200     width=15     height=17     xoffset=1     yoffset=17    xadvance=14     page=0  chnl=0 \nchar id=963   x=97     y=200     width=18     height=17     xoffset=2     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=960   x=115     y=200     width=21     height=17     xoffset=1     yoffset=17    xadvance=20     page=0  chnl=0 \nchar id=959   x=136     y=200     width=17     height=17     xoffset=2     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=957   x=153     y=200     width=16     height=17     xoffset=1     yoffset=17    xadvance=16     page=0  chnl=0 \nchar id=954   x=169     y=200     width=15     height=17     xoffset=3     yoffset=17    xadvance=16     page=0  chnl=0 \nchar id=953   x=184     y=200     width=9     height=17     xoffset=3     yoffset=17    xadvance=10     page=0  chnl=0 \nchar id=949   x=193     y=200     width=13     height=17     xoffset=2     yoffset=17    xadvance=14     page=0  chnl=0 \nchar id=945   x=206     y=200     width=18     height=17     xoffset=2     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=1103   x=224     y=200     width=16     height=17     xoffset=1     yoffset=17    xadvance=17     page=0  chnl=0 \nchar id=1102   x=240     y=200     width=23     height=17     xoffset=3     yoffset=17    xadvance=25     page=0  chnl=0 \nchar id=1101   x=263     y=200     width=15     height=17     xoffset=1     yoffset=17    xadvance=15     page=0  chnl=0 \nchar id=1100   x=278     y=200     width=16     height=17     xoffset=3     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=1099   x=294     y=200     width=20     height=17     xoffset=3     yoffset=17    xadvance=23     page=0  chnl=0 \nchar id=1098   x=314     y=200     width=21     height=17     xoffset=1     yoffset=17    xadvance=21     page=0  chnl=0 \nchar id=1096   x=335     y=200     width=24     height=17     xoffset=3     yoffset=17    xadvance=27     page=0  chnl=0 \nchar id=1095   x=359     y=200     width=15     height=17     xoffset=3     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=1093   x=374     y=200     width=17     height=17     xoffset=1     yoffset=17    xadvance=16     page=0  chnl=0 \nchar id=1090   x=391     y=200     width=15     height=17     xoffset=1     yoffset=17    xadvance=14     page=0  chnl=0 \nchar id=1089   x=406     y=200     width=14     height=17     xoffset=2     yoffset=17    xadvance=14     page=0  chnl=0 \nchar id=1087   x=420     y=200     width=16     height=17     xoffset=3     yoffset=17    xadvance=19     page=0  chnl=0 \nchar id=1086   x=436     y=200     width=17     height=17     xoffset=2     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=1085   x=453     y=200     width=16     height=17     xoffset=3     yoffset=17    xadvance=19     page=0  chnl=0 \nchar id=1084   x=469     y=200     width=19     height=17     xoffset=3     yoffset=17    xadvance=22     page=0  chnl=0 \nchar id=1083   x=488     y=200     width=16     height=17     xoffset=1     yoffset=17    xadvance=17     page=0  chnl=0 \nchar id=1082   x=0     y=221     width=15     height=17     xoffset=3     yoffset=17    xadvance=16     page=0  chnl=0 \nchar id=1080   x=15     y=221     width=16     height=17     xoffset=3     yoffset=17    xadvance=19     page=0  chnl=0 \nchar id=1079   x=31     y=221     width=14     height=17     xoffset=1     yoffset=17    xadvance=14     page=0  chnl=0 \nchar id=1078   x=45     y=221     width=23     height=17     xoffset=1     yoffset=17    xadvance=22     page=0  chnl=0 \nchar id=1077   x=68     y=221     width=16     height=17     xoffset=2     yoffset=17    xadvance=17     page=0  chnl=0 \nchar id=1075   x=84     y=221     width=12     height=17     xoffset=3     yoffset=17    xadvance=13     page=0  chnl=0 \nchar id=1074   x=96     y=221     width=16     height=17     xoffset=3     yoffset=17    xadvance=17     page=0  chnl=0 \nchar id=1072   x=112     y=221     width=15     height=17     xoffset=2     yoffset=17    xadvance=17     page=0  chnl=0 \nchar id=305   x=127     y=221     width=5     height=17     xoffset=3     yoffset=17    xadvance=8     page=0  chnl=0 \nchar id=43   x=132     y=221     width=16     height=17     xoffset=2     yoffset=14    xadvance=17     page=0  chnl=0 \nchar id=58   x=148     y=221     width=5     height=17     xoffset=3     yoffset=17    xadvance=8     page=0  chnl=0 \nchar id=122   x=153     y=221     width=13     height=17     xoffset=2     yoffset=17    xadvance=14     page=0  chnl=0 \nchar id=120   x=166     y=221     width=17     height=17     xoffset=1     yoffset=17    xadvance=16     page=0  chnl=0 \nchar id=119   x=183     y=221     width=24     height=17     xoffset=1     yoffset=17    xadvance=23     page=0  chnl=0 \nchar id=118   x=207     y=221     width=16     height=17     xoffset=1     yoffset=17    xadvance=15     page=0  chnl=0 \nchar id=117   x=223     y=221     width=15     height=17     xoffset=3     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=115   x=238     y=221     width=13     height=17     xoffset=2     yoffset=17    xadvance=14     page=0  chnl=0 \nchar id=114   x=251     y=221     width=11     height=17     xoffset=3     yoffset=17    xadvance=12     page=0  chnl=0 \nchar id=111   x=262     y=221     width=17     height=17     xoffset=2     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=110   x=279     y=221     width=15     height=17     xoffset=3     yoffset=17    xadvance=18     page=0  chnl=0 \nchar id=109   x=294     y=221     width=25     height=17     xoffset=3     yoffset=17    xadvance=28     page=0  chnl=0 \nchar id=101   x=319     y=221     width=16     height=17     xoffset=2     yoffset=17    xadvance=17     page=0  chnl=0 \nchar id=99   x=335     y=221     width=14     height=17     xoffset=2     yoffset=17    xadvance=14     page=0  chnl=0 \nchar id=97   x=349     y=221     width=15     height=17     xoffset=2     yoffset=17    xadvance=17     page=0  chnl=0 \nchar id=94   x=364     y=221     width=17     height=15     xoffset=1     yoffset=11    xadvance=16     page=0  chnl=0 \nchar id=62   x=381     y=221     width=16     height=15     xoffset=2     yoffset=15    xadvance=17     page=0  chnl=0 \nchar id=60   x=397     y=221     width=16     height=15     xoffset=2     yoffset=15    xadvance=17     page=0  chnl=0 \nchar id=42   x=413     y=221     width=16     height=14     xoffset=2     yoffset=10    xadvance=17     page=0  chnl=0 \nchar id=61   x=429     y=221     width=16     height=9     xoffset=2     yoffset=18    xadvance=17     page=0  chnl=0 \nchar id=39   x=445     y=221     width=4     height=9     xoffset=3     yoffset=12    xadvance=7     page=0  chnl=0 \nchar id=34   x=449     y=221     width=11     height=9     xoffset=2     yoffset=12    xadvance=12     page=0  chnl=0 \nchar id=44   x=460     y=221     width=7     height=8     xoffset=1     yoffset=30    xadvance=7     page=0  chnl=0 \nchar id=8226   x=467     y=221     width=8     height=8     xoffset=3     yoffset=18    xadvance=11     page=0  chnl=0 \nchar id=96   x=475     y=221     width=8     height=6     xoffset=6     yoffset=10    xadvance=17     page=0  chnl=0 \nchar id=903   x=483     y=221     width=5     height=5     xoffset=3     yoffset=20    xadvance=8     page=0  chnl=0 \nchar id=46   x=488     y=221     width=5     height=5     xoffset=3     yoffset=29    xadvance=8     page=0  chnl=0 \nchar id=126   x=493     y=221     width=16     height=4     xoffset=2     yoffset=21    xadvance=17     page=0  chnl=0 \nchar id=45   x=0     y=238     width=9     height=4     xoffset=2     yoffset=24    xadvance=10     page=0  chnl=0 \nchar id=95   x=9     y=238     width=16     height=3     xoffset=0     yoffset=36    xadvance=13     page=0  chnl=0 \nkernings count=1604\nkerning first=75  second=67  amount=-1\nkerning first=88  second=71  amount=-1\nkerning first=46  second=85  amount=-1\nkerning first=271  second=93  amount=2\nkerning first=84  second=97  amount=-2\nkerning first=271  second=98  amount=1\nkerning first=89  second=99  amount=-1\nkerning first=356  second=101  amount=-2\nkerning first=271  second=104  amount=1\nkerning first=271  second=108  amount=1\nkerning first=221  second=109  amount=-1\nkerning first=39  second=112  amount=-1\nkerning first=87  second=113  amount=-1\nkerning first=89  second=115  amount=-1\nkerning first=34  second=117  amount=-1\nkerning first=84  second=121  amount=-1\nkerning first=271  second=125  amount=2\nkerning first=66  second=192  amount=-1\nkerning first=80  second=193  amount=-1\nkerning first=199  second=199  amount=-1\nkerning first=1043  second=1088  amount=-1\nkerning first=260  second=210  amount=-1\nkerning first=46  second=217  amount=-1\nkerning first=44  second=218  amount=-1\nkerning first=46  second=220  amount=-1\nkerning first=39  second=225  amount=-1\nkerning first=86  second=231  amount=-1\nkerning first=221  second=232  amount=-1\nkerning first=77  second=236  amount=-2\nkerning first=77  second=237  amount=-2\nkerning first=89  second=249  amount=-1\nkerning first=321  second=262  amount=-1\nkerning first=268  second=286  amount=-1\nkerning first=34  second=287  amount=-1\nkerning first=34  second=103  amount=-1\nkerning first=221  second=351  amount=-1\nkerning first=46  second=366  amount=-1\nkerning first=39  second=367  amount=-1\nkerning first=221  second=378  amount=-1\nkerning first=84  second=382  amount=-1\nkerning first=34  second=99  amount=-2\nkerning first=39  second=902  amount=-2\nkerning first=34  second=913  amount=-2\nkerning first=934  second=918  amount=-1\nkerning first=932  second=920  amount=-1\nkerning first=913  second=927  amount=-1\nkerning first=46  second=1060  amount=-1\nkerning first=913  second=933  amount=-2\nkerning first=935  second=934  amount=-1\nkerning first=908  second=935  amount=-1\nkerning first=916  second=936  amount=-1\nkerning first=932  second=937  amount=-1\nkerning first=932  second=941  amount=-1\nkerning first=932  second=942  amount=-1\nkerning first=910  second=944  amount=-1\nkerning first=39  second=945  amount=-1\nkerning first=915  second=947  amount=-1\nkerning first=39  second=948  amount=-1\nkerning first=910  second=951  amount=-1\nkerning first=44  second=952  amount=-1\nkerning first=933  second=953  amount=-1\nkerning first=933  second=954  amount=-1\nkerning first=929  second=955  amount=-1\nkerning first=915  second=956  amount=-1\nkerning first=915  second=957  amount=-1\nkerning first=932  second=959  amount=-2\nkerning first=955  second=960  amount=-1\nkerning first=915  second=961  amount=-1\nkerning first=39  second=962  amount=-1\nkerning first=955  second=964  amount=-1\nkerning first=915  second=967  amount=-1\nkerning first=932  second=968  amount=-1\nkerning first=915  second=969  amount=-1\nkerning first=915  second=973  amount=-1\nkerning first=910  second=974  amount=-1\nkerning first=972  second=947  amount=-1\nkerning first=1060  second=1047  amount=-1\nkerning first=1066  second=1091  amount=-1\nkerning first=1060  second=1069  amount=-1\nkerning first=39  second=1072  amount=-1\nkerning first=34  second=1076  amount=-2\nkerning first=1092  second=1078  amount=-1\nkerning first=34  second=1089  amount=-2\nkerning first=1043  second=1093  amount=-1\nkerning first=1043  second=1094  amount=-1\nkerning first=1058  second=1096  amount=-1\nkerning first=1043  second=1100  amount=-1\nkerning first=1058  second=1102  amount=-1\nkerning first=933  second=969  amount=-1\nkerning first=39  second=224  amount=-2\nkerning first=39  second=228  amount=-1\nkerning first=84  second=324  amount=-1\nkerning first=262  second=67  amount=-1\nkerning first=89  second=271  amount=-1\nkerning first=1043  second=1075  amount=-1\nkerning first=68  second=46  amount=-1\nkerning first=114  second=99  amount=-1\nkerning first=67  second=262  amount=-1\nkerning first=66  second=196  amount=-1\nkerning first=79  second=84  amount=-1\nkerning first=1082  second=1105  amount=-1\nkerning first=34  second=923  amount=-2\nkerning first=84  second=283  amount=-2\nkerning first=44  second=79  amount=-1\nkerning first=1040  second=1058  amount=-2\nkerning first=120  second=283  amount=-1\nkerning first=283  second=253  amount=-1\nkerning first=221  second=79  amount=-1\nkerning first=933  second=916  amount=-2\nkerning first=87  second=261  amount=-1\nkerning first=84  second=214  amount=-1\nkerning first=961  second=947  amount=-1\nkerning first=39  second=87  amount=1\nkerning first=118  second=63  amount=1\nkerning first=114  second=232  amount=-1\nkerning first=915  second=974  amount=-1\nkerning first=908  second=46  amount=-1\nkerning first=88  second=199  amount=-1\nkerning first=193  second=199  amount=-1\nkerning first=954  second=962  amount=-1\nkerning first=1070  second=1063  amount=-1\nkerning first=356  second=63  amount=1\nkerning first=44  second=1060  amount=-1\nkerning first=65  second=81  amount=-1\nkerning first=1061  second=1060  amount=-1\nkerning first=34  second=950  amount=-1\nkerning first=967  second=972  amount=-1\nkerning first=934  second=933  amount=-1\nkerning first=262  second=286  amount=-1\nkerning first=1060  second=1044  amount=-1\nkerning first=1060  second=1040  amount=-1\nkerning first=89  second=117  amount=-1\nkerning first=39  second=100  amount=-2\nkerning first=221  second=246  amount=-1\nkerning first=910  second=943  amount=-1\nkerning first=1054  second=1058  amount=-1\nkerning first=98  second=120  amount=-1\nkerning first=932  second=949  amount=-1\nkerning first=913  second=934  amount=-1\nkerning first=107  second=269  amount=-1\nkerning first=46  second=89  amount=-2\nkerning first=86  second=228  amount=-1\nkerning first=356  second=269  amount=-2\nkerning first=1056  second=1046  amount=-1\nkerning first=270  second=46  amount=-1\nkerning first=1070  second=1059  amount=-1\nkerning first=84  second=378  amount=-1\nkerning first=950  second=964  amount=-1\nkerning first=39  second=271  amount=-2\nkerning first=1093  second=1092  amount=-1\nkerning first=196  second=268  amount=-1\nkerning first=910  second=973  amount=-1\nkerning first=221  second=242  amount=-1\nkerning first=356  second=67  amount=-1\nkerning first=268  second=268  amount=-1\nkerning first=915  second=948  amount=-1\nkerning first=86  second=224  amount=-1\nkerning first=87  second=231  amount=-1\nkerning first=1058  second=1095  amount=-1\nkerning first=221  second=380  amount=-1\nkerning first=79  second=196  amount=-1\nkerning first=39  second=1105  amount=-2\nkerning first=1058  second=1099  amount=-1\nkerning first=193  second=71  amount=-1\nkerning first=77  second=105  amount=-2\nkerning first=101  second=253  amount=-1\nkerning first=262  second=71  amount=-1\nkerning first=345  second=243  amount=-1\nkerning first=80  second=88  amount=-1\nkerning first=915  second=902  amount=-2\nkerning first=915  second=965  amount=-1\nkerning first=87  second=283  amount=-1\nkerning first=34  second=249  amount=-1\nkerning first=1059  second=44  amount=-2\nkerning first=932  second=940  amount=-2\nkerning first=356  second=115  amount=-2\nkerning first=321  second=87  amount=-1\nkerning first=221  second=101  amount=-1\nkerning first=932  second=947  amount=-1\nkerning first=120  second=99  amount=-1\nkerning first=929  second=935  amount=-1\nkerning first=1058  second=1060  amount=-1\nkerning first=34  second=954  amount=-1\nkerning first=87  second=196  amount=-1\nkerning first=1054  second=44  amount=-1\nkerning first=936  second=44  amount=-2\nkerning first=65  second=89  amount=-2\nkerning first=1088  second=1078  amount=-1\nkerning first=1060  second=1066  amount=-1\nkerning first=345  second=269  amount=-1\nkerning first=936  second=916  amount=-1\nkerning first=46  second=286  amount=-1\nkerning first=86  second=263  amount=-1\nkerning first=39  second=1083  amount=-2\nkerning first=1056  second=1076  amount=-1\nkerning first=67  second=210  amount=-1\nkerning first=46  second=221  amount=-2\nkerning first=101  second=120  amount=-1\nkerning first=242  second=120  amount=-1\nkerning first=243  second=118  amount=-1\nkerning first=923  second=932  amount=-2\nkerning first=1043  second=1097  amount=-1\nkerning first=967  second=948  amount=-1\nkerning first=89  second=262  amount=-1\nkerning first=932  second=46  amount=-2\nkerning first=46  second=67  amount=-1\nkerning first=214  second=192  amount=-1\nkerning first=233  second=253  amount=-1\nkerning first=86  second=271  amount=-1\nkerning first=913  second=920  amount=-1\nkerning first=193  second=268  amount=-1\nkerning first=221  second=281  amount=-1\nkerning first=934  second=923  amount=-1\nkerning first=88  second=268  amount=-1\nkerning first=910  second=916  amount=-2\nkerning first=221  second=367  amount=-1\nkerning first=1102  second=1078  amount=-1\nkerning first=321  second=79  amount=-1\nkerning first=1043  second=44  amount=-2\nkerning first=119  second=44  amount=-1\nkerning first=356  second=243  amount=-2\nkerning first=77  second=225  amount=-3\nkerning first=210  second=88  amount=-1\nkerning first=232  second=118  amount=-1\nkerning first=916  second=920  amount=-1\nkerning first=44  second=1058  amount=-2\nkerning first=121  second=63  amount=1\nkerning first=76  second=356  amount=-1\nkerning first=262  second=199  amount=-1\nkerning first=932  second=962  amount=-2\nkerning first=81  second=65  amount=-1\nkerning first=193  second=84  amount=-2\nkerning first=260  second=87  amount=-1\nkerning first=39  second=972  amount=-1\nkerning first=1058  second=1080  amount=-1\nkerning first=111  second=121  amount=-1\nkerning first=34  second=959  amount=-1\nkerning first=356  second=286  amount=-1\nkerning first=39  second=942  amount=-1\nkerning first=1090  second=44  amount=-1\nkerning first=1093  second=1105  amount=-1\nkerning first=221  second=324  amount=-1\nkerning first=112  second=120  amount=-1\nkerning first=1043  second=1084  amount=-1\nkerning first=75  second=211  amount=-1\nkerning first=114  second=39  amount=1\nkerning first=957  second=46  amount=-1\nkerning first=1075  second=46  amount=-1\nkerning first=1070  second=1046  amount=-1\nkerning first=220  second=46  amount=-1\nkerning first=260  second=79  amount=-1\nkerning first=79  second=46  amount=-1\nkerning first=84  second=192  amount=-2\nkerning first=910  second=927  amount=-1\nkerning first=39  second=113  amount=-2\nkerning first=89  second=287  amount=-1\nkerning first=34  second=261  amount=-1\nkerning first=1058  second=1077  amount=-2\nkerning first=1059  second=1076  amount=-1\nkerning first=262  second=268  amount=-1\nkerning first=84  second=262  amount=-1\nkerning first=1098  second=1093  amount=-1\nkerning first=192  second=86  amount=-1\nkerning first=1043  second=1060  amount=-1\nkerning first=211  second=192  amount=-1\nkerning first=70  second=192  amount=-1\nkerning first=34  second=192  amount=-2\nkerning first=114  second=100  amount=-1\nkerning first=34  second=65  amount=-2\nkerning first=70  second=65  amount=-1\nkerning first=920  second=902  amount=-1\nkerning first=356  second=252  amount=-1\nkerning first=211  second=65  amount=-1\nkerning first=84  second=249  amount=-1\nkerning first=44  second=71  amount=-1\nkerning first=44  second=1063  amount=-2\nkerning first=221  second=71  amount=-1\nkerning first=67  second=214  amount=-1\nkerning first=1058  second=1090  amount=-1\nkerning first=232  second=119  amount=-1\nkerning first=954  second=940  amount=-1\nkerning first=356  second=225  amount=-2\nkerning first=920  second=932  amount=-1\nkerning first=1066  second=39  amount=-1\nkerning first=1056  second=46  amount=-4\nkerning first=356  second=45  amount=-1\nkerning first=89  second=224  amount=-1\nkerning first=345  second=283  amount=-1\nkerning first=1040  second=1063  amount=-1\nkerning first=933  second=44  amount=-2\nkerning first=114  second=243  amount=-1\nkerning first=39  second=232  amount=-2\nkerning first=46  second=84  amount=-2\nkerning first=84  second=81  amount=-1\nkerning first=932  second=944  amount=-1\nkerning first=86  second=283  amount=-1\nkerning first=268  second=211  amount=-1\nkerning first=196  second=211  amount=-1\nkerning first=196  second=71  amount=-1\nkerning first=1069  second=1061  amount=-1\nkerning first=214  second=196  amount=-1\nkerning first=268  second=71  amount=-1\nkerning first=114  second=34  amount=1\nkerning first=270  second=356  amount=-1\nkerning first=283  second=120  amount=-1\nkerning first=89  second=210  amount=-1\nkerning first=967  second=963  amount=-1\nkerning first=356  second=110  amount=-1\nkerning first=933  second=961  amount=-1\nkerning first=39  second=260  amount=-2\nkerning first=932  second=971  amount=-1\nkerning first=84  second=287  amount=-2\nkerning first=1043  second=1083  amount=-2\nkerning first=88  second=67  amount=-1\nkerning first=221  second=250  amount=-1\nkerning first=970  second=34  amount=-1\nkerning first=933  second=934  amount=-1\nkerning first=85  second=46  amount=-1\nkerning first=932  second=945  amount=-2\nkerning first=260  second=74  amount=4\nkerning first=221  second=113  amount=-1\nkerning first=193  second=67  amount=-1\nkerning first=66  second=260  amount=-1\nkerning first=75  second=210  amount=-1\nkerning first=916  second=933  amount=-2\nkerning first=210  second=44  amount=-1\nkerning first=81  second=192  amount=-1\nkerning first=947  second=44  amount=-1\nkerning first=910  second=44  amount=-2\nkerning first=1090  second=1083  amount=-1\nkerning first=954  second=966  amount=-1\nkerning first=908  second=902  amount=-1\nkerning first=966  second=957  amount=-1\nkerning first=915  second=913  amount=-2\nkerning first=1041  second=39  amount=-1\nkerning first=76  second=81  amount=-1\nkerning first=46  second=199  amount=-1\nkerning first=955  second=947  amount=-1\nkerning first=114  second=231  amount=-1\nkerning first=80  second=44  amount=-4\nkerning first=221  second=44  amount=-2\nkerning first=114  second=224  amount=-1\nkerning first=84  second=122  amount=-1\nkerning first=270  second=84  amount=-1\nkerning first=1043  second=1040  amount=-2\nkerning first=221  second=211  amount=-1\nkerning first=934  second=46  amount=-1\nkerning first=950  second=972  amount=-1\nkerning first=77  second=97  amount=-3\nkerning first=283  second=121  amount=-1\nkerning first=86  second=193  amount=-1\nkerning first=39  second=959  amount=-1\nkerning first=1043  second=1044  amount=-1\nkerning first=68  second=356  amount=-1\nkerning first=34  second=942  amount=-1\nkerning first=39  second=263  amount=-2\nkerning first=44  second=934  amount=-1\nkerning first=46  second=356  amount=-2\nkerning first=84  second=103  amount=-2\nkerning first=1070  second=1058  amount=-1\nkerning first=356  second=382  amount=-1\nkerning first=79  second=356  amount=-1\nkerning first=199  second=211  amount=-1\nkerning first=950  second=960  amount=-1\nkerning first=84  second=65  amount=-2\nkerning first=214  second=84  amount=-1\nkerning first=65  second=86  amount=-1\nkerning first=221  second=228  amount=-1\nkerning first=1041  second=34  amount=-1\nkerning first=114  second=263  amount=-1\nkerning first=933  second=973  amount=-1\nkerning first=89  second=122  amount=-1\nkerning first=356  second=268  amount=-1\nkerning first=345  second=39  amount=1\nkerning first=1078  second=1086  amount=-1\nkerning first=44  second=89  amount=-2\nkerning first=34  second=283  amount=-2\nkerning first=39  second=1044  amount=-2\nkerning first=270  second=193  amount=-1\nkerning first=1066  second=1095  amount=-1\nkerning first=75  second=79  amount=-1\nkerning first=65  second=286  amount=-1\nkerning first=1058  second=1079  amount=-1\nkerning first=366  second=46  amount=-1\nkerning first=927  second=916  amount=-1\nkerning first=196  second=74  amount=4\nkerning first=89  second=214  amount=-1\nkerning first=915  second=45  amount=-1\nkerning first=955  second=957  amount=-1\nkerning first=929  second=913  amount=-1\nkerning first=1042  second=46  amount=-1\nkerning first=118  second=46  amount=-1\nkerning first=910  second=961  amount=-1\nkerning first=221  second=114  amount=-1\nkerning first=46  second=932  amount=-2\nkerning first=345  second=111  amount=-1\nkerning first=218  second=44  amount=-1\nkerning first=1058  second=1100  amount=-1\nkerning first=1058  second=1094  amount=-1\nkerning first=34  second=941  amount=-1\nkerning first=46  second=262  amount=-1\nkerning first=44  second=87  amount=-2\nkerning first=910  second=934  amount=-1\nkerning first=915  second=953  amount=-1\nkerning first=1069  second=1051  amount=-1\nkerning first=966  second=947  amount=-1\nkerning first=214  second=65  amount=-1\nkerning first=80  second=260  amount=-1\nkerning first=221  second=260  amount=-2\nkerning first=39  second=193  amount=-2\nkerning first=89  second=193  amount=-2\nkerning first=76  second=86  amount=-1\nkerning first=967  second=959  amount=-1\nkerning first=34  second=963  amount=-1\nkerning first=86  second=242  amount=-1\nkerning first=39  second=117  amount=-1\nkerning first=933  second=951  amount=-1\nkerning first=221  second=233  amount=-1\nkerning first=84  second=120  amount=-1\nkerning first=89  second=100  amount=-1\nkerning first=89  second=263  amount=-1\nkerning first=954  second=945  amount=-1\nkerning first=932  second=927  amount=-1\nkerning first=87  second=63  amount=1\nkerning first=260  second=211  amount=-1\nkerning first=1100  second=1098  amount=-1\nkerning first=356  second=46  amount=-2\nkerning first=1066  second=34  amount=-1\nkerning first=345  second=225  amount=-1\nkerning first=39  second=1092  amount=-2\nkerning first=914  second=923  amount=-1\nkerning first=111  second=253  amount=-1\nkerning first=356  second=84  amount=1\nkerning first=84  second=196  amount=-2\nkerning first=84  second=261  amount=-2\nkerning first=86  second=101  amount=-1\nkerning first=1058  second=1078  amount=-1\nkerning first=932  second=966  amount=-2\nkerning first=1066  second=1090  amount=-1\nkerning first=46  second=1054  amount=-1\nkerning first=39  second=961  amount=-1\nkerning first=356  second=111  amount=-2\nkerning first=933  second=966  amount=-1\nkerning first=210  second=260  amount=-1\nkerning first=1058  second=1051  amount=-1\nkerning first=107  second=111  amount=-1\nkerning first=192  second=81  amount=-1\nkerning first=66  second=44  amount=-1\nkerning first=39  second=242  amount=-2\nkerning first=1068  second=1066  amount=-2\nkerning first=910  second=956  amount=-1\nkerning first=196  second=87  amount=-1\nkerning first=345  second=233  amount=-1\nkerning first=67  second=81  amount=-1\nkerning first=271  second=41  amount=2\nkerning first=44  second=1057  amount=-1\nkerning first=112  second=121  amount=-1\nkerning first=910  second=959  amount=-1\nkerning first=87  second=193  amount=-1\nkerning first=366  second=44  amount=-1\nkerning first=1050  second=1060  amount=-1\nkerning first=34  second=252  amount=-1\nkerning first=81  second=44  amount=-1\nkerning first=89  second=232  amount=-1\nkerning first=916  second=927  amount=-1\nkerning first=86  second=281  amount=-1\nkerning first=114  second=246  amount=-1\nkerning first=1100  second=1093  amount=-1\nkerning first=39  second=954  amount=-1\nkerning first=932  second=963  amount=-2\nkerning first=39  second=1040  amount=-2\nkerning first=199  second=79  amount=-1\nkerning first=65  second=262  amount=-1\nkerning first=44  second=366  amount=-1\nkerning first=902  second=936  amount=-1\nkerning first=76  second=67  amount=-1\nkerning first=39  second=101  amount=-2\nkerning first=1054  second=1059  amount=-1\nkerning first=76  second=262  amount=-1\nkerning first=1043  second=1089  amount=-2\nkerning first=192  second=67  amount=-1\nkerning first=920  second=923  amount=-1\nkerning first=915  second=934  amount=-1\nkerning first=34  second=347  amount=-1\nkerning first=75  second=268  amount=-1\nkerning first=39  second=283  amount=-2\nkerning first=39  second=281  amount=-2\nkerning first=192  second=356  amount=-2\nkerning first=34  second=1077  amount=-2\nkerning first=89  second=79  amount=-1\nkerning first=1078  second=1095  amount=-1\nkerning first=1043  second=1074  amount=-1\nkerning first=87  second=65  amount=-1\nkerning first=933  second=942  amount=-1\nkerning first=356  second=231  amount=-2\nkerning first=192  second=286  amount=-1\nkerning first=46  second=1095  amount=-2\nkerning first=1075  second=45  amount=-1\nkerning first=211  second=84  amount=-1\nkerning first=107  second=231  amount=-1\nkerning first=1100  second=1078  amount=-1\nkerning first=114  second=261  amount=-1\nkerning first=910  second=902  amount=-2\nkerning first=321  second=71  amount=-1\nkerning first=75  second=214  amount=-1\nkerning first=116  second=39  amount=1\nkerning first=44  second=1098  amount=-1\nkerning first=1040  second=39  amount=-2\nkerning first=1050  second=1063  amount=-1\nkerning first=87  second=232  amount=-1\nkerning first=1040  second=1098  amount=-1\nkerning first=1061  second=1063  amount=-1\nkerning first=221  second=63  amount=1\nkerning first=914  second=913  amount=-1\nkerning first=356  second=271  amount=-2\nkerning first=321  second=199  amount=-1\nkerning first=65  second=84  amount=-2\nkerning first=193  second=87  amount=-1\nkerning first=933  second=944  amount=-1\nkerning first=260  second=221  amount=-2\nkerning first=34  second=112  amount=-1\nkerning first=1046  second=1054  amount=-1\nkerning first=932  second=965  amount=-1\nkerning first=112  second=119  amount=-1\nkerning first=39  second=103  amount=-1\nkerning first=1069  second=1040  amount=-1\nkerning first=76  second=286  amount=-1\nkerning first=927  second=923  amount=-1\nkerning first=221  second=117  amount=-1\nkerning first=932  second=961  amount=-1\nkerning first=967  second=945  amount=-1\nkerning first=89  second=246  amount=-1\nkerning first=88  second=211  amount=-1\nkerning first=193  second=211  amount=-1\nkerning first=927  second=935  amount=-1\nkerning first=84  second=347  amount=-2\nkerning first=321  second=86  amount=-1\nkerning first=915  second=951  amount=-1\nkerning first=65  second=210  amount=-1\nkerning first=196  second=39  amount=-2\nkerning first=902  second=934  amount=-1\nkerning first=77  second=228  amount=-3\nkerning first=953  second=34  amount=-1\nkerning first=916  second=34  amount=-2\nkerning first=192  second=262  amount=-1\nkerning first=34  second=1092  amount=-2\nkerning first=89  second=192  amount=-2\nkerning first=66  second=46  amount=-1\nkerning first=34  second=113  amount=-2\nkerning first=89  second=242  amount=-1\nkerning first=84  second=271  amount=-2\nkerning first=908  second=923  amount=-1\nkerning first=76  second=84  amount=-1\nkerning first=77  second=224  amount=-3\nkerning first=70  second=44  amount=-2\nkerning first=345  second=231  amount=-1\nkerning first=356  second=380  amount=-1\nkerning first=46  second=218  amount=-1\nkerning first=211  second=44  amount=-1\nkerning first=34  second=101  amount=-2\nkerning first=1098  second=1090  amount=-1\nkerning first=1068  second=1091  amount=-1\nkerning first=89  second=261  amount=-1\nkerning first=89  second=351  amount=-1\nkerning first=936  second=902  amount=-1\nkerning first=1058  second=1087  amount=-1\nkerning first=199  second=71  amount=-1\nkerning first=119  second=39  amount=1\nkerning first=972  second=957  amount=-1\nkerning first=967  second=940  amount=-1\nkerning first=260  second=39  amount=-2\nkerning first=84  second=232  amount=-2\nkerning first=114  second=283  amount=-1\nkerning first=120  second=232  amount=-1\nkerning first=915  second=46  amount=-2\nkerning first=1082  second=1089  amount=-1\nkerning first=952  second=46  amount=-1\nkerning first=1070  second=46  amount=-1\nkerning first=1057  second=1054  amount=-1\nkerning first=1043  second=1098  amount=-1\nkerning first=1078  second=1077  amount=-1\nkerning first=101  second=119  amount=-1\nkerning first=242  second=119  amount=-1\nkerning first=221  second=115  amount=-1\nkerning first=243  second=119  amount=-1\nkerning first=260  second=199  amount=-1\nkerning first=44  second=221  amount=-2\nkerning first=89  second=101  amount=-1\nkerning first=1070  second=1051  amount=-1\nkerning first=68  second=84  amount=-1\nkerning first=86  second=260  amount=-1\nkerning first=98  second=121  amount=-1\nkerning first=954  second=963  amount=-1\nkerning first=84  second=252  amount=-1\nkerning first=87  second=269  amount=-1\nkerning first=321  second=214  amount=-1\nkerning first=1054  second=1044  amount=-1\nkerning first=356  second=356  amount=1\nkerning first=114  second=242  amount=-1\nkerning first=196  second=221  amount=-2\nkerning first=76  second=210  amount=-1\nkerning first=111  second=118  amount=-1\nkerning first=233  second=120  amount=-1\nkerning first=1068  second=1059  amount=-1\nkerning first=1093  second=1089  amount=-1\nkerning first=1059  second=46  amount=-2\nkerning first=922  second=920  amount=-1\nkerning first=356  second=250  amount=-1\nkerning first=70  second=46  amount=-2\nkerning first=89  second=281  amount=-1\nkerning first=1059  second=1086  amount=-1\nkerning first=89  second=283  amount=-1\nkerning first=67  second=79  amount=-1\nkerning first=86  second=192  amount=-1\nkerning first=1086  second=1078  amount=-1\nkerning first=934  second=44  amount=-1\nkerning first=39  second=110  amount=-1\nkerning first=961  second=957  amount=-1\nkerning first=271  second=39  amount=1\nkerning first=221  second=243  amount=-1\nkerning first=114  second=101  amount=-1\nkerning first=260  second=71  amount=-1\nkerning first=1059  second=1105  amount=-1\nkerning first=271  second=63  amount=2\nkerning first=34  second=111  amount=-2\nkerning first=123  second=74  amount=3\nkerning first=192  second=74  amount=4\nkerning first=918  second=934  amount=-1\nkerning first=902  second=932  amount=-2\nkerning first=1043  second=1076  amount=-2\nkerning first=1047  second=44  amount=-1\nkerning first=79  second=260  amount=-1\nkerning first=1043  second=1057  amount=-1\nkerning first=933  second=974  amount=-1\nkerning first=1059  second=1051  amount=-1\nkerning first=120  second=271  amount=-1\nkerning first=39  second=950  amount=-1\nkerning first=950  second=959  amount=-1\nkerning first=44  second=1066  amount=-2\nkerning first=932  second=923  amount=-2\nkerning first=356  second=99  amount=-2\nkerning first=39  second=86  amount=1\nkerning first=940  second=955  amount=1\nkerning first=107  second=99  amount=-1\nkerning first=34  second=1040  amount=-2\nkerning first=1040  second=1066  amount=-1\nkerning first=932  second=943  amount=-1\nkerning first=46  second=1058  amount=-2\nkerning first=356  second=324  amount=-1\nkerning first=39  second=246  amount=-2\nkerning first=1090  second=1076  amount=-1\nkerning first=192  second=210  amount=-1\nkerning first=34  second=940  amount=-1\nkerning first=246  second=39  amount=-1\nkerning first=34  second=271  amount=-2\nkerning first=929  second=46  amount=-4\nkerning first=84  second=67  amount=-1\nkerning first=356  second=378  amount=-1\nkerning first=120  second=113  amount=-1\nkerning first=114  second=113  amount=-1\nkerning first=199  second=268  amount=-1\nkerning first=1058  second=45  amount=-1\nkerning first=1059  second=1083  amount=-1\nkerning first=1043  second=1102  amount=-1\nkerning first=280  second=74  amount=2\nkerning first=79  second=65  amount=-1\nkerning first=929  second=902  amount=-1\nkerning first=39  second=249  amount=-1\nkerning first=1043  second=1081  amount=-1\nkerning first=68  second=260  amount=-1\nkerning first=89  second=71  amount=-1\nkerning first=34  second=232  amount=-2\nkerning first=1043  second=1054  amount=-1\nkerning first=910  second=46  amount=-2\nkerning first=947  second=46  amount=-1\nkerning first=210  second=46  amount=-1\nkerning first=933  second=949  amount=-1\nkerning first=221  second=224  amount=-1\nkerning first=1056  second=1051  amount=-2\nkerning first=75  second=81  amount=-1\nkerning first=1060  second=44  amount=-1\nkerning first=87  second=99  amount=-1\nkerning first=34  second=972  amount=-1\nkerning first=34  second=193  amount=-2\nkerning first=281  second=121  amount=-1\nkerning first=70  second=193  amount=-1\nkerning first=211  second=193  amount=-1\nkerning first=86  second=261  amount=-1\nkerning first=1059  second=1044  amount=-1\nkerning first=46  second=79  amount=-1\nkerning first=246  second=34  amount=-1\nkerning first=221  second=112  amount=-1\nkerning first=34  second=945  amount=-1\nkerning first=46  second=211  amount=-1\nkerning first=86  second=246  amount=-1\nkerning first=66  second=356  amount=-1\nkerning first=1092  second=1093  amount=-1\nkerning first=923  second=936  amount=-1\nkerning first=281  second=119  amount=-1\nkerning first=44  second=85  amount=-1\nkerning first=221  second=110  amount=-1\nkerning first=283  second=118  amount=-1\nkerning first=46  second=936  amount=-2\nkerning first=1090  second=46  amount=-1\nkerning first=1054  second=46  amount=-1\nkerning first=1058  second=1092  amount=-2\nkerning first=345  second=228  amount=-1\nkerning first=260  second=34  amount=-2\nkerning first=119  second=34  amount=1\nkerning first=936  second=46  amount=-2\nkerning first=923  second=934  amount=-1\nkerning first=1069  second=1063  amount=-1\nkerning first=84  second=112  amount=-1\nkerning first=89  second=113  amount=-1\nkerning first=68  second=65  amount=-1\nkerning first=260  second=268  amount=-1\nkerning first=356  second=351  amount=-2\nkerning first=39  second=351  amount=-1\nkerning first=1050  second=1095  amount=-1\nkerning first=356  second=196  amount=-2\nkerning first=84  second=367  amount=-1\nkerning first=915  second=916  amount=-2\nkerning first=260  second=214  amount=-1\nkerning first=44  second=199  amount=-1\nkerning first=221  second=199  amount=-1\nkerning first=46  second=1063  amount=-2\nkerning first=321  second=39  amount=-2\nkerning first=1043  second=1079  amount=-1\nkerning first=34  second=1072  amount=-1\nkerning first=1068  second=39  amount=-1\nkerning first=356  second=97  amount=-2\nkerning first=913  second=39  amount=-2\nkerning first=357  second=39  amount=1\nkerning first=915  second=971  amount=-1\nkerning first=932  second=913  amount=-2\nkerning first=84  second=111  amount=-2\nkerning first=196  second=199  amount=-1\nkerning first=268  second=199  amount=-1\nkerning first=120  second=111  amount=-1\nkerning first=1057  second=1057  amount=-1\nkerning first=89  second=44  amount=-2\nkerning first=84  second=84  amount=1\nkerning first=967  second=44  amount=-1\nkerning first=915  second=944  amount=-1\nkerning first=114  second=281  amount=-1\nkerning first=356  second=211  amount=-1\nkerning first=945  second=955  amount=1\nkerning first=84  second=286  amount=-1\nkerning first=1070  second=1044  amount=-1\nkerning first=271  second=34  amount=1\nkerning first=196  second=356  amount=-2\nkerning first=356  second=109  amount=-1\nkerning first=34  second=269  amount=-2\nkerning first=193  second=356  amount=-2\nkerning first=262  second=211  amount=-1\nkerning first=270  second=65  amount=-1\nkerning first=910  second=969  amount=-1\nkerning first=34  second=242  amount=-2\nkerning first=356  second=228  amount=-2\nkerning first=913  second=34  amount=-2\nkerning first=357  second=34  amount=1\nkerning first=321  second=34  amount=-2\nkerning first=1068  second=34  amount=-1\nkerning first=932  second=953  amount=-1\nkerning first=232  second=253  amount=-1\nkerning first=221  second=122  amount=-1\nkerning first=44  second=268  amount=-1\nkerning first=84  second=79  amount=-1\nkerning first=932  second=948  amount=-1\nkerning first=910  second=942  amount=-1\nkerning first=1056  second=1061  amount=-1\nkerning first=1100  second=1090  amount=-1\nkerning first=221  second=214  amount=-1\nkerning first=915  second=966  amount=-2\nkerning first=44  second=214  amount=-1\nkerning first=345  second=97  amount=-1\nkerning first=953  second=39  amount=-1\nkerning first=920  second=913  amount=-1\nkerning first=916  second=39  amount=-2\nkerning first=933  second=46  amount=-2\nkerning first=356  second=114  amount=-1\nkerning first=1098  second=1098  amount=-1\nkerning first=1043  second=1091  amount=-1\nkerning first=221  second=268  amount=-1\nkerning first=89  second=81  amount=-1\nkerning first=1046  second=1057  amount=-1\nkerning first=967  second=962  amount=-1\nkerning first=927  second=44  amount=-1\nkerning first=44  second=1054  amount=-1\nkerning first=356  second=287  amount=-2\nkerning first=933  second=959  amount=-1\nkerning first=192  second=84  amount=-2\nkerning first=86  second=44  amount=-1\nkerning first=356  second=260  amount=-2\nkerning first=84  second=193  amount=-2\nkerning first=1058  second=1075  amount=-1\nkerning first=68  second=196  amount=-1\nkerning first=101  second=121  amount=-1\nkerning first=253  second=44  amount=-1\nkerning first=107  second=233  amount=-1\nkerning first=356  second=233  amount=-2\nkerning first=242  second=121  amount=-1\nkerning first=111  second=120  amount=-1\nkerning first=221  second=100  amount=-1\nkerning first=89  second=103  amount=-1\nkerning first=922  second=927  amount=-1\nkerning first=87  second=111  amount=-1\nkerning first=89  second=347  amount=-1\nkerning first=77  second=232  amount=-3\nkerning first=233  second=118  amount=-1\nkerning first=87  second=225  amount=-1\nkerning first=114  second=271  amount=-1\nkerning first=76  second=89  amount=-1\nkerning first=1056  second=1083  amount=-1\nkerning first=221  second=46  amount=-2\nkerning first=65  second=67  amount=-1\nkerning first=80  second=46  amount=-4\nkerning first=1043  second=1051  amount=-1\nkerning first=1100  second=1095  amount=-1\nkerning first=243  second=253  amount=-1\nkerning first=356  second=119  amount=-1\nkerning first=39  second=261  amount=-1\nkerning first=929  second=916  amount=-1\nkerning first=34  second=367  amount=-1\nkerning first=356  second=199  amount=-1\nkerning first=76  second=268  amount=-1\nkerning first=192  second=89  amount=-2\nkerning first=75  second=71  amount=-1\nkerning first=1043  second=1096  amount=-1\nkerning first=932  second=45  amount=-1\nkerning first=908  second=913  amount=-1\nkerning first=200  second=74  amount=2\nkerning first=84  second=269  amount=-2\nkerning first=120  second=269  amount=-1\nkerning first=193  second=221  amount=-2\nkerning first=356  second=65  amount=-2\nkerning first=221  second=263  amount=-1\nkerning first=214  second=193  amount=-1\nkerning first=44  second=932  amount=-2\nkerning first=84  second=242  amount=-2\nkerning first=120  second=242  amount=-1\nkerning first=46  second=87  amount=-2\nkerning first=915  second=949  amount=-1\nkerning first=199  second=81  amount=-1\nkerning first=1058  second=1097  amount=-1\nkerning first=81  second=84  amount=-1\nkerning first=45  second=84  amount=-1\nkerning first=915  second=927  amount=-1\nkerning first=1070  second=1061  amount=-1\nkerning first=260  second=356  amount=-2\nkerning first=910  second=945  amount=-1\nkerning first=87  second=246  amount=-1\nkerning first=1058  second=1084  amount=-1\nkerning first=193  second=86  amount=-1\nkerning first=98  second=118  amount=-1\nkerning first=270  second=196  amount=-1\nkerning first=913  second=936  amount=-1\nkerning first=107  second=243  amount=-1\nkerning first=67  second=67  amount=-1\nkerning first=955  second=34  amount=-2\nkerning first=107  second=271  amount=-1\nkerning first=210  second=192  amount=-1\nkerning first=84  second=101  amount=-2\nkerning first=86  second=46  amount=-1\nkerning first=120  second=101  amount=-1\nkerning first=262  second=262  amount=-1\nkerning first=929  second=923  amount=-1\nkerning first=84  second=268  amount=-1\nkerning first=84  second=281  amount=-2\nkerning first=120  second=281  amount=-1\nkerning first=1058  second=1058  amount=1\nkerning first=1068  second=1090  amount=-1\nkerning first=84  second=114  amount=-1\nkerning first=914  second=916  amount=-1\nkerning first=221  second=231  amount=-1\nkerning first=39  second=243  amount=-2\nkerning first=39  second=913  amount=-2\nkerning first=912  second=39  amount=-1\nkerning first=1041  second=1063  amount=-1\nkerning first=345  second=232  amount=-1\nkerning first=86  second=113  amount=-1\nkerning first=927  second=46  amount=-1\nkerning first=345  second=113  amount=-1\nkerning first=39  second=966  amount=-1\nkerning first=89  second=63  amount=1\nkerning first=221  second=382  amount=-1\nkerning first=34  second=114  amount=-1\nkerning first=933  second=941  amount=-1\nkerning first=260  second=81  amount=-1\nkerning first=1075  second=44  amount=-1\nkerning first=920  second=44  amount=-1\nkerning first=957  second=44  amount=-1\nkerning first=356  second=117  amount=-1\nkerning first=915  second=963  amount=-2\nkerning first=34  second=110  amount=-1\nkerning first=67  second=286  amount=-1\nkerning first=1098  second=34  amount=-2\nkerning first=321  second=356  amount=-1\nkerning first=933  second=971  amount=-1\nkerning first=34  second=281  amount=-2\nkerning first=915  second=937  amount=-1\nkerning first=39  second=347  amount=-1\nkerning first=933  second=945  amount=-1\nkerning first=271  second=107  amount=1\nkerning first=44  second=211  amount=-1\nkerning first=118  second=39  amount=1\nkerning first=932  second=934  amount=-1\nkerning first=39  second=940  amount=-1\nkerning first=89  second=269  amount=-1\nkerning first=102  second=34  amount=2\nkerning first=84  second=113  amount=-2\nkerning first=89  second=67  amount=-1\nkerning first=221  second=192  amount=-2\nkerning first=80  second=192  amount=-1\nkerning first=970  second=39  amount=-1\nkerning first=1082  second=1077  amount=-1\nkerning first=1043  second=1086  amount=-2\nkerning first=39  second=1051  amount=-2\nkerning first=79  second=44  amount=-1\nkerning first=1040  second=1095  amount=-1\nkerning first=220  second=44  amount=-1\nkerning first=44  second=1095  amount=-2\nkerning first=192  second=79  amount=-1\nkerning first=39  second=115  amount=-1\nkerning first=1043  second=1090  amount=-1\nkerning first=1098  second=1078  amount=-1\nkerning first=84  second=99  amount=-2\nkerning first=221  second=261  amount=-1\nkerning first=86  second=243  amount=-1\nkerning first=268  second=214  amount=-1\nkerning first=196  second=214  amount=-1\nkerning first=67  second=71  amount=-1\nkerning first=84  second=45  amount=-1\nkerning first=34  second=948  amount=-1\nkerning first=934  second=902  amount=-1\nkerning first=65  second=79  amount=-1\nkerning first=910  second=949  amount=-1\nkerning first=1043  second=46  amount=-2\nkerning first=84  second=225  amount=-2\nkerning first=950  second=940  amount=-1\nkerning first=233  second=119  amount=-1\nkerning first=321  second=81  amount=-1\nkerning first=915  second=959  amount=-2\nkerning first=1040  second=1060  amount=-1\nkerning first=356  second=121  amount=-1\nkerning first=46  second=1066  amount=-2\nkerning first=39  second=252  amount=-1\nkerning first=1098  second=1091  amount=-1\nkerning first=114  second=269  amount=-1\nkerning first=217  second=44  amount=-1\nkerning first=81  second=260  amount=-1\nkerning first=87  second=242  amount=-1\nkerning first=44  second=356  amount=-2\nkerning first=86  second=111  amount=-1\nkerning first=84  second=118  amount=-1\nkerning first=1093  second=1077  amount=-1\nkerning first=1043  second=1092  amount=-2\nkerning first=932  second=973  amount=-1\nkerning first=262  second=210  amount=-1\nkerning first=196  second=86  amount=-1\nkerning first=39  second=1077  amount=-2\nkerning first=915  second=923  amount=-2\nkerning first=214  second=88  amount=-1\nkerning first=76  second=79  amount=-1\nkerning first=356  second=262  amount=-1\nkerning first=221  second=283  amount=-1\nkerning first=933  second=902  amount=-2\nkerning first=193  second=214  amount=-1\nkerning first=84  second=110  amount=-1\nkerning first=88  second=214  amount=-1\nkerning first=121  second=39  amount=1\nkerning first=89  second=243  amount=-1\nkerning first=87  second=101  amount=-1\nkerning first=76  second=221  amount=-1\nkerning first=910  second=971  amount=-1\nkerning first=67  second=199  amount=-1\nkerning first=201  second=74  amount=2\nkerning first=967  second=966  amount=-1\nkerning first=910  second=941  amount=-1\nkerning first=933  second=927  amount=-1\nkerning first=913  second=932  amount=-2\nkerning first=950  second=962  amount=-1\nkerning first=34  second=260  amount=-2\nkerning first=70  second=260  amount=-1\nkerning first=211  second=260  amount=-1\nkerning first=34  second=84  amount=1\nkerning first=65  second=87  amount=-1\nkerning first=34  second=956  amount=-1\nkerning first=1043  second=1103  amount=-1\nkerning first=1079  second=1103  amount=1\nkerning first=221  second=99  amount=-1\nkerning first=44  second=927  amount=-1\nkerning first=1069  second=1058  amount=-1\nkerning first=89  second=286  amount=-1\nkerning first=1040  second=34  amount=-2\nkerning first=1066  second=1063  amount=-1\nkerning first=932  second=951  amount=-1\nkerning first=1056  second=1044  amount=-2\nkerning first=915  second=954  amount=-1\nkerning first=120  second=246  amount=-1\nkerning first=84  second=246  amount=-2\nkerning first=1058  second=1093  amount=-1\nkerning first=356  second=232  amount=-2\nkerning first=107  second=232  amount=-1\nkerning first=34  second=225  amount=-1\nkerning first=77  second=281  amount=-3\nkerning first=1066  second=1059  amount=-1\nkerning first=116  second=34  amount=1\nkerning first=44  second=936  amount=-2\nkerning first=1058  second=1101  amount=-1\nkerning first=39  second=192  amount=-2\nkerning first=1093  second=1086  amount=-1\nkerning first=283  second=119  amount=-1\nkerning first=321  second=67  amount=-1\nkerning first=46  second=210  amount=-1\nkerning first=67  second=268  amount=-1\nkerning first=1082  second=1086  amount=-1\nkerning first=915  second=942  amount=-1\nkerning first=967  second=45  amount=-1\nkerning first=40  second=74  amount=3\nkerning first=935  second=920  amount=-1\nkerning first=345  second=100  amount=-1\nkerning first=34  second=961  amount=-1\nkerning first=262  second=214  amount=-1\nkerning first=959  second=957  amount=-1\nkerning first=89  second=252  amount=-1\nkerning first=193  second=39  amount=-2\nkerning first=119  second=63  amount=1\nkerning first=1040  second=1090  amount=-1\nkerning first=932  second=956  amount=-1\nkerning first=1043  second=1082  amount=-1\nkerning first=89  second=225  amount=-1\nkerning first=910  second=966  amount=-1\nkerning first=107  second=224  amount=-1\nkerning first=214  second=44  amount=-1\nkerning first=356  second=224  amount=-2\nkerning first=927  second=932  amount=-1\nkerning first=914  second=44  amount=-1\nkerning first=76  second=87  amount=-1\nkerning first=1050  second=1054  amount=-1\nkerning first=1069  second=44  amount=-1\nkerning first=915  second=941  amount=-1\nkerning first=345  second=99  amount=-1\nkerning first=915  second=968  amount=-1\nkerning first=932  second=916  amount=-2\nkerning first=79  second=193  amount=-1\nkerning first=1101  second=1078  amount=-1\nkerning first=77  second=261  amount=-3\nkerning first=39  second=356  amount=1\nkerning first=356  second=112  amount=-1\nkerning first=345  second=34  amount=1\nkerning first=1066  second=1058  amount=-1\nkerning first=1075  second=1083  amount=-1\nkerning first=933  second=963  amount=-1\nkerning first=356  second=210  amount=-1\nkerning first=89  second=110  amount=-1\nkerning first=214  second=260  amount=-1\nkerning first=87  second=228  amount=-1\nkerning first=1068  second=1098  amount=-1\nkerning first=270  second=260  amount=-1\nkerning first=950  second=945  amount=-1\nkerning first=65  second=74  amount=4\nkerning first=356  second=253  amount=-1\nkerning first=923  second=920  amount=-1\nkerning first=910  second=923  amount=-2\nkerning first=84  second=260  amount=-2\nkerning first=39  second=1086  amount=-2\nkerning first=1059  second=1095  amount=-1\nkerning first=87  second=44  amount=-1\nkerning first=221  second=196  amount=-2\nkerning first=80  second=196  amount=-1\nkerning first=120  second=233  amount=-1\nkerning first=84  second=233  amount=-2\nkerning first=46  second=920  amount=-1\nkerning first=192  second=71  amount=-1\nkerning first=345  second=224  amount=-1\nkerning first=89  second=199  amount=-1\nkerning first=1058  second=1088  amount=-1\nkerning first=927  second=902  amount=-1\nkerning first=934  second=913  amount=-1\nkerning first=902  second=39  amount=-2\nkerning first=39  second=111  amount=-2\nkerning first=221  second=249  amount=-1\nkerning first=281  second=118  amount=-1\nkerning first=916  second=932  amount=-2\nkerning first=268  second=81  amount=-1\nkerning first=39  second=84  amount=1\nkerning first=192  second=87  amount=-1\nkerning first=1054  second=1051  amount=-1\nkerning first=196  second=81  amount=-1\nkerning first=1058  second=44  amount=-2\nkerning first=84  second=119  amount=-1\nkerning first=44  second=86  amount=-2\nkerning first=34  second=246  amount=-2\nkerning first=87  second=281  amount=-1\nkerning first=936  second=923  amount=-1\nkerning first=932  second=972  amount=-2\nkerning first=923  second=933  amount=-2\nkerning first=68  second=193  amount=-1\nkerning first=46  second=933  amount=-2\nkerning first=75  second=286  amount=-1\nkerning first=121  second=34  amount=1\nkerning first=1091  second=1083  amount=-1\nkerning first=66  second=65  amount=-1\nkerning first=76  second=211  amount=-1\nkerning first=260  second=86  amount=-1\nkerning first=34  second=109  amount=-1\nkerning first=210  second=196  amount=-1\nkerning first=112  second=118  amount=-1\nkerning first=1078  second=1092  amount=-1\nkerning first=232  second=120  amount=-1\nkerning first=89  second=367  amount=-1\nkerning first=99  second=34  amount=1\nkerning first=910  second=962  amount=-1\nkerning first=321  second=221  amount=-1\nkerning first=902  second=34  amount=-2\nkerning first=1043  second=1105  amount=-2\nkerning first=1086  second=1093  amount=-1\nkerning first=1060  second=1059  amount=-1\nkerning first=345  second=263  amount=-1\nkerning first=356  second=122  amount=-1\nkerning first=210  second=356  amount=-1\nkerning first=88  second=262  amount=-1\nkerning first=46  second=934  amount=-1\nkerning first=193  second=262  amount=-1\nkerning first=89  second=268  amount=-1\nkerning first=81  second=88  amount=-1\nkerning first=260  second=286  amount=-1\nkerning first=1101  second=1093  amount=-1\nkerning first=1058  second=1040  amount=-2\nkerning first=39  second=231  amount=-2\nkerning first=89  second=111  amount=-1\nkerning first=908  second=916  amount=-1\nkerning first=356  second=214  amount=-1\nkerning first=87  second=97  amount=-1\nkerning first=1043  second=1099  amount=-1\nkerning first=102  second=39  amount=2\nkerning first=933  second=940  amount=-1\nkerning first=75  second=199  amount=-1\nkerning first=221  second=97  amount=-1\nkerning first=1098  second=39  amount=-2\nkerning first=1060  second=46  amount=-1\nkerning first=86  second=63  amount=1\nkerning first=1091  second=44  amount=-1\nkerning first=44  second=81  amount=-1\nkerning first=221  second=81  amount=-1\nkerning first=221  second=287  amount=-1\nkerning first=86  second=269  amount=-1\nkerning first=1061  second=1095  amount=-1\nkerning first=1057  second=1060  amount=-1\nkerning first=192  second=211  amount=-1\nkerning first=87  second=192  amount=-1\nkerning first=356  second=193  amount=-2\nkerning first=321  second=286  amount=-1\nkerning first=954  second=972  amount=-1\nkerning first=356  second=100  amount=-2\nkerning first=107  second=100  amount=-1\nkerning first=221  second=103  amount=-1\nkerning first=107  second=263  amount=-1\nkerning first=65  second=211  amount=-1\nkerning first=321  second=268  amount=-1\nkerning first=221  second=347  amount=-1\nkerning first=114  second=111  amount=-1\nkerning first=45  second=1058  amount=-1\nkerning first=243  second=120  amount=-1\nkerning first=1058  second=1105  amount=-2\nkerning first=242  second=118  amount=-1\nkerning first=101  second=118  amount=-1\nkerning first=87  second=271  amount=-1\nkerning first=910  second=940  amount=-1\nkerning first=955  second=39  amount=-2\nkerning first=114  second=225  amount=-1\nkerning first=76  second=214  amount=-1\nkerning first=1054  second=1061  amount=-1\nkerning first=193  second=34  amount=-2\nkerning first=65  second=356  amount=-2\nkerning first=1058  second=1089  amount=-2\nkerning first=967  second=46  amount=-1\nkerning first=84  second=250  amount=-1\nkerning first=89  second=46  amount=-2\nkerning first=1043  second=1077  amount=-2\nkerning first=39  second=949  amount=-1\nkerning first=1058  second=1083  amount=-2\nkerning first=196  second=34  amount=-2\nkerning first=211  second=88  amount=-1\nkerning first=98  second=119  amount=-1\nkerning first=914  second=935  amount=-1\nkerning first=1046  second=1060  amount=-1\nkerning first=77  second=283  amount=-3\nkerning first=920  second=916  amount=-1\nkerning first=281  second=253  amount=-1\nkerning first=84  second=380  amount=-1\nkerning first=1098  second=1095  amount=-1\nkerning first=950  second=966  amount=-1\nkerning first=44  second=217  amount=-1\nkerning first=84  second=71  amount=-1\nkerning first=959  second=947  amount=-1\nkerning first=84  second=109  amount=-1\nkerning first=39  second=269  amount=-2\nkerning first=80  second=65  amount=-1\nkerning first=221  second=65  amount=-2\nkerning first=87  second=260  amount=-1\nkerning first=34  second=115  amount=-1\nkerning first=356  second=263  amount=-2\nkerning first=39  second=1076  amount=-2\nkerning first=84  second=44  amount=-2\nkerning first=933  second=962  amount=-1\nkerning first=66  second=88  amount=-1\nkerning first=87  second=233  amount=-1\nkerning first=321  second=84  amount=-1\nkerning first=321  second=211  amount=-1\nkerning first=262  second=81  amount=-1\nkerning first=34  second=1051  amount=-2\nkerning first=39  second=941  amount=-1\nkerning first=910  second=972  amount=-1\nkerning first=210  second=193  amount=-1\nkerning first=1058  second=1057  amount=-1\nkerning first=345  second=246  amount=-1\nkerning first=1058  second=1044  amount=-1\nkerning first=34  second=951  amount=-1\nkerning first=39  second=916  amount=-2\nkerning first=950  second=963  amount=-1\nkerning first=221  second=271  amount=-1\nkerning first=915  second=962  amount=-2\nkerning first=356  second=118  amount=-1\nkerning first=1058  second=1082  amount=-1\nkerning first=260  second=262  amount=-1\nkerning first=84  second=228  amount=-2\nkerning first=935  second=927  amount=-1\nkerning first=199  second=67  amount=-1\nkerning first=1100  second=34  amount=-2\nkerning first=1043  second=1101  amount=-1\nkerning first=39  second=1089  amount=-2\nkerning first=199  second=262  amount=-1\nkerning first=39  second=109  amount=-1\nkerning first=321  second=210  amount=-1\nkerning first=46  second=927  amount=-1\nkerning first=68  second=88  amount=-1\nkerning first=210  second=65  amount=-1\nkerning first=34  second=962  amount=-1\nkerning first=356  second=79  amount=-1\nkerning first=345  second=261  amount=-1\nkerning first=81  second=196  amount=-1\nkerning first=39  second=114  amount=-1\nkerning first=89  second=231  amount=-1\nkerning first=34  second=966  amount=-1\nkerning first=84  second=243  amount=-2\nkerning first=120  second=243  amount=-1\nkerning first=1082  second=1092  amount=-1\nkerning first=1043  second=1087  amount=-1\nkerning first=45  second=1090  amount=-1\nkerning first=345  second=242  amount=-1\nkerning first=34  second=224  amount=-2\nkerning first=1068  second=1063  amount=-1\nkerning first=1054  second=1046  amount=-1\nkerning first=1058  second=1098  amount=-1\nkerning first=1091  second=46  amount=-1\nkerning first=1075  second=1076  amount=-1\nkerning first=933  second=913  amount=-2\nkerning first=34  second=87  amount=1\nkerning first=260  second=84  amount=-2\nkerning first=929  second=44  amount=-4\nkerning first=86  second=99  amount=-1\nkerning first=954  second=959  amount=-1\nkerning first=65  second=221  amount=-2\nkerning first=39  second=956  amount=-1\nkerning first=84  second=351  amount=-2\nkerning first=933  second=968  amount=-1\nkerning first=46  second=268  amount=-1\nkerning first=1069  second=1044  amount=-1\nkerning first=199  second=286  amount=-1\nkerning first=39  second=324  amount=-1\nkerning first=81  second=356  amount=-1\nkerning first=356  second=246  amount=-2\nkerning first=45  second=356  amount=-1\nkerning first=120  second=100  amount=-1\nkerning first=84  second=100  amount=-2\nkerning first=107  second=246  amount=-1\nkerning first=89  second=382  amount=-1\nkerning first=356  second=120  amount=-1\nkerning first=91  second=74  amount=3\nkerning first=922  second=934  amount=-1\nkerning first=221  second=269  amount=-1\nkerning first=356  second=192  amount=-2\nkerning first=221  second=67  amount=-1\nkerning first=44  second=67  amount=-1\nkerning first=84  second=46  amount=-2\nkerning first=915  second=920  amount=-1\nkerning first=34  second=250  amount=-1\nkerning first=107  second=242  amount=-1\nkerning first=356  second=242  amount=-2\nkerning first=89  second=380  amount=-1\nkerning first=1059  second=1060  amount=-1\nkerning first=270  second=88  amount=-1\nkerning first=70  second=196  amount=-1\nkerning first=34  second=196  amount=-2\nkerning first=211  second=196  amount=-1\nkerning first=356  second=261  amount=-2\nkerning first=1069  second=1059  amount=-1\nkerning first=84  second=115  amount=-2\nkerning first=196  second=89  amount=-2\nkerning first=46  second=214  amount=-1\nkerning first=76  second=71  amount=-1\nkerning first=87  second=243  amount=-1\nkerning first=86  second=97  amount=-1\nkerning first=65  second=39  amount=-2\nkerning first=943  second=39  amount=-1\nkerning first=86  second=232  amount=-1\nkerning first=1054  second=1063  amount=-1\nkerning first=218  second=46  amount=-1\nkerning first=89  second=112  amount=-1\nkerning first=65  second=199  amount=-1\nkerning first=934  second=932  amount=-1\nkerning first=193  second=89  amount=-2\nkerning first=107  second=101  amount=-1\nkerning first=46  second=952  amount=-1\nkerning first=910  second=954  amount=-1\nkerning first=39  second=99  amount=-2\nkerning first=1078  second=1105  amount=-1\nkerning first=1043  second=1078  amount=-1\nkerning first=933  second=972  amount=-1\nkerning first=85  second=44  amount=-1\nkerning first=121  second=44  amount=-1\nkerning first=910  second=963  amount=-1\nkerning first=196  second=286  amount=-1\nkerning first=199  second=214  amount=-1\nkerning first=910  second=968  amount=-1\nkerning first=232  second=121  amount=-1\nkerning first=908  second=932  amount=-1\nkerning first=1059  second=1092  amount=-1\nkerning first=356  second=281  amount=-2\nkerning first=199  second=210  amount=-1\nkerning first=1074  second=1103  amount=1\nkerning first=84  second=224  amount=-2\nkerning first=932  second=954  amount=-1\nkerning first=120  second=224  amount=-1\nkerning first=118  second=34  amount=1\nkerning first=34  second=228  amount=-1\nkerning first=221  second=262  amount=-1\nkerning first=268  second=67  amount=-1\nkerning first=262  second=79  amount=-1\nkerning first=196  second=67  amount=-1\nkerning first=932  second=967  amount=-1\nkerning first=81  second=46  amount=-1\nkerning first=242  second=253  amount=-1\nkerning first=902  second=920  amount=-1\nkerning first=44  second=262  amount=-1\nkerning first=107  second=281  amount=-1\nkerning first=46  second=86  amount=-2\nkerning first=1059  second=1040  amount=-2\nkerning first=950  second=948  amount=-1\nkerning first=107  second=283  amount=-1\nkerning first=84  second=210  amount=-1\nkerning first=44  second=933  amount=-2\nkerning first=356  second=367  amount=-1\nkerning first=34  second=1086  amount=-2\nkerning first=68  second=192  amount=-1\nkerning first=1070  second=44  amount=-1\nkerning first=915  second=44  amount=-2\nkerning first=952  second=44  amount=-1\nkerning first=1100  second=1091  amount=-1\nkerning first=932  second=902  amount=-2\nkerning first=65  second=71  amount=-1\nkerning first=253  second=39  amount=1\nkerning first=86  second=100  amount=-1\nkerning first=39  second=97  amount=-1\nkerning first=76  second=39  amount=-2\nkerning first=910  second=913  amount=-2\nkerning first=86  second=225  amount=-1\nkerning first=345  second=101  amount=-1\nkerning first=915  second=943  amount=-1\nkerning first=253  second=63  amount=1\nkerning first=88  second=81  amount=-1\nkerning first=76  second=199  amount=-1\nkerning first=69  second=74  amount=2\nkerning first=45  second=932  amount=-1\nkerning first=193  second=81  amount=-1\nkerning first=282  second=74  amount=2\nkerning first=923  second=927  amount=-1\nkerning first=1061  second=1057  amount=-1\nkerning first=192  second=221  amount=-2\nkerning first=34  second=233  amount=-2\nkerning first=1060  second=1058  amount=-1\nkerning first=243  second=121  amount=-1\nkerning first=34  second=1105  amount=-2\nkerning first=221  second=286  amount=-1\nkerning first=44  second=286  amount=-1\nkerning first=912  second=34  amount=-1\nkerning first=923  second=39  amount=-2\nkerning first=34  second=100  amount=-2\nkerning first=34  second=263  amount=-2\nkerning first=84  second=211  amount=-1\nkerning first=89  second=324  amount=-1\nkerning first=1058  second=1074  amount=-1\nkerning first=192  second=39  amount=-2\nkerning first=268  second=262  amount=-1\nkerning first=211  second=46  amount=-1\nkerning first=89  second=378  amount=-1\nkerning first=112  second=253  amount=-1\nkerning first=270  second=192  amount=-1\nkerning first=196  second=262  amount=-1\nkerning first=268  second=210  amount=-1\nkerning first=196  second=210  amount=-1\nkerning first=933  second=923  amount=-2\nkerning first=75  second=262  amount=-1\nkerning first=88  second=79  amount=-1\nkerning first=193  second=286  amount=-1\nkerning first=34  second=1044  amount=-2\nkerning first=193  second=79  amount=-1\nkerning first=88  second=286  amount=-1\nkerning first=1043  second=1095  amount=-1\nkerning first=79  second=192  amount=-1\nkerning first=916  second=934  amount=-1\nkerning first=356  second=71  amount=-1\nkerning first=932  second=957  amount=-1\nkerning first=221  second=252  amount=-1\nkerning first=910  second=965  amount=-1\nkerning first=34  second=902  amount=-2\nkerning first=936  second=913  amount=-1\nkerning first=221  second=225  amount=-1\nkerning first=1061  second=1054  amount=-1\nkerning first=1066  second=1098  amount=-1\nkerning first=911  second=932  amount=-1\nkerning first=1047  second=46  amount=-1\nkerning first=86  second=233  amount=-1\nkerning first=87  second=46  amount=-1\nkerning first=192  second=199  amount=-1\nkerning first=1078  second=1089  amount=-1\nkerning first=937  second=932  amount=-1\nkerning first=910  second=953  amount=-1\nkerning first=118  second=44  amount=-1\nkerning first=1050  second=1057  amount=-1\nkerning first=1042  second=44  amount=-1\nkerning first=196  second=84  amount=-2\nkerning first=46  second=71  amount=-1\nkerning first=1060  second=1061  amount=-1\nkerning first=89  second=109  amount=-1\nkerning first=932  second=44  amount=-2\nkerning first=77  second=233  amount=-3\nkerning first=192  second=34  amount=-2\nkerning first=34  second=1083  amount=-2\nkerning first=233  second=121  amount=-1\nkerning first=84  second=356  amount=1\nkerning first=221  second=210  amount=-1\nkerning first=44  second=210  amount=-1\nkerning first=932  second=969  amount=-1\nkerning first=65  second=34  amount=-2\nkerning first=39  second=287  amount=-1\nkerning first=114  second=228  amount=-1\nkerning first=253  second=46  amount=-1\nkerning first=915  second=940  amount=-2\nkerning first=943  second=34  amount=-1\nkerning first=217  second=46  amount=-1\nkerning first=1088  second=1093  amount=-1\nkerning first=89  second=250  amount=-1\nkerning first=321  second=89  amount=-1\nkerning first=98  second=253  amount=-1\nkerning first=1069  second=1046  amount=-1\nkerning first=86  second=65  amount=-1\nkerning first=107  second=113  amount=-1\nkerning first=933  second=920  amount=-1\nkerning first=356  second=113  amount=-2\nkerning first=65  second=268  amount=-1\nkerning first=260  second=89  amount=-2\nkerning first=1068  second=1095  amount=-1\nkerning first=89  second=196  amount=-2\nkerning first=39  second=233  amount=-2\nkerning first=1056  second=44  amount=-4\nkerning first=34  second=231  amount=-2\nkerning first=934  second=916  amount=-1\nkerning first=87  second=224  amount=-1\nkerning first=920  second=935  amount=-1\nkerning first=65  second=214  amount=-1\nkerning first=920  second=46  amount=-1\nkerning first=933  second=948  amount=-1\nkerning first=89  second=97  amount=-1\nkerning first=45  second=1098  amount=-1\nkerning first=119  second=46  amount=-1\nkerning first=356  second=249  amount=-1\nkerning first=70  second=63  amount=1\nkerning first=34  second=97  amount=-1\nkerning first=1058  second=1091  amount=-1\nkerning first=1058  second=1103  amount=-1\nkerning first=66  second=84  amount=-1\nkerning first=356  second=44  amount=-2\nkerning first=46  second=81  amount=-1\nkerning first=111  second=119  amount=-1\nkerning first=1070  second=1040  amount=-1\nkerning first=44  second=1090  amount=-1\nkerning first=89  second=211  amount=-1\nkerning first=76  second=34  amount=-2\nkerning first=253  second=34  amount=1\nkerning first=84  second=263  amount=-2\nkerning first=120  second=263  amount=-1\nkerning first=34  second=86  amount=1\nkerning first=1058  second=1076  amount=-2\nkerning first=39  second=963  amount=-1\nkerning first=214  second=356  amount=-1\nkerning first=345  second=281  amount=-1\nkerning first=211  second=356  amount=-1\nkerning first=39  second=951  amount=-1\nkerning first=34  second=356  amount=1\nkerning first=39  second=65  amount=-2\nkerning first=67  second=211  amount=-1\nkerning first=121  second=46  amount=-1\nkerning first=45  second=1066  amount=-1\nkerning first=1043  second=1058  amount=1\nkerning first=1091  second=1076  amount=-1\nkerning first=89  second=228  amount=-1\nkerning first=356  second=283  amount=-2\nkerning first=915  second=945  amount=-2\nkerning first=87  second=263  amount=-1\nkerning first=1043  second=1085  amount=-1\nkerning first=1054  second=1040  amount=-1\nkerning first=81  second=193  amount=-1\nkerning first=1058  second=1085  amount=-1\nkerning first=39  second=923  amount=-2\nkerning first=902  second=933  amount=-2\nkerning first=1057  second=1095  amount=-1\nkerning first=1093  second=1095  amount=-1\nkerning first=44  second=920  amount=-1\nkerning first=1090  second=45  amount=-1\nkerning first=84  second=231  amount=-2\nkerning first=120  second=231  amount=-1\nkerning first=933  second=965  amount=-1\nkerning first=114  second=97  amount=-1\nkerning first=914  second=902  amount=-1\nkerning first=34  second=243  amount=-2\nkerning first=1043  second=45  amount=-1\nkerning first=84  second=199  amount=-1\nkerning first=34  second=949  amount=-1\nkerning first=99  second=39  amount=1\nkerning first=914  second=46  amount=-1\nkerning first=1069  second=46  amount=-1\nkerning first=1058  second=1081  amount=-1\nkerning first=89  second=114  amount=-1\nkerning first=214  second=46  amount=-1\nkerning first=46  second=1098  amount=-1\nkerning first=356  second=81  amount=-1\nkerning first=908  second=44  amount=-1\nkerning first=1046  second=1063  amount=-1\nkerning first=1058  second=1054  amount=-1\nkerning first=1060  second=1051  amount=-1\nkerning first=193  second=74  amount=4\nkerning first=46  second=1090  amount=-1\nkerning first=210  second=84  amount=-1\nkerning first=915  second=972  amount=-2\nkerning first=89  second=260  amount=-2\nkerning first=68  second=44  amount=-1\nkerning first=66  second=193  amount=-1\nkerning first=86  second=196  amount=-1\nkerning first=34  second=351  amount=-1\nkerning first=221  second=193  amount=-2\nkerning first=46  second=1057  amount=-1\nkerning first=1066  second=1066  amount=-2\nkerning first=356  second=347  amount=-2\nkerning first=84  second=117  amount=-1\nkerning first=89  second=233  amount=-1\nkerning first=1056  second=1040  amount=-1\nkerning first=1068  second=1058  amount=-1\nkerning first=356  second=103  amount=-2\nkerning first=44  second=220  amount=-1\nkerning first=1102  second=1093  amount=-1\nkerning first=34  second=324  amount=-1\nkerning first=902  second=927  amount=-1\nkerning first=1100  second=39  amount=-2\nkerning first=1058  second=46  amount=-2\nkerning first=345  second=271  amount=-1\nkerning first=260  second=67  amount=-1\nkerning first=39  second=250  amount=-1\nkerning first=1043  second=1080  amount=-1\nkerning first=910  second=920  amount=-1\nkerning first=192  second=268  amount=-1\nkerning first=1058  second=1086  amount=-2\nkerning first=193  second=210  amount=-1\nkerning first=1046  second=1095  amount=-1\nkerning first=88  second=210  amount=-1\nkerning first=1082  second=1095  amount=-1\nkerning first=84  second=253  amount=-1\nkerning first=79  second=88  amount=-1\nkerning first=1059  second=1077  amount=-1\nkerning first=910  second=948  amount=-1\nkerning first=1059  second=1089  amount=-1\nkerning first=268  second=79  amount=-1\nkerning first=39  second=196  amount=-2\nkerning first=196  second=79  amount=-1\nkerning first=932  second=974  amount=-1\nkerning first=923  second=34  amount=-2\nkerning first=77  second=101  amount=-3\nkerning first=34  second=916  amount=-2\nkerning first=1060  second=1046  amount=-1\nkerning first=192  second=214  amount=-1\nkerning first=933  second=943  amount=-1\nkerning first=950  second=45  amount=-1\nkerning first=927  second=913  amount=-1\nkerning first=87  second=100  amount=-1\nkerning first=281  second=120  amount=-1\nkerning first=89  second=65  amount=-2\nkerning first=221  second=111  amount=-1\nkerning first=84  second=63  amount=1\nkerning first=270  second=44  amount=-1\nkerning first=933  second=956  amount=-1\nkerning first=44  second=84  amount=-2\nkerning first=114  second=233  amount=-1\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/skin/x2/font-small.fnt",
    "content": "info face=\"Vis Open Sans\" size=24 bold=0 italic=0 charset=\"\" unicode=0 stretchH=100 smooth=1 aa=1 padding=1,0,0,0 spacing=0,0\ncommon lineHeight=34 base=26 scaleW=512 scaleH=256 pages=1 packed=0\npage id=0 file=\"font-small.png\"\nchars count=309\nchar id=32   x=0     y=0     width=0     height=0     xoffset=0     yoffset=26    xadvance=6     page=0  chnl=0 \nchar id=942   x=0     y=0     width=13     height=28     xoffset=3     yoffset=5    xadvance=15     page=0  chnl=0 \nchar id=253   x=13     y=0     width=13     height=27     xoffset=1     yoffset=6    xadvance=12     page=0  chnl=0 \nchar id=366   x=26     y=0     width=14     height=26     xoffset=3     yoffset=1    xadvance=17     page=0  chnl=0 \nchar id=968   x=40     y=0     width=17     height=26     xoffset=2     yoffset=7    xadvance=18     page=0  chnl=0 \nchar id=946   x=57     y=0     width=13     height=26     xoffset=3     yoffset=7    xadvance=15     page=0  chnl=0 \nchar id=1092   x=70     y=0     width=16     height=26     xoffset=2     yoffset=7    xadvance=17     page=0  chnl=0 \nchar id=287   x=86     y=0     width=14     height=26     xoffset=1     yoffset=7    xadvance=13     page=0  chnl=0 \nchar id=124   x=100     y=0     width=4     height=26     xoffset=6     yoffset=7    xadvance=13     page=0  chnl=0 \nchar id=106   x=104     y=0     width=9     height=26     xoffset=-1     yoffset=7    xadvance=6     page=0  chnl=0 \nchar id=381   x=113     y=0     width=15     height=25     xoffset=1     yoffset=2    xadvance=14     page=0  chnl=0 \nchar id=221   x=128     y=0     width=14     height=25     xoffset=1     yoffset=2    xadvance=13     page=0  chnl=0 \nchar id=356   x=142     y=0     width=14     height=25     xoffset=1     yoffset=2    xadvance=13     page=0  chnl=0 \nchar id=352   x=156     y=0     width=12     height=25     xoffset=2     yoffset=2    xadvance=13     page=0  chnl=0 \nchar id=344   x=168     y=0     width=14     height=25     xoffset=3     yoffset=2    xadvance=15     page=0  chnl=0 \nchar id=327   x=182     y=0     width=15     height=25     xoffset=3     yoffset=2    xadvance=18     page=0  chnl=0 \nchar id=282   x=197     y=0     width=11     height=25     xoffset=3     yoffset=2    xadvance=13     page=0  chnl=0 \nchar id=270   x=208     y=0     width=16     height=25     xoffset=3     yoffset=2    xadvance=18     page=0  chnl=0 \nchar id=268   x=224     y=0     width=15     height=25     xoffset=2     yoffset=2    xadvance=15     page=0  chnl=0 \nchar id=1049   x=239     y=0     width=15     height=25     xoffset=3     yoffset=2    xadvance=18     page=0  chnl=0 \nchar id=217   x=254     y=0     width=14     height=25     xoffset=3     yoffset=2    xadvance=17     page=0  chnl=0 \nchar id=210   x=268     y=0     width=18     height=25     xoffset=2     yoffset=2    xadvance=19     page=0  chnl=0 \nchar id=204   x=286     y=0     width=7     height=25     xoffset=0     yoffset=2    xadvance=7     page=0  chnl=0 \nchar id=200   x=293     y=0     width=11     height=25     xoffset=3     yoffset=2    xadvance=13     page=0  chnl=0 \nchar id=192   x=304     y=0     width=16     height=25     xoffset=1     yoffset=2    xadvance=15     page=0  chnl=0 \nchar id=218   x=320     y=0     width=14     height=25     xoffset=3     yoffset=2    xadvance=17     page=0  chnl=0 \nchar id=205   x=334     y=0     width=7     height=25     xoffset=2     yoffset=2    xadvance=7     page=0  chnl=0 \nchar id=201   x=341     y=0     width=11     height=25     xoffset=3     yoffset=2    xadvance=13     page=0  chnl=0 \nchar id=193   x=352     y=0     width=16     height=25     xoffset=1     yoffset=2    xadvance=15     page=0  chnl=0 \nchar id=199   x=368     y=0     width=15     height=25     xoffset=2     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=350   x=383     y=0     width=12     height=25     xoffset=2     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=377   x=395     y=0     width=15     height=25     xoffset=1     yoffset=2    xadvance=14     page=0  chnl=0 \nchar id=346   x=410     y=0     width=12     height=25     xoffset=2     yoffset=2    xadvance=13     page=0  chnl=0 \nchar id=211   x=422     y=0     width=18     height=25     xoffset=2     yoffset=2    xadvance=19     page=0  chnl=0 \nchar id=323   x=440     y=0     width=15     height=25     xoffset=3     yoffset=2    xadvance=18     page=0  chnl=0 \nchar id=262   x=455     y=0     width=15     height=25     xoffset=2     yoffset=2    xadvance=15     page=0  chnl=0 \nchar id=958   x=470     y=0     width=11     height=24     xoffset=2     yoffset=7    xadvance=11     page=0  chnl=0 \nchar id=950   x=481     y=0     width=12     height=24     xoffset=2     yoffset=7    xadvance=12     page=0  chnl=0 \nchar id=304   x=493     y=0     width=5     height=24     xoffset=2     yoffset=3    xadvance=7     page=0  chnl=0 \nchar id=286   x=0     y=28     width=16     height=24     xoffset=2     yoffset=3    xadvance=17     page=0  chnl=0 \nchar id=379   x=16     y=28     width=15     height=24     xoffset=1     yoffset=3    xadvance=14     page=0  chnl=0 \nchar id=280   x=31     y=28     width=11     height=24     xoffset=3     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=260   x=42     y=28     width=17     height=24     xoffset=1     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=209   x=59     y=28     width=15     height=24     xoffset=3     yoffset=3    xadvance=18     page=0  chnl=0 \nchar id=1065   x=74     y=28     width=24     height=23     xoffset=3     yoffset=8    xadvance=25     page=0  chnl=0 \nchar id=1062   x=98     y=28     width=17     height=23     xoffset=3     yoffset=8    xadvance=18     page=0  chnl=0 \nchar id=1025   x=115     y=28     width=11     height=23     xoffset=3     yoffset=4    xadvance=13     page=0  chnl=0 \nchar id=1044   x=126     y=28     width=17     height=23     xoffset=1     yoffset=8    xadvance=16     page=0  chnl=0 \nchar id=220   x=143     y=28     width=14     height=23     xoffset=3     yoffset=4    xadvance=17     page=0  chnl=0 \nchar id=214   x=157     y=28     width=18     height=23     xoffset=2     yoffset=4    xadvance=19     page=0  chnl=0 \nchar id=196   x=175     y=28     width=16     height=23     xoffset=1     yoffset=4    xadvance=15     page=0  chnl=0 \nchar id=125   x=191     y=28     width=10     height=23     xoffset=1     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=123   x=201     y=28     width=10     height=23     xoffset=1     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=93   x=211     y=28     width=8     height=23     xoffset=1     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=91   x=219     y=28     width=8     height=23     xoffset=2     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=41   x=227     y=28     width=8     height=23     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=40   x=235     y=28     width=8     height=23     xoffset=1     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=81   x=243     y=28     width=18     height=23     xoffset=2     yoffset=8    xadvance=19     page=0  chnl=0 \nchar id=74   x=261     y=28     width=10     height=23     xoffset=-2     yoffset=8    xadvance=6     page=0  chnl=0 \nchar id=367   x=271     y=28     width=13     height=22     xoffset=2     yoffset=5    xadvance=15     page=0  chnl=0 \nchar id=944   x=284     y=28     width=14     height=22     xoffset=2     yoffset=5    xadvance=15     page=0  chnl=0 \nchar id=912   x=298     y=28     width=10     height=22     xoffset=0     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=974   x=308     y=28     width=18     height=22     xoffset=2     yoffset=5    xadvance=19     page=0  chnl=0 \nchar id=973   x=326     y=28     width=14     height=22     xoffset=2     yoffset=5    xadvance=15     page=0  chnl=0 \nchar id=972   x=340     y=28     width=14     height=22     xoffset=2     yoffset=5    xadvance=15     page=0  chnl=0 \nchar id=943   x=354     y=28     width=8     height=22     xoffset=2     yoffset=5    xadvance=8     page=0  chnl=0 \nchar id=941   x=362     y=28     width=11     height=22     xoffset=2     yoffset=5    xadvance=11     page=0  chnl=0 \nchar id=940   x=373     y=28     width=15     height=22     xoffset=2     yoffset=5    xadvance=15     page=0  chnl=0 \nchar id=382   x=388     y=28     width=12     height=21     xoffset=1     yoffset=6    xadvance=11     page=0  chnl=0 \nchar id=353   x=400     y=28     width=10     height=21     xoffset=2     yoffset=6    xadvance=11     page=0  chnl=0 \nchar id=345   x=410     y=28     width=10     height=21     xoffset=2     yoffset=6    xadvance=10     page=0  chnl=0 \nchar id=328   x=420     y=28     width=13     height=21     xoffset=3     yoffset=6    xadvance=15     page=0  chnl=0 \nchar id=283   x=433     y=28     width=12     height=21     xoffset=2     yoffset=6    xadvance=13     page=0  chnl=0 \nchar id=269   x=445     y=28     width=11     height=21     xoffset=2     yoffset=6    xadvance=11     page=0  chnl=0 \nchar id=8679   x=456     y=28     width=14     height=21     xoffset=5     yoffset=6    xadvance=20     page=0  chnl=0 \nchar id=8984   x=470     y=28     width=21     height=21     xoffset=3     yoffset=6    xadvance=24     page=0  chnl=0 \nchar id=967   x=491     y=28     width=15     height=21     xoffset=0     yoffset=12    xadvance=13     page=0  chnl=0 \nchar id=966   x=0     y=52     width=16     height=21     xoffset=2     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=961   x=16     y=52     width=13     height=21     xoffset=3     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=956   x=29     y=52     width=12     height=21     xoffset=3     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=951   x=41     y=52     width=13     height=21     xoffset=3     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=947   x=54     y=52     width=13     height=21     xoffset=1     yoffset=12    xadvance=12     page=0  chnl=0 \nchar id=1091   x=67     y=52     width=13     height=21     xoffset=1     yoffset=12    xadvance=12     page=0  chnl=0 \nchar id=1088   x=80     y=52     width=13     height=21     xoffset=3     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=1081   x=93     y=52     width=12     height=21     xoffset=3     yoffset=6    xadvance=15     page=0  chnl=0 \nchar id=249   x=105     y=52     width=13     height=21     xoffset=2     yoffset=6    xadvance=15     page=0  chnl=0 \nchar id=242   x=118     y=52     width=14     height=21     xoffset=2     yoffset=6    xadvance=15     page=0  chnl=0 \nchar id=236   x=132     y=52     width=7     height=21     xoffset=0     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=232   x=139     y=52     width=12     height=21     xoffset=2     yoffset=6    xadvance=13     page=0  chnl=0 \nchar id=224   x=151     y=52     width=12     height=21     xoffset=2     yoffset=6    xadvance=13     page=0  chnl=0 \nchar id=250   x=163     y=52     width=13     height=21     xoffset=2     yoffset=6    xadvance=15     page=0  chnl=0 \nchar id=237   x=176     y=52     width=7     height=21     xoffset=2     yoffset=6    xadvance=6     page=0  chnl=0 \nchar id=233   x=183     y=52     width=12     height=21     xoffset=2     yoffset=6    xadvance=13     page=0  chnl=0 \nchar id=225   x=195     y=52     width=12     height=21     xoffset=2     yoffset=6    xadvance=13     page=0  chnl=0 \nchar id=231   x=207     y=52     width=11     height=21     xoffset=2     yoffset=12    xadvance=11     page=0  chnl=0 \nchar id=351   x=218     y=52     width=10     height=21     xoffset=2     yoffset=12    xadvance=11     page=0  chnl=0 \nchar id=378   x=228     y=52     width=12     height=21     xoffset=1     yoffset=6    xadvance=11     page=0  chnl=0 \nchar id=347   x=240     y=52     width=10     height=21     xoffset=2     yoffset=6    xadvance=11     page=0  chnl=0 \nchar id=243   x=250     y=52     width=14     height=21     xoffset=2     yoffset=6    xadvance=15     page=0  chnl=0 \nchar id=324   x=264     y=52     width=13     height=21     xoffset=3     yoffset=6    xadvance=15     page=0  chnl=0 \nchar id=263   x=277     y=52     width=11     height=21     xoffset=2     yoffset=6    xadvance=11     page=0  chnl=0 \nchar id=36   x=288     y=52     width=13     height=21     xoffset=2     yoffset=7    xadvance=14     page=0  chnl=0 \nchar id=64   x=301     y=52     width=21     height=21     xoffset=2     yoffset=8    xadvance=22     page=0  chnl=0 \nchar id=121   x=322     y=52     width=13     height=21     xoffset=1     yoffset=12    xadvance=12     page=0  chnl=0 \nchar id=113   x=335     y=52     width=13     height=21     xoffset=2     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=112   x=348     y=52     width=13     height=21     xoffset=3     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=103   x=361     y=52     width=14     height=21     xoffset=1     yoffset=12    xadvance=13     page=0  chnl=0 \nchar id=357   x=375     y=52     width=10     height=20     xoffset=1     yoffset=7    xadvance=8     page=0  chnl=0 \nchar id=271   x=385     y=52     width=18     height=20     xoffset=2     yoffset=7    xadvance=15     page=0  chnl=0 \nchar id=955   x=403     y=52     width=15     height=20     xoffset=0     yoffset=7    xadvance=13     page=0  chnl=0 \nchar id=952   x=418     y=52     width=13     height=20     xoffset=2     yoffset=7    xadvance=14     page=0  chnl=0 \nchar id=948   x=431     y=52     width=14     height=20     xoffset=2     yoffset=7    xadvance=14     page=0  chnl=0 \nchar id=911   x=445     y=52     width=21     height=20     xoffset=1     yoffset=7    xadvance=20     page=0  chnl=0 \nchar id=910   x=466     y=52     width=17     height=20     xoffset=1     yoffset=7    xadvance=17     page=0  chnl=0 \nchar id=908   x=483     y=52     width=20     height=20     xoffset=1     yoffset=7    xadvance=20     page=0  chnl=0 \nchar id=906   x=503     y=52     width=8     height=20     xoffset=1     yoffset=7    xadvance=9     page=0  chnl=0 \nchar id=905   x=0     y=73     width=19     height=20     xoffset=1     yoffset=7    xadvance=19     page=0  chnl=0 \nchar id=904   x=19     y=73     width=14     height=20     xoffset=1     yoffset=7    xadvance=15     page=0  chnl=0 \nchar id=902   x=33     y=73     width=16     height=20     xoffset=1     yoffset=7    xadvance=15     page=0  chnl=0 \nchar id=1073   x=49     y=73     width=13     height=20     xoffset=2     yoffset=7    xadvance=14     page=0  chnl=0 \nchar id=1051   x=62     y=73     width=16     height=20     xoffset=1     yoffset=8    xadvance=17     page=0  chnl=0 \nchar id=223   x=78     y=73     width=13     height=20     xoffset=3     yoffset=7    xadvance=15     page=0  chnl=0 \nchar id=380   x=91     y=73     width=12     height=20     xoffset=1     yoffset=7    xadvance=11     page=0  chnl=0 \nchar id=322   x=103     y=73     width=9     height=20     xoffset=0     yoffset=7    xadvance=6     page=0  chnl=0 \nchar id=281   x=112     y=73     width=13     height=20     xoffset=2     yoffset=12    xadvance=13     page=0  chnl=0 \nchar id=261   x=125     y=73     width=13     height=20     xoffset=2     yoffset=12    xadvance=13     page=0  chnl=0 \nchar id=241   x=138     y=73     width=13     height=20     xoffset=3     yoffset=7    xadvance=15     page=0  chnl=0 \nchar id=108   x=151     y=73     width=3     height=20     xoffset=3     yoffset=7    xadvance=6     page=0  chnl=0 \nchar id=107   x=154     y=73     width=12     height=20     xoffset=3     yoffset=7    xadvance=13     page=0  chnl=0 \nchar id=105   x=166     y=73     width=5     height=20     xoffset=2     yoffset=7    xadvance=6     page=0  chnl=0 \nchar id=104   x=171     y=73     width=13     height=20     xoffset=3     yoffset=7    xadvance=15     page=0  chnl=0 \nchar id=102   x=184     y=73     width=12     height=20     xoffset=1     yoffset=7    xadvance=8     page=0  chnl=0 \nchar id=100   x=196     y=73     width=13     height=20     xoffset=2     yoffset=7    xadvance=15     page=0  chnl=0 \nchar id=98   x=209     y=73     width=13     height=20     xoffset=3     yoffset=7    xadvance=15     page=0  chnl=0 \nchar id=971   x=222     y=73     width=14     height=19     xoffset=2     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=962   x=236     y=73     width=12     height=19     xoffset=2     yoffset=12    xadvance=12     page=0  chnl=0 \nchar id=970   x=248     y=73     width=10     height=19     xoffset=0     yoffset=8    xadvance=8     page=0  chnl=0 \nchar id=937   x=258     y=73     width=20     height=19     xoffset=1     yoffset=8    xadvance=19     page=0  chnl=0 \nchar id=936   x=278     y=73     width=18     height=19     xoffset=2     yoffset=8    xadvance=19     page=0  chnl=0 \nchar id=935   x=296     y=73     width=15     height=19     xoffset=1     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=934   x=311     y=73     width=18     height=19     xoffset=2     yoffset=8    xadvance=19     page=0  chnl=0 \nchar id=933   x=329     y=73     width=14     height=19     xoffset=1     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=932   x=343     y=73     width=14     height=19     xoffset=1     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=931   x=357     y=73     width=15     height=19     xoffset=1     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=929   x=372     y=73     width=12     height=19     xoffset=3     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=928   x=384     y=73     width=15     height=19     xoffset=3     yoffset=8    xadvance=18     page=0  chnl=0 \nchar id=927   x=399     y=73     width=18     height=19     xoffset=2     yoffset=8    xadvance=19     page=0  chnl=0 \nchar id=926   x=417     y=73     width=14     height=19     xoffset=1     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=925   x=431     y=73     width=15     height=19     xoffset=3     yoffset=8    xadvance=18     page=0  chnl=0 \nchar id=924   x=446     y=73     width=19     height=19     xoffset=3     yoffset=8    xadvance=22     page=0  chnl=0 \nchar id=923   x=465     y=73     width=15     height=19     xoffset=1     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=922   x=480     y=73     width=14     height=19     xoffset=3     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=921   x=494     y=73     width=4     height=19     xoffset=3     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=920   x=0     y=93     width=18     height=19     xoffset=2     yoffset=8    xadvance=19     page=0  chnl=0 \nchar id=919   x=18     y=93     width=15     height=19     xoffset=3     yoffset=8    xadvance=18     page=0  chnl=0 \nchar id=918   x=33     y=93     width=15     height=19     xoffset=1     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=917   x=48     y=93     width=11     height=19     xoffset=3     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=916   x=59     y=93     width=15     height=19     xoffset=1     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=915   x=74     y=93     width=11     height=19     xoffset=3     yoffset=8    xadvance=12     page=0  chnl=0 \nchar id=914   x=85     y=93     width=14     height=19     xoffset=3     yoffset=8    xadvance=16     page=0  chnl=0 \nchar id=913   x=99     y=93     width=16     height=19     xoffset=1     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=1097   x=115     y=93     width=21     height=19     xoffset=3     yoffset=12    xadvance=22     page=0  chnl=0 \nchar id=1094   x=136     y=93     width=14     height=19     xoffset=3     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=1105   x=150     y=93     width=12     height=19     xoffset=2     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=1076   x=162     y=93     width=15     height=19     xoffset=1     yoffset=12    xadvance=14     page=0  chnl=0 \nchar id=1071   x=177     y=93     width=14     height=19     xoffset=1     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=1070   x=191     y=93     width=23     height=19     xoffset=3     yoffset=8    xadvance=25     page=0  chnl=0 \nchar id=1069   x=214     y=93     width=15     height=19     xoffset=1     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=1068   x=229     y=93     width=13     height=19     xoffset=3     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=1067   x=242     y=93     width=17     height=19     xoffset=3     yoffset=8    xadvance=20     page=0  chnl=0 \nchar id=1066   x=259     y=93     width=17     height=19     xoffset=1     yoffset=8    xadvance=17     page=0  chnl=0 \nchar id=1064   x=276     y=93     width=22     height=19     xoffset=3     yoffset=8    xadvance=25     page=0  chnl=0 \nchar id=1063   x=298     y=93     width=14     height=19     xoffset=3     yoffset=8    xadvance=17     page=0  chnl=0 \nchar id=1061   x=312     y=93     width=15     height=19     xoffset=1     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=1060   x=327     y=93     width=18     height=19     xoffset=2     yoffset=8    xadvance=19     page=0  chnl=0 \nchar id=1059   x=345     y=93     width=16     height=19     xoffset=1     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=1058   x=361     y=93     width=14     height=19     xoffset=1     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=1057   x=375     y=93     width=15     height=19     xoffset=2     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=1056   x=390     y=93     width=12     height=19     xoffset=3     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=1055   x=402     y=93     width=15     height=19     xoffset=3     yoffset=8    xadvance=18     page=0  chnl=0 \nchar id=1054   x=417     y=93     width=18     height=19     xoffset=2     yoffset=8    xadvance=19     page=0  chnl=0 \nchar id=1053   x=435     y=93     width=15     height=19     xoffset=3     yoffset=8    xadvance=18     page=0  chnl=0 \nchar id=1052   x=450     y=93     width=19     height=19     xoffset=3     yoffset=8    xadvance=22     page=0  chnl=0 \nchar id=1050   x=469     y=93     width=14     height=19     xoffset=3     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=1048   x=483     y=93     width=15     height=19     xoffset=3     yoffset=8    xadvance=18     page=0  chnl=0 \nchar id=1047   x=0     y=112     width=14     height=19     xoffset=1     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=1046   x=14     y=112     width=21     height=19     xoffset=1     yoffset=8    xadvance=20     page=0  chnl=0 \nchar id=1045   x=35     y=112     width=11     height=19     xoffset=3     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=1043   x=46     y=112     width=11     height=19     xoffset=3     yoffset=8    xadvance=12     page=0  chnl=0 \nchar id=1042   x=57     y=112     width=14     height=19     xoffset=3     yoffset=8    xadvance=16     page=0  chnl=0 \nchar id=1041   x=71     y=112     width=13     height=19     xoffset=3     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=1040   x=84     y=112     width=16     height=19     xoffset=1     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=252   x=100     y=112     width=13     height=19     xoffset=2     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=246   x=113     y=112     width=14     height=19     xoffset=2     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=228   x=127     y=112     width=12     height=19     xoffset=2     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=321   x=139     y=112     width=14     height=19     xoffset=1     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=127   x=153     y=112     width=11     height=19     xoffset=3     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=38   x=164     y=112     width=18     height=19     xoffset=2     yoffset=8    xadvance=18     page=0  chnl=0 \nchar id=35   x=182     y=112     width=17     height=19     xoffset=1     yoffset=8    xadvance=16     page=0  chnl=0 \nchar id=37   x=199     y=112     width=19     height=19     xoffset=2     yoffset=8    xadvance=20     page=0  chnl=0 \nchar id=165   x=218     y=112     width=15     height=19     xoffset=1     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=8364   x=233     y=112     width=15     height=19     xoffset=1     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=92   x=248     y=112     width=10     height=19     xoffset=1     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=47   x=258     y=112     width=10     height=19     xoffset=1     yoffset=8    xadvance=9     page=0  chnl=0 \nchar id=191   x=268     y=112     width=11     height=19     xoffset=1     yoffset=12    xadvance=10     page=0  chnl=0 \nchar id=63   x=279     y=112     width=11     height=19     xoffset=1     yoffset=8    xadvance=10     page=0  chnl=0 \nchar id=33   x=290     y=112     width=5     height=19     xoffset=2     yoffset=8    xadvance=6     page=0  chnl=0 \nchar id=48   x=295     y=112     width=13     height=19     xoffset=2     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=57   x=308     y=112     width=13     height=19     xoffset=2     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=56   x=321     y=112     width=13     height=19     xoffset=2     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=55   x=334     y=112     width=13     height=19     xoffset=2     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=54   x=347     y=112     width=13     height=19     xoffset=2     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=53   x=360     y=112     width=13     height=19     xoffset=2     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=52   x=373     y=112     width=15     height=19     xoffset=1     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=51   x=388     y=112     width=13     height=19     xoffset=2     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=50   x=401     y=112     width=13     height=19     xoffset=2     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=49   x=414     y=112     width=8     height=19     xoffset=3     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=90   x=422     y=112     width=15     height=19     xoffset=1     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=89   x=437     y=112     width=14     height=19     xoffset=1     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=88   x=451     y=112     width=15     height=19     xoffset=1     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=87   x=466     y=112     width=23     height=19     xoffset=1     yoffset=8    xadvance=22     page=0  chnl=0 \nchar id=86   x=489     y=112     width=15     height=19     xoffset=1     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=85   x=0     y=131     width=14     height=19     xoffset=3     yoffset=8    xadvance=17     page=0  chnl=0 \nchar id=84   x=14     y=131     width=14     height=19     xoffset=1     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=83   x=28     y=131     width=12     height=19     xoffset=2     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=82   x=40     y=131     width=14     height=19     xoffset=3     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=80   x=54     y=131     width=12     height=19     xoffset=3     yoffset=8    xadvance=14     page=0  chnl=0 \nchar id=79   x=66     y=131     width=18     height=19     xoffset=2     yoffset=8    xadvance=19     page=0  chnl=0 \nchar id=78   x=84     y=131     width=15     height=19     xoffset=3     yoffset=8    xadvance=18     page=0  chnl=0 \nchar id=77   x=99     y=131     width=19     height=19     xoffset=3     yoffset=8    xadvance=22     page=0  chnl=0 \nchar id=76   x=118     y=131     width=11     height=19     xoffset=3     yoffset=8    xadvance=12     page=0  chnl=0 \nchar id=75   x=129     y=131     width=14     height=19     xoffset=3     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=73   x=143     y=131     width=4     height=19     xoffset=3     yoffset=8    xadvance=7     page=0  chnl=0 \nchar id=72   x=147     y=131     width=15     height=19     xoffset=3     yoffset=8    xadvance=18     page=0  chnl=0 \nchar id=71   x=162     y=131     width=16     height=19     xoffset=2     yoffset=8    xadvance=17     page=0  chnl=0 \nchar id=70   x=178     y=131     width=11     height=19     xoffset=3     yoffset=8    xadvance=12     page=0  chnl=0 \nchar id=69   x=189     y=131     width=11     height=19     xoffset=3     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=68   x=200     y=131     width=16     height=19     xoffset=3     yoffset=8    xadvance=18     page=0  chnl=0 \nchar id=67   x=216     y=131     width=15     height=19     xoffset=2     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=66   x=231     y=131     width=14     height=19     xoffset=3     yoffset=8    xadvance=16     page=0  chnl=0 \nchar id=65   x=245     y=131     width=16     height=19     xoffset=1     yoffset=8    xadvance=15     page=0  chnl=0 \nchar id=59   x=261     y=131     width=6     height=18     xoffset=1     yoffset=12    xadvance=6     page=0  chnl=0 \nchar id=116   x=267     y=131     width=9     height=18     xoffset=1     yoffset=9    xadvance=8     page=0  chnl=0 \nchar id=8997   x=276     y=131     width=26     height=16     xoffset=2     yoffset=11    xadvance=28     page=0  chnl=0 \nchar id=969   x=302     y=131     width=18     height=15     xoffset=2     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=965   x=320     y=131     width=14     height=15     xoffset=2     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=964   x=334     y=131     width=12     height=15     xoffset=1     yoffset=12    xadvance=11     page=0  chnl=0 \nchar id=963   x=346     y=131     width=15     height=15     xoffset=2     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=960   x=361     y=131     width=17     height=15     xoffset=1     yoffset=12    xadvance=16     page=0  chnl=0 \nchar id=959   x=378     y=131     width=14     height=15     xoffset=2     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=957   x=392     y=131     width=14     height=15     xoffset=1     yoffset=12    xadvance=13     page=0  chnl=0 \nchar id=954   x=406     y=131     width=12     height=15     xoffset=2     yoffset=12    xadvance=12     page=0  chnl=0 \nchar id=953   x=418     y=131     width=8     height=15     xoffset=2     yoffset=12    xadvance=8     page=0  chnl=0 \nchar id=949   x=426     y=131     width=11     height=15     xoffset=2     yoffset=12    xadvance=11     page=0  chnl=0 \nchar id=945   x=437     y=131     width=15     height=15     xoffset=2     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=1103   x=452     y=131     width=12     height=15     xoffset=1     yoffset=12    xadvance=13     page=0  chnl=0 \nchar id=1102   x=464     y=131     width=18     height=15     xoffset=3     yoffset=12    xadvance=20     page=0  chnl=0 \nchar id=1101   x=482     y=131     width=12     height=15     xoffset=1     yoffset=12    xadvance=12     page=0  chnl=0 \nchar id=1100   x=494     y=131     width=12     height=15     xoffset=3     yoffset=12    xadvance=14     page=0  chnl=0 \nchar id=1099   x=0     y=150     width=15     height=15     xoffset=3     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=1098   x=15     y=150     width=17     height=15     xoffset=1     yoffset=12    xadvance=17     page=0  chnl=0 \nchar id=1096   x=32     y=150     width=18     height=15     xoffset=3     yoffset=12    xadvance=21     page=0  chnl=0 \nchar id=1095   x=50     y=150     width=13     height=15     xoffset=2     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=1093   x=63     y=150     width=14     height=15     xoffset=1     yoffset=12    xadvance=13     page=0  chnl=0 \nchar id=1090   x=77     y=150     width=12     height=15     xoffset=1     yoffset=12    xadvance=11     page=0  chnl=0 \nchar id=1089   x=89     y=150     width=11     height=15     xoffset=2     yoffset=12    xadvance=11     page=0  chnl=0 \nchar id=1087   x=100     y=150     width=12     height=15     xoffset=3     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=1086   x=112     y=150     width=14     height=15     xoffset=2     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=1085   x=126     y=150     width=12     height=15     xoffset=3     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=1084   x=138     y=150     width=15     height=15     xoffset=3     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=1083   x=153     y=150     width=13     height=15     xoffset=1     yoffset=12    xadvance=14     page=0  chnl=0 \nchar id=1082   x=166     y=150     width=12     height=15     xoffset=2     yoffset=12    xadvance=12     page=0  chnl=0 \nchar id=1080   x=178     y=150     width=12     height=15     xoffset=3     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=1079   x=190     y=150     width=12     height=15     xoffset=1     yoffset=12    xadvance=12     page=0  chnl=0 \nchar id=1078   x=202     y=150     width=19     height=15     xoffset=1     yoffset=12    xadvance=18     page=0  chnl=0 \nchar id=1077   x=221     y=150     width=12     height=15     xoffset=2     yoffset=12    xadvance=13     page=0  chnl=0 \nchar id=1075   x=233     y=150     width=9     height=15     xoffset=3     yoffset=12    xadvance=10     page=0  chnl=0 \nchar id=1074   x=242     y=150     width=13     height=15     xoffset=3     yoffset=12    xadvance=14     page=0  chnl=0 \nchar id=1072   x=255     y=150     width=12     height=15     xoffset=2     yoffset=12    xadvance=13     page=0  chnl=0 \nchar id=305   x=267     y=150     width=3     height=15     xoffset=3     yoffset=12    xadvance=6     page=0  chnl=0 \nchar id=43   x=270     y=150     width=13     height=15     xoffset=2     yoffset=10    xadvance=14     page=0  chnl=0 \nchar id=58   x=283     y=150     width=5     height=15     xoffset=2     yoffset=12    xadvance=6     page=0  chnl=0 \nchar id=122   x=288     y=150     width=12     height=15     xoffset=1     yoffset=12    xadvance=11     page=0  chnl=0 \nchar id=120   x=300     y=150     width=14     height=15     xoffset=1     yoffset=12    xadvance=13     page=0  chnl=0 \nchar id=119   x=314     y=150     width=20     height=15     xoffset=1     yoffset=12    xadvance=19     page=0  chnl=0 \nchar id=118   x=334     y=150     width=13     height=15     xoffset=1     yoffset=12    xadvance=12     page=0  chnl=0 \nchar id=117   x=347     y=150     width=13     height=15     xoffset=2     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=115   x=360     y=150     width=10     height=15     xoffset=2     yoffset=12    xadvance=11     page=0  chnl=0 \nchar id=114   x=370     y=150     width=9     height=15     xoffset=3     yoffset=12    xadvance=10     page=0  chnl=0 \nchar id=111   x=379     y=150     width=14     height=15     xoffset=2     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=110   x=393     y=150     width=13     height=15     xoffset=3     yoffset=12    xadvance=15     page=0  chnl=0 \nchar id=109   x=406     y=150     width=20     height=15     xoffset=3     yoffset=12    xadvance=22     page=0  chnl=0 \nchar id=101   x=426     y=150     width=12     height=15     xoffset=2     yoffset=12    xadvance=13     page=0  chnl=0 \nchar id=99   x=438     y=150     width=11     height=15     xoffset=2     yoffset=12    xadvance=11     page=0  chnl=0 \nchar id=97   x=449     y=150     width=12     height=15     xoffset=2     yoffset=12    xadvance=13     page=0  chnl=0 \nchar id=62   x=461     y=150     width=13     height=14     xoffset=2     yoffset=10    xadvance=14     page=0  chnl=0 \nchar id=60   x=474     y=150     width=13     height=14     xoffset=2     yoffset=10    xadvance=14     page=0  chnl=0 \nchar id=42   x=487     y=150     width=13     height=13     xoffset=1     yoffset=7    xadvance=13     page=0  chnl=0 \nchar id=94   x=0     y=165     width=14     height=13     xoffset=1     yoffset=8    xadvance=13     page=0  chnl=0 \nchar id=61   x=14     y=165     width=13     height=9     xoffset=2     yoffset=13    xadvance=14     page=0  chnl=0 \nchar id=44   x=27     y=165     width=6     height=8     xoffset=1     yoffset=22    xadvance=6     page=0  chnl=0 \nchar id=39   x=33     y=165     width=4     height=8     xoffset=2     yoffset=8    xadvance=5     page=0  chnl=0 \nchar id=34   x=37     y=165     width=9     height=8     xoffset=2     yoffset=8    xadvance=10     page=0  chnl=0 \nchar id=8226   x=46     y=165     width=8     height=8     xoffset=2     yoffset=13    xadvance=9     page=0  chnl=0 \nchar id=903   x=54     y=165     width=5     height=6     xoffset=2     yoffset=15    xadvance=6     page=0  chnl=0 \nchar id=46   x=59     y=165     width=5     height=6     xoffset=2     yoffset=21    xadvance=6     page=0  chnl=0 \nchar id=96   x=64     y=165     width=7     height=6     xoffset=5     yoffset=6    xadvance=14     page=0  chnl=0 \nchar id=126   x=71     y=165     width=13     height=5     xoffset=2     yoffset=15    xadvance=14     page=0  chnl=0 \nchar id=95   x=84     y=165     width=14     height=4     xoffset=0     yoffset=27    xadvance=11     page=0  chnl=0 \nchar id=45   x=98     y=165     width=7     height=4     xoffset=2     yoffset=18    xadvance=8     page=0  chnl=0 \nkernings count=869\nkerning first=1040  second=34  amount=-2\nkerning first=271  second=41  amount=2\nkerning first=44  second=67  amount=-1\nkerning first=46  second=71  amount=-1\nkerning first=46  second=81  amount=-1\nkerning first=65  second=87  amount=-1\nkerning first=46  second=89  amount=-1\nkerning first=271  second=93  amount=2\nkerning first=271  second=98  amount=1\nkerning first=77  second=105  amount=-2\nkerning first=271  second=107  amount=1\nkerning first=356  second=109  amount=-1\nkerning first=39  second=110  amount=-1\nkerning first=221  second=112  amount=-1\nkerning first=84  second=122  amount=-1\nkerning first=271  second=125  amount=2\nkerning first=40  second=74  amount=2\nkerning first=356  second=192  amount=-2\nkerning first=87  second=196  amount=-1\nkerning first=46  second=199  amount=-1\nkerning first=44  second=214  amount=-1\nkerning first=1066  second=1066  amount=-1\nkerning first=44  second=221  amount=-1\nkerning first=89  second=225  amount=-1\nkerning first=356  second=228  amount=-2\nkerning first=77  second=236  amount=-2\nkerning first=77  second=237  amount=-2\nkerning first=34  second=962  amount=-1\nkerning first=39  second=243  amount=-1\nkerning first=89  second=250  amount=-1\nkerning first=86  second=260  amount=-1\nkerning first=44  second=262  amount=-1\nkerning first=44  second=268  amount=-1\nkerning first=46  second=286  amount=-1\nkerning first=84  second=287  amount=-2\nkerning first=1058  second=1105  amount=-2\nkerning first=89  second=115  amount=-1\nkerning first=68  second=84  amount=-1\nkerning first=932  second=953  amount=-1\nkerning first=39  second=916  amount=-2\nkerning first=1058  second=1060  amount=-1\nkerning first=915  second=902  amount=-2\nkerning first=915  second=913  amount=-2\nkerning first=44  second=920  amount=-1\nkerning first=915  second=923  amount=-2\nkerning first=44  second=927  amount=-1\nkerning first=46  second=936  amount=-1\nkerning first=932  second=937  amount=-1\nkerning first=933  second=940  amount=-1\nkerning first=910  second=941  amount=-1\nkerning first=910  second=942  amount=-1\nkerning first=932  second=945  amount=-2\nkerning first=910  second=948  amount=-1\nkerning first=932  second=949  amount=-1\nkerning first=915  second=953  amount=-1\nkerning first=915  second=954  amount=-1\nkerning first=910  second=956  amount=-1\nkerning first=34  second=959  amount=-1\nkerning first=915  second=969  amount=-1\nkerning first=34  second=961  amount=-1\nkerning first=39  second=962  amount=-1\nkerning first=915  second=968  amount=-1\nkerning first=910  second=971  amount=-1\nkerning first=34  second=972  amount=-1\nkerning first=910  second=973  amount=-1\nkerning first=932  second=974  amount=-1\nkerning first=46  second=1054  amount=-1\nkerning first=44  second=1057  amount=-1\nkerning first=44  second=1063  amount=-2\nkerning first=356  second=110  amount=-1\nkerning first=932  second=966  amount=-2\nkerning first=34  second=1086  amount=-1\nkerning first=1070  second=46  amount=-1\nkerning first=39  second=225  amount=-1\nkerning first=1043  second=1095  amount=-1\nkerning first=1043  second=1099  amount=-1\nkerning first=1043  second=1103  amount=-1\nkerning first=929  second=46  amount=-3\nkerning first=118  second=34  amount=1\nkerning first=84  second=109  amount=-1\nkerning first=65  second=74  amount=3\nkerning first=34  second=109  amount=-1\nkerning first=221  second=111  amount=-1\nkerning first=39  second=196  amount=-2\nkerning first=932  second=923  amount=-2\nkerning first=34  second=916  amount=-2\nkerning first=34  second=112  amount=-1\nkerning first=932  second=972  amount=-2\nkerning first=271  second=39  amount=1\nkerning first=1100  second=39  amount=-1\nkerning first=46  second=1098  amount=-1\nkerning first=1058  second=1089  amount=-2\nkerning first=89  second=44  amount=-1\nkerning first=79  second=84  amount=-1\nkerning first=967  second=44  amount=-1\nkerning first=89  second=367  amount=-1\nkerning first=356  second=243  amount=-2\nkerning first=321  second=34  amount=-2\nkerning first=221  second=114  amount=-1\nkerning first=933  second=951  amount=-1\nkerning first=39  second=351  amount=-1\nkerning first=1043  second=1094  amount=-1\nkerning first=1043  second=1060  amount=-1\nkerning first=356  second=246  amount=-2\nkerning first=1066  second=1063  amount=-1\nkerning first=910  second=951  amount=-1\nkerning first=34  second=271  amount=-1\nkerning first=1058  second=1074  amount=-1\nkerning first=932  second=969  amount=-1\nkerning first=193  second=74  amount=3\nkerning first=923  second=39  amount=-2\nkerning first=211  second=84  amount=-1\nkerning first=1058  second=1102  amount=-1\nkerning first=221  second=101  amount=-1\nkerning first=39  second=1051  amount=-1\nkerning first=1056  second=1051  amount=-1\nkerning first=260  second=34  amount=-2\nkerning first=119  second=34  amount=1\nkerning first=65  second=221  amount=-1\nkerning first=271  second=34  amount=1\nkerning first=953  second=39  amount=-1\nkerning first=39  second=115  amount=-1\nkerning first=1043  second=1097  amount=-1\nkerning first=1058  second=1044  amount=-1\nkerning first=34  second=232  amount=-1\nkerning first=80  second=192  amount=-1\nkerning first=221  second=192  amount=-1\nkerning first=927  second=44  amount=-1\nkerning first=913  second=932  amount=-2\nkerning first=86  second=44  amount=-1\nkerning first=89  second=261  amount=-1\nkerning first=84  second=242  amount=-2\nkerning first=39  second=228  amount=-1\nkerning first=356  second=233  amount=-2\nkerning first=1043  second=1075  amount=-1\nkerning first=1058  second=1076  amount=-1\nkerning first=221  second=347  amount=-1\nkerning first=86  second=192  amount=-1\nkerning first=1058  second=45  amount=-1\nkerning first=271  second=108  amount=1\nkerning first=947  second=46  amount=-1\nkerning first=66  second=46  amount=-1\nkerning first=89  second=196  amount=-1\nkerning first=46  second=211  amount=-1\nkerning first=915  second=973  amount=-1\nkerning first=193  second=221  amount=-1\nkerning first=221  second=263  amount=-1\nkerning first=65  second=84  amount=-2\nkerning first=916  second=932  amount=-2\nkerning first=39  second=961  amount=-1\nkerning first=77  second=233  amount=-2\nkerning first=932  second=913  amount=-2\nkerning first=356  second=249  amount=-1\nkerning first=1090  second=46  amount=-1\nkerning first=1058  second=1099  amount=-1\nkerning first=932  second=902  amount=-2\nkerning first=81  second=44  amount=-1\nkerning first=46  second=1057  amount=-1\nkerning first=1058  second=1095  amount=-1\nkerning first=933  second=945  amount=-1\nkerning first=45  second=1066  amount=-1\nkerning first=1042  second=44  amount=-1\nkerning first=89  second=193  amount=-1\nkerning first=933  second=941  amount=-1\nkerning first=84  second=281  amount=-2\nkerning first=46  second=927  amount=-1\nkerning first=84  second=252  amount=-1\nkerning first=34  second=115  amount=-1\nkerning first=356  second=103  amount=-2\nkerning first=44  second=199  amount=-1\nkerning first=1040  second=1058  amount=-2\nkerning first=943  second=39  amount=-1\nkerning first=66  second=356  amount=-1\nkerning first=84  second=232  amount=-2\nkerning first=910  second=953  amount=-1\nkerning first=65  second=39  amount=-2\nkerning first=44  second=1060  amount=-1\nkerning first=916  second=936  amount=-1\nkerning first=221  second=117  amount=-1\nkerning first=913  second=34  amount=-2\nkerning first=1043  second=1084  amount=-1\nkerning first=1054  second=1058  amount=-1\nkerning first=192  second=39  amount=-2\nkerning first=927  second=932  amount=-1\nkerning first=260  second=221  amount=-1\nkerning first=89  second=351  amount=-1\nkerning first=34  second=281  amount=-1\nkerning first=221  second=228  amount=-1\nkerning first=356  second=324  amount=-1\nkerning first=34  second=367  amount=-1\nkerning first=39  second=347  amount=-1\nkerning first=1075  second=1076  amount=-1\nkerning first=89  second=112  amount=-1\nkerning first=39  second=261  amount=-1\nkerning first=89  second=283  amount=-1\nkerning first=932  second=963  amount=-2\nkerning first=34  second=99  amount=-1\nkerning first=910  second=945  amount=-1\nkerning first=221  second=269  amount=-1\nkerning first=77  second=224  amount=-2\nkerning first=1059  second=1051  amount=-1\nkerning first=34  second=1089  amount=-1\nkerning first=70  second=44  amount=-1\nkerning first=211  second=44  amount=-1\nkerning first=1098  second=1095  amount=-1\nkerning first=271  second=63  amount=2\nkerning first=196  second=356  amount=-2\nkerning first=253  second=39  amount=1\nkerning first=76  second=39  amount=-2\nkerning first=34  second=1092  amount=-1\nkerning first=46  second=920  amount=-1\nkerning first=193  second=356  amount=-2\nkerning first=39  second=99  amount=-1\nkerning first=214  second=84  amount=-1\nkerning first=932  second=940  amount=-2\nkerning first=932  second=944  amount=-1\nkerning first=221  second=225  amount=-1\nkerning first=910  second=974  amount=-1\nkerning first=1059  second=46  amount=-1\nkerning first=89  second=110  amount=-1\nkerning first=210  second=46  amount=-1\nkerning first=196  second=221  amount=-1\nkerning first=34  second=1044  amount=-1\nkerning first=34  second=252  amount=-1\nkerning first=932  second=959  amount=-2\nkerning first=192  second=87  amount=-1\nkerning first=1043  second=1091  amount=-1\nkerning first=916  second=34  amount=-2\nkerning first=953  second=34  amount=-1\nkerning first=89  second=260  amount=-1\nkerning first=34  second=196  amount=-2\nkerning first=934  second=44  amount=-1\nkerning first=34  second=103  amount=-1\nkerning first=44  second=1058  amount=-2\nkerning first=39  second=112  amount=-1\nkerning first=84  second=378  amount=-1\nkerning first=1100  second=1090  amount=-1\nkerning first=201  second=74  amount=1\nkerning first=1043  second=1105  amount=-2\nkerning first=1075  second=1083  amount=-1\nkerning first=933  second=971  amount=-1\nkerning first=46  second=1060  amount=-1\nkerning first=46  second=268  amount=-1\nkerning first=84  second=367  amount=-1\nkerning first=221  second=65  amount=-1\nkerning first=80  second=65  amount=-1\nkerning first=936  second=46  amount=-1\nkerning first=39  second=283  amount=-1\nkerning first=1054  second=46  amount=-1\nkerning first=356  second=99  amount=-2\nkerning first=84  second=99  amount=-2\nkerning first=34  second=1040  amount=-2\nkerning first=910  second=902  amount=-1\nkerning first=932  second=46  amount=-1\nkerning first=192  second=86  amount=-1\nkerning first=1066  second=34  amount=-1\nkerning first=102  second=39  amount=1\nkerning first=65  second=356  amount=-2\nkerning first=193  second=84  amount=-2\nkerning first=1043  second=1081  amount=-1\nkerning first=84  second=196  amount=-2\nkerning first=1098  second=39  amount=-1\nkerning first=933  second=44  amount=-1\nkerning first=39  second=117  amount=-1\nkerning first=39  second=101  amount=-1\nkerning first=967  second=46  amount=-1\nkerning first=80  second=46  amount=-3\nkerning first=913  second=933  amount=-1\nkerning first=76  second=34  amount=-2\nkerning first=46  second=84  amount=-2\nkerning first=39  second=1092  amount=-1\nkerning first=84  second=283  amount=-2\nkerning first=84  second=246  amount=-2\nkerning first=932  second=956  amount=-1\nkerning first=221  second=110  amount=-1\nkerning first=34  second=269  amount=-1\nkerning first=933  second=934  amount=-1\nkerning first=920  second=46  amount=-1\nkerning first=957  second=46  amount=-1\nkerning first=1075  second=46  amount=-1\nkerning first=39  second=109  amount=-1\nkerning first=34  second=283  amount=-1\nkerning first=89  second=111  amount=-1\nkerning first=915  second=45  amount=-1\nkerning first=34  second=225  amount=-1\nkerning first=1058  second=1051  amount=-1\nkerning first=210  second=44  amount=-1\nkerning first=915  second=937  amount=-1\nkerning first=1056  second=1044  amount=-1\nkerning first=39  second=193  amount=-2\nkerning first=947  second=44  amount=-1\nkerning first=910  second=44  amount=-1\nkerning first=89  second=231  amount=-1\nkerning first=1058  second=1088  amount=-1\nkerning first=923  second=933  amount=-1\nkerning first=910  second=944  amount=-1\nkerning first=902  second=34  amount=-2\nkerning first=955  second=39  amount=-1\nkerning first=932  second=962  amount=-2\nkerning first=80  second=44  amount=-3\nkerning first=221  second=44  amount=-1\nkerning first=89  second=271  amount=-1\nkerning first=913  second=936  amount=-1\nkerning first=1043  second=1040  amount=-2\nkerning first=356  second=242  amount=-2\nkerning first=221  second=243  amount=-1\nkerning first=915  second=966  amount=-2\nkerning first=1058  second=1103  amount=-1\nkerning first=356  second=114  amount=-1\nkerning first=39  second=263  amount=-1\nkerning first=44  second=934  amount=-1\nkerning first=44  second=79  amount=-1\nkerning first=196  second=89  amount=-1\nkerning first=929  second=902  amount=-1\nkerning first=44  second=936  amount=-1\nkerning first=1058  second=1098  amount=-1\nkerning first=65  second=86  amount=-1\nkerning first=1058  second=1096  amount=-1\nkerning first=908  second=46  amount=-1\nkerning first=193  second=89  amount=-1\nkerning first=932  second=916  amount=-2\nkerning first=356  second=122  amount=-1\nkerning first=910  second=949  amount=-1\nkerning first=910  second=954  amount=-1\nkerning first=39  second=242  amount=-1\nkerning first=68  second=46  amount=-1\nkerning first=933  second=963  amount=-1\nkerning first=34  second=923  amount=-2\nkerning first=933  second=942  amount=-1\nkerning first=84  second=115  amount=-1\nkerning first=356  second=252  amount=-1\nkerning first=39  second=972  amount=-1\nkerning first=44  second=211  amount=-1\nkerning first=39  second=224  amount=-1\nkerning first=34  second=963  amount=-1\nkerning first=910  second=934  amount=-1\nkerning first=356  second=287  amount=-2\nkerning first=1100  second=1095  amount=-1\nkerning first=915  second=920  amount=-1\nkerning first=936  second=902  amount=-1\nkerning first=1043  second=1077  amount=-2\nkerning first=46  second=1090  amount=-1\nkerning first=45  second=932  amount=-1\nkerning first=1058  second=1083  amount=-1\nkerning first=39  second=948  amount=-1\nkerning first=91  second=74  amount=2\nkerning first=356  second=347  amount=-1\nkerning first=89  second=263  amount=-1\nkerning first=933  second=902  amount=-1\nkerning first=270  second=46  amount=-1\nkerning first=1056  second=1040  amount=-1\nkerning first=1043  second=1076  amount=-1\nkerning first=915  second=943  amount=-1\nkerning first=76  second=89  amount=-1\nkerning first=932  second=954  amount=-1\nkerning first=39  second=111  amount=-1\nkerning first=44  second=81  amount=-1\nkerning first=1070  second=1058  amount=-1\nkerning first=934  second=932  amount=-1\nkerning first=221  second=196  amount=-1\nkerning first=934  second=918  amount=-1\nkerning first=80  second=196  amount=-1\nkerning first=902  second=39  amount=-2\nkerning first=84  second=351  amount=-1\nkerning first=192  second=356  amount=-2\nkerning first=39  second=1076  amount=-2\nkerning first=114  second=34  amount=1\nkerning first=84  second=100  amount=-2\nkerning first=221  second=46  amount=-1\nkerning first=356  second=250  amount=-1\nkerning first=221  second=109  amount=-1\nkerning first=933  second=944  amount=-1\nkerning first=915  second=945  amount=-2\nkerning first=916  second=933  amount=-1\nkerning first=77  second=261  amount=-2\nkerning first=321  second=221  amount=-1\nkerning first=221  second=249  amount=-1\nkerning first=86  second=46  amount=-1\nkerning first=39  second=1040  amount=-2\nkerning first=1043  second=1092  amount=-2\nkerning first=915  second=951  amount=-1\nkerning first=118  second=46  amount=-1\nkerning first=1042  second=46  amount=-1\nkerning first=89  second=224  amount=-1\nkerning first=118  second=39  amount=1\nkerning first=932  second=968  amount=-1\nkerning first=260  second=89  amount=-1\nkerning first=34  second=101  amount=-1\nkerning first=356  second=100  amount=-2\nkerning first=39  second=232  amount=-1\nkerning first=34  second=1105  amount=-1\nkerning first=39  second=103  amount=-1\nkerning first=1058  second=1092  amount=-2\nkerning first=89  second=117  amount=-1\nkerning first=34  second=231  amount=-1\nkerning first=89  second=232  amount=-1\nkerning first=321  second=89  amount=-1\nkerning first=356  second=378  amount=-1\nkerning first=356  second=113  amount=-2\nkerning first=86  second=65  amount=-1\nkerning first=39  second=97  amount=-1\nkerning first=356  second=97  amount=-2\nkerning first=192  second=74  amount=3\nkerning first=84  second=225  amount=-2\nkerning first=221  second=324  amount=-1\nkerning first=46  second=1095  amount=-1\nkerning first=34  second=1076  amount=-2\nkerning first=44  second=286  amount=-1\nkerning first=1058  second=44  amount=-1\nkerning first=933  second=966  amount=-1\nkerning first=84  second=261  amount=-2\nkerning first=914  second=46  amount=-1\nkerning first=356  second=46  amount=-1\nkerning first=196  second=74  amount=3\nkerning first=1058  second=1090  amount=-1\nkerning first=89  second=269  amount=-1\nkerning first=1058  second=1075  amount=-1\nkerning first=955  second=34  amount=-1\nkerning first=46  second=356  amount=-2\nkerning first=34  second=351  amount=-1\nkerning first=121  second=39  amount=1\nkerning first=221  second=97  amount=-1\nkerning first=39  second=65  amount=-2\nkerning first=1060  second=44  amount=-1\nkerning first=1054  second=44  amount=-1\nkerning first=936  second=44  amount=-1\nkerning first=933  second=973  amount=-1\nkerning first=1090  second=44  amount=-1\nkerning first=44  second=89  amount=-1\nkerning first=196  second=86  amount=-1\nkerning first=356  second=281  amount=-2\nkerning first=34  second=246  amount=-1\nkerning first=910  second=968  amount=-1\nkerning first=221  second=242  amount=-1\nkerning first=1056  second=46  amount=-3\nkerning first=46  second=221  amount=-1\nkerning first=84  second=271  amount=-2\nkerning first=933  second=972  amount=-1\nkerning first=929  second=913  amount=-1\nkerning first=119  second=44  amount=-1\nkerning first=46  second=214  amount=-1\nkerning first=84  second=231  amount=-2\nkerning first=1058  second=1082  amount=-1\nkerning first=915  second=961  amount=-1\nkerning first=68  second=356  amount=-1\nkerning first=910  second=46  amount=-1\nkerning first=915  second=944  amount=-1\nkerning first=918  second=934  amount=-1\nkerning first=34  second=260  amount=-2\nkerning first=1043  second=1100  amount=-1\nkerning first=69  second=74  amount=1\nkerning first=282  second=74  amount=1\nkerning first=915  second=974  amount=-1\nkerning first=87  second=193  amount=-1\nkerning first=34  second=1083  amount=-2\nkerning first=270  second=84  amount=-1\nkerning first=1043  second=1087  amount=-1\nkerning first=39  second=1077  amount=-1\nkerning first=934  second=933  amount=-1\nkerning first=39  second=233  amount=-1\nkerning first=39  second=367  amount=-1\nkerning first=933  second=943  amount=-1\nkerning first=915  second=941  amount=-1\nkerning first=84  second=380  amount=-1\nkerning first=34  second=261  amount=-1\nkerning first=34  second=940  amount=-1\nkerning first=121  second=46  amount=-1\nkerning first=46  second=1058  amount=-2\nkerning first=89  second=65  amount=-1\nkerning first=87  second=260  amount=-1\nkerning first=910  second=965  amount=-1\nkerning first=915  second=959  amount=-2\nkerning first=260  second=87  amount=-1\nkerning first=1058  second=1097  amount=-1\nkerning first=81  second=46  amount=-1\nkerning first=89  second=109  amount=-1\nkerning first=39  second=902  amount=-2\nkerning first=39  second=963  amount=-1\nkerning first=935  second=934  amount=-1\nkerning first=34  second=117  amount=-1\nkerning first=1043  second=1086  amount=-2\nkerning first=356  second=193  amount=-2\nkerning first=916  second=39  amount=-2\nkerning first=39  second=271  amount=-1\nkerning first=1058  second=1087  amount=-1\nkerning first=84  second=101  amount=-2\nkerning first=84  second=192  amount=-2\nkerning first=34  second=65  amount=-2\nkerning first=902  second=933  amount=-1\nkerning first=933  second=913  amount=-1\nkerning first=1098  second=1091  amount=-1\nkerning first=1066  second=1058  amount=-1\nkerning first=39  second=246  amount=-1\nkerning first=34  second=224  amount=-1\nkerning first=934  second=46  amount=-1\nkerning first=46  second=87  amount=-1\nkerning first=933  second=965  amount=-1\nkerning first=70  second=46  amount=-1\nkerning first=211  second=46  amount=-1\nkerning first=356  second=115  amount=-1\nkerning first=1056  second=44  amount=-3\nkerning first=77  second=225  amount=-2\nkerning first=929  second=916  amount=-1\nkerning first=932  second=961  amount=-1\nkerning first=356  second=351  amount=-1\nkerning first=81  second=356  amount=-1\nkerning first=45  second=356  amount=-1\nkerning first=84  second=250  amount=-1\nkerning first=902  second=936  amount=-1\nkerning first=915  second=965  amount=-1\nkerning first=80  second=193  amount=-1\nkerning first=221  second=271  amount=-1\nkerning first=1040  second=1063  amount=-1\nkerning first=356  second=44  amount=-1\nkerning first=89  second=243  amount=-1\nkerning first=221  second=250  amount=-1\nkerning first=356  second=367  amount=-1\nkerning first=84  second=263  amount=-2\nkerning first=910  second=972  amount=-1\nkerning first=356  second=380  amount=-1\nkerning first=193  second=87  amount=-1\nkerning first=932  second=971  amount=-1\nkerning first=950  second=45  amount=-1\nkerning first=89  second=246  amount=-1\nkerning first=1091  second=46  amount=-1\nkerning first=84  second=103  amount=-2\nkerning first=65  second=34  amount=-2\nkerning first=943  second=34  amount=-1\nkerning first=253  second=34  amount=1\nkerning first=915  second=962  amount=-2\nkerning first=910  second=913  amount=-1\nkerning first=84  second=117  amount=-1\nkerning first=1058  second=1094  amount=-1\nkerning first=84  second=224  amount=-2\nkerning first=908  second=44  amount=-1\nkerning first=1058  second=1100  amount=-1\nkerning first=68  second=44  amount=-1\nkerning first=356  second=45  amount=-1\nkerning first=356  second=261  amount=-2\nkerning first=89  second=233  amount=-1\nkerning first=910  second=969  amount=-1\nkerning first=1043  second=45  amount=-1\nkerning first=910  second=940  amount=-1\nkerning first=910  second=966  amount=-1\nkerning first=933  second=959  amount=-1\nkerning first=79  second=44  amount=-1\nkerning first=84  second=111  amount=-2\nkerning first=84  second=46  amount=-1\nkerning first=1058  second=1081  amount=-1\nkerning first=1100  second=1091  amount=-1\nkerning first=39  second=1086  amount=-1\nkerning first=356  second=196  amount=-2\nkerning first=34  second=948  amount=-1\nkerning first=1068  second=39  amount=-1\nkerning first=913  second=39  amount=-2\nkerning first=915  second=916  amount=-2\nkerning first=321  second=39  amount=-2\nkerning first=221  second=233  amount=-1\nkerning first=192  second=34  amount=-2\nkerning first=84  second=260  amount=-2\nkerning first=39  second=100  amount=-1\nkerning first=84  second=269  amount=-2\nkerning first=77  second=232  amount=-2\nkerning first=44  second=1054  amount=-1\nkerning first=87  second=192  amount=-1\nkerning first=270  second=44  amount=-1\nkerning first=39  second=113  amount=-1\nkerning first=260  second=84  amount=-2\nkerning first=121  second=34  amount=1\nkerning first=933  second=949  amount=-1\nkerning first=89  second=249  amount=-1\nkerning first=221  second=367  amount=-1\nkerning first=44  second=933  amount=-1\nkerning first=210  second=84  amount=-1\nkerning first=44  second=1095  amount=-1\nkerning first=915  second=949  amount=-1\nkerning first=345  second=34  amount=1\nkerning first=214  second=46  amount=-1\nkerning first=1069  second=46  amount=-1\nkerning first=77  second=281  amount=-2\nkerning first=196  second=87  amount=-1\nkerning first=76  second=221  amount=-1\nkerning first=39  second=923  amount=-2\nkerning first=933  second=953  amount=-1\nkerning first=933  second=948  amount=-1\nkerning first=260  second=39  amount=-2\nkerning first=119  second=39  amount=1\nkerning first=1040  second=1066  amount=-1\nkerning first=46  second=79  amount=-1\nkerning first=46  second=1066  amount=-2\nkerning first=260  second=74  amount=3\nkerning first=221  second=232  amount=-1\nkerning first=1060  second=46  amount=-1\nkerning first=44  second=84  amount=-2\nkerning first=908  second=932  amount=-1\nkerning first=1090  second=1076  amount=-1\nkerning first=221  second=113  amount=-1\nkerning first=39  second=1083  amount=-2\nkerning first=34  second=1077  amount=-1\nkerning first=923  second=936  amount=-1\nkerning first=34  second=110  amount=-1\nkerning first=89  second=324  amount=-1\nkerning first=932  second=951  amount=-1\nkerning first=80  second=260  amount=-1\nkerning first=356  second=112  amount=-1\nkerning first=192  second=221  amount=-1\nkerning first=910  second=959  amount=-1\nkerning first=356  second=283  amount=-2\nkerning first=1043  second=1080  amount=-1\nkerning first=1058  second=46  amount=-1\nkerning first=1100  second=34  amount=-1\nkerning first=193  second=39  amount=-2\nkerning first=922  second=934  amount=-1\nkerning first=34  second=111  amount=-1\nkerning first=932  second=948  amount=-1\nkerning first=44  second=87  amount=-1\nkerning first=1100  second=1098  amount=-1\nkerning first=1090  second=1083  amount=-1\nkerning first=221  second=231  amount=-1\nkerning first=1043  second=44  amount=-1\nkerning first=920  second=932  amount=-1\nkerning first=44  second=1066  amount=-2\nkerning first=39  second=249  amount=-1\nkerning first=214  second=356  amount=-1\nkerning first=923  second=34  amount=-2\nkerning first=936  second=913  amount=-1\nkerning first=89  second=100  amount=-1\nkerning first=39  second=940  amount=-1\nkerning first=89  second=97  amount=-1\nkerning first=84  second=65  amount=-2\nkerning first=211  second=356  amount=-1\nkerning first=1043  second=1085  amount=-1\nkerning first=1040  second=39  amount=-2\nkerning first=79  second=356  amount=-1\nkerning first=1059  second=1044  amount=-1\nkerning first=221  second=99  amount=-1\nkerning first=932  second=45  amount=-1\nkerning first=196  second=84  amount=-2\nkerning first=933  second=974  amount=-1\nkerning first=39  second=966  amount=-1\nkerning first=1058  second=1077  amount=-2\nkerning first=34  second=114  amount=-1\nkerning first=121  second=44  amount=-1\nkerning first=910  second=943  amount=-1\nkerning first=1059  second=1040  amount=-2\nkerning first=1043  second=1083  amount=-1\nkerning first=39  second=1105  amount=-1\nkerning first=87  second=46  amount=-1\nkerning first=1047  second=46  amount=-1\nkerning first=84  second=382  amount=-1\nkerning first=86  second=193  amount=-1\nkerning first=221  second=281  amount=-1\nkerning first=46  second=86  amount=-1\nkerning first=915  second=942  amount=-1\nkerning first=356  second=260  amount=-2\nkerning first=1070  second=44  amount=-1\nkerning first=915  second=44  amount=-1\nkerning first=1058  second=1084  amount=-1\nkerning first=84  second=110  amount=-1\nkerning first=915  second=972  amount=-2\nkerning first=1043  second=1102  amount=-1\nkerning first=910  second=963  amount=-1\nkerning first=34  second=192  amount=-2\nkerning first=221  second=224  amount=-1\nkerning first=196  second=39  amount=-2\nkerning first=923  second=932  amount=-2\nkerning first=66  second=84  amount=-1\nkerning first=46  second=932  amount=-2\nkerning first=46  second=934  amount=-1\nkerning first=46  second=67  amount=-1\nkerning first=34  second=233  amount=-1\nkerning first=933  second=956  amount=-1\nkerning first=39  second=324  amount=-1\nkerning first=34  second=1051  amount=-1\nkerning first=44  second=210  amount=-1\nkerning first=34  second=263  amount=-1\nkerning first=86  second=196  amount=-1\nkerning first=89  second=252  amount=-1\nkerning first=84  second=114  amount=-1\nkerning first=253  second=46  amount=-1\nkerning first=915  second=956  amount=-1\nkerning first=1069  second=1058  amount=-1\nkerning first=84  second=193  amount=-2\nkerning first=932  second=920  amount=-1\nkerning first=221  second=260  amount=-1\nkerning first=79  second=46  amount=-1\nkerning first=932  second=941  amount=-1\nkerning first=1043  second=1090  amount=-1\nkerning first=280  second=74  amount=1\nkerning first=84  second=97  amount=-2\nkerning first=260  second=356  amount=-2\nkerning first=1043  second=1082  amount=-1\nkerning first=39  second=959  amount=-1\nkerning first=221  second=193  amount=-1\nkerning first=214  second=44  amount=-1\nkerning first=914  second=44  amount=-1\nkerning first=39  second=192  amount=-2\nkerning first=1069  second=44  amount=-1\nkerning first=46  second=1063  amount=-2\nkerning first=1068  second=1066  amount=-1\nkerning first=1060  second=1059  amount=-1\nkerning first=87  second=65  amount=-1\nkerning first=1058  second=1080  amount=-1\nkerning first=1043  second=1098  amount=-1\nkerning first=933  second=968  amount=-1\nkerning first=77  second=283  amount=-2\nkerning first=119  second=46  amount=-1\nkerning first=192  second=84  amount=-2\nkerning first=1043  second=46  amount=-1\nkerning first=39  second=287  amount=-1\nkerning first=34  second=945  amount=-1\nkerning first=356  second=231  amount=-2\nkerning first=77  second=228  amount=-2\nkerning first=356  second=111  amount=-2\nkerning first=221  second=115  amount=-1\nkerning first=1068  second=1063  amount=-1\nkerning first=87  second=44  amount=-1\nkerning first=39  second=913  amount=-2\nkerning first=1047  second=44  amount=-1\nkerning first=84  second=233  amount=-2\nkerning first=118  second=44  amount=-1\nkerning first=221  second=351  amount=-1\nkerning first=915  second=940  amount=-2\nkerning first=34  second=97  amount=-1\nkerning first=356  second=271  amount=-2\nkerning first=39  second=250  amount=-1\nkerning first=39  second=231  amount=-1\nkerning first=34  second=113  amount=-1\nkerning first=89  second=242  amount=-1\nkerning first=44  second=86  amount=-1\nkerning first=89  second=114  amount=-1\nkerning first=34  second=228  amount=-1\nkerning first=34  second=100  amount=-1\nkerning first=34  second=902  amount=-2\nkerning first=193  second=34  amount=-2\nkerning first=1058  second=1040  amount=-2\nkerning first=221  second=246  amount=-1\nkerning first=44  second=1098  amount=-1\nkerning first=260  second=86  amount=-1\nkerning first=927  second=46  amount=-1\nkerning first=84  second=243  amount=-2\nkerning first=1058  second=1091  amount=-1\nkerning first=34  second=324  amount=-1\nkerning first=932  second=943  amount=-1\nkerning first=356  second=101  amount=-2\nkerning first=929  second=923  amount=-1\nkerning first=77  second=97  amount=-2\nkerning first=44  second=356  amount=-2\nkerning first=932  second=965  amount=-1\nkerning first=1066  second=39  amount=-1\nkerning first=1091  second=44  amount=-1\nkerning first=89  second=192  amount=-1\nkerning first=81  second=84  amount=-1\nkerning first=45  second=84  amount=-1\nkerning first=932  second=973  amount=-1\nkerning first=902  second=932  amount=-2\nkerning first=221  second=261  amount=-1\nkerning first=84  second=228  amount=-2\nkerning first=1059  second=1060  amount=-1\nkerning first=932  second=927  amount=-1\nkerning first=89  second=347  amount=-1\nkerning first=1058  second=1085  amount=-1\nkerning first=46  second=933  amount=-1\nkerning first=933  second=46  amount=-1\nkerning first=1068  second=1058  amount=-1\nkerning first=915  second=971  amount=-1\nkerning first=34  second=193  amount=-2\nkerning first=1068  second=34  amount=-1\nkerning first=210  second=356  amount=-1\nkerning first=34  second=249  amount=-1\nkerning first=200  second=74  amount=1\nkerning first=356  second=263  amount=-2\nkerning first=84  second=44  amount=-1\nkerning first=84  second=113  amount=-2\nkerning first=39  second=1089  amount=-1\nkerning first=932  second=44  amount=-1\nkerning first=1043  second=1088  amount=-1\nkerning first=39  second=260  amount=-2\nkerning first=1059  second=1076  amount=-1\nkerning first=1098  second=1098  amount=-1\nkerning first=44  second=71  amount=-1\nkerning first=193  second=86  amount=-1\nkerning first=1098  second=1090  amount=-1\nkerning first=65  second=89  amount=-1\nkerning first=34  second=243  amount=-1\nkerning first=936  second=916  amount=-1\nkerning first=356  second=224  amount=-2\nkerning first=66  second=44  amount=-1\nkerning first=915  second=963  amount=-2\nkerning first=1043  second=1051  amount=-1\nkerning first=39  second=281  amount=-1\nkerning first=39  second=1044  amount=-1\nkerning first=39  second=252  amount=-1\nkerning first=34  second=347  amount=-1\nkerning first=910  second=962  amount=-1\nkerning first=933  second=961  amount=-1\nkerning first=1056  second=1083  amount=-1\nkerning first=356  second=117  amount=-1\nkerning first=933  second=962  amount=-1\nkerning first=114  second=39  amount=1\nkerning first=356  second=232  amount=-2\nkerning first=89  second=113  amount=-1\nkerning first=1075  second=44  amount=-1\nkerning first=920  second=44  amount=-1\nkerning first=270  second=356  amount=-1\nkerning first=89  second=228  amount=-1\nkerning first=356  second=382  amount=-1\nkerning first=84  second=347  amount=-1\nkerning first=1043  second=1096  amount=-1\nkerning first=89  second=46  amount=-1\nkerning first=221  second=283  amount=-1\nkerning first=1043  second=1074  amount=-1\nkerning first=356  second=269  amount=-2\nkerning first=915  second=934  amount=-1\nkerning first=932  second=934  amount=-1\nkerning first=89  second=101  amount=-1\nkerning first=933  second=923  amount=-1\nkerning first=39  second=269  amount=-1\nkerning first=915  second=46  amount=-1\nkerning first=196  second=34  amount=-2\nkerning first=84  second=249  amount=-1\nkerning first=44  second=1090  amount=-1\nkerning first=221  second=100  amount=-1\nkerning first=910  second=916  amount=-1\nkerning first=932  second=942  amount=-1\nkerning first=1098  second=34  amount=-1\nkerning first=89  second=99  amount=-1\nkerning first=915  second=927  amount=-1\nkerning first=34  second=242  amount=-1\nkerning first=46  second=262  amount=-1\nkerning first=933  second=916  amount=-1\nkerning first=44  second=932  amount=-2\nkerning first=1043  second=1089  amount=-2\nkerning first=957  second=44  amount=-1\nkerning first=253  second=44  amount=-1\nkerning first=356  second=225  amount=-2\nkerning first=915  second=948  amount=-1\nkerning first=933  second=969  amount=-1\nkerning first=910  second=961  amount=-1\nkerning first=1059  second=44  amount=-1\nkerning first=89  second=281  amount=-1\nkerning first=1056  second=1076  amount=-1\nkerning first=84  second=324  amount=-1\nkerning first=1058  second=1086  amount=-2\nkerning first=102  second=34  amount=1\nkerning first=933  second=954  amount=-1\nkerning first=936  second=923  amount=-1\nkerning first=34  second=913  amount=-2\nkerning first=1043  second=1044  amount=-1\nkerning first=271  second=104  amount=1\nkerning first=34  second=287  amount=-1\nkerning first=84  second=112  amount=-1\nkerning first=123  second=74  amount=2\nkerning first=46  second=210  amount=-1\nkerning first=39  second=945  amount=-1\nkerning first=34  second=250  amount=-1\nkerning first=34  second=966  amount=-1\nkerning first=929  second=44  amount=-3\nkerning first=77  second=101  amount=-2\nkerning first=221  second=252  amount=-1\nkerning first=1059  second=1083  amount=-1\nkerning first=192  second=89  amount=-1\nkerning first=39  second=114  amount=-1\nkerning first=84  second=45  amount=-1\nkerning first=345  second=39  amount=1\nkerning first=45  second=1058  amount=-1\nkerning first=356  second=65  amount=-2\nkerning first=1060  second=1058  amount=-1\nkerning first=910  second=923  amount=-1\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/skin/x2/uiskin.atlas",
    "content": "\nuiskin.png\nsize: 1024,512\nformat: RGBA8888\nfilter: Nearest,Nearest\nrepeat: none\nborder\n  rotate: false\n  xy: 527, 105\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nborder-circle\n  rotate: false\n  xy: 195, 63\n  size: 28, 28\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\nborder-circle-error\n  rotate: false\n  xy: 224, 63\n  size: 28, 28\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\nborder-dark-blue\n  rotate: false\n  xy: 569, 401\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nborder-error\n  rotate: false\n  xy: 581, 418\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nbutton\n  rotate: false\n  xy: 756, 471\n  size: 24, 40\n  split: 10, 10, 10, 8\n  pad: 8, 8, 2, 2\n  orig: 24, 40\n  offset: 0, 0\n  index: -1\nbutton-blue\n  rotate: false\n  xy: 656, 471\n  size: 24, 40\n  split: 10, 10, 10, 8\n  pad: 8, 8, 2, 2\n  orig: 24, 40\n  offset: 0, 0\n  index: -1\nbutton-down\n  rotate: false\n  xy: 656, 471\n  size: 24, 40\n  split: 10, 10, 10, 8\n  pad: 8, 8, 2, 2\n  orig: 24, 40\n  offset: 0, 0\n  index: -1\nbutton-blue-down\n  rotate: false\n  xy: 591, 426\n  size: 24, 40\n  split: 10, 10, 10, 8\n  pad: 8, 8, 2, 2\n  orig: 24, 40\n  offset: 0, 0\n  index: -1\nbutton-blue-over\n  rotate: false\n  xy: 631, 471\n  size: 24, 40\n  split: 10, 10, 10, 8\n  pad: 8, 8, 2, 2\n  orig: 24, 40\n  offset: 0, 0\n  index: -1\nbutton-over\n  rotate: false\n  xy: 681, 471\n  size: 24, 40\n  split: 10, 10, 10, 8\n  pad: 8, 8, 2, 2\n  orig: 24, 40\n  offset: 0, 0\n  index: -1\nbutton-red\n  rotate: false\n  xy: 706, 471\n  size: 24, 40\n  split: 10, 10, 10, 8\n  pad: 8, 8, 2, 2\n  orig: 24, 40\n  offset: 0, 0\n  index: -1\nbutton-window-bg\n  rotate: false\n  xy: 731, 471\n  size: 24, 40\n  split: 10, 10, 10, 8\n  pad: 8, 8, 2, 2\n  orig: 24, 40\n  offset: 0, 0\n  index: -1\ncheck-off\n  rotate: false\n  xy: 253, 63\n  size: 28, 28\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\ntextfield\n  rotate: false\n  xy: 253, 63\n  size: 28, 28\n  split: 2, 2, 2, 2\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\nvis-check\n  rotate: false\n  xy: 253, 63\n  size: 28, 28\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\ncheck-on\n  rotate: false\n  xy: 282, 63\n  size: 28, 28\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\ncolor-picker-bar-selector\n  rotate: false\n  xy: 616, 438\n  size: 14, 28\n  orig: 14, 28\n  offset: 0, 0\n  index: -1\ncolor-picker-cross\n  rotate: false\n  xy: 422, 81\n  size: 10, 10\n  orig: 10, 10\n  offset: 0, 0\n  index: -1\ncolor-picker-selector-horizontal\n  rotate: false\n  xy: 311, 63\n  size: 6, 1\n  orig: 6, 1\n  offset: 0, 0\n  index: -1\ncolor-picker-selector-vertical\n  rotate: false\n  xy: 535, 325\n  size: 1, 6\n  orig: 1, 6\n  offset: 0, 0\n  index: -1\ncursor\n  rotate: false\n  xy: 537, 363\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\ndefault\n  rotate: false\n  xy: 1, 270\n  size: 510, 241\n  orig: 512, 256\n  offset: 0, 15\n  index: -1\ndefault-pane\n  rotate: false\n  xy: 402, 68\n  size: 5, 3\n  split: 1, 1, 1, 1\n  orig: 5, 3\n  offset: 0, 0\n  index: -1\ndefault-pane-no-border\n  rotate: false\n  xy: 539, 250\n  size: 1, 1\n  split: 0, 0, 0, 0\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\ndefault-select\n  rotate: false\n  xy: 1, 43\n  size: 54, 48\n  split: 8, 32, 0, 48\n  orig: 54, 48\n  offset: 0, 0\n  index: -1\ndefault-select-selection\n  rotate: false\n  xy: 56, 40\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nfont-small\n  rotate: false\n  xy: 1, 92\n  size: 510, 177\n  orig: 512, 256\n  offset: 0, 79\n  index: -1\ngrey\n  rotate: false\n  xy: 512, 92\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nmenu-bg\n  rotate: false\n  xy: 512, 92\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nicon-arrow-left\n  rotate: false\n  xy: 91, 63\n  size: 36, 28\n  orig: 44, 44\n  offset: 4, 8\n  index: -1\nicon-arrow-right\n  rotate: false\n  xy: 781, 483\n  size: 36, 28\n  orig: 44, 44\n  offset: 4, 8\n  index: -1\nicon-close\n  rotate: false\n  xy: 631, 450\n  size: 20, 20\n  orig: 44, 44\n  offset: 12, 12\n  index: -1\nicon-close-titlebar\n  rotate: false\n  xy: 1002, 491\n  size: 20, 20\n  orig: 44, 44\n  offset: 12, 12\n  index: -1\nicon-drive\n  rotate: false\n  xy: 781, 472\n  size: 36, 10\n  orig: 44, 44\n  offset: 4, 18\n  index: -1\nicon-file-audio\n  rotate: false\n  xy: 540, 368\n  size: 28, 36\n  orig: 44, 44\n  offset: 8, 4\n  index: -1\nicon-file-image\n  rotate: false\n  xy: 512, 254\n  size: 26, 30\n  orig: 44, 44\n  offset: 9, 7\n  index: -1\nicon-file-pdf\n  rotate: false\n  xy: 512, 285\n  size: 28, 34\n  orig: 44, 44\n  offset: 8, 5\n  index: -1\nicon-file-text\n  rotate: false\n  xy: 512, 223\n  size: 26, 30\n  orig: 44, 44\n  offset: 9, 7\n  index: -1\nicon-folder\n  rotate: false\n  xy: 853, 487\n  size: 32, 24\n  orig: 44, 44\n  offset: 6, 12\n  index: -1\nicon-folder-new\n  rotate: false\n  xy: 128, 62\n  size: 35, 29\n  orig: 44, 44\n  offset: 5, 7\n  index: -1\nicon-folder-parent\n  rotate: false\n  xy: 311, 67\n  size: 32, 24\n  orig: 44, 44\n  offset: 6, 12\n  index: -1\nicon-folder-star\n  rotate: false\n  xy: 818, 485\n  size: 34, 26\n  orig: 44, 44\n  offset: 5, 9\n  index: -1\nicon-list-settings\n  rotate: false\n  xy: 1, 8\n  size: 38, 34\n  orig: 44, 44\n  offset: 5, 3\n  index: -1\nicon-maximize\n  rotate: false\n  xy: 512, 109\n  size: 22, 22\n  orig: 44, 44\n  offset: 11, 11\n  index: -1\nicon-minimize\n  rotate: false\n  xy: 818, 478\n  size: 20, 6\n  orig: 44, 44\n  offset: 12, 11\n  index: -1\nicon-refresh\n  rotate: false\n  xy: 512, 192\n  size: 26, 30\n  orig: 44, 44\n  offset: 9, 7\n  index: -1\nicon-restore\n  rotate: false\n  xy: 512, 163\n  size: 26, 28\n  orig: 44, 44\n  offset: 10, 7\n  index: -1\nicon-star\n  rotate: false\n  xy: 164, 63\n  size: 30, 28\n  orig: 44, 44\n  offset: 7, 8\n  index: -1\nicon-star-outline\n  rotate: false\n  xy: 56, 59\n  size: 34, 32\n  orig: 44, 44\n  offset: 5, 6\n  index: -1\nicon-trash\n  rotate: false\n  xy: 512, 132\n  size: 24, 30\n  orig: 44, 44\n  offset: 10, 7\n  index: -1\nlist-selection\n  rotate: false\n  xy: 616, 427\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nvis-blue\n  rotate: false\n  xy: 616, 427\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\npadded-list-selection\n  rotate: false\n  xy: 591, 424\n  size: 10, 1\n  split: 4, 4, 0, 1\n  orig: 10, 1\n  offset: 0, 0\n  index: -1\nprogressbar\n  rotate: false\n  xy: 535, 332\n  size: 1, 32\n  orig: 1, 32\n  offset: 0, 0\n  index: -1\nprogressbar-filled\n  rotate: false\n  xy: 539, 252\n  size: 1, 32\n  orig: 1, 32\n  offset: 0, 0\n  index: -1\nprogressbar-filled-vertical\n  rotate: false\n  xy: 853, 485\n  size: 32, 1\n  orig: 32, 1\n  offset: 0, 0\n  index: -1\nprogressbar-vertical\n  rotate: false\n  xy: 311, 65\n  size: 32, 1\n  orig: 32, 1\n  offset: 0, 0\n  index: -1\nradio-off\n  rotate: false\n  xy: 886, 483\n  size: 28, 28\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\nvis-radio\n  rotate: false\n  xy: 886, 483\n  size: 28, 28\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\nradio-on\n  rotate: false\n  xy: 915, 483\n  size: 28, 28\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\nscroll\n  rotate: false\n  xy: 36, 1\n  size: 34, 6\n  split: 4, 4, 2, 2\n  orig: 34, 6\n  offset: 0, 0\n  index: -1\nscroll-horizontal\n  rotate: false\n  xy: 40, 8\n  size: 6, 34\n  split: 2, 2, 0, 34\n  pad: -1, -1, 5, 4\n  orig: 6, 34\n  offset: 0, 0\n  index: -1\nscroll-knob-horizontal\n  rotate: false\n  xy: 47, 8\n  size: 6, 34\n  split: 2, 2, 0, 34\n  pad: -1, -1, 13, 12\n  orig: 6, 34\n  offset: 0, 0\n  index: -1\nscroll-knob-vertical\n  rotate: false\n  xy: 1, 1\n  size: 34, 6\n  split: 12, 12, 2, 2\n  orig: 34, 6\n  offset: 0, 0\n  index: -1\nselect-box-list-bg\n  rotate: false\n  xy: 631, 433\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nwindow-bg\n  rotate: false\n  xy: 631, 433\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nselect-down\n  rotate: false\n  xy: 71, 50\n  size: 14, 8\n  orig: 14, 8\n  offset: 0, 0\n  index: -1\nselect-up\n  rotate: false\n  xy: 616, 429\n  size: 14, 8\n  orig: 14, 8\n  offset: 0, 0\n  index: -1\nselection\n  rotate: false\n  xy: 640, 448\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nseparator\n  rotate: false\n  xy: 422, 79\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\ntree-over\n  rotate: false\n  xy: 422, 79\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nseparator-menu\n  rotate: false\n  xy: 433, 90\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nslider\n  rotate: false\n  xy: 537, 154\n  size: 1, 8\n  orig: 1, 8\n  offset: 0, 0\n  index: -1\nslider-knob\n  rotate: false\n  xy: 585, 467\n  size: 22, 44\n  orig: 22, 44\n  offset: 0, 0\n  index: -1\nslider-knob-disabled\n  rotate: false\n  xy: 512, 320\n  size: 22, 44\n  orig: 22, 44\n  offset: 0, 0\n  index: -1\nslider-knob-down\n  rotate: false\n  xy: 568, 422\n  size: 22, 44\n  orig: 22, 44\n  offset: 0, 0\n  index: -1\nslider-knob-over\n  rotate: false\n  xy: 608, 467\n  size: 22, 44\n  orig: 22, 44\n  offset: 0, 0\n  index: -1\nslider-vertical\n  rotate: false\n  xy: 91, 61\n  size: 8, 1\n  orig: 8, 1\n  offset: 0, 0\n  index: -1\nsplitpane\n  rotate: false\n  xy: 540, 366\n  size: 8, 1\n  orig: 8, 1\n  offset: 0, 0\n  index: -1\nsplitpane-over\n  rotate: false\n  xy: 1002, 489\n  size: 8, 1\n  orig: 8, 1\n  offset: 0, 0\n  index: -1\nsplitpane-vertical\n  rotate: false\n  xy: 535, 123\n  size: 1, 8\n  orig: 1, 8\n  offset: 0, 0\n  index: -1\nsplitpane-vertical-over\n  rotate: false\n  xy: 54, 34\n  size: 1, 8\n  orig: 1, 8\n  offset: 0, 0\n  index: -1\nsub-menu\n  rotate: false\n  xy: 631, 435\n  size: 8, 14\n  orig: 8, 14\n  offset: 0, 0\n  index: -1\ntextfield-over\n  rotate: false\n  xy: 944, 483\n  size: 28, 28\n  split: 2, 2, 2, 2\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\nvis-check-over\n  rotate: false\n  xy: 944, 483\n  size: 28, 28\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\ntooltip-bg\n  rotate: false\n  xy: 839, 481\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\ntouchpad-knob\n  rotate: false\n  xy: 540, 467\n  size: 44, 44\n  orig: 44, 44\n  offset: 0, 0\n  index: -1\ntree-minus\n  rotate: false\n  xy: 672, 460\n  size: 10, 10\n  orig: 16, 16\n  offset: 2, 4\n  index: -1\ntree-plus\n  rotate: false\n  xy: 568, 405\n  size: 12, 16\n  orig: 16, 16\n  offset: 2, 0\n  index: -1\ntree-selection\n  rotate: false\n  xy: 818, 474\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nvis-check-down\n  rotate: false\n  xy: 973, 483\n  size: 28, 28\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\nvis-check-tick\n  rotate: false\n  xy: 402, 72\n  size: 19, 19\n  orig: 28, 28\n  offset: 5, 4\n  index: -1\nvis-check-tick-disabled\n  rotate: false\n  xy: 652, 451\n  size: 19, 19\n  orig: 28, 28\n  offset: 5, 4\n  index: -1\nvis-radio-down\n  rotate: false\n  xy: 344, 63\n  size: 28, 28\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\nvis-radio-over\n  rotate: false\n  xy: 373, 63\n  size: 28, 28\n  orig: 28, 28\n  offset: 0, 0\n  index: -1\nvis-radio-tick\n  rotate: false\n  xy: 512, 94\n  size: 14, 14\n  orig: 28, 28\n  offset: 7, 7\n  index: -1\nvis-radio-tick-disabled\n  rotate: false\n  xy: 56, 44\n  size: 14, 14\n  orig: 28, 28\n  offset: 7, 7\n  index: -1\nvis-red\n  rotate: false\n  xy: 672, 458\n  size: 1, 1\n  orig: 1, 1\n  offset: 0, 0\n  index: -1\nwhite\n  rotate: false\n  xy: 71, 46\n  size: 3, 3\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nwindow\n  rotate: false\n  xy: 540, 405\n  size: 27, 61\n  split: 5, 4, 53, 3\n  orig: 27, 61\n  offset: 0, 0\n  index: -1\nwindow-border-bg\n  rotate: false\n  xy: 86, 55\n  size: 3, 3\n  split: 1, 1, 1, 1\n  orig: 3, 3\n  offset: 0, 0\n  index: -1\nwindow-noborder\n  rotate: false\n  xy: 512, 365\n  size: 27, 61\n  split: 5, 4, 53, 3\n  orig: 27, 61\n  offset: 0, 0\n  index: -1\nwindow-resizable\n  rotate: false\n  xy: 512, 427\n  size: 27, 84\n  split: 3, 19, 2, 20\n  pad: 5, 5, 50, 7\n  orig: 27, 84\n  offset: 0, 0\n  index: -1\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/skin/x2/uiskin.json",
    "content": "{\ncom.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: {file: default.fnt },\n\tsmall-font: {file: font-small.fnt }\n},\ncom.badlogic.gdx.graphics.Color: {\n\tblack: {a: 1, b: 0, g: 0, r: 0 },\n\twhite: {a: 1, b: 1, g: 1, r: 1 },\n\tgreen: {a: 1, b: 0, g: 1, r: 0 },\n\tred: {a: 1, b: 0, g: 0, r: 1 },\n\tblue: {a: 1, b: 1, g: 0, r: 0 },\n\tgrey: {a: 1, b: 0.32, g: 0.32, r: 0.32 },\n\tvis-blue: {a: 1, b: 0.886, g: 0.631, r: 0.105 },\n\tvis-red: {a: 1, b: 0.047, g: 0, r: 0.862 },\n\tmenuitem: {a: 1, b: 0.65, g: 0.65, r: 0.65 },\n\tlink-label: {a: 1, b: 0.886, g: 0.631, r: 0.105 }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable: {\n\tdialogDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.45} }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: {\n\tdefault: {down: button-down, up: button },\n\tblue: {down: button-blue-down, up: button-blue },\n\ttoggle: {checked: button-down, down: button-down, up: button }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: {\n\tdefault: {over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, down: button-down, up: button },\n\tblue: {over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, down: button-blue-down, up: button-blue },\n\ttoggle: {font: default-font, fontColor: white, checked: button-down, down: button-down, up: button, over: button-over, disabled: button, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ImageButton$ImageButtonStyle: {\n\tdefault: {down: button-down, up: button },\n\tblue: {down: button-blue-down, up: button-blue },\n\ttoggle: {checked: button-down, down: button-down, up: button }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ImageTextButton$ImageTextButtonStyle: {\n\tdefault: {down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ScrollPane$ScrollPaneStyle: {\n\tlist: {vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal, corner: grey },\n\tdefault: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal, corner: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.SelectBox$SelectBoxStyle: {\n\tdefault: {background: default-select, scrollStyle: default, listStyle: {font: default-font, selection: padded-list-selection, background: select-box-list-bg}, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.SplitPane$SplitPaneStyle: {\n\tdefault-vertical: {handle: splitpane-vertical },\n\tdefault-horizontal: {handle: splitpane }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Window$WindowStyle: {\n\tdefault: {titleFont: default-font, background: window, titleFontColor: white },\n\tresizable: {background: window-resizable, titleFont: default-font, titleFontColor: white },\n\tnoborder: {background: window-noborder, titleFont: default-font, titleFontColor: white },\n\tdialog: {stageBackground: dialogDim, titleFont: default-font, background: window, titleFontColor: white }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ProgressBar$ProgressBarStyle: {\n\tdefault-horizontal: {background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled },\n\tdefault-vertical: {background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle: {\n\tdefault-horizontal: {background: slider, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled },\n\tdefault-vertical: {background: slider-vertical, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {\n\tdefault: {font: default-font, fontColor: white },\n\tlink-label: {fontColor: link-label, font: default-font },\n\tsmall: {font: small-font, fontColor: white },\n\tmenuitem-shortcut: {font: default-font, fontColor: menuitem }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextField$TextFieldStyle: {\n\tdefault: {font: default-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey },\n\tsmall: {font: small-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.CheckBox$CheckBoxStyle: {\n\tdefault: {checkboxOn: check-on, checkboxOff: check-off, font: default-font, fontColor: white, disabledFontColor: grey },\n\tradio: {checkboxOn: radio-on, checkboxOff: radio-off, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.List$ListStyle: {\n\tdefault: {fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Touchpad$TouchpadStyle: {\n\tdefault: {background: default-pane, knob: touchpad-knob }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Tree$TreeStyle: {\n\tdefault: {minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextTooltip$TextTooltipStyle: {\n\tdefault: {background: default-pane, label: {font: default-font, fontColor: white} }\n},\ncom.kotcrab.vis.ui.Sizes: {\n\tdefault: {scaleFactor: 1, spacingBottom: 8, spacingRight: 6, buttonBarSpacing: 10, menuItemIconSize: 22, borderSize: 1, spinnerButtonHeight: 12, spinnerFieldSize: 40, fileChooserViewModeBigIconsSize: 200, fileChooserViewModeMediumIconsSize: 128, fileChooserViewModeSmallIconsSize: 64, fileChooserViewModeListWidthSize: 155 },\n\tx2: {scaleFactor: 2, menuItemIconSize: 44, spinnerButtonHeight: 24, spinnerFieldSize: 80, spacingBottom: 8, spacingRight: 6, buttonBarSpacing: 10, borderSize: 1, fileChooserViewModeBigIconsSize: 200, fileChooserViewModeMediumIconsSize: 128, fileChooserViewModeSmallIconsSize: 64, fileChooserViewModeListWidthSize: 155 }\n},\ncom.kotcrab.vis.ui.widget.VisTextField$VisTextFieldStyle: {\n\tdefault: {focusBorder: border, errorBorder: border-error, font: default-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor },\n\ttextArea: {errorBorder: border-error, font: default-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, cursor: cursor },\n\tsmall: {focusBorder: border, errorBorder: border-error, font: small-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor },\n\tlabel: {selection: selection, errorBorder: border-error, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.VisTextButton$VisTextButtonStyle: {\n\tdefault: {focusBorder: border, down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle: {focusBorder: border, checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey },\n\tblue: {focusBorder: border-dark-blue, down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\tmenu-bar: {over: button-down, font: default-font, fontColor: white, down: button-down, up: button, disabled: button, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.VisImageButton$VisImageButtonStyle: {\n\tdefault: {down: button-down, up: button, over: button-over, disabled: button, focusBorder: border },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue, focusBorder: border-dark-blue },\n\ttoggle: {checked: button-down, focusBorder: border, down: button-down, up: button, over: button-over, disabled: button },\n\tclose: {down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button },\n\tclose-active-tab: {down: button-red, imageUp: icon-close, up: button-blue, over: button-blue-over, disabled: button-blue },\n\tclose-window: {up: button-window-bg, down: button-red, over: button-over, imageUp: icon-close, disabled: button },\n\tclose-titlebar: {imageUp: icon-close-titlebar, down: button-red, up: button, over: button-over, disabled: button }\n},\ncom.kotcrab.vis.ui.widget.VisImageTextButton$VisImageTextButtonStyle: {\n\tdefault: {down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, focusBorder: border },\n\ttoggle: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey, focusBorder: border },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, focusBorder: border-dark-blue },\n\tdefault-noborder: {down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle-noborder: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey },\n\tmenu-bar: {over: button-down, font: default-font, fontColor: white, down: button-down, up: button, disabled: button, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.VisCheckBox$VisCheckBoxStyle: {\n\tdefault: {checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled, focusBorder: border, errorBorder: border-error, font: default-font, fontColor: white, disabledFontColor: grey },\n\tradio: {checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled, focusBorder: border-circle, errorBorder: border-circle-error, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.PopupMenu$PopupMenuStyle: {\n\tnoborder: {background: button },\n\tdefault: {background: button, border: border }\n},\ncom.kotcrab.vis.ui.widget.Menu$MenuStyle: {\n\tdefault: {background: button, border: border, openButtonStyle: menu-bar },\n\tnoborder: {background: button, openButtonStyle: menu-bar }\n},\ncom.kotcrab.vis.ui.widget.MenuBar$MenuBarStyle: {\n\tdefault: {background: menu-bg }\n},\ncom.kotcrab.vis.ui.widget.Separator$SeparatorStyle: {\n\tdefault: {background: separator, thickness: 4 },\n\tvertical: {background: separator, thickness: 4 },\n\tmenu: {background: separator-menu, thickness: 3 }\n},\ncom.kotcrab.vis.ui.widget.VisSplitPane$VisSplitPaneStyle: {\n\tdefault-vertical: {handle: splitpane-vertical, handleOver: splitpane-vertical-over },\n\tdefault-horizontal: {handle: splitpane, handleOver: splitpane-over }\n},\ncom.kotcrab.vis.ui.widget.MultiSplitPane$MultiSplitPaneStyle: {\n\tdefault-vertical: {handle: splitpane-vertical, handleOver: splitpane-vertical-over },\n\tdefault-horizontal: {handle: splitpane, handleOver: splitpane-over }\n},\ncom.kotcrab.vis.ui.widget.MenuItem$MenuItemStyle: {\n\tdefault: {subMenu: sub-menu, down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey, subMenu: sub-menu }\n},\ncom.kotcrab.vis.ui.widget.Tooltip$TooltipStyle: {\n\tdefault: {background: tooltip-bg }\n},\ncom.kotcrab.vis.ui.widget.LinkLabel$LinkLabelStyle: {\n\tdefault: {fontColor: link-label, underline: white, font: default-font }\n},\ncom.kotcrab.vis.ui.widget.tabbedpane.TabbedPane$TabbedPaneStyle: {\n\tdefault: {background: menu-bg, separatorBar: list-selection, vertical: false, buttonStyle: {down: button-down, up: button, checked: button-down, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey} },\n\tvertical: {vertical: true, background: menu-bg, separatorBar: list-selection, buttonStyle: {down: button-down, up: button, checked: button-down, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey} }\n},\ncom.kotcrab.vis.ui.widget.spinner.Spinner$SpinnerStyle: {\n\tdefault: {down: select-down, up: select-up }\n},\ncom.kotcrab.vis.ui.widget.file.FileChooserStyle: {\n\tdefault: {highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right, iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive, iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh, iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio, iconListSettings: icon-list-settings, contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n},\ncom.kotcrab.vis.ui.widget.color.ColorPickerWidgetStyle: {\n\tdefault: {barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right, verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n},\ncom.kotcrab.vis.ui.widget.color.ColorPickerStyle: {\n\tdefault: {pickerStyle: {barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right, verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal}, titleFont: default-font, background: window, titleFontColor: white }\n},\ncom.kotcrab.vis.ui.widget.toast.Toast$ToastStyle: {\n\tdefault: {background: tooltip-bg, closeButtonStyle: close },\n\tdark: {background: window-border-bg, closeButtonStyle: close-window }\n},\ncom.kotcrab.vis.ui.widget.BusyBar$BusyBarStyle: {\n\tdefault: {height: 2, segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 },\n\tslim: {height: 1, segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 },\n\tthick: {height: 6, segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n},\ncom.kotcrab.vis.ui.widget.ListViewStyle: {\n\tdefault: {scrollPaneStyle: list }\n},\ncom.kotcrab.vis.ui.util.form.SimpleFormValidator$FormValidatorStyle: {\n\tdefault: {errorLabelColor: vis-red, validLabelColor: white },\n\tsmooth: {colorTransitionDuration: 0.3, errorLabelColor: vis-red, validLabelColor: white }\n},\ncom.kotcrab.vis.ui.util.adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\tdefault: {background: window-bg, selection: list-selection }\n}\n\n}"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/widget/color/internal/checkerboard.frag",
    "content": "#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform float u_width;\nuniform float u_height;\nuniform float u_gridSize;\n\nvarying vec4 v_color;\nvarying vec2 v_texCoords;\n\nvoid main() {\n    vec2 res = v_texCoords.xy * vec2(u_width / u_height, 1) / vec2(u_width, u_height);\n\tvec2 uvx = floor(u_height * u_width / u_gridSize * res);\n\tvec2 uvy = floor(u_height * u_height / u_gridSize * res);\n\tbool isEven = (mod(uvx.x + uvy.y, 2.0) == 0.0);\n\tgl_FragColor = isEven ? v_color * vec4(0.6, 0.6, 0.6, 1.0) : v_color * vec4(0.4, 0.4, 0.4, 1.0);\n}\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/widget/color/internal/default.vert",
    "content": "uniform mat4 u_projTrans;\n \nattribute vec4 a_position;\nattribute vec2 a_texCoord0;\nattribute vec4 a_color;\n\nvarying vec4 v_color;\nvarying vec2 v_texCoords;\n\nvoid main() {\n    gl_Position = u_projTrans * a_position;\n    v_texCoords = a_texCoord0;\n    v_color = a_color;\n}\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/widget/color/internal/hsv.frag",
    "content": "#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform int u_mode; //defined in ChannelBar.java\nuniform float u_h;\nuniform float u_s;\nuniform float u_v;\n\nvarying vec4 v_color;\nvarying vec2 v_texCoords;\n\nvec3 hsv2rgb(vec3 c) {\n    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\nvoid main() {\n    if(u_mode == 4) gl_FragColor = v_color * vec4(hsv2rgb(vec3(v_texCoords.s, u_s, u_v)), 1.0); //h bar\n    if(u_mode == 5) gl_FragColor = v_color * vec4(hsv2rgb(vec3(u_h, v_texCoords.s, u_v)), 1.0); //s bar\n    if(u_mode == 6) gl_FragColor = v_color * vec4(hsv2rgb(vec3(u_h, u_s, v_texCoords.s)), 1.0); //v bar\n}\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/widget/color/internal/palette.frag",
    "content": "#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform float u_h;\n\nvarying vec4 v_color;\nvarying vec2 v_texCoords;\n\nvec3 hsv2rgb(vec3 c) {\n    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\nvoid main() {\n    gl_FragColor = v_color * vec4(hsv2rgb(vec3(u_h, 1.0 - v_texCoords.t, v_texCoords.s)), 1.0);\n}\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/widget/color/internal/rgb.frag",
    "content": "#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform int u_mode; //defined in ChannelBar.java\nuniform float u_r;\nuniform float u_g;\nuniform float u_b;\n\nvarying vec4 v_color;\nvarying vec2 v_texCoords;\n\nvoid main() {\n    if(u_mode == 0) gl_FragColor = v_color * vec4(u_r, u_g, u_b, v_texCoords.s); //alpha bar\n\n    if(u_mode == 1) gl_FragColor = v_color * vec4(v_texCoords.s, u_g, u_b, 1.0); //r bar\n    if(u_mode == 2) gl_FragColor = v_color * vec4(u_r, v_texCoords.s, u_b, 1.0); //g bar\n    if(u_mode == 3) gl_FragColor = v_color * vec4(u_r, u_g, v_texCoords.s, 1.0); //b bar\n}\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/ui/widget/color/internal/verticalBar.frag",
    "content": "#ifdef GL_ES\nprecision mediump float;\n#endif\n\nvarying vec4 v_color;\nvarying vec2 v_texCoords;\n\nvec3 hsv2rgb(vec3 c) {\n    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\nvoid main() {\n    gl_FragColor = v_color * vec4(hsv2rgb(vec3(1.0 - v_texCoords.t, 1, 1)), 1.0);\n}\n"
  },
  {
    "path": "ui/src/main/resources/com/kotcrab/vis/vis-ui.gwt.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 2014-2017 See AUTHORS file.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~ http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n\n<!DOCTYPE module PUBLIC \"-//Google Inc.//DTD Google Web Toolkit trunk//EN\" \"http://google-web-toolkit.googlecode.com/svn/trunk/distro-source/core/src/gwt-module.dtd\">\n<module>\n\t<source path='ui'>\n\t\t<exclude name=\"widget/file/FileChooser.java\" />\n\t\t<exclude name=\"widget/file/FileChooserAdapter.java\" />\n\t\t<exclude name=\"widget/file/FileChooserListener.java\" />\n\t\t<exclude name=\"widget/file/FileUtils.java\" />\n\t\t<exclude name=\"widget/file/JNAFileDeleter.java\" />\n\t\t<exclude name=\"widget/file/SingleFileChooserListener.java\" />\n\t\t<exclude name=\"widget/file/StreamingFileChooserListener.java\" />\n        <exclude name=\"widget/file/internal/**\" />\n\t\t<exclude name=\"util/form/FormValidator.java\" />\n\t\t<exclude name=\"util/highlight/Highlighter.java\" />\n\t\t<exclude name=\"util/highlight/RegexHighlightRule.java\" />\n\t\t<exclude name=\"util/async/**\" />\n\t</source>\n\n    <!-- X1 skin -->\n\t<extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/skin/x1/uiskin.json\" />\n\t<extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/skin/x1/uiskin.atlas\" />\n\t<extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/skin/x1/uiskin.png\" />\n\t<extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/skin/x1/default.fnt\" />\n\t<extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/skin/x1/font-small.fnt\" />\n\n    <!-- X2 skin -->\n\t<extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/skin/x2/uiskin.json\" />\n    <extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/skin/x2/uiskin.atlas\" />\n    <extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/skin/x2/uiskin.png\" />\n    <extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/skin/x2/default.fnt\" />\n    <extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/skin/x2/font-small.fnt\" />\n\n    <!-- ColorPicker shaders -->\n    <extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/widget/color/internal/default.vert\" />\n    <extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/widget/color/internal/hsv.frag\" />\n    <extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/widget/color/internal/rgb.frag\" />\n    <extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/widget/color/internal/palette.frag\" />\n    <extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/widget/color/internal/verticalBar.frag\" />\n    <extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/widget/color/internal/checkerboard.frag\" />\n\n    <!-- I18N files -->\n\t<extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/i18n/ButtonBar.properties\" />\n\t<extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/i18n/ColorPicker.properties\" />\n\t<extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/i18n/Common.properties\" />\n\t<extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/i18n/Dialogs.properties\" />\n\t<extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/i18n/FileChooser.properties\" />\n\t<extend-configuration-property name=\"gdx.files.classpath\" value=\"com/kotcrab/vis/ui/i18n/TabbedPane.properties\" />\n\n    <!-- When changing those don't forget to update META-INF/robovm/ios/robovm.xml -->\n\n\t<extend-configuration-property name=\"gdx.reflect.include\" value=\"com.kotcrab.vis.ui.Sizes\" />\n\t<extend-configuration-property name=\"gdx.reflect.include\" value=\"com.kotcrab.vis.ui.widget\" />\n\t<extend-configuration-property name=\"gdx.reflect.include\" value=\"com.kotcrab.vis.ui.widget.spinner\" />\n\t<extend-configuration-property name=\"gdx.reflect.include\" value=\"com.kotcrab.vis.ui.widget.dialog\" />\n\t<extend-configuration-property name=\"gdx.reflect.include\" value=\"com.kotcrab.vis.ui.widget.color\" />\n\t<extend-configuration-property name=\"gdx.reflect.include\" value=\"com.kotcrab.vis.ui.widget.tabbedpane\" />\n\t<extend-configuration-property name=\"gdx.reflect.include\" value=\"com.kotcrab.vis.ui.widget.toast\" />\n\t<extend-configuration-property name=\"gdx.reflect.include\" value=\"com.kotcrab.vis.ui.util.form\" />\n    <extend-configuration-property name=\"gdx.reflect.include\" value=\"com.kotcrab.vis.ui.util.adapter.SimpleListAdapter\" />\n\n    <extend-configuration-property name=\"gdx.reflect.exclude\" value=\"com.kotcrab.vis.ui.widget.file\" />\n    <extend-configuration-property name=\"gdx.reflect.include\" value=\"com.kotcrab.vis.ui.widget.file.FileChooserStyle\" />\n</module>\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/GreaterThanValidatorTest.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test;\n\nimport com.kotcrab.vis.ui.util.Validators.GreaterThanValidator;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\npublic class GreaterThanValidatorTest {\n\n\t@Test\n\tpublic void testValidateInput () throws Exception {\n\t\tGreaterThanValidator validator = new GreaterThanValidator(5);\n\t\tGreaterThanValidator validatorEquals = new GreaterThanValidator(5, true);\n\n\t\tassertFalse(validator.validateInput(\"A\"));\n\t\tassertFalse(validator.validateInput(\"\"));\n\t\tassertFalse(validatorEquals.validateInput(\"A\"));\n\t\tassertFalse(validatorEquals.validateInput(\"\"));\n\n\t\tassertFalse(validator.validateInput(\"5\"));\n\t\tassertTrue(validator.validateInput(\"6\"));\n\t\tassertTrue(validatorEquals.validateInput(\"5\"));\n\t\tassertTrue(validatorEquals.validateInput(\"6\"));\n\n\t\tassertTrue(validator.validateInput(String.valueOf(Float.MAX_VALUE)));\n\t\tassertTrue(validatorEquals.validateInput(String.valueOf(Float.MAX_VALUE)));\n\n\t\tassertFalse(validator.validateInput(String.valueOf(Float.MIN_VALUE)));\n\t\tassertFalse(validatorEquals.validateInput(String.valueOf(Float.MIN_VALUE)));\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/LesserThanValidatorTest.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test;\n\nimport com.kotcrab.vis.ui.util.Validators.LesserThanValidator;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\npublic class LesserThanValidatorTest {\n\t@Test\n\tpublic void testValidateInput () throws Exception {\n\t\tLesserThanValidator validator = new LesserThanValidator(5);\n\t\tLesserThanValidator validatorEquals = new LesserThanValidator(5, true);\n\n\t\tassertFalse(validator.validateInput(\"A\"));\n\t\tassertFalse(validator.validateInput(\"\"));\n\t\tassertFalse(validatorEquals.validateInput(\"A\"));\n\t\tassertFalse(validatorEquals.validateInput(\"\"));\n\n\t\tassertFalse(validator.validateInput(\"5\"));\n\t\tassertTrue(validator.validateInput(\"4\"));\n\t\tassertTrue(validatorEquals.validateInput(\"5\"));\n\t\tassertTrue(validatorEquals.validateInput(\"4\"));\n\n\t\tassertFalse(validator.validateInput(String.valueOf(Float.MAX_VALUE)));\n\t\tassertFalse(validatorEquals.validateInput(String.valueOf(Float.MAX_VALUE)));\n\n\t\tassertTrue(validator.validateInput(String.valueOf(Float.MIN_VALUE)));\n\t\tassertTrue(validatorEquals.validateInput(String.valueOf(Float.MIN_VALUE)));\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/TestImageTextButtonOrientation.java",
    "content": "package com.kotcrab.vis.ui.test;\n\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.VisImageTextButton;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\npublic class TestImageTextButtonOrientation extends VisWindow {\n    public TestImageTextButtonOrientation() {\n        super(\"text image button orientation\");\n\n        TableUtils.setSpacingDefaults(this);\n        columnDefaults(0).left();\n\n        addVisWidgets();\n\n        setSize(400, 250);\n        centerWindow();\n    }\n\n    private void addVisWidgets () {\n        Drawable icon = VisUI.getSkin().getDrawable(\"icon-folder\");\n\n        VisImageTextButton right = new VisImageTextButton(\"right\", icon);\n        VisImageTextButton left = new VisImageTextButton(\"left\", icon);\n        VisImageTextButton top = new VisImageTextButton(\"top\", icon);\n        VisImageTextButton bottom = new VisImageTextButton(\"bottom\", icon);\n\n        // 'text_right' is the default orientation for backwards compatibility, so no need to set it explicitly\n        // right.setOrientation(VisImageTextButton.Orientation.text_right);\n        left.setOrientation(VisImageTextButton.Orientation.TEXT_LEFT);\n        top.setOrientation(VisImageTextButton.Orientation.TEXT_TOP);\n        bottom.setOrientation(VisImageTextButton.Orientation.TEXT_BOTTOM);\n\n        add(new VisLabel(\"VisImageTextButton TEXT_RIGHT (default)\"));\n        add(right).row();\n        add(new VisLabel(\"VisImageTextButton TEXT_LEFT\"));\n        add(left).row();\n        add(new VisLabel(\"VisImageTextButton TEXT_TOP\"));\n        add(top).row();\n        add(new VisLabel(\"VisImageTextButton TEXT_BOTTOM\"));\n        add(bottom).padBottom(3f).row();\n    }\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/HighResFileChooserIconProvider.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.graphics.g2d.TextureAtlas;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;\nimport com.badlogic.gdx.utils.Disposable;\nimport com.kotcrab.vis.ui.widget.file.FileChooser;\nimport com.kotcrab.vis.ui.widget.file.FileChooser.FileIconProvider;\n\n/**\n * {@link FileIconProvider} implementation supporting extended file chooser view modes (big icons, medium icons and\n * small icons). To use this you must include high resolution texture atlas for files icons. (see `vis-ui-contrib/file-chooser-high-res.atlas`)\n * @author Kotcrab\n */\npublic class HighResFileChooserIconProvider extends FileChooser.DefaultFileIconProvider implements Disposable {\n\tprivate TextureAtlas highResTextures;\n\n\tprivate Drawable[] iconFolderBig = new Drawable[3];\n\tprivate Drawable[] iconFileText = new Drawable[3];\n\tprivate Drawable[] iconFileImage = new Drawable[3];\n\tprivate Drawable[] iconFilePdf = new Drawable[3];\n\tprivate Drawable[] iconFileAudio = new Drawable[3];\n\n\tpublic HighResFileChooserIconProvider (FileChooser chooser) {\n\t\tsuper(chooser);\n\t\thighResTextures = new TextureAtlas(Gdx.files.classpath(\"file-chooser-high-res.atlas\"));\n\t\tloadIcons(iconFolderBig, \"icon-folder\");\n\t\tloadIcons(iconFileText, \"icon-file-text\");\n\t\tloadIcons(iconFileImage, \"icon-file-image\");\n\t\tloadIcons(iconFilePdf, \"icon-file-pdf\");\n\t\tloadIcons(iconFileAudio, \"icon-file-audio\");\n\t}\n\n\tprivate void loadIcons (Drawable[] target, String prefix) {\n\t\ttarget[0] = new TextureRegionDrawable(highResTextures.findRegion(prefix + \"-small\"));\n\t\ttarget[1] = new TextureRegionDrawable(highResTextures.findRegion(prefix + \"-medium\"));\n\t\ttarget[2] = new TextureRegionDrawable(highResTextures.findRegion(prefix + \"-big\"));\n\t}\n\n\tprivate Drawable getIcon (Drawable[] source, FileChooser.ViewMode viewMode) {\n\t\tif (viewMode == FileChooser.ViewMode.SMALL_ICONS) return source[0];\n\t\tif (viewMode == FileChooser.ViewMode.MEDIUM_ICONS) return source[1];\n\t\tif (viewMode == FileChooser.ViewMode.BIG_ICONS) return source[2];\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean isThumbnailModesSupported () {\n\t\treturn true;\n\t}\n\n\t@Override\n\tprotected Drawable getDirIcon (FileChooser.FileItem item) {\n\t\tDrawable icon = getIcon(iconFolderBig, chooser.getViewMode());\n\t\tif (icon == null)\n\t\t\treturn super.getDirIcon(item);\n\t\treturn icon;\n\t}\n\n\t@Override\n\tprotected Drawable getImageIcon (FileChooser.FileItem item) {\n\t\tDrawable icon = getIcon(iconFileImage, chooser.getViewMode());\n\t\tif (icon == null)\n\t\t\treturn super.getImageIcon(item);\n\t\treturn icon;\n\t}\n\n\t@Override\n\tprotected Drawable getAudioIcon (FileChooser.FileItem item) {\n\t\tDrawable icon = getIcon(iconFileAudio, chooser.getViewMode());\n\t\tif (icon == null)\n\t\t\treturn super.getAudioIcon(item);\n\t\treturn icon;\n\t}\n\n\t@Override\n\tprotected Drawable getPdfIcon (FileChooser.FileItem item) {\n\t\tDrawable icon = getIcon(iconFilePdf, chooser.getViewMode());\n\t\tif (icon == null)\n\t\t\treturn super.getPdfIcon(item);\n\t\treturn icon;\n\t}\n\n\t@Override\n\tprotected Drawable getTextIcon (FileChooser.FileItem item) {\n\t\tDrawable icon = getIcon(iconFileText, chooser.getViewMode());\n\t\tif (icon == null)\n\t\t\treturn super.getTextIcon(item);\n\t\treturn icon;\n\t}\n\n\t@Override\n\tpublic void dispose () {\n\t\thighResTextures.dispose();\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestBuilders.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.math.MathUtils;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.kotcrab.vis.ui.building.*;\nimport com.kotcrab.vis.ui.building.utilities.CellWidget;\nimport com.kotcrab.vis.ui.building.utilities.Padding;\nimport com.kotcrab.vis.ui.building.utilities.layouts.ActorLayout;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.*;\n\npublic class TestBuilders extends VisWindow {\n\n\tpublic TestBuilders () {\n\t\tsuper(\"table builders\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\n\t\tVisTextButton standardButton;\n\t\tVisTextButton centeredButton;\n\t\tVisTextButton oneColumnButton;\n\t\tVisTextButton oneRowButton;\n\t\tVisTextButton gridButton;\n\n\t\tVisTable table = new VisTable(true);\n\t\ttable.add(standardButton = new VisTextButton(\"standard\"));\n\t\ttable.add(centeredButton = new VisTextButton(\"centered\"));\n\t\ttable.add(oneColumnButton = new VisTextButton(\"one column\"));\n\t\ttable.add(oneRowButton = new VisTextButton(\"one row\"));\n\t\ttable.add(gridButton = new VisTextButton(\"grid\"));\n\n\t\tfinal Padding padding = new Padding(2, 3);\n\n\t\tstandardButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tgetStage().addActor(new TestBuilder(\"standard builder\", new StandardTableBuilder(padding)));\n\t\t\t}\n\t\t});\n\n\t\tcenteredButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tgetStage().addActor(new TestBuilder(\"centered builder\", new CenteredTableBuilder(padding)));\n\t\t\t}\n\t\t});\n\n\t\toneColumnButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tgetStage().addActor(new TestBuilder(\"one column builder\", new OneColumnTableBuilder(padding)));\n\t\t\t}\n\t\t});\n\n\t\toneRowButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tgetStage().addActor(new TestBuilder(\"one row builder\", new OneRowTableBuilder(padding)));\n\t\t\t}\n\t\t});\n\n\t\tgridButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tgetStage().addActor(new TestBuilder(\"grid builder (row size == 2)\", new GridTableBuilder(padding, 2)));\n\t\t\t}\n\t\t});\n\n\t\tadd(standardButton);\n\t\tadd(centeredButton);\n\t\tadd(oneColumnButton);\n\t\tadd(oneRowButton);\n\t\tadd(gridButton);\n\n\t\tpack();\n\t\tsetPosition(31, 35);\n\n\t\tnew GridTableBuilder(4);\n\t}\n\n\tprivate class TestBuilder extends VisWindow {\n\t\tpublic TestBuilder (String name, TableBuilder builder) {\n\t\t\tsuper(name);\n\n\t\t\tRowLayout rowLayout = new RowLayout(new Padding(0, 0, 0, 5));\n\n\t\t\tsetModal(true);\n\t\t\tcloseOnEscape();\n\t\t\taddCloseButton();\n\n\t\t\tfinal VisCheckBox debugViewCheckBox = new VisCheckBox(\"toggle debug view\");\n\t\t\tdebugViewCheckBox.addListener(new ChangeListener() {\n\t\t\t\t@Override\n\t\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t\tsetDebug(debugViewCheckBox.isChecked(), true);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tbuilder.append(debugViewCheckBox);\n\t\t\tbuilder.row();\n\n\t\t\tbuilder.append(new VisLabel(\"title label\"));\n\t\t\tbuilder.row();\n\n\t\t\tbuilder.append(new VisLabel(\"path\"));\n\t\t\tbuilder.append(rowLayout, CellWidget.builder().fillX(),\n\t\t\t\t\tCellWidget.of(new VisTextField()).expandX().fillX().wrap(),\n\t\t\t\t\tCellWidget.of(new VisTextButton(\"choose\")).padding(new Padding(0, 0)).wrap());\n\t\t\tbuilder.row();\n\n\t\t\tbuilder.append(new VisLabel(\"name\"));\n\t\t\tbuilder.append(CellWidget.of(new VisTextField()).expandX().fillX().wrap());\n\t\t\tbuilder.row();\n\n\t\t\tbuilder.append(new VisLabel(\"description\"));\n\t\t\tbuilder.append(CellWidget.of(new VisTextField()).fillX().wrap());\n\t\t\tbuilder.row();\n\n\t\t\t//rest of content won't fit on screen with OneRowTableBuilder\n\t\t\tif (builder instanceof OneRowTableBuilder == false) {\n\t\t\t\tbuilder.append(new VisLabel(\"checkboxes\"));\n\t\t\t\tbuilder.append(rowLayout, getCheckBoxArray(5));\n\t\t\t\tbuilder.row();\n\n\t\t\t\tbuilder.append(CellWidget.of(new Separator()).fillX().wrap());\n\t\t\t\tbuilder.row();\n\n\t\t\t\tbuilder.append(new VisLabel(\"second part\"));\n\t\t\t\tbuilder.row();\n\n\t\t\t\tbuilder.append(new VisLabel(\"sliders\"));\n\t\t\t\tbuilder.append(rowLayout, getSlider(false), getSlider(false), getSlider(false), getSlider(true));\n\t\t\t\tbuilder.row();\n\n\t\t\t\tbuilder.append(rowLayout, getCheckBoxArray(8));\n\t\t\t}\n\n\t\t\tTable table = builder.build();\n\t\t\tadd(table).expand().fill();\n\n\t\t\tpack();\n\t\t\tcenterWindow();\n\t\t}\n\n\t\tprivate VisSlider getSlider (boolean vertical) {\n\t\t\tVisSlider slider = new VisSlider(0, 100, 1, vertical);\n\t\t\tslider.setValue(MathUtils.random(20, 80));\n\t\t\treturn slider;\n\t\t}\n\n\t\tprivate VisCheckBox[] getCheckBoxArray (int count) {\n\t\t\tVisCheckBox[] array = new VisCheckBox[count];\n\n\t\t\tfor (int i = 0; i < count; i++)\n\t\t\t\tarray[i] = new VisCheckBox(\"check\");\n\n\t\t\treturn array;\n\t\t}\n\t}\n\n\tprivate class RowLayout implements ActorLayout {\n\t\tprivate Padding padding;\n\n\t\tpublic RowLayout (Padding padding) {\n\t\t\tthis.padding = padding;\n\t\t}\n\n\t\t@Override\n\t\tpublic Actor convertToActor (Actor... widgets) {\n\t\t\treturn convertToActor(CellWidget.wrap(widgets));\n\t\t}\n\n\t\t@Override\n\t\tpublic Actor convertToActor (CellWidget<?>... widgets) {\n\t\t\tOneRowTableBuilder builder = new OneRowTableBuilder(padding);\n\n\t\t\tfor (CellWidget<?> widget : widgets)\n\t\t\t\tbuilder.append(widget);\n\n\t\t\treturn builder.build();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestBusyBar.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.utils.Align;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.BusyBar;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\npublic class TestBusyBar extends VisWindow {\n\tpublic TestBusyBar () {\n\t\tsuper(\"busybar\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\taddCloseButton();\n\t\taddVisWidgets();\n\n\t\tsetResizable(true);\n\t\tsetSize(320, 170);\n\t\tcenterWindow();\n\t}\n\n\tprivate void addVisWidgets () {\n\t\tBusyBar busyBar = new BusyBar();\n\t\tadd(busyBar).top().space(0).growX().row();\n\t\tadd(new VisLabel(\"Working...\", Align.center)).grow().center();\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestButtonBar.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.ButtonBar;\nimport com.kotcrab.vis.ui.widget.ButtonBar.ButtonType;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\n/** @author Kotcrab */\npublic class TestButtonBar extends VisWindow {\n\n\tpublic TestButtonBar () {\n\t\tsuper(\"buttonbar\");\n\n\t\taddCloseButton();\n\t\tcloseOnEscape();\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\tadd(new VisLabel(\"Windows: \"));\n\t\tadd(createTable(ButtonBar.WINDOWS_ORDER)).expand().fill();\n\t\trow();\n\n\t\tadd(new VisLabel(\"Linux: \"));\n\t\tadd(createTable(ButtonBar.LINUX_ORDER)).expand().fill();\n\t\trow();\n\n\t\tadd(new VisLabel(\"Mac: \"));\n\t\tadd(createTable(ButtonBar.OSX_ORDER)).expand().fill();\n\t\trow();\n\n\t\tpack();\n\t\tsetPosition(300, 245);\n\t}\n\n\tprivate VisTable createTable (String order) {\n\t\tButtonBar buttonBar = new ButtonBar(order);\n\n\t\tChangeListener dummyListener = new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\n\t\t\t}\n\t\t};\n\n\t\tbuttonBar.setButton(ButtonType.LEFT, dummyListener);\n\t\tbuttonBar.setButton(ButtonType.RIGHT, dummyListener);\n\t\tbuttonBar.setButton(ButtonType.HELP, dummyListener);\n\t\tbuttonBar.setButton(ButtonType.NO, dummyListener);\n\t\tbuttonBar.setButton(ButtonType.YES, dummyListener);\n\t\tbuttonBar.setButton(ButtonType.CANCEL, dummyListener);\n\t\tbuttonBar.setButton(ButtonType.BACK, dummyListener);\n\t\tbuttonBar.setButton(ButtonType.NEXT, dummyListener);\n\t\tbuttonBar.setButton(ButtonType.APPLY, dummyListener);\n\t\tbuttonBar.setButton(ButtonType.FINISH, dummyListener);\n\t\tbuttonBar.setButton(ButtonType.OK, dummyListener);\n\t\treturn buttonBar.createTable();\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestCollapsible.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.kotcrab.vis.ui.util.dialog.Dialogs;\nimport com.kotcrab.vis.ui.widget.*;\n\npublic class TestCollapsible extends VisWindow {\n\n\tpublic TestCollapsible () {\n\t\tsuper(\"collapsiblewidget\");\n\n\t\tcolumnDefaults(0).left();\n\n\t\taddVisComponents();\n\n\t\tsetPosition(955, 418);\n\t\tpack();\n\t}\n\n\tprivate void addVisComponents () {\n\t\tVisCheckBox collapseCheckBox = new VisCheckBox(\"show advanced settings\");\n\t\tcollapseCheckBox.setChecked(true);\n\n\t\tVisTable table = new VisTable();\n\t\tfinal CollapsibleWidget collapsibleWidget = new CollapsibleWidget(table);\n\n\t\tVisTable numberTable = new VisTable(true);\n\t\tnumberTable.add(new VisLabel(\"2 + 2 * 2 = \"));\n\t\tnumberTable.add(new VisTextField());\n\n\t\ttable.defaults().left();\n\t\ttable.defaults().padLeft(10);\n\t\ttable.add(new VisCheckBox(\"advanced option #1\")).row();\n\t\ttable.add(new VisCheckBox(\"advanced option #2\")).row();\n\t\ttable.add(numberTable).padTop(3).row();\n\n\t\tcollapseCheckBox.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tcollapsibleWidget.setCollapsed(!collapsibleWidget.isCollapsed());\n\t\t\t}\n\t\t});\n\n\t\tVisTable notAdvancedTable = new VisTable(true);\n\n\t\tVisTextButton dummyButton = new VisTextButton(\"button\");\n\n\t\tnotAdvancedTable.defaults().left();\n\t\tnotAdvancedTable.add(new VisLabel(\"less advanced settings\")).expandX().fillX().row();\n\t\tnotAdvancedTable.add(new VisCheckBox(\"option #1\")).row();\n\t\tnotAdvancedTable.add(new VisCheckBox(\"option #2\")).row();\n\t\tnotAdvancedTable.add(dummyButton);\n\n\t\tadd(collapseCheckBox).row();\n\t\tadd(collapsibleWidget).expandX().fillX().row();\n\t\tadd(new Separator()).padTop(10).fillX().expandX().row();\n\t\tadd(notAdvancedTable).expandX().fillX().padTop(5).row();\n\t\tadd().expand().fill().padBottom(3);\n\n\t\tdummyButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tDialogs.showOKDialog(getStage(), \"message\", \"this button is for showcase only, please don't press\");\n\t\t\t}\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestColorPicker.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Image;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.VisTextButton;\nimport com.kotcrab.vis.ui.widget.VisWindow;\nimport com.kotcrab.vis.ui.widget.color.ColorPicker;\nimport com.kotcrab.vis.ui.widget.color.ColorPickerAdapter;\n\npublic class TestColorPicker extends VisWindow {\n\tprivate static final Drawable white = VisUI.getSkin().getDrawable(\"white\");\n\n\tprivate ColorPicker picker;\n\n\tpublic TestColorPicker () {\n\t\tsuper(\"color picker\");\n\n\t\tfinal Image image = new Image(white);\n\n\t\tpicker = new ColorPicker(\"color picker\", new ColorPickerAdapter() {\n\t\t\t@Override\n\t\t\tpublic void finished (Color newColor) {\n\t\t\t\timage.setColor(newColor);\n\t\t\t}\n\t\t});\n\n\t\tVisTextButton showPickerButton = new VisTextButton(\"show color picker\");\n\t\tshowPickerButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tgetStage().addActor(picker.fadeIn());\n\t\t\t}\n\t\t});\n\n\t\tColor c = new Color(27 / 255.0f, 161 / 255.0f, 226 / 255.0f, 1);\n\t\tpicker.setColor(c);\n\t\timage.setColor(c);\n\n\t\tTableUtils.setSpacingDefaults(this);\n\n\t\tadd(showPickerButton);\n\t\tadd(image).size(32).pad(3);\n\n\t\tpack();\n\t\tsetPosition(948, 148);\n\t}\n\n\t@Override\n\tprotected void close () {\n\t\tsuper.close();\n\t\tpicker.dispose();\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestDialogs.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.util.Validators;\nimport com.kotcrab.vis.ui.util.dialog.ConfirmDialogListener;\nimport com.kotcrab.vis.ui.util.dialog.Dialogs;\nimport com.kotcrab.vis.ui.util.dialog.Dialogs.DetailsDialog;\nimport com.kotcrab.vis.ui.util.dialog.Dialogs.OptionDialogType;\nimport com.kotcrab.vis.ui.util.dialog.InputDialogAdapter;\nimport com.kotcrab.vis.ui.util.dialog.OptionDialogAdapter;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.VisTextButton;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\npublic class TestDialogs extends VisWindow {\n\n\tpublic TestDialogs () {\n\t\tsuper(\"dialogs\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\tVisTextButton showOKMsg = new VisTextButton(\"show ok popup\");\n\t\tVisTextButton showErrorMsg = new VisTextButton(\"show error popup\");\n\t\tVisTextButton showErrorDetailsMsg = new VisTextButton(\"show error with details popup\");\n\t\tVisTextButton showInputDialog = new VisTextButton(\"show input dialog\");\n\t\tVisTextButton showInputDialogIntOnly = new VisTextButton(\"show input dialog (int only)\");\n\t\tVisTextButton showOptionDialog = new VisTextButton(\"show option dialog\");\n\t\tVisTextButton showConfirmDialog = new VisTextButton(\"show dialog with custom buttons\");\n\t\tVisTextButton showDetailsDialog = new VisTextButton(\"show details dialog\");\n\t\tVisTextButton showDetailsExpandedDialog = new VisTextButton(\"show expanded details dialog\");\n\n\t\tVisTable firstRowTable = new VisTable(true);\n\t\tVisTable secondRowTable = new VisTable(true);\n\t\tVisTable thirdRowTable = new VisTable(true);\n\t\tVisTable fourthRowTable = new VisTable(true);\n\n\t\tfirstRowTable.add(showOKMsg);\n\t\tfirstRowTable.add(showErrorMsg);\n\t\tfirstRowTable.add(showErrorDetailsMsg);\n\n\t\tsecondRowTable.add(showInputDialog);\n\t\tsecondRowTable.add(showInputDialogIntOnly);\n\n\t\tthirdRowTable.add(showOptionDialog);\n\t\tthirdRowTable.add(showConfirmDialog);\n\n\t\tfourthRowTable.add(showDetailsDialog);\n\t\tfourthRowTable.add(showDetailsExpandedDialog);\n\n\t\tadd(firstRowTable).row();\n\t\tadd(secondRowTable).row();\n\t\tadd(thirdRowTable).row();\n\t\tadd(fourthRowTable).row();\n\t\tpadBottom(3);\n\n\t\tshowOKMsg.addListener(new ChangeListener() {\n\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tDialogs.showOKDialog(getStage(), \"VisUI demo\", \"Everything is OK!\");\n\t\t\t}\n\t\t});\n\n\t\tshowErrorMsg.addListener(new ChangeListener() {\n\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tDialogs.showErrorDialog(getStage(), \"Error occurred while trying to show error popup\");\n\t\t\t}\n\t\t});\n\n\t\tshowErrorDetailsMsg.addListener(new ChangeListener() {\n\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tDialogs.showErrorDialog(getStage(), \"Error occurred while trying to show error popup\", new IllegalStateException(\n\t\t\t\t\t\t\"Carrots cannot be casted to Potatoes\"));\n\t\t\t}\n\t\t});\n\n\t\tshowInputDialog.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tDialogs.showInputDialog(getStage(), \"enter your name\", \"name: \", new InputDialogAdapter() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void finished (String input) {\n\t\t\t\t\t\tDialogs.showOKDialog(getStage(), \"result\", \"your name is: \" + input);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tshowInputDialogIntOnly.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tDialogs.showInputDialog(getStage(), \"enter int number\", null, Validators.INTEGERS, new InputDialogAdapter() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void finished (String input) {\n\t\t\t\t\t\tDialogs.showOKDialog(getStage(), \"result\", \"you entered: \" + input);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tshowOptionDialog.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tDialogs.showOptionDialog(getStage(), \"option dialog\", \"do you want to do something?\", OptionDialogType.YES_NO_CANCEL, new OptionDialogAdapter() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void yes () {\n\t\t\t\t\t\tDialogs.showOKDialog(getStage(), \"result\", \"pressed: yes\");\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void no () {\n\t\t\t\t\t\tDialogs.showOKDialog(getStage(), \"result\", \"pressed: no\");\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void cancel () {\n\t\t\t\t\t\tDialogs.showOKDialog(getStage(), \"result\", \"pressed: cancel\");\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tshowConfirmDialog.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tfinal int nothing = 1;\n\t\t\t\tfinal int everything = 2;\n\t\t\t\tfinal int something = 3;\n\n\t\t\t\t//confirmdialog may return result of any type, here we are just using ints\n\t\t\t\tDialogs.showConfirmDialog(getStage(), \"confirm dialog\", \"what do you want?\",\n\t\t\t\t\t\tnew String[]{\"nothing\", \"everything\", \"something\"}, new Integer[]{nothing, everything, something},\n\t\t\t\t\t\tnew ConfirmDialogListener<Integer>() {\n\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\tpublic void result (Integer result) {\n\t\t\t\t\t\t\t\tif (result == nothing)\n\t\t\t\t\t\t\t\t\tDialogs.showOKDialog(getStage(), \"result\", \"pressed: nothing\");\n\t\t\t\t\t\t\t\tif (result == everything)\n\t\t\t\t\t\t\t\t\tDialogs.showOKDialog(getStage(), \"result\", \"pressed: everything\");\n\t\t\t\t\t\t\t\tif (result == something)\n\t\t\t\t\t\t\t\t\tDialogs.showOKDialog(getStage(), \"result\", \"pressed: something\");\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tfinal String loremIpsum = \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec pretium, justo sed \" +\n\t\t\t\t\"porttitor pretium, justo est porta risus, sed semper elit turpis in leo. Nam aliquam ac augue id congue. \" +\n\t\t\t\t\"Maecenas luctus, tortor et suscipit dictum, augue lectus semper erat, a gravida velit libero vel magna. \" +\n\t\t\t\t\"Nunc vitae fermentum nisl. Cras magna mauris, porttitor dignissim nunc vitae, viverra congue libero. \" +\n\t\t\t\t\"Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Duis et \" +\n\t\t\t\t\"suscipit neque, dictum vehicula leo. Sed eu ullamcorper justo, quis sagittis urna. Etiam porttitor ligula \" +\n\t\t\t\t\"a eros rutrum fringilla. Quisque quis ligula at neque aliquet malesuada a ac tellus. \";\n\n\t\tshowDetailsDialog.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tDetailsDialog dialog = Dialogs.showDetailsDialog(getStage(), \"this is a short description text\", \"details dialog test\", loremIpsum);\n\t\t\t\tdialog.setCopyDetailsButtonVisible(false);\n\t\t\t\tdialog.setWrapDetails(true);\n\t\t\t}\n\t\t});\n\n\t\tshowDetailsExpandedDialog.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tDetailsDialog dialog = Dialogs.showDetailsDialog(getStage(), \"this is a short description text\", \"details dialog test\", loremIpsum, true);\n\t\t\t\tdialog.setCopyDetailsButtonVisible(false);\n\t\t\t\tdialog.setWrapDetails(true);\n\t\t\t}\n\t\t});\n\n\t\tpack();\n\t\tsetPosition(25, 106);\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestFileChooser.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.files.FileHandle;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.VisCheckBox;\nimport com.kotcrab.vis.ui.widget.VisTextButton;\nimport com.kotcrab.vis.ui.widget.VisWindow;\nimport com.kotcrab.vis.ui.widget.file.FileChooser;\nimport com.kotcrab.vis.ui.widget.file.FileChooser.Mode;\nimport com.kotcrab.vis.ui.widget.file.FileTypeFilter;\nimport com.kotcrab.vis.ui.widget.file.StreamingFileChooserListener;\n\npublic class TestFileChooser extends VisWindow {\n\n\tpublic TestFileChooser () {\n\t\tsuper(\"filechooser\");\n\n\t\tFileChooser.setDefaultPrefsName(\"com.kotcrab.vis.ui.test.manual\");\n\t\tFileChooser.setSaveLastDirectory(true);\n\t\tfinal FileChooser chooser = new FileChooser(Mode.OPEN);\n\t\tchooser.setSelectionMode(FileChooser.SelectionMode.FILES_AND_DIRECTORIES);\n\t\tchooser.setMultiSelectionEnabled(true);\n\t\tchooser.setFavoriteFolderButtonVisible(true);\n\t\tchooser.setShowSelectionCheckboxes(true);\n//\t\tchooser.setIconProvider(new ImgScalrFileChooserIconProvider(chooser));\n\t\tchooser.setIconProvider(new HighResFileChooserIconProvider(chooser));\n\t\tchooser.setListener(new StreamingFileChooserListener() {\n\t\t\t@Override\n\t\t\tpublic void selected (FileHandle file) {\n\t\t\t\tSystem.out.println(file.path());\n\t\t\t}\n\t\t});\n\t\tfinal FileTypeFilter typeFilter = new FileTypeFilter(true);\n\t\ttypeFilter.addRule(\"Image files (*.png, *.jpg, *.gif)\", \"png\", \"jpg\", \"gif\");\n\t\ttypeFilter.addRule(\"Text files (*.txt)\", \"txt\");\n\t\ttypeFilter.addRule(\"Audio files (*.mp3, *.wav, *.ogg)\", \"mp3\", \"wav\", \"ogg\");\n\n\t\tVisTextButton open = new VisTextButton(\"mode open\");\n\t\tVisTextButton save = new VisTextButton(\"mode save\");\n\t\tfinal VisCheckBox useTypeFilter = new VisCheckBox(\"use type filter\");\n\t\tfinal VisCheckBox multiSelect = new VisCheckBox(\"multi-selection\");\n\t\tmultiSelect.setChecked(true);\n\n\t\tTableUtils.setSpacingDefaults(this);\n\n\t\topen.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tchooser.setMode(Mode.OPEN);\n\t\t\t\tgetStage().addActor(chooser.fadeIn());\n\t\t\t}\n\t\t});\n\t\tsave.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tchooser.setMode(Mode.SAVE);\n\t\t\t\tgetStage().addActor(chooser.fadeIn());\n\t\t\t}\n\t\t});\n\t\tuseTypeFilter.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tif (useTypeFilter.isChecked()) {\n\t\t\t\t\tchooser.setFileTypeFilter(typeFilter);\n\t\t\t\t} else {\n\t\t\t\t\tchooser.setFileTypeFilter(null);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tmultiSelect.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tchooser.setMultiSelectionEnabled(multiSelect.isChecked());\n\t\t\t}\n\t\t});\n\n\t\tadd(open);\n\t\tadd(save).row();\n\t\tadd(useTypeFilter).colspan(2).left().row();\n\t\tadd(multiSelect).colspan(2).left().row();\n\n\t\tpack();\n\t\tsetPosition(950, 20);\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestFloatingGroup.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.ApplicationAdapter;\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.graphics.GL20;\nimport com.badlogic.gdx.scenes.scene2d.Stage;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.utils.viewport.ScreenViewport;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.layout.FloatingGroup;\n\nclass TestFloatingGroup extends ApplicationAdapter {\n\tprivate Stage stage;\n\n\t@Override\n\tpublic void create () {\n\t\tVisUI.load();\n\n\t\tstage = new Stage(new ScreenViewport());\n\t\tfinal Table root = new Table();\n\t\troot.setFillParent(true);\n\t\tstage.addActor(root);\n\n\t\tTestWindow window = new TestWindow();\n\t\tTestCollapsible collapsible = new TestCollapsible();\n\t\twindow.setKeepWithinParent(true);\n\t\twindow.setPosition(110, 110);\n\t\tcollapsible.setKeepWithinParent(true);\n\t\tcollapsible.setPosition(200, 200);\n\n\t\tFloatingGroup floatingGroup = new FloatingGroup(1000, 600);\n\t\tfloatingGroup.addActor(window);\n\t\tfloatingGroup.addActor(collapsible);\n\n\t\troot.debugAll();\n\t\troot.left().bottom();\n\t\troot.add(floatingGroup).padLeft(100).padBottom(100);\n\n\t\tGdx.input.setInputProcessor(stage);\n\t}\n\n\t@Override\n\tpublic void resize (int width, int height) {\n\t\tif (width == 0 && height == 0) return;\n\t\tstage.getViewport().update(width, height, true);\n\t}\n\n\t@Override\n\tpublic void render () {\n\t\tGdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);\n\t\tstage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));\n\t\tstage.draw();\n\t}\n\n\t@Override\n\tpublic void dispose () {\n\t\tVisUI.dispose();\n\t\tstage.dispose();\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestFlowGroup.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.kotcrab.vis.ui.layout.FlowGroup;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisScrollPane;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\n/** @author Kotcrab */\npublic class TestFlowGroup extends VisWindow {\n\tpublic TestFlowGroup () {\n\t\tsuper(\"flow groups\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\tsetResizable(true);\n\t\taddCloseButton();\n\t\tcloseOnEscape();\n\n\t\tFlowGroup group = new FlowGroup(true, 2);\n\n\t\tString lorem = \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi luctus magna sit amet tellus egestas tincidunt. \" +\n\t\t\t\t\"Morbi tempus eleifend dictum. Nunc ex nisl, dignissim eget gravida vel, rutrum a nibh. Fusce congue odio ac elit \" +\n\t\t\t\t\"rhoncus rutrum. Donec nec lectus leo. Phasellus et consectetur ante. Cras vel consectetur mauris, sed semper lectus. \";\n\t\tString[] parts = lorem.split(\" \");\n\t\tfor (String part : parts) {\n\t\t\tgroup.addActor(new VisLabel(part));\n\t\t}\n\n//\t\tgroup.addActor(new VisLabel(\"Lorem ipsum\"));\n//\t\tgroup.addActor(new VisLabel(\"dolor sit\"));\n//\t\tgroup.addActor(new VisLabel(\"amet\"));\n//\t\tgroup.addActor(new VisLabel(\"a\\nb\\nc\"));\n//\t\tgroup.addActor(new VisLabel(\"Lorem ipsum\"));\n//\t\tgroup.addActor(new VisLabel(\"dolor sit\"));\n//\t\tgroup.addActor(new VisLabel(\"amet\"));\n//\t\tgroup.addActor(new VisLabel(\"a\\nb\\nc\"));\n//\t\tgroup.addActor(new VisLabel(\"Lorem ipsum\"));\n//\t\tgroup.addActor(new VisLabel(\"dolor sit\"));\n//\t\tgroup.addActor(new VisLabel(\"amet\"));\n//\t\tgroup.addActor(new VisLabel(\"a\\nb\\nc\"));\n\n\t\tVisScrollPane scrollPane = new VisScrollPane(group);\n\t\tscrollPane.setFadeScrollBars(false);\n\t\tscrollPane.setFlickScroll(false);\n\t\tscrollPane.setOverscroll(false, false);\n\t\tscrollPane.setScrollingDisabled(!group.isVertical(), group.isVertical());\n\t\tadd(scrollPane).grow();\n\n\t\tsetSize(300, 150);\n\t\tcenterWindow();\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestFormValidator.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.util.dialog.Dialogs;\nimport com.kotcrab.vis.ui.util.form.SimpleFormValidator;\nimport com.kotcrab.vis.ui.widget.*;\n\npublic class TestFormValidator extends VisWindow {\n\n\tpublic TestFormValidator () {\n\t\tsuper(\"form validator\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tdefaults().padRight(1);\n\t\tdefaults().padLeft(1);\n\t\tcolumnDefaults(0).left();\n\n\t\tVisTextButton cancelButton = new VisTextButton(\"cancel\");\n\t\tVisTextButton acceptButton = new VisTextButton(\"accept\");\n\n\t\tVisValidatableTextField firstNameField = new VisValidatableTextField();\n\t\tVisValidatableTextField lastNameField = new VisValidatableTextField();\n\t\tVisValidatableTextField age = new VisValidatableTextField();\n\t\tVisCheckBox termsCheckbox = new VisCheckBox(\"accept terms\");\n\n\t\tVisLabel errorLabel = new VisLabel();\n\t\terrorLabel.setColor(Color.RED);\n\n\t\tVisTable buttonTable = new VisTable(true);\n\t\tbuttonTable.add(errorLabel).expand().fill();\n\t\tbuttonTable.add(cancelButton);\n\t\tbuttonTable.add(acceptButton);\n\n\t\tadd(new VisLabel(\"first name: \"));\n\t\tadd(firstNameField).expand().fill();\n\t\trow();\n\t\tadd(new VisLabel(\"last name: \"));\n\t\tadd(lastNameField).expand().fill();\n\t\trow();\n\t\tadd(new VisLabel(\"age: \"));\n\t\tadd(age).expand().fill();\n\t\trow();\n\t\tadd(termsCheckbox).colspan(2);\n\t\trow();\n\t\tadd(buttonTable).fill().expand().colspan(2).padBottom(3);\n\n\t\tSimpleFormValidator validator; //for GWT compatibility\n\t\tvalidator = new SimpleFormValidator(acceptButton, errorLabel, \"smooth\");\n\t\tvalidator.setSuccessMessage(\"all good!\");\n\t\tvalidator.notEmpty(firstNameField, \"first name cannot be empty\");\n\t\tvalidator.notEmpty(lastNameField, \"last name cannot be empty\");\n\t\tvalidator.notEmpty(age, \"age cannot be empty\");\n\t\tvalidator.integerNumber(age, \"age must be a number\");\n\t\tvalidator.valueGreaterThan(age, \"you must be at least 18 years old\", 18, true);\n\t\tvalidator.checked(termsCheckbox, \"you must accept terms\");\n\n\t\tacceptButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tDialogs.showOKDialog(getStage(), \"message\", \"you made it!\");\n\t\t\t}\n\t\t});\n\n\t\tcancelButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tDialogs.showOKDialog(getStage(), \"message\", \"you can't escape this!\");\n\t\t\t}\n\t\t});\n\n\t\tpack();\n\t\tsetSize(getWidth() + 60, getHeight());\n\t\tsetPosition(548, 85);\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestGenerateDisabledImage.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.VisImageButton;\nimport com.kotcrab.vis.ui.widget.VisImageTextButton;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\npublic class TestGenerateDisabledImage extends VisWindow {\n\tpublic TestGenerateDisabledImage () {\n\t\tsuper(\"generate disabled image\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\taddVisWidgets();\n\n\t\tsetSize(300, 150);\n\t\tcenterWindow();\n\t}\n\n\tprivate void addVisWidgets () {\n\t\tDrawable icon = VisUI.getSkin().getDrawable(\"icon-folder\");\n\t\tVisImageButton normal = new VisImageButton(icon);\n\t\tVisImageButton disabled = new VisImageButton(icon);\n\t\tdisabled.setGenerateDisabledImage(true);\n\t\tdisabled.setDisabled(true);\n\t\tadd(new VisLabel(\"VisImageButton normal\"));\n\t\tadd(normal).row();\n\t\tadd(new VisLabel(\"VisImageButton disabled\"));\n\t\tadd(disabled).row();\n\n\t\tVisImageTextButton normalText = new VisImageTextButton(\"text\", icon);\n\t\tVisImageTextButton disabledText = new VisImageTextButton(\"text\", icon);\n\t\tdisabledText.setGenerateDisabledImage(true);\n\t\tdisabledText.setDisabled(true);\n\t\tadd(new VisLabel(\"VisImageTextButton normal\"));\n\t\tadd(normalText).row();\n\t\tadd(new VisLabel(\"VisImageTextButton disabled\"));\n\t\tadd(disabledText).padBottom(3f).row();\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestHighlightTextArea.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.util.highlight.Highlighter;\nimport com.kotcrab.vis.ui.widget.HighlightTextArea;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\npublic class TestHighlightTextArea extends VisWindow {\n\n\tpublic TestHighlightTextArea () {\n\t\tsuper(\"highlight textarea\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\tsetResizable(true);\n\t\taddCloseButton();\n\t\tcloseOnEscape();\n\t\taddVisWidgets();\n\n\t\tsetSize(280, 380);\n\t\tcenterWindow();\n\t}\n\n\tprivate void addVisWidgets () {\n\t\tHighlightTextArea textArea = new HighlightTextArea(\"private class Foo {\\n\" +\n\t\t\t\t\"  int foo;\\n\" +\n\t\t\t\t\"  float bar;\\n\" +\n\t\t\t\t\"  String foobar;\\n\" +\n\t\t\t\t\"}\");\n\t\tHighlighter highlighter = new Highlighter();\n\t\t//it is much more reliable to use regex for keyword detection\n\t\thighlighter.regex(Color.valueOf(\"66CCB3\"), \"\\\\b(class|private|protected|public|if|else|void|for|while|continue|break)\\\\b\");\n\t\thighlighter.regex(Color.valueOf(\"BED6FF\"), \"\\\\b(int|float|boolean|short|long|char)\\\\b\");\n\t\thighlighter.regex(Color.valueOf(\"EFC090\"), \"\\\\b(foo|bar)\\\\b\");\n\t\thighlighter.regex(Color.valueOf(\"75715E\"), \"/\\\\*(?:.|[\\\\n\\\\r])*?\\\\*/\"); //block comments (/* comment */)\n\t\ttextArea.setHighlighter(highlighter);\n\t\tadd(textArea.createCompatibleScrollPane()).grow();\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestIssue131.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.kotcrab.vis.ui.util.FloatDigitsOnlyFilter;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.LinkLabel;\nimport com.kotcrab.vis.ui.widget.VisTextField;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\n/** @author Kotcrab */\npublic class TestIssue131 extends VisWindow {\n\tpublic TestIssue131 () {\n\t\tsuper(\"issue #131\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\tVisTextField field1 = new VisTextField(\"0.1234\");\n\t\tVisTextField field2 = new VisTextField(\"4.5678\");\n\t\tfield1.setTextFieldFilter(new FloatDigitsOnlyFilter(true));\n\t\tfield2.setTextFieldFilter(new FloatDigitsOnlyFilter(true));\n\n\t\tadd(new LinkLabel(\"issue #131 - decimal point lost\", \"https://github.com/kotcrab/vis-ui/issues/131\")).colspan(2).row();\n\t\tadd(field1);\n\t\tadd(field2);\n\n\t\tsetResizable(true);\n\t\tsetModal(false);\n\t\taddCloseButton();\n\t\tcloseOnEscape();\n\t\tpack();\n\t\tcenterWindow();\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestIssue326.java",
    "content": "package com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.kotcrab.vis.ui.widget.LinkLabel;\nimport com.kotcrab.vis.ui.widget.VisTextField;\nimport com.kotcrab.vis.ui.widget.VisWindow;\nimport com.kotcrab.vis.ui.widget.spinner.IntSpinnerModel;\nimport com.kotcrab.vis.ui.widget.spinner.Spinner;\n\npublic class TestIssue326 extends VisWindow {\n\tpublic TestIssue326 () {\n\t\tsuper(\"issue #326\");\n\n\t\tfinal VisTextField passwordTextField = new VisTextField(\"password\");\n\n\t\tfinal IntSpinnerModel intModel = new IntSpinnerModel(10, -5, 20, 2);\n\t\tSpinner intSpinner = new Spinner(\"int\", intModel);\n\t\tintSpinner.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tpasswordTextField.setDisabled(true);\n\t\t\t}\n\t\t});\n\n\t\tadd(new LinkLabel(\"issue #326 - FocusManager crash\", \"https://github.com/kotcrab/vis-ui/issues/326\")).colspan(2).row();\n\t\tadd(passwordTextField);\n\t\trow();\n\t\tadd(intSpinner);\n\n\t\tsetResizable(false);\n\t\tsetModal(false);\n\t\taddCloseButton();\n\t\tcloseOnEscape();\n\t\tpack();\n\t\tcenterWindow();\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestLauncher.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.Application.ApplicationType;\nimport com.badlogic.gdx.ApplicationAdapter;\nimport com.badlogic.gdx.Gdx;\nimport com.badlogic.gdx.Input.Keys;\nimport com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;\nimport com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;\nimport com.badlogic.gdx.graphics.GL20;\nimport com.badlogic.gdx.scenes.scene2d.*;\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.utils.viewport.ScreenViewport;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.VisUI.SkinScale;\nimport com.kotcrab.vis.ui.test.TestImageTextButtonOrientation;\nimport com.kotcrab.vis.ui.util.dialog.Dialogs;\nimport com.kotcrab.vis.ui.widget.Menu;\nimport com.kotcrab.vis.ui.widget.MenuBar;\nimport com.kotcrab.vis.ui.widget.MenuItem;\nimport com.kotcrab.vis.ui.widget.PopupMenu;\n\npublic class TestLauncher {\n\n\tpublic static void main (String[] args) {\n\t\tLwjgl3ApplicationConfiguration c = new Lwjgl3ApplicationConfiguration();\n\t\tc.setTitle(\"VisUI test application\");\n\t\tc.setWindowedMode(1280, 720);\n\t\tnew Lwjgl3Application(new TestApplication(), c);\n\t}\n\n}\n\nclass TestApplication extends ApplicationAdapter {\n\tpublic static final boolean USE_VIS_WIDGETS = true;\n\n\tprivate Stage stage;\n\tprivate MenuBar menuBar;\n\n\t@Override\n\tpublic void create () {\n\t\tVisUI.load(SkinScale.X1);\n\n\t\tstage = new Stage(new ScreenViewport());\n\t\tfinal Table root = new Table();\n\t\troot.setFillParent(true);\n\t\tstage.addActor(root);\n\n\t\tGdx.input.setInputProcessor(stage);\n\n\t\tmenuBar = new MenuBar();\n\t\tmenuBar.setMenuListener(new MenuBar.MenuBarListener() {\n\t\t\t@Override\n\t\t\tpublic void menuOpened (Menu menu) {\n\t\t\t\tSystem.out.println(\"Opened menu: \" + menu.getTitle());\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void menuClosed (Menu menu) {\n\t\t\t\tSystem.out.println(\"Closed menu: \" + menu.getTitle());\n\t\t\t}\n\t\t});\n\t\troot.add(menuBar.getTable()).expandX().fillX().row();\n\t\troot.add().expand().fill();\n\n\t\tcreateMenus();\n\n\t\tstage.addActor(new TestCollapsible());\n\t\tstage.addActor(new TestColorPicker());\n\t\tif (Gdx.app.getType() == ApplicationType.Desktop) stage.addActor(new TestFileChooser());\n\t\tstage.addActor(new TestWindow());\n\t\tstage.addActor(new TestSplitPane());\n\t\tstage.addActor(new TestTextAreaAndScroll());\n\t\tstage.addActor(new TestTree());\n\t\tstage.addActor(new TestVertical());\n\t\tstage.addActor(new TestFormValidator());\n\t\tstage.addActor(new TestDialogs());\n\t\tstage.addActor(new TestValidator());\n\t\tstage.addActor(new TestBuilders());\n//\t\tstage.addActor(new TestTabbedPane());\n//\t\tstage.addActor(new TestFlowGroup());\n//\t\tstage.addActor(new TestButtonBar());\n//\t\tstage.addActor(new TestListView());\n//\t\tstage.addActor(new TestToasts(stage));\n//\t\tstage.addActor(new TestHighlightTextArea());\n//\t\tstage.addActor(new TestBusyBar());\n//\t\tstage.addActor(new TestMultiSplitPane());\n\n\t\tstage.addListener(new InputListener() {\n\t\t\tboolean debug = false;\n\n\t\t\t@Override\n\t\t\tpublic boolean keyDown (InputEvent event, int keycode) {\n\t\t\t\tif (keycode == Keys.F12) {\n\t\t\t\t\tdebug = !debug;\n\t\t\t\t\troot.setDebug(debug, true);\n\t\t\t\t\tfor (Actor actor : stage.getActors()) {\n\t\t\t\t\t\tif (actor instanceof Group) {\n\t\t\t\t\t\t\tGroup group = (Group) actor;\n\t\t\t\t\t\t\tgroup.setDebug(debug, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate void createMenus () {\n\t\tMenu fileMenu = new Menu(\"File\");\n\t\tMenu editMenu = new Menu(\"Edit\");\n\t\tMenu windowMenu = new Menu(\"Window\");\n\t\tMenu helpMenu = new Menu(\"Help\");\n\n\t\tfileMenu.addItem(createTestsMenu());\n\t\tfileMenu.addItem(new MenuItem(\"menuitem #1\"));\n\t\tfileMenu.addItem(new MenuItem(\"menuitem #2\").setShortcut(\"f1\"));\n\t\tfileMenu.addItem(new MenuItem(\"menuitem #3\").setShortcut(\"f2\"));\n\t\tfileMenu.addItem(new MenuItem(\"menuitem #4\").setShortcut(\"alt + f4\"));\n\n\t\tMenuItem subMenuItem = new MenuItem(\"submenu #1\");\n\t\tsubMenuItem.setShortcut(\"alt + insert\");\n\t\tsubMenuItem.setSubMenu(createSubMenu());\n\t\tfileMenu.addItem(subMenuItem);\n\n\t\tMenuItem subMenuItem2 = new MenuItem(\"submenu #2\");\n\t\tsubMenuItem2.setSubMenu(createSubMenu());\n\t\tfileMenu.addItem(subMenuItem2);\n\n\t\tMenuItem subMenuItem3 = new MenuItem(\"submenu disabled\");\n\t\tsubMenuItem3.setDisabled(true);\n\t\tsubMenuItem3.setSubMenu(createSubMenu());\n\t\tfileMenu.addItem(subMenuItem3);\n\n\t\t// ---\n\n\t\teditMenu.addItem(new MenuItem(\"menuitem #5\"));\n\t\teditMenu.addItem(new MenuItem(\"menuitem #6\"));\n\t\teditMenu.addSeparator();\n\t\teditMenu.addItem(new MenuItem(\"menuitem #7\"));\n\t\teditMenu.addItem(new MenuItem(\"menuitem #8\"));\n\t\teditMenu.addItem(createDoubleNestedMenu());\n\n\t\tMenuItem disabledItem = new MenuItem(\"disabled menuitem\");\n\t\tdisabledItem.setDisabled(true);\n\t\tMenuItem disabledItem2 = new MenuItem(\"disabled menuitem shortcut\").setShortcut(\"alt + f4\");\n\t\tdisabledItem2.setDisabled(true);\n\n\t\teditMenu.addItem(disabledItem);\n\t\teditMenu.addItem(disabledItem2);\n\n\t\twindowMenu.addItem(new MenuItem(\"menuitem #9\"));\n\t\twindowMenu.addItem(new MenuItem(\"menuitem #10\"));\n\t\twindowMenu.addItem(new MenuItem(\"menuitem #11\"));\n\t\twindowMenu.addSeparator();\n\t\twindowMenu.addItem(new MenuItem(\"menuitem #12\"));\n\n\t\thelpMenu.addItem(new MenuItem(\"about\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tDialogs.showOKDialog(stage, \"about\", \"visui test application\");\n\t\t\t}\n\t\t}));\n\n\t\tmenuBar.addMenu(fileMenu);\n\t\tmenuBar.addMenu(editMenu);\n\t\tmenuBar.addMenu(windowMenu);\n\t\tmenuBar.addMenu(helpMenu);\n\t}\n\n\tprivate MenuItem createDoubleNestedMenu () {\n\t\tMenuItem doubleNestedMenuItem = new MenuItem(\"submenu nested x2\");\n\t\tdoubleNestedMenuItem.setSubMenu(createSubMenu());\n\n\t\tPopupMenu nestedMenu = new PopupMenu();\n\t\tnestedMenu.addItem(doubleNestedMenuItem);\n\t\tnestedMenu.addItem(new MenuItem(\"single nested\"));\n\n\t\tMenuItem menuItem = new MenuItem(\"submenu nested\");\n\t\tmenuItem.setSubMenu(nestedMenu);\n\t\treturn menuItem;\n\t}\n\n\tprivate MenuItem createTestsMenu () {\n\t\tMenuItem item = new MenuItem(\"start test\");\n\n\t\tPopupMenu menu = new PopupMenu();\n\t\tmenu.addItem(new MenuItem(\"tabbed pane\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tstage.addActor(new TestTabbedPane(false));\n\t\t\t}\n\t\t}));\n\t\tmenu.addItem(new MenuItem(\"tabbed pane (vertical)\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tstage.addActor(new TestTabbedPane(true));\n\t\t\t}\n\t\t}));\n\t\tmenu.addItem(new MenuItem(\"flow groups\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tstage.addActor(new TestFlowGroup());\n\t\t\t}\n\t\t}));\n\t\tmenu.addItem(new MenuItem(\"button bar\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tstage.addActor(new TestButtonBar());\n\t\t\t}\n\t\t}));\n\t\tmenu.addItem(new MenuItem(\"list view\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tstage.addActor(new TestListView());\n\t\t\t}\n\t\t}));\n\t\tmenu.addItem(new MenuItem(\"toasts\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tstage.addActor(new TestToasts(stage));\n\t\t\t}\n\t\t}));\n\t\tmenu.addItem(new MenuItem(\"highlight textarea\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tstage.addActor(new TestHighlightTextArea());\n\t\t\t}\n\t\t}));\n\t\tmenu.addItem(new MenuItem(\"busybar\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tstage.addActor(new TestBusyBar());\n\t\t\t}\n\t\t}));\n\t\tmenu.addItem(new MenuItem(\"multisplitpane\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tstage.addActor(new TestMultiSplitPane());\n\t\t\t}\n\t\t}));\n\t\tmenu.addItem(new MenuItem(\"generate disabled image\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tstage.addActor(new TestGenerateDisabledImage());\n\t\t\t}\n\t\t}));\n\t\tmenu.addItem(new MenuItem(\"imagetextbutton orientation\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tstage.addActor(new TestImageTextButtonOrientation());\n\t\t\t}\n\t\t}));\n\t\tmenu.addSeparator();\n\t\tmenu.addItem(new MenuItem(\"test issue #131\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tstage.addActor(new TestIssue131());\n\t\t\t}\n\t\t}));\n\t\tmenu.addItem(new MenuItem(\"test issue #326\", new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tstage.addActor(new TestIssue326());\n\t\t\t}\n\t\t}));\n\n\t\titem.setSubMenu(menu);\n\t\treturn item;\n\t}\n\n\tprivate PopupMenu createSubMenu () {\n\t\tPopupMenu menu = new PopupMenu();\n\t\tmenu.addItem(new MenuItem(\"submenuitem #1\"));\n\t\tmenu.addItem(new MenuItem(\"submenuitem #2\"));\n\t\tmenu.addSeparator();\n\t\tmenu.addItem(new MenuItem(\"submenuitem #3\"));\n\t\tmenu.addItem(new MenuItem(\"submenuitem #4\"));\n\t\treturn menu;\n\t}\n\n\t@Override\n\tpublic void resize (int width, int height) {\n\t\tif (width == 0 && height == 0) return; //see https://github.com/libgdx/libgdx/issues/3673#issuecomment-177606278\n\t\tstage.getViewport().update(width, height, true);\n\t\tPopupMenu.removeEveryMenu(stage);\n\t\tWindowResizeEvent resizeEvent = new WindowResizeEvent();\n\t\tfor (Actor actor : stage.getActors()) {\n\t\t\tactor.fire(resizeEvent);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void render () {\n\t\tGdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);\n\t\tstage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));\n\t\tstage.draw();\n\t}\n\n\t@Override\n\tpublic void dispose () {\n\t\tVisUI.dispose();\n\t\tstage.dispose();\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestListView.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.graphics.Color;\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.scenes.scene2d.utils.Drawable;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.util.adapter.AbstractListAdapter;\nimport com.kotcrab.vis.ui.util.adapter.ArrayAdapter;\nimport com.kotcrab.vis.ui.util.adapter.ListSelectionAdapter;\nimport com.kotcrab.vis.ui.util.form.SimpleFormValidator;\nimport com.kotcrab.vis.ui.widget.*;\nimport com.kotcrab.vis.ui.widget.ListView.ItemClickListener;\nimport com.kotcrab.vis.ui.widget.ListView.UpdatePolicy;\n\nimport java.util.Comparator;\n\n/** @author Kotcrab */\npublic class TestListView extends VisWindow {\n\tpublic TestListView () {\n\t\tsuper(\"listview\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\taddCloseButton();\n\t\tcloseOnEscape();\n\n\t\tArray<Model> array = new Array<Model>();\n\t\tfor (int i = 1; i <= 3; i++) {\n\t\t\tarray.add(new Model(\"Windows\" + i, VisUI.getSkin().getColor(\"vis-red\")));\n\t\t\tarray.add(new Model(\"Linux\" + i, Color.GREEN));\n\t\t\tarray.add(new Model(\"OSX\" + i, Color.WHITE));\n\t\t}\n\n\t\tfinal TestAdapter adapter = new TestAdapter(array);\n\t\tListView<Model> view = new ListView<Model>(adapter);\n\t\tview.setUpdatePolicy(UpdatePolicy.ON_DRAW);\n\n\t\tVisTable footerTable = new VisTable();\n\t\tfooterTable.addSeparator();\n\t\tfooterTable.add(\"Table Footer\");\n\t\tview.setFooter(footerTable);\n\n\t\tfinal VisValidatableTextField nameField = new VisValidatableTextField();\n\t\tVisTextButton addButton = new VisTextButton(\"Add\");\n\n\t\tSimpleFormValidator validator = new SimpleFormValidator(addButton);\n\t\tvalidator.notEmpty(nameField, \"\");\n\n\t\tadd(new VisLabel(\"New Name:\"));\n\t\tadd(nameField);\n\t\tadd(addButton);\n\t\trow();\n\t\tadd(view.getMainTable()).colspan(3).grow();\n\n\t\taddButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\t//by changing array using adapter view will be invalidated automatically\n\t\t\t\tadapter.add(new Model(nameField.getText(), Color.GRAY));\n\t\t\t\tnameField.setText(\"\");\n\t\t\t}\n\t\t});\n\n\t\tadapter.setSelectionMode(AbstractListAdapter.SelectionMode.SINGLE);\n\t\tview.setItemClickListener(new ItemClickListener<Model>() {\n\t\t\t@Override\n\t\t\tpublic void clicked (Model item) {\n\t\t\t\tSystem.out.println(\"Clicked: \" + item.name);\n\t\t\t}\n\t\t});\n\t\tadapter.getSelectionManager().setListener(new ListSelectionAdapter<Model, VisTable>() {\n\t\t\t@Override\n\t\t\tpublic void selected (Model item, VisTable view) {\n\t\t\t\tSystem.out.println(\"ListSelection Selected: \" + item.name);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void deselected (Model item, VisTable view) {\n\t\t\t\tSystem.out.println(\"ListSelection Deselected: \" + item.name);\n\t\t\t}\n\t\t});\n\n\t\tsetSize(300, 300);\n\t\tsetPosition(458, 245);\n\t}\n\n\tprivate static class Model {\n\t\tpublic String name;\n\t\tpublic Color color;\n\n\t\tpublic Model (String name, Color color) {\n\t\t\tthis.name = name;\n\t\t\tthis.color = color;\n\t\t}\n\t}\n\n\tprivate static class TestAdapter extends ArrayAdapter<Model, VisTable> {\n\t\tprivate final Drawable bg = VisUI.getSkin().getDrawable(\"window-bg\");\n\t\tprivate final Drawable selection = VisUI.getSkin().getDrawable(\"list-selection\");\n\n\t\tpublic TestAdapter (Array<Model> array) {\n\t\t\tsuper(array);\n\t\t\tsetSelectionMode(SelectionMode.SINGLE);\n\n\t\t\tsetItemsSorter(new Comparator<Model>() {\n\t\t\t\t@Override\n\t\t\t\tpublic int compare (Model o1, Model o2) {\n\t\t\t\t\treturn o1.name.toLowerCase().compareTo(o2.name.toLowerCase());\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t@Override\n\t\tprotected VisTable createView (Model item) {\n\t\t\tVisLabel label = new VisLabel(item.name);\n\t\t\tlabel.setColor(item.color);\n\n\t\t\tVisTable table = new VisTable();\n\t\t\ttable.left();\n\t\t\ttable.add(label);\n\t\t\treturn table;\n\t\t}\n\n\t\t@Override\n\t\tprotected void updateView (VisTable view, Model item) {\n\t\t\tsuper.updateView(view, item);\n\t\t}\n\n\t\t@Override\n\t\tprotected void selectView (VisTable view) {\n\t\t\tview.setBackground(selection);\n\t\t}\n\n\t\t@Override\n\t\tprotected void deselectView (VisTable view) {\n\t\t\tview.setBackground(bg);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestMultiSplitPane.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.MultiSplitPane;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\npublic class TestMultiSplitPane extends VisWindow {\n\tprivate boolean vertical = false;\n\n\tpublic TestMultiSplitPane () {\n\t\tsuper(\"multisplitpane\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\taddVisWidgets();\n\n\t\tsetSize(300, 150);\n\t\tcenterWindow();\n\t}\n\n\tprivate void addVisWidgets () {\n\t\tVisLabel label = new VisLabel(\"Label #1\");\n\t\tVisLabel label2 = new VisLabel(\"Label #2\");\n\t\tVisLabel label3 = new VisLabel(\"Label #3\");\n\n\t\tMultiSplitPane splitPane = new MultiSplitPane(vertical);\n\t\tsplitPane.setWidgets(label, label2, label3);\n\t\tadd(splitPane).fill().expand();\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestSplitPane.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Label;\nimport com.badlogic.gdx.scenes.scene2d.ui.Skin;\nimport com.badlogic.gdx.scenes.scene2d.ui.SplitPane;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisSplitPane;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\npublic class TestSplitPane extends VisWindow {\n\tprivate boolean vertical = false;\n\n\tpublic TestSplitPane () {\n\t\tsuper(\"splitpane\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\tif (TestApplication.USE_VIS_WIDGETS)\n\t\t\taddVisWidgets();\n\t\telse\n\t\t\taddNormalWidgets();\n\n\t\tsetSize(300, 150);\n\t\tsetPosition(958, 245);\n\t}\n\n\tprivate void addVisWidgets () {\n\t\tVisLabel label = new VisLabel(\"Lorem \\nipsum \\ndolor \\nsit \\namet\");\n\t\tVisLabel label2 = new VisLabel(\"Consectetur \\nadipiscing \\nelit\");\n\t\tVisTable table = new VisTable(true);\n\t\tVisTable table2 = new VisTable(true);\n\n\t\ttable.add(label);\n\t\ttable2.add(label2);\n\n\t\tVisSplitPane splitPane = new VisSplitPane(table, table2, vertical);\n\t\tadd(splitPane).fill().expand();\n\t}\n\n\tprivate void addNormalWidgets () {\n\t\tSkin skin = VisUI.getSkin();\n\t\tLabel label = new Label(\"Lorem \\nipsum \\ndolor \\nsit \\namet\", skin);\n\t\tLabel label2 = new Label(\"Consectetur \\nadipiscing \\nelit\", skin);\n\n\t\tVisTable table = new VisTable(true);\n\t\tVisTable table2 = new VisTable(true);\n\n\t\ttable.add(label);\n\t\ttable2.add(label2);\n\n\t\tSplitPane splitPane = new SplitPane(table, table2, false, skin);\n\t\tadd(splitPane).fill().expand();\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestTabbedPane.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Table;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.VisWindow;\nimport com.kotcrab.vis.ui.widget.tabbedpane.Tab;\nimport com.kotcrab.vis.ui.widget.tabbedpane.TabbedPane;\nimport com.kotcrab.vis.ui.widget.tabbedpane.TabbedPane.TabbedPaneStyle;\nimport com.kotcrab.vis.ui.widget.tabbedpane.TabbedPaneAdapter;\n\npublic class TestTabbedPane extends VisWindow {\n\n\tpublic TestTabbedPane (boolean vertical) {\n\t\tsuper(\"tabbed pane\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\n\t\tsetResizable(true);\n\t\taddCloseButton();\n\t\tcloseOnEscape();\n\n\t\tfinal VisTable container = new VisTable();\n\n\t\tTabbedPaneStyle style = VisUI.getSkin().get(vertical ? \"vertical\" : \"default\", TabbedPaneStyle.class);\n\t\tTabbedPane tabbedPane = new TabbedPane(style);\n\t\ttabbedPane.addListener(new TabbedPaneAdapter() {\n\t\t\t@Override\n\t\t\tpublic void switchedTab (Tab tab) {\n\t\t\t\tcontainer.clearChildren();\n\t\t\t\tcontainer.add(tab.getContentTable()).expand().fill();\n\t\t\t}\n\t\t});\n\n\t\tif (style.vertical) {\n\t\t\ttop();\n\t\t\tdefaults().top();\n\t\t\tadd(tabbedPane.getTable()).growY();\n\t\t\tadd(container).expand().fill();\n\t\t} else {\n\t\t\tadd(tabbedPane.getTable()).expandX().fillX();\n\t\t\trow();\n\t\t\tadd(container).expand().fill();\n\t\t}\n\n\t\ttabbedPane.add(new TestTab(\"tab1\"));\n\t\ttabbedPane.add(new TestTab(\"tab2\"));\n\t\ttabbedPane.add(new TestTab(\"tab3\"));\n\t\ttabbedPane.add(new TestTab(\"tab4\"));\n\t\ttabbedPane.add(new TestTab(\"tab5\"));\n\t\ttabbedPane.add(new TestTab(\"tab6\"));\n\t\ttabbedPane.add(new TestTab(\"tab7\"));\n\t\ttabbedPane.add(new TestTab(\"tab8\"));\n\n\t\tTab tab = new TestTab(\"tab9\");\n\t\ttabbedPane.add(tab);\n\t\ttabbedPane.disableTab(tab, true);\n\n//\t\tdebugAll();\n\t\tsetSize(300, 200);\n\t\tcenterWindow();\n\t}\n\n\tprivate class TestTab extends Tab {\n\t\tprivate String title;\n\t\tprivate Table content;\n\n\t\tpublic TestTab (String title) {\n\t\t\tsuper(false, true);\n\t\t\tthis.title = title;\n\n\t\t\tcontent = new VisTable();\n\t\t\tcontent.add(new VisLabel(title));\n\t\t}\n\n\t\t@Override\n\t\tpublic String getTabTitle () {\n\t\t\treturn title;\n\t\t}\n\n\t\t@Override\n\t\tpublic Table getContentTable () {\n\t\t\treturn content;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestTextAreaAndScroll.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.Label;\nimport com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;\nimport com.badlogic.gdx.scenes.scene2d.ui.Skin;\nimport com.badlogic.gdx.scenes.scene2d.ui.TextArea;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.*;\n\npublic class TestTextAreaAndScroll extends VisWindow {\n\n\tpublic TestTextAreaAndScroll () {\n\t\tsuper(\"textarea / scrollpane\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\tif (TestApplication.USE_VIS_WIDGETS)\n\t\t\taddVisWidgets();\n\t\telse\n\t\t\taddNormalWidgets();\n\n\t\tsetResizable(true);\n\t\tsetSize(180, 380);\n\t\tsetPosition(28, 300);\n\t}\n\n\tprivate void addNormalWidgets () {\n\t\tSkin skin = VisUI.getSkin();\n\n\t\tTextArea textArea = new TextArea(\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec iaculis odio.\", skin);\n\t\ttextArea.setPrefRows(5);\n\n\t\t// ---\n\n\t\tVisTable table = new VisTable();\n\n\t\tfor (int i = 0; i < 20; i++)\n\t\t\ttable.add(new Label(\"Label #\" + (i + 1), skin)).expand().fill().row();\n\n\t\tScrollPane scrollPane = new ScrollPane(table, skin, \"list\");\n\t\tscrollPane.setFlickScroll(false);\n\t\tscrollPane.setFadeScrollBars(false);\n\n\t\t// ---\n\n\t\tadd(textArea).row();\n\t\tadd(scrollPane).spaceTop(8).fillX().expandX().row();\n\t}\n\n\tprivate void addVisWidgets () {\n\t\tScrollableTextArea textArea = new ScrollableTextArea(\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec iaculis odio.\\nFun thing: This text area supports scrolling.\");\n\n\t\t// ---\n\n\t\tVisTable table = new VisTable();\n\n\t\tfor (int i = 0; i < 20; i++)\n\t\t\ttable.add(new VisLabel(\"Label #\" + (i + 1))).expand().fill().row();\n\n\t\tVisScrollPane scrollPane = new VisScrollPane(table);\n\t\tscrollPane.setFlickScroll(false);\n\t\tscrollPane.setFadeScrollBars(false);\n\n\t\t// ---\n\n\t\tadd(textArea.createCompatibleScrollPane()).growX().height(100).row();\n\t\tadd(scrollPane).spaceTop(8).growX().row();\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestToasts.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.Stage;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.utils.Align;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.util.ToastManager;\nimport com.kotcrab.vis.ui.widget.*;\nimport com.kotcrab.vis.ui.widget.toast.MessageToast;\nimport com.kotcrab.vis.ui.widget.toast.Toast;\n\n/** @author Kotcrab */\npublic class TestToasts extends VisWindow {\n\tprivate ToastManager toastManager;\n\n\tpublic TestToasts (Stage stage) {\n\t\tsuper(\"toasts\");\n\n\t\ttoastManager = new ToastManager(stage);\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\taddCloseButton();\n\t\tcloseOnEscape();\n\n\t\taddListener(new WindowResizeListener() {\n\t\t\t@Override\n\t\t\tpublic void resize () {\n\t\t\t\ttoastManager.resize();\n\t\t\t}\n\t\t});\n\n\t\tfinal VisSelectBox<String> alignment = new VisSelectBox<String>();\n\t\talignment.setItems(\"top left\", \"top right\", \"top center\", \"bottom left\", \"bottom right\", \"bottom center\");\n\t\talignment.setSelectedIndex(1);\n\t\talignment.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tint alignIndex = alignment.getSelectedIndex();\n\t\t\t\tswitch (alignIndex) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\ttoastManager.setAlignment(Align.topLeft);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\ttoastManager.setAlignment(Align.topRight);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\ttoastManager.setAlignment(Align.top | Align.center);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\ttoastManager.setAlignment(Align.bottomLeft);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 4:\n\t\t\t\t\t\ttoastManager.setAlignment(Align.bottomRight);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 5:\n\t\t\t\t\t\ttoastManager.setAlignment(Align.bottom | Align.center);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tVisTextButton textToastButton = new VisTextButton(\"text only\");\n\t\ttextToastButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\ttoastManager.show(\"Text only toast\", 3);\n\t\t\t}\n\t\t});\n\n\t\tVisTextButton messageToastButton = new VisTextButton(\"message toast\");\n\t\tmessageToastButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tshowSimpleToast();\n\t\t\t}\n\t\t});\n\n\t\tVisTextButton customToastButton = new VisTextButton(\"custom toast\");\n\t\tcustomToastButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tVisTable content = new VisTable(true);\n\t\t\t\tcontent.add(\"Toast content can be very complex\").row();\n\t\t\t\tcontent.add(\"This toast has a text field\");\n\t\t\t\tcontent.add(new VisTextField()).row();\n\t\t\t\tcontent.add(\"And a button \");\n\t\t\t\tcontent.add(new VisTextButton(\"press me\"));\n\t\t\t\ttoastManager.show(new Toast(\"dark\", content));\n\t\t\t}\n\t\t});\n\n\t\tVisTextButton clearButton = new VisTextButton(\"clear\");\n\t\tclearButton.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\ttoastManager.clear();\n\t\t\t}\n\t\t});\n\n\t\tVisTable alignTable = new VisTable(true);\n\t\talignTable.add(\"Alignment: \");\n\t\talignTable.add(alignment);\n\t\talignTable.add(clearButton);\n\n\t\tVisTable toastBtnTable = new VisTable(true);\n\t\ttoastBtnTable.add(textToastButton);\n\t\ttoastBtnTable.add(messageToastButton);\n\t\ttoastBtnTable.add(customToastButton);\n\n\t\tadd(alignTable).row();\n\t\tadd(toastBtnTable).row();\n\n\t\tpack();\n\t\tcenterWindow();\n\t}\n\n\tprivate void showSimpleToast () {\n\t\tfinal MessageToast messageToast = new MessageToast(\"This is a toast example.\\nPress any of the button to close it.\");\n\t\tmessageToast.addLinkLabel(\"link1\", new LinkLabel.LinkLabelListener() {\n\t\t\t@Override\n\t\t\tpublic void clicked (String url) {\n\t\t\t\tSystem.out.println(\"clicked: link1\");\n\t\t\t\tmessageToast.fadeOut();\n\t\t\t}\n\t\t});\n\t\tmessageToast.addLinkLabel(\"link2\", new LinkLabel.LinkLabelListener() {\n\t\t\t@Override\n\t\t\tpublic void clicked (String url) {\n\t\t\t\tSystem.out.println(\"clicked: link2\");\n\t\t\t\tmessageToast.fadeOut();\n\t\t\t}\n\t\t});\n\t\tmessageToast.addLinkLabel(\"link3\", new LinkLabel.LinkLabelListener() {\n\t\t\t@Override\n\t\t\tpublic void clicked (String url) {\n\t\t\t\tSystem.out.println(\"clicked: link3\");\n\t\t\t\tmessageToast.fadeOut();\n\t\t\t}\n\t\t});\n\t\ttoastManager.show(messageToast, 5);\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestTree.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.Label;\nimport com.badlogic.gdx.scenes.scene2d.ui.Skin;\nimport com.badlogic.gdx.scenes.scene2d.ui.Tree;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.VisLabel;\nimport com.kotcrab.vis.ui.widget.VisTree;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\npublic class TestTree extends VisWindow {\n\n\tpublic TestTree () {\n\t\tsuper(\"tree\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\tif (TestApplication.USE_VIS_WIDGETS)\n\t\t\taddVisWidgets();\n\t\telse\n\t\t\taddNormalWidgets();\n\n\t\tsetSize(150, 380);\n\t\tsetPosition(774, 303);\n\t}\n\n\tprivate void addNormalWidgets () {\n\t\tSkin skin = VisUI.getSkin();\n\n\t\tTree tree = new Tree(skin);\n\t\tTestNode item1 = new TestNode(new Label(\"item 1\", skin));\n\t\tTestNode item2 = new TestNode(new Label(\"item 2\", skin));\n\t\tTestNode item3 = new TestNode(new Label(\"item 3\", skin));\n\n\t\titem1.add(new TestNode(new Label(\"item 1.1\", skin)));\n\t\titem1.add(new TestNode(new Label(\"item 1.2\", skin)));\n\t\titem1.add(new TestNode(new Label(\"item 1.3\", skin)));\n\n\t\titem2.add(new TestNode(new Label(\"item 2.1\", skin)));\n\t\titem2.add(new TestNode(new Label(\"item 2.2\", skin)));\n\t\titem2.add(new TestNode(new Label(\"item 2.3\", skin)));\n\n\t\titem3.add(new TestNode(new Label(\"item 3.1\", skin)));\n\t\titem3.add(new TestNode(new Label(\"item 3.2\", skin)));\n\t\titem3.add(new TestNode(new Label(\"item 3.3\", skin)));\n\n\t\titem1.setExpanded(true);\n\n\t\ttree.add(item1);\n\t\ttree.add(item2);\n\t\ttree.add(item3);\n\n\t\tadd(tree).expand().fill();\n\t}\n\n\tprivate void addVisWidgets () {\n\t\tVisTree tree = new VisTree();\n\t\tTestNode item1 = new TestNode(new VisLabel(\"item 1\"));\n\t\tTestNode item2 = new TestNode(new VisLabel(\"item 2\"));\n\t\tTestNode item3 = new TestNode(new VisLabel(\"item 3\"));\n\n\t\titem1.add(new TestNode(new VisLabel(\"item 1.1\")));\n\t\titem1.add(new TestNode(new VisLabel(\"item 1.2\")));\n\t\titem1.add(new TestNode(new VisLabel(\"item 1.3\")));\n\n\t\titem2.add(new TestNode(new VisLabel(\"item 2.1\")));\n\t\titem2.add(new TestNode(new VisLabel(\"item 2.2\")));\n\t\titem2.add(new TestNode(new VisLabel(\"item 2.3\")));\n\n\t\titem3.add(new TestNode(new VisLabel(\"item 3.1\")));\n\t\titem3.add(new TestNode(new VisLabel(\"item 3.2\")));\n\t\titem3.add(new TestNode(new VisLabel(\"item 3.3\")));\n\n\t\titem1.setExpanded(true);\n\n\t\ttree.add(item1);\n\t\ttree.add(item2);\n\t\ttree.add(item3);\n\n\t\tadd(tree).expand().fill();\n\t}\n\n\tstatic class TestNode extends Tree.Node {\n\t\tpublic TestNode (Actor actor) {\n\t\t\tsuper(actor);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestValidator.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.util.Validators;\nimport com.kotcrab.vis.ui.widget.VisValidatableTextField;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\npublic class TestValidator extends VisWindow {\n\n\tpublic TestValidator () {\n\t\tsuper(\"input validator (float number)\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\tVisValidatableTextField textField = new VisValidatableTextField(Validators.FLOATS);\n\n\t\tadd(textField);\n\n\t\tpack();\n\t\tsetPosition(600, 18);\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestVertical.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.scenes.scene2d.ui.ProgressBar;\nimport com.badlogic.gdx.scenes.scene2d.ui.Slider;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.VisProgressBar;\nimport com.kotcrab.vis.ui.widget.VisSlider;\nimport com.kotcrab.vis.ui.widget.VisTable;\nimport com.kotcrab.vis.ui.widget.VisWindow;\n\npublic class TestVertical extends VisWindow {\n\n\tpublic TestVertical () {\n\t\tsuper(\"vertical\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\tif (TestApplication.USE_VIS_WIDGETS)\n\t\t\taddVisWidgets();\n\t\telse\n\t\t\taddNormalWidgets();\n\n\t\tsetSize(100, 200);\n\t\tsetPosition(1154, 20);\n\t}\n\n\tprivate void addNormalWidgets () {\n\t\tProgressBar progressbar = new ProgressBar(0, 100, 1, true, VisUI.getSkin());\n\t\tSlider slider = new Slider(0, 100, 1, true, VisUI.getSkin());\n\t\tSlider sliderDisabled = new Slider(0, 100, 1, true, VisUI.getSkin());\n\n\t\tprogressbar.setValue(50);\n\t\tslider.setValue(50);\n\t\tsliderDisabled.setValue(50);\n\t\tsliderDisabled.setDisabled(true);\n\n\t\tVisTable progressbarTable = new VisTable(true);\n\t\tprogressbarTable.add(progressbar);\n\t\tprogressbarTable.add(slider);\n\t\tprogressbarTable.add(sliderDisabled);\n\n\t\tadd(progressbarTable);\n\t}\n\n\tprivate void addVisWidgets () {\n\t\tVisProgressBar progressbar = new VisProgressBar(0, 100, 1, true);\n\t\tVisSlider slider = new VisSlider(0, 100, 1, true);\n\t\tVisSlider sliderDisabled = new VisSlider(0, 100, 1, true);\n\n\t\tprogressbar.setValue(50);\n\t\tslider.setValue(50);\n\t\tsliderDisabled.setValue(50);\n\t\tsliderDisabled.setDisabled(true);\n\n\t\tVisTable progressbarTable = new VisTable(true);\n\t\tprogressbarTable.add(progressbar);\n\t\tprogressbarTable.add(slider);\n\t\tprogressbarTable.add(sliderDisabled);\n\n\t\tadd(progressbarTable);\n\t}\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/TestWindow.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.scenes.scene2d.Actor;\nimport com.badlogic.gdx.scenes.scene2d.ui.*;\nimport com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;\nimport com.badlogic.gdx.utils.Array;\nimport com.kotcrab.vis.ui.VisUI;\nimport com.kotcrab.vis.ui.util.TableUtils;\nimport com.kotcrab.vis.ui.widget.Tooltip;\nimport com.kotcrab.vis.ui.widget.*;\nimport com.kotcrab.vis.ui.widget.spinner.*;\n\npublic class TestWindow extends VisWindow {\n\n\tpublic TestWindow () {\n\t\tsuper(\"test window\");\n\n\t\tTableUtils.setSpacingDefaults(this);\n\t\tcolumnDefaults(0).left();\n\n\t\tif (TestApplication.USE_VIS_WIDGETS)\n\t\t\taddVisWidgets();\n\t\telse\n\t\t\taddNormalWidgets();\n\n\t\tpack();\n\t\tsetPosition(234, 280);\n\t}\n\n\tprivate void addVisWidgets () {\n\t\tVisLabel label = new VisLabel(\"label\");\n\t\tfinal VisLabel labelWithTooltip = new VisLabel(\"label with tooltip\");\n\t\tlabelWithTooltip.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tlabelWithTooltip.remove();\n\t\t\t}\n\t\t});\n\t\tnew Tooltip.Builder(\"this label has a tooltip\").target(labelWithTooltip).build();\n\n\t\tTableUtils.setSpacingDefaults(this);\n\n\t\tVisTable labelTable = new VisTable(true);\n\t\tlabelTable.add(label);\n\t\tlabelTable.add(labelWithTooltip);\n\t\t// ---\n\n\t\tVisTextButton normalButton = new VisTextButton(\"button\");\n\t\tVisTextButton normalBlueButton = new VisTextButton(\"button blue\", \"blue\");\n\t\tVisTextButton disabledButton = new VisTextButton(\"disabled\");\n\t\tVisTextButton toggleButton = new VisTextButton(\"toggle\", \"toggle\");\n\t\tdisabledButton.setDisabled(true);\n\n\t\tVisTable buttonTable = new VisTable(true);\n\t\tbuttonTable.add(normalButton);\n\t\tbuttonTable.add(normalBlueButton);\n\t\tbuttonTable.add(disabledButton);\n\t\tbuttonTable.add(toggleButton);\n\n\t\t// ---\n\n\t\tVisCheckBox normalCheckbox = new VisCheckBox(\"checkbox\");\n\t\tVisCheckBox disabledCheckbox = new VisCheckBox(\"disabled\");\n\t\tVisCheckBox disabledCheckedCheckbox = new VisCheckBox(\"disabled checked\");\n\t\tdisabledCheckbox.setDisabled(true);\n\t\tdisabledCheckedCheckbox.setDisabled(true);\n\t\tdisabledCheckedCheckbox.setChecked(true);\n\n\t\tVisTable checkboxTable = new VisTable(true);\n\t\tcheckboxTable.add(normalCheckbox);\n\t\tcheckboxTable.add(disabledCheckbox);\n\t\tcheckboxTable.add(disabledCheckedCheckbox);\n\n\t\t// ---\n\t\tVisRadioButton normalRadio = new VisRadioButton(\"radio\");\n\t\tVisRadioButton disabledRadio = new VisRadioButton(\"disabled\");\n\t\tVisRadioButton disabledCheckedRadio = new VisRadioButton(\"disabled checked\");\n\t\tdisabledRadio.setDisabled(true);\n\t\tdisabledCheckedRadio.setDisabled(true);\n\t\tdisabledCheckedRadio.setChecked(true);\n\n\t\tVisTable radioTable = new VisTable(true);\n\t\tradioTable.add(normalRadio);\n\t\tradioTable.add(disabledRadio);\n\t\tradioTable.add(disabledCheckedRadio);\n\n\t\t// ---\n\n\t\tVisTextField normalTextField = new VisTextField(\"textbox\");\n\t\tVisTextField disabledTextField = new VisTextField(\"disabled\");\n\t\tVisTextField passwordTextField = new VisTextField(\"password\");\n\t\tVisTextField invalidTextField = new VisTextField(\"invalid\");\n\t\tdisabledTextField.setDisabled(true);\n\t\tpasswordTextField.setPasswordMode(true);\n\t\tinvalidTextField.setInputValid(false);\n\n\t\tVisTable textFieldTable = new VisTable(true);\n\t\ttextFieldTable.defaults().width(120);\n\t\ttextFieldTable.add(normalTextField);\n\t\ttextFieldTable.add(disabledTextField);\n\t\ttextFieldTable.add(passwordTextField);\n\t\ttextFieldTable.add(invalidTextField);\n\n\t\t// ---\n\n\t\tVisProgressBar progressbar = new VisProgressBar(0, 100, 1, false);\n\t\tVisSlider slider = new VisSlider(0, 100, 1, false);\n\t\tVisSlider sliderDisabled = new VisSlider(0, 100, 1, false);\n\n\t\tprogressbar.setValue(50);\n\t\tslider.setValue(50);\n\t\tsliderDisabled.setValue(50);\n\t\tsliderDisabled.setDisabled(true);\n\n\t\tVisTable progressbarTable = new VisTable(true);\n\t\tprogressbarTable.add(progressbar);\n\t\tprogressbarTable.add(slider);\n\t\tprogressbarTable.add(sliderDisabled);\n\n\t\t// ---\n\n\t\tVisTable listSpinnerTable = new VisTable();\n\t\tVisList<String> list = new VisList<String>();\n\t\tlist.setItems(\"item 1\", \"item 2\", \"item 3\", \"item 4\");\n\n\t\tlistSpinnerTable.add(new VisLabel(\"list: \"));\n\t\tlistSpinnerTable.add(list);\n\n\t\tArray<String> stringArray = new Array<String>();\n\t\tstringArray.add(\"a\");\n\t\tstringArray.add(\"b\");\n\t\tstringArray.add(\"c\");\n\t\tstringArray.add(\"d\");\n\t\tstringArray.add(\"e\");\n\t\tfinal ArraySpinnerModel<String> arrayModel = new ArraySpinnerModel<String>(stringArray);\n\t\tSpinner arraySpinner = new Spinner(\"array\", arrayModel);\n\n\t\tfinal IntSpinnerModel intModel = new IntSpinnerModel(10, -5, 20, 1);\n\t\tSpinner intSpinner = new Spinner(\"int\", intModel);\n\n\t\tVisTable spinnerTable = new VisTable(true);\n\t\tspinnerTable.add(new VisLabel(\"spinners\")).colspan(2).row();\n\t\tspinnerTable.add(intSpinner);\n\t\tspinnerTable.add(arraySpinner).row();\n\t\tspinnerTable.add(new Spinner(\"simple float\", new SimpleFloatSpinnerModel(10f, -5f, 20f, 1.5f, 3)));\n\t\tspinnerTable.add(new Spinner(\"float\", new FloatSpinnerModel(\"1\", \"-5\", \"10\", \"0.5\", 2)));\n\n\t\tarraySpinner.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tSystem.out.println(\"changed array spinner to: \" + arrayModel.getCurrent());\n\t\t\t}\n\t\t});\n\n\t\tintSpinner.addListener(new ChangeListener() {\n\t\t\t@Override\n\t\t\tpublic void changed (ChangeEvent event, Actor actor) {\n\t\t\t\tSystem.out.println(\"changed int spinner to: \" + intModel.getValue());\n\t\t\t}\n\t\t});\n\n\t\tlistSpinnerTable.add(spinnerTable).padLeft(10f);\n\n\t\t// ---\n\n\t\tVisTable selectorsTable = new VisTable(true);\n\t\tVisSelectBox<String> selectBox = new VisSelectBox<String>();\n\t\tselectBox.setItems(\"item 1\", \"item 2\", \"item 3\", \"item 4\");\n\n\t\tselectorsTable.add(new VisLabel(\"select box: \"));\n\t\tselectorsTable.add(selectBox);\n\n\t\t// ---\n\n\t\tVisTable linkTable = new VisTable(true);\n\t\tlinkTable.add(new VisLabel(\"link label:\"));\n\t\tlinkTable.add(new LinkLabel(\"https://github.com/kotcrab/vis-ui\")).row();\n\n\t\tVisTable linkTable2 = new VisTable(true);\n\t\tlinkTable2.add(new VisLabel(\"link label with custom text:\"));\n\t\tlinkTable2.add(new LinkLabel(\"kotcrab's blog\", \"http://kotcrab.com\")).row();\n\n\t\t// ---\n\n\t\tadd(labelTable).row();\n\t\tadd(buttonTable).row();\n\t\tadd(checkboxTable).row();\n\t\tadd(radioTable).row();\n\t\tadd(textFieldTable).row();\n\t\tadd(progressbarTable).row();\n\t\tadd(listSpinnerTable).row();\n\t\tadd(selectorsTable).row();\n\t\tadd(linkTable).row();\n\t\tadd(linkTable2).padBottom(3).row();\n\t}\n\n\tprivate void addNormalWidgets () {\n\t\tSkin skin = VisUI.getSkin();\n\n\t\tLabel label = new VisLabel(\"label\");\n\n\t\tVisTable labelTable = new VisTable(true);\n\t\tlabelTable.add(label);\n\t\t// ---\n\n\t\tTextButton normalButton = new TextButton(\"button\", skin);\n\t\tTextButton disabledButton = new TextButton(\"disabled\", skin);\n\t\tTextButton toggleButton = new TextButton(\"toggle\", skin, \"toggle\");\n\t\tdisabledButton.setDisabled(true);\n\n\t\tVisTable buttonTable = new VisTable(true);\n\t\tbuttonTable.add(normalButton);\n\t\tbuttonTable.add(disabledButton);\n\t\tbuttonTable.add(toggleButton);\n\n\t\t// ---\n\n\t\tCheckBox normalCheckbox = new CheckBox(\" checkbox\", skin);\n\t\tCheckBox disabledCheckbox = new CheckBox(\" disabled\", skin);\n\t\tCheckBox disabledCheckedCheckbox = new CheckBox(\" disabled checked\", skin);\n\t\tdisabledCheckbox.setDisabled(true);\n\t\tdisabledCheckedCheckbox.setDisabled(true);\n\t\tdisabledCheckedCheckbox.setChecked(true);\n\n\t\tVisTable checkboxTable = new VisTable(true);\n\t\tcheckboxTable.add(normalCheckbox);\n\t\tcheckboxTable.add(disabledCheckbox);\n\t\tcheckboxTable.add(disabledCheckedCheckbox);\n\n\t\t// ---\n\n\t\tCheckBox normalRadio = new CheckBox(\" radio\", skin, \"radio\");\n\t\tCheckBox disabledRadio = new CheckBox(\" disabled\", skin, \"radio\");\n\t\tCheckBox disabledCheckedRadio = new CheckBox(\" disabled checked\", skin, \"radio\");\n\t\tdisabledRadio.setDisabled(true);\n\t\tdisabledCheckedRadio.setDisabled(true);\n\t\tdisabledCheckedRadio.setChecked(true);\n\n\t\tVisTable radioTable = new VisTable(true);\n\t\tradioTable.add(normalRadio);\n\t\tradioTable.add(disabledRadio);\n\t\tradioTable.add(disabledCheckedRadio);\n\n\t\t// ---\n\n\t\tTextField normalTextField = new TextField(\"textbox\", skin);\n\t\tTextField disabledTextField = new TextField(\"disabled\", skin);\n\t\tTextField passwordTextField = new TextField(\"password\", skin);\n\t\tdisabledTextField.setDisabled(true);\n\t\tpasswordTextField.setPasswordMode(true);\n\n\t\tVisTable textFieldTable = new VisTable(true);\n\t\ttextFieldTable.add(normalTextField);\n\t\ttextFieldTable.add(disabledTextField);\n\t\ttextFieldTable.add(passwordTextField);\n\n\t\t// ---\n\n\t\tProgressBar progressbar = new ProgressBar(0, 100, 1, false, skin);\n\t\tSlider slider = new Slider(0, 100, 1, false, skin);\n\t\tSlider sliderDisabled = new Slider(0, 100, 1, false, skin);\n\n\t\tprogressbar.setValue(50);\n\t\tslider.setValue(50);\n\t\tsliderDisabled.setValue(50);\n\t\tsliderDisabled.setDisabled(true);\n\n\t\tVisTable progressbarTable = new VisTable(true);\n\t\tprogressbarTable.add(progressbar);\n\t\tprogressbarTable.add(slider);\n\t\tprogressbarTable.add(sliderDisabled);\n\n\t\t// ---\n\n\t\tVisTable listTable = new VisTable();\n\t\tList<String> list = new List<String>(skin);\n\t\tlist.setItems(\"item 1\", \"item 2\", \"item 3\", \"item 4\");\n\n\t\tlistTable.add(new VisLabel(\"list: \")).top().spaceRight(10);\n\t\tlistTable.add(list);\n\n\t\t// ---\n\n\t\tVisTable selectBoxTable = new VisTable();\n\t\tSelectBox<String> selectBox = new SelectBox<String>(skin);\n\t\tselectBox.setItems(\"item 1\", \"item 2\", \"item 3\", \"item 4\");\n\n\t\tselectBoxTable.add(new VisLabel(\"select box: \")).top().spaceRight(6);\n\t\tselectBoxTable.add(selectBox);\n\n\t\t// ---\n\n\t\tadd(labelTable).row();\n\t\tadd(buttonTable).row();\n\t\tadd(checkboxTable).row();\n\t\tadd(radioTable).row();\n\t\tadd(textFieldTable).row();\n\t\tadd(progressbarTable).row();\n\t\tadd(listTable).row();\n\t\tadd(selectBoxTable).row();\n\t}\n\n}\n"
  },
  {
    "path": "ui/src/test/java/com/kotcrab/vis/ui/test/manual/WindowResizeListener.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.ui.test.manual;\n\nimport com.badlogic.gdx.scenes.scene2d.Event;\nimport com.badlogic.gdx.scenes.scene2d.EventListener;\n\npublic abstract class WindowResizeListener implements EventListener {\n\t@Override\n\tpublic boolean handle (Event event) {\n\t\tif (event instanceof WindowResizeEvent == false) return false;\n\t\tresize();\n\t\treturn false;\n\t}\n\n\tpublic abstract void resize ();\n}\n\nclass WindowResizeEvent extends Event {\n}\n"
  },
  {
    "path": "ui/src/test/resources/file-chooser-high-res.atlas",
    "content": "\nfile-chooser-high-res.png\nsize: 1024,512\nformat: RGBA8888\nfilter: Nearest,Nearest\nrepeat: none\nicon-file-audio-big\n  rotate: false\n  xy: 2, 266\n  size: 200, 200\n  orig: 200, 200\n  offset: 0, 0\n  index: -1\nicon-file-audio-medium\n  rotate: false\n  xy: 406, 134\n  size: 130, 130\n  orig: 130, 130\n  offset: 0, 0\n  index: -1\nicon-file-audio-small\n  rotate: false\n  xy: 538, 204\n  size: 60, 60\n  orig: 60, 60\n  offset: 0, 0\n  index: -1\nicon-file-image-big\n  rotate: false\n  xy: 2, 64\n  size: 200, 200\n  orig: 200, 200\n  offset: 0, 0\n  index: -1\nicon-file-image-medium\n  rotate: false\n  xy: 608, 336\n  size: 130, 130\n  orig: 130, 130\n  offset: 0, 0\n  index: -1\nicon-file-image-small\n  rotate: false\n  xy: 608, 274\n  size: 60, 60\n  orig: 60, 60\n  offset: 0, 0\n  index: -1\nicon-file-pdf-big\n  rotate: false\n  xy: 204, 266\n  size: 200, 200\n  orig: 200, 200\n  offset: 0, 0\n  index: -1\nicon-file-pdf-medium\n  rotate: false\n  xy: 740, 336\n  size: 130, 130\n  orig: 130, 130\n  offset: 0, 0\n  index: -1\nicon-file-pdf-small\n  rotate: false\n  xy: 2, 2\n  size: 60, 60\n  orig: 60, 60\n  offset: 0, 0\n  index: -1\nicon-file-text-big\n  rotate: false\n  xy: 204, 64\n  size: 200, 200\n  orig: 200, 200\n  offset: 0, 0\n  index: -1\nicon-file-text-medium\n  rotate: false\n  xy: 872, 336\n  size: 130, 130\n  orig: 130, 130\n  offset: 0, 0\n  index: -1\nicon-file-text-small\n  rotate: false\n  xy: 538, 142\n  size: 60, 60\n  orig: 60, 60\n  offset: 0, 0\n  index: -1\nicon-folder-big\n  rotate: false\n  xy: 406, 266\n  size: 200, 200\n  orig: 200, 200\n  offset: 0, 0\n  index: -1\nicon-folder-medium\n  rotate: false\n  xy: 406, 2\n  size: 130, 130\n  orig: 130, 130\n  offset: 0, 0\n  index: -1\nicon-folder-small\n  rotate: false\n  xy: 670, 274\n  size: 60, 60\n  orig: 60, 60\n  offset: 0, 0\n  index: -1\n"
  },
  {
    "path": "usl/CHANGES.md",
    "content": "#### Version: 0.2.1\n- Fixed parsing negative values (eg. pressedOffsetY: -1)\n\n#### Version: 0.2.0\n- Java 7 is minimum required version\n- Removed support for latest VisUI include (`include <visui>`). Version must be explicitly stated now (eg. `include <visui-1.1.0>`)\n- Removed default skins from the JAR, skins are now stored in GitHub repository\n"
  },
  {
    "path": "usl/build.gradle",
    "content": "archivesBaseName = \"vis-usl\"\nsourceCompatibility = 1.8\n[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'\n\ndependencies {\n    testImplementation \"junit:junit:$junitVersion\"\n}\n\ntask run(type: JavaExec) {\n    main = 'com.kotcrab.vis.usl.Main'\n    classpath = sourceSets.main.runtimeClasspath\n    ignoreExitValue = true\n    if (project.hasProperty(\"runArgs\")) {\n        args = Eval.me(runArgs)\n    }\n}\n"
  },
  {
    "path": "usl/gradle.properties",
    "content": "projectName=vis-usl\nprojectDesc=UI styling language for scene2d.ui\nprojectVersion=0.2.2-SNAPSHOT\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/CollectionUtils.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl;\n\nimport java.util.*;\n\n/** CollectionUtils copied from Apache Commons */\npublic class CollectionUtils {\n\n\t/**\n\t * Returns <tt>true</tt> iff the given {@link Collection}s contain\n\t * exactly the same elements with exactly the same cardinality.\n\t * <p>\n\t * That is, iff the cardinality of <i>e</i> in <i>a</i> is\n\t * equal to the cardinality of <i>e</i> in <i>b</i>,\n\t * for each element <i>e</i> in <i>a</i> or <i>b</i>.\n\t */\n\tpublic static boolean isEqualCollection (final Collection a, final Collection b) {\n\t\tif (a.size() != b.size()) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\tMap mapa = getCardinalityMap(a);\n\t\t\tMap mapb = getCardinalityMap(b);\n\t\t\tif (mapa.size() != mapb.size()) {\n\t\t\t\treturn false;\n\t\t\t} else {\n\t\t\t\tIterator it = mapa.keySet().iterator();\n\t\t\t\twhile (it.hasNext()) {\n\t\t\t\t\tObject obj = it.next();\n\t\t\t\t\tif (getFreq(obj, mapa) != getFreq(obj, mapb)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static final int getFreq (final Object obj, final Map freqMap) {\n\t\ttry {\n\t\t\treturn ((Integer) (freqMap.get(obj))).intValue();\n\t\t} catch (NullPointerException e) {\n\t\t\t// ignored\n\t\t} catch (NoSuchElementException e) {\n\t\t\t// ignored\n\t\t}\n\t\treturn 0;\n\t}\n\n\t/**\n\t * Returns a {@link Map} mapping each unique element in\n\t * the given {@link Collection} to an {@link Integer}\n\t * representing the number of occurances of that element\n\t * in the {@link Collection}.\n\t * An entry that maps to <tt>null</tt> indicates that the\n\t * element does not appear in the given {@link Collection}.\n\t */\n\tpublic static Map getCardinalityMap (final Collection col) {\n\t\tHashMap count = new HashMap();\n\t\tIterator it = col.iterator();\n\t\twhile (it.hasNext()) {\n\t\t\tObject obj = it.next();\n\t\t\tInteger c = (Integer) (count.get(obj));\n\t\t\tif (null == c) {\n\t\t\t\tcount.put(obj, new Integer(1));\n\t\t\t} else {\n\t\t\t\tcount.put(obj, new Integer(c.intValue() + 1));\n\t\t\t}\n\t\t}\n\t\treturn count;\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/IncludeLoader.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.net.HttpURLConnection;\nimport java.net.URL;\nimport java.nio.channels.Channels;\nimport java.nio.channels.ReadableByteChannel;\nimport java.util.ArrayList;\nimport java.util.Scanner;\n\n/** @author Kotcrab */\npublic class IncludeLoader {\n\tprivate File cacheFolder = new File(USL.CACHE_FOLDER_PATH);\n\tprivate File tmpFolder = new File(USL.TMP_FOLDER_PATH);\n\n\tprivate ArrayList<String> includeSources = new ArrayList<>();\n\n\tpublic IncludeLoader () {\n\t\tcacheFolder.mkdirs();\n\t\ttmpFolder.mkdirs();\n\n\t\tString additionalIncludeDir = System.getProperty(\"usl.include.path\");\n\t\tif (additionalIncludeDir != null) includeSources.add(additionalIncludeDir);\n\t\tincludeSources.add(\"http://apps.kotcrab.com/vis/usl/\");\n\t\tincludeSources.add(\"https://raw.githubusercontent.com/kotcrab/vis-ui/master/usl/styles/\");\n\t}\n\n\tpublic String loadInclude (String includeName) {\n\t\treturn fileToString(loadIncludeFile(includeName));\n\t}\n\n\tprivate File loadIncludeFile (String includeName) {\n\t\ttry {\n\t\t\tincludeName += \".usl\";\n\t\t\tFile cacheFile = new File(cacheFolder, includeName);\n\t\t\tFile tmpFile = new File(tmpFolder, includeName);\n\t\t\tif (cacheFile.exists()) return cacheFile;\n\n\t\t\tboolean snapshot = includeName.endsWith(\"-SNAPSHOT.usl\");\n\n\t\t\tfor (String includeSource : includeSources) {\n\t\t\t\tif (includeSource.startsWith(\"https://\") || includeSource.startsWith(\"http://\")) {\n\t\t\t\t\tURL url = new URL(includeSource + includeName);\n\n\t\t\t\t\tHttpURLConnection connection = (HttpURLConnection) url.openConnection();\n\t\t\t\t\tfinal int responseCode = connection.getResponseCode();\n\t\t\t\t\tif (responseCode != 200) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tSystem.out.println(\"Download include file \" + includeSource + includeName + \"...\");\n\t\t\t\t\tReadableByteChannel rbc = Channels.newChannel(url.openStream());\n\t\t\t\t\tFileOutputStream fos = new FileOutputStream(snapshot ? tmpFile : cacheFile);\n\t\t\t\t\tfos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);\n\t\t\t\t\treturn snapshot ? tmpFile : cacheFile;\n\n\t\t\t\t} else {\n\t\t\t\t\tFile localFile = new File(includeSource, includeName);\n\t\t\t\t\tif (localFile.exists()) return localFile;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tStringBuilder exceptionMsg = new StringBuilder();\n\t\t\texceptionMsg.append(\"Could not find '\").append(includeName).append(\"' include. Searched in the following locations:\\n\");\n\t\t\tfor (String includeSource : includeSources) {\n\t\t\t\texceptionMsg.append(\"\\t\").append(includeSource + includeName).append(\"\\n\");\n\t\t\t}\n\t\t\tthrow new IllegalStateException(exceptionMsg.toString());\n\t\t} catch (IOException e) {\n\t\t\tthrow new IllegalStateException(\"Error during include file downloading\", e);\n\t\t}\n\t}\n\n\tprivate String fileToString (File file) {\n\t\ttry {\n\t\t\tScanner s = new Scanner(file).useDelimiter(\"\\\\A\");\n\t\t\treturn s.hasNext() ? s.next() : \"\";\n\t\t} catch (FileNotFoundException e) {\n\t\t\tthrow new IllegalStateException(\"Error reading file\", e);\n\t\t}\n\t}\n\n\tpublic void addIncludeSource (String path) {\n\t\tincludeSources.add(0, path);\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/Lexer.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl;\n\nimport com.kotcrab.vis.usl.Token.Type;\n\nimport java.io.File;\nimport java.util.List;\nimport java.util.regex.Pattern;\n\n/** USL Lexer that turns USL file intro stream of tokens */\npublic class Lexer {\n\tprivate static final String INCLUDE = \"include\";\n\tprivate static final String EXTENDS = \"extends\";\n\tprivate static final String INHERITS = \"inherits\";\n\tprivate static final String PACKAGE = \"package\";\n\n\tprivate static final Pattern globalStyleRegex = Pattern.compile(\"^\\\\.[a-zA-Z0-9-_]+:.*$\", Pattern.DOTALL);\n\tprivate static final Pattern metaStyleRegex = Pattern.compile(\"^-[a-zA-Z0-9-_ ]+:.*$\", Pattern.DOTALL);\n\n\tprivate static IncludeLoader includeLoader = new IncludeLoader();\n\n\tstatic void lexUsl (LexerContext ctx, String usl) {\n\t\tusl = usl.replace(\"\\r\\n\", \"\\n\");\n\t\tusl = removeComments(usl);\n\n\t\tfor (int i = 0; i < usl.length(); ) {\n\t\t\tchar ch = usl.charAt(i);\n\n\t\t\tif (Character.isWhitespace(ch)) { //white space\n\t\t\t\ti++;\n\n\t\t\t} else if (usl.startsWith(INCLUDE + \" \", i)) { //include <type> <path> directive\n\t\t\t\ti = parseAndLexInclude(ctx, usl, i + INCLUDE.length() + 1);\n\n\t\t\t} else if (usl.startsWith(PACKAGE + \" \", i)) { //package <path> directive\n\t\t\t\ti = lexPackage(ctx, usl, i + PACKAGE.length() + 1);\n\n\t\t\t} else if (ch == '#') { //block style definition\n\t\t\t\ti = lexStyleBlock(ctx, usl, i + 1);\n\n\t\t\t} else if (ch == '^') { //block style override block definition\n\t\t\t\ti = lexStyleBlockOverride(ctx, usl, i + 1);\n\n\t\t\t} else if (ch == '.') { //global block style definition\n\t\t\t\tif (globalStyleRegex.matcher(usl.substring(i)).matches() == false)\n\t\t\t\t\tUtils.throwException(\"Unexpected '.' or invalid global style block declaration\", usl, i);\n\n\t\t\t\ti = lexGlobalStyleDeclaration(ctx, usl, i + 1);\n\n\t\t\t} else if (ch == '-' && peek(ctx.tokens).type != Type.IDENTIFIER) { //meta style definition\n\t\t\t\tif (metaStyleRegex.matcher(usl.substring(i)).matches() == false) {\n\t\t\t\t\tUtils.throwException(\"Unexpected '-'\", usl, i);\n\t\t\t\t}\n\n\t\t\t\t//put meta token and continue, lexIdentifier will be called in next loop\n\t\t\t\tctx.tokens.add(new Token(usl, i, Type.META_STYLE));\n\t\t\t\ti++;\n\n\t\t\t} else if (ch == '{') {\n\t\t\t\tctx.curliesLevel++;\n\t\t\t\tctx.tokens.add(new Token(usl, i, Type.LCURL));\n\t\t\t\ti++;\n\t\t\t} else if (ch == '}') {\n\t\t\t\tctx.curliesLevel--;\n\t\t\t\tif (ctx.curliesLevel < 0) Utils.throwException(\"Unexpected '}'\", usl, i);\n\t\t\t\tctx.tokens.add(new Token(usl, i, Type.RCURL));\n\t\t\t\ti++;\n\t\t\t} else if (ch == ',') {\n\t\t\t\tif (ctx.curliesLevel > 1 && peek(ctx.tokens, 2).type == Type.IDENTIFIER_CONTENT) //',' will be valid if we are currently inside style definition\n\t\t\t\t\ti++;\n\t\t\t\telse\n\t\t\t\t\tUtils.throwException(\"Unexpected ','\", usl, i);\n\t\t\t} else if (peek(ctx.tokens).type == Type.IDENTIFIER) { //identifier content: someName: content\n\t\t\t\ti = lexIdentifierContent(ctx, usl, i);\n\t\t\t} else if (checkIdentifierDef(usl, i)) { // identifier: someName: content\n\t\t\t\ti = lexIdentifier(ctx, usl, i);\n\t\t\t} else {\n\t\t\t\tUtils.throwException(\"Unrecognized symbol '\" + usl.substring(i, usl.indexOf(\" \", i)) + \"'\", usl, i);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static String removeComments (String usl) {\n\t\tStringBuilder newUsl = new StringBuilder(usl.length());\n\t\tboolean insideComment = false;\n\t\tfor (int i = 0; i < usl.length(); i++) {\n\t\t\tchar ch = usl.charAt(i);\n\n\t\t\tif (usl.startsWith(\"//\", i)) {\n\t\t\t\tinsideComment = true;\n\t\t\t}\n\n\t\t\tif (ch == '\\n' && insideComment) {\n\t\t\t\tinsideComment = false;\n\t\t\t}\n\n\t\t\tif (insideComment == false) {\n\t\t\t\tnewUsl.append(ch);\n\t\t\t}\n\t\t}\n\n\t\treturn newUsl.toString();\n\t}\n\n\tprivate static int lexPackage (LexerContext ctx, String usl, int i) {\n\t\tint curlyIndex = usl.indexOf('{', i);\n\t\tString packageName = usl.substring(i, curlyIndex);\n\t\tctx.tokens.add(new Token(usl, i, Type.PACKAGE, packageName.replace(\" \", \"\")));\n\t\treturn curlyIndex - 1;\n\t}\n\n\tprivate static int lexIdentifier (LexerContext ctx, String usl, int i) {\n\t\tint idDefEnd = usl.indexOf(\":\", i);\n\n\t\tString idDef = usl.substring(i, idDefEnd);\n\n\t\tif (idDef.contains(\" \")) { //blocks definition contains inherits\n\t\t\tif (idDef.contains(INHERITS) == false) Utils.throwException(\"Expected inherits\", usl, i);\n\t\t\tString parts[] = idDef.split(\" \", 3);\n\t\t\tif (parts.length != 3) Utils.throwException(\"Invalid inherits format\", usl, i);\n\n\t\t\tctx.tokens.add(new Token(usl, i, Type.IDENTIFIER, parts[0]));\n\t\t\tctx.tokens.add(new Token(usl, i, Type.INHERITS));\n\t\t\tlexInherits(usl, i, ctx, parts[2]);\n\t\t} else {\n\t\t\tctx.tokens.add(new Token(usl, i, Type.IDENTIFIER, idDef));\n\t\t}\n\n\t\treturn idDefEnd + 1; //+1 for : at the end of id definition\n\t}\n\n\tprivate static int lexIdentifierContent (LexerContext ctx, String usl, int i) {\n\t\tint commaIndex = usl.indexOf(',', i);\n\t\tint curlyIndex = usl.indexOf('}', i);\n\t\tint endLineIndex = usl.indexOf('\\r', i);\n\t\tif (endLineIndex == -1) endLineIndex = usl.indexOf('\\n', i);\n\n\t\tif (commaIndex == -1) commaIndex = Integer.MAX_VALUE;\n\t\tif (curlyIndex == -1) curlyIndex = Integer.MAX_VALUE;\n\t\tif (endLineIndex == -1) endLineIndex = Integer.MAX_VALUE;\n\n\t\tint end = Math.min(commaIndex, Math.min(curlyIndex, endLineIndex));\n\t\tif (end == -1) Utils.throwException(\"Identifier content end could not be found\", usl, i);\n\n\t\tString content = usl.substring(i, end);\n\t\tint origLength = content.length();\n\t\tif (content.endsWith(\" \")) content = content.substring(0, content.length() - 1);\n\t\tctx.tokens.add(new Token(usl, i, Type.IDENTIFIER_CONTENT, content));\n\n\t\ti = i + origLength;\n\t\tif (usl.charAt(i) == ',') i++;\n\t\treturn i;\n\t}\n\n\tprivate static int lexGlobalStyleDeclaration (LexerContext ctx, String usl, int i) {\n\t\tint end = usl.indexOf(':', i);\n\t\tif (end == -1) Utils.throwException(\"Global style definition end could not be found\", usl, i);\n\n\t\tString declaration = usl.substring(i, end);\n\n\t\tif (declaration.contains(\" \")) { //global style definition contains inherits\n\t\t\tif (declaration.contains(INHERITS) == false) Utils.throwException(\"Expected inherits\", usl, i);\n\t\t\tString parts[] = declaration.split(\" \", 3);\n\t\t\tif (parts.length != 3) Utils.throwException(\"Invalid inherits format\", usl, i);\n\n\t\t\tctx.tokens.add(new Token(usl, i, Type.GLOBAL_STYLE, parts[0]));\n\t\t\tctx.tokens.add(new Token(usl, i, Type.INHERITS));\n\t\t\tlexInherits(usl, i, ctx, parts[2]);\n\t\t} else {\n\t\t\tctx.tokens.add(new Token(usl, i, Type.GLOBAL_STYLE, declaration));\n\t\t}\n\n\t\treturn end + 1;\n\t}\n\n\tprivate static void lexInherits (String usl, int i, LexerContext ctx, String inheritString) {\n\t\tinheritString = inheritString.replace(\" \", \"\");\n\t\tString[] inherits = inheritString.split(\",\");\n\n\t\tfor (String inherit : inherits)\n\t\t\tctx.tokens.add(new Token(usl, i, Type.INHERITS_NAME, inherit));\n\t}\n\n\tprivate static boolean checkIdentifierDef (String usl, int i) {\n\t\t//checks if this is possible identifier definition\n\t\tint colonIndex = usl.indexOf(':', i);\n\t\tint spaceIndex = usl.indexOf(' ', i);\n\t\tif (colonIndex == -1) return false;\n\t\tif (colonIndex < spaceIndex)\n\t\t\treturn true;\n\t\telse {\n\t\t\tif (usl.substring(spaceIndex + 1, colonIndex).startsWith(INHERITS))\n\t\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate static int lexStyleBlock (LexerContext ctx, String usl, int i) {\n\t\tint blockDefEnd = usl.indexOf(\":\", i);\n\t\tif (blockDefEnd == -1) Utils.throwException(\"Expected block definition end\", usl, i);\n\n\t\tString blockDef = usl.substring(i, blockDefEnd);\n\n\t\tif (blockDef.contains(\" \")) { //blocks definition contains extends\n\t\t\tif (blockDef.contains(EXTENDS) == false) Utils.throwException(\"Expected extends\", usl, i);\n\t\t\tString parts[] = blockDef.split(\" \");\n\t\t\tif (parts.length != 3) Utils.throwException(\"Invalid extends format\", usl, i);\n\n\t\t\tctx.tokens.add(new Token(usl, i, Type.STYLE_BLOCK, parts[0]));\n\t\t\tctx.tokens.add(new Token(usl, i, Type.STYLE_BLOCK_EXTENDS, parts[2]));\n\t\t} else\n\t\t\tctx.tokens.add(new Token(usl, i, Type.STYLE_BLOCK, blockDef));\n\n\t\treturn blockDefEnd + 1; //+1 for : at the end of style definition\n\t}\n\n\tprivate static int lexStyleBlockOverride (LexerContext ctx, String usl, int i) {\n\t\tint blockDefEnd = usl.indexOf(\":\", i);\n\t\tif (blockDefEnd == -1) Utils.throwException(\"Expected block definition end\", usl, i);\n\n\t\tString blockDef = usl.substring(i, blockDefEnd);\n\n\t\tif (blockDef.contains(\" \")) {\n\t\t\tif (blockDef.contains(\"extends\"))\n\t\t\t\tUtils.throwException(\"Override style block cannot extend other style\", usl, i);\n\t\t\telse\n\t\t\t\tUtils.throwException(\"Invalid block definition\", usl, i);\n\t\t} else\n\t\t\tctx.tokens.add(new Token(usl, i, Type.STYLE_BLOCK_OVERRIDE, blockDef));\n\n\t\treturn blockDefEnd + 1; //+1 for : at the end of style definition\n\t}\n\n\tprivate static int parseAndLexInclude (LexerContext ctx, String usl, int i) {\n\t\tif (usl.startsWith(\"<\", i)) {\n\t\t\tint includeEnd = usl.indexOf(\">\", i);\n\t\t\tif (includeEnd == -1) Utils.throwException(\"Invalid include format, '>` expected\", usl, i);\n\n\t\t\tString includeName = usl.substring(i + 1, includeEnd);\n\t\t\tString content = includeLoader.loadInclude(includeName);\n\t\t\tlexUsl(ctx, content);\n\n\t\t\treturn includeEnd + 1;\n\t\t} else if (usl.startsWith(\"\\\"\", i)) {\n\t\t\tint includeEnd = usl.indexOf(\"\\\"\", i + 1);\n\t\t\tif (includeEnd == -1) Utils.throwException(\"Invalid include format, '\\\"' expected\", usl, i);\n\n\t\t\tString path = usl.substring(i + 1, includeEnd);\n\t\t\tFile file = new File(path);\n\n\t\t\tif (file.exists() == false)\n\t\t\t\tUtils.throwException(\"Include file does not exist, file: \" + file.getAbsolutePath(), usl, i);\n\t\t\tlexUsl(ctx, Utils.readFile(file));\n\t\t\treturn includeEnd + 1;\n\t\t} else\n\t\t\tUtils.throwException(\"Invalid include format\", usl, i);\n\n\t\treturn -1;\n\t}\n\n\tpublic static void addIncludeSource (String path) {\n\t\tincludeLoader.addIncludeSource(path);\n\t}\n\n\tprivate static <T> T peek (List<T> list) {\n\t\treturn peek(list, 1);\n\t}\n\n\tprivate static <T> T peek (List<T> list, int i) {\n\t\tif (list != null && !list.isEmpty()) {\n\t\t\treturn list.get(list.size() - i);\n\t\t}\n\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/LexerContext.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl;\n\nimport java.io.File;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/** Class holding properties required for USL {@link Lexer} */\npublic class LexerContext {\n\tfinal File workingDirectory;\n\n\tfinal List<Token> tokens = new ArrayList<Token>();\n\tint curliesLevel = 0;\n\n\tpublic LexerContext (File workingDirectory) {\n\t\tthis.workingDirectory = workingDirectory;\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/Main.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.PrintStream;\n\n/** Main class of ULS, allowing to use it from command line */\npublic class Main {\n\tpublic static void main (String[] args) {\n\t\tif (args.length < 2) {\n\t\t\tSystem.out.println(\"Usage: <input usl file> <output json file>\");\n\t\t\tSystem.exit(1);\n\t\t}\n\n\t\tFile input = new File(args[0]);\n\t\tFile output = new File(args[1]);\n\n\t\tif (input.exists() == false) {\n\t\t\tSystem.out.println(\"Input file does not exist\");\n\t\t\tSystem.exit(2);\n\t\t}\n\n\t\tSystem.out.println(\"Parsing USL...\");\n\t\tString usl = USL.parse(input);\n\n\t\ttry {\n\t\t\tif (output.exists() == false) {\n\t\t\t\toutput.createNewFile();\n\t\t\t}\n\n\t\t\tSystem.out.println(\"Writing JSON \" + output.getPath() + \"...\");\n\t\t\tPrintStream out = new PrintStream(new FileOutputStream(output));\n\t\t\tout.print(usl);\n\t\t\tout.close();\n\t\t\tSystem.out.println(\"Success.\");\n\t\t} catch (IOException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/Parser.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl;\n\nimport com.kotcrab.vis.usl.Token.Type;\nimport com.kotcrab.vis.usl.lang.*;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Stack;\n\n/** Converts stream of tokens created by {@link Lexer} into json string. */\npublic class Parser {\n\tprivate StringBuilder out;\n\tprivate List<Token> tokens;\n\tprivate int i = 0;\n\n\tprivate String currentPackage;\n\tprivate StyleBlock currentStyleBlock;\n\tprivate int currentPackageEnd;\n\tprivate int currentStyleBlockEnd;\n\n\tprivate ArrayList<StyleBlock> styleBlocks = new ArrayList<StyleBlock>();\n\tprivate ArrayList<StyleBlock> styleBlocksOverride = new ArrayList<StyleBlock>();\n\tprivate ArrayList<StyleIdentifier> globalStyles = new ArrayList<StyleIdentifier>();\n\n\tprivate Stack<GroupIdentifier> identifiers = new Stack<GroupIdentifier>();\n\n\tpublic String getJson (List<Token> tokens) {\n\t\tout = new StringBuilder();\n\t\tthis.tokens = tokens;\n\n\t\tfor (; i < tokens.size(); ) {\n\t\t\tToken t = tokens.get(i);\n\t\t\t//System.out.println(t.type + \" \" + (t.content == null ? \"\" : t.content));\n\n\t\t\tif (t.type == Type.PACKAGE) {\n\t\t\t\tif (currentPackage != null) Utils.throwException(\"Packages cannot be nested\", t);\n\t\t\t\tif (t.content.endsWith(\".\")) Utils.throwException(\"Package name cannot end with dot\", t);\n\t\t\t\tcurrentPackage = t.content;\n\t\t\t\ti++;\n\t\t\t\tcurrentPackageEnd = findBlockEnd();\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (t.type == Type.STYLE_BLOCK) {\n\t\t\t\tif (currentStyleBlock != null) Utils.throwException(\"Style cannot be nested\", t);\n\t\t\t\tcurrentStyleBlock = new StyleBlock();\n\t\t\t\tstyleBlocks.add(currentStyleBlock);\n\t\t\t\ti++;\n\t\t\t\tcurrentStyleBlockEnd = findBlockEnd();\n\n\t\t\t\tif (currentPackage != null)\n\t\t\t\t\tcurrentStyleBlock.fullName = currentPackage + \".\" + t.content;\n\t\t\t\telse\n\t\t\t\t\tcurrentStyleBlock.fullName = t.content;\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (t.type == Type.STYLE_BLOCK_OVERRIDE) {\n\t\t\t\tif (currentStyleBlock != null) Utils.throwException(\"Style cannot be nested\", t);\n\t\t\t\tcurrentStyleBlock = new StyleBlock();\n\t\t\t\tstyleBlocksOverride.add(currentStyleBlock);\n\t\t\t\ti++;\n\t\t\t\tcurrentStyleBlockEnd = findBlockEnd();\n\n\t\t\t\tcurrentStyleBlock.fullName = findMatchingStyle(t, t.content).fullName;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (t.type == Type.STYLE_BLOCK_EXTENDS) {\n\t\t\t\tif (currentStyleBlock == null)\n\t\t\t\t\tUtils.throwException(\"Unexpected extends\", t);\n\t\t\t\tif (currentStyleBlock.extendsStyle != null)\n\t\t\t\t\tUtils.throwException(\"Style block can only extend one style\", t);\n\n\t\t\t\tboolean isDefinedOnly = t.content.startsWith(\"~\");\n\n\t\t\t\tcurrentStyleBlock.extendsStyle = findMatchingStyle(t, isDefinedOnly ? t.content.substring(1) : t.content);\n\t\t\t\tcurrentStyleBlock.extendsInheritOnlyDefinedStyles = isDefinedOnly;\n\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (t.type == Type.GLOBAL_STYLE) {\n\t\t\t\tStyleIdentifier globalId = new StyleIdentifier();\n\t\t\t\tglobalId.name = \".\" + t.content;\n\t\t\t\tglobalStyles.add(globalId);\n\t\t\t\tidentifiers.push(globalId);\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (t.type == Type.IDENTIFIER) {\n\t\t\t\tif (identifiers.size() == 0) {\n\t\t\t\t\tStyleIdentifier id = new StyleIdentifier();\n\t\t\t\t\tif (peekPrev().type == Type.META_STYLE) id.metaStyle = true;\n\t\t\t\t\tid.name = t.content;\n\n\t\t\t\t\tcurrentStyleBlock.styles.add(id);\n\t\t\t\t\tidentifiers.push(id);\n\t\t\t\t\ti++;\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\n\t\t\t\t\tif (peekNext().type == Type.IDENTIFIER_CONTENT) {\n\t\t\t\t\t\tidentifiers.peek().content.add(new BasicIdentifier(t.content, peekNext().content));\n\t\t\t\t\t\ti += 2;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (peekNext().type == Type.INHERITS || peekNext().type == Type.LCURL) {\n\t\t\t\t\t\tGroupIdentifier id = new GroupIdentifier();\n\t\t\t\t\t\tidentifiers.peek().content.add(id);\n\t\t\t\t\t\tidentifiers.push(id);\n\n\t\t\t\t\t\tid.name = t.content;\n\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//handles case where JSON alias is used (IDENTIFIER_CONTENT occurs right after IDENTIFIER)\n\t\t\tif (t.type == Type.IDENTIFIER_CONTENT && identifiers.size() == 1) {\n\t\t\t\tidentifiers.pop().content.add(new AliasIdentifier(t.content));\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (t.type == Type.INHERITS || t.type == Type.IDENTIFIER_CONTENT || t.type == Type.LCURL || t.type == Type.META_STYLE) {\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (t.type == Type.INHERITS_NAME) {\n\t\t\t\tidentifiers.peek().inherits.add(t.content);\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (t.type == Type.RCURL) {\n\t\t\t\tif (i == currentPackageEnd) {\n\t\t\t\t\tcurrentPackage = null;\n\t\t\t\t\tcurrentPackageEnd = -1;\n\t\t\t\t} else if (i == currentStyleBlockEnd) {\n\t\t\t\t\tcurrentStyleBlock = null;\n\t\t\t\t\tcurrentStyleBlockEnd = -1;\n\n\t\t\t\t} else {\n\t\t\t\t\tidentifiers.pop();\n\t\t\t\t}\n\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tUtils.throwException(\"Parser failed, invalid token: \" + t.type, t);\n\t\t}\n\n\t\tpostCheck();\n\n\t\tArrayList<StyleBlock> mergedStyleBlocks = new StyleMerger(globalStyles, styleBlocks, styleBlocksOverride).merge();\n\t\treturn new USLJsonWriter(mergedStyleBlocks).getJson();\n\t}\n\n\tprivate StyleBlock findMatchingStyle (Token t, String name) {\n\t\tArrayList<StyleBlock> matches = new ArrayList<StyleBlock>();\n\n\t\t//search for literal match\n\t\tfor (StyleBlock block : styleBlocks) {\n\t\t\tif (block.fullName.equals(name)) {\n\t\t\t\tmatches.add(block);\n\t\t\t}\n\t\t}\n\n\t\t//search for last $ match\n\t\tfor (StyleBlock block : styleBlocks) {\n\t\t\tString parts[] = block.fullName.split(\"\\\\$\");\n\t\t\tif (parts.length == 2 && parts[1].equals(name)) {\n\t\t\t\tmatches.add(block);\n\t\t\t}\n\t\t}\n\n\t\t//search for last . match\n\t\tfor (StyleBlock block : styleBlocks) {\n\t\t\tString parts[] = block.fullName.split(\"\\\\.\");\n\t\t\tif (parts.length == 2 && parts[1].equals(name)) {\n\t\t\t\tmatches.add(block);\n\t\t\t}\n\t\t}\n\n\t\tif (matches.size() == 0) Utils.throwException(\"Style block extends unknown undefined style: \" + name, t);\n\n\t\tStyleBlock match = matches.get(0);\n\n\t\tif (matches.size() > 1)\n\t\t\tSystem.out.println(\"Warn: multiples matches found for name: '\" + name + \"', using: \" + match.fullName);\n\n\t\tif (match == currentStyleBlock) Utils.throwException(\"Style block cannot extend itself\", t);\n\n\t\treturn match;\n\t}\n\n\tprivate int findBlockEnd () {\n\t\tint curliesLevel = 0;\n\n\t\tint firstLCurl;\n\n\t\tfor (firstLCurl = i; firstLCurl < tokens.size(); firstLCurl++) {\n\t\t\tToken t = tokens.get(firstLCurl);\n\t\t\tif (t.type == Type.LCURL) break;\n\t\t}\n\n\t\tfor (int j = firstLCurl; j < tokens.size(); j++) {\n\t\t\tToken t = tokens.get(j);\n\n\t\t\tif (t.type == Type.LCURL) curliesLevel++;\n\t\t\tif (t.type == Type.RCURL) curliesLevel--;\n\n\t\t\tif (curliesLevel == 0)\n\t\t\t\treturn j;\n\t\t}\n\n\t\tUtils.throwException(\"Parser failed, end of block not found\", tokens.get(i));\n\t\treturn -1;\n\t}\n\n\tprivate Token peekPrev () {\n\t\treturn tokens.get(i - 1);\n\t}\n\n\tprivate Token peekNext () {\n\t\tif (i + 1 > tokens.size())\n\t\t\tUtils.throwException(\"Unexpected EOF\", tokens.get(i));\n\n\t\treturn tokens.get(i + 1);\n\t}\n\n\tprivate void postCheck () {\n\t\tif (identifiers.size() > 0)\n\t\t\tSystem.out.println(\"Post check warning: identifier stack not empty after parsing. \" +\n\t\t\t\t\t\"Some identifiers not closed or internal parser error.\");\n\n\t\tfor (StyleIdentifier id : globalStyles) {\n\t\t\tpostCheckStyleId(id);\n\t\t}\n\n\t\tfor (StyleBlock block : styleBlocks) {\n\t\t\tfor (StyleIdentifier id : block.styles)\n\t\t\t\tpostCheckStyleId(id);\n\t\t}\n\t}\n\n\tprivate void postCheckStyleId (StyleIdentifier styleId) {\n\t\tif (styleId.name.contains(\" \")) throwContainsSpaceException(styleId);\n\n\t\tfor (Identifier id : styleId.content) {\n\t\t\tpostCheckId(id);\n\t\t}\n\t}\n\n\tprivate void postCheckId (Identifier id) {\n\t\tif (id instanceof BasicIdentifier) {\n\t\t\tBasicIdentifier bid = (BasicIdentifier) id;\n\t\t\tif (bid.name.contains(\" \") || bid.content.contains(\" \")) throwContainsSpaceException(bid);\n\t\t}\n\n\t\tif (id instanceof GroupIdentifier) {\n\t\t\tGroupIdentifier gid = (GroupIdentifier) id;\n\t\t\tif (gid.name.contains(\" \")) throwContainsSpaceException(gid);\n\n\t\t\tfor (Identifier gidId : gid.content)\n\t\t\t\tpostCheckId(gidId);\n\t\t}\n\t}\n\n\tprivate void throwContainsSpaceException (BasicIdentifier id) {\n\t\tthrow new USLException(\"Identifier contains illegal space in name or content. Name: '\" + id.name + \"', content: '\" + id.content + \"'\");\n\t}\n\n\tprivate void throwContainsSpaceException (GroupIdentifier groupId) {\n\t\tString content = null;\n\t\tfor (Identifier id : groupId.content) {\n\t\t\tcontent += id.name + \":..., \";\n\t\t}\n\t\tthrow new USLException(\"Identifier contains illegal space in name or content. Name: '\" + groupId.name + \"', content: '\" + content + \"'\");\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/StyleMerger.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl;\n\nimport com.kotcrab.vis.usl.lang.GroupIdentifier;\nimport com.kotcrab.vis.usl.lang.Identifier;\nimport com.kotcrab.vis.usl.lang.StyleBlock;\nimport com.kotcrab.vis.usl.lang.StyleIdentifier;\n\nimport java.util.ArrayList;\n\n/** Performs styles mering during USL parsing. */\npublic class StyleMerger {\n\tprivate ArrayList<StyleIdentifier> globalStyles;\n\tprivate ArrayList<StyleBlock> styleBlocks;\n\tprivate ArrayList<StyleBlock> styleBlocksOverride;\n\n\tpublic StyleMerger (ArrayList<StyleIdentifier> globalStyles, ArrayList<StyleBlock> styleBlocks, ArrayList<StyleBlock> styleBlocksOverride) {\n\t\tthis.globalStyles = globalStyles;\n\t\tthis.styleBlocks = styleBlocks;\n\t\tthis.styleBlocksOverride = styleBlocksOverride;\n\t}\n\n\tpublic ArrayList<StyleBlock> merge () {\n\t\tmergeBlocksOverrides();\n\t\tmergeGlobalStyles();\n\n\t\tfor (StyleBlock block : styleBlocks) {\n\t\t\t//merge 'style a extends style b'\n\t\t\tif (block.extendsStyle != null) mergeBlocksExtends(block, block.extendsStyle);\n\n\t\t\t//merge inner styles\n\t\t\tfor (StyleIdentifier baseStyle : block.styles) {\n\t\t\t\tfor (String inherit : baseStyle.inherits) {\n\t\t\t\t\tif (inherit.startsWith(\".\")) continue; //global styles was already merged at this point\n\t\t\t\t\tStyleIdentifier styleToBeMerged = findStyle(block.styles, inherit);\n\n\t\t\t\t\tif (styleToBeMerged == null)\n\t\t\t\t\t\tthrow new USLException(\"Style to inherit: '\" + inherit + \"' not found, block: \" + block.fullName);\n\n\t\t\t\t\tmergeStylesContent(styleToBeMerged, baseStyle);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn styleBlocks;\n\t}\n\n\tprivate void mergeBlocksOverrides () {\n\t\tfor (StyleBlock overrider : styleBlocksOverride) {\n\t\t\tStyleBlock mergeTarget = findBlock(styleBlocks, overrider.fullName);\n\n\t\t\tfor (StyleIdentifier styleToBeMerged : overrider.styles) {\n\t\t\t\tStyleIdentifier mergeTargetStyle = findStyle(mergeTarget.styles, styleToBeMerged.name);\n\n\t\t\t\tif (mergeTargetStyle != null) {\n\t\t\t\t\tSystem.out.println(\"Warn: overriding existing super style inside block: '\" + overrider.fullName + \"', style: '\" + mergeTargetStyle.name + \"'\");\n\t\t\t\t\tmergeTarget.styles.remove(mergeTargetStyle);\n\t\t\t\t}\n\n\t\t\t\tmergeTarget.styles.add(styleToBeMerged);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void mergeGlobalStyles () {\n\t\tfor (StyleBlock block : styleBlocks) {\n\t\t\tfor (StyleIdentifier style : block.styles) {\n\t\t\t\tmergeGlobalStyles(block.fullName, style.inherits, style.content);\n\t\t\t\tfor (String inherit : style.inherits) {\n\t\t\t\t\tif (inherit.startsWith(\".\")) {\n\t\t\t\t\t\tStyleIdentifier styleToInherit = findStyle(globalStyles, inherit);\n\n\t\t\t\t\t\tif (styleToInherit == null) {\n\t\t\t\t\t\t\tthrow new USLException(\"Style to inherit: '\" + inherit + \"' not found, block: \" + block.fullName);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor (Identifier id : styleToInherit.content) {\n\t\t\t\t\t\t\tif (findIdentifier(style.content, id.name) == null)\n\t\t\t\t\t\t\t\tstyle.content.add(id);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (StyleBlock block : styleBlocks) {\n\t\t\tfor (StyleIdentifier style : block.styles) {\n\t\t\t\tmergeGlobalStylesForIds(block.fullName, style.content);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void mergeGlobalStylesForIds (String blockName, ArrayList<Identifier> content) {\n\t\tfor (Identifier id : content) {\n\t\t\tif (id instanceof GroupIdentifier) {\n\t\t\t\tGroupIdentifier gid = (GroupIdentifier) id;\n\t\t\t\tmergeGlobalStyles(blockName, gid.inherits, gid.content);\n\t\t\t\tmergeGlobalStylesForIds(blockName, gid.content);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void mergeGlobalStyles (String blockName, ArrayList<String> inherits, ArrayList<Identifier> content) {\n\t\tfor (String inherit : inherits) {\n\t\t\tif (inherit.startsWith(\".\")) {\n\t\t\t\tStyleIdentifier styleToInherit = findStyle(globalStyles, inherit);\n\n\t\t\t\tif (styleToInherit == null) {\n\t\t\t\t\tthrow new USLException(\"Style to inherit: '\" + inherit + \"' not found, block: \" + blockName);\n\t\t\t\t}\n\n\t\t\t\tfor (Identifier id : styleToInherit.content) {\n\t\t\t\t\tif (findIdentifier(content, id.name) == null) {\n\t\t\t\t\t\tcontent.add(id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void mergeBlocksExtends (StyleBlock mergeTarget, StyleBlock blockToMerge) {\n\t\tif (blockToMerge.extendsStyle != null) mergeBlocksExtends(mergeTarget, blockToMerge.extendsStyle);\n\n\t\tfor (StyleIdentifier styleToBeMerged : blockToMerge.styles) {\n\t\t\tStyleIdentifier mergeTargetStyle = findStyle(mergeTarget.styles, styleToBeMerged.name);\n\n\t\t\tif (mergeTargetStyle != null)\n\t\t\t\tmergeStyles(styleToBeMerged, mergeTargetStyle);\n\t\t\telse if (mergeTarget.extendsInheritOnlyDefinedStyles == false)\n\t\t\t\tmergeTarget.styles.add(new StyleIdentifier(styleToBeMerged));\n\t\t}\n\t}\n\n\tprivate void mergeStyles (StyleIdentifier styleToBeMerge, StyleIdentifier mergeTargetStyle) {\n\t\tfor (String inherit : styleToBeMerge.inherits)\n\t\t\tif (mergeTargetStyle.inherits.contains(inherit) == false) mergeTargetStyle.inherits.add(inherit);\n\n\t\tmergeStylesContent(styleToBeMerge, mergeTargetStyle);\n\t}\n\n\tprivate void mergeStylesContent (StyleIdentifier styleToBeMerged, StyleIdentifier mergeTargetStyle) {\n\t\tfor (Identifier id : styleToBeMerged.content) {\n\t\t\tif (findIdentifier(mergeTargetStyle.content, id.name) == null) //mergeTargetStyle.content.remove(id);\n\t\t\t\tmergeTargetStyle.content.add(id);\n\t\t}\n\t}\n\n\tprivate StyleBlock findBlock (ArrayList<StyleBlock> target, String fullName) {\n\t\tfor (StyleBlock block : target)\n\t\t\tif (block.fullName.equals(fullName)) return block;\n\n\t\tthrow new USLException(\"Block '\" + fullName + \"' not found\");\n\t}\n\n\tprivate StyleIdentifier findStyle (ArrayList<StyleIdentifier> target, String name) {\n\t\tfor (StyleIdentifier style : target)\n\t\t\tif (style.name.equals(name)) return style;\n\n\t\treturn null;\n\t}\n\n\tprivate Identifier findIdentifier (ArrayList<? extends Identifier> target, String name) {\n\t\tfor (Identifier identifier : target)\n\t\t\tif (identifier.name.equals(name)) return identifier;\n\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/Token.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl;\n\n/** Single token of USL file */\npublic class Token {\n\tpublic String usl;\n\tpublic int i;\n\n\tpublic Type type;\n\tpublic String content;\n\n\tpublic Token (String usl, int i, Type type) {\n\t\tthis.usl = usl;\n\t\tthis.i = i;\n\t\tthis.type = type;\n\t}\n\n\tpublic Token (String usl, int i, Type type, String content) {\n\t\tthis.usl = usl;\n\t\tthis.i = i;\n\t\tthis.type = type;\n\t\tthis.content = content;\n\t}\n\n\tpublic enum Type {\n\t\tINVALID,\n\t\tLCURL, RCURL, // { }\n\t\tSTYLE_BLOCK, STYLE_BLOCK_EXTENDS,\n\t\tSTYLE_BLOCK_OVERRIDE,\n\t\tGLOBAL_STYLE, PACKAGE,\n\t\tIDENTIFIER, IDENTIFIER_CONTENT,\n\t\tINHERITS, INHERITS_NAME,\n\t\tMETA_STYLE\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/USL.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl;\n\nimport java.io.File;\n\n/** Allows to use USL from code. */\npublic class USL {\n\tprivate static final String USER_HOME_PATH = System.getProperty(\"user.home\") + File.separator;\n\tpublic static final String USL_FOLDER_PATH = USER_HOME_PATH + \".usl\" + File.separator;\n\tpublic static final String CACHE_FOLDER_PATH = USL_FOLDER_PATH + \"cache\" + File.separator;\n\tpublic static final String TMP_FOLDER_PATH = USL_FOLDER_PATH + \"tmp\" + File.separator;\n\n\tpublic static String parse (File uslFile) {\n\t\treturn parse(uslFile.getParentFile(), Utils.readFile(uslFile));\n\t}\n\n\t/**\n\t * @param workingDirectory used for finding included files, may be null only if parsed string does not contains\n\t * any file include directive. However 'include <gdx>' or 'include <visui>' is always allowed even when workingDirectory\n\t * is null.\n\t */\n\tpublic static String parse (File workingDirectory, String usl) {\n\t\tLexerContext context = new LexerContext(workingDirectory);\n\t\tLexer.lexUsl(context, usl);\n\t\treturn new Parser().getJson(context.tokens);\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/USLException.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl;\n\n/** Exception that is thrown when USL file parsing fails */\npublic class USLException extends RuntimeException {\n\tpublic USLException (String message) {\n\t\tsuper(message);\n\t}\n\n\tpublic USLException (Throwable cause) {\n\t\tsuper(cause);\n\t}\n\n\tpublic USLException (String message, Throwable cause) {\n\t\tsuper(message, cause);\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/USLJsonWriter.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl;\n\nimport com.kotcrab.vis.usl.lang.*;\n\nimport java.util.ArrayList;\n\n/** Converts list of blocks created by {@link Parser} into json string */\npublic class USLJsonWriter {\n\tprivate ArrayList<StyleBlock> styleBlocks;\n\n\tprivate StringBuilder out;\n\n\tpublic USLJsonWriter (ArrayList<StyleBlock> mergedStyleBlocks) {\n\t\tout = new StringBuilder();\n\t\tstyleBlocks = mergedStyleBlocks;\n\t}\n\n\tpublic String getJson () {\n\t\tout.append(\"{\\n\");\n\n\t\tfor (int i = 0; i < styleBlocks.size(); i++) {\n\t\t\tStyleBlock block = styleBlocks.get(i);\n\t\t\tout.append(block.fullName).append(\": {\\n\");\n\n\t\t\tArrayList<StyleIdentifier> styles = block.styles;\n\t\t\tfor (int j = 0; j < styles.size(); j++) {\n\t\t\t\tStyleIdentifier style = styles.get(j);\n\t\t\t\tif (style.metaStyle) continue;\n\n\t\t\t\tout.append(\"\\t\").append(style.name).append(\": \");\n\t\t\t\tif (style.content.size() == 1 && style.content.get(0) instanceof AliasIdentifier) {\n\t\t\t\t\twriteIdentifiers(style.content);\n\t\t\t\t} else {\n\t\t\t\t\tout.append(\"{\");\n\t\t\t\t\twriteIdentifiers(style.content);\n\t\t\t\t\tout.append(\" }\");\n\t\t\t\t}\n\n\t\t\t\tif (j == styles.size() - 1) {\n\t\t\t\t\tout.append(\"\\n\");\n\t\t\t\t} else {\n\t\t\t\t\tout.append(\",\\n\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (i == styleBlocks.size() - 1) {\n\t\t\t\tout.append(\"}\\n\");\n\t\t\t} else {\n\t\t\t\tout.append(\"},\\n\");\n\t\t\t}\n\n\t\t}\n\n\t\tout.append(\"\\n}\");\n\t\treturn out.toString();\n\t}\n\n\tprivate void writeIdentifiers (ArrayList<Identifier> content) {\n\t\tfor (int i = 0; i < content.size(); i++) {\n\t\t\tIdentifier id = content.get(i);\n\t\t\tif (id instanceof BasicIdentifier) {\n\t\t\t\tBasicIdentifier bid = (BasicIdentifier) id;\n\t\t\t\tif (bid.content.equals(\"NULL\")) continue;\n\t\t\t\tout.append(bid.name).append(\": \").append(bid.content);\n\t\t\t} else if (id instanceof GroupIdentifier) {\n\t\t\t\tGroupIdentifier gid = (GroupIdentifier) id;\n\t\t\t\tout.append(gid.name).append(\": {\");\n\t\t\t\twriteIdentifiers(gid.content);\n\t\t\t\tout.append(\"}\");\n\t\t\t} else if (id instanceof AliasIdentifier) {\n\t\t\t\tout.append(id.name);\n\t\t\t}\n\n\t\t\tif (i != content.size() - 1) {\n\t\t\t\tout.append(\", \");\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/Utils.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.nio.file.Files;\n\n/** Various utilises */\npublic class Utils {\n\tstatic String readFile (File file) {\n\t\ttry {\n\t\t\tbyte[] encoded = Files.readAllBytes(file.toPath());\n\t\t\treturn new String(encoded, StandardCharsets.UTF_8);\n\t\t} catch (IOException e) {\n\t\t\tthrow new IllegalStateException(\"Reading file '\" + file.getPath() + \"' failed!\", e);\n\t\t}\n\t}\n\n\tstatic void throwException (String exception, Token token) {\n\t\tthrowException(exception, token.usl, token.i);\n\t}\n\n\tstatic void throwException (String exception, String usl, int i) {\n\t\tthrow new USLException(exception + \" \" + \"(line \" + Utils.countLines(usl.substring(0, i)) + \")\");\n\t}\n\n\tstatic int countLines (String str) {\n\t\tif (str == null || str.isEmpty()) return 0;\n\n\t\tint lines = 1;\n\t\tint pos = 0;\n\t\twhile ((pos = str.indexOf(\"\\n\", pos) + 1) != 0) {\n\t\t\tlines++;\n\t\t}\n\n\t\treturn lines;\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/lang/AliasIdentifier.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl.lang;\n\n/** @author Kotcrab */\npublic class AliasIdentifier extends Identifier {\n\tpublic AliasIdentifier (String name) {\n\t\tsuper(name);\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/lang/BasicIdentifier.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl.lang;\n\n/** Represents single identifier of USL lang, similar to json: \"name: value\" */\npublic class BasicIdentifier extends Identifier {\n\tpublic String content;\n\n\tpublic BasicIdentifier () {\n\t}\n\n\tpublic BasicIdentifier (String name, String content) {\n\t\tsuper(name);\n\t\tthis.content = content;\n\t}\n\n\tpublic BasicIdentifier (BasicIdentifier other) {\n\t\tsuper(other);\n\t\tthis.content = other.content;\n\t}\n\n\t@Override\n\tpublic boolean equals (Object o) {\n\t\tif (this == o) return true;\n\t\tif (o == null || getClass() != o.getClass()) return false;\n\t\tif (!super.equals(o)) return false;\n\n\t\tBasicIdentifier that = (BasicIdentifier) o;\n\n\t\treturn content.equals(that.content);\n\n\t}\n\n\t@Override\n\tpublic int hashCode () {\n\t\tint result = super.hashCode();\n\t\tresult = 31 * result + content.hashCode();\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/lang/GroupIdentifier.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl.lang;\n\nimport com.kotcrab.vis.usl.CollectionUtils;\n\nimport java.util.ArrayList;\n\n/** Represents group identifier of USL lang */\npublic class GroupIdentifier extends Identifier {\n\tpublic ArrayList<String> inherits = new ArrayList<String>();\n\tpublic ArrayList<Identifier> content = new ArrayList<Identifier>();\n\n\tpublic GroupIdentifier () {\n\t}\n\n\tpublic GroupIdentifier (GroupIdentifier other) {\n\t\tsuper(other);\n\t\tthis.inherits = new ArrayList<String>(other.inherits);\n\n\t\tfor (Identifier id : other.content) {\n\t\t\tif (id instanceof BasicIdentifier)\n\t\t\t\tthis.content.add(new BasicIdentifier((BasicIdentifier) id));\n\n\t\t\tif (id instanceof GroupIdentifier)\n\t\t\t\tthis.content.add(new GroupIdentifier((GroupIdentifier) id));\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean equals (Object o) {\n\t\tif (this == o) return true;\n\t\tif (o == null || getClass() != o.getClass()) return false;\n\t\tif (!super.equals(o)) return false;\n\n\t\tGroupIdentifier that = (GroupIdentifier) o;\n\n\t\tif (!CollectionUtils.isEqualCollection(inherits, that.inherits)) return false;\n\t\treturn CollectionUtils.isEqualCollection(content, that.content);\n\n\t}\n\n\t@Override\n\tpublic int hashCode () {\n\t\tint result = super.hashCode();\n\t\tresult = 31 * result + inherits.hashCode();\n\t\tresult = 31 * result + content.hashCode();\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/lang/Identifier.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl.lang;\n\n/** Represents identifier of USL lang, see subclasses. */\npublic abstract class Identifier {\n\tpublic String name;\n\n\tpublic Identifier () {\n\t}\n\n\tpublic Identifier (String name) {\n\t\tthis.name = name;\n\t}\n\n\tpublic Identifier (Identifier other) {\n\t\tthis.name = other.name;\n\t}\n\n\t@Override\n\tpublic boolean equals (Object o) {\n\t\tif (this == o) return true;\n\t\tif (o == null || getClass() != o.getClass()) return false;\n\n\t\tIdentifier that = (Identifier) o;\n\n\t\treturn name.equals(that.name);\n\n\t}\n\n\t@Override\n\tpublic int hashCode () {\n\t\treturn name.hashCode();\n\t}\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/lang/StyleBlock.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl.lang;\n\nimport java.util.ArrayList;\n\n/** Represents StyleBlock in USL file */\npublic class StyleBlock {\n\tpublic String fullName;\n\tpublic StyleBlock extendsStyle;\n\tpublic boolean extendsInheritOnlyDefinedStyles;\n\tpublic ArrayList<StyleIdentifier> styles = new ArrayList<StyleIdentifier>();\n}\n"
  },
  {
    "path": "usl/src/main/java/com/kotcrab/vis/usl/lang/StyleIdentifier.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl.lang;\n\n/** Represents style identifier of USL lang */\npublic class StyleIdentifier extends GroupIdentifier {\n\tpublic boolean metaStyle;\n\n\tpublic StyleIdentifier () {\n\t}\n\n\tpublic StyleIdentifier (StyleIdentifier other) {\n\t\tsuper(other);\n\t\tthis.metaStyle = other.metaStyle;\n\t}\n\n\t@Override\n\tpublic boolean equals (Object o) {\n\t\tif (this == o) return true;\n\t\tif (o == null || getClass() != o.getClass()) return false;\n\t\tif (!super.equals(o)) return false;\n\n\t\tStyleIdentifier that = (StyleIdentifier) o;\n\n\t\treturn metaStyle == that.metaStyle;\n\n\t}\n\n\t@Override\n\tpublic int hashCode () {\n\t\tint result = super.hashCode();\n\t\tresult = 31 * result + (metaStyle ? 1 : 0);\n\t\treturn result;\n\t}\n}\n"
  },
  {
    "path": "usl/src/test/java/com/kotcrab/vis/usl/test/RemoteTest.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl.test;\n\nimport com.kotcrab.vis.usl.USL;\nimport org.junit.Ignore;\nimport org.junit.Test;\n\npublic class RemoteTest {\n\t@Ignore\n\t@Test\n\tpublic void testRemote () throws Exception {\n\t\tUSL.parse(null, \"include <visui-0.7.7>\");\n\t\tUSL.parse(null, \"include <visui-0.8.0>\");\n\t\tUSL.parse(null, \"include <visui-0.8.1>\");\n\t}\n}\n"
  },
  {
    "path": "usl/src/test/java/com/kotcrab/vis/usl/test/TemplateBasedParserTest.java",
    "content": "/*\n * Copyright 2014-2017 See AUTHORS file.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.kotcrab.vis.usl.test;\n\nimport com.kotcrab.vis.usl.USL;\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.util.Scanner;\n\npublic class TemplateBasedParserTest {\n\t@Test\n\tpublic void testParserUsingVisUITemplate () throws Exception {\n\t\ttestUsingTemplate(\"/test-visui.usl\", \"/test-visui-expected.json\");\n\t}\n\n\t@Test\n\tpublic void testParserUsingGdxTemplate () throws Exception {\n\t\ttestUsingTemplate(\"/test-gdx.usl\", \"/test-gdx-expected.json\");\n\t}\n\n\t@Test\n\tpublic void testParserUsingTintedTemplate () throws Exception {\n\t\ttestUsingTemplate(\"/test-tinted.usl\", \"/test-tinted-expected.json\");\n\t}\n\n\t@Test\n\tpublic void testParserAlias () throws Exception {\n\t\ttestUsingTemplate(\"/test-alias.usl\", \"/test-alias-expected.json\");\n\t}\n\n\t@Test\n\tpublic void testParserComments () throws Exception {\n\t\ttestUsingTemplate(\"/test-comments.usl\", \"/test-comments-expected.json\");\n\t}\n\n\t@Test\n\tpublic void testMinus () throws Exception {\n\t\ttestUsingTemplate(\"/test-minus.usl\", \"/test-minus-expected.json\");\n\t}\n\n\tprivate void testUsingTemplate (String uslPath, String jsonPath) throws Exception {\n\t\tString expected = readFile(jsonPath);\n\t\tString result = USL.parse(null, readFile(uslPath));\n\t\tcompareResult(expected, result);\n\t}\n\n\tprivate void compareResult (String expectedJson, String resultJson) {\n\t\tString[] expected = expectedJson.replace(\"\\r\\n\", \"\\n\").split(\"\\n\");\n\t\tString[] result = resultJson.replace(\"\\r\\n\", \"\\n\").split(\"\\n\");\n\n\t\tfor (int i = 0; i < expected.length; i++) {\n\t\t\tif (i >= result.length) {\n\t\t\t\tthrow new IllegalStateException(\"Unexpected end of result string at line \" + (i + 1));\n\t\t\t}\n\n\t\t\tAssert.assertEquals(\"Json mismatch at line \" + (i + 1), expected[i], result[i]);\n\t\t}\n\t}\n\n\tprivate String readFile (String path) throws IOException {\n\t\treturn new Scanner(TemplateBasedParserTest.class.getResourceAsStream(path), \"UTF-8\").useDelimiter(\"\\\\A\").next();\n\t}\n}\n"
  },
  {
    "path": "usl/src/test/resources/test-alias-expected.json",
    "content": "{\ncom.badlogic.gdx.graphics.Color: {\n\tgreen: {a: 1, b: 0, g: 1, r: 0 },\n\tgreen-alias: green\n}\n\n}\n"
  },
  {
    "path": "usl/src/test/resources/test-alias.usl",
    "content": "#com.badlogic.gdx.graphics.Color: {\n    green: {a: 1, b: 0, g: 1, r: 0 }\n    green-alias: green\n}\n"
  },
  {
    "path": "usl/src/test/resources/test-comments-expected.json",
    "content": "{\ncom.badlogic.gdx.graphics.Color: {\n\tgreen: {a: 1, b: 0, g: 1, r: 0 },\n\tgreen-alias: green\n},\ncom.Test: {\n\tgreen: {a: 1, b: 0, g: 1, r: 0 }\n},\nSkin$TintedDrawable: {\n\tdialogDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.45} }\n},\nSkin$TintedDrawable2: {\n\tdialogDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.45} }\n}\n\n}\n"
  },
  {
    "path": "usl/src/test/resources/test-comments.usl",
    "content": "//header\n#com.badlogic.gdx.graphics.Color: { //after block end\n    //block header\n    green: {a: 1, b: 0, g: 1, r: 0 } //after identifier block\n    green-alias: green //after alias\n}\n//footer\n\n#com.Test: {\n    green: //after block id\n            {a: 1, b: 0, //inside identifier\n            //new line inside identifier\n            g: 1, r: 0\n            //new line before identifier end\n            }\n}\n\n\n#Skin$TintedDrawable: {\n\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a:\n\t //between identifier id and content\n\t0.45\n\t //double nested\n\t}\n\t //nested\n\t}\n}\n\n#Skin$TintedDrawable2: {\n\tdialogDim: { name: white, color:\n\t //between identifier id and content block\n\t{ r: 0, g: 0, b: 0, a: 0.45 } }\n}\n"
  },
  {
    "path": "usl/src/test/resources/test-gdx-expected.json",
    "content": "{\ncom.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: {file: default.fnt }\n},\ncom.badlogic.gdx.graphics.Color: {\n\tgreen: {a: 1, b: 0, g: 1, r: 0 },\n\twhite: {a: 1, b: 1, g: 1, r: 1 },\n\tred: {a: 1, b: 0, g: 0, r: 1 },\n\tblack: {a: 1, b: 0, g: 0, r: 0 }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable: {\n\tdialogDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.45} }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: {\n\tdefault: {down: default-round-down, up: default-round },\n\ttoggle: {checked: default-round-down, down: default-round-down, up: default-round }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: {\n\tdefault: {down: default-round-down, up: default-round, font: default-font, fontColor: white },\n\ttoggle: {checked: default-round-down, downFontColor: red, down: default-round-down, up: default-round, font: default-font, fontColor: white }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ScrollPane$ScrollPaneStyle: {\n\tdefault: {vScroll: default-scroll, hScrollKnob: default-round-large, background: default-rect, hScroll: default-scroll, vScrollKnob: default-round-large }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.SelectBox$SelectBoxStyle: {\n\tdefault: {font: default-font, fontColor: white, background: default-select, scrollStyle: default, listStyle: {font: default-font, selection: default-select-selection} }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.SplitPane$SplitPaneStyle: {\n\tdefault-vertical: {handle: default-splitpane-vertical },\n\tdefault-horizontal: {handle: default-splitpane }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Window$WindowStyle: {\n\tdefault: {titleFont: default-font, background: default-window, titleFontColor: white },\n\tdialog: {stageBackground: dialogDim, titleFont: default-font, background: default-window, titleFontColor: white }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle: {\n\tdefault-horizontal: {background: default-slider, knob: default-slider-knob }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {\n\tdefault: {font: default-font, fontColor: white }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextField$TextFieldStyle: {\n\tdefault: {selection: selection, background: textfield, font: default-font, fontColor: white, cursor: cursor }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.CheckBox$CheckBoxStyle: {\n\tdefault: {checkboxOn: check-on, checkboxOff: check-off, font: default-font, fontColor: white }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.List$ListStyle: {\n\tdefault: {fontColorUnselected: white, selection: selection, fontColorSelected: white, font: default-font }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Touchpad$TouchpadStyle: {\n\tdefault: {background: default-pane, knob: default-round-large }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Tree$TreeStyle: {\n\tdefault: {minus: tree-minus, plus: tree-plus, selection: default-select-selection }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextTooltip$TextTooltipStyle: {\n\tdefault: {background: default-pane, label: {font: default-font, fontColor: white} }\n}\n\n}"
  },
  {
    "path": "usl/src/test/resources/test-gdx.usl",
    "content": "//This is test file used to verify that USL parser is working correctly\n//DO NOT USE THIS FILE AS YOUR BASE FOR USL SKIN - look at directory usl/styles\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: { default-font: { file: default.fnt } }\n#com.badlogic.gdx.graphics.Color: {\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n}\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: default-round-down, up: default-round }\n\t\ttoggle inherits default: { checked: default-round-down }\n\t}\n\n\t#TextButton$TextButtonStyle: {\n\t\tdefault: { down: default-round-down, up: default-round, font: default-font, fontColor: white }\n\t\ttoggle inherits default: { checked: default-round-down, downFontColor: red }\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tdefault: { vScroll: default-scroll, hScrollKnob: default-round-large, background: default-rect, hScroll: default-scroll, vScrollKnob: default-round-large }\n\t}\n\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault: {\n\t\t\tfont: default-font, fontColor: white, background: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: default-select-selection }\n\t\t}\n\t}\n\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: default-splitpane-vertical }\n\t\tdefault-horizontal: { handle: default-splitpane }\n\t}\n\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: default-window, titleFontColor: white }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\n\t#Slider$SliderStyle: {\n\t\tdefault-horizontal: { background: default-slider, knob: default-slider-knob }\n\t}\n\n\t#Label$LabelStyle: {\n\t\tdefault: { font: default-font, fontColor: white }\n\t}\n\n\t#TextField$TextFieldStyle: {\n\t\tdefault: { selection: selection, background: textfield, font: default-font, fontColor: white, cursor: cursor }\n\t}\n\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault: { checkboxOn: check-on, checkboxOff: check-off, font: default-font, fontColor: white }\n\t}\n\n\t#List$ListStyle: {\n\t\tdefault: { fontColorUnselected: white, selection: selection, fontColorSelected: white, font: default-font }\n\t}\n\n\t#Touchpad$TouchpadStyle: {\n\t\tdefault: { background: default-pane, knob: default-round-large }\n\t}\n\n\t#Tree$TreeStyle: {\n\t\tdefault: { minus: tree-minus, plus: tree-plus, selection: default-select-selection }\n\t}\n\n\t#TextTooltip$TextTooltipStyle: {\n        default: {\n            background: default-pane,\n            label: { font: default-font, fontColor: white }\n        }\n    }\n}\n"
  },
  {
    "path": "usl/src/test/resources/test-minus-expected.json",
    "content": "{\nfoo.Bar: {\n\tdefault: {foo: 1, bar: -1 }\n}\n\n}\n"
  },
  {
    "path": "usl/src/test/resources/test-minus.usl",
    "content": "#foo.Bar: {\n    default: {foo: 1, bar: -1 }\n}\n"
  },
  {
    "path": "usl/src/test/resources/test-tinted-expected.json",
    "content": "{\ncom.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: {file: default.fnt },\n\tsmall-font: {file: font-small.fnt }\n},\ncom.badlogic.gdx.graphics.Color: {\n\tgreen: {a: 1, b: 0, g: 1, r: 0 },\n\tred: {a: 1, b: 0, g: 0, r: 1 },\n\tblue: {a: 1, b: 1, g: 0, r: 0 },\n\tt-white: {r: 1, g: 1, b: 1, a: 1 },\n\tt-black: {r: 0, g: 0, b: 0, a: 1 },\n\tt-highlight: {r: 0.85, g: 0.5, b: 0.05, a: 1 },\n\tt-highlight-medium: {r: 0.7, g: 0.4, b: 0, a: 1 },\n\tt-highlight-dark: {r: 0.6, g: 0.3, b: 0, a: 1 },\n\tt-warn: {r: 1, g: 0, b: 0, a: 1 },\n\tt-light: {r: 0.4, g: 0.4, b: 0.4, a: 1 },\n\tt-medium: {r: 0.2, g: 0.2, b: 0.2, a: 1 },\n\tt-medium-dark: {r: 0.15, g: 0.15, b: 0.15, a: 1 },\n\tt-dark: {r: 0.1, g: 0.1, b: 0.1, a: 1 },\n\tt-alpha: {r: 0, g: 0, b: 0, a: 0.5 },\n\tblack: t-black,\n\twhite: t-white,\n\tgrey: t-light,\n\tvis-blue: t-highlight,\n\tvis-red: t-warn,\n\tmenuitem: t-medium-dark,\n\tlink-label: t-highlight\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable: {\n\tdialogDim: {name: t-dot, color: t-alpha },\n\tborder: {name: t-border, color: t-highlight },\n\tborder-circle: {name: t-border-circle, color: t-highlight },\n\tborder-circle-error: {name: t-border-circle, color: t-warn },\n\tborder-dark-blue: {name: t-border, color: t-highlight-dark },\n\tborder-error: {name: t-border, color: t-warn },\n\tbutton: {name: t-base, color: t-medium },\n\tbutton-blue: {name: t-base, color: t-highlight },\n\tbutton-blue-down: {name: t-base, color: t-highlight-dark },\n\tbutton-blue-over: {name: t-base, color: t-highlight-medium },\n\tbutton-down: {name: t-base, color: t-highlight },\n\tbutton-over: {name: t-base, color: t-light },\n\tbutton-red: {name: t-base, color: t-warn },\n\tbutton-window-bg: {name: t-base, color: t-dark },\n\tcheck-down: {name: t-check-off, color: t-highlight },\n\tcheck-down-on: {name: t-check-on, color: t-highlight },\n\tcheck-off: {name: t-check-off, color: t-medium },\n\tcheck-off-disabled: {name: t-check-off, color: t-medium },\n\tcheck-on: {name: t-check-on, color: t-medium },\n\tcheck-on-disabled: {name: t-check-on, color: t-medium },\n\tcheck-over-off: {name: t-check-off, color: t-light },\n\tcheck-over-on: {name: t-check-on, color: t-light },\n\tdefault-pane: {name: t-dot, color: t-medium },\n\tdefault-pane-noborder: {name: t-dot, color: t-medium },\n\tdefault-select: {name: t-select, color: t-medium },\n\tdefault-select-selection: {name: t-dot, color: t-highlight-medium },\n\tgrey: {name: t-dot, color: t-medium },\n\tlist-selection: {name: t-dot, color: t-highlight },\n\tmenu-bg: {name: t-dot, color: t-medium-dark },\n\tpadded-list-selection: {name: t-hline, color: t-highlight },\n\tprogressbar: {name: t-vline, color: t-medium },\n\tprogressbar-filled: {name: t-vline, color: t-highlight },\n\tprogressbar-filled-vertical: {name: t-hline, color: t-highlight },\n\tprogressbar-vertical: {name: t-hline, color: t-medium },\n\tradio-down: {name: t-radio-off, color: t-highlight },\n\tradio-down-on: {name: t-radio-on, color: t-highlight },\n\tradio-off: {name: t-radio-off, color: t-medium },\n\tradio-off-disabled: {name: t-radio-off, color: t-medium-dark },\n\tradio-on: {name: t-radio-on, color: t-medium },\n\tradio-on-disabled: {name: t-radio-on, color: t-medium-dark },\n\tradio-over-off: {name: t-radio-off, color: t-light },\n\tradio-over-on: {name: t-radio-on, color: t-light },\n\tscroll: {name: t-hline, color: t-medium },\n\tscroll-horizontal: {name: t-vline, color: t-medium },\n\tscroll-knob-horizontal: {name: t-hknob, color: t-dark },\n\tscroll-knob-vertical: {name: t-vknob, color: t-dark },\n\tselect-box-list-bg: {name: t-dot, color: t-medium },\n\tselect-down: {name: t-select-down, color: t-light },\n\tselection: {name: t-dot, color: t-highlight-dark },\n\tselect-up: {name: t-select-up, color: t-light },\n\tseparator: {name: t-dot, color: t-light },\n\tseparator-menu: {name: t-dot, color: t-medium },\n\tslider: {name: t-hslider, color: t-medium-dark },\n\tslider-knob: {name: t-base, color: t-medium },\n\tslider-knob-disabled: {name: t-base, color: t-medium-dark },\n\tslider-knob-down: {name: t-base, color: t-highlight },\n\tslider-knob-over: {name: t-base, color: t-light },\n\tslider-vertical: {name: t-vslider, color: t-medium-dark },\n\tsplitpane: {name: t-vslider, color: t-medium-dark },\n\tsplitpane-over: {name: t-vslider, color: t-light },\n\tsplitpane-vertical: {name: t-hslider, color: t-medium-dark },\n\tsplitpane-vertical-over: {name: t-hslider, color: t-light },\n\tsub-menu: {name: t-tree-plus, color: t-light },\n\ttextfield: {name: t-base, color: t-medium },\n\ttextfield-over: {name: t-base, color: t-medium-dark },\n\ttooltip-bg: {name: t-dot, color: t-medium-dark },\n\ttouchpad-knob: {name: t-radio-off, color: t-highlight },\n\ttree-minus: {name: t-tree-minus, color: t-light },\n\ttree-over: {name: t-dot, color: t-medium-dark },\n\ttree-plus: {name: t-tree-plus, color: t-light },\n\ttree-selection: {name: t-dot, color: t-highlight },\n\tvis-blue: {name: t-dot, color: t-highlight },\n\tvis-red: {name: t-dot, color: t-warn },\n\twhite: {name: t-dot, color: white },\n\twindow: {name: t-window, color: t-dark },\n\twindow-bg: {name: t-dot, color: t-dark },\n\twindow-noborder: {name: t-window-border, color: t-dark },\n\twindow-resizable: {name: t-window-resize, color: t-dark }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: {\n\tdefault: {down: button-down, up: button },\n\tblue: {down: button-blue-down, up: button-blue },\n\ttoggle: {checked: button-down, down: button-down, up: button }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: {\n\tdefault: {over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, down: button-down, up: button },\n\tblue: {over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, down: button-blue-down, up: button-blue },\n\ttoggle: {font: default-font, fontColor: white, checked: button-down, down: button-down, up: button, over: button-over, disabled: button, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ScrollPane$ScrollPaneStyle: {\n\tlist: {vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal },\n\tdefault: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.SelectBox$SelectBoxStyle: {\n\tdefault: {background: default-select, scrollStyle: default, listStyle: {font: default-font, selection: padded-list-selection, background: select-box-list-bg}, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.SplitPane$SplitPaneStyle: {\n\tdefault-vertical: {handle: splitpane-vertical },\n\tdefault-horizontal: {handle: splitpane }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Window$WindowStyle: {\n\tdefault: {titleFont: default-font, background: window, titleFontColor: white },\n\tresizable: {background: window-resizable, titleFont: default-font, titleFontColor: white },\n\tnoborder: {background: window-noborder, titleFont: default-font, titleFontColor: white },\n\tdialog: {stageBackground: dialogDim, titleFont: default-font, background: window, titleFontColor: white }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ProgressBar$ProgressBarStyle: {\n\tdefault-horizontal: {background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled },\n\tdefault-vertical: {background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle: {\n\tdefault-horizontal: {background: slider, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled },\n\tdefault-vertical: {background: slider-vertical, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {\n\tdefault: {font: default-font, fontColor: white },\n\tlink-label: {fontColor: link-label, font: default-font },\n\tsmall: {font: small-font, fontColor: white },\n\tmenuitem-shortcut: {font: default-font, fontColor: menuitem }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextField$TextFieldStyle: {\n\tdefault: {font: default-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey },\n\tsmall: {font: small-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.CheckBox$CheckBoxStyle: {\n\tdefault: {checkboxOn: check-on, checkboxOff: check-off, font: default-font, fontColor: white, disabledFontColor: grey },\n\tradio: {checkboxOn: radio-on, checkboxOff: radio-off, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.List$ListStyle: {\n\tdefault: {fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Touchpad$TouchpadStyle: {\n\tdefault: {background: default-pane, knob: touchpad-knob }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Tree$TreeStyle: {\n\tdefault: {minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextTooltip$TextTooltipStyle: {\n\tdefault: {background: default-pane, label: {font: default-font, fontColor: white} }\n},\ncom.kotcrab.vis.ui.Sizes: {\n\tdefault: {scaleFactor: 1, spacingBottom: 8, spacingRight: 6, buttonBarSpacing: 10, menuItemIconSize: 22, numberSelectorButtonSize: 12, numberSelectorButtonsWidth: 12, numberSelectorFieldSize: 40, numberSelectorFieldRightPadding: 1, spinnerButtonSize: 12, spinnerButtonsWidth: 12, spinnerFieldSize: 40, spinnerFieldRightPadding: 1 },\n\tx2: {scaleFactor: 2, spacingBottom: 8, spacingRight: 6, buttonBarSpacing: 10, menuItemIconSize: 44, numberSelectorButtonSize: 24, numberSelectorButtonsWidth: 20, numberSelectorFieldSize: 80, numberSelectorFieldRightPadding: 5, spinnerButtonSize: 24, spinnerButtonsWidth: 20, spinnerFieldSize: 80, spinnerFieldRightPadding: 5 }\n},\ncom.kotcrab.vis.ui.widget.VisTextField$VisTextFieldStyle: {\n\tdefault: {focusBorder: border, font: default-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, backgroundOver: textfield-over, errorBorder: border-error, cursor: cursor },\n\tsmall: {focusBorder: border, font: small-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, backgroundOver: textfield-over, errorBorder: border-error, cursor: cursor }\n},\ncom.kotcrab.vis.ui.widget.VisTextButton$VisTextButtonStyle: {\n\tdefault: {focusBorder: border, down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle: {focusBorder: border, checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey },\n\tblue: {focusBorder: border-dark-blue, down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\tmenu-bar: {over: button-down, font: default-font, fontColor: white, down: button-down, up: button, disabled: button, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.VisImageButton$VisImageButtonStyle: {\n\tdefault: {down: button-down, up: button, over: button-over, disabled: button, focusBorder: border },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue, focusBorder: border-dark-blue },\n\ttoggle: {checked: button-down, focusBorder: border, down: button-down, up: button, over: button-over, disabled: button },\n\tclose: {down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button },\n\tclose-active-tab: {down: button-red, imageUp: icon-close, up: button-blue, over: button-blue-over, disabled: button-blue },\n\tclose-window: {up: button-window-bg, down: button-red, over: button-over, imageUp: icon-close, disabled: button }\n},\ncom.kotcrab.vis.ui.widget.VisImageTextButton$VisImageTextButtonStyle: {\n\tdefault: {down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, focusBorder: border },\n\ttoggle: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey, focusBorder: border },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, focusBorder: border-dark-blue },\n\tdefault-noborder: {down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle-noborder: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey },\n\tmenu-bar: {over: button-down, font: default-font, fontColor: white, down: button-down, up: button, disabled: button, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.VisCheckBox$VisCheckBoxStyle: {\n\tdefault: {checkboxOver: check-over-off, checkboxOnOver: check-over-on, checkboxOffDown: check-down, checkboxOnDown: check-down-on, checkboxOffDisabled: check-off-disabled, checkboxOnDisabled: check-on-disabled, errorBorder: border-error, focusBorder: border, checkboxOn: check-on, checkboxOff: check-off, font: default-font, fontColor: white, disabledFontColor: grey },\n\tradio: {checkboxOver: radio-over-off, checkboxOnOver: radio-over-on, checkboxOffDown: radio-down, checkboxOnDown: radio-down-on, checkboxOffDisabled: radio-off-disabled, checkboxOnDisabled: radio-on-disabled, errorBorder: border-circle-error, focusBorder: border-circle, checkboxOn: radio-on, checkboxOff: radio-off, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.PopupMenu$PopupMenuStyle: {\n\tnoborder: {background: button },\n\tdefault: {background: button, border: border }\n},\ncom.kotcrab.vis.ui.widget.Menu$MenuStyle: {\n\tdefault: {background: button, border: border, openButtonStyleName: \"menu-bar\" },\n\tnoborder: {background: button, openButtonStyleName: \"menu-bar\" }\n},\ncom.kotcrab.vis.ui.widget.MenuBar$MenuBarStyle: {\n\tdefault: {background: menu-bg }\n},\ncom.kotcrab.vis.ui.widget.Separator$SeparatorStyle: {\n\tdefault: {background: separator, thickness: 4 },\n\tmenu: {background: separator-menu, thickness: 3 }\n},\ncom.kotcrab.vis.ui.widget.VisSplitPane$VisSplitPaneStyle: {\n\tdefault-vertical: {handle: splitpane-vertical, handleOver: splitpane-vertical-over },\n\tdefault-horizontal: {handle: splitpane, handleOver: splitpane-over }\n},\ncom.kotcrab.vis.ui.widget.MenuItem$MenuItemStyle: {\n\tdefault: {subMenu: sub-menu, down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey, subMenu: sub-menu }\n},\ncom.kotcrab.vis.ui.widget.NumberSelector$NumberSelectorStyle: {\n\tdefault: {down: select-down, up: select-up }\n},\ncom.kotcrab.vis.ui.widget.Tooltip$TooltipStyle: {\n\tdefault: {background: tooltip-bg }\n},\ncom.kotcrab.vis.ui.widget.LinkLabel$LinkLabelStyle: {\n\tdefault: {fontColor: link-label, underline: white, font: default-font }\n},\ncom.kotcrab.vis.ui.widget.tabbedpane.TabbedPane$TabbedPaneStyle: {\n\tdefault: {background: menu-bg, separatorBar: list-selection, buttonStyle: {down: button-down, up: button, checked: button-down, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey} }\n},\ncom.kotcrab.vis.ui.widget.spinner.Spinner$SpinnerStyle: {\n\tdefault: {down: select-down, up: select-up }\n},\ncom.kotcrab.vis.ui.widget.file.FileChooserStyle: {\n\tdefault: {highlight: list-selection, popupMenuStyleName: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right, iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive, iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio }\n},\ncom.kotcrab.vis.ui.widget.color.ColorPickerWidgetStyle: {\n\tdefault: {barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right, verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n},\ncom.kotcrab.vis.ui.widget.color.ColorPickerStyle: {\n\tdefault: {pickerStyle: {barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right, verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal}, titleFont: default-font, background: window, titleFontColor: white }\n},\ncom.kotcrab.vis.ui.util.form.SimpleFormValidator$FormValidatorStyle: {\n\tdefault: {errorLabelColor: vis-red, validLabelColor: white },\n\tsmooth: {colorTransitionDuration: 0.3, errorLabelColor: vis-red, validLabelColor: white }\n},\ncom.kotcrab.vis.ui.util.adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\tdefault: {background: window-bg, selection: list-selection }\n}\n\n}"
  },
  {
    "path": "usl/src/test/resources/test-tinted.usl",
    "content": "//This is test file used to verify that USL parser is working correctly\n//DO NOT USE THIS FILE AS YOUR BASE FOR USL SKIN - look at https://github.com/kotcrab/vis-ui-contrib/blob/master/skins/tinted/tinted.usl\n\ninclude <visui-1.0.2>\n\n^com.badlogic.gdx.graphics.Color: {\n  green: {a: 1, b: 0, g: 1, r: 0 }\n  red: {a: 1, b: 0, g: 0, r: 1 }\n  blue: {a: 1, b: 1, g: 0, r: 0 }\n\n  t-white: {r: 1, g: 1, b: 1, a: 1}\n  t-black: {r: 0, g: 0, b: 0, a: 1}\n  t-highlight: {r: 0.85, g: 0.5, b: 0.05, a: 1}\n  t-highlight-medium: {r: 0.7, g: 0.4, b: 0, a: 1}\n  t-highlight-dark: {r: 0.6, g: 0.3, b: 0, a: 1}\n  t-warn: {r: 1, g: 0, b: 0, a: 1}\n  t-light: {r: 0.4, g: 0.4, b: 0.4, a: 1}\n  t-medium: {r: 0.2, g: 0.2, b: 0.2, a: 1}\n  t-medium-dark: {r: 0.15, g: 0.15, b: 0.15, a: 1}\n  t-dark: {r: 0.1, g: 0.1, b: 0.1, a: 1}\n  t-alpha: {r: 0, g: 0, b: 0, a: 0.5}\n\n  black: t-black\n  white: t-white\n  grey: t-light\n  vis-blue: t-highlight\n  vis-red: t-warn\n  menuitem: t-medium-dark\n  link-label: t-highlight\n}\n\n^TintedDrawable: {\n  dialogDim: {name: t-dot, color: t-alpha}\n\n  border: {name: t-border, color: t-highlight}\n  border-circle: {name: t-border-circle, color: t-highlight}\n  border-circle-error: {name: t-border-circle, color: t-warn}\n  border-dark-blue: {name: t-border, color: t-highlight-dark}\n  border-error: {name: t-border, color: t-warn}\n  button: {name: t-base, color: t-medium}\n  button-blue: {name: t-base, color: t-highlight}\n  button-blue-down: {name: t-base, color: t-highlight-dark}\n  button-blue-over: {name: t-base, color: t-highlight-medium}\n  button-down: {name: t-base, color: t-highlight}\n  button-over: {name: t-base, color: t-light}\n  button-red: {name: t-base, color: t-warn}\n  button-window-bg: {name: t-base, color: t-dark}\n  check-down: {name: t-check-off, color: t-highlight}\n  check-down-on: {name: t-check-on, color: t-highlight}\n  check-off: {name: t-check-off, color: t-medium}\n  check-off-disabled: {name: t-check-off, color: t-medium}\n  check-on: {name: t-check-on, color: t-medium}\n  check-on-disabled: {name: t-check-on, color: t-medium}\n  check-over-off: {name: t-check-off, color: t-light}\n  check-over-on: {name: t-check-on, color: t-light}\n  default-pane: {name: t-dot, color: t-medium}\n  default-pane-noborder: {name: t-dot, color: t-medium}\n  default-select: {name: t-select, color: t-medium}\n  default-select-selection: {name: t-dot, color: t-highlight-medium}\n  grey: {name: t-dot, color: t-medium}\n  list-selection: {name: t-dot, color: t-highlight}\n  menu-bg: {name: t-dot, color: t-medium-dark}\n  padded-list-selection: {name: t-hline, color: t-highlight}\n  progressbar: {name: t-vline, color: t-medium}\n  progressbar-filled: {name: t-vline, color: t-highlight}\n  progressbar-filled-vertical: {name: t-hline, color: t-highlight}\n  progressbar-vertical: {name: t-hline, color: t-medium}\n  radio-down: {name: t-radio-off, color: t-highlight}\n  radio-down-on: {name: t-radio-on, color: t-highlight}\n  radio-off: {name: t-radio-off, color: t-medium}\n  radio-off-disabled: {name: t-radio-off, color: t-medium-dark}\n  radio-on: {name: t-radio-on, color: t-medium}\n  radio-on-disabled: {name: t-radio-on, color: t-medium-dark}\n  radio-over-off: {name: t-radio-off, color: t-light}\n  radio-over-on: {name: t-radio-on, color: t-light}\n  scroll: {name: t-hline, color: t-medium}\n  scroll-horizontal: {name: t-vline, color: t-medium}\n  scroll-knob-horizontal: {name: t-hknob, color: t-dark}\n  scroll-knob-vertical: {name: t-vknob, color: t-dark}\n  select-box-list-bg: {name: t-dot, color: t-medium}\n  select-down: {name: t-select-down, color: t-light}\n  selection: {name: t-dot, color: t-highlight-dark}\n  select-up: {name: t-select-up, color: t-light}\n  separator: {name: t-dot, color: t-light}\n  separator-menu: {name: t-dot, color: t-medium}\n  slider: {name: t-hslider, color: t-medium-dark}\n  slider-knob: {name: t-base, color: t-medium}\n  slider-knob-disabled: {name: t-base, color: t-medium-dark}\n  slider-knob-down: {name: t-base, color: t-highlight}\n  slider-knob-over: {name: t-base, color: t-light}\n  slider-vertical: {name: t-vslider, color: t-medium-dark}\n  splitpane: {name: t-vslider, color: t-medium-dark}\n  splitpane-over: {name: t-vslider, color: t-light}\n  splitpane-vertical: {name: t-hslider, color: t-medium-dark}\n  splitpane-vertical-over: {name: t-hslider, color: t-light}\n  sub-menu: {name: t-tree-plus, color: t-light}\n  textfield: {name: t-base, color: t-medium}\n  textfield-over: {name: t-base, color: t-medium-dark}\n  tooltip-bg: {name: t-dot, color: t-medium-dark}\n  touchpad-knob: {name: t-radio-off, color: t-highlight}\n  tree-minus: {name: t-tree-minus, color: t-light}\n  tree-over: {name: t-dot, color: t-medium-dark}\n  tree-plus: {name: t-tree-plus, color: t-light}\n  tree-selection: {name: t-dot, color: t-highlight}\n  vis-blue: {name: t-dot, color: t-highlight}\n  vis-red: {name: t-dot, color: t-warn}\n  white: {name: t-dot, color: white}\n  window: {name: t-window, color: t-dark}\n  window-bg: {name: t-dot, color: t-dark}\n  window-noborder: {name: t-window-border, color: t-dark}\n  window-resizable: {name: t-window-resize, color: t-dark}\n}\n\n// Includes additional check-off-disabled and radio-off-disabled drawables.\n^VisCheckBoxStyle: {\n  default inherits .focus-border: { checkboxOver: check-over-off, checkboxOnOver:\n    check-over-on, checkboxOffDown: check-down, checkboxOnDown: check-down-on,\n    checkboxOffDisabled: check-off-disabled, checkboxOnDisabled: check-on-disabled,\n    errorBorder: border-error }\n  radio inherits .focus-border-circle: { checkboxOver: radio-over-off, checkboxOnOver:\n    radio-over-on, checkboxOffDown: radio-down, checkboxOnDown: radio-down-on, \n    checkboxOffDisabled: radio-off-disabled, checkboxOnDisabled: radio-on-disabled,\n    errorBorder: border-circle-error }\n}\n"
  },
  {
    "path": "usl/src/test/resources/test-visui-expected.json",
    "content": "{\ncom.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: {file: default.fnt },\n\tsmall-font: {file: font-small.fnt }\n},\ncom.badlogic.gdx.graphics.Color: {\n\tblack: {a: 1, b: 0, g: 0, r: 0 },\n\twhite: {a: 1, b: 1, g: 1, r: 1 },\n\tgreen: {a: 1, b: 0, g: 1, r: 0 },\n\tred: {a: 1, b: 0, g: 0, r: 1 },\n\tblue: {a: 1, b: 1, g: 0, r: 0 },\n\tgrey: {a: 1, b: 0.32, g: 0.32, r: 0.32 },\n\tvis-blue: {a: 1, b: 0.886, g: 0.631, r: 0.105 },\n\tvis-red: {a: 1, b: 0.047, g: 0, r: 0.862 },\n\tmenuitem: {a: 1, b: 0.65, g: 0.65, r: 0.65 },\n\tlink-label: {a: 1, b: 0.886, g: 0.631, r: 0.105 }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable: {\n\tdialogDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.45} }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: {\n\tdefault: {down: button-down, up: button },\n\tblue: {down: button-blue-down, up: button-blue },\n\ttoggle: {checked: button-down, down: button-down, up: button }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: {\n\tdefault: {over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, down: button-down, up: button },\n\tblue: {over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, down: button-blue-down, up: button-blue },\n\ttoggle: {font: default-font, fontColor: white, checked: button-down, down: button-down, up: button, over: button-over, disabled: button, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ImageButton$ImageButtonStyle: {\n\tdefault: {down: button-down, up: button },\n\tblue: {down: button-blue-down, up: button-blue },\n\ttoggle: {checked: button-down, down: button-down, up: button }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ImageTextButton$ImageTextButtonStyle: {\n\tdefault: {down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ScrollPane$ScrollPaneStyle: {\n\tlist: {vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal },\n\tdefault: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.SelectBox$SelectBoxStyle: {\n\tdefault: {background: default-select, scrollStyle: default, listStyle: {font: default-font, selection: padded-list-selection, background: select-box-list-bg}, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.SplitPane$SplitPaneStyle: {\n\tdefault-vertical: {handle: splitpane-vertical },\n\tdefault-horizontal: {handle: splitpane }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Window$WindowStyle: {\n\tdefault: {titleFont: default-font, background: window, titleFontColor: white },\n\tresizable: {background: window-resizable, titleFont: default-font, titleFontColor: white },\n\tnoborder: {background: window-noborder, titleFont: default-font, titleFontColor: white },\n\tdialog: {stageBackground: dialogDim, titleFont: default-font, background: window, titleFontColor: white }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.ProgressBar$ProgressBarStyle: {\n\tdefault-horizontal: {background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled },\n\tdefault-vertical: {background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle: {\n\tdefault-horizontal: {background: slider, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled },\n\tdefault-vertical: {background: slider-vertical, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {\n\tdefault: {font: default-font, fontColor: white },\n\tlink-label: {fontColor: link-label, font: default-font },\n\tsmall: {font: small-font, fontColor: white },\n\tmenuitem-shortcut: {font: default-font, fontColor: menuitem }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextField$TextFieldStyle: {\n\tdefault: {font: default-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey },\n\tsmall: {font: small-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.CheckBox$CheckBoxStyle: {\n\tdefault: {checkboxOn: check-on, checkboxOff: check-off, font: default-font, fontColor: white, disabledFontColor: grey },\n\tradio: {checkboxOn: radio-on, checkboxOff: radio-off, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.List$ListStyle: {\n\tdefault: {fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Touchpad$TouchpadStyle: {\n\tdefault: {background: default-pane, knob: touchpad-knob }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.Tree$TreeStyle: {\n\tdefault: {minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over }\n},\ncom.badlogic.gdx.scenes.scene2d.ui.TextTooltip$TextTooltipStyle: {\n\tdefault: {background: default-pane, label: {font: default-font, fontColor: white} }\n},\ncom.kotcrab.vis.ui.Sizes: {\n\tdefault: {scaleFactor: 1, spacingBottom: 8, spacingRight: 6, buttonBarSpacing: 10, menuItemIconSize: 22, spinnerButtonSize: 12, spinnerButtonsWidth: 12, spinnerFieldSize: 40, spinnerFieldRightPadding: 1 },\n\tx2: {scaleFactor: 2, spacingBottom: 8, spacingRight: 6, buttonBarSpacing: 10, menuItemIconSize: 44, spinnerButtonSize: 24, spinnerButtonsWidth: 20, spinnerFieldSize: 80, spinnerFieldRightPadding: 5 }\n},\ncom.kotcrab.vis.ui.widget.VisTextField$VisTextFieldStyle: {\n\tdefault: {focusBorder: border, font: default-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, backgroundOver: textfield-over, errorBorder: border-error, cursor: cursor },\n\tsmall: {focusBorder: border, font: small-font, fontColor: white, disabledFontColor: grey, selection: selection, background: textfield, backgroundOver: textfield-over, errorBorder: border-error, cursor: cursor }\n},\ncom.kotcrab.vis.ui.widget.VisTextButton$VisTextButtonStyle: {\n\tdefault: {focusBorder: border, down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle: {focusBorder: border, checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey },\n\tblue: {focusBorder: border-dark-blue, down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\tmenu-bar: {over: button-down, font: default-font, fontColor: white, down: button-down, up: button, disabled: button, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.VisImageButton$VisImageButtonStyle: {\n\tdefault: {down: button-down, up: button, over: button-over, disabled: button, focusBorder: border },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue, focusBorder: border-dark-blue },\n\ttoggle: {checked: button-down, focusBorder: border, down: button-down, up: button, over: button-over, disabled: button },\n\tclose: {down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button },\n\tclose-active-tab: {down: button-red, imageUp: icon-close, up: button-blue, over: button-blue-over, disabled: button-blue },\n\tclose-window: {up: button-window-bg, down: button-red, over: button-over, imageUp: icon-close, disabled: button }\n},\ncom.kotcrab.vis.ui.widget.VisImageTextButton$VisImageTextButtonStyle: {\n\tdefault: {down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, focusBorder: border },\n\ttoggle: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey, focusBorder: border },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, focusBorder: border-dark-blue },\n\tdefault-noborder: {down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle-noborder: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey },\n\tmenu-bar: {over: button-down, font: default-font, fontColor: white, down: button-down, up: button, disabled: button, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.VisCheckBox$VisCheckBoxStyle: {\n\tdefault: {checkboxOver: check-over-off, checkboxOnOver: check-over-on, checkboxOffDown: check-down, checkboxOnDown: check-down-on, checkboxOffDisabled: check-off, checkboxOnDisabled: check-on-disabled, errorBorder: border-error, focusBorder: border, checkboxOn: check-on, checkboxOff: check-off, font: default-font, fontColor: white, disabledFontColor: grey },\n\tradio: {checkboxOver: radio-over-off, checkboxOnOver: radio-over-on, checkboxOffDown: radio-down, checkboxOnDown: radio-down-on, checkboxOffDisabled: radio-off, checkboxOnDisabled: radio-on-disabled, errorBorder: border-circle-error, focusBorder: border-circle, checkboxOn: radio-on, checkboxOff: radio-off, font: default-font, fontColor: white, disabledFontColor: grey }\n},\ncom.kotcrab.vis.ui.widget.PopupMenu$PopupMenuStyle: {\n\tnoborder: {background: button },\n\tdefault: {background: button, border: border }\n},\ncom.kotcrab.vis.ui.widget.Menu$MenuStyle: {\n\tdefault: {background: button, border: border, openButtonStyleName: \"menu-bar\" },\n\tnoborder: {background: button, openButtonStyleName: \"menu-bar\" }\n},\ncom.kotcrab.vis.ui.widget.MenuBar$MenuBarStyle: {\n\tdefault: {background: menu-bg }\n},\ncom.kotcrab.vis.ui.widget.Separator$SeparatorStyle: {\n\tdefault: {background: separator, thickness: 4 },\n\tmenu: {background: separator-menu, thickness: 3 }\n},\ncom.kotcrab.vis.ui.widget.VisSplitPane$VisSplitPaneStyle: {\n\tdefault-vertical: {handle: splitpane-vertical, handleOver: splitpane-vertical-over },\n\tdefault-horizontal: {handle: splitpane, handleOver: splitpane-over }\n},\ncom.kotcrab.vis.ui.widget.MenuItem$MenuItemStyle: {\n\tdefault: {subMenu: sub-menu, down: button-down, up: button, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\tblue: {down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey },\n\ttoggle: {checked: button-down, down: button-down, up: button, font: default-font, fontColor: white, over: button-over, disabled: button, disabledFontColor: grey, subMenu: sub-menu }\n},\ncom.kotcrab.vis.ui.widget.NumberSelector$NumberSelectorStyle: {\n\tdefault: {down: select-down, up: select-up }\n},\ncom.kotcrab.vis.ui.widget.Tooltip$TooltipStyle: {\n\tdefault: {background: tooltip-bg }\n},\ncom.kotcrab.vis.ui.widget.LinkLabel$LinkLabelStyle: {\n\tdefault: {fontColor: link-label, underline: white, font: default-font }\n},\ncom.kotcrab.vis.ui.widget.tabbedpane.TabbedPane$TabbedPaneStyle: {\n\tdefault: {background: menu-bg, separatorBar: list-selection, buttonStyle: {down: button-down, up: button, checked: button-down, over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey} }\n},\ncom.kotcrab.vis.ui.widget.spinner.Spinner$SpinnerStyle: {\n\tdefault: {down: select-down, up: select-up }\n},\ncom.kotcrab.vis.ui.widget.file.FileChooserStyle: {\n\tdefault: {highlight: list-selection, popupMenuStyleName: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right, iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive, iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio }\n},\ncom.kotcrab.vis.ui.widget.color.ColorPickerWidgetStyle: {\n\tdefault: {barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right, verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n},\ncom.kotcrab.vis.ui.widget.color.ColorPickerStyle: {\n\tdefault: {pickerStyle: {barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right, verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal}, titleFont: default-font, background: window, titleFontColor: white }\n},\ncom.kotcrab.vis.ui.util.form.SimpleFormValidator$FormValidatorStyle: {\n\tdefault: {errorLabelColor: vis-red, validLabelColor: white },\n\tsmooth: {colorTransitionDuration: 0.3, errorLabelColor: vis-red, validLabelColor: white }\n},\ncom.kotcrab.vis.ui.util.adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\tdefault: {background: window-bg, selection: list-selection }\n}\n\n}\n"
  },
  {
    "path": "usl/src/test/resources/test-visui.usl",
    "content": "//VisUI 1.1.0 style\n//This is test file used to verify that USL parser is working correctly\n//DO NOT USE THIS FILE AS YOUR BASE FOR USL SKIN - look at directory usl/styles\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n\t\tdefault inherits list: { background: border }\n\t}\n\t\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n\t\tspinnerButtonSize: 12,\n\t\tspinnerButtonsWidth: 12,\n\t\tspinnerFieldSize: 40,\n\t\tspinnerFieldRightPadding: 1\n\t}\n\n\tx2: {\n\t\tscaleFactor: 2,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonSize: 24,\n\t\tspinnerButtonsWidth: 20,\n\t\tspinnerFieldSize: 80,\n\t\tspinnerFieldRightPadding: 5\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, errorBorder: border-error, cursor: cursor }\n\t\tdefault inherits .focus-border, .font, .font-disabled, base: { }\n\t\tsmall inherits .focus-border, .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle extends CheckBoxStyle: {\n\t\tdefault inherits .focus-border: { checkboxOver: check-over-off, checkboxOnOver: check-over-on, checkboxOffDown: check-down, checkboxOnDown: check-down-on,\n\t\t\t\t\t\t\t\t\t\t\t\tcheckboxOffDisabled: check-off, checkboxOnDisabled: check-on-disabled, errorBorder: border-error }\n\t\tradio inherits .focus-border-circle: { checkboxOver: radio-over-off, checkboxOnOver: radio-over-on, checkboxOffDown: radio-down, checkboxOnDown: radio-down-on, \n\t\t\t\t\t\t\t\t\t\t\t\tcheckboxOffDisabled: radio-off, checkboxOnDisabled: radio-on-disabled, errorBorder: border-circle-error }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: {background: button}\n\t\tdefault inherits noborder: {background: button, border: border}\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyleName: \"menu-bar\" }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\t\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#NumberSelector$NumberSelectorStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyleName: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconFileText: icon-file-text, iconFileImage: icon-file-image,\n\t\t\t\t   iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/gdx.usl",
    "content": "//libGDX default style in USL format, useful for including in other files (include <gdx>)\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: { default-font: { file: default.fnt } }\n#com.badlogic.gdx.graphics.Color: {\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n}\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: default-round-down, up: default-round }\n\t\ttoggle inherits default: { checked: default-round-down }\n\t}\n\n\t#TextButton$TextButtonStyle: {\n\t\tdefault: { down: default-round-down, up: default-round, font: default-font, fontColor: white }\n\t\ttoggle inherits default: { checked: default-round-down, downFontColor: red }\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tdefault: { vScroll: default-scroll, hScrollKnob: default-round-large, background: default-rect, hScroll: default-scroll, vScrollKnob: default-round-large }\n\t}\n\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault: {\n\t\t\tfont: default-font, fontColor: white, background: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: default-select-selection }\n\t\t}\n\t}\n\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: default-splitpane-vertical }\n\t\tdefault-horizontal: { handle: default-splitpane }\n\t}\n\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: default-window, titleFontColor: white }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\n\t#Slider$SliderStyle: {\n\t\tdefault-horizontal: { background: default-slider, knob: default-slider-knob }\n\t}\n\n\t#Label$LabelStyle: {\n\t\tdefault: { font: default-font, fontColor: white }\n\t}\n\n\t#TextField$TextFieldStyle: {\n\t\tdefault: { selection: selection, background: textfield, font: default-font, fontColor: white, cursor: cursor }\n\t}\n\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault: { checkboxOn: check-on, checkboxOff: check-off, font: default-font, fontColor: white }\n\t}\n\n\t#List$ListStyle: {\n\t\tdefault: { fontColorUnselected: white, selection: selection, fontColorSelected: white, font: default-font }\n\t}\n\n\t#Touchpad$TouchpadStyle: {\n\t\tdefault: { background: default-pane, knob: default-round-large }\n\t}\n\n\t#Tree$TreeStyle: {\n\t\tdefault: { minus: tree-minus, plus: tree-plus, selection: default-select-selection }\n\t}\n\n\t#TextTooltip$TextTooltipStyle: {\n        default: {\n            background: default-pane,\n            label: { font: default-font, fontColor: white }\n        }\n    }\n}\n"
  },
  {
    "path": "usl/styles/visui-1.0.2.usl",
    "content": "//VisUI 1.0.2 style\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\t\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n\t\tdefault inherits list: { background: border }\n\t}\n\t\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n\t\tnumberSelectorButtonSize: 12,\n\t\tnumberSelectorButtonsWidth: 12,\n\t\tnumberSelectorFieldSize: 40,\n\t\tnumberSelectorFieldRightPadding: 1\n\n\t\tspinnerButtonSize: 12,\n        spinnerButtonsWidth: 12,\n        spinnerFieldSize: 40,\n        spinnerFieldRightPadding: 1\n\t}\n\n\tx2: {\n\t\tscaleFactor: 2,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tnumberSelectorButtonSize: 24,\n\t\tnumberSelectorButtonsWidth: 20,\n\t\tnumberSelectorFieldSize: 80,\n\t\tnumberSelectorFieldRightPadding: 5,\n\n\t\tspinnerButtonSize: 24,\n        spinnerButtonsWidth: 20,\n        spinnerFieldSize: 80,\n        spinnerFieldRightPadding: 5\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, errorBorder: border-error, cursor: cursor }\n\t\tdefault inherits .focus-border, .font, .font-disabled, base: { }\n\t\tsmall inherits .focus-border, .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle extends CheckBoxStyle: {\n\t\tdefault inherits .focus-border: { checkboxOver: check-over-off, checkboxOnOver: check-over-on, checkboxOffDown: check-down, checkboxOnDown: check-down-on,\n\t\t\t\t\t\t\t\t\t\t\t\tcheckboxOffDisabled: check-off, checkboxOnDisabled: check-on-disabled, errorBorder: border-error }\n\t\tradio inherits .focus-border-circle: { checkboxOver: radio-over-off, checkboxOnOver: radio-over-on, checkboxOffDown: radio-down, checkboxOnDown: radio-down-on, \n\t\t\t\t\t\t\t\t\t\t\t\tcheckboxOffDisabled: radio-off, checkboxOnDisabled: radio-on-disabled, errorBorder: border-circle-error }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: {background: button}\n\t\tdefault inherits noborder: {background: button, border: border}\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyleName: \"menu-bar\" }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\t\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#NumberSelector$NumberSelectorStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n       \tdefault: { down: select-down, up: select-up }\n    }\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyleName: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconFileText: icon-file-text, iconFileImage: icon-file-image,\n\t\t\t\t   iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n    #form.SimpleFormValidator$FormValidatorStyle: {\n        default: { errorLabelColor: vis-red, validLabelColor: white }\n        smooth inherits default: { colorTransitionDuration: 0.3 }\n    }\n\n    #adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n        default: { background: window-bg, selection: list-selection }\n    }\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.1.6.usl",
    "content": "//VisUI 1.1.6 style\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n\t\tdefault inherits list: { background: border }\n\t}\n\t\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n        borderSize: 1,\n\n\t\tspinnerButtonSize: 12,\n\t\tspinnerButtonsWidth: 12,\n\t\tspinnerFieldSize: 40,\n\t\tspinnerFieldRightPadding: 1,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonSize: 24,\n\t\tspinnerButtonsWidth: 20,\n\t\tspinnerFieldSize: 80,\n\t\tspinnerFieldRightPadding: 5\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t    { checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t    { checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyleName: \"menu-bar\" }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n    }\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyleName: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t    default: { background: tooltip-bg, closeButtonStyleName: \"close\" }\n\t    dark: { background: window-border-bg, closeButtonStyleName: \"close-window\" }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t    -base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t    default inherits base: { height: 2 }\n\t    slim inherits base: { height: 1 }\n\t    thick inherits base: { height: 6 }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.2.3.usl",
    "content": "//VisUI 1.2.3 style\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n\t\tdefault inherits list: { background: border }\n\t}\n\t\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n        borderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t    { checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t    { checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n    }\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t    default: { background: tooltip-bg, closeButtonStyle: close }\n\t    dark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t    -base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t    default inherits base: { height: 2 }\n\t    slim inherits base: { height: 1 }\n\t    thick inherits base: { height: 6 }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.2.4.usl",
    "content": "//VisUI 1.2.4 style\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n\t\tdefault inherits list: { background: border }\n\t}\n\t\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n        borderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t    { checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t    { checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n    }\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t    default: { background: tooltip-bg, closeButtonStyle: close }\n\t    dark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t    -base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t    default inherits base: { height: 2 }\n\t    slim inherits base: { height: 1 }\n\t    thick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t    default: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.2.5.usl",
    "content": "//VisUI 1.2.5 style\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n\t\tdefault inherits list: { background: border }\n\t}\n\t\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n        borderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t    { checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t    { checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n    }\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t    default: { background: tooltip-bg, closeButtonStyle: close }\n\t    dark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t    -base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t    default inherits base: { height: 2 }\n\t    slim inherits base: { height: 1 }\n\t    thick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t    default: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.3.0.usl",
    "content": "//VisUI 1.3.0 style\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n\t\tdefault inherits list: { background: border }\n\t}\n\t\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n        borderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t    { checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t    { checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n    }\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t    default: { background: tooltip-bg, closeButtonStyle: close }\n\t    dark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t    -base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t    default inherits base: { height: 2 }\n\t    slim inherits base: { height: 1 }\n\t    thick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t    default: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.4.0.usl",
    "content": "//VisUI 1.4.0 style\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n\t\tdefault inherits list: { background: border }\n\t}\n\t\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n        borderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t    { checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t    { checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n    }\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t    default: { background: tooltip-bg, closeButtonStyle: close }\n\t    dark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t    -base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t    default inherits base: { height: 2 }\n\t    slim inherits base: { height: 1 }\n\t    thick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t    default: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.4.1.usl",
    "content": "//VisUI 1.4.1 style\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n\t\tdefault inherits list: { background: border }\n\t}\n\t\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n        borderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t    { checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t    { checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n    }\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t    default: { background: tooltip-bg, closeButtonStyle: close }\n\t    dark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t    -base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t    default inherits base: { height: 2 }\n\t    slim inherits base: { height: 1 }\n\t    thick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t    default: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.4.10.usl",
    "content": "#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal, corner: grey }\n\t\tdefault inherits list: { background: border }\n\t}\n\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n\t\tborderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tvertical inherits default: {}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n\t}\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t\tdefault: { background: tooltip-bg, closeButtonStyle: close }\n\t\tdark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t\t-base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t\tdefault inherits base: { height: 2 }\n\t\tslim inherits base: { height: 1 }\n\t\tthick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t\tdefault: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.4.11.usl",
    "content": "#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal, corner: grey }\n\t\tdefault inherits list: { background: border }\n\t}\n\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n\t\tborderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tvertical inherits default: {}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n\t}\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t\tdefault: { background: tooltip-bg, closeButtonStyle: close }\n\t\tdark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t\t-base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t\tdefault inherits base: { height: 2 }\n\t\tslim inherits base: { height: 1 }\n\t\tthick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t\tdefault: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.4.2.usl",
    "content": "//VisUI 1.4.2 style\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n\t\tdefault inherits list: { background: border }\n\t}\n\t\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n        borderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t    { checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t    { checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n    }\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t    default: { background: tooltip-bg, closeButtonStyle: close }\n\t    dark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t    -base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t    default inherits base: { height: 2 }\n\t    slim inherits base: { height: 1 }\n\t    thick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t    default: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.4.3.usl",
    "content": "//VisUI 1.4.3 style\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n\t\tdefault inherits list: { background: border }\n\t}\n\t\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n        borderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t    { checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t    { checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n    }\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t    default: { background: tooltip-bg, closeButtonStyle: close }\n\t    dark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t    -base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t    default inherits base: { height: 2 }\n\t    slim inherits base: { height: 1 }\n\t    thick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t    default: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.4.4.usl",
    "content": "//VisUI 1.4.4 style\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal }\n\t\tdefault inherits list: { background: border }\n\t}\n\t\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n        borderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t    { checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t    { checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n    }\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t    default: { background: tooltip-bg, closeButtonStyle: close }\n\t    dark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t    -base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t    default inherits base: { height: 2 }\n\t    slim inherits base: { height: 1 }\n\t    thick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t    default: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.4.5.usl",
    "content": "//VisUI 1.4.5 style\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal, corner: grey }\n\t\tdefault inherits list: { background: border }\n\t}\n\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n\t\tborderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tvertical inherits default: {}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n\t}\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t\tdefault: { background: tooltip-bg, closeButtonStyle: close }\n\t\tdark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t\t-base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t\tdefault inherits base: { height: 2 }\n\t\tslim inherits base: { height: 1 }\n\t\tthick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t\tdefault: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.4.6.usl",
    "content": "//VisUI 1.4.6 style\n\n#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal, corner: grey }\n\t\tdefault inherits list: { background: border }\n\t}\n\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n\t\tborderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tvertical inherits default: {}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n\t}\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t\tdefault: { background: tooltip-bg, closeButtonStyle: close }\n\t\tdark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t\t-base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t\tdefault inherits base: { height: 2 }\n\t\tslim inherits base: { height: 1 }\n\t\tthick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t\tdefault: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.4.7.usl",
    "content": "#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal, corner: grey }\n\t\tdefault inherits list: { background: border }\n\t}\n\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n\t\tborderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tvertical inherits default: {}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n\t}\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t\tdefault: { background: tooltip-bg, closeButtonStyle: close }\n\t\tdark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t\t-base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t\tdefault inherits base: { height: 2 }\n\t\tslim inherits base: { height: 1 }\n\t\tthick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t\tdefault: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.4.8.usl",
    "content": "#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal, corner: grey }\n\t\tdefault inherits list: { background: border }\n\t}\n\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n\t\tborderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tvertical inherits default: {}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n\t}\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t\tdefault: { background: tooltip-bg, closeButtonStyle: close }\n\t\tdark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t\t-base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t\tdefault inherits base: { height: 2 }\n\t\tslim inherits base: { height: 1 }\n\t\tthick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t\tdefault: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "usl/styles/visui-1.4.9.usl",
    "content": "#com.badlogic.gdx.graphics.g2d.BitmapFont: {\n\tdefault-font: { file: default.fnt }\n\tsmall-font: { file: font-small.fnt }\n}\n\n#com.badlogic.gdx.graphics.Color: {\n\tblack: { a: 1, b: 0, g: 0, r: 0 }\n\twhite: { a: 1, b: 1, g: 1, r: 1 }\n\tgreen: { a: 1, b: 0, g: 1, r: 0 }\n\tred: { a: 1, b: 0, g: 0, r: 1 }\n\tblue: { a: 1, b: 1, g: 0, r: 0 }\n\tgrey: { a: 1, b: 0.32, g: 0.32, r: 0.32 }\n\tvis-blue: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n\tvis-red: { a: 1, b: 0.047, g: 0, r: 0.862 }\n\n\tmenuitem: { a: 1, b: 0.65, g: 0.65, r: 0.65 }\n\tlink-label: { a: 1, b: 0.886, g: 0.631, r: 0.105 }\n}\n\n.font: { font: default-font, fontColor: white,  }\n.font-disabled: { disabledFontColor: grey }\n\n.font-small: { font: small-font, fontColor: white }\n.font-small-disabled: { disabledFontColor: grey }\n\n.focus-border: { focusBorder: border }\n.focus-border-dark-blue: { focusBorder: border-dark-blue }\n.focus-border-circle: { focusBorder: border-circle }\n.error-border: { errorBorder: border-error }\n.error-border-circle: { errorBorder: border-circle-error }\n\npackage com.badlogic.gdx.scenes.scene2d.ui {\n\t#Skin$TintedDrawable: {\n\t\tdialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } }\n\t}\n\n\t#Button$ButtonStyle: {\n\t\tdefault: { down: button-down, up: button }\n\t\tblue: { down: button-blue-down, up: button-blue }\n\t\ttoggle inherits default: { checked: button-down }\n\t}\n\t\n\t#TextButton$TextButtonStyle extends ButtonStyle: {\n\t\tdefault inherits .font, .font-disabled: { over: button-over, disabled: button }\n\t\tblue inherits .font, .font-disabled: { over: button-blue-over, disabled: button }\n\t\ttoggle inherits default, .font: {}\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageButton$ImageButtonStyle extends ButtonStyle: {\n\t}\n\n\t//all styles inherited without any change required\n\t#ImageTextButton$ImageTextButtonStyle extends TextButtonStyle: {\n\t}\n\n\t#ScrollPane$ScrollPaneStyle: {\n\t\tlist: { vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal, corner: grey }\n\t\tdefault inherits list: { background: border }\n\t}\n\n\t#SelectBox$SelectBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: {\n\t\t\tbackground: default-select,\n\t\t\tscrollStyle: default,\n\t\t\tlistStyle: { font: default-font, selection: padded-list-selection, background: select-box-list-bg }\n\t\t}\n\t}\n\t\n\t#SplitPane$SplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical }\n\t\tdefault-horizontal: { handle: splitpane }\n\t}\n\t\n\t#Window$WindowStyle: {\n\t\tdefault: { titleFont: default-font, background: window, titleFontColor: white }\n\t\tresizable inherits default: { background: window-resizable }\n\t\tnoborder inherits default: { background: window-noborder }\n\t\tdialog inherits default: { stageBackground: dialogDim }\n\t}\n\t\n\t#ProgressBar$ProgressBarStyle: {\n\t\tdefault-horizontal: { background: progressbar, knob: progressbar-filled, knobBefore: progressbar-filled}\n\t\tdefault-vertical: { background: progressbar-vertical, knob: progressbar-filled-vertical, knobBefore: progressbar-filled-vertical }\n\t}\n\t\n\t#Slider$SliderStyle: {\n\t\t-base: { knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down, disabledKnob: slider-knob-disabled}\n\t\tdefault-horizontal inherits base: { background: slider }\n\t\tdefault-vertical inherits base: { background: slider-vertical }\n\t}\n\t\n\t#Label$LabelStyle: {\n\t\tdefault inherits .font: { }\n\t\tlink-label inherits default: { fontColor: link-label }\n\t\tsmall inherits .font-small: { }\n\t\tmenuitem-shortcut: { font: default-font, fontColor: menuitem }\n\t}\n\t\n\t#TextField$TextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, cursor: cursor, messageFont: default-font, messageFontColor: grey }\n\t\tdefault inherits .font, .font-disabled, base: { }\n\t\tsmall inherits .font-small, .font-small-disabled, base: { }\n\t}\n\t\n\t#CheckBox$CheckBoxStyle: {\n\t\tdefault inherits .font, .font-disabled: { checkboxOn: check-on, checkboxOff: check-off }\n\t\tradio inherits .font, .font-disabled: { checkboxOn: radio-on, checkboxOff: radio-off }\n\t}\n\t\n\t#List$ListStyle: { default: { fontColorUnselected: white, selection: padded-list-selection, fontColorSelected: white, font: default-font } }\n\t#Touchpad$TouchpadStyle: { default: { background: default-pane, knob: touchpad-knob } }\n\t#Tree$TreeStyle: { default: { minus: tree-minus, plus: tree-plus, selection: tree-selection, over: tree-over } }\n\n\t#TextTooltip$TextTooltipStyle: {\n\t\tdefault: {\n\t\t\tbackground: default-pane,\n\t\t\tlabel inherits .font: { }\n\t\t}\n\t}\n}\n\n#com.kotcrab.vis.ui.Sizes: {\n\tdefault: {\n\t\tscaleFactor: 1,\n\n\t\tspacingBottom: 8,\n\t\tspacingRight: 6,\n\n\t\tbuttonBarSpacing: 10,\n\n\t\tmenuItemIconSize: 22,\n\n\t\tborderSize: 1,\n\n\t\tspinnerButtonHeight: 12,\n\t\tspinnerFieldSize: 40,\n\n\t\tfileChooserViewModeBigIconsSize: 200,\n\t\tfileChooserViewModeMediumIconsSize: 128,\n\t\tfileChooserViewModeSmallIconsSize: 64,\n\t\tfileChooserViewModeListWidthSize: 155,\n\t}\n\n\tx2 inherits default: {\n\t\tscaleFactor: 2,\n\n\t\tmenuItemIconSize: 44,\n\n\t\tspinnerButtonHeight: 24,\n\t\tspinnerFieldSize: 80,\n\t}\n}\n\npackage com.kotcrab.vis.ui.widget {\n\t#VisTextField$VisTextFieldStyle: {\n\t\t-base: { selection: selection, background: textfield, backgroundOver: textfield-over, cursor: cursor }\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled, base: { }\n\t\ttextArea inherits default: { backgroundOver: NULL, focusBorder: NULL }\n\t\tsmall inherits .focus-border, .error-border, .font-small, .font-small-disabled, base: { }\n\t\tlabel inherits .error-border, .font, .font-disabled: { selection: selection }\n\t}\n\t\n\t#VisTextButton$VisTextButtonStyle extends TextButtonStyle: {\n\t\tdefault inherits .focus-border: {}\n\t\ttoggle inherits .focus-border: {}\n\t\tblue inherits .focus-border-dark-blue: {}\n\t\tmenu-bar inherits default, .font: { over: button-down, focusBorder: NULL }\n\t}\n\t\n\t#VisImageButton$VisImageButtonStyle: {\n\t\tdefault inherits .focus-border: { down: button-down, up: button, over: button-over, disabled: button }\n\t\tblue inherits .focus-border-dark-blue: { down: button-blue-down, up: button-blue, over: button-blue-over, disabled: button-blue }\n\t\ttoggle inherits default, .focus-border: { checked: button-down }\n\t\tclose: { down: button-red, up: button, over: button-over, imageUp: icon-close, disabled: button }\n\t\tclose-active-tab inherits blue: { down: button-red, imageUp: icon-close, focusBorder: NULL }\n\t\tclose-window inherits close: { up: button-window-bg }\n\t\tclose-titlebar inherits close: { imageUp: icon-close-titlebar }\n\t}\n\t\n\t#VisImageTextButton$VisImageTextButtonStyle extends VisTextButtonStyle: {\n\t\tdefault: { }\n\t\ttoggle: { }\n\t\tblue: { }\n\t\tdefault-noborder inherits default: { focusBorder: NULL }\n\t\ttoggle-noborder inherits toggle: { focusBorder: NULL }\n\t}\n\t\n\t#VisCheckBox$VisCheckBoxStyle: {\n\t\tdefault inherits .focus-border, .error-border, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-check, checkBackgroundOver: vis-check-over, checkBackgroundDown: vis-check-down, tick: vis-check-tick, tickDisabled: vis-check-tick-disabled }\n\t\tradio inherits .focus-border-circle, .error-border-circle, .font, .font-disabled:\n\t\t\t{ checkBackground: vis-radio, checkBackgroundOver: vis-radio-over, checkBackgroundDown: vis-radio-down, tick: vis-radio-tick, tickDisabled: vis-radio-tick-disabled }\n\t}\n\t\n\t#PopupMenu$PopupMenuStyle: {\n\t\tnoborder: { background: button }\n\t\tdefault inherits noborder: { background: button, border: border }\n\t}\n\n\t#Menu$MenuStyle extends PopupMenuStyle: {\n\t\t-base: { openButtonStyle: menu-bar }\n\t\tdefault inherits base: {}\n\t\tnoborder inherits base: {}\n\t}\n\n\t#MenuBar$MenuBarStyle: {\n\t\tdefault: { background: menu-bg }\n\t}\n\n\t#Separator$SeparatorStyle: {\n\t\tdefault: {background: separator, thickness: 4}\n\t\tvertical inherits default: {}\n\t\tmenu: {background: separator-menu, thickness: 3}\n\t}\n\t\n\t#VisSplitPane$VisSplitPaneStyle: {\n\t\tdefault-vertical: { handle: splitpane-vertical, handleOver: splitpane-vertical-over }\n\t\tdefault-horizontal: { handle: splitpane, handleOver: splitpane-over }\n\t}\n\n\t#MultiSplitPane$MultiSplitPaneStyle extends VisSplitPaneStyle: {\n\t}\n\n\t#MenuItem$MenuItemStyle extends TextButtonStyle: {\n\t\tdefault: { subMenu: sub-menu }\n\t}\n\t\n\t#Tooltip$TooltipStyle: {\n\t\tdefault: { background: tooltip-bg }\n\t}\n\n\t#LinkLabel$LinkLabelStyle: {\n\t\tdefault inherits .font: { fontColor: link-label, underline: white }\n\t}\n\n\t#tabbedpane.TabbedPane$TabbedPaneStyle: {\n\t\tdefault: { background: menu-bg, separatorBar: list-selection, vertical: false,\n\t\t\t\t\tbuttonStyle inherits .font, .font-disabled: { down: button-down, up: button, checked: button-down, over: button-over, disabled: button } }\n\t\tvertical inherits default: { vertical: true }\n\t}\n\n\t#spinner.Spinner$SpinnerStyle: {\n\t\tdefault: { down: select-down, up: select-up }\n\t}\n\n\t#file.FileChooserStyle: {\n\t\tdefault: { highlight: list-selection, popupMenuStyle: \"default\", iconArrowLeft: icon-arrow-left, iconArrowRight: icon-arrow-right,\n\t\t\t\t   iconFolder: icon-folder, iconFolderParent: icon-folder-parent, iconFolderNew: icon-folder-new, iconDrive: icon-drive,\n\t\t\t\t   iconFolderStar: icon-folder-star, iconTrash: icon-trash, iconStar: icon-star, iconStarOutline: icon-star-outline, iconRefresh: icon-refresh\n\t\t\t\t   iconFileText: icon-file-text, iconFileImage: icon-file-image, iconFilePdf: icon-file-pdf, iconFileAudio: icon-file-audio\n\t\t\t\t   iconListSettings: icon-list-settings,\n\t\t\t\t   contextMenuSelectedItem: vis-radio-tick, expandDropdown: select-down }\n\t}\n\n\t#color.ColorPickerWidgetStyle: {\n\t\tdefault: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }\n\t}\n\n\t#color.ColorPickerStyle extends ~WindowStyle: {\n\t\tdefault: { pickerStyle: { barSelector: color-picker-bar-selector, cross: color-picker-cross, iconArrowRight: icon-arrow-right\n\t\t\t\t   verticalSelector: color-picker-selector-vertical, horizontalSelector: color-picker-selector-horizontal }}\n\t}\n\n\t#toast.Toast$ToastStyle: {\n\t\tdefault: { background: tooltip-bg, closeButtonStyle: close }\n\t\tdark: { background: window-border-bg, closeButtonStyle: close-window }\n\t}\n\n\t#BusyBar$BusyBarStyle: {\n\t\t-base: { segment: vis-blue, segmentWidth: 100, segmentOverflow: 50 }\n\t\tdefault inherits base: { height: 2 }\n\t\tslim inherits base: { height: 1 }\n\t\tthick inherits base: { height: 6 }\n\t}\n\n\t#ListViewStyle: {\n\t\tdefault: { scrollPaneStyle: list }\n\t}\n}\n\npackage com.kotcrab.vis.ui.util {\n\t#form.SimpleFormValidator$FormValidatorStyle: {\n\t\tdefault: { errorLabelColor: vis-red, validLabelColor: white }\n\t\tsmooth inherits default: { colorTransitionDuration: 0.3 }\n\t}\n\n\t#adapter.SimpleListAdapter$SimpleListAdapterStyle: {\n\t\tdefault: { background: window-bg, selection: list-selection }\n\t}\n}\n\n"
  },
  {
    "path": "vis-intellij-formatter.xml",
    "content": "<code_scheme name=\"vis-intellij-formatter\">\n  <option name=\"AUTODETECT_INDENTS\" value=\"false\" />\n  <option name=\"PACKAGES_TO_USE_IMPORT_ON_DEMAND\">\n    <value />\n  </option>\n  <option name=\"JD_ALIGN_PARAM_COMMENTS\" value=\"false\" />\n  <option name=\"JD_ALIGN_EXCEPTION_COMMENTS\" value=\"false\" />\n  <option name=\"JD_ADD_BLANK_AFTER_DESCRIPTION\" value=\"false\" />\n  <option name=\"JD_DO_NOT_WRAP_ONE_LINE_COMMENTS\" value=\"true\" />\n  <option name=\"JD_KEEP_EMPTY_PARAMETER\" value=\"false\" />\n  <option name=\"JD_KEEP_EMPTY_EXCEPTION\" value=\"false\" />\n  <option name=\"JD_KEEP_EMPTY_RETURN\" value=\"false\" />\n  <option name=\"JD_PRESERVE_LINE_FEEDS\" value=\"true\" />\n  <option name=\"FORMATTER_TAGS_ENABLED\" value=\"true\" />\n  <JavaCodeStyleSettings>\n    <option name=\"DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION\" value=\"true\" />\n    <option name=\"CLASS_NAMES_IN_JAVADOC\" value=\"3\" />\n  </JavaCodeStyleSettings>\n  <XML>\n    <option name=\"XML_LEGACY_SETTINGS_IMPORTED\" value=\"true\" />\n  </XML>\n  <codeStyleSettings language=\"JAVA\">\n    <option name=\"KEEP_BLANK_LINES_IN_DECLARATIONS\" value=\"1\" />\n    <option name=\"KEEP_BLANK_LINES_IN_CODE\" value=\"1\" />\n    <option name=\"KEEP_BLANK_LINES_BEFORE_RBRACE\" value=\"1\" />\n    <option name=\"SPACE_BEFORE_METHOD_PARENTHESES\" value=\"true\" />\n    <option name=\"CLASS_ANNOTATION_WRAP\" value=\"1\" />\n    <option name=\"FIELD_ANNOTATION_WRAP\" value=\"1\" />\n    <indentOptions>\n      <option name=\"USE_TAB_CHARACTER\" value=\"true\" />\n    </indentOptions>\n    <arrangement>\n      <rules>\n        <section>\n          <rule>\n            <match>\n              <FIELD>true</FIELD>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <CONSTRUCTOR>true</CONSTRUCTOR>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <METHOD>true</METHOD>\n                <STATIC>true</STATIC>\n              </AND>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <METHOD>true</METHOD>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <ENUM>true</ENUM>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <INTERFACE>true</INTERFACE>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <AND>\n                <CLASS>true</CLASS>\n                <STATIC>true</STATIC>\n              </AND>\n            </match>\n          </rule>\n        </section>\n        <section>\n          <rule>\n            <match>\n              <CLASS>true</CLASS>\n            </match>\n          </rule>\n        </section>\n      </rules>\n    </arrangement>\n  </codeStyleSettings>\n</code_scheme>"
  }
]